Package org.apache.cocoon.components.axis

Source Code of org.apache.cocoon.components.axis.SoapServerImpl

/*

============================================================================
                   The Apache Software License, Version 1.1
============================================================================

Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.

Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:

1. Redistributions of  source code must  retain the above copyright  notice,
    this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

3. The end-user documentation included with the redistribution, if any, must
    include  the following  acknowledgment:  "This product includes  software
    developed  by the  Apache Software Foundation  (http://www.apache.org/)."
    Alternately, this  acknowledgment may  appear in the software itself,  if
    and wherever such third-party acknowledgments normally appear.

4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
    used to  endorse or promote  products derived from  this software without
    prior written permission. For written permission, please contact
    apache@apache.org.

5. Products  derived from this software may not  be called "Apache", nor may
    "Apache" appear  in their name,  without prior written permission  of the
    Apache Software Foundation.

THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
(INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This software  consists of voluntary contributions made  by many individuals
on  behalf of the Apache Software  Foundation and was  originally created by
Stefano Mazzocchi  <stefano@apache.org>. For more  information on the Apache
Software Foundation, please see <http://www.apache.org/>.

*/
package org.apache.cocoon.components.axis;

import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.axis.AxisEngine;
import org.apache.axis.Constants;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.MessageContext;
import org.apache.axis.configuration.FileProvider;
import org.apache.axis.deployment.wsdd.WSDDDeployment;
import org.apache.axis.deployment.wsdd.WSDDDocument;
import org.apache.axis.deployment.wsdd.WSDDService;
import org.apache.axis.security.servlet.ServletSecurityProvider;
import org.apache.axis.server.AxisServer;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.axis.transport.http.HTTPTransport;
import org.apache.axis.transport.http.ServletEndpointContextImpl;
import org.apache.axis.utils.XMLUtils;
import org.apache.cocoon.components.axis.providers.AvalonProvider;
import org.apache.cocoon.util.IOUtils;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;
import org.apache.excalibur.xml.dom.DOMParser;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

/**
* SOAP Server Implementation
*
* <p>
*  This server accepts a SOAP Request, and generates the resultant
*  response as output. Essentially, this reader allows you to serve SOAP
*  requests from your Cocoon application.
* </p>
*
* <p>
*  Code originates from the Apache
*  <a href="http://xml.apache.org/axis">AXIS</a> project,
<code>org.apache.axis.http.transport.AxisServlet</code>.
* </p>
*
* Ported to Cocoon by:
*
* @author <a href="mailto:crafterm@apache.org">Marcus Crafter</a>
*
* Original <code>AxisServlet</code> authors:
*
* @author <a href="mailto:">Steve Loughran</a>
* @author <a href="mailto:dug@us.ibm.com">Doug Davis</a>
*
* @version CVS $Id: SoapServerImpl.java,v 1.2 2003/03/24 14:33:58 stefano Exp $
*/
public class SoapServerImpl extends AbstractLogEnabled
    implements SoapServer, Composable, Configurable, Contextualizable, Initializable,
               Startable, ThreadSafe
{
    /**
     * Constant describing the default location of the server configuration file
     */
    public static final String DEFAULT_SERVER_CONFIG
        = "resource://org/apache/axis/server/server-config.wsdd";

    // transport name
    private String m_transportName;

    // security provider reference
    private ServletSecurityProvider m_securityProvider;

    // JWS output directory
    private String m_jwsClassDir;

    // per-instance cache of the axis server
    private AxisServer m_axisServer;

    // axis server configuration
    private FileProvider m_engineConfig;

    // location of attachments
    private String m_attachmentDir;

    // server configuration
    private Source m_serverWSDD;

    // array containing locations to descriptors this reader should manage
    private WSDDDocument[] m_descriptors;

    // context reference
    private Context m_context;

    // component manager reference
    private ComponentManager m_manager;

    /**
     * Contextualize this Reader.
     *
     * @param context a <code>Context</code> instance
     * @exception ContextException if an error occurs
     */
    public void contextualize(final Context context)
        throws ContextException
    {
        m_context = context;
    }

    /**
     * Compose this server
     *
     * @param manager a <code>ComponentManager</code> value
     * @exception ComponentException if an error occurs
     */
    public void compose(ComponentManager manager)
        throws ComponentException
    {
        m_manager = manager;
    }

    /**
     * Configures this reader.
     *
     * <p>
     *  Sets the following optional configuration settings:
     *
     *  <ul>
     *   <li>Server WSDD configuration
     *   <li>Attachment directory
     *   <li>JWS directory
     *   <li>Security provider
     *   <li>Transport name
     *   <li>Mananged services
     *  </ul>
     * </p>
     *
     * <p>
     *  The following format is used:
     *  <pre>
     *   &lt;soap-server&gt;
     *    &lt;server-wsdd src="..."/&gt;
     *    &lt;attachment-dir src="..."/&gt;
     *    &lt;jws-dir src="..."/&gt;
     *    &lt;security-provider enabled="..."/&gt;
     *    &lt;transport name="..."/&gt;
     *    &lt;managed-services&gt;
     *     &lt;descriptor src="..."/&gt;
     *     &lt;descriptor src="..."/&gt;
     *    &lt;/managed-services&gt;
     *   &lt;/soap-server&gt;
     *  </pre>
     * </p>
     *
     * @param config a <code>Configuration</code> instance
     * @exception ConfigurationException if an error occurs
     */
    public void configure(final Configuration config)
        throws ConfigurationException
    {
        try {
            setServerConfig(config);
            setAttachmentDir(config);
            setJWSDir(config);
            setSecurityProvider(config);
            setTransportName(config);
            setManagedServices(config);

            if (getLogger().isDebugEnabled()) {
                getLogger().debug("SoapServerImpl.configure() complete");
            }
        } catch (final Exception e) {
            throw new ConfigurationException("Error during configuration", e);
        }
    }

    /**
     * Helper method to set the axis server configuration.
     *
     * @param config a <code>Configuration</code> instance
     * @exception Exception if an error occurs
     */
    public void setServerConfig(final Configuration config)
        throws Exception
    {
        final Configuration wsdd = config.getChild("server-wsdd");
        SourceResolver resolver = null;

        try
        {
            resolver = (SourceResolver) m_manager.lookup(SourceResolver.ROLE);
            m_serverWSDD =
                resolver.resolveURI(
                    wsdd.getAttribute("src", DEFAULT_SERVER_CONFIG)
                );
        }
        finally
        {
            if (resolver != null) m_manager.release(resolver);
        }
    }

    /**
     * Helper method to set the attachment dir. If no attachment directory has
     * been specified, then its set up to operate out of the Cocoon workarea.
     *
     * @param config a <code>Configuration</code> instance
     * @exception ConfigurationException if a configuration error occurs
     * @exception ContextException if a context error occurs
     */
    private void setAttachmentDir(final Configuration config)
        throws ConfigurationException, ContextException
    {
        final Configuration dir = config.getChild("attachment-dir");
        m_attachmentDir = dir.getAttribute("src", null);

        if (m_attachmentDir == null)
        {
            File workDir =
                (File) m_context.get(org.apache.cocoon.Constants.CONTEXT_WORK_DIR);
            File attachmentDir =
                IOUtils.createFile(workDir, "attachments" + File.separator);
            m_attachmentDir = IOUtils.getFullFilename(attachmentDir);
        }

        if (getLogger().isDebugEnabled())
        {
            getLogger().debug("attachment directory = " + m_attachmentDir);
        }
    }

    /**
     * Helper method to set the JWS class dir. If no directory is specified then
     * the directory <i>axis-jws</i> is used, under the Cocoon workarea.
     *
     * @param config a <code>Configuration</code> instance
     * @exception ConfigurationException if a configuration error occurs
     * @exception ContextException if a context error occurs
     */
    private void setJWSDir(final Configuration config)
        throws ConfigurationException, ContextException
    {
        final Configuration dir = config.getChild("jws-dir");
        m_jwsClassDir = dir.getAttribute("src", null);

        if (m_jwsClassDir == null)
        {
            File workDir =
                (File) m_context.get(org.apache.cocoon.Constants.CONTEXT_WORK_DIR);
            File jwsClassDir =
                IOUtils.createFile(workDir, "axis-jws" + File.separator);
            m_jwsClassDir = IOUtils.getFullFilename(jwsClassDir);
        }

        if (getLogger().isDebugEnabled())
        {
            getLogger().debug("jws class directory = " + m_jwsClassDir);
        }
    }

    /**
     * Helper method to set the security provider.
     *
     * @param config a <code>Configuration</code> instance
     * @exception ConfigurationException if an error occurs
     */
    private void setSecurityProvider(final Configuration config)
        throws ConfigurationException
    {
        final Configuration secProvider =
            config.getChild("security-provider", false);

        if (secProvider != null)
        {
            final String attr = secProvider.getAttribute("enabled");
            final boolean providerIsEnabled =
                "true".equalsIgnoreCase(attr) || "yes".equalsIgnoreCase(attr);

            if (providerIsEnabled)
                m_securityProvider = new ServletSecurityProvider();
        }

        if (getLogger().isDebugEnabled())
        {
            getLogger().debug("security provider = " + m_securityProvider);
        }
    }

    /**
     * Helper method to set the transport name
     *
     * @param config a <code>Configuration</code> instance
     * @exception ConfigurationException if an error occurs
     */
    private void setTransportName(final Configuration config)
        throws ConfigurationException
    {
        final Configuration name = config.getChild("transport");
        m_transportName =
            name.getAttribute("name", HTTPTransport.DEFAULT_TRANSPORT_NAME);
    }

    /**
     * Helper method to obtain a list of managed services from the given
     * configuration (ie. locations of deployement descriptors to be
     * deployed).
     *
     * @param config a <code>Configuration</code> value
     * @exception Exception if an error occurs
     */
    private void setManagedServices(final Configuration config)
        throws Exception
    {
        final Configuration m = config.getChild("managed-services", false);
        final List descriptors = new ArrayList();

        if (m != null)
        {
            SourceResolver resolver = null;
            DOMParser parser = null;

            try
            {
                final Configuration[] services = m.getChildren("descriptor");
                resolver = (SourceResolver) m_manager.lookup(SourceResolver.ROLE);
                parser = (DOMParser) m_manager.lookup(DOMParser.ROLE);

                for (int i = 0; i < services.length; ++i)
                {
                    final String location = services[i].getAttribute("src");
                    Source source = resolver.resolveURI(location);

                    final Document d =
                        parser.parseDocument(
                            new InputSource(
                                new InputStreamReader(source.getInputStream())
                            )
                        );

                    descriptors.add(new WSDDDocument(d));
                }
            }
            finally
            {
                if (resolver != null) m_manager.release(resolver);
                if (parser != null) m_manager.release((Component)parser);
            }
        }

        // convert the list of descriptors to an array, for easier iteration
        m_descriptors =
            (WSDDDocument[]) descriptors.toArray(new WSDDDocument[]{});
    }

    /**
     * Initialize this reader, creates AXIS server engine.
     *
     * @exception Exception if an error occurs
     */
    public void initialize()
        throws Exception
    {
        m_axisServer = createEngine();

        if (getLogger().isDebugEnabled())
        {
            getLogger().debug("SoapServerImpl.initialize() complete");
        }
    }

    /**
     * Starts this reader. Deploys all managed services as specified at
     * configuration time.
     *
     * @exception Exception if an error occurs
     */
    public void start()
        throws Exception
    {
        // deploy all configured services
        for (int i = 0; i < m_descriptors.length; ++i)
        {
            WSDDDeployment deployment = m_engineConfig.getDeployment();
            m_descriptors[i].deploy(deployment);

            if (getLogger().isDebugEnabled())
            {
                getLogger().debug(
                    "Deployed Descriptor:\n" +
                    XMLUtils.DocumentToString(m_descriptors[i].getDOMDocument())
                );
            }
        }

        if (getLogger().isDebugEnabled())
        {
            getLogger().debug("SoapServerImpl.start() complete");
        }
    }

    /**
     * Stops this reader. Undeploys all managed services this reader
     * currently manages (includes services dynamically added to the reader
     * during runtime).
     *
     * @exception Exception if an error occurs
     */
    public void stop()
        throws Exception
    {
        WSDDDeployment deployment = m_engineConfig.getDeployment();
        WSDDService[] services = deployment.getServices();

        // undeploy all deployed services
        for (int i = 0; i < services.length; ++i)
        {
            deployment.undeployService(services[i].getQName());

            if (getLogger().isDebugEnabled())
            {
                getLogger().debug("Undeployed: " + services[i].toString());
            }
        }

        if (getLogger().isDebugEnabled())
        {
            getLogger().debug("SoapServerImpl.stop() complete");
        }
    }

    public void invoke(MessageContext message)
        throws Exception
    {
        m_axisServer.invoke(message);
    }

    /**
     * Place the Request message in the MessagContext object - notice
     * that we just leave it as a 'ServletRequest' object and let the
     * Message processing routine convert it - we don't do it since we
     * don't know how it's going to be used - perhaps it might not
     * even need to be parsed.
     */
    public MessageContext createMessageContext(
        HttpServletRequest req,
        HttpServletResponse res,
        ServletContext con
    )
    {
        MessageContext msgContext = new MessageContext(m_axisServer);
        String webInfPath = con.getRealPath("/WEB-INF");
        String homeDir = con.getRealPath("/");

        // Set the Transport
        msgContext.setTransportName(m_transportName);

        // Add Avalon specifics to MessageContext
        msgContext.setProperty(LOGGER, getLogger());
        msgContext.setProperty(AvalonProvider.COMPONENT_MANAGER, m_manager);

        // Save some HTTP specific info in the bag in case someone needs it
        msgContext.setProperty(Constants.MC_JWS_CLASSDIR, m_jwsClassDir);
        msgContext.setProperty(Constants.MC_HOME_DIR, homeDir);
        msgContext.setProperty(Constants.MC_RELATIVE_PATH, req.getServletPath());
        msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLET, this );
        msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST, req );
        msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE, res );
        msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETLOCATION, webInfPath);
        msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETPATHINFO,
                               req.getPathInfo() );
        msgContext.setProperty(HTTPConstants.HEADER_AUTHORIZATION,
                               req.getHeader(HTTPConstants.HEADER_AUTHORIZATION));
        msgContext.setProperty(Constants.MC_REMOTE_ADDR, req.getRemoteAddr());


        // Set up a javax.xml.rpc.server.ServletEndpointContext
        ServletEndpointContextImpl sec = new ServletEndpointContextImpl();
        msgContext.setProperty(Constants.MC_SERVLET_ENDPOINT_CONTEXT, sec);

        // Save the real path
        String realpath = con.getRealPath(req.getServletPath());

        if (realpath != null)
        {
            msgContext.setProperty(Constants.MC_REALPATH, realpath);
        }

        msgContext.setProperty(Constants.MC_CONFIGPATH, webInfPath);

        if (m_securityProvider != null)
            msgContext.setProperty("securityProvider", m_securityProvider);

        // write out the contents of the message context for debugging purposes
        if (getLogger().isDebugEnabled())
        {
            debugMessageContext(msgContext);
        }

        return msgContext;
    }

    /**
     * Helper method to log the contents of a given message context
     *
     * @param context a <code>MessageContext</code> instance
     */
    private void debugMessageContext(final MessageContext context)
    {
        for (final Iterator i = context.getPropertyNames();
             i.hasNext();
        )
        {
            final String key = (String) i.next();
            getLogger().debug(
                "MessageContext: Key:" + key + ": Value: " + context.getProperty(key)
            );
        }
    }


    /**
     * This is a uniform method of initializing AxisServer in a servlet
     * context.
     */
    public AxisServer createEngine()
        throws Exception
    {
        AxisServer engine = AxisServer.getServer(getEngineEnvironment());

        if (getLogger().isDebugEnabled())
        {
            getLogger().debug("Axis engine created");
        }

        return engine;
    }

    protected Map getEngineEnvironment()
        throws Exception
    {
        Map env = new HashMap();

        // use FileProvider directly with a Avalon Source object instead of going
        // through the EngineConfigurationFactoryServlet class
        m_engineConfig = new FileProvider(m_serverWSDD.getInputStream());

        env.put(EngineConfiguration.PROPERTY_NAME, m_engineConfig);
        env.put(AxisEngine.ENV_ATTACHMENT_DIR, m_attachmentDir);
        // REVISIT(MC): JNDI Factory support ?
        //env.put(AxisEngine.ENV_SERVLET_CONTEXT, context);

        return env;
    }

    /*
     * Helper method to convert a <code>Message</code> structure
     * into a <code>String</code>.
     *
     * @param msg a <code>Message</code> value
     * @return a <code>String</code> value
     */
    /* FIXME (SM): this method appears to be unused, should we remove it?
    private String messageToString(final Message msg)
    {
        try
        {
            OutputStream os = new ByteArrayOutputStream();
            msg.writeTo(os);
            return os.toString();
        }
        catch (Exception e)
        {
            if (getLogger().isWarnEnabled())
            {
                getLogger().warn(
                    "Warning, could not convert message (" + msg + ") into string", e
                );
            }

            return null;
        }
    } */
TOP

Related Classes of org.apache.cocoon.components.axis.SoapServerImpl

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.