org.apache.struts.service.ServiceManager.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.struts.service.ServiceManager.java

Source

/*
 * $Header: /home/cvs/jakarta-struts/contrib/service-manager/src/core/org/apache/struts/service/ServiceManager.java,v 1.2 2002/12/08 07:53:32 rleland Exp $
 * $Revision: 1.2 $
 * $Date: 2002/12/08 07:53:32 $
 *
 * ====================================================================
 *
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, 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 acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Struts", 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 names without prior written
 *    permission of the Apache Group.
 *
 * 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 (INCLUDING, 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.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */

package org.apache.struts.service;

import java.io.Serializable;
import java.io.InputStream;
import java.io.FileInputStream;
import java.util.Iterator;
import java.util.HashMap;
import java.util.ArrayList;
import java.lang.NoSuchMethodException;
import java.util.MissingResourceException;
import javax.servlet.UnavailableException;
import java.util.MissingResourceException;
import java.lang.reflect.Method;
import org.xml.sax.SAXException;
import org.apache.commons.digester.Digester;
import org.apache.struts.util.MessageResources;

/** 
 * @author Oleg V Alexeev
 * @version $Revision: 1.2 $ $Date: 2002/12/08 07:53:32 $
 */
public class ServiceManager implements Serializable {

    //------------------------------------------------------ Constants

    /** Name of class to register service
     */
    protected static final String serviceRegistrationClass = "org.apache.struts.service.ServiceRegistration";

    /** Name of class to register process
     */
    protected static final String processRegistrationClass = "org.apache.struts.service.ProcessRegistration";

    /** Name of class to subscribe service to handle processing point
     */
    protected static final String processSubscriptionClass = "org.apache.struts.service.ProcessSubscription";

    protected static final Class[] parList = new Class[] { Object.class };

    //------------------------------------------------------ Variables

    /** Parent object for ServiceManager
     */
    protected Object parent = null;

    /** Empty list to use it as cork
     */
    protected ArrayList emptyList = new ArrayList();

    /** Map to store process registrations
     */
    protected HashMap processRegistrations = new HashMap();

    /** Map to store service registrations
     */
    protected HashMap serviceRegistrations = new HashMap();

    /** List ofinstantiated services
     */
    protected ArrayList services = new ArrayList();

    /** Log helper to support external logging. 
     */
    protected LogBridge logHelper = null;

    /** Debug level.
     */
    protected int debug = 0;

    /**
    * The resources object for our internal resources.
    */
    protected MessageResources internal = null;

    /**
    * The Java base name of our internal resources.
    */
    protected String internalName = "org.apache.struts.service.ServiceManagerResources";

    //------------------------------------------------------ Protected methods

    /** Return Iterator via empty list.
     */
    protected Iterator getEmptyIterator() {
        return emptyList.iterator();
    }

    /** Init log helper reference by default log helper class.
     */
    protected void initLogHelper() {
        logHelper = new ConsoleLogBridge();
    }

    /** Builds method name to call it in Service
     */
    protected String makeMethodName(String processName) {
        return "process" + processName.substring(0, 1).toUpperCase() + processName.substring(1).toLowerCase();
    }

    /** Return Iterator via Services, subscribed to the specified process.
     */
    protected Iterator servicesIterator(String processName) {

        ProcessRegistration processRegistration = (ProcessRegistration) processRegistrations.get(processName);
        if (processRegistration != null) {

            if (debug > 0)
                logHelper.log("Found processRegistration for process name '" + processName + "'");

            return processRegistration.getServicesIterator();
        } else {
            logHelper.log("Can not found process registration for process name '" + processName + "'");
            return getEmptyIterator();
        }
    }

    //------------------------------------------------------ Constructors

    /** Default constructor.
     */
    public ServiceManager() {
        setParent(null);
        initLogHelper();
    }

    /** Constructor to mount ServiceManager to the parent object.
     */
    public ServiceManager(Object parent) {
        setParent(parent);
        initLogHelper();
    }

    //------------------------------------------------------ Properties support

    /** Debug getter
     */
    public int getDebug() {
        return debug;
    }

    /** Debug setter
     */
    public void setDebug(int debug) {
        this.debug = debug;
    }

    /** ProcessRegistrations getter
     */
    public HashMap getProcessRegistrations() {
        return processRegistrations;
    }

    /** ServiceRegistrations getter
     */
    public HashMap getServiceRegistrations() {
        return serviceRegistrations;
    }

    /** LogHelper setter
     */
    public void setLogHelper(LogBridge logHelper) {
        this.logHelper = logHelper;
    }

    /** LogHelper getter
     */
    public LogBridge getLogHelper() {
        if (logHelper == null)
            initLogHelper();
        return logHelper;
    }

    /** Parent object setter
     */
    public void setParent(Object parent) {
        this.parent = parent;
    }

    /** Parent object getter
     */
    public Object getParent() {
        return parent;
    }

    //------------------------------------------------------ Public methods

    /** Process registration handler for digester
     */
    public void registerProcess(ProcessRegistration registration) {

        if (debug > 0)
            logHelper.log("Register process '" + registration.getName() + "'");

        registration.setServiceManager(this);
        processRegistrations.put(registration.getName(), registration);
    }

    /** Service registration handler for digester
     */
    public void registerService(ServiceRegistration registration) throws Exception {

        if (debug > 0)
            logHelper.log(
                    "Register service '" + registration.getName() + "' class - '" + registration.getType() + "'");

        registration.setServiceManager(this);
        serviceRegistrations.put(registration.getName(), registration);
        services.add(registration.getService());
    }

    //------------------------------------------------------- Init methods

    /** Single init method. Use this method to init ServiceManager
     *  with its own service-manager.xml config file.
     */
    public void init() throws Exception {

        if (debug > 0)
            logHelper.log("Init ServiceManager class - '" + this.getClass().getName() + "'");

        initStructures();
        initConfig();
    }

    /** Init internal structures to fill it later in init process
     */
    public void initStructures() throws Exception {
        initInternal();
        processRegistrations.clear();
        serviceRegistrations.clear();
        services.clear();
    }

    /**
    * Initialize our internal MessageResources bundle.
    *
    * @exception UnavailableException if we cannot initialize these resources
    */
    protected void initInternal() throws Exception {

        try {
            internal = MessageResources.getMessageResources(internalName);
        } catch (MissingResourceException e) {
            logHelper.log("Cannot load internal resources from '" + internalName + "'", e);
            throw e;
        }
    }

    /** Read self-contained config with help of digester.
     */
    public void initConfig() throws Exception {

        String value = null;
        String configLocation = "service-manager.xml";

        try {
            value = System.getProperty("org.apache.struts.service.Debug");
            setDebug(Integer.parseInt(value));
        } catch (Throwable t) {
            setDebug(0);
        }

        try {
            value = System.getProperty("org.apache.struts.service.ConfigLocation");
        } catch (SecurityException e) {
            throw e;
        } catch (Exception e) {
            if (debug > 0)
                logHelper.log(internal.getMessage("configLocationProperty.emptyProperty", configLocation));
        }
        if (value != null)
            configLocation = value;

        int detail;
        try {
            value = System.getProperty("org.apache.struts.service.ConfigDetail");
            detail = Integer.parseInt(value);
        } catch (Throwable t) {
            detail = 0;
        }

        // Acquire an input stream to our configuration resource
        InputStream input = new FileInputStream(configLocation);

        // Build a digester to process our configuration resource
        Digester digester = initDigester(detail);

        // Parse the input stream to configure our mappings
        try {
            digester.parse(input);
        } catch (SAXException e) {
            throw e;
        } finally {
            input.close();
        }

    }

    /** Init digester to be used with independent
     *  service manager config. 
     */
    public Digester initDigester(int detail) {
        Digester digester = new Digester();
        digester.setNamespaceAware(true);
        digester.setValidating(false);
        return initDigester(digester, null);
    }

    /** Init digester to parse config
     */
    public Digester initDigester(Digester digester, String path) {

        if (debug > 0)
            logHelper.log("Init digester in ServiceManager class - '" + this.getClass().getName() + "'");

        if (path != null)
            path += "/";
        else
            path = "";

        String serviceManagerPath = path + "service-manager";
        String processRegistrationPath = serviceManagerPath + "/process-registrations/process-registration";
        String serviceRegistrationPath = serviceManagerPath + "/service-registrations/service-registration";
        String processSubscriptionPath = serviceRegistrationPath + "/process-subscription";

        digester.addRule(serviceManagerPath, new InitServiceManagerRule(digester, this));

        // parse process registrations
        digester.addObjectCreate(processRegistrationPath, processRegistrationClass);
        digester.addSetProperties(processRegistrationPath);
        digester.addSetNext(processRegistrationPath, "registerProcess", processRegistrationClass);

        // parse service registrations
        digester.addObjectCreate(serviceRegistrationPath, serviceRegistrationClass);
        digester.addSetProperties(serviceRegistrationPath);
        digester.addSetNext(serviceRegistrationPath, "registerService", serviceRegistrationClass);
        digester.addRule(serviceRegistrationPath,
                new InitServiceRule(digester, new String(serviceRegistrationPath), this));

        // parse process subscriptions
        digester.addObjectCreate(processSubscriptionPath, processSubscriptionClass);
        digester.addSetProperties(processSubscriptionPath);
        digester.addSetNext(processSubscriptionPath, "subscribeTo", processSubscriptionClass);

        return digester;
    }

    //------------------------------------------------------- Destroy methods

    public void destroy() {
        if (debug > 0)
            logHelper.log("Destroy ServiceManager class - '" + this.getClass().getName() + "'");
        try {
            Iterator iterator = services.iterator();
            Service service = null;
            ProcessRegistration processRegistration = null;
            ServiceRegistration serviceRegistration = null;
            String key = null;
            while (iterator.hasNext()) {
                service = (Service) iterator.next();
                service.destroy();
            }
            services.clear();
            parent = null;
            iterator = processRegistrations.keySet().iterator();
            while (iterator.hasNext()) {
                key = (String) iterator.next();
                processRegistration = (ProcessRegistration) processRegistrations.get(key);
                processRegistration.getServices().clear();
            }
            processRegistrations.clear();
            iterator = serviceRegistrations.keySet().iterator();
            while (iterator.hasNext()) {
                key = (String) iterator.next();
                serviceRegistration = (ServiceRegistration) serviceRegistrations.get(key);
                serviceRegistration.getSubscriptions().clear();
            }
            serviceRegistrations.clear();
        } catch (Exception e) {
            logHelper.log("Exception in destroy of ServiceManager - ", e);
        }
    }

    //------------------------------------------------------ Perform methods

    /** Perform call with specified parameters to every Service, subscribed 
     *  to the specified process.
     */
    public void performCall(String processName, Object[] parameters) throws Exception {

        if (debug > 0)
            logHelper.log("Call to perfomCall for process '" + processName + "'");

        String methodName = makeMethodName(processName);
        Iterator iterator = servicesIterator(processName);
        Service service = null;
        Method method = null;

        if (parameters == null)
            parameters = new Object[] { null };

        while (iterator.hasNext()) {
            service = (Service) iterator.next();

            if (debug > 0)
                logHelper.log("Call to Service '" + service.getClass().getName() + "'");

            try {
                method = service.getClass().getMethod(methodName, parList);
            } catch (NoSuchMethodException e) {
                method = null;
            }

            if (method != null) {

                if (debug > 0)
                    logHelper.log("Try to invoke method '" + methodName + "' for class '"
                            + service.getClass().getName() + "'");

                method.invoke(service, parameters);

            } else {
                if (debug > 0)
                    logHelper.log("Can not find method '" + methodName + "'");
            }
        }
    }

    /** Perform call with specified parameters to Services, subscribed 
     *  to the specified process. Third input parameter indicate type of the call - 
     *  AND (true) or OR (false). AND call to this methods iterate via Services,
     *  subscribed to specified process thus far one of the Services methods return false.
     *  OR call collects all results from calls to the Services methods and perform
     *  'or' operation under this results. So every method in Services, called via 
     *  performBooleanCall() must return boolean or Boolean.
     */
    public boolean performBooleanCall(String processName, Object[] parameters, boolean type) throws Exception {

        if (debug > 0)
            logHelper.log("Call to perfomBooleanCall for process '" + processName + "' and call type - '"
                    + ((type) ? "AND" : "OR") + "'");

        String methodName = makeMethodName(processName);
        Iterator iterator = servicesIterator(processName);
        Service service = null;
        Method method = null;
        Boolean result = null;
        boolean collector = false;

        if (parameters == null)
            parameters = new Object[] { null };

        while (iterator.hasNext()) {
            service = (Service) iterator.next();

            if (debug > 0)
                logHelper.log("Call to Service '" + service.getClass().getName() + "'");

            try {
                method = service.getClass().getMethod(methodName, parList);
            } catch (NoSuchMethodException e) {
                method = null;
            }

            if (method != null) {

                if (debug > 0)
                    logHelper.log("Try to invoke method '" + methodName + "' for class '"
                            + service.getClass().getName() + "'");

                result = (Boolean) method.invoke(service, parameters);
                if (result != null) {
                    if (type) {
                        if (!result.booleanValue())
                            return false;
                    } else {
                        if (result.booleanValue())
                            collector = true;
                    }
                }
            } else {

                if (debug > 0)
                    logHelper.log("Can not find method '" + methodName + "'");
            }
        }

        if (type)
            return true;
        else
            return collector;

    }

}