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