001    /*****************************************************************************
002     * Copyright (c) PicoContainer Organization. All rights reserved.            *
003     * ------------------------------------------------------------------------- *
004     * The software in this package is published under the terms of the BSD      *
005     * style license a copy of which has been included with this distribution in *
006     * the LICENSE.txt file.                                                     *
007     *                                                                           *
008     * Idea by Rachel Davies, Original code by Jon Tirsen                        *
009     *****************************************************************************/
010    
011    package org.picocontainer.parameters;
012    
013    import org.picocontainer.ComponentAdapter;
014    import org.picocontainer.Parameter;
015    import org.picocontainer.PicoContainer;
016    import org.picocontainer.PicoException;
017    import org.picocontainer.PicoCompositionException;
018    import org.picocontainer.PicoVisitor;
019    import org.picocontainer.ParameterName;
020    
021    import java.io.Serializable;
022    import java.lang.reflect.Field;
023    
024    
025    /**
026     * A ConstantParameter should be used to pass in "constant" arguments to constructors. This
027     * includes {@link String}s,{@link Integer}s or any other object that is not registered in
028     * the container.
029     *
030     * @author Jon Tirsén
031     * @author Aslak Hellesøy
032     * @author Jörg Schaible
033     * @author Thomas Heller
034     */
035    public class ConstantParameter
036            implements Parameter, Serializable {
037    
038        private final Object value;
039    
040        public ConstantParameter(Object value) {
041            this.value = value;
042        }
043    
044        public Object resolveInstance(PicoContainer container, ComponentAdapter adapter, Class expectedType, ParameterName expectedParameterName) {
045            return value;
046        }
047    
048        public boolean isResolvable(PicoContainer container, ComponentAdapter adapter, Class expectedType, ParameterName expectedParameterName) {
049            try {
050                verify(container, adapter, expectedType, expectedParameterName);
051                return true;
052            } catch(final PicoCompositionException e) {
053                return false;
054            }
055        }
056    
057        /**
058         * {@inheritDoc}
059         *
060         * @see org.picocontainer.Parameter#verify(org.picocontainer.PicoContainer,org.picocontainer.ComponentAdapter,Class,org.picocontainer.ParameterName)
061         */
062        public void verify(PicoContainer container, ComponentAdapter adapter, Class expectedType, ParameterName expectedParameterName) throws PicoException {
063            if (!checkPrimitive(expectedType) && !expectedType.isInstance(value)) {
064                throw new PicoCompositionException(expectedType.getClass().getName() + " is not assignable from " +
065                                                     (value != null ? value.getClass().getName() : "null"));
066            }
067        }
068    
069        /**
070         * Visit the current {@link Parameter}.
071         *
072         * @see org.picocontainer.Parameter#accept(org.picocontainer.PicoVisitor)
073         */
074        public void accept(final PicoVisitor visitor) {
075            visitor.visitParameter(this);
076        }
077    
078        private boolean checkPrimitive(Class expectedType) {
079            try {
080                if (expectedType.isPrimitive()) {
081                    final Field field = value.getClass().getField("TYPE");
082                    final Class type = (Class) field.get(value);
083                    return expectedType.isAssignableFrom(type);
084                }
085            } catch (NoSuchFieldException e) {
086                //ignore
087            } catch (IllegalAccessException e) {
088                //ignore
089            }
090            return false;
091        }
092    
093    }