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én 034 * @author Aslak Hellesøy 035 * @author Jörg Schaible 036 * @author Thomas Heller 037 */ 038 @SuppressWarnings("serial") 039 public class ConstantParameter extends AbstractParameter 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 }