alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

PicoContainer example source code file (AbstractInjector.java)

This example PicoContainer source code file (AbstractInjector.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - PicoContainer tags/keywords

abstractinjector, class, class, cyclicdependencyexception, lifecyclestrategy, notconcreteregistrationexception, object, object, parameter, parameter, picocompositionexception, picocompositionexception, picocontainer, reflection, set, util

The PicoContainer AbstractInjector.java source code

/*****************************************************************************
 * Copyright (C) PicoContainer Organization. All rights reserved.            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *                                                                           *
 * Original code by                                                          *
 *****************************************************************************/
package org.picocontainer.injectors;

import org.picocontainer.ComponentMonitor;
import org.picocontainer.Parameter;
import org.picocontainer.PicoContainer;
import org.picocontainer.PicoCompositionException;
import org.picocontainer.PicoVisitor;
import org.picocontainer.LifecycleStrategy;
import org.picocontainer.ComponentAdapter;
import org.picocontainer.ObjectReference;
import org.picocontainer.adapters.AbstractAdapter;
import org.picocontainer.monitors.AbstractComponentMonitor;
import org.picocontainer.parameters.ComponentParameter;
import org.picocontainer.lifecycle.StartableLifecycleStrategy;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.lang.reflect.Member;
import java.util.List;
import java.util.LinkedList;
import java.util.Arrays;
import java.util.Set;

/**
 * This ComponentAdapter will instantiate a new object for each call to
 * {@link org.picocontainer.ComponentAdapter#getComponentInstance(PicoContainer)}.
 * That means that when used with a PicoContainer, getComponent will
 * return a new object each time.
 *
 * @author Aslak Hellesøy
 * @author Paul Hammant
 * @author Jörg Schaible
 * @author Mauro Talevi
 * @version $Revision: 3701 $
 */
public abstract class AbstractInjector extends AbstractAdapter implements LifecycleStrategy {
    /** The cycle guard for the verification. */ 
    protected transient ThreadLocalCyclicDependencyGuard verifyingGuard;
    /** The parameters to use for initialization. */ 
    protected transient Parameter[] parameters;
 
    /** The strategy used to control the lifecycle */
    protected LifecycleStrategy lifecycleStrategy;
    
    /**
     * Constructs a new ComponentAdapter for the given key and implementation. 
     * @param componentKey the search key for this implementation
     * @param componentImplementation the concrete implementation
     * @param parameters the parameters to use for the initialization
     * @param monitor the component monitor used by this ComponentAdapter
     * @param lifecycleStrategy the lifecycle strategy used by this ComponentAdapter
     * @throws org.picocontainer.injectors.AbstractInjector.NotConcreteRegistrationException if the implementation is not a concrete class
     * @throws NullPointerException if one of the parameters is <code>null
     */
    protected AbstractInjector(Object componentKey, Class componentImplementation, Parameter[] parameters,
                                            ComponentMonitor monitor, LifecycleStrategy lifecycleStrategy) {
        super(componentKey, componentImplementation, monitor);
        checkConcrete();
        if (parameters != null) {
            for (int i = 0; i < parameters.length; i++) {
                if(parameters[i] == null) {
                    throw new NullPointerException("Parameter " + i + " is null");
                }
            }
        }
        this.parameters = parameters;
        this.lifecycleStrategy = lifecycleStrategy;
    }

    /**
     * Constructs a new ComponentAdapter for the given key and implementation. 
     * @param componentKey the search key for this implementation
     * @param componentImplementation the concrete implementation
     * @param parameters the parameters to use for the initialization
     * @param monitor the component monitor used by this ComponentAdapter
     * @throws org.picocontainer.injectors.AbstractInjector.NotConcreteRegistrationException if the implementation is not a concrete class
     * @throws NullPointerException if one of the parameters is <code>null
     */
    protected AbstractInjector(Object componentKey, Class componentImplementation,
                                            Parameter[] parameters,
                                            ComponentMonitor monitor) {
        this(componentKey, componentImplementation, parameters, monitor, new StartableLifecycleStrategy(monitor));
    }

    /**
     * Constructs a new ComponentAdapter for the given key and implementation. 
     * @param componentKey the search key for this implementation
     * @param componentImplementation the concrete implementation
     * @param parameters the parameters to use for the initialization
     * @throws org.picocontainer.injectors.AbstractInjector.NotConcreteRegistrationException if the implementation is not a concrete class.
     * @throws NullPointerException if one of the parameters is <code>null
     */
    protected AbstractInjector(Object componentKey, Class componentImplementation, Parameter... parameters) {
        this(componentKey, componentImplementation, parameters, new AbstractComponentMonitor());
    }
    
    private void checkConcrete() throws NotConcreteRegistrationException {
        // Assert that the component class is concrete.
        boolean isAbstract = (getComponentImplementation().getModifiers() & Modifier.ABSTRACT) == Modifier.ABSTRACT;
        if (getComponentImplementation().isInterface() || isAbstract) {
            throw new NotConcreteRegistrationException(getComponentImplementation());
        }
    }

    /**
     * Create default parameters for the given types.
     *
     * @param parameters the parameter types
     * @return the array with the default parameters.
     */
    protected Parameter[] createDefaultParameters(Class[] parameters) {
        Parameter[] componentParameters = new Parameter[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            componentParameters[i] = ComponentParameter.DEFAULT;
        }
        return componentParameters;
    }

    public abstract void verify(PicoContainer container) throws PicoCompositionException;

    public void accept(PicoVisitor visitor) {
        super.accept(visitor);
        if (parameters != null) {
            for (Parameter parameter : parameters) {
                parameter.accept(visitor);
            }
        }
    }
  
    public void start(Object component) {
        lifecycleStrategy.start(component);
    }

    public void stop(Object component) {
        lifecycleStrategy.stop(component);
    }

    public void dispose(Object component) {
        lifecycleStrategy.dispose(component);
    }

    public boolean hasLifecycle(Class type) {
        return lifecycleStrategy.hasLifecycle(type);
    }

    /**
     * Instantiate an object with given parameters and respect the accessible flag.
     * 
     * @param constructor the constructor to use
     * @param parameters the parameters for the constructor 
     * @return the new object.
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    protected Object newInstance(Constructor constructor, Object[] parameters) throws InstantiationException, IllegalAccessException, InvocationTargetException {
        return constructor.newInstance(parameters);
    }

    protected Object caughtInstantiationException(ComponentMonitor componentMonitor,
                                                Constructor constructor,
                                                InstantiationException e, PicoContainer container) {
        // can't get here because checkConcrete() will catch it earlier, but see PICO-191
        componentMonitor.instantiationFailed(container, this, constructor, e);
        throw new PicoCompositionException("Should never get here");
    }

    protected Object caughtIllegalAccessException(ComponentMonitor componentMonitor,
                                                Constructor constructor,
                                                IllegalAccessException e, PicoContainer container) {
        // can't get here because either filtered or access mode set
        componentMonitor.instantiationFailed(container, this, constructor, e);
        throw new PicoCompositionException(e);
    }

    protected Object caughtInvocationTargetException(ComponentMonitor componentMonitor,
                                                   Member member,
                                                   Object componentInstance, InvocationTargetException e) {
        componentMonitor.invocationFailed(member, componentInstance, e);
        if (e.getTargetException() instanceof RuntimeException) {
            throw (RuntimeException) e.getTargetException();
        } else if (e.getTargetException() instanceof Error) {
            throw (Error) e.getTargetException();
        }
        throw new PicoCompositionException(e.getTargetException());
    }

    protected Object caughtIllegalAccessException(ComponentMonitor componentMonitor,
                                                Member member,
                                                Object componentInstance, IllegalAccessException e) {
        componentMonitor.invocationFailed(member, componentInstance, e);
        throw new PicoCompositionException(e);
    }

    /**
     * Abstract utility class to detect recursion cycles.
     * Derive from this class and implement {@link ThreadLocalCyclicDependencyGuard#run}.
     * The method will be called by  {@link ThreadLocalCyclicDependencyGuard#observe}. Select
     * an appropriate guard for your scope. Any {@link ObjectReference} can be
     * used as long as it is initialized with  <code>Boolean.FALSE.
     *
     * @author Jörg Schaible
     */
    static abstract class ThreadLocalCyclicDependencyGuard extends ThreadLocal {

        protected PicoContainer guardedContainer;

        protected Object initialValue() {
            return Boolean.FALSE;
        }

        /**
         * Derive from this class and implement this function with the functionality
         * to observe for a dependency cycle.
         *
         * @return a value, if the functionality result in an expression,
         *      otherwise just return <code>null
         */
        public abstract Object run();

        /**
         * Call the observing function. The provided guard will hold the {@link Boolean} value.
         * If the guard is already <code>Boolean.TRUE a {@link CyclicDependencyException}
         * will be  thrown.
         *
         * @param stackFrame the current stack frame
         * @return the result of the <code>run method
         */
        public final Object observe(Class stackFrame) {
            if (Boolean.TRUE.equals(get())) {
                throw new CyclicDependencyException(stackFrame);
            }
            Object result = null;
            try {
                set(Boolean.TRUE);
                result = run();
            } catch (final CyclicDependencyException e) {
                e.push(stackFrame);
                throw e;
            } finally {
                set(Boolean.FALSE);
            }
            return result;
        }

        public void setGuardedContainer(PicoContainer container) {
            this.guardedContainer = container;
        }

    }

    public static class CyclicDependencyException extends PicoCompositionException {
        private final List<Class> stack;

        /**
         * @param element
         */
        public CyclicDependencyException(Class element) {
            super((Throwable)null);
            this.stack = new LinkedList<Class>();
            push(element);
        }

        /**
         * @param element
         */
        public void push(Class element) {
            stack.add(element);
        }

        public Class[] getDependencies() {
            return stack.toArray(new Class[stack.size()]);
        }

        public String getMessage() {
            return "Cyclic dependency: " + stack.toString();
        }
    }

    /**
     * Exception that is thrown as part of the introspection. Raised if a PicoContainer cannot resolve a
     * type dependency because the registered {@link org.picocontainer.ComponentAdapter}s are not
     * distinct.
     *
     * @author Paul Hammant
     * @author Aslak Hellesøy
     * @author Jon Tirsén
     */
    public static final class AmbiguousComponentResolutionException extends PicoCompositionException {
        private Class component;
        private final Class ambiguousDependency;
        private final Object[] ambiguousComponentKeys;


        /**
         * Construct a new exception with the ambigous class type and the ambiguous component keys.
         *
         * @param ambiguousDependency the unresolved dependency type
         * @param componentKeys the ambiguous keys.
         */
        public AmbiguousComponentResolutionException(Class ambiguousDependency, Object[] componentKeys) {
            super("");
            this.ambiguousDependency = ambiguousDependency;
            this.ambiguousComponentKeys = new Class[componentKeys.length];
            System.arraycopy(componentKeys, 0, ambiguousComponentKeys, 0, componentKeys.length);
        }

        /**
         * @return Returns a string containing the unresolved class type and the ambiguous keys.
         */
        public String getMessage() {
            StringBuffer msg = new StringBuffer();
            msg.append(component);
            msg.append(" needs a '");
            msg.append(ambiguousDependency.getName());
            msg.append("' injected, but there are too many choices to inject. These:");
            msg.append(Arrays.asList(getAmbiguousComponentKeys()));
            msg.append(", refer http://picocontainer.org/ambiguous-injectable.html");
            return msg.toString();
        }

        /**
         * @return Returns the ambiguous component keys as array.
         */
        public Object[] getAmbiguousComponentKeys() {
            return ambiguousComponentKeys;
        }

        public void setComponent(Class component) {
            this.component = component;
        }
    }

    /**
     * Exception thrown when some of the component's dependencies are not satisfiable.
     *
     * @author Aslak Hellesøy
     * @author Mauro Talevi
     * @version $Revision: 3701 $
     */
    public static class UnsatisfiableDependenciesException extends PicoCompositionException {

        private final ComponentAdapter instantiatingComponentAdapter;
        private final Set unsatisfiableDependencies;
        private final Class unsatisfiedDependencyType;
        private final PicoContainer leafContainer;

        public UnsatisfiableDependenciesException(ComponentAdapter instantiatingComponentAdapter,
                                                  Class unsatisfiedDependencyType, Set unsatisfiableDependencies,
                                                  PicoContainer leafContainer) {
            super(instantiatingComponentAdapter.getComponentImplementation().getName() + " has unsatisfied dependency: " + unsatisfiedDependencyType
                    +" among unsatisfiable dependencies: "+unsatisfiableDependencies + " where " + leafContainer
                    + " was the leaf container being asked for dependencies.");
            this.instantiatingComponentAdapter = instantiatingComponentAdapter;
            this.unsatisfiableDependencies = unsatisfiableDependencies;
            this.unsatisfiedDependencyType = unsatisfiedDependencyType;
            this.leafContainer = leafContainer;
        }

        public ComponentAdapter getUnsatisfiableComponentAdapter() {
            return instantiatingComponentAdapter;
        }

        public Set getUnsatisfiableDependencies() {
            return unsatisfiableDependencies;
        }

        public Class getUnsatisfiedDependencyType() {
            return unsatisfiedDependencyType;
        }

        public PicoContainer getLeafContainer() {
            return leafContainer;
        }

    }

    /**
     * @author Aslak Hellesoy
     * @version $Revision: 3701 $
     */
    public static class NotConcreteRegistrationException extends PicoCompositionException {
        private final Class componentImplementation;

        public NotConcreteRegistrationException(Class componentImplementation) {
            super("Bad Access: '" + componentImplementation.getName() + "' is not instantiable");
            this.componentImplementation = componentImplementation;
        }

        public Class getComponentImplementation() {
            return componentImplementation;
        }
    }





}

Other PicoContainer examples (source code examples)

Here is a short list of links related to this PicoContainer AbstractInjector.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.