001// Copyright 2009, 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.internal.util.CollectionFactory;
019import org.apache.tapestry5.ioc.internal.util.InjectionResources;
020import org.apache.tapestry5.ioc.internal.util.InternalUtils;
021import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
022import org.slf4j.Logger;
023
024import java.lang.reflect.Method;
025import java.util.Map;
026
027/**
028 * Base class for service decorators and service advisors that work by invoking a module method.
029 *
030 * @since 5.1.0.0
031 */
032public class AbstractMethodInvokingInstrumenter
033{
034    private final ModuleBuilderSource moduleSource;
035
036    protected final Map<Class, Object> resourcesDefaults = CollectionFactory.newMap();
037
038    private final ServiceResources resources;
039
040    private final PlasticProxyFactory proxyFactory;
041
042    protected final Method method;
043
044    protected final Class serviceInterface;
045
046    protected final String serviceId;
047
048    private final Logger logger;
049
050    public AbstractMethodInvokingInstrumenter(ModuleBuilderSource moduleSource, Method method,
051                                              ServiceResources resources, PlasticProxyFactory proxyFactory)
052    {
053        this.moduleSource = moduleSource;
054        this.method = method;
055        this.resources = resources;
056        this.proxyFactory = proxyFactory;
057
058        serviceId = resources.getServiceId();
059
060        resourcesDefaults.put(String.class, serviceId);
061        resourcesDefaults.put(ObjectLocator.class, resources);
062        resourcesDefaults.put(ServiceResources.class, resources);
063        logger = resources.getLogger();
064        resourcesDefaults.put(Logger.class, logger);
065        serviceInterface = resources.getServiceInterface();
066        resourcesDefaults.put(Class.class, serviceInterface);
067        resourcesDefaults.put(OperationTracker.class, resources.getTracker());
068    }
069
070    @Override
071    public String toString()
072    {
073        Location location = proxyFactory.getMethodLocation(method);
074
075        return location.toString();
076    }
077
078    private Object getModuleInstance()
079    {
080        return InternalUtils.isStatic(method) ? null : moduleSource.getModuleBuilder();
081    }
082
083    protected Object invoke(final InjectionResources injectionResources)
084    {
085        String description = String.format("Invoking method %s", toString());
086
087        ObjectCreator<Object> plan = InternalUtils.createMethodInvocationPlan(resources.getTracker(), resources, injectionResources, logger, description, getModuleInstance(), method);
088
089        return plan.createObject();
090    }
091}