    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&eacute;n
    033     * @author Aslak Helles&oslash;y
    034     * @author J&ouml;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    }