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 }