001// Copyright 2006-2013 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014 015package org.apache.tapestry5.internal.transform; 016 017import org.apache.tapestry5.func.F; 018import org.apache.tapestry5.func.Predicate; 019import org.apache.tapestry5.ioc.ObjectLocator; 020import org.apache.tapestry5.ioc.OperationTracker; 021import org.apache.tapestry5.ioc.annotations.Inject; 022import org.apache.tapestry5.ioc.util.ExceptionUtils; 023import org.apache.tapestry5.model.MutableComponentModel; 024import org.apache.tapestry5.plastic.PlasticClass; 025import org.apache.tapestry5.plastic.PlasticField; 026import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2; 027import org.apache.tapestry5.services.transform.InjectionProvider2; 028import org.apache.tapestry5.services.transform.TransformationSupport; 029 030/** 031 * Performs injection triggered by any field annotated with the {@link org.apache.tapestry5.ioc.annotations.Inject} 032 * annotation or the {@link javax.inject.Inject} annotation. 033 * <p/> 034 * The implementation of this worker mostly delegates to a chain of command of {@link InjectionProvider2}. 035 */ 036public class InjectWorker implements ComponentClassTransformWorker2 037{ 038 private final ObjectLocator locator; 039 040 // Really, a chain of command 041 042 private final InjectionProvider2 injectionProvider; 043 044 private final OperationTracker tracker; 045 046 private final Predicate<PlasticField> MATCHER = new Predicate<PlasticField>() 047 { 048 public boolean accept(PlasticField field) 049 { 050 return field.hasAnnotation(Inject.class) || 051 field.hasAnnotation(javax.inject.Inject.class); 052 } 053 }; 054 055 public InjectWorker(ObjectLocator locator, InjectionProvider2 injectionProvider, OperationTracker tracker) 056 { 057 this.locator = locator; 058 this.injectionProvider = injectionProvider; 059 this.tracker = tracker; 060 } 061 062 public void transform(final PlasticClass plasticClass, TransformationSupport support, final MutableComponentModel model) 063 { 064 for (final PlasticField field : F.flow(plasticClass.getUnclaimedFields()).filter(MATCHER)) 065 { 066 final String fieldName = field.getName(); 067 068 tracker.run(String.format("Injecting field %s.%s", plasticClass.getClassName(), fieldName), new Runnable() 069 { 070 public void run() 071 { 072 try 073 { 074 boolean success = injectionProvider.provideInjection(field, locator, model); 075 076 if (success) 077 { 078 field.claim("@Inject"); 079 } 080 } catch (RuntimeException ex) 081 { 082 throw new RuntimeException(String.format("Error obtaining injected value for field %s.%s: %s", plasticClass.getClassName(), fieldName, ExceptionUtils.toMessage(ex)), ex); 083 } 084 } 085 }); 086 } 087 } 088}