blob: 60977a5dbd6d0d63e48382d3c8d9b98b949267ff [file] [log] [blame]
/*
* 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.apache.zest.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.apache.zest.api.composite.InjectedFieldDescriptor;
import org.apache.zest.api.util.Classes;
import org.apache.zest.bootstrap.BindingException;
import org.apache.zest.bootstrap.InjectionException;
import org.apache.zest.functional.HierarchicalVisitor;
import org.apache.zest.functional.Specification;
import org.apache.zest.functional.VisitableHierarchy;
import org.apache.zest.runtime.composite.TransientInstance;
import org.apache.zest.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 + '}';
}
}