Package org.jboss.internal.soa.esb.webservice

Source Code of org.jboss.internal.soa.esb.webservice.BaseWebService

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.internal.soa.esb.webservice;

import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.Detail;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPMessage;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.Provider;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.addressing.AttributedURI;
import javax.xml.ws.addressing.Relationship;

import org.apache.log4j.Logger;
import org.jboss.internal.soa.esb.util.XMLHelper;
import org.jboss.internal.soa.esb.webservice.addressing.AddressingConstants;
import org.jboss.internal.soa.esb.webservice.addressing.MAP;
import org.jboss.internal.soa.esb.webservice.addressing.MAPBuilder;
import org.jboss.internal.soa.esb.webservice.addressing.MAPBuilderFactory;
import org.jboss.internal.soa.esb.webservice.addressing.MAPRelatesTo;
import org.jboss.soa.esb.client.ServiceInvoker;
import org.jboss.soa.esb.common.Environment;
import org.jboss.soa.esb.common.ModulePropertyManager;
import org.jboss.soa.esb.couriers.FaultMessageException;
import org.jboss.soa.esb.lifecycle.LifecycleResourceManager;
import org.jboss.soa.esb.listeners.message.MessageDeliverException;
import org.jboss.soa.esb.message.Body;
import org.jboss.soa.esb.message.Fault;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.MessagePayloadProxy;
import org.jboss.soa.esb.message.Properties;
import org.jboss.soa.esb.message.format.MessageFactory;
import org.jboss.soa.esb.services.security.SecurityServiceException;
import org.jboss.soa.esb.services.security.auth.AuthenticationRequest;
import org.jboss.soa.esb.services.security.auth.ExtractionException;
import org.jboss.soa.esb.services.security.auth.ExtractorUtil;
import org.jboss.soa.esb.services.security.auth.SecurityInfoExtractor;
import org.jboss.soa.esb.services.security.auth.ws.SamlSoapAssertionExtractor;
import org.jboss.soa.esb.services.security.auth.ws.WSSecuritySoapExtractor;
import org.w3c.dom.Document;

import com.arjuna.common.util.propertyservice.PropertyManager;


/**
* This is the abstract base class for a SOAP messages
* @author kevin
* @author <a href="mailto:mageshbk@jboss.com">Magesh Kumar B</a>
*/
public abstract class BaseWebService implements Provider<SOAPMessage>
{
    private static final QName SERVER_FAULT_QN = new QName("http://schemas.xmlsoap.org/soap/envelope/", "Server") ;

    private static final boolean RETURN_STACK_TRACES ;
    private static final Logger LOGGER = Logger.getLogger(BaseWebService.class);
    private static final javax.xml.soap.MessageFactory SOAP_MESSAGE_FACTORY ;

    private static final MAPBuilder ADDRESSING_BUILDER = MAPBuilderFactory.getInstance().getBuilderInstance() ;
    private static final String ADDRESSING_NAMESPACE = AddressingConstants.Core.NS ;
    private static final QName ADDRESSING_REPLY = new QName(ADDRESSING_NAMESPACE, "Reply") ;
   
    private static final Set<SecurityInfoExtractor<SOAPMessage>> extractors = new LinkedHashSet<SecurityInfoExtractor<SOAPMessage>>();
    static
    {
        extractors.add(new WSSecuritySoapExtractor());
        extractors.add(new SamlSoapAssertionExtractor());
    }
   
    private final String deployment ;
    protected final ServiceInvoker serviceInvoker ;
    protected final MessagePayloadProxy requestProxy ;
    protected final MessagePayloadProxy responseProxy ;
    protected final String action ;

    protected BaseWebService(final String deployment, final ServiceInvoker serviceInvoker, final String requestLocation, final String responseLocation, final String action)
        throws MessageDeliverException
    {
        this.deployment = deployment ;
        this.serviceInvoker = serviceInvoker ;
        requestProxy = new MessagePayloadProxy(null, requestLocation) ;
        responseProxy = new MessagePayloadProxy(responseLocation, null) ;
        this.action = action ;
    }

    public SOAPMessage invoke(final SOAPMessage request)
    {
        if (SOAP_MESSAGE_FACTORY == null)
        {
            throw new WebServiceException("Failed to instantiate SOAP Message Factory") ;
        }
       
        final MAP soapIncomingProps = AddressingContext.getAddressingProperties() ;
       
        final Message esbReq = MessageFactory.getInstance().getMessage() ;
        final ClassLoader origClassLoader = Thread.currentThread().getContextClassLoader() ;
        final ClassLoader deploymentClassLoader = LifecycleResourceManager.getSingleton().getClassLoaderForDeployment(deployment) ;
        if (deploymentClassLoader != null)
        {
            Thread.currentThread().setContextClassLoader(deploymentClassLoader) ;
        }
        try
        {
            final SOAPBody soapBody = request.getSOAPBody() ;
            if (soapBody == null)
            {
                throw new WebServiceException("Missing SOAP body from request") ;
            }
            // There is a bug in JBossWS extractContentAsDocument so we do this ourselves
            final Iterator children = soapBody.getChildElements() ;
            boolean found = false ;
            while(children.hasNext())
            {
                final Node node = (Node)children.next() ;
                if (node instanceof SOAPElement)
                {
                    if (found)
                    {
                        throw new SOAPException("Found multiple SOAPElements in SOAPBody") ;
                    }
                    final StringWriter sw = new StringWriter() ;
                    final XMLEventWriter writer = XMLHelper.getXMLEventWriter(new StreamResult(sw)) ;
                    XMLHelper.readDomNode(node, writer, true) ;
                    requestProxy.setPayload(esbReq, sw.toString()) ;
                    found = true ;
                }
            }

            if (!found)
            {
                throw new SOAPException("Could not find SOAPElement in SOAPBody") ;
            }

            if (soapIncomingProps != null)
            {
                initialiseWSAProps(esbReq, soapIncomingProps) ;
            }
           
            // Extract security info from SOAPMessage.
            AuthenticationRequest authRequest = extractSecurityDetails(request, esbReq);
          ExtractorUtil.addAuthRequestToMessage(authRequest, esbReq);

            // We should be able to return null here but this causes JBossWS to NPE.
            final Message esbRes = deliverMessage(esbReq) ;
           
            final SOAPMessage response = SOAP_MESSAGE_FACTORY.createMessage();
            if (esbRes != null)
            {
                final Object input = responseProxy.getPayload(esbRes) ;
                if (input == null)
                {
                    throw new SOAPException("Null response from service") ;
                }
                final String soapRes = input.toString();

                final Document root = parseAsDom(soapRes) ;
               
                response.getSOAPBody().addDocument(root) ;
            }
            if (soapIncomingProps == null)
            {
                AddressingContext.setAddressingProperties(null) ;
            }
            else
            {
                final MAP soapOutgoingProps = ADDRESSING_BUILDER.newMap() ;
                if (action != null)
                {
                    soapOutgoingProps.setAction(action) ;
                }
                AddressingContext.setAddressingProperties(soapOutgoingProps) ;
            }
           
            return response ;
        }
        catch (final WebServiceException wse)
        {
            throw wse ;
        }
        catch (final Exception ex)
        {
            try
            {
                SOAPMessage faultMsg = null;
                if (ex instanceof FaultMessageException)
                {
                    final FaultMessageException fme = (FaultMessageException) ex ;
                    final Message faultMessage = fme.getReturnedMessage() ;
                    if (faultMessage != null)
                    {
                        final Body body = faultMessage.getBody() ;
                        final QName faultCode = (QName)body.get(Fault.DETAIL_CODE_CONTENT) ;
                        final String faultDescription = (String)body.get(Fault.DETAIL_DESCRIPTION_CONTENT) ;
                        final String faultDetail = (String)body.get(Fault.DETAIL_DETAIL_CONTENT) ;

                        if (faultCode != null)
                        {
                            faultMsg = SOAP_MESSAGE_FACTORY.createMessage() ;
                            final SOAPFault fault = faultMsg.getSOAPBody().addFault(faultCode, faultDescription) ;
                            if (faultDetail != null)
                            {
                                try
                                {
                                    final Document detailDoc = parseAsDom(faultDetail) ;
                                    final Detail detail = fault.addDetail() ;
                                    detail.appendChild(detailDoc.getDocumentElement()) ;
                                }
                                catch (final Exception ex2)
                                {
                                    LOGGER.warn("Failed to parse fault detail", ex2) ;
                                }
                            }
                        }
                        else
                        {
                            final Throwable cause = fme.getCause() ;
                            faultMsg = (cause != null) ? generateFault(cause) : generateFault(ex) ;
                        }
                    }
                }

                if (faultMsg == null)
                {
                    faultMsg = generateFault(ex) ;
                }
                return faultMsg ;
            }
            catch (final SOAPException soape)
            {
                throw new WebServiceException("Unexpected exception generating fault response", soape) ;
            }
        }
        finally
        {
            Thread.currentThread().setContextClassLoader(origClassLoader) ;
        }
    }

    private static Document parseAsDom(String soapRes) throws ParserConfigurationException, XMLStreamException
    {
        final XMLEventReader reader = XMLHelper.getXMLEventReader(new ByteArrayInputStream(soapRes.getBytes())) ;
        return XMLHelper.createDocument(reader) ;
    }

    protected AuthenticationRequest extractSecurityDetails(SOAPMessage request, Message esbReq) throws SecurityServiceException
    {
        try
        {
            return ExtractorUtil.extract(request, extractors);
        }
        catch (final ExtractionException e)
        {
            throw new SecurityServiceException(e.getMessage(), e);
        }
    }

    private SOAPMessage generateFault(final Throwable th)
        throws SOAPException
    {
        final SOAPMessage faultMsg = SOAP_MESSAGE_FACTORY.createMessage() ;
        if (RETURN_STACK_TRACES)
        {
            final StringWriter sw = new StringWriter() ;
            final PrintWriter pw = new PrintWriter(sw) ;
            th.printStackTrace(pw) ;
            pw.flush() ;
            pw.close() ;
            faultMsg.getSOAPBody().addFault(SERVER_FAULT_QN, sw.toString());
        }
        else
        {
            faultMsg.getSOAPBody().addFault(SERVER_FAULT_QN, th.getMessage());
        }
        return faultMsg ;
    }

    private void initialiseWSAProps(final Message esbReq, final MAP props)
    {
        final String messageID = props.getMessageID() ;
        final Properties esbReqProps = esbReq.getProperties() ;
       
        if (messageID != null)
        {
            esbReqProps.setProperty(Environment.WSA_MESSAGE_ID, messageID) ;
        }
        final MAPRelatesTo relationship = props.getRelatesTo() ;

        if (relationship != null)
        {
            final String[] relatesTo = new String[1] ;
            final String[] relationshipType = new String[1] ;
            relatesTo[0] = relationship.getRelatesTo() ;
            final QName type = relationship.getType() ;
            if (type != null)
            {
                relationshipType[0] = type.toString() ;
            }
            else
            {
                relationshipType[0] = ADDRESSING_REPLY.toString() ;
            }
            esbReqProps.setProperty(Environment.WSA_RELATES_TO, relatesTo) ;
            esbReqProps.setProperty(Environment.WSA_RELATIONSHIP_TYPE, relationshipType) ;
        }
    }

    protected abstract Message deliverMessage(final Message request)
        throws Exception ;

    static
    {
        final PropertyManager propertyManager = ModulePropertyManager.getPropertyManager(ModulePropertyManager.TRANSPORTS_MODULE) ;
        final String returnStackTraces = propertyManager.getProperty(Environment.WS_RETURN_STACK_TRACE);
        RETURN_STACK_TRACES = Boolean.parseBoolean(returnStackTraces) ;
       
        javax.xml.soap.MessageFactory soapMessageFactory = null ;
        try
        {
            soapMessageFactory = javax.xml.soap.MessageFactory.newInstance() ;
        }
        catch (final SOAPException soape)
        {
            LOGGER.error("Could not instantiate SOAP Message Factory", soape) ;
        }
        SOAP_MESSAGE_FACTORY = soapMessageFactory ;
    }
}
TOP

Related Classes of org.jboss.internal.soa.esb.webservice.BaseWebService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.