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.NameBinding;
020    
021    import java.io.Serializable;
022    import java.lang.reflect.Field;
023    import java.lang.annotation.Annotation;
024    
025    
026    /**
027     * A ConstantParameter should be used to pass in "constant" arguments to constructors. This
028     * includes {@link String}s,{@link Integer}s or any other object that is not registered in
029     * the container.
030     *
031     * @author Jon Tirsén
032     * @author Aslak Hellesøy
033     * @author Jörg Schaible
034     * @author Thomas Heller
035     */
036    @SuppressWarnings("serial")
037    public class ConstantParameter
038            implements Parameter, Serializable {
039    
040        private final Object value;
041    
042        public ConstantParameter(Object value) {
043            this.value = value;
044        }
045    
046        public Object resolveInstance(PicoContainer container,
047                                      ComponentAdapter adapter,
048                                      Class expectedType,
049                                      NameBinding expectedNameBinding,
050                                      boolean useNames, Annotation binding) {
051            return value;
052        }
053    
054        public boolean isResolvable(PicoContainer container,
055                                    ComponentAdapter adapter,
056                                    Class expectedType,
057                                    NameBinding expectedNameBinding,
058                                    boolean useNames, Annotation binding) {
059            try {
060                verify(container, adapter, expectedType, expectedNameBinding, useNames, binding);
061                return true;
062            } catch(final PicoCompositionException e) {
063                return false;
064            }
065        }
066    
067        /**
068         * {@inheritDoc}
069         *
070         * @see Parameter#verify(PicoContainer, ComponentAdapter, Class, NameBinding ,boolean, Annotation)
071         */
072        public void verify(PicoContainer container,
073                           ComponentAdapter adapter,
074                           Class expectedType,
075                           NameBinding expectedNameBinding,
076                           boolean useNames, Annotation binding) throws PicoException {
077            if (!checkPrimitive(expectedType) && !expectedType.isInstance(value)) {
078                throw new PicoCompositionException(expectedType.getClass().getName() + " is not assignable from " +
079                                                     (value != null ? value.getClass().getName() : "null"));
080            }
081        }
082    
083        /**
084         * Visit the current {@link Parameter}.
085         *
086         * @see org.picocontainer.Parameter#accept(org.picocontainer.PicoVisitor)
087         */
088        public void accept(final PicoVisitor visitor) {
089            visitor.visitParameter(this);
090        }
091    
092        private boolean checkPrimitive(Class expectedType) {
093            try {
094                if (expectedType.isPrimitive()) {
095                    final Field field = value.getClass().getField("TYPE");
096                    final Class type = (Class) field.get(value);
097                    return expectedType.isAssignableFrom(type);
098                }
099            } catch (NoSuchFieldException e) {
100                //ignore
101            } catch (IllegalAccessException e) {
102                //ignore
103            }
104            return false;
105        }
106    
107    }