    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.ParameterizedType;
    024    import java.lang.reflect.Type;
    025    import java.lang.annotation.Annotation;
    026
    027
    028    /**
    029     * A ConstantParameter should be used to pass in "constant" arguments to constructors. This
    030     * includes {@link String}s,{@link Integer}s or any other object that is not registered in
    031     * the container.
    032     *
    033     * @author Jon Tirs&eacute;n
    034     * @author Aslak Helles&oslash;y
    035     * @author J&ouml;rg Schaible
    036     * @author Thomas Heller
    037     */
    038    @SuppressWarnings("serial")
    039    public class ConstantParameter implements Parameter, Serializable {
    040
    041        private final Object value;
    042
    043
    044        public ConstantParameter(Object value) {
    045            this.value = value;
    046        }
    047
    048        public Resolver resolve(PicoContainer container, ComponentAdapter<?> forAdapter,
    049                                ComponentAdapter<?> injecteeAdapter, final Type expectedType, NameBinding expectedNameBinding,
    050                                boolean useNames, Annotation binding) {
    051            if (expectedType instanceof Class) {
    052                return new Parameter.ValueResolver(isAssignable((Class) expectedType), value, null);
    053            } else if (expectedType instanceof ParameterizedType) {
    054                    return new Parameter.ValueResolver(isAssignable(((ParameterizedType)expectedType).getRawType()), value, null);
    055            }
    056            return new Parameter.ValueResolver(true, value, null);
    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    }