001 // Copyright 2009 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.ModuleBuilderSource;
018 import org.apache.tapestry5.ioc.ObjectLocator;
019 import org.apache.tapestry5.ioc.OperationTracker;
020 import org.apache.tapestry5.ioc.ServiceResources;
021 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
022 import org.apache.tapestry5.ioc.internal.util.InjectionResources;
023 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
024 import org.apache.tapestry5.ioc.services.ClassFactory;
025 import org.slf4j.Logger;
026
027 import java.lang.reflect.InvocationTargetException;
028 import java.lang.reflect.Method;
029 import java.util.Map;
030
031 /**
032 * Based class for service decorators and service advisors that work by invoking a module method.
033 *
034 * @since 5.1.0.0
035 */
036 public class AbstractMethodInvokingInstrumenter
037 {
038 private final ModuleBuilderSource moduleSource;
039
040 protected final Map<Class, Object> resourcesDefaults = CollectionFactory.newMap();
041
042 private final ServiceResources resources;
043
044 private final ClassFactory classFactory;
045
046 protected final Method method;
047
048 protected final Class serviceInterface;
049
050 protected final String serviceId;
051 private final Logger logger;
052
053 public AbstractMethodInvokingInstrumenter(
054 ModuleBuilderSource moduleSource, Method method, ServiceResources resources, ClassFactory classFactory)
055 {
056 this.moduleSource = moduleSource;
057 this.method = method;
058 this.resources = resources;
059 this.classFactory = classFactory;
060
061 serviceId = resources.getServiceId();
062
063 resourcesDefaults.put(String.class, serviceId);
064 resourcesDefaults.put(ObjectLocator.class, resources);
065 resourcesDefaults.put(ServiceResources.class, resources);
066 logger = resources.getLogger();
067 resourcesDefaults.put(Logger.class, logger);
068 serviceInterface = resources.getServiceInterface();
069 resourcesDefaults.put(Class.class, serviceInterface);
070 resourcesDefaults.put(OperationTracker.class, resources.getTracker());
071 }
072
073 @Override
074 public String toString()
075 {
076 return classFactory.getMethodLocation(method).toString();
077 }
078
079 private Object getModuleInstance()
080 {
081 return InternalUtils.isStatic(method)
082 ? null
083 : moduleSource.getModuleBuilder();
084 }
085
086 protected Object invoke(InjectionResources injectionResources)
087 {
088 Object result = null;
089 Throwable failure = null;
090
091 if (logger.isDebugEnabled())
092 logger.debug(String.format("Invoking method %s", this));
093
094 try
095 {
096 Object[] parameters = InternalUtils.calculateParametersForMethod(
097 method,
098 resources,
099 injectionResources, resources.getTracker());
100
101 result = method.invoke(getModuleInstance(), parameters);
102 }
103 catch (InvocationTargetException ite)
104 {
105 failure = ite.getTargetException();
106 }
107 catch (Exception ex)
108 {
109 failure = ex;
110 }
111
112 if (failure != null)
113 throw new RuntimeException(
114 String.format("Exception invoking method %s: %s",
115 this,
116 InternalUtils.toMessage(failure)),
117 failure);
118
119 return result;
120 }
121 }