245 lines
10 KiB
Java
Executable File
245 lines
10 KiB
Java
Executable File
/*
|
|
* BEGIN_HEADER - DO NOT EDIT
|
|
*
|
|
* The contents of this file are subject to the terms
|
|
* of the Common Development and Distribution License
|
|
* (the "License"). You may not use this file except
|
|
* in compliance with the License.
|
|
*
|
|
* You can obtain a copy of the license at
|
|
* https://open-jbi-components.dev.java.net/public/CDDLv1.0.html.
|
|
* See the License for the specific language governing
|
|
* permissions and limitations under the License.
|
|
*
|
|
* When distributing Covered Code, include this CDDL
|
|
* HEADER in each file and include the License file at
|
|
* https://open-jbi-components.dev.java.net/public/CDDLv1.0.html.
|
|
* If applicable add the following below this CDDL HEADER,
|
|
* with the fields enclosed by brackets "[]" replaced with
|
|
* your own identifying information: Portions Copyright
|
|
* [year] [name of copyright owner]
|
|
*/
|
|
|
|
/*
|
|
* @(#)OperationResolver.java
|
|
*
|
|
* Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
|
|
*
|
|
* END_HEADER - DO NOT EDIT
|
|
*/
|
|
|
|
package com.sun.jbi.httpsoapbc;
|
|
|
|
import com.sun.jbi.internationalization.Messages;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.logging.Logger;
|
|
import java.util.logging.Level;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import javax.xml.namespace.QName;
|
|
import javax.wsdl.Message;
|
|
import javax.wsdl.Part;
|
|
import javax.xml.soap.SOAPBody;
|
|
import javax.xml.soap.SOAPException;
|
|
import javax.xml.soap.SOAPMessage;
|
|
|
|
import org.w3c.dom.Element;
|
|
import org.w3c.dom.NodeList;
|
|
import org.w3c.dom.Node;
|
|
|
|
/**
|
|
* Looks at the soap message content to decide which operation is being invoked/to be invoked.
|
|
*/
|
|
public class OperationResolver {
|
|
|
|
private static final String SOAP_ACTION_HEADER = "SOAPAction"; // NOI18N
|
|
private static Messages mMessages = Messages.getMessages(OperationResolver.class);
|
|
private static Logger mLogger = Messages.getLogger(OperationResolver.class);
|
|
|
|
/** Creates a new instance of MessageRouter */
|
|
public OperationResolver() {
|
|
}
|
|
|
|
/**
|
|
* first look at the soap action to see if any defined operation match.
|
|
* second look at the soap body to see if the names of the root nodes matches
|
|
* any of the defined Input messages or operation.
|
|
*
|
|
* Note:
|
|
* In doc-lit mode, if all messages have the same number of parts, all parts use type, and all parts have the same name.
|
|
* There is no way to differentiate between operations based on operation because
|
|
* all nodes of soap body would be the same part name.
|
|
*
|
|
* @param soapMsg Soap message
|
|
* @param metaDataMap map of OperationMetaData objects keyed by operation name
|
|
* @return
|
|
*/
|
|
public static OperationMetaData resolveOperation(SOAPMessage soapMsg, Map metaDataMap) {
|
|
|
|
String[] tempS = soapMsg.getMimeHeaders().getHeader(SOAP_ACTION_HEADER);
|
|
String rawSoapAction = (tempS != null && tempS.length > 0) ? tempS[0] : null;
|
|
|
|
//use this once the metro fix for the content-type
|
|
//action parameter is propagated
|
|
//if( (rawSoapAction!=null) && isSoap12(metaDataMap)){
|
|
// rawSoapAction = getSoap12Action(soapMsg);
|
|
//}
|
|
|
|
// Allow for SOAPAction with or without surrounding quotes
|
|
String soapAction = stripQuotes(rawSoapAction);
|
|
|
|
if (soapAction != null && !soapAction.equals("")) { // NOI18N
|
|
// see if the soap action can be used to find the mapping
|
|
Iterator iter = metaDataMap.values().iterator();
|
|
while (iter != null && iter.hasNext()) {
|
|
OperationMetaData meta = (OperationMetaData) iter.next();
|
|
if (meta.useSoapAction() && soapAction.equals(meta.getSoapActionURL())) {
|
|
return meta;
|
|
}
|
|
}
|
|
// if soap action is not null and we don't find a matching operation, the routing hint wasn't defined correctly'
|
|
mLogger.log(Level.WARNING, "HTTPBC-W00760.Soap_action_cant_resolve_to_operation", soapAction);
|
|
}
|
|
|
|
try {
|
|
SOAPBody soapBody = soapMsg.getSOAPBody();
|
|
NodeList nl = soapBody.getChildNodes();
|
|
|
|
List nodeNames = new ArrayList();
|
|
List nodeLocalNames = new ArrayList();
|
|
for (int i = 0; i < nl.getLength(); i++) {
|
|
Node n = nl.item(i);
|
|
|
|
if (Node.ELEMENT_NODE == n.getNodeType()) {
|
|
String ns = n.lookupNamespaceURI(n.getPrefix());
|
|
QName nodeQName = new QName(ns, ((Element)n).getLocalName());
|
|
QName unqualifiedNodeQName = new QName(((Element)n).getLocalName());
|
|
nodeNames.add(nodeQName);
|
|
nodeLocalNames.add(unqualifiedNodeQName);
|
|
}
|
|
}
|
|
|
|
// now we have a list of node names from the SOAPBody, we see if these match
|
|
// any of the messages in the list of possible operations
|
|
Iterator iter = metaDataMap.values().iterator();
|
|
while (iter != null && iter.hasNext()) {
|
|
OperationMetaData meta = (OperationMetaData) iter.next();
|
|
if (meta.isDocumentMode()) {
|
|
if (meta.useMsgAsID()) {
|
|
Set set = meta.getCachedInputPartNames();
|
|
// see if the list of input node names matches the list of expected names in the Input WSDL message
|
|
if (set.size() == nodeNames.size() && set.containsAll(nodeNames)) {
|
|
// it matches, so this operation is the one we want
|
|
return meta;
|
|
}
|
|
} else {
|
|
mLogger.log(Level.WARNING, "HTTPBC-W00761.Soap_action_cant_resolve_by_message", soapAction);
|
|
}
|
|
} else {
|
|
// for rpc mode, the root node name (wrapper) would equal the operation name
|
|
if (nodeNames.size() > 0) {
|
|
QName wrapperName = (QName)nodeNames.get(0);
|
|
if (meta.getOperationName().equals(wrapperName.getLocalPart())) {
|
|
String metaWrapperNS = getNameSpaceURIFrom(meta);
|
|
// if both have no namespace, it's a match'
|
|
if (metaWrapperNS == null || metaWrapperNS.length() == 0) {
|
|
if (wrapperName.getNamespaceURI() == null) {
|
|
return meta;
|
|
}
|
|
} else {
|
|
// if there is a namespace, it's a match if it's the same'
|
|
if (metaWrapperNS.equals(wrapperName.getNamespaceURI())) {
|
|
return meta;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
mLogger.warning("HTTPBC-W00763.Soap_body_empty");
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If no strict match is found, fall back onto more lenient matching
|
|
// It may be desirable to make this leniency optional
|
|
Iterator lenientIter = metaDataMap.values().iterator();
|
|
while (lenientIter != null && lenientIter.hasNext()) {
|
|
OperationMetaData meta = (OperationMetaData) lenientIter.next();
|
|
if (meta.isDocumentMode()) {
|
|
if (meta.useMsgAsID()) {
|
|
Set set = meta.getCachedInputPartNames();
|
|
// see if the list of input node names matches the list of expected names in the Input WSDL message
|
|
// More lenient match, look at local name of nodes
|
|
if (set.size() == nodeNames.size() && set.containsAll(nodeLocalNames)) {
|
|
return meta;
|
|
}
|
|
}
|
|
} else {
|
|
// for rpc mode, the root node name (wrapper) would equal the operation name
|
|
if (nodeNames.size() > 0) {
|
|
QName wrapperName = (QName)nodeNames.get(0);
|
|
// Just match on operation name, ignore namespace to be lenient
|
|
if (meta.getOperationName().equals(wrapperName.getLocalPart())) {
|
|
return meta;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (SOAPException e) {
|
|
if (mLogger.isLoggable(Level.WARNING)) {
|
|
String text = mMessages.getString("HTTPBC-W00762.Soap_action_cant_resolve_due_access_error", e.getLocalizedMessage());
|
|
mLogger.log(Level.WARNING, text, e);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static String getNameSpaceURIFrom(OperationMetaData meta) {
|
|
if (meta.isSoap12())
|
|
return meta.getInputSoap12Body().getNamespaceURI();
|
|
else
|
|
return meta.getInputSoapBody().getNamespaceURI();
|
|
}
|
|
|
|
private static String getSoap12Action(SOAPMessage soapMsg) {
|
|
|
|
String soapAction = null;
|
|
String[] values = soapMsg.getMimeHeaders().getHeader("Content-Type");
|
|
for (int i = 0; i < values.length; i++) {
|
|
String s= values[i];
|
|
|
|
if( s.startsWith("action=")){
|
|
soapAction = s.substring(s.lastIndexOf("action="));
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
return soapAction;
|
|
}
|
|
|
|
private static boolean isSoap12(Map metaDataMap) {
|
|
Object key = metaDataMap.keySet().iterator().next();
|
|
|
|
OperationMetaData meta = (OperationMetaData) metaDataMap.get(key);
|
|
return meta.isSoap12();
|
|
}
|
|
|
|
/**
|
|
* Remove quotes surrounding a string if present
|
|
* @param rawString string which might be surrounded by quotes
|
|
* @return string without surrounding quotes
|
|
*/
|
|
static String stripQuotes(String rawString) {
|
|
String result = rawString;
|
|
if (rawString != null && rawString.length() > 1 && rawString.startsWith("\"") && rawString.endsWith("\"")) { // NOI18N
|
|
result = rawString.substring(1, rawString.length() - 1);
|
|
}
|
|
return result;
|
|
}
|
|
}
|