001// Copyright 2006, 2007, 2008, 2009, 2010, 2011 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.ioc.internal; 016 017import org.apache.tapestry5.ioc.*; 018import org.apache.tapestry5.ioc.def.ContributionDef3; 019import org.apache.tapestry5.ioc.internal.util.*; 020import org.apache.tapestry5.ioc.services.PlasticProxyFactory; 021import org.slf4j.Logger; 022 023import java.lang.reflect.InvocationTargetException; 024import java.lang.reflect.Method; 025import java.util.Map; 026import java.util.Set; 027 028public class ContributionDefImpl implements ContributionDef3 029{ 030 private final String serviceId; 031 032 private final Method contributorMethod; 033 034 private final boolean optional; 035 036 private final PlasticProxyFactory proxyFactory; 037 038 private final Set<Class> markers; 039 040 private final Class serviceInterface; 041 042 private static final Class[] CONFIGURATION_TYPES = new Class[] 043 {Configuration.class, MappedConfiguration.class, OrderedConfiguration.class}; 044 045 public ContributionDefImpl(String serviceId, Method contributorMethod, boolean optional, PlasticProxyFactory proxyFactory, 046 Class serviceInterface, Set<Class> markers) 047 { 048 this.serviceId = serviceId; 049 this.contributorMethod = contributorMethod; 050 this.optional = optional; 051 this.proxyFactory = proxyFactory; 052 this.serviceInterface = serviceInterface; 053 this.markers = markers; 054 } 055 056 @Override 057 public String toString() 058 { 059 return InternalUtils.asString(contributorMethod, proxyFactory); 060 } 061 062 @Override 063 public boolean isOptional() 064 { 065 return optional; 066 } 067 068 @Override 069 public String getServiceId() 070 { 071 return serviceId; 072 } 073 074 @Override 075 public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources, Configuration configuration) 076 { 077 invokeMethod(moduleSource, resources, Configuration.class, configuration); 078 } 079 080 @Override 081 public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources, 082 OrderedConfiguration configuration) 083 { 084 invokeMethod(moduleSource, resources, OrderedConfiguration.class, configuration); 085 } 086 087 @Override 088 public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources, 089 MappedConfiguration configuration) 090 { 091 invokeMethod(moduleSource, resources, MappedConfiguration.class, configuration); 092 } 093 094 private <T> void invokeMethod(ModuleBuilderSource source, ServiceResources resources, Class<T> parameterType, 095 T parameterValue) 096 { 097 Map<Class, Object> resourceMap = CollectionFactory.newMap(); 098 099 resourceMap.put(parameterType, parameterValue); 100 resourceMap.put(ObjectLocator.class, resources); 101 resourceMap.put(Logger.class, resources.getLogger()); 102 103 InjectionResources injectionResources = new MapInjectionResources(resourceMap); 104 105 // For each of the other configuration types that is not expected, add a guard. 106 107 for (Class t : CONFIGURATION_TYPES) 108 { 109 if (parameterType != t) 110 { 111 injectionResources = new DelegatingInjectionResources(new WrongConfigurationTypeGuard( 112 resources.getServiceId(), t, parameterType), injectionResources); 113 } 114 } 115 116 Throwable fail = null; 117 118 Object moduleInstance = InternalUtils.isStatic(contributorMethod) ? null : source.getModuleBuilder(); 119 120 try 121 { 122 ObjectCreator[] parameters = InternalUtils.calculateParametersForMethod(contributorMethod, resources, 123 injectionResources, resources.getTracker()); 124 125 contributorMethod.invoke(moduleInstance, InternalUtils.realizeObjects(parameters)); 126 } catch (InvocationTargetException ex) 127 { 128 fail = ex.getTargetException(); 129 } catch (Exception ex) 130 { 131 fail = ex; 132 } 133 134 if (fail != null) 135 throw new RuntimeException(IOCMessages.contributionMethodError(contributorMethod, fail), fail); 136 } 137 138 @Override 139 public Set<Class> getMarkers() 140 { 141 return markers; 142 } 143 144 @Override 145 public Class getServiceInterface() 146 { 147 return serviceInterface; 148 } 149}