| /* |
| * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| package org.eclipse.persistence.internal.jaxb; |
| |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Method; |
| import jakarta.xml.bind.ValidationEventHandler; |
| import jakarta.xml.bind.annotation.DomHandler; |
| import javax.xml.transform.Source; |
| import javax.xml.transform.Result; |
| import javax.xml.transform.dom.DOMResult; |
| import javax.xml.transform.dom.DOMSource; |
| |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Node; |
| import org.xml.sax.ErrorHandler; |
| |
| import org.eclipse.persistence.exceptions.JAXBException; |
| import org.eclipse.persistence.internal.helper.ConversionManager; |
| import org.eclipse.persistence.internal.security.PrivilegedAccessHelper; |
| import org.eclipse.persistence.jaxb.JAXBErrorHandler; |
| import org.eclipse.persistence.mappings.DatabaseMapping; |
| import org.eclipse.persistence.oxm.mappings.converters.XMLConverter; |
| import org.eclipse.persistence.oxm.XMLMarshaller; |
| import org.eclipse.persistence.oxm.XMLUnmarshaller; |
| import org.eclipse.persistence.platform.xml.XMLPlatform; |
| import org.eclipse.persistence.platform.xml.XMLPlatformFactory; |
| import org.eclipse.persistence.platform.xml.XMLTransformer; |
| import org.eclipse.persistence.sessions.Session; |
| |
| /** |
| * INTERNAL: |
| * <p><b>Purpose:</b>Provide support for the JAXB DomHandler API through the use of an EclipseLink |
| * Converter. |
| * <p><b>Responsibilities:</b><ul> |
| * <li>Wrap a provided instance of a DomHandler implementation.</li> |
| * <li>Invoke the createUnmarshaller method on DomHandler and to a transform on unmarshal</li> |
| * <li>Invoke the marshal method on the DomHandler on a marshal</li> |
| * </ul> |
| * |
| * @author mmacivor |
| * |
| */ |
| public class DomHandlerConverter implements XMLConverter { |
| private DomHandler domHandler; |
| private XMLPlatform xmlPlatform; |
| private String domHandlerClassName; |
| private Class<?> elementClass; |
| private Class<?> resultType; |
| |
| public DomHandlerConverter(String domHandlerClassName) { |
| this.domHandlerClassName = domHandlerClassName; |
| } |
| |
| @Override |
| public void initialize(DatabaseMapping mapping, Session session) { |
| try { |
| ConversionManager cMgr = session.getDatasourcePlatform().getConversionManager(); |
| Class<? extends DomHandler> domHandlerClass = PrivilegedAccessHelper.getClassForName(domHandlerClassName, true, cMgr.getLoader()); |
| |
| Constructor<? extends DomHandler> cons = PrivilegedAccessHelper.getDeclaredConstructorFor(domHandlerClass, new Class<?>[]{}, true); |
| this.domHandler = PrivilegedAccessHelper.invokeConstructor(cons, new Object[]{}); |
| |
| Method createUnmarshallerMethod = PrivilegedAccessHelper.getDeclaredMethod(domHandlerClass, "createUnmarshaller", new Class<?>[]{ValidationEventHandler.class}); |
| resultType = PrivilegedAccessHelper.getMethodReturnType(createUnmarshallerMethod); |
| |
| Method getElementMethod = PrivilegedAccessHelper.getDeclaredMethod(domHandlerClass, "getElement", new Class<?>[]{resultType}); |
| elementClass = PrivilegedAccessHelper.getMethodReturnType(getElementMethod); |
| |
| xmlPlatform = XMLPlatformFactory.getInstance().getXMLPlatform(); |
| } catch(Exception ex) { |
| throw JAXBException.couldNotInitializeDomHandlerConverter(ex, domHandlerClassName, mapping.getAttributeName()); |
| } |
| } |
| |
| @Override |
| public Object convertDataValueToObjectValue(Object dataValue, Session session, XMLUnmarshaller unmarshaller) { |
| if(dataValue instanceof org.w3c.dom.Element) { |
| ErrorHandler handler = unmarshaller.getErrorHandler(); |
| Result result = null; |
| if(handler != null && handler instanceof JAXBErrorHandler) { |
| result = domHandler.createUnmarshaller(((JAXBErrorHandler)handler).getValidationEventHandler()); |
| } else { |
| result = domHandler.createUnmarshaller(null); |
| } |
| if(result instanceof DOMResult){ |
| ((DOMResult) result).setNode((org.w3c.dom.Element)dataValue); |
| }else{ |
| xmlPlatform.newXMLTransformer().transform((org.w3c.dom.Element)dataValue, result); |
| } |
| return domHandler.getElement(result); |
| } |
| return dataValue; |
| } |
| |
| @Override |
| public Object convertObjectValueToDataValue(Object objectValue, Session session, XMLMarshaller marshaller) { |
| if (objectValue != null && elementClass.isAssignableFrom(objectValue.getClass())) { |
| ErrorHandler handler = marshaller.getErrorHandler(); |
| Source source = null; |
| if(handler != null && handler instanceof JAXBErrorHandler) { |
| source = domHandler.marshal(objectValue, ((JAXBErrorHandler)handler).getValidationEventHandler()); |
| } else { |
| source = domHandler.marshal(objectValue, null); |
| } |
| DOMResult result = new DOMResult(); |
| if(source instanceof DOMSource){ |
| Node n = ((DOMSource)source).getNode(); |
| if(n.getNodeType() == Node.DOCUMENT_NODE){ |
| return ((Document)n).getDocumentElement(); |
| } |
| return n; |
| }else{ |
| XMLTransformer xmlTransformer = xmlPlatform.newXMLTransformer(); |
| xmlTransformer.setFormattedOutput(marshaller.isFormattedOutput()); |
| xmlTransformer.transform(source, result); |
| return result.getNode().getFirstChild(); |
| } |
| } |
| return objectValue; |
| } |
| |
| @Override |
| public boolean isMutable() { |
| return true; |
| } |
| |
| @Override |
| public Object convertDataValueToObjectValue(Object dataValue, Session session) { |
| return convertDataValueToObjectValue(dataValue, session, null); |
| } |
| |
| @Override |
| public Object convertObjectValueToDataValue(Object objectValue, Session session) { |
| return convertObjectValueToDataValue(objectValue, session, null); |
| } |
| |
| } |