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 015 package org.apache.tapestry5.ioc.internal; 016 017 import org.apache.tapestry5.ioc.*; 018 import org.apache.tapestry5.ioc.def.ContributionDef3; 019 import org.apache.tapestry5.ioc.internal.util.*; 020 import org.apache.tapestry5.ioc.services.PlasticProxyFactory; 021 import org.slf4j.Logger; 022 023 import java.lang.reflect.InvocationTargetException; 024 import java.lang.reflect.Method; 025 import java.util.Map; 026 import java.util.Set; 027 028 public 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 public boolean isOptional() 063 { 064 return optional; 065 } 066 067 public String getServiceId() 068 { 069 return serviceId; 070 } 071 072 public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources, Configuration configuration) 073 { 074 invokeMethod(moduleSource, resources, Configuration.class, configuration); 075 } 076 077 public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources, 078 OrderedConfiguration configuration) 079 { 080 invokeMethod(moduleSource, resources, OrderedConfiguration.class, configuration); 081 } 082 083 public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources, 084 MappedConfiguration configuration) 085 { 086 invokeMethod(moduleSource, resources, MappedConfiguration.class, configuration); 087 } 088 089 private <T> void invokeMethod(ModuleBuilderSource source, ServiceResources resources, Class<T> parameterType, 090 T parameterValue) 091 { 092 Map<Class, Object> resourceMap = CollectionFactory.newMap(); 093 094 resourceMap.put(parameterType, parameterValue); 095 resourceMap.put(ObjectLocator.class, resources); 096 resourceMap.put(Logger.class, resources.getLogger()); 097 098 InjectionResources injectionResources = new MapInjectionResources(resourceMap); 099 100 // For each of the other configuration types that is not expected, add a guard. 101 102 for (Class t : CONFIGURATION_TYPES) 103 { 104 if (parameterType != t) 105 { 106 injectionResources = new DelegatingInjectionResources(new WrongConfigurationTypeGuard( 107 resources.getServiceId(), t, parameterType), injectionResources); 108 } 109 } 110 111 Throwable fail = null; 112 113 Object moduleInstance = InternalUtils.isStatic(contributorMethod) ? null : source.getModuleBuilder(); 114 115 try 116 { 117 ObjectCreator[] parameters = InternalUtils.calculateParametersForMethod(contributorMethod, resources, 118 injectionResources, resources.getTracker()); 119 120 contributorMethod.invoke(moduleInstance, InternalUtils.realizeObjects(parameters)); 121 } catch (InvocationTargetException ex) 122 { 123 fail = ex.getTargetException(); 124 } catch (Exception ex) 125 { 126 fail = ex; 127 } 128 129 if (fail != null) 130 throw new RuntimeException(IOCMessages.contributionMethodError(contributorMethod, fail), fail); 131 } 132 133 public Set<Class> getMarkers() 134 { 135 return markers; 136 } 137 138 public Class getServiceInterface() 139 { 140 return serviceInterface; 141 } 142 }