All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.plexus.servlet.ServletContextUtils Maven / Gradle / Ivy

The newest version!
package org.codehaus.plexus.servlet;

/**
 * The MIT License
 *
 * Copyright (c) 2004, The Codehaus
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;

import javax.servlet.ServletContext;

import org.codehaus.plexus.*;
import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.util.PropertyUtils;

/**
 * ServletContextUtils provides methods to embed a Plexus container within a Servlet context.
 *
 * @author Mark Wilkinson
 * @version $Id: ServletContextUtils.java 6730 2007-08-05 22:24:02Z handyande $
 */
public final class ServletContextUtils
{
    private ServletContext context;

    private PlexusContainer container;

    private boolean removeFromContext;

    private List components = new ArrayList();

    /**
     * Create a Plexus container using the {@link org.codehaus.plexus.DefaultPlexusContainer}. This method should be
     * called from an environment where a ServletContext is available. It will create and initialize the
     * Plexus container and place references to the container into the context.
     *
     * @param context The servlet context to place the container in.
     * @return a Plexus container that has been initialized and started.
     * @throws PlexusContainerException If the Plexus container could not be started.
     */
    public void start( ServletContext context )
        throws PlexusContainerException
    {
        this.context = context;

        Object o = context.getAttribute( PlexusConstants.PLEXUS_KEY );

        Map containerContext = initializeContext( context, resolveContextProperties( context ) );

        if ( o == null )
        {
            context.log( "Initializing Plexus." );

            ContainerConfiguration cc = new DefaultContainerConfiguration();
            cc.setName( null );
            cc.setContext( containerContext );
            cc.setContainerConfigurationURL( resolveConfig( context ) );

            container = new DefaultPlexusContainer( cc );

            context.setAttribute( PlexusConstants.PLEXUS_KEY, container );

            removeFromContext = true;
        }
        else
        {
            if ( !( o instanceof PlexusContainer ) )
            {
                throw new PlexusContainerException( "An attribute with key '" + PlexusConstants.PLEXUS_KEY
                    + "' was in the context but it was not an instance of " + PlexusContainer.class.getName() + "." );
            }

            context.log( "Plexus container already in context, creating child container" );

            // make a child container. The child container load the WEB-INF/classes/META-INF/application.xml the WAR.
            // TODO merge with existing context values and existing properties ?

            MutablePlexusContainer parentContainer = (MutablePlexusContainer) o;

            // Don't specify any classworld, either with the thread context loader or the parent
            // container realm, or even the parent classworld, since then the
            // components in WEB-INF/lib won't be discovered.

            ContainerConfiguration cc = new DefaultContainerConfiguration();
            cc.setName( parentContainer.getName() + "-war" );
            cc.setContext( containerContext );
            cc.setContainerConfigurationURL( resolveConfig( context ) );
            cc.setParentContainer( parentContainer );

            container = new DefaultPlexusContainer( cc );

            context.setAttribute( PlexusConstants.PLEXUS_KEY, container );
        }

        lookupAddToContextComponents( context );

        context.log( "Plexus initialized." );
    }

    public void stop()
    {
        context.log( "Stopping Plexus." );

        if ( removeFromContext )
        {
            context.removeAttribute( PlexusConstants.PLEXUS_KEY );
        }

        releaseAddToContextComponents();

        container.dispose();

        context.log( "Plexus stopped." );
    }

    // -----------------------------------------------------------------------
    // Private
    // -----------------------------------------------------------------------

    private Map initializeContext( ServletContext ctx, Properties properties )
    {
        Map map = new HashMap();

        // When run inside a Maven plugin (eg, the Jetty plugin), this will pick up the Maven core class
        // configuration instead of the webapp. While ideally Maven would isolate the plugin classes from itself,
        // this prevents Plexus from attempting to load a container configuration file as a workaround.
        map.put( PlexusConstants.IGNORE_CONTAINER_CONFIGURATION, Boolean.TRUE );

        // used by the servlet configuration phase
        map.put( ServletContext.class.getName(), ctx );

        map.putAll( properties );

        return map;
    }

    private Properties resolveContextProperties( ServletContext context )
    {
        Properties properties = new Properties();

        String filename = context.getInitParameter( PlexusServletUtils.PLEXUS_PROPERTIES_PARAM );

        if ( filename == null )
        {
            filename = PlexusServletUtils.DEFAULT_PLEXUS_PROPERTIES;
        }

        context.log( "Loading plexus context properties from: '" + filename + "'" );

        try
        {
            URL url = context.getResource( filename );
            // bwalding: I think we'd be better off not using this exception swallower!
            properties = PropertyUtils.loadProperties( url );
        }
        catch ( Exception e )
        {
            // michal: I don't think it is that good idea to ignore this error.
            // bwalding: it's actually pretty difficult to get here as the PropertyUtils.loadProperties absorbs all
            // Exceptions
            context.log( "Could not load plexus context properties from: '" + filename + "'" );
        }

        if ( properties == null )
        {
            context.log( "Could not load plexus context properties from: '" + filename + "'" );
            properties = new Properties();
        }

        if ( !properties.containsKey( PlexusServletUtils.PLEXUS_HOME ) )
        {
            setPlexusHome( context, properties );
        }

        return properties;
    }

    private URL resolveConfig( ServletContext context )
        throws PlexusContainerException
    {
        String plexusConf = context.getInitParameter( PlexusServletUtils.PLEXUS_CONFIG_PARAM );

        if ( plexusConf == null )
        {
            plexusConf = PlexusServletUtils.DEFAULT_PLEXUS_CONFIG;
        }

        try
        {
            URL resource = context.getResource( plexusConf );

            if ( resource == null )
            {
                resource = Thread.currentThread().getContextClassLoader().getResource(
                    "META-INF/plexus/application.xml" );
            }

            context.log( "resource = " + resource );

            return resource;
        }
        catch ( MalformedURLException e )
        {
            throw new PlexusContainerException( "Error while getting URL to '" + plexusConf + "'", e );
        }
        catch ( IOException e )
        {
            throw new PlexusContainerException( "Error while getting URL to '" + plexusConf + "'", e );
        }
    }

    /**
     * Set plexus.home context variable
     */
    private void setPlexusHome( ServletContext context, Properties contexProperties )
    {
        String realPath = context.getRealPath( "/WEB-INF" );

        if ( realPath != null )
        {
            File f = new File( realPath );

            contexProperties.setProperty( PlexusServletUtils.PLEXUS_HOME, f.getAbsolutePath() );
        }
        else
        {
            context.log( "Not setting 'plexus.home' as plexus is running inside webapp with no 'real path'." );
        }
    }

    private void lookupAddToContextComponents( ServletContext context )
        throws PlexusContainerException
    {
        String string = context.getInitParameter( PlexusServletUtils.PLEXUS_CONFIG_ADD_TO_CONTEXT );

        if ( string == null || string.length() == 0 )
        {
            return;
        }

        StringTokenizer tokenizer = new StringTokenizer( string, "," );

        while ( tokenizer.hasMoreTokens() )
        {
            String token = tokenizer.nextToken();

            int index = token.indexOf( ":" );

            Object component;

            if ( index > 0 )
            {
                String role = token.substring( 0, index );
                String roleHint = role.substring( index );

                try
                {
                    component = container.lookup( role, roleHint );
                }
                catch ( ComponentLookupException e )
                {
                    throw new PlexusContainerException( "Error while looking up component '" + role + ":" + roleHint
                        + "'", e );
                }
            }
            else
            {
                try
                {
                    component = container.lookup( token );
                }
                catch ( ComponentLookupException e )
                {
                    throw new PlexusContainerException( "Error while looking up component '" + token + "'", e );
                }
            }

            context.setAttribute( token, component );
            components.add( component );
        }
    }

    private void releaseAddToContextComponents()
    {
        for ( Iterator it = components.iterator(); it.hasNext(); )
        {
            Object component = it.next();

            try
            {
                container.release( component );
            }
            catch ( ComponentLifecycleException e )
            {
                context.log( "Error while releasing " + component, e );
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy