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    
015    package org.apache.tapestry5.ioc.internal;
016    
017    import org.apache.tapestry5.ioc.ObjectCreator;
018    import org.apache.tapestry5.ioc.ServiceBuilderResources;
019    import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
020    import org.apache.tapestry5.services.UpdateListenerHub;
021    
022    import java.lang.reflect.Method;
023    
024    /**
025     * Responsible for creating a {@link ReloadableServiceImplementationObjectCreator} for a service implementation.
026     */
027    @SuppressWarnings("unchecked")
028    public 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        public ObjectCreator constructCreator(final ServiceBuilderResources resources)
052        {
053            return new ObjectCreator()
054            {
055                public Object createObject()
056                {
057                    return createReloadableProxy(resources);
058                }
059    
060                @Override
061                public String toString()
062                {
063                    return proxyFactory.getMethodLocation(bindMethod).toString();
064                }
065            };
066        }
067    
068        public String getDescription()
069        {
070            return String.format("Reloadable %s via %s", serviceImplementationClass.getName(),
071                    proxyFactory.getMethodLocation(bindMethod));
072        }
073    
074        private Object createReloadableProxy(ServiceBuilderResources resources)
075        {
076            ReloadableServiceImplementationObjectCreator reloadableCreator = new ReloadableServiceImplementationObjectCreator(proxyFactory,
077                    resources, proxyFactory.getClassLoader(), serviceImplementationClass.getName());
078    
079            resources.getService(UpdateListenerHub.class).addUpdateListener(reloadableCreator);
080    
081            if (eagerLoad)
082            {
083                reloadableCreator.createObject();
084            }
085    
086            return proxyFactory.createProxy(serviceInterfaceClass, reloadableCreator, getDescription());
087        }
088    }