| /* |
| * Copyright (c) 2008, Rickard Öberg. All Rights Reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package org.qi4j.runtime.injection; |
| |
| import java.lang.annotation.Annotation; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.InvocationHandler; |
| import java.lang.reflect.Proxy; |
| import java.util.Collection; |
| import org.qi4j.api.composite.InjectedFieldDescriptor; |
| import org.qi4j.api.util.Classes; |
| import org.qi4j.bootstrap.BindingException; |
| import org.qi4j.bootstrap.InjectionException; |
| import org.qi4j.functional.HierarchicalVisitor; |
| import org.qi4j.functional.Specification; |
| import org.qi4j.functional.VisitableHierarchy; |
| import org.qi4j.runtime.composite.TransientInstance; |
| import org.qi4j.runtime.model.Resolution; |
| |
| import static java.util.Collections.emptyList; |
| import static java.util.Collections.singleton; |
| |
| /** |
| * JAVADOC |
| */ |
| public final class InjectedFieldModel |
| implements InjectedFieldDescriptor, VisitableHierarchy<InjectedFieldModel, DependencyModel> |
| { |
| private DependencyModel dependencyModel; |
| private Field injectedField; |
| |
| public InjectedFieldModel( Field injectedField, DependencyModel dependencyModel ) |
| { |
| injectedField.setAccessible( true ); |
| this.injectedField = injectedField; |
| this.dependencyModel = dependencyModel; |
| } |
| |
| @Override |
| public DependencyModel dependency() |
| { |
| return dependencyModel; |
| } |
| |
| @Override |
| public Field field() |
| { |
| return injectedField; |
| } |
| |
| public void bind( Resolution resolution ) |
| throws BindingException |
| { |
| dependencyModel.bind( resolution.forField( injectedField ) ); |
| } |
| |
| public void inject( InjectionContext context, Object instance ) |
| { |
| Object value = dependencyModel.inject( context ); |
| try |
| { |
| injectedField.set( instance, value ); |
| } |
| catch( IllegalAccessException e ) |
| { |
| throw new InjectionException( e ); |
| } |
| catch( IllegalArgumentException e ) |
| { |
| String valueClassName; |
| if( Proxy.isProxyClass( value.getClass() ) ) |
| { |
| InvocationHandler invocationHandler = Proxy.getInvocationHandler( value ); |
| if( invocationHandler instanceof TransientInstance ) |
| { |
| TransientInstance handler = (TransientInstance) invocationHandler; |
| valueClassName = Classes.toString( handler.descriptor().types() ) |
| + " in [" + handler.module().name() + "] of [" + handler.layer().name() + "]"; |
| } |
| else |
| { |
| valueClassName = invocationHandler.toString(); |
| } |
| } |
| else |
| { |
| valueClassName = value.getClass().getName(); |
| } |
| StringBuilder annotBuilder = new StringBuilder(); |
| for( Annotation annot : injectedField.getAnnotations() ) |
| { |
| String s = annot.toString(); |
| annotBuilder.append( "@" ).append( s.substring( s.lastIndexOf( '.' ) + 1, s.length() - 2 ) ); |
| annotBuilder.append( " " ); |
| } |
| String annots = annotBuilder.toString(); |
| String message = "Can not inject the field\n " |
| + injectedField.getDeclaringClass() |
| + "\n {\n " + annots + "\n " |
| + injectedField.getType().getSimpleName() + " " + injectedField.getName() |
| + "\n }\nwith value \n " + value + "\nof type\n " |
| + valueClassName; |
| throw new InjectionException( message, e ); |
| } |
| } |
| |
| @Override |
| public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super InjectedFieldModel, ? super DependencyModel, ThrowableType> visitor ) |
| throws ThrowableType |
| { |
| if( visitor.visitEnter( this ) ) |
| { |
| visitor.visit( dependencyModel ); |
| } |
| return visitor.visitLeave( this ); |
| } |
| |
| public Collection<DependencyModel> filter( Specification<DependencyModel> specification ) |
| { |
| if( specification.satisfiedBy( dependencyModel ) ) |
| { |
| return singleton( dependencyModel ); |
| } |
| else |
| { |
| return emptyList(); |
| } |
| } |
| |
| @Override |
| public String toString() |
| { |
| return "InjectedFieldModel{" + ", injectedField=" + injectedField + '}'; |
| } |
| } |