    001// Copyright 2010, 2011, 2012 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.ObjectCreator;
    018import org.apache.tapestry5.ioc.ServiceBuilderResources;
    019import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
    020import org.apache.tapestry5.services.UpdateListenerHub;
    021
    022import java.lang.reflect.Method;
    023
    024/**
    025 * Responsible for creating a {@link ReloadableServiceImplementationObjectCreator} for a service implementation.
    026 */
    027@SuppressWarnings("unchecked")
    028public class ReloadableObjectCreatorSource implements ObjectCreatorSource
    029{
    030    private final PlasticProxyFactory proxyFactory;
    031
    032    private final Method bindMethod;
    033
    034    private final Class serviceInterfaceClass;
    035
    036    private final Class serviceImplementationClass;
    037
    038    private final boolean eagerLoad;
    039
    040    public ReloadableObjectCreatorSource(PlasticProxyFactory proxyFactory, Method bindMethod,
    041                                         Class serviceInterfaceClass, Class serviceImplementationClass, boolean eagerLoad)
    042    {
    043        this.proxyFactory = proxyFactory;
    044        this.bindMethod = bindMethod;
    045        this.serviceInterfaceClass = serviceInterfaceClass;
    046        this.serviceImplementationClass = serviceImplementationClass;
    047        this.eagerLoad = eagerLoad;
    048    }
    049
    050
    051    @Override
    052    public ObjectCreator constructCreator(final ServiceBuilderResources resources)
    053    {
    054        return new ObjectCreator()
    055        {
    056            @Override
    057            public Object createObject()
    058            {
    059                return createReloadableProxy(resources);
    060            }
    061
    062            @Override
    063            public String toString()
    064            {
    065                return proxyFactory.getMethodLocation(bindMethod).toString();
    066            }
    067        };
    068    }
    069
    070    @Override
    071    public String getDescription()
    072    {
    073        return String.format("Reloadable %s via %s", serviceImplementationClass.getName(),
    074                proxyFactory.getMethodLocation(bindMethod));
    075    }
    076
    077    private Object createReloadableProxy(ServiceBuilderResources resources)
    078    {
    079        ReloadableServiceImplementationObjectCreator reloadableCreator = new ReloadableServiceImplementationObjectCreator(proxyFactory,
    080                resources, proxyFactory.getClassLoader(), serviceImplementationClass.getName());
    081
    082        resources.getService(UpdateListenerHub.class).addUpdateListener(reloadableCreator);
    083
    084        if (eagerLoad)
    085        {
    086            reloadableCreator.createObject();
    087        }
    088
    089        return proxyFactory.createProxy(serviceInterfaceClass, resources.getServiceImplementation(), reloadableCreator, getDescription());
    090    }
    091}