981 lines
48 KiB
Java
Executable File
981 lines
48 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]
|
|
*/
|
|
|
|
/*
|
|
* @(#)SoapNormalizer.java
|
|
*
|
|
* Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
|
|
*
|
|
* END_HEADER - DO NOT EDIT
|
|
*/
|
|
package com.sun.jbi.httpsoapbc;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
|
|
import javax.activation.DataHandler;
|
|
import javax.jbi.messaging.Fault;
|
|
import javax.jbi.messaging.MessageExchange;
|
|
import javax.jbi.messaging.MessagingException;
|
|
import javax.jbi.messaging.NormalizedMessage;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.wsdl.Message;
|
|
import javax.wsdl.Part;
|
|
import javax.wsdl.extensions.mime.MIMEContent;
|
|
import javax.xml.namespace.QName;
|
|
import javax.xml.parsers.DocumentBuilder;
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
import javax.xml.parsers.ParserConfigurationException;
|
|
import javax.xml.soap.AttachmentPart;
|
|
import javax.xml.soap.Detail;
|
|
import javax.xml.soap.DetailEntry;
|
|
import javax.xml.soap.SOAPBody;
|
|
import javax.xml.soap.SOAPElement;
|
|
import javax.xml.soap.SOAPEnvelope;
|
|
import javax.xml.soap.SOAPException;
|
|
import javax.xml.soap.SOAPFault;
|
|
import javax.xml.soap.SOAPHeader;
|
|
import javax.xml.soap.SOAPHeaderElement;
|
|
import javax.xml.soap.SOAPMessage;
|
|
import javax.xml.soap.SOAPPart;
|
|
import javax.xml.transform.dom.DOMSource;
|
|
import javax.xml.ws.handler.MessageContext;
|
|
|
|
import net.java.hulp.measure.Probe;
|
|
|
|
import org.w3c.dom.Document;
|
|
import org.w3c.dom.DocumentFragment;
|
|
import org.w3c.dom.Element;
|
|
import org.w3c.dom.NamedNodeMap;
|
|
import org.w3c.dom.Node;
|
|
import org.w3c.dom.NodeList;
|
|
|
|
import com.sun.jbi.httpsoapbc.util.DebugLog;
|
|
import com.sun.jbi.internationalization.Messages;
|
|
import com.sun.jbi.nms.wsdl11wrapper.HelperFactory;
|
|
import com.sun.jbi.nms.wsdl11wrapper.WrapperBuilder;
|
|
import com.sun.jbi.nms.wsdl11wrapper.WrapperProcessingException;
|
|
import com.sun.jbi.nms.wsdl11wrapper.util.WrapperUtil;
|
|
import java.util.HashSet;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public class Soap11Normalizer implements SoapNormalizer {
|
|
|
|
private static Messages mMessages = Messages.getMessages(Soap11Normalizer.class);
|
|
private static Logger mLog = Messages.getLogger(Soap11Normalizer.class);
|
|
protected boolean mIsHttpHeaderCopyEnabled = true;
|
|
protected boolean mIsSoapHeaderCopyEnabled = true;
|
|
// measurements
|
|
protected Probe mMeasurement = null;
|
|
private static DocumentBuilder docBuilder;
|
|
//private static DocumentBuilderFactory dbf;
|
|
protected static Map<String, String> mStandardNamespaceURIs = new HashMap<String, String>();
|
|
|
|
static {
|
|
mStandardNamespaceURIs.put("http://schemas.xmlsoap.org/soap/envelope", "http://schemas.xmlsoap.org/soap/envelope");
|
|
mStandardNamespaceURIs.put("http://www.w3.org/2003/05/soap-envelope", "http://www.w3.org/2003/05/soap-envelope");
|
|
mStandardNamespaceURIs.put("http://www.w3.org/1999/XMLSchema", "http://www.w3.org/1999/XMLSchema");
|
|
mStandardNamespaceURIs.put("http://www.w3.org/1999/XMLSchema-instance", "http://www.w3.org/1999/XMLSchema-instance");
|
|
mStandardNamespaceURIs.put("http://www.w3.org/2001/XMLSchema", "http://www.w3.org/2001/XMLSchema");
|
|
mStandardNamespaceURIs.put("http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/2001/XMLSchema-instance");
|
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
|
try {
|
|
docBuilder = dbf.newDocumentBuilder();
|
|
} catch (ParserConfigurationException pce) {
|
|
mLog.log(Level.SEVERE, mMessages.getString("HTTPBC-E01056.Failed_to_create_document_builder", pce.getLocalizedMessage()));
|
|
}
|
|
}
|
|
|
|
;
|
|
|
|
/** Creates a new instance of SoapNormalizer */
|
|
public Soap11Normalizer() {
|
|
}
|
|
|
|
public void setPropagateSoapHeader(boolean propagateSoapHeader) {
|
|
mIsSoapHeaderCopyEnabled = propagateSoapHeader;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc) @see
|
|
* com.sun.jbi.httpsoapbc.SoapNormalizerI#normalize(java.lang.Object,
|
|
* javax.jbi.messaging.MessageExchange,
|
|
* com.sun.jbi.httpsoapbc.OperationMetaData, boolean,
|
|
* javax.xml.ws.handler.MessageContext)
|
|
*/
|
|
public NormalizedMessage normalize(Object message, MessageExchange exchange, OperationMetaData meta, boolean inMsg, MessageContext context) throws MessagingException, SOAPException {
|
|
NormalizedMessage normalMsg = exchange.createMessage();
|
|
|
|
try {
|
|
String topic = "normalize" + (inMsg ? "Request" : "Reply");
|
|
mMeasurement = Probe.fine(getClass(), topic);
|
|
|
|
WrapperBuilder wrapperBuilder = HelperFactory.createBuilder();
|
|
SOAPMessage soapMessage = (SOAPMessage) message;
|
|
|
|
// Get "global" namespace(s) from SOAP envelope
|
|
Map soapEnvelopeNSs = new HashMap();
|
|
SOAPPart soapPart = soapMessage.getSOAPPart();
|
|
if (soapPart != null) {
|
|
SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();
|
|
soapEnvelopeNSs = WrapperUtil.extractNamespaceDeclarations(soapEnvelope);
|
|
filterStandardNS(soapEnvelopeNSs);
|
|
}
|
|
|
|
// Per namespace mapping rules, add any namespaces(s) from soap:envelope
|
|
// as namespace(s) to the JBI message root element
|
|
wrapperBuilder.declareGlobalNS(soapEnvelopeNSs);
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
DebugLog.debugLog(mLog, Level.FINE, "SOAP envelope namespaces", soapEnvelopeNSs);
|
|
}
|
|
|
|
// Don't create a new document; let the builder use the document
|
|
// reference from the first part that is added.
|
|
QName type = null;
|
|
String name = null;
|
|
Message msg = null;
|
|
if (inMsg) {
|
|
name = meta.getInMsgName();
|
|
msg = meta.getInputMessage();
|
|
} else {
|
|
name = meta.getOutMsgName();
|
|
msg = meta.getOutputMessage();
|
|
}
|
|
|
|
|
|
/**
|
|
* Process the SOAP body before the headers. This allows us to
|
|
* re-use the (potentially heavyweight) document object from the
|
|
* body instead of importing it into another document.
|
|
*/
|
|
SOAPBody soapBody = soapMessage.getSOAPBody();
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
DebugLog.debugLog(mLog, Level.FINE, "SOAP body to normalize", soapBody);
|
|
}
|
|
|
|
wrapperBuilder.initialize(msg, name, soapBody.getOwnerDocument());
|
|
|
|
//wrapperBuilder.initialize( msg, name);
|
|
processSoapBody(wrapperBuilder, soapBody, meta, inMsg);
|
|
|
|
|
|
|
|
|
|
SOAPHeader soapHeader = soapMessage.getSOAPHeader();
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
DebugLog.debugLog(mLog, Level.FINE, "SOAP header to normalize", soapHeader);
|
|
}
|
|
|
|
|
|
processSoapHeader(wrapperBuilder, normalMsg, soapHeader, meta, inMsg, exchange);
|
|
|
|
|
|
if (mIsHttpHeaderCopyEnabled && context != null && inMsg) {
|
|
processHTTPRequestHeaders(normalMsg, context);
|
|
}
|
|
|
|
|
|
processSoapAttachment(wrapperBuilder, soapMessage, meta, inMsg, normalMsg);
|
|
|
|
|
|
Document normalDoc = wrapperBuilder.getResult();
|
|
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
DebugLog.debugLog(mLog, Level.FINE, "Normalized message", normalDoc);
|
|
}
|
|
|
|
normalMsg.setContent(new DOMSource(normalDoc));
|
|
|
|
} catch (ParserConfigurationException tex) {
|
|
throw new MessagingException(mMessages.getString("HTTPBC-E00798.Normalize_fail", tex.getLocalizedMessage()), tex);
|
|
} catch (WrapperProcessingException ex) {
|
|
throw new MessagingException(mMessages.getString("HTTPBC-E00798.Normalize_fail", ex.getLocalizedMessage()), ex);
|
|
} catch (ClassCastException ex) {
|
|
String msg = mMessages.getString("HTTPBC-E00797.Normalize_fail_wrong_type",
|
|
new Object[]{"SOAPMessage", message.getClass().toString()});
|
|
throw new MessagingException(msg, ex);
|
|
} catch (Exception ex) {
|
|
throw new MessagingException(mMessages.getString("HTTPBC-E00798.Normalize_fail", ex.getLocalizedMessage()), ex);
|
|
} finally {
|
|
if (mMeasurement != null) {
|
|
mMeasurement.end();
|
|
}
|
|
}
|
|
|
|
return normalMsg;
|
|
}
|
|
|
|
public Fault normalizeFault(SOAPMessage soapMessage, MessageExchange exchange, OperationMetaData meta, boolean failFast) throws MessagingException, SOAPException {
|
|
return normalizeFault(soapMessage.getSOAPBody().getFault(), exchange, meta, failFast);
|
|
}
|
|
|
|
public Fault normalizeFault(SOAPFault soapFault, MessageExchange exchange, OperationMetaData meta, boolean failFast) throws MessagingException, SOAPException {
|
|
Fault normalFault = exchange.createFault();
|
|
boolean hasMatchingDefinedFault = false;
|
|
boolean hasFaultDetail = false;
|
|
|
|
Document normalDoc = docBuilder.newDocument();
|
|
|
|
try {
|
|
|
|
normalFault.setContent(new DOMSource(normalDoc));
|
|
|
|
Element normalRoot = null;
|
|
|
|
// Identify fault by comparing the detail element in the
|
|
// soap message to the wsdl fault messages defined
|
|
Detail detail = soapFault.getDetail();
|
|
hasFaultDetail = (detail != null);
|
|
if (hasFaultDetail) {
|
|
Map definedFaults = meta.getFaults();
|
|
Message foundFault = null;
|
|
String foundFaultName = null;
|
|
Part foundPart = null;
|
|
Iterator detailIterator = detail.getDetailEntries();
|
|
while (detailIterator != null && detailIterator.hasNext() && foundFault == null) {
|
|
DetailEntry de = (DetailEntry) detailIterator.next();
|
|
String detailName = de.getLocalName();
|
|
String detailElemURI = de.getElementName().getURI();
|
|
String detailElemLocalName = de.getElementName().getLocalName();
|
|
Iterator faultsIter = definedFaults.entrySet().iterator();
|
|
while (faultsIter.hasNext() && foundFault == null) {
|
|
Map.Entry entry = (Map.Entry) faultsIter.next();
|
|
String faultName = (String) entry.getKey();
|
|
javax.wsdl.Fault wsdlFault = (javax.wsdl.Fault) entry.getValue();
|
|
Message faultMsg = wsdlFault.getMessage();
|
|
// Fault message can only have one part
|
|
Map partNamesToParts = faultMsg.getParts();
|
|
Iterator partsIter = partNamesToParts.values().iterator();
|
|
if (partsIter.hasNext()) {
|
|
Part part = (Part) partsIter.next();
|
|
QName partElemName = part.getElementName();
|
|
QName partTypeName = part.getTypeName();
|
|
// Match soap faults based on element name
|
|
if (partElemName != null) {
|
|
String partElemURI = partElemName.getNamespaceURI();
|
|
String partElemLocalName = partElemName.getLocalPart();
|
|
// if the namespace matches, and the local name of the detail element
|
|
// then this fault matches
|
|
if (((detailElemURI == null && partElemURI == null) || (detailElemURI != null && detailElemURI.equals(partElemURI))) && detailElemLocalName.equals(partElemLocalName)) {
|
|
foundFault = faultMsg;
|
|
foundFaultName = faultName;
|
|
foundPart = part;
|
|
}
|
|
// Match soap faults based on type name
|
|
} else if (partTypeName != null) {
|
|
// Find an element with the same name as the part
|
|
if (detailElemLocalName.equals(part.getName())) {
|
|
foundFault = faultMsg;
|
|
foundFaultName = faultName;
|
|
foundPart = part;
|
|
}
|
|
}
|
|
} else {
|
|
if (mLog.isLoggable(Level.WARNING)) {
|
|
mLog.log(Level.WARNING, "HTTPBC-W00710.Fault_message_has_no_parts", faultName);
|
|
}
|
|
}
|
|
}
|
|
|
|
hasMatchingDefinedFault = (foundFault != null);
|
|
if (hasMatchingDefinedFault) {
|
|
// super! we found the fault message associated with this fault
|
|
// create normalized message based on defined WSDL message
|
|
|
|
QName type = foundFault.getQName();
|
|
WrapperBuilder wrapperBuilder = HelperFactory.createBuilder();
|
|
wrapperBuilder.initialize(normalDoc, foundFault, foundFaultName);
|
|
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
mLog.log(Level.FINE, "Found matching WSDL message for detail entry: " + detailName);
|
|
}
|
|
|
|
// create jbi part wrapper and add to normal doc
|
|
wrapperBuilder.addPart(foundPart.getName(), de);
|
|
normalDoc = wrapperBuilder.getResult();
|
|
} else {
|
|
// message with this name is not found just get the DetailEntries
|
|
// and add them into the normalized document
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
mLog.log(Level.FINE, "Did NOT find matching WSDL message for detail entry " + detailName);
|
|
}
|
|
|
|
// @TODO: should it add wsdl 1.1 wrapper even though not defined in wsdl?
|
|
// If so, how could it fill in the mandatory type attribute?
|
|
if (!normalDoc.hasChildNodes()) {
|
|
normalRoot = normalDoc.createElement(meta.getOperationName());
|
|
normalDoc.appendChild(normalRoot);
|
|
}
|
|
|
|
Node n = normalDoc.importNode(de, true);
|
|
normalRoot.appendChild(n);
|
|
}
|
|
}
|
|
} else {
|
|
// no details in the fault, its just a generic soap fault
|
|
// create a generic normalized fault
|
|
// @TODO: should it add wsdl 1.1 wrapper even though there is no detail content?
|
|
}
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
DebugLog.debugLog(mLog, Level.FINE, "SOAP Fault to normalize", normalDoc);
|
|
}
|
|
} catch (WrapperProcessingException ex) {
|
|
throw new MessagingException(mMessages.getString("HTTPBC-E00798.Normalize_fail", ex.getLocalizedMessage()), ex);
|
|
}
|
|
// failFast flag is intended to suppress "hiding" of a fault mismatch
|
|
// (between what is defined in the WSDL, and what is in the actual message).
|
|
// If message has no fault detail, or message has a fault not defined
|
|
// in the web service operation, instead of returning a "fake" Fault,
|
|
// return null pointer, when failFlag is set.
|
|
if (failFast) {
|
|
if (!hasMatchingDefinedFault || !hasFaultDetail) {
|
|
return null;
|
|
}
|
|
}
|
|
return normalFault;
|
|
}
|
|
|
|
protected void processSoapAttachment(WrapperBuilder wrapperBuilder, SOAPMessage soapMessage, OperationMetaData metaData, boolean inMsg, NormalizedMessage normalMsg)
|
|
throws Exception {
|
|
Map mimeParts = null;
|
|
if (inMsg) {
|
|
mimeParts = metaData.getInputSOAPMimeContents();
|
|
} else {
|
|
mimeParts = metaData.getOutputSOAPMimeContents();
|
|
}
|
|
|
|
Set<String> resolvedAttachments = new HashSet<String>();
|
|
|
|
// Process MIME attachments
|
|
Iterator mimeContents = mimeParts.values().iterator();
|
|
while (mimeContents.hasNext()) {
|
|
MIMEContent mimeContent = (MIMEContent) mimeContents.next();
|
|
String mimePart = mimeContent.getPart();
|
|
String mimeType = mimeContent.getType();
|
|
|
|
for (Iterator attachments = soapMessage.getAttachments(); attachments.hasNext();) {
|
|
AttachmentPart attachment = (AttachmentPart) attachments.next();
|
|
String contentId = attachment.getContentId();
|
|
String contentType = attachment.getContentType();
|
|
//if (contentId.indexOf(mimePart + "=") >= 0 && contentType.equalsIgnoreCase(mimeType)) {
|
|
if (contentId.indexOf(mimePart + "=") >= 0 && contentType.indexOf(mimeType) >= 0) {
|
|
// found the mime attachment
|
|
DataHandler dataHandler = attachment.getDataHandler();
|
|
// add the message part
|
|
//wrapperBuilder.addPartWithAttachment(mimePart, contentId);
|
|
// rely on the WrapperBuilder API to create the cid per the URI scheme
|
|
String cid = wrapperBuilder.addPartWithAttachment(mimePart);
|
|
normalMsg.addAttachment(cid, dataHandler);
|
|
|
|
resolvedAttachments.add(contentId);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Process other attachments : MTOM, SWAREF
|
|
for (Iterator attachments = soapMessage.getAttachments(); attachments.hasNext();) {
|
|
AttachmentPart attachment = (AttachmentPart) attachments.next();
|
|
String contentId = attachment.getContentId();
|
|
|
|
if (! resolvedAttachments.contains(contentId)) {
|
|
DataHandler dataHandler = attachment.getDataHandler();
|
|
// Be careful about <cid: ...>
|
|
if (contentId.indexOf('<') == 0 && (contentId.indexOf('>') == contentId.length() - 1)) {
|
|
contentId = contentId.substring(1, contentId.length() - 1);
|
|
}
|
|
|
|
normalMsg.addAttachment(contentId, dataHandler);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void processSoapBody(WrapperBuilder wrapperBuilder, SOAPBody soapElement, OperationMetaData meta, boolean inMsg)
|
|
throws WrapperProcessingException, Exception {
|
|
// Per namespace mapping rules, collect all relevant namespaces from
|
|
// soap:body and add them as namespaces to the JBI part
|
|
Map nameSpaces = WrapperUtil.extractNamespaceDeclarations(soapElement);
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
DebugLog.debugLog(mLog, Level.FINE, "SOAP body namespaces", nameSpaces);
|
|
}
|
|
|
|
javax.wsdl.extensions.soap.SOAPBody soapBody = null;
|
|
if (inMsg) {
|
|
soapBody = meta.getInputSoapBody();
|
|
} else {
|
|
soapBody = meta.getOutputSoapBody();
|
|
}
|
|
Message msg = null;
|
|
if (inMsg) {
|
|
msg = meta.getInputMessage();
|
|
} else {
|
|
msg = meta.getOutputMessage();
|
|
}
|
|
String msgTNS = meta.getFullDefinition().getTargetNamespace();
|
|
// IF the soap body is defined as empty, return
|
|
if (soapBody == null) {
|
|
return;
|
|
}
|
|
List bodyParts = soapBody.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
|
|
if (msg == null) {
|
|
// assert failed
|
|
throw new IllegalStateException("Unexpected state, input WSDLMessage is not defined, however we are attempting to invoke the operation with non-empty input");
|
|
}
|
|
bodyIterator = msg.getParts().keySet().iterator();
|
|
/*
|
|
* For debugging String [] keyArr = (String[])
|
|
* msg.getParts().keySet().toArray(new String[0]); Map.Entry[]
|
|
* entryArr = (Map.Entry[]) msg.getParts().entrySet().toArray(new
|
|
* Map.Entry[0]); for(int i=0;i<keyArr.length;++i) { String key =
|
|
* keyArr[i]; Map.Entry entry = entryArr[i]; mLog.fine("####Debug
|
|
* SoapNormalizer key ["+key+"] entry
|
|
* ["+entry.getKey()+"]["+entry.getValue()+"]"); }
|
|
*/
|
|
}
|
|
String soapBodyURI = soapBody.getNamespaceURI();
|
|
boolean isDocument = (meta.isDocumentMode() == true);
|
|
boolean isRPC = (meta.isDocumentMode() == false);
|
|
Element operElem = null;
|
|
if (isRPC) {
|
|
if (soapBodyURI != null) {
|
|
if (mLog.isLoggable(Level.FINER)) {
|
|
mLog.log(Level.FINER, "SOAP body namespace in use: " + soapBodyURI);
|
|
}
|
|
}
|
|
String operationTNS = soapBodyURI == null ? "*" : soapBodyURI;
|
|
operElem = findResponsePart(soapElement, new QName(operationTNS, meta.getOperationName()), inMsg);
|
|
// look for operation node in soap msg
|
|
// should have only 1 element with operation's name under wrapper
|
|
// get the part node under operation node
|
|
// use namespace to find operation, parts do not have a namespace
|
|
if (operElem == null) {
|
|
mLog.log(Level.WARNING, "HTTPBC-W00711.Soap_message_has_no_match_for_operation", meta.getOperationName());
|
|
throw new WrapperProcessingException(mMessages.getString("HTTPBC-W00711.Soap_message_has_no_match_for_operation",
|
|
meta.getOperationName()));
|
|
} else {
|
|
// Per namespace mapping rules, collect all relevant namespaces from
|
|
// soap:body operation and add them as namespaces to the JBI part
|
|
Map operElemNSs = WrapperUtil.extractNamespaceDeclarations(operElem);
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
DebugLog.debugLog(mLog, Level.FINE, "Operation " + operElem.getLocalName() + " namespaces", nameSpaces);
|
|
}
|
|
if (operElemNSs != null) {
|
|
nameSpaces.putAll(operElemNSs);
|
|
}
|
|
}
|
|
}
|
|
|
|
while (bodyIterator != null && bodyIterator.hasNext()) {
|
|
Map partNameSpaces;
|
|
Map partAttributes;
|
|
if (nameSpaces != null) {
|
|
partNameSpaces = new HashMap(nameSpaces);
|
|
} else {
|
|
partNameSpaces = new HashMap();
|
|
}
|
|
|
|
// initialize the part attributes map
|
|
partAttributes = new HashMap();
|
|
|
|
String bodyPart = (String) bodyIterator.next();
|
|
|
|
// based on the part name, look up the element/type QName in the WSDLMessage
|
|
if (msg == null) {
|
|
// assert failed
|
|
throw new IllegalStateException("Unexpected state, input WSDLMessage is not defined, however we are attempting to invoke the operation with non-empty input");
|
|
}
|
|
Part part = msg.getPart(bodyPart);
|
|
if (part == null) {
|
|
// assert failed
|
|
String err = mMessages.getString("HTTPBC-E00702.Message_part_bad_reference", new Object[]{bodyPart, msg.getQName().toString()});
|
|
throw new IllegalStateException(err);
|
|
}
|
|
QName typeQName = part.getTypeName(); //wsdl:part of type
|
|
QName elemQName = part.getElementName(); //wsdl:part of element
|
|
boolean isType = typeQName != null;
|
|
boolean isElem = elemQName != null;
|
|
boolean TYPE_DOC = (isType && isDocument);
|
|
boolean TYPE_RPC = (isType && isRPC);
|
|
boolean ELEM_DOC = (isElem && isDocument);
|
|
boolean ELEM_RPC = (isElem && isRPC);
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
mLog.log(Level.FINE, "TYPE_DOC: " + TYPE_DOC + " TYPE_RPC: " + TYPE_RPC + " ELEM_DOC: " + ELEM_DOC + " ELEM_RPC: " + ELEM_RPC);
|
|
}
|
|
|
|
Element e = null;
|
|
Element msgElem = isDocument ? soapElement : operElem;
|
|
String lookingMsg = isType ? "Looking for part in SOAP message" : "Looking for element in normalized message";
|
|
String nullMsg = isType ? "HTTPBC-W00712.Soap_message_has_no_match_for_part" : "HTTPBC-W00713.Soap_message_has_no_match_for_element";
|
|
String creatingMsg = null;
|
|
String uri = null;
|
|
String localName = null;
|
|
if (TYPE_DOC) {
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
mLog.log(Level.FINE, "Style is Document, part " + part.getName() + " is Type, QName " + typeQName.toString());
|
|
}
|
|
creatingMsg = "Creating normalized message for doc-literal mode with type";
|
|
uri = msgTNS;
|
|
localName = part.getName();
|
|
} else if (TYPE_RPC) {
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
mLog.log(Level.FINE, "Style is RPC, part " + part.getName() + " is Type, QName " + typeQName.toString());
|
|
}
|
|
creatingMsg = "Creating normalized message for rpc-literal mode with type";
|
|
uri = "*";
|
|
localName = part.getName();
|
|
} else if (ELEM_DOC) {
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
mLog.log(Level.FINE, "Style is Document, part " + part.getName() + " is Element, QName " + elemQName.toString());
|
|
}
|
|
creatingMsg = "Creating normalized message for doc-literal mode with element";
|
|
uri = elemQName.getNamespaceURI();
|
|
localName = elemQName.getLocalPart();
|
|
} else if (ELEM_RPC) {
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
mLog.log(Level.FINE, "Style is RPC, part " + part.getName() + " is Element, QName " + elemQName.toString());
|
|
}
|
|
creatingMsg = "Creating normalized message for rpc-literal mode with element";
|
|
uri = "*";
|
|
msgElem = findMsgElement(operElem, new QName(uri, bodyPart)); //elemQName.getLocalPart()
|
|
if (msgElem == null) {
|
|
throw new Exception(mMessages.getString("HTTPBC-E00802.Missing_message_part_in_RPC_element", bodyPart));
|
|
}
|
|
localName = elemQName.getLocalPart();
|
|
}
|
|
QName partQName = new QName(uri, localName);
|
|
|
|
if (mLog.isLoggable(Level.FINEST)) {
|
|
mLog.log(Level.FINEST, lookingMsg);
|
|
}
|
|
e = findMsgElement(msgElem, partQName);
|
|
if (e != null) {
|
|
// Per namespace mapping rules, collect all relevant namespaces from
|
|
// the part element of the soap message if the corresponding part is defined as a type
|
|
// in the wsdl; these namespaces will be added to the JBI part
|
|
if (isType) {
|
|
Map partNSs = WrapperUtil.extractNamespaceDeclarations(e);
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
DebugLog.debugLog(mLog, Level.FINE, "Part '" + localName + "' namespaces", partNSs);
|
|
}
|
|
if (partNSs != null) {
|
|
partNameSpaces.putAll(partNSs);
|
|
}
|
|
// extract any attribute declarations on the part to propagate onto the corresponding jbi:part
|
|
partAttributes = WrapperUtil.extractAttributeDeclarations(e);
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
DebugLog.debugLog(mLog, Level.FINE, "Part '" + localName + "' attributes", partAttributes);
|
|
}
|
|
}
|
|
if (mLog.isLoggable(Level.FINEST)) {
|
|
mLog.log(Level.FINEST, creatingMsg);
|
|
}
|
|
// add the part node to the normalized document
|
|
if (TYPE_DOC) {
|
|
// document mode using type
|
|
// see if the part name can be found in the soap body element
|
|
// add the part node to the normalized document
|
|
wrapperBuilder.addPart(part.getName(), e.getChildNodes(), partNameSpaces, partAttributes);
|
|
} else if (TYPE_RPC) {
|
|
// rpc mode using type
|
|
// look for operation node in soap msg
|
|
// should have only 1 element with operation's name under wrapper
|
|
// get the part node under operation node
|
|
wrapperBuilder.addPart(part.getName(), e.getChildNodes(), partNameSpaces, partAttributes);
|
|
} else if (ELEM_DOC) {
|
|
// it is a element
|
|
// document mode using element
|
|
// see if the element name can be found in the soap body
|
|
wrapperBuilder.addPart(part.getName(), e, partNameSpaces);
|
|
} else if (ELEM_RPC) {
|
|
// rpc mode using element
|
|
// look for operation node in soap msg
|
|
// get the part node under operation node
|
|
// Add the contents under the existing part node in the request to the JBI part wrapper
|
|
//mWrapperBuilder.addPart(part.getName(), e.getChildNodes());
|
|
wrapperBuilder.addPart(part.getName(), e, partNameSpaces);
|
|
}
|
|
} else {
|
|
throw new WrapperProcessingException(mMessages.getString(nullMsg, partQName.toString()));
|
|
}
|
|
} // end while
|
|
}
|
|
|
|
protected void processSoapHeader(WrapperBuilder wrapperBuilder, NormalizedMessage normalMsg, SOAPHeader soapHeader, OperationMetaData meta, boolean inMsg, MessageExchange mex)
|
|
throws WrapperProcessingException {
|
|
List headerList = null;
|
|
if (inMsg) {
|
|
headerList = meta.getInputSoapHeaders();
|
|
} else {
|
|
headerList = meta.getOutputSoapHeaders();
|
|
}
|
|
|
|
// Handle custom reliability protocol.
|
|
// If present, Extract MessageID and place it in the message exchange properties
|
|
if (soapHeader != null) {
|
|
Iterator headerIter = soapHeader.examineAllHeaderElements();
|
|
while (headerIter.hasNext()) {
|
|
SOAPHeaderElement he = (SOAPHeaderElement) headerIter.next();
|
|
|
|
if (he.getLocalName().equals(WSRM_Sequence)
|
|
&& (he.getNamespaceURI().equals(WSRM__1_0__NAMESPACE_URI) || he.getNamespaceURI().equals(WSRM__1_1__NAMESPACE_URI))) {
|
|
// handle ws-rm soap messages
|
|
propagateWSRMIdsToExchange(he, mex);
|
|
}
|
|
|
|
// 11-20-2007 - With the introduction of using WS-RM and the new JBI message properties for grouping/sequencing,
|
|
// the following code in the "if" clause for handling custom reliability may be removed upon further review...
|
|
if (he.getLocalName().equals(CUSTOM_RELIABILITY_HEADER_LOCAL_NAME) && CUSTOM_RELIABILITY_HEADER_NAMESPACE_URI.equals(he.getNamespaceURI())) {
|
|
String messageID = he.getTextContent();
|
|
normalMsg.setProperty(CUSTOM_RELIABILITY_MESSAGE_ID_PROPERTY, messageID);
|
|
if (mLog.isLoggable(Level.FINEST)) {
|
|
mLog.log(Level.FINEST, "Normalized Message ID set to: " + messageID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// End handling of custom reliability protocol
|
|
|
|
// The service does not define any headers. All headers in the message
|
|
// will be copied to the Normalized Message as properties.
|
|
if (mIsSoapHeaderCopyEnabled && soapHeader != null && (headerList == null || headerList.size() < 1)) {
|
|
for (Iterator headerIter = soapHeader.examineAllHeaderElements();
|
|
headerIter.hasNext();) {
|
|
addSOAPHeader(normalMsg, (SOAPHeaderElement) headerIter.next());
|
|
}
|
|
return;
|
|
}
|
|
|
|
// assumes the message where the header part is defined is the same
|
|
// as the in/out message of the operation.
|
|
// @todo consider the case where header is not a part in the in/out message
|
|
Message wsMessage = null;
|
|
if (inMsg) {
|
|
wsMessage = meta.getInputMessage();
|
|
} else {
|
|
wsMessage = meta.getOutputMessage();
|
|
}
|
|
if (soapHeader != null) {
|
|
// Per namespace mapping rules, collect all relevant namespaces from
|
|
// soap:header and add them as namespaces to the JBI part
|
|
Map nameSpaces = WrapperUtil.extractNamespaceDeclarations(soapHeader);
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
DebugLog.debugLog(mLog, Level.FINE, "SOAP header namespaces", nameSpaces);
|
|
}
|
|
|
|
for (Iterator headerIter = soapHeader.examineAllHeaderElements();
|
|
headerIter.hasNext();) {
|
|
|
|
SOAPHeaderElement elem = (SOAPHeaderElement) headerIter.next();
|
|
boolean headerProcessed = false;
|
|
|
|
for (int i = 0; i < headerList.size() && !headerProcessed; ++i) {
|
|
javax.wsdl.extensions.soap.SOAPHeader headerDef =
|
|
(javax.wsdl.extensions.soap.SOAPHeader) headerList.get(i);
|
|
|
|
if (headerDef.getMessage().equals(wsMessage.getQName())) {
|
|
Part part = wsMessage.getPart(headerDef.getPart());
|
|
if (part == null) {
|
|
// part not found in the in/out message, currently not supported
|
|
String msg = mMessages.getString("HTTPBC-W00714.Unsupported_feature_part_in_header_not_in_message", new Object[]{headerDef.getPart(), wsMessage.getQName()});
|
|
throw new IllegalArgumentException(msg);
|
|
}
|
|
QName partElemName = part.getElementName();
|
|
if (partElemName == null) {
|
|
// part needs to be defined as element, currently not supported
|
|
String msg = mMessages.getString("HTTPBC-W00715.Unsupported_feature_part_in_header_not_element", new Object[]{headerDef.getPart(), wsMessage.getQName()});
|
|
throw new IllegalArgumentException(msg);
|
|
}
|
|
if (partElemName.equals(elem.getElementQName())) {
|
|
Map partNameSpaces;
|
|
if (nameSpaces != null) {
|
|
partNameSpaces = new HashMap(nameSpaces);
|
|
} else {
|
|
partNameSpaces = new HashMap();
|
|
}
|
|
|
|
/*
|
|
* boolean isType = part.getTypeName() != null; if
|
|
* (isType) { // Per namespace mapping rules,
|
|
* collect all relevant namespaces from // the part
|
|
* element of the soap message if the corresponding
|
|
* part is defined as a type // in the wsdl; these
|
|
* namespaces will be added to the JBI part Map
|
|
* partNSs =
|
|
* WrapperUtil.extractNamespaceDeclarations(elem);
|
|
* if (partNSs != null) { if
|
|
* (mLog.isLoggable(Level.FINE)) {
|
|
* DebugLog.debugLog(mLog, Level.FINE, "SOAP header
|
|
* element (type) '" + elem.getLocalName() + "'
|
|
* namespaces", partNSs); }
|
|
* partNameSpaces.putAll(partNSs); } }
|
|
*/
|
|
wrapperBuilder.addPart(part.getName(), elem, partNameSpaces);
|
|
headerProcessed = true;
|
|
}
|
|
}
|
|
}
|
|
if (mIsSoapHeaderCopyEnabled && !headerProcessed) {
|
|
addSOAPHeader(normalMsg, elem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void addSOAPHeader(NormalizedMessage msg, SOAPHeaderElement elem) throws WrapperProcessingException {
|
|
Map<String, DocumentFragment> propertyMap = null;
|
|
propertyMap = (Map<String, DocumentFragment>) msg.getProperty(NormalizedMessageProperties.SOAP_HEADER_PROPERTY);
|
|
if (propertyMap == null) {
|
|
propertyMap = new HashMap<String, DocumentFragment>();
|
|
msg.setProperty(NormalizedMessageProperties.SOAP_HEADER_PROPERTY, propertyMap);
|
|
}
|
|
|
|
|
|
|
|
|
|
Document document = null;
|
|
DocumentFragment documentFragment = null;
|
|
|
|
String name = elem.getElementQName().toString();
|
|
if (propertyMap.get(name) != null && propertyMap.get(name) instanceof DocumentFragment) {
|
|
documentFragment = (DocumentFragment) propertyMap.get(name);
|
|
} else {
|
|
|
|
document = docBuilder.newDocument();
|
|
documentFragment = document.createDocumentFragment();
|
|
|
|
}
|
|
|
|
Node imported = documentFragment.getOwnerDocument().importNode(elem, true);
|
|
documentFragment.appendChild(imported);
|
|
propertyMap.put(name, documentFragment);
|
|
|
|
}
|
|
|
|
protected Element findResponsePart(Element soapElement, QName operationQName, boolean inMsg) throws Exception {
|
|
Element e = null;
|
|
//Util.toXml(soapElement.getOwnerDocument(),"UTF-8", false);
|
|
// The BP 1.0 clarifies in R2729 that for RPC literal, the response wrapper should be operation name + "Response"
|
|
// Therefore for operation output messages check for an element matching this pattern first.
|
|
if (!inMsg) {
|
|
e = findMsgElement(soapElement, new QName(operationQName.getNamespaceURI(),
|
|
operationQName.getLocalPart() + SoapDenormalizer.RPC_RESPONSE_SUFFIX));
|
|
}
|
|
|
|
// For operation input messages, or if the output message wrapper is not named in a BP compliant manner
|
|
// look for the wrapper named according to the operation name only
|
|
if (e == null) {
|
|
e = findMsgElement(soapElement, operationQName);
|
|
}
|
|
|
|
return e;
|
|
}
|
|
|
|
protected Element findMsgElement(Element root, QName elemQName) throws Exception {
|
|
if (mLog.isLoggable(Level.FINER)) {
|
|
mLog.log(Level.FINER, "Finding part for root", elemQName.toString());
|
|
DebugLog.debugLog(mLog, Level.FINER, "", root);
|
|
}
|
|
boolean ignoreNS = elemQName.getNamespaceURI().equals("*") ? true : false;
|
|
|
|
// We only care about the next level.
|
|
NodeList nl = root.getChildNodes();
|
|
int nodeLen = nl.getLength();
|
|
if (mLog.isLoggable(Level.FINEST)) {
|
|
mLog.log(Level.FINEST, "Found " + nl.getLength() + " nodes");
|
|
}
|
|
if (nl != null && nl.getLength() > 0) {
|
|
for (int i = 0; i < nodeLen; i++) {
|
|
Object obj = nl.item(i);
|
|
if (!(obj instanceof Element)) {
|
|
continue;
|
|
}
|
|
Element e2 = (Element) obj;
|
|
if (mLog.isLoggable(Level.FINEST)) {
|
|
mLog.log(Level.FINEST, "Looking for element namespace [" + e2.getNamespaceURI() + "] localname [" + e2.getLocalName() + "]");
|
|
//DebugLog.debugLog(mLog, Level.FINEST, "", e2);
|
|
}
|
|
if (e2.getLocalName().equals(elemQName.getLocalPart())) {
|
|
String e2NS = e2.getNamespaceURI() == null ? "" : e2.getNamespaceURI();
|
|
if (ignoreNS || e2NS.equals(elemQName.getNamespaceURI())) {
|
|
if (mLog.isLoggable(Level.FINER)) {
|
|
mLog.log(Level.FINEST, "Found element with namespace [" + e2.getNamespaceURI() + "] localname [" + e2.getLocalName() + "]");
|
|
DebugLog.debugLog(mLog, Level.FINER, "Returning element", e2);
|
|
}
|
|
return e2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
protected void propagateWSRMIdsToExchange(SOAPHeaderElement wsrmSequenceElem, MessageExchange mex) {
|
|
boolean sequenceIdentifierFound = false;
|
|
// First try locating the sequence identifier from the wsrm 1.0 namespace
|
|
Iterator identifierIter = wsrmSequenceElem.getChildElements(QNAME_WSRM__1_0__Sequence_Identifier);
|
|
while (identifierIter.hasNext()) {
|
|
SOAPElement identifierElem = (SOAPElement) identifierIter.next();
|
|
String sequenceIdentifier = identifierElem.getValue();
|
|
mex.setProperty(CRMP_GROUP_ID, sequenceIdentifier);
|
|
sequenceIdentifierFound = true;
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
mLog.log(Level.FINE, "The soap message is ws-rm 1.0 enabled message; populated "
|
|
+ SoapNormalizer.CRMP_GROUP_ID + " with value ["
|
|
+ sequenceIdentifier + "] for message exchange with ID [" + mex.getExchangeId() + "]");
|
|
}
|
|
break;
|
|
}
|
|
|
|
// If sequence identifier not found, try the wsrm 1.1 namespace
|
|
if (!sequenceIdentifierFound) {
|
|
identifierIter = wsrmSequenceElem.getChildElements(this.QNAME_WSRM__1_1__Sequence_Identifier);
|
|
while (identifierIter.hasNext()) {
|
|
SOAPElement identifierElem = (SOAPElement) identifierIter.next();
|
|
String sequenceIdentifier = identifierElem.getValue();
|
|
mex.setProperty(CRMP_GROUP_ID, sequenceIdentifier);
|
|
sequenceIdentifierFound = true;
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
mLog.log(Level.FINE, "The soap message is ws-rm 1.1 enabled message; populated "
|
|
+ SoapNormalizer.CRMP_GROUP_ID + " with value ["
|
|
+ sequenceIdentifier + "] for message exchange with ID [" + mex.getExchangeId() + "]");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
boolean sequenceMessageNumberFound = false;
|
|
// First try locating the sequence messagenumber from the wsrm 1.0 namespace
|
|
Iterator messageNumberIter = wsrmSequenceElem.getChildElements(QNAME_WSRM__1_0__Sequence_MessageNumber);
|
|
while (messageNumberIter.hasNext()) {
|
|
SOAPElement messageNumberElem = (SOAPElement) messageNumberIter.next();
|
|
String sequenceMessageNumber = messageNumberElem.getValue();
|
|
mex.setProperty(CRMP_MESSAGE_ID, sequenceMessageNumber);
|
|
sequenceMessageNumberFound = true;
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
mLog.log(Level.FINE, "The soap message is ws-rm 1.0 enabled message; populated "
|
|
+ SoapNormalizer.CRMP_MESSAGE_ID + " with value ["
|
|
+ sequenceMessageNumber + "] for message exchange with ID [" + mex.getExchangeId() + "]");
|
|
}
|
|
break;
|
|
}
|
|
|
|
// If sequence messagenumber not found, try the wsrm 1.1 namespace
|
|
if (!sequenceMessageNumberFound) {
|
|
messageNumberIter = wsrmSequenceElem.getChildElements(QNAME_WSRM__1_1__Sequence_MessageNumber);
|
|
while (messageNumberIter.hasNext()) {
|
|
SOAPElement messageNumberElem = (SOAPElement) messageNumberIter.next();
|
|
String sequenceMessageNumber = messageNumberElem.getValue();
|
|
mex.setProperty(CRMP_MESSAGE_ID, sequenceMessageNumber);
|
|
sequenceMessageNumberFound = true;
|
|
if (mLog.isLoggable(Level.FINE)) {
|
|
mLog.log(Level.FINE, "The soap message is ws-rm 1.1 enabled message; populated "
|
|
+ SoapNormalizer.CRMP_MESSAGE_ID + " with value ["
|
|
+ sequenceMessageNumber + "] for message exchange with ID [" + mex.getExchangeId() + "]");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void copyNode(Node src, Node dest) {
|
|
NodeList nl = src.getChildNodes();
|
|
for (int i = 0; i < nl.getLength(); i++) {
|
|
Node n = nl.item(i);
|
|
n = dest.getOwnerDocument().importNode(n, true);
|
|
dest.appendChild(n);
|
|
}
|
|
|
|
NamedNodeMap attrs = src.getAttributes();
|
|
NamedNodeMap destAttrs = dest.getAttributes();
|
|
if (attrs != null) {
|
|
for (int i = 0; i < attrs.getLength(); i++) {
|
|
Node attr = attrs.item(i);
|
|
Node n = dest.getOwnerDocument().importNode(attr, true);
|
|
if (destAttrs != null) {
|
|
destAttrs.setNamedItemNS(n);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Copies HTTP request headers from the context, into the normalized
|
|
// message.
|
|
private void processHTTPRequestHeaders(NormalizedMessage normalMsg, MessageContext context) {
|
|
Map httpHeadersProperty = (Map) normalMsg.getProperty(NormalizedMessageProperties.INBOUND_HTTP_HEADERS_PROPERTY);
|
|
if (httpHeadersProperty == null) {
|
|
httpHeadersProperty = new HashMap<String, String>();
|
|
normalMsg.setProperty(NormalizedMessageProperties.INBOUND_HTTP_HEADERS_PROPERTY, httpHeadersProperty);
|
|
}
|
|
Map requestHeaders = (Map) context.get(MessageContext.HTTP_REQUEST_HEADERS);
|
|
if (requestHeaders != null) {
|
|
for (Iterator iter = requestHeaders.entrySet().iterator(); iter.hasNext();) {
|
|
Map.Entry entry = (Map.Entry) iter.next();
|
|
String key = (String) entry.getKey();
|
|
// JAX-WS Packet implementation populates each header's value
|
|
// as a single value contained in a singleton list.
|
|
String value = (String) ((List) entry.getValue()).get(0);
|
|
httpHeadersProperty.put(key, value);
|
|
}
|
|
}
|
|
|
|
// let's also populate the client host information in this property
|
|
if (context.get(MessageContext.SERVLET_REQUEST) != null) {
|
|
HttpServletRequest servletRequest = (HttpServletRequest) context.get(MessageContext.SERVLET_REQUEST);
|
|
httpHeadersProperty.put(NormalizedMessageProperties.HTTP_HEADER_ClIENT_HOST_NAME, servletRequest.getRemoteAddr());
|
|
httpHeadersProperty.put(NormalizedMessageProperties.HTTP_HEADER_CLIENT_PORT_NUMBER, Integer.valueOf(servletRequest.getRemotePort()).toString());
|
|
}
|
|
|
|
}
|
|
|
|
private void filterStandardNS(Map namespaces) {
|
|
List standardNS = new ArrayList();
|
|
|
|
for (Iterator entries = namespaces.keySet().iterator(); entries.hasNext();) {
|
|
String prefix = (String) entries.next();
|
|
String nsURI = ((String) namespaces.get(prefix)).trim();
|
|
nsURI = nsURI.endsWith("/") ? new StringBuffer(nsURI).deleteCharAt(nsURI.length() - 1).toString() : nsURI;
|
|
if (mStandardNamespaceURIs.containsKey(nsURI)) {
|
|
standardNS.add(prefix);
|
|
}
|
|
}
|
|
|
|
if (standardNS.size() > 0) {
|
|
for (int ii = 0; ii < standardNS.size(); ii++) {
|
|
namespaces.remove(standardNS.get(ii));
|
|
}
|
|
}
|
|
}
|
|
} |