org.apache.axis.configuration.EngineConfigurationFactoryFinder.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.axis.configuration.EngineConfigurationFactoryFinder.java

Source

/*
 * Copyright 2002-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.axis.configuration;

import org.apache.axis.AxisProperties;
import org.apache.axis.EngineConfigurationFactory;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.utils.Messages;
import org.apache.commons.discovery.ResourceClassIterator;
import org.apache.commons.discovery.tools.ClassUtils;
import org.apache.commons.logging.Log;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;

/**
 * This is a default implementation of EngineConfigurationFactory.
 * It is user-overrideable by a system property without affecting
 * the caller. If you decide to override it, use delegation if
 * you want to inherit the behaviour of this class as using
 * class extension will result in tight loops. That is, your
 * class should implement EngineConfigurationFactory and keep
 * an instance of this class in a member field and delegate
 * methods to that instance when the default behaviour is
 * required.
 *
 * @author Richard A. Sitze
 */
public class EngineConfigurationFactoryFinder {
    protected static Log log = LogFactory.getLog(EngineConfigurationFactoryFinder.class.getName());

    private static final Class mySpi = EngineConfigurationFactory.class;

    private static final Class[] newFactoryParamTypes = new Class[] { Object.class };

    private static final String requiredMethod = "public static EngineConfigurationFactory newFactory(Object)";

    static {
        AxisProperties.setClassOverrideProperty(EngineConfigurationFactory.class,
                EngineConfigurationFactory.SYSTEM_PROPERTY_NAME);

        AxisProperties.setClassDefaults(EngineConfigurationFactory.class,
                new String[] { "org.apache.axis.configuration.EngineConfigurationFactoryServlet",
                        "org.apache.axis.configuration.EngineConfigurationFactoryDefault", });
    }

    private EngineConfigurationFactoryFinder() {
    }

    /**
     * Create the default engine configuration and detect whether the user
     * has overridden this with their own.
     *
     * The discovery mechanism will use the following logic:
     *
     * - discover all available EngineConfigurationFactories
     *   - find all META-INF/services/org.apache.axis.EngineConfigurationFactory
     *     files available through class loaders.
     *   - read files (see Discovery) to obtain implementation(s) of that
     *     interface
     * - For each impl, call 'newFactory(Object param)'
     * - Each impl should examine the 'param' and return a new factory ONLY
     *   - if it knows what to do with it
     *     (i.e. it knows what to do with the 'real' type)
     *   - it can find it's configuration information
     * - Return first non-null factory found.
     * - Try EngineConfigurationFactoryServlet.newFactory(obj)
     * - Try EngineConfigurationFactoryDefault.newFactory(obj)
     * - If zero found (all return null), throw exception
     *
     * ***
     * This needs more work: System.properties, etc.
     * Discovery will have more tools to help with that
     * (in the manner of use below) in the near future.
     * ***
     *
     */
    public static EngineConfigurationFactory newFactory(final Object obj) {
        /**
         * recreate on each call is critical to gaining
         * the right class loaders.  Do not cache.
         */
        final Object[] params = new Object[] { obj };

        /**
         * Find and examine each service
         */
        return (EngineConfigurationFactory) AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                ResourceClassIterator services = AxisProperties.getResourceClassIterator(mySpi);

                EngineConfigurationFactory factory = null;

                while (factory == null && services.hasNext()) {
                    try {
                        Class service = services.nextResourceClass().loadClass();

                        /* service == null
                         * if class resource wasn't loadable
                         */
                        if (service != null) {
                            factory = newFactory(service, newFactoryParamTypes, params);
                        }
                    } catch (Exception e) {
                        // there was an exception creating the factory
                        // the most likely cause was the JDK 1.4 problem
                        // in the discovery code that requires servlet.jar
                        // to be in the client classpath.  For now, fall
                        // through to the next factory
                    }
                }

                if (factory != null) {
                    if (log.isDebugEnabled()) {
                        log.debug(Messages.getMessage("engineFactory", factory.getClass().getName()));
                    }
                } else {
                    log.error(Messages.getMessage("engineConfigFactoryMissing"));
                    // we should be throwing an exception here,
                    //
                    // but again, requires more refactoring than we want to swallow
                    // at this point in time.  Ifthis DOES occur, it's a coding error:
                    // factory should NEVER be null.
                    // Testing will find this, as NullPointerExceptions will be generated
                    // elsewhere.
                }

                return factory;
            }
        });
    }

    public static EngineConfigurationFactory newFactory() {
        return newFactory(null);
    }

    private static EngineConfigurationFactory newFactory(Class service, Class[] paramTypes, Object[] param) {
        /**
         * Some JDK's may link on method resolution (findPublicStaticMethod)
         * and others on method call (method.invoke).
         * 
         * Either way, catch class load/resolve problems and return null.
         */

        try {
            /**
             * Verify that service implements:
             *  public static EngineConfigurationFactory newFactory(Object);
             */
            Method method = ClassUtils.findPublicStaticMethod(service, EngineConfigurationFactory.class,
                    "newFactory", paramTypes);

            if (method == null) {
                log.warn(Messages.getMessage("engineConfigMissingNewFactory", service.getName(), requiredMethod));
            } else {
                try {
                    return (EngineConfigurationFactory) method.invoke(null, param);
                } catch (InvocationTargetException e) {
                    if (e.getTargetException() instanceof NoClassDefFoundError) {
                        log.debug(Messages.getMessage("engineConfigLoadFactory", service.getName()));
                    } else {
                        log.warn(Messages.getMessage("engineConfigInvokeNewFactory", service.getName(),
                                requiredMethod), e);
                    }
                } catch (Exception e) {
                    log.warn(Messages.getMessage("engineConfigInvokeNewFactory", service.getName(), requiredMethod),
                            e);
                }
            }
        } catch (NoClassDefFoundError e) {
            log.debug(Messages.getMessage("engineConfigLoadFactory", service.getName()));
        }

        return null;
    }
}