Package org.apache.pluto.portalImpl.services

Source Code of org.apache.pluto.portalImpl.services.ServiceManager

/*
* Copyright 2003,2004 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.pluto.portalImpl.services;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;

import org.apache.pluto.portalImpl.util.Properties;
import org.apache.pluto.util.StringUtils;

/**
* Manages the life-time of services registered during servlet startup.
* There are two types of services: Services required by the container,
* and Services used for the portal driver configuration and execution.
* All services required by the container have to derive from
* {@link org.apache.pluto.services.ContainerService} and implement the
* <CODE>init()</CODE> and <CODE>destroy()</CODE> methods as appropriate.
* All services must derive from the
* {@link org.apache.pluto.portalImpl.services.Service} interface if they
* are to be used with the portal driver.
* <P>
* By registering the service and its implementation in the file
* <CODE>/config/services.properties</CODE>, the service will become
* available to the portal engine. The format of the file is simple:
*
* <PRE>
*   org.apache.pluto.portalImpl.services.log.Logger = org.apache.pluto.portalImpl.services.log.LogServicesImpl
* </PRE>
*
* Each entry represents one service. The left-hand side is the abstract
* service class, the right-hand side is the implementation of this service.
* The services are initialized in the order of appearance.
*
* <P>
* Each service can have its own configuration file, located in
* <CODE>/config/services</CODE>. It has to have the name of either
* implementation or abstract class of the service, without the
* leading package name. For example, the service manager looks
* for <CODE>LoggerImpl
.properties</CODE>. This allows a special
* implementation to provide different configuration than the
* general (abstract) service requires.
*
* <P>
* If present, one of the services configuration files is loaded
* and passed to the service as {@link org.apache.pluto.portalImpl.util.Properties}
* object. Not providing a service configuration file is okay too,
* in that case the properties are emptyemptySessionPath .
*
* @see org.apache.pluto.services.ContainerService
*/
public class ServiceManager
{

    private final static String SERVICES_CONFIG_FILE = "/WEB-INF/config/services.properties";
    private final static String SERVICES_CONFIG_DIR  = "/WEB-INF/config/services/";

    /**
     ** Initializes all services specified in <CODE>services.properties</CODE>.
     ** By specifying a different implementation of the service the behaviour
     ** of the portal can be modified.
     **
     ** @param   aConfig
     **          the servlet configuration
     **
     ** @exception    Exception
     **               if loading <CODE>services.properties</CODE>
     **               or initializing any of its contained services fails
     **/

    public static void init (ServletConfig aConfig) throws Exception
    {
        init (aConfig, SERVICES_CONFIG_FILE, SERVICES_CONFIG_DIR);
    }

    /**
     ** Initializes all services specified in <CODE>services.properties</CODE>.
     ** By specifying a different implementation of the service the behaviour
     ** of the portal can be modified.
     **
     ** @param   aConfig
     **          the servlet configuration
     ** @param   aServiceConfigFile
     **          The location of <CODE>services.properties</CODE> (relative to classpath)
     ** @param   aServiceConfigDir
     **          The direcory with the services' properties files (relative to classpath)
     **
     ** @exception    Exception
     **               if loading <CODE>services.properties</CODE>
     **               or initializing any of its contained services fails
     **/

    public static void init (ServletConfig aConfig,
                             String aServiceConfigFile,
                             String aServiceConfigDir) throws Exception
    {
        // avoid duplicate initialization of services

        if (! cInitialized)
        {
            synchronized (ServiceManager.class)
            {
                if (! cInitialized)
                {
                    cInitialized = true;
                }
                else
                {
                    return;
                }
            }
        }
        else
        {
            return;
        }

        ServletContext context = null;

        if (aConfig != null)
            context = aConfig.getServletContext ();

        if (context != null)
            context.log ("ServiceManager: Loading services...");

        Properties props = new Properties ();

        try
        {
            props.load (context.getResourceAsStream (aServiceConfigFile));
        }
        catch (IOException exc)
        {
            if (context != null)
                context.log ("ServiceManager: File \"" + aServiceConfigFile + "\" cannot be found or read.");
            throw new Exception("ServiceManager: File \"" + aServiceConfigFile + "\" cannot be found or read.");
        }

        int numAll = 0;
        int numSuccessful = 0;

        for (Iterator iter = props.names (); iter.hasNext (); )
        {
            String serviceBaseName = (String) iter.next ();

            numAll++;

            // ty to get hold of the base service

            Class serviceBase;

            try
            {
                serviceBase = Class.forName (serviceBaseName);
            }
            catch (ClassNotFoundException exc)
            {
                if (context != null)
                    context.log ("ServiceManager: A service with name " + serviceBaseName + " cannot be found.");

                continue;
            }

            String serviceImplName = props.getString (serviceBaseName);

            Class serviceImpl = null;

            Service service = null;

            try
            {
                serviceImpl = Class.forName (serviceImplName);

                service = (Service) serviceImpl.newInstance ();

                Properties serviceProps = new Properties ();

                try
                {
                    InputStream is = null;

                    is = context.getResourceAsStream (aServiceConfigDir + StringUtils.nameOf (serviceImpl) + ".properties");

                    if (is == null)
                        is = context.getResourceAsStream (aServiceConfigDir + StringUtils.nameOf (serviceBase) + ".properties");

                    if (is != null)
                        serviceProps.load (is);
                }
                catch (IOException exc)
                {
                    // ignore -- we go without properties then
                }

                if (context != null)
                    context.log (StringUtils.nameOf (serviceBase) + " initializing...");

                service.init (aConfig, serviceProps);

                if (context != null)
                    context.log (StringUtils.nameOf (serviceBase) + " done.");
            }
            catch (ClassNotFoundException exc)
            {
                if (context != null)
                    context.log ("ServiceManager: A service implementation with name " + serviceImplName + " cannot be found.", exc);

                continue;
            }
            catch (ClassCastException exc)
            {
                if (context != null)
                    context.log ("ServiceManager: Service implementation " + serviceImplName + " is not a service of the required type.", exc);

                continue;
            }
            catch (InstantiationException exc)
            {
                if (context != null)
                    context.log ("ServiceManager: Service implementation " + serviceImplName + " cannot be instantiated.", exc);

                continue;
            }
            catch (Exception exc)
            {
                if (context != null)
                    context.log ("ServiceManager: An unidentified error occurred", exc);

                service = null;
            }

            if (service != null)
            {
                cServicesMap.put (serviceBase, service);

                // build up list in reverse order for later destruction

                cServicesList.add (0, service);

                numSuccessful++;
            }
        }

        if (context != null)
            context.log ("ServiceManager: Services initialized (" + numSuccessful + "/" + numAll + " successful).");
        if (numSuccessful!=numAll)
        {
            throw new Exception("ServiceManager: Services initialized (" + numSuccessful + "/" + numAll + " successful).");
        }
    }

    /**
     * Calls post init for all services
     *
     * @param   aConfig
     *         the servlet configuration
     **/
     public static void postInit(ServletConfig aConfig) {
          // avoid duplicate destruction of services

        if (cInitialized)
        {
            synchronized (ServiceManager.class)
            {
                if (cInitialized)
                {
                    cInitialized = false;
                }
                else
                {
                    return;
                }
            }
        }
        else
        {
            return;
        }

        ServletContext context = null;

        if (aConfig != null)
            context = aConfig.getServletContext ();

        // post init all services
        for (Iterator iterator = cServicesList.iterator (); iterator.hasNext (); )
       {
           Service service = (Service) iterator.next ();

           try
           {
               service.postInit(aConfig);
           }
           catch (Exception exc)
           {
               if (context != null)
                   context.log ("ServiceManager: Service couldn't be started (postInit) after init..", exc);
           }
       }

     }

    /**
     ** Destroys all services.
     **
     ** @param   aConfig
     **          the servlet configuration
     **/

    public static void destroy (ServletConfig aConfig)
    {
        // avoid duplicate destruction of services

        if (cInitialized)
        {
            synchronized (ServiceManager.class)
            {
                if (cInitialized)
                {
                    cInitialized = false;
                }
                else
                {
                    return;
                }
            }
        }
        else
        {
            return;
        }

        ServletContext context = null;

        if (aConfig != null)
            context = aConfig.getServletContext ();

        // destroy the services in reverse order

        for (Iterator iterator = cServicesList.iterator (); iterator.hasNext (); )
        {
            Service service = (Service) iterator.next ();

            try
            {
                service.destroy (aConfig);
            }
            catch (Exception exc)
            {
                if (context != null)
                    context.log ("ServiceManager: Service couldn't be destroyed.", exc);
            }
        }

        cServicesList.clear();
        cServicesMap.clear();

    }

    /**
     ** Returns the service implementation for the given service class, or
     ** <CODE>null</CODE> if no such service is registered.
     **
     ** @param   aClass
     **          the service class
     **
     ** @return   the service implementation
     **/

    public static Service getService (Class aClass)
    {
        // at this state the services map is read-only,
        // therefore we can go without synchronization

        return ((Service) cServicesMap.get (aClass));
    }

    // --- PRIVATE MEMBERS --- //

    private static volatile boolean cInitialized = false;

    private static Map  cServicesMap  = new HashMap ();
    private static List cServicesList = new LinkedList ();
}



TOP

Related Classes of org.apache.pluto.portalImpl.services.ServiceManager

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.