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