blob: 361c4e13b4080539bc242712a396b103dbee8106 [file] [log] [blame]
/*
* 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 javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;
import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
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 org.eclipse.persistence.internal.oxm.Constants.BASE_64_BINARY;
import static org.eclipse.persistence.internal.oxm.Constants.SCHEMA_INSTANCE_PREFIX;
import static org.eclipse.persistence.internal.oxm.Constants.SCHEMA_PREFIX;
import static org.eclipse.persistence.internal.xr.Util.SERVICE_NAMESPACE_PREFIX;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import jakarta.activation.DataHandler;
import javax.xml.namespace.QName;
import jakarta.xml.soap.AttachmentPart;
import jakarta.xml.soap.MessageFactory;
import jakarta.xml.soap.SOAPBody;
import jakarta.xml.soap.SOAPException;
import jakarta.xml.soap.SOAPMessage;
import org.eclipse.persistence.internal.oxm.schema.model.ComplexType;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.internal.xr.Attachment;
import org.eclipse.persistence.internal.xr.Operation;
import org.eclipse.persistence.internal.xr.QueryOperation;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.mappings.XMLAnyObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLBinaryDataMapping;
import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLDirectMapping;
public class SOAPResponseWriter {
protected DBWSAdapter dbwsAdapter;
protected Map<String, XMLDescriptor> resultDescriptors = new HashMap<String, XMLDescriptor>();
public static final QName RECEIVER_QNAME = new QName(URI_NS_SOAP_1_2_ENVELOPE, "Receiver");
public static final QName SERVER_QNAME = new QName(URI_NS_SOAP_1_1_ENVELOPE, "Server");
public SOAPResponseWriter(DBWSAdapter dbwsAdapter) {
this.dbwsAdapter = dbwsAdapter;
}
@SuppressWarnings("unchecked")
public void initialize() {
SOAPResponseClassLoader loader =
new SOAPResponseClassLoader(Thread.currentThread().getContextClassLoader());
NamespaceResolver nr = new NamespaceResolver();
nr.put(SERVICE_NAMESPACE_PREFIX, dbwsAdapter.getExtendedSchema().getTargetNamespace());
for (Operation op : dbwsAdapter.getOperationsList()) {
String className = op.getName() + "_Response";
Class<?> opClass = loader.buildClass(className);
XMLDescriptor descriptor = new XMLDescriptor();
descriptor.setDefaultRootElement(SERVICE_NAMESPACE_PREFIX + ":" + op.getName() + "Response");
descriptor.setNamespaceResolver(nr);
descriptor.setJavaClass(opClass);
if (op instanceof QueryOperation) {
QueryOperation queryOperation = (QueryOperation)op;
if (queryOperation.isSimpleXMLFormat()) {
XMLAnyObjectMapping mapping = new XMLAnyObjectMapping();
mapping.setUseXMLRoot(true);
mapping.setAttributeName("result");
mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result");
descriptor.addMapping(mapping);
mapping.initialize((AbstractSession)dbwsAdapter.getOXSession());
}
else if (queryOperation.isAttachment()) {
Attachment attachment = queryOperation.getResult().getAttachment();
XMLBinaryDataMapping mapping = new XMLBinaryDataMapping();
mapping.setAttributeName("result");
mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result");
mapping.setSwaRef(true);
mapping.setShouldInlineBinaryData(false);
mapping.setMimeType(attachment.getMimeType());
descriptor.addMapping(mapping);
}
else {
QName type = queryOperation.getResult().getType();
String localElement = type.getLocalPart();
// look for top-level complex types
Set<Map.Entry<String, ComplexType>> entrySet =
dbwsAdapter.getSchema().getTopLevelComplexTypes().entrySet();
for (Map.Entry<String, ComplexType> me : entrySet) {
if (me.getValue().getName().equals(type.getLocalPart())) {
localElement = me.getKey();
break;
}
}
XMLDescriptor typeDescriptor =
dbwsAdapter.getDescriptorsByQName().get(type);
if (typeDescriptor != null) {
if (queryOperation.isCollection()) {
XMLCompositeCollectionMapping mapping =
new XMLCompositeCollectionMapping();
mapping.setAttributeName("result");
mapping.setReferenceClass(typeDescriptor.getJavaClass());
mapping.useCollectionClass(ArrayList.class);
mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result/" + localElement);
descriptor.getNamespaceResolver().setDefaultNamespaceURI(
typeDescriptor.getNamespaceResolver().getDefaultNamespaceURI());
descriptor.addMapping(mapping);
mapping.initialize((AbstractSession)dbwsAdapter.getOXSession());
}
else {
XMLCompositeObjectMapping mapping = new XMLCompositeObjectMapping();
mapping.setAttributeName("result");
mapping.setReferenceClass(typeDescriptor.getJavaClass());
mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result/" + localElement);
descriptor.getNamespaceResolver().setDefaultNamespaceURI(
typeDescriptor.getNamespaceResolver().getDefaultNamespaceURI());
descriptor.addMapping(mapping);
mapping.initialize((AbstractSession)dbwsAdapter.getOXSession());
}
}
else {
if (type.equals(new QName(W3C_XML_SCHEMA_NS_URI, "any"))) {
XMLAnyObjectMapping mapping = new XMLAnyObjectMapping();
mapping.setAttributeName("result");
mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result");
descriptor.addMapping(mapping);
}
else if (type.equals(new QName(W3C_XML_SCHEMA_NS_URI, BASE_64_BINARY))) {
XMLBinaryDataMapping mapping = new XMLBinaryDataMapping();
mapping.setAttributeName("result");
mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result");
mapping.setShouldInlineBinaryData(true);
((XMLField)mapping.getField()).setSchemaType(type);
descriptor.addMapping(mapping);
}
else {
XMLDirectMapping mapping = new XMLDirectMapping();
mapping.setAttributeName("result");
mapping.setXPath(SERVICE_NAMESPACE_PREFIX + ":" + "result/text()");
descriptor.addMapping(mapping);
}
}
}
}
dbwsAdapter.getOXSession().getProject().addDescriptor(descriptor);
((DatabaseSessionImpl)dbwsAdapter.getOXSession())
.initializeDescriptorIfSessionAlive(descriptor);
dbwsAdapter.getXMLContext().storeXMLDescriptorByQName(descriptor);
resultDescriptors.put(op.getName(), descriptor);
}
}
public SOAPMessage generateResponse(Operation op, boolean useSOAP12, Exception e) throws SOAPException {
MessageFactory messageFactory = null;
if (useSOAP12) {
messageFactory = MessageFactory.newInstance(SOAP_1_2_PROTOCOL);
} else {
messageFactory = MessageFactory.newInstance();
}
SOAPMessage message = messageFactory.createMessage();
message.getSOAPPart().getEnvelope().addNamespaceDeclaration(SCHEMA_PREFIX, W3C_XML_SCHEMA_NS_URI);
message.getSOAPPart().getEnvelope().addNamespaceDeclaration(SCHEMA_INSTANCE_PREFIX, W3C_XML_SCHEMA_INSTANCE_NS_URI);
SOAPBody body = message.getSOAPPart().getEnvelope().getBody();
QName faultCodeQName = null;
if (useSOAP12) {
faultCodeQName = RECEIVER_QNAME;
} else {
faultCodeQName = SERVER_QNAME;
}
body.addFault(faultCodeQName, op.getName() + " failed: " + e);
return message;
}
public SOAPMessage generateResponse(Operation op, boolean useSOAP12, Object result) throws SOAPException {
MessageFactory messageFactory = null;
if (useSOAP12) {
messageFactory = MessageFactory.newInstance(SOAP_1_2_PROTOCOL);
}
else {
messageFactory = MessageFactory.newInstance();
}
SOAPMessage message = messageFactory.createMessage();
message.getSOAPPart().getEnvelope().addNamespaceDeclaration(SCHEMA_PREFIX, W3C_XML_SCHEMA_NS_URI);
message.getSOAPPart().getEnvelope().addNamespaceDeclaration(SCHEMA_INSTANCE_PREFIX, W3C_XML_SCHEMA_INSTANCE_NS_URI);
SOAPBody body = message.getSOAPPart().getEnvelope().getBody();
XMLDescriptor descriptor = resultDescriptors.get(op.getName());
SOAPResponse response = null;
try {
response = (SOAPResponse) descriptor.getJavaClass().getConstructor().newInstance();
} catch (ReflectiveOperationException ie) {
throw new SOAPException(ie);
}
response.setResult(result);
SOAPAttachmentHandler attachmentHandler = new SOAPAttachmentHandler();
XMLMarshaller marshaller = dbwsAdapter.getXMLContext().createMarshaller();
marshaller.setAttachmentMarshaller(attachmentHandler);
marshaller.marshal(response, body);
if (attachmentHandler.hasAttachments()) {
// add attachments to message
for (String id : attachmentHandler.getAttachments().keySet()) {
DataHandler attachment = attachmentHandler.getAttachments().get(id);
AttachmentPart part = message.createAttachmentPart(attachment);
part.setContentType(attachment.getContentType());
String contentId = "<" + id.substring(4) + ">";
part.setContentId(contentId);
part.setMimeHeader("Content-Transfer-Encoding", "binary");
message.addAttachmentPart(part);
}
}
message.saveChanges();
return message;
}
}