openesb-components/ojc-core/httpsoapbc/httpsoapbcimpl/src/main/java/com/sun/jbi/httpsoapbc/HttpSoap12Endpoint.java

525 lines
19 KiB
Java
Executable File

/**
*
*/
package com.sun.jbi.httpsoapbc;
import java.net.InetAddress;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.wsdl.Binding;
import javax.wsdl.BindingInput;
import javax.wsdl.BindingOperation;
import javax.wsdl.BindingOutput;
import javax.wsdl.Definition;
import javax.wsdl.Input;
import javax.wsdl.Message;
import javax.wsdl.extensions.mime.MIMEContent;
import javax.wsdl.extensions.mime.MIMEPart;
import javax.wsdl.extensions.mime.MIMEMultipartRelated;
import javax.wsdl.Output;
import javax.wsdl.Part;
import javax.wsdl.Port;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.soap12.SOAP12Address;
import javax.wsdl.extensions.soap12.SOAP12Binding;
import javax.wsdl.extensions.soap12.SOAP12Body;
import javax.wsdl.extensions.soap12.SOAP12Header;
import javax.wsdl.extensions.soap12.SOAP12Operation;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import com.sun.jbi.httpsoapbc.security.api.EndpointSecurityConfig;
import com.sun.jbi.httpsoapbc.security.impl.CredentialValidatorManager;
/**
* @author Sujit Biswas
*
*/
public class HttpSoap12Endpoint extends HttpSoapEndpoint {
private static final long serialVersionUID = 1L;
private static Logger mLogger = mMessages.getLogger(HttpSoap12Endpoint.class);
/**
* @param def
* @param serviceName
* @param endpointName
* @param interfaceName
* @param isProvider
* @param wsdlPath
* @param securityConfig
* @param serviceUnitID
* @param serviceUnitRootPath
* @param cvm
*/
public HttpSoap12Endpoint(
Definition def,
QName serviceName,
String endpointName,
QName interfaceName,
boolean isProvider,
HttpClientConnectionProperties clientConnProps,
boolean propagateSoapHeader,
String wsdlPath,
EndpointSecurityConfig securityConfig,
String serviceUnitID,
String serviceUnitRootPath,
CredentialValidatorManager cvm) {
super(def,serviceName,endpointName,interfaceName,isProvider,clientConnProps, propagateSoapHeader, wsdlPath,securityConfig,serviceUnitID,serviceUnitRootPath,cvm);
}
public void init() throws Exception {
// If it has a soap binding, we need a soap address. soap:address
// should be a valid HTTP URL when we reach here.
String location = getEndpointUrl(getPort());
// if HTTP BC is providing the service, i.e. a consumer of the endpoint,
// only "localhost" is allowed as the host in the URL location
if (mIsInbound) {
String hostname = new URL(location).getHost();
if (! ( InetAddress.getLocalHost().getCanonicalHostName().equalsIgnoreCase(hostname) || "localhost".equalsIgnoreCase(hostname)) &&
!mValidHostnames.containsKey(hostname) ) {
throw new Exception(mMessages.getString("HTTPBC-E00298.Invalid_host_name", new Object[] { hostname, location, mWsdlPath }));
}
}
////////////////////////////////////////////////////////
// GSR changed for Java EE Service Engine
// As instructed by Jerry Waldorf.
////////////////////////////////////////////////////////
if ("REPLACE_WITH_ACTUAL_URL".equals(location)) {
return;
}
setEndpointUrl(new URL(location));
initSecuritySupport();
// get the operation name from the wsdl, for now assume only 1 operation
// but need to refactor this code so that a endpointbean is created for
// each operation, or refactor endpointbean so that it can handle multiple
// operations per endpoint
BindingOperation[] bos = null;
Definition currentDef = null;
bos = getOperations(getServiceDescriptor(), getServiceName().toString(), getEndpointName());
currentDef = getServiceDescriptor();
if (bos == null) {
String exMsg = mMessages.getString("HTTPBC-E00353.Endpoint_no_operation", new Object[] { getEndpointName() });
throw new Exception(exMsg);
}
LinkedHashMap operationNameToMeta = new LinkedHashMap();
for (int operationCount = 0; operationCount < bos.length; operationCount++) {
OperationMetaData meta = new OperationMetaData();
BindingOperation bo = bos[operationCount];
String operationName = bo.getName();
meta.setOperationName(operationName);
// get the soap action for the operation
String soapAction = getSoapAction(bo);
if (soapAction == null) {
if (mLogger.isLoggable(Level.FINE)) {
mLogger.log(Level.FINE, "SOAP action is not set in the wsdl for operation " + operationName);
}
meta.setSoapActionURL("");
} else {
if (mLogger.isLoggable(Level.FINE)) {
mLogger.log(Level.FINE, "SOAP action is: " + soapAction);
}
meta.setSoapActionURL(soapAction);
}
// find out the input/out messages for this operation
Input inMsg = bo.getOperation().getInput();
if (inMsg != null) {
if (inMsg.getMessage() == null) {
String exMsg = mMessages.getString("HTTPBC-E00354.Operation_no_message", new Object[] { inMsg.getName(), bo.getOperation().getName(), getEndpointName() });
throw new Exception(exMsg);
}
QName n = inMsg.getMessage().getQName();
meta.setInMsgName(inMsg.getName());
meta.setInMsgQName(n);
meta.setInputMessage(inMsg.getMessage());
}
Output outMsg = bo.getOperation().getOutput();
if (outMsg != null) {
if (outMsg.getMessage() == null) {
String exMsg = mMessages.getString("HTTPBC-E00354.Operation_no_message", new Object[] { outMsg.getName(), bo.getOperation().getName(), getEndpointName() });
throw new Exception(exMsg);
}
QName n = outMsg.getMessage().getQName();
meta.setOutMsgName(outMsg.getName());
meta.setOutMsgQName(n);
meta.setOutputMessage(outMsg.getMessage());
}
BindingInput inputBinding = bo.getBindingInput();
meta.setBindingInput(inputBinding);
if (inputBinding != null) {
meta.setInputSoap12Body(getSoap12Body(inputBinding));
meta.setInputSOAPMimeContents(getInputMimeParts(inputBinding));
}
BindingOutput outputBinding = bo.getBindingOutput();
meta.setBindingOutput(outputBinding);
if (outputBinding != null) {
meta.setOutputSoap12Body(getSoap12Body(outputBinding));
meta.setOutputSOAPMimeContents(getOutputMimeParts(outputBinding));
}
meta.setSoap12(true);
// soap headers for in/out
if (inputBinding != null) {
meta.setInputSoapHeaders(getSoapHeaders(inputBinding));
}
if (outputBinding != null) {
meta.setOutputSoapHeaders(getSoapHeaders(outputBinding));
}
//Check soap:operation first then soap:binding
boolean isDocument = true;
String style = getSoapOpStyle(bo);
if (style != null) {
isDocument = style.equalsIgnoreCase("rpc") ? false : true;
} else {
Binding binding = null;
binding = getBinding(getServiceDescriptor(), getServiceName().toString(), getEndpointName());
if (binding == null) {
String exMsg = mMessages.getString("HTTPBC-E00355.Endpoint_no_binding", new Object[] { getEndpointName() });
throw new Exception(exMsg);
}
isDocument = isDocumentMode(binding);
}
if (mLogger.isLoggable(Level.FINE)) {
mLogger.log(Level.FINE, "isDocumentMode " + isDocument + " for endpoint " + getEndpointName() + " operation " + operationName);
}
meta.setIsDocumentMode(isDocument);
// find out the faults this operation may throw
Map m = bo.getOperation().getFaults();
if (m != null) {
meta.setFaults(m);
}
meta.setFullDefinition(currentDef);
if (bo.getOperation().getStyle() == null) {
String exMsg = mMessages.getString("HTTPBC-E00356.Operation_no_mep", new Object[] { operationName });
throw new Exception(exMsg);
} else {
String mep = determineMEP(bo);
meta.setMessageExchangePattern(mep);
}
Set partNames = getInputPartNames(meta);
meta.setCachedInputPartNames(partNames);
operationNameToMeta.put(operationName, meta);
}
setOperationNameToMetaData(operationNameToMeta);
// Determine which operations have unique soap actions defined suitable for identification
Set duplicates = getDuplicateSoapActions(operationNameToMeta);
Collection metas = operationNameToMeta.values();
Iterator metasIter = metas.iterator();
while (metasIter.hasNext()) {
OperationMetaData currMeta = (OperationMetaData) metasIter.next();
String currSoapAction = currMeta.getSoapActionURL();
String currOperation = currMeta.getOperationName();
if (duplicates.contains(currSoapAction)) {
// don't rely on soap action if they are not unique
if (mLogger.isLoggable(Level.FINE)) {
mLogger.log(Level.FINE, "soap actions for operation " + currOperation + " are not unique (" + currSoapAction + "), disabling use of soap action as hints");
}
currMeta.setUseSoapAction(false);
} else {
// use soap action if they are unique within a binding
if (mLogger.isLoggable(Level.FINE)) {
mLogger.log(Level.FINE, "using soap action (" + currSoapAction + ") as hints for operation " + currOperation);
}
currMeta.setUseSoapAction(true);
}
// Determine whether the message signatures are unique within a binding
// If document mode, for each entry, compare to all other operations
boolean isUnique = true;
if (currMeta.isDocumentMode()) {
Iterator secondMetasIter = metas.iterator();
while (secondMetasIter.hasNext()) {
OperationMetaData compareMeta = (OperationMetaData) secondMetasIter.next();
if (compareMeta != currMeta) {
Set compare = compareMeta.getCachedInputPartNames();
Set current = currMeta.getCachedInputPartNames();
if (compare.size() == current.size() && compare.containsAll(current)) {
// Message signature is not unique
isUnique = false;
if (mLogger.isLoggable(Level.FINE)) {
mLogger.log(Level.FINE, "The message signature for operation " + currOperation
+ " is not unique within the binding and will not be used as a factor to resolve operations for incoming messages");
}
break;
}
}
}
}
currMeta.setUseMsgAsID(isUnique);
}
}
public String getSoapAction(BindingOperation bo) {
if (bo == null) {
return null;
}
List extElems = bo.getExtensibilityElements();
//<soap:operation soapAction="http://www.webserviceX.NET/GetQuote" style="document"/>
String soapAction = null;
Iterator extIter = extElems == null ? null : extElems.iterator();
while (extIter != null && extIter.hasNext()) {
ExtensibilityElement ee = (ExtensibilityElement) extIter.next();
if (SOAP12Operation.class.isInstance(ee)) {
SOAP12Operation oper = (SOAP12Operation) ee;
soapAction = oper.getSoapActionURI();
}
}
return soapAction;
}
public String getSoapOpStyle(BindingOperation bo) {
if (bo == null) {
return null;
}
List extElems = bo.getExtensibilityElements();
//<soap:operation soapAction="http://www.webserviceX.NET/GetQuote" style="document"/>
String soapOpStyle = null;
Iterator extIter = extElems == null ? null : extElems.iterator();
while (extIter != null && extIter.hasNext()) {
ExtensibilityElement ee = (ExtensibilityElement) extIter.next();
if (SOAP12Operation.class.isInstance(ee)) {
SOAP12Operation oper = (SOAP12Operation) ee;
soapOpStyle = oper.getStyle();
}
}
return soapOpStyle;
}
public SOAP12Body getSoap12Body(BindingInput bi) {
// assert bi != null
if (bi == null) {
throw new IllegalArgumentException(mMessages.getString("HTTPBC-E00357.BindingInput_null"));
}
return getSoap12Body0(bi.getExtensibilityElements());
}
protected SOAP12Body getSoap12Body0(List extElems) {
//soap:body
Iterator extIter = extElems == null ? null : extElems.iterator();
while (extIter != null && extIter.hasNext()) {
ExtensibilityElement ee = (ExtensibilityElement) extIter.next();
if (SOAP12Body.class.isInstance(ee)) {
SOAP12Body body = (SOAP12Body) ee; // no mime extensions
return body;
} else {
if (MIMEMultipartRelated.class.isInstance(ee)) {
MIMEMultipartRelated mimeMultipartsRelated = (MIMEMultipartRelated) ee;
List mimeParts = mimeMultipartsRelated.getMIMEParts();
Iterator mimeIter = mimeParts.iterator();
while (mimeIter.hasNext()) {
MIMEPart mimePart = (MIMEPart) mimeIter.next();
List extensions = mimePart.getExtensibilityElements();
Iterator mimePartIter = extensions.iterator();
while (mimePartIter.hasNext()) {
ee = (ExtensibilityElement) mimePartIter.next();
// only one soap:body allowed in the mime:part extension
// and by this point, we should have done the validation already
if (SOAP12Body.class.isInstance (ee)) {
SOAP12Body body = (SOAP12Body) ee;
return body;
}
}
}
}
}
}
return null;
}
public SOAP12Body getSoap12Body(BindingOutput bo) {
// assert bi != null
if (bo == null) {
throw new IllegalArgumentException(mMessages.getString("HTTPBC-E00358.BindingOutput_null"));
}
return getSoap12Body0(bo.getExtensibilityElements());
}
public List getSoapHeaders(BindingInput bi) {
if (bi == null) {
throw new IllegalArgumentException(mMessages.getString("HTTPBC-E00358.BindingOutput_null"));
}
return getSoapHeaders0(bi.getExtensibilityElements());
}
public List getSoapHeaders(BindingOutput bo) {
if (bo == null) {
throw new IllegalArgumentException(mMessages.getString("HTTPBC-E00358.BindingOutput_null"));
}
return getSoapHeaders0(bo.getExtensibilityElements());
}
public List getSoapHeaders0(List extElems) {
//soap:header
List headers = new ArrayList();
Iterator extIter = extElems == null ? null : extElems.iterator();
while (extIter != null && extIter.hasNext()) {
ExtensibilityElement ee = (ExtensibilityElement) extIter.next();
if (SOAP12Header.class.isInstance(ee)) {
SOAP12Header header = (SOAP12Header) ee;
headers.add(header);
} else {
// soap:header may be embedded in a mime extension
// good news is that by this point, all the mime extension validations would have
// been done already(at deployment time), so we are just looking for soap:header extensions here.
if (MIMEMultipartRelated.class.isInstance(ee)) {
MIMEMultipartRelated mimeMultipartsRelated = (MIMEMultipartRelated) ee;
List mimeParts = mimeMultipartsRelated.getMIMEParts();
Iterator mimeExtIter = mimeParts.iterator();
while (mimeExtIter.hasNext()) {
MIMEPart mimePart = (MIMEPart) mimeExtIter.next();
List extensions = mimePart.getExtensibilityElements();
Iterator mimePartIter = extensions.iterator();
while (mimePartIter.hasNext()) {
ee = (ExtensibilityElement) mimePartIter.next();
if (SOAP12Header.class.isInstance (ee)) {
SOAP12Header header = (SOAP12Header) ee;
headers.add(header);
}
}
}
}
}
}
return headers;
}
public String getEndpointUrl(Port port) {
String location = null;
if (port != null) {
List extElems = port.getExtensibilityElements();
//soap:address
Iterator extIter = extElems == null ? null : extElems.iterator();
while (extIter != null && extIter.hasNext()) {
ExtensibilityElement ee = (ExtensibilityElement) extIter.next();
if (SOAP12Address.class.isInstance(ee)) {
SOAP12Address addr = (SOAP12Address) ee;
location = addr.getLocationURI();
}
}
}
return location;
}
public boolean isDocumentMode(Binding binding) {
//soap:binding
//default for soap:binding style is true
List extElems = binding.getExtensibilityElements();
Iterator extIter = extElems == null ? null : extElems.iterator();
while (extIter != null && extIter.hasNext()) {
ExtensibilityElement ee = (ExtensibilityElement) extIter.next();
if (SOAP12Binding.class.isInstance(ee)) {
SOAP12Binding soapBinding = (SOAP12Binding) ee;
return (soapBinding.getStyle() == null) ? true : "document".equalsIgnoreCase(soapBinding.getStyle()); // NOI18N
}
}
return true;
}
/**
* Get the input message part names
* @param meta the operation definition
* @return part names
*/
protected Set getInputPartNames(OperationMetaData meta) {
Set set = new HashSet();
Message msg = meta.getInputMessage();
if (msg != null) {
SOAP12Body bodyBinding = meta.getInputSoap12Body();
// Should we validate here the bodyBinidng object? Don't do it for now.
List bodyParts = null;
if (bodyBinding != null) {
bodyParts = bodyBinding.getParts();
}
Iterator bodyIterator = null;
if (bodyParts != null && bodyParts.size() > 0) {
// since soap body binding specifies parts, we use only the parts that are in the binding
bodyIterator = bodyParts.iterator();
} else {
// if no parts were specified in the SOAP binding section, we use all the message parts
// currently doesn't care about order of parts
Map msgParts = msg.getParts();
if (msgParts != null) {
bodyIterator = msgParts.keySet().iterator();
}
}
// construct a set of expected names
while (bodyIterator != null && bodyIterator.hasNext()) {
String bodyPart = (String) bodyIterator.next();
Part part = msg.getPart(bodyPart);
if (part == null) {
// assert failed
String err = mMessages.getString("HTTPBC-E00352.Part_not_in_message", new Object[] { bodyPart, msg.getQName().toString() });
throw new IllegalStateException(err);
}
QName typeQName = part.getTypeName();
QName elemQName = part.getElementName();
if (typeQName != null) {
// it uses type, so the root node name is the part name
set.add(new QName(part.getName()));
} else if (elemQName != null) {
// it uses element, so the root node name is the element name
set.add(elemQName);
} else {
mLogger.log(Level.SEVERE, "HTTPBC-E00351.Part_neither_element_or_type", bodyPart);
}
}
}
return set;
}
}