org.eclipse.persistence.internal.dbws.ProviderHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction f2b9fc5
/*
* 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.dbws;
//javase imports
import static jakarta.xml.soap.SOAPConstants.SOAP_1_2_PROTOCOL;
import static jakarta.xml.soap.SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE;
import static jakarta.xml.soap.SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE;
import static jakarta.xml.ws.handler.MessageContext.INBOUND_MESSAGE_ATTACHMENTS;
import static org.eclipse.persistence.internal.dbws.SOAPResponseWriter.RECEIVER_QNAME;
import static org.eclipse.persistence.internal.dbws.SOAPResponseWriter.SERVER_QNAME;
import static org.eclipse.persistence.internal.xr.Util.DBWS_SCHEMA_XML;
import static org.eclipse.persistence.internal.xr.Util.DBWS_SERVICE_XML;
import static org.eclipse.persistence.internal.xr.Util.DBWS_WSDL;
import static org.eclipse.persistence.internal.xr.Util.META_INF_PATHS;
import static org.eclipse.persistence.internal.xr.Util.SCHEMA_2_CLASS;
import static org.eclipse.persistence.internal.xr.Util.SERVICE_NAMESPACE_PREFIX;
import static org.eclipse.persistence.internal.xr.Util.WEB_INF_DIR;
import static org.eclipse.persistence.internal.xr.Util.WSDL_DIR;
import static org.eclipse.persistence.oxm.mappings.UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
import jakarta.activation.DataHandler;
import jakarta.servlet.ServletContext;
import javax.xml.namespace.QName;
import jakarta.xml.soap.SOAPBodyElement;
import jakarta.xml.soap.SOAPElement;
import jakarta.xml.soap.SOAPEnvelope;
import jakarta.xml.soap.SOAPException;
import jakarta.xml.soap.SOAPFactory;
import jakarta.xml.soap.SOAPFault;
import jakarta.xml.soap.SOAPMessage;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import jakarta.xml.ws.Provider;
import jakarta.xml.ws.WebServiceException;
import jakarta.xml.ws.handler.MessageContext;
import jakarta.xml.ws.soap.SOAPFaultException;
import org.eclipse.persistence.dbws.DBWSModelProject;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.DBWSException;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.internal.oxm.schema.SchemaModelProject;
import org.eclipse.persistence.internal.oxm.schema.model.ComplexType;
import org.eclipse.persistence.internal.oxm.schema.model.Schema;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.internal.xr.Invocation;
import org.eclipse.persistence.internal.xr.Operation;
import org.eclipse.persistence.internal.xr.Parameter;
import org.eclipse.persistence.internal.xr.ValueObject;
import org.eclipse.persistence.internal.xr.XRServiceAdapter;
import org.eclipse.persistence.internal.xr.XRServiceFactory;
import org.eclipse.persistence.internal.xr.XRServiceModel;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.AttributeAccessor;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLRoot;
import org.eclipse.persistence.oxm.XMLUnmarshaller;
import org.eclipse.persistence.oxm.attachment.XMLAttachmentUnmarshaller;
import org.eclipse.persistence.oxm.mappings.XMLAnyCollectionMapping;
import org.eclipse.persistence.oxm.schema.XMLSchemaReference;
import org.eclipse.persistence.sessions.Project;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
// Java extension imports
// EclipseLink imports
/**
*
* INTERNAL: ProviderHelper bridges between {@link DBWSAdapter}'s and JAX-WS {@link Provider}'s
*
* @author Mike Norman - [email protected]
* @since EclipseLink 1.1
*
* packaging required for deployment as a Web Service
* \--- root of war file
* |
* \---web-inf
* | web.xml
* |
* +---classes
* | +---META-INF
* | | eclipselink-dbws.xml
* | | eclipselink-dbws-sessions.xml -- name can be overridden by <sessions-file> entry in eclipselink-dbws.xml
* | | eclipselink-dbws-or.xml
* | | eclipselink-dbws-ox.xml
* | |
* | +---_dbws
* | | DBWSProvider.java -- (source provided as a convenience for IDE integration)
* | | DBWSProvider.class -- ASM-generated jakarta.xml.ws.Provider
* | |
* | \---foo -- optional domain classes
* | \---bar
* | Address.class
* | Employee.class
* | PhoneNumber.class
* \---wsdl
* swaref.xsd -- optional to handle attachments
* eclipselink-dbws.wsdl
* eclipselink-dbws-schema.xsd
*
*/
public class ProviderHelper extends XRServiceFactory {
public static final QName SENDER_QNAME = new QName(URI_NS_SOAP_1_2_ENVELOPE, "Sender");
public static final QName CLIENT_QNAME = new QName(URI_NS_SOAP_1_1_ENVELOPE, "Client");
protected static final String XSL_PREAMBLE =
" " +
" " +
" ";
protected static final String XSL_POSTSCRIPT = " ";
public static final String MATCH_SCHEMA =
XSL_PREAMBLE +
"" +
" " +
" " +
"" +
"" +
" " +
XSL_POSTSCRIPT;
public SOAPResponseWriter responseWriter = null;
protected boolean mtomEnabled;
protected MessageContext mc;
// Default constructor required by servlet/jax-ws spec
public ProviderHelper() {
super();
}
protected void setMessageContext(MessageContext mc) {
this.mc = mc;
}
protected InputStream initXRServiceStream(ClassLoader parentClassLoader,
@SuppressWarnings("unused") ServletContext sc) {
InputStream xrServiceStream = null;
for (String searchPath : META_INF_PATHS) {
String path = searchPath + DBWS_SERVICE_XML;
xrServiceStream = parentClassLoader.getResourceAsStream(path);
if (xrServiceStream != null) {
break;
}
}
if (xrServiceStream == null) {
throw new WebServiceException(DBWSException.couldNotLocateFile(DBWS_SERVICE_XML));
}
return xrServiceStream;
}
protected InputStream initXRSchemaStream(ClassLoader parentClassLoader, ServletContext sc) {
InputStream xrSchemaStream;
String path = WSDL_DIR + DBWS_SCHEMA_XML;
if (sc != null) {
path = "/" + WEB_INF_DIR + path;
xrSchemaStream = sc.getResourceAsStream(path);
}
else {
// if ServletContext is null, then we are running in JavaSE6 'container-less' mode
xrSchemaStream = parentClassLoader.getResourceAsStream(path);
}
if (xrSchemaStream == null) {
throw new WebServiceException(DBWSException.couldNotLocateFile(DBWS_SCHEMA_XML));
}
return xrSchemaStream;
}
protected InputStream initWSDLInputStream(ClassLoader parentClassLoader, ServletContext sc) {
InputStream wsdlInputStream;
String path = WSDL_DIR + DBWS_WSDL;
if (sc != null) {
path = "/" + WEB_INF_DIR + path;
wsdlInputStream = sc.getResourceAsStream(path);
}
else {
// if ServletContext is null, then we are running in JavaSE6 'container-less' mode
wsdlInputStream = parentClassLoader.getResourceAsStream(path);
}
if (wsdlInputStream == null) {
throw new WebServiceException(DBWSException.couldNotLocateFile(DBWS_WSDL));
}
return wsdlInputStream;
}
@SuppressWarnings("unchecked")
public void init(ClassLoader parentClassLoader, ServletContext sc, boolean mtomEnabled) {
this.parentClassLoader = parentClassLoader;
this.mtomEnabled = mtomEnabled;
InputStream xrServiceStream = initXRServiceStream(parentClassLoader, sc);
DBWSModelProject xrServiceModelProject = new DBWSModelProject();
XMLContext xmlContext = new XMLContext(xrServiceModelProject);
XMLUnmarshaller unmarshaller = xmlContext.createUnmarshaller();
XRServiceModel xrServiceModel;
try {
xrServiceModel = (XRServiceModel)unmarshaller.unmarshal(xrServiceStream);
}
catch (XMLMarshalException e) {
// something went wrong parsing the eclipselink-dbws.xml - can't recover from that
throw new WebServiceException(DBWSException.couldNotParseDBWSFile());
}
finally {
try {
xrServiceStream.close();
}
catch (IOException e) {
// ignore
}
}
xrSchemaStream = initXRSchemaStream(parentClassLoader, sc);
try {
buildService(xrServiceModel); // inherit xrService processing from XRServiceFactory
}
catch (Exception e) {
// something went wrong building the service
throw new WebServiceException(e);
}
// the xrService built by 'buildService' above is overridden to produce an
// instance of DBWSAdapter (a sub-class of XRService)
DBWSAdapter dbwsAdapter = (DBWSAdapter)xrService;
// get inline schema from WSDL - has additional types for the operations
try (InputStream wsdlInputStream = initWSDLInputStream(parentClassLoader, sc)) {
StringWriter sw = new StringWriter();
StreamSource wsdlStreamSource = new StreamSource(wsdlInputStream);
Transformer t = TransformerFactory.newInstance().newTransformer(new StreamSource(
new StringReader(MATCH_SCHEMA)));
StreamResult streamResult = new StreamResult(sw);
t.transform(wsdlStreamSource, streamResult);
SchemaModelProject schemaProject = new SchemaModelProject();
XMLContext xmlContext2 = new XMLContext(schemaProject);
unmarshaller = xmlContext2.createUnmarshaller();
Schema extendedSchema = (Schema)unmarshaller.unmarshal(new StringReader(sw.toString()));
dbwsAdapter.setExtendedSchema(extendedSchema);
} catch (IOException | TransformerException e) {
// that's Ok, WSDL may not contain inline schema
xmlContext.getSession().getSessionLog().log(
SessionLog.FINE, SessionLog.DBWS, "dbws_no_wsdl_inline_schema", e.getLocalizedMessage());
}
// an Invocation needs a mapping for its parameters - use XMLAnyCollectionMapping +
// custom AttributeAccessor
// NB - this code is NOt in it own initNNN method, cannot be overridden
String tns = dbwsAdapter.getExtendedSchema().getTargetNamespace();
Project oxProject = dbwsAdapter.getOXSession().getProject();
XMLDescriptor invocationDescriptor = new XMLDescriptor();
invocationDescriptor.setJavaClass(Invocation.class);
NamespaceResolver nr = new NamespaceResolver();
invocationDescriptor.setNamespaceResolver(nr);
nr.put(SERVICE_NAMESPACE_PREFIX, tns);
nr.setDefaultNamespaceURI(tns);
XMLAnyCollectionMapping parametersMapping = new XMLAnyCollectionMapping();
parametersMapping.setAttributeName("parameters");
parametersMapping.setAttributeAccessor(new AttributeAccessor() {
Project oxProject;
DBWSAdapter dbwsAdapter;
@Override
public Object getAttributeValueFromObject(Object object) {
return ((Invocation)object).getParameters();
}
@Override
public void setAttributeValueInObject(Object object, Object value) {
Invocation invocation = (Invocation)object;
Vector