blob: 5082f1474934b80472ff83f0dfc576e15dc9066c [file] [log] [blame]
/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rampart.util;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.impl.dom.DOOMAbstractFactory;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder;
import org.apache.axiom.soap.impl.dom.SOAPHeaderBlockImpl;
import org.apache.axiom.soap.impl.dom.factory.DOMSOAPFactory;
import org.apache.rampart.handler.WSSHandlerConstants;
import org.apache.ws.security.WSSecurityException;
import org.apache.xml.security.utils.XMLUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
/**
* Utility class for the Axis2-WSS4J Module
*/
public class Axis2Util {
private static ThreadLocal doomTacker = new ThreadLocal();
public static boolean isUseDOOM() {
Object value = doomTacker.get();
return (value != null);
}
public static void useDOOM(boolean isDOOMRequired) {
//TODO Enable this when we have DOOM fixed to be able to flow in and out of Axis2
// if(isDOOMRequired) {
// if(!isUseDOOM()) {
// System.setProperty(OMAbstractFactory.SOAP11_FACTORY_NAME_PROPERTY, SOAP11Factory.class.getName());
// System.setProperty(OMAbstractFactory.SOAP12_FACTORY_NAME_PROPERTY, SOAP12Factory.class.getName());
// System.setProperty(OMAbstractFactory.OM_FACTORY_NAME_PROPERTY, OMDOMFactory.class.getName());
// doomTacker.set(new Object());
// }
// } else {
// System.getProperties().remove(OMAbstractFactory.SOAP11_FACTORY_NAME_PROPERTY);
// System.getProperties().remove(OMAbstractFactory.SOAP12_FACTORY_NAME_PROPERTY);
// System.getProperties().remove(OMAbstractFactory.OM_FACTORY_NAME_PROPERTY);
// doomTacker.set(null);
// }
}
/**
* Creates a DOM Document using the SOAP Envelope.
* @param env An org.apache.axiom.soap.SOAPEnvelope instance
* @return Returns the DOM Document of the given SOAP Envelope.
* @throws Exception
*/
public static Document getDocumentFromSOAPEnvelope(SOAPEnvelope env, boolean useDoom)
throws WSSecurityException {
try {
if(env instanceof Element) {
return ((Element)env).getOwnerDocument();
}
if (useDoom) {
env.build();
// Workaround to prevent a bug in AXIOM where
// there can be an incomplete OMElement as the first child body
OMElement firstElement = env.getBody().getFirstElement();
if (firstElement != null) {
firstElement.build();
}
//Get processed headers
SOAPHeader soapHeader = env.getHeader();
ArrayList processedHeaderQNames = new ArrayList();
if(soapHeader != null) {
Iterator headerBlocs = soapHeader.getChildElements();
while (headerBlocs.hasNext()) {
SOAPHeaderBlock element = (SOAPHeaderBlock) headerBlocs.next();
if(element.isProcessed()) {
processedHeaderQNames.add(element.getQName());
}
}
}
// Check the namespace and find SOAP version and factory
String nsURI = null;
SOAPFactory factory;
if (env.getNamespace().getNamespaceURI().equals(
SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI)) {
nsURI = SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI;
factory = DOOMAbstractFactory.getSOAP11Factory();
} else {
nsURI = SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI;
factory = DOOMAbstractFactory.getSOAP12Factory();
}
StAXSOAPModelBuilder stAXSOAPModelBuilder = new StAXSOAPModelBuilder(
env.getXMLStreamReader(), factory, nsURI);
SOAPEnvelope envelope = (stAXSOAPModelBuilder)
.getSOAPEnvelope();
((OMNode) envelope.getParent()).build();
//Set the processed flag of the processed headers
SOAPHeader header = envelope.getHeader();
for (Iterator iter = processedHeaderQNames.iterator(); iter
.hasNext();) {
QName name = (QName) iter.next();
Iterator omKids = header.getChildrenWithName(name);
if(omKids.hasNext()) {
((SOAPHeaderBlock)omKids.next()).setProcessed();
}
}
Element envElem = (Element) envelope;
return envElem.getOwnerDocument();
} else {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
env.build();
env.serialize(baos);
ByteArrayInputStream bais = new ByteArrayInputStream(baos
.toByteArray());
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setNamespaceAware(true);
return factory.newDocumentBuilder().parse(bais);
}
} catch (Exception e) {
throw new WSSecurityException(
"Error in converting SOAP Envelope to Document", e);
}
}
public static SOAPEnvelope getSOAPEnvelopeFromDOMDocument(Document doc, boolean useDoom)
throws WSSecurityException {
if(useDoom) {
try {
//Get processed headers
SOAPEnvelope env = (SOAPEnvelope)doc.getDocumentElement();
ArrayList processedHeaderQNames = new ArrayList();
SOAPHeader soapHeader = env.getHeader();
if(soapHeader != null) {
Iterator headerBlocs = soapHeader.getChildElements();
while (headerBlocs.hasNext()) {
OMElement element = (OMElement)headerBlocs.next();
SOAPHeaderBlock header = null;
if (element instanceof SOAPHeaderBlock) {
header = (SOAPHeaderBlock) element;
// If a header block is not an instance of SOAPHeaderBlock, it means that
// it is a header we have added in rampart eg. EncryptedHeader and should
// be converted to SOAPHeaderBlock for processing
} else {
header = soapHeader.addHeaderBlock(element.getLocalName(), element.getNamespace());
Iterator attrIter = element.getAllAttributes();
while (attrIter.hasNext()) {
OMAttribute attr = (OMAttribute)attrIter.next();
header.addAttribute(attr.getLocalName(), attr.getAttributeValue(), attr.getNamespace());
}
Iterator nsIter = element.getAllDeclaredNamespaces();
while (nsIter.hasNext()) {
OMNamespace ns = (OMNamespace) nsIter.next();
header.declareNamespace(ns);
}
Iterator children = element.getChildElements();
while (children.hasNext()) {
OMNode child = (OMNode)children.next();
child.detach();
header.addChild(child);
}
element.detach();
soapHeader.build();
header.setProcessed();
}
if(header.isProcessed()) {
processedHeaderQNames.add(element.getQName());
}
}
}
XMLStreamReader reader = ((OMElement) doc.getDocumentElement())
.getXMLStreamReader();
StAXSOAPModelBuilder stAXSOAPModelBuilder = new StAXSOAPModelBuilder(
reader, null);
SOAPEnvelope envelope = stAXSOAPModelBuilder.getSOAPEnvelope();
//Set the processed flag of the processed headers
SOAPHeader header = envelope.getHeader();
for (Iterator iter = processedHeaderQNames.iterator(); iter
.hasNext();) {
QName name = (QName) iter.next();
Iterator omKids = header.getChildrenWithName(name);
if(omKids.hasNext()) {
((SOAPHeaderBlock)omKids.next()).setProcessed();
}
}
envelope.build();
return envelope;
} catch (FactoryConfigurationError e) {
throw new WSSecurityException(e.getMessage());
}
} else {
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
XMLUtils.outputDOM(doc.getDocumentElement(), os, true);
ByteArrayInputStream bais = new ByteArrayInputStream(os.toByteArray());
StAXSOAPModelBuilder stAXSOAPModelBuilder = new StAXSOAPModelBuilder(XMLInputFactory.newInstance().createXMLStreamReader(bais), null);
return stAXSOAPModelBuilder.getSOAPEnvelope();
} catch (Exception e) {
throw new WSSecurityException(e.getMessage());
}
}
}
/**
* Provides the appropriate key to pickup config params from the message context.
* This is acutally used when the outflow handler (WSDoAllSender)
* is repeated n number of times.
* @param originalKey The default key
* @param inHandler Whether the handler is the inflow handler or not
* @param repetition The current repetition number
* @return Returns the key to be used internally in the security module to pick
* up the config params.
*/
public static String getKey(String originalKey, boolean inHandler, int repetition) {
if(repetition > 0 && !inHandler &&
!originalKey.equals(WSSHandlerConstants.OUTFLOW_SECURITY)&&
!originalKey.equals(WSSHandlerConstants.SENDER_REPEAT_COUNT)) {
return originalKey + repetition;
}
return originalKey;
}
/**
* This will build a DOOM Element that is of the same <code>Document</code>
* @param factory
* @param element
* @return
*/
public static OMElement toDOOM(OMFactory factory, OMElement element){
StAXOMBuilder builder = new StAXOMBuilder(factory, element.getXMLStreamReader());
OMElement elem = builder.getDocumentElement();
elem.build();
return elem;
}
}