Package org.apache.hivemind.impl.servicemodel

Source Code of org.apache.hivemind.impl.servicemodel.ThreadedServiceModel$CleanupListener

// Copyright 2004, 2005 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.apache.hivemind.impl.servicemodel;

import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.Discardable;
import org.apache.hivemind.HiveMind;
import org.apache.hivemind.ShutdownCoordinator;
import org.apache.hivemind.events.RegistryShutdownListener;
import org.apache.hivemind.impl.ConstructableServicePoint;
import org.apache.hivemind.impl.ProxyUtils;
import org.apache.hivemind.internal.Module;
import org.apache.hivemind.service.ThreadCleanupListener;
import org.apache.hivemind.service.ThreadEventNotifier;

/**
* Like {@link org.apache.hivemind.impl.servicemodel.SingletonServiceModel}, this method returns a proxy
* (implementing the service interface); unlike SingletonServiceModel, it <em>always</em> returns
* the proxy. Invoking a service method on the proxy constructs a service implementation and binds
* it to the current thread.
*
* @author Howard Lewis Ship
*/
public final class ThreadedServiceModel extends AbstractServiceModelImpl
{
    /**
     * Name of a method in the deferred proxy that is used to obtain the constructed service.
     */
    protected static final String SERVICE_ACCESSOR_METHOD_NAME = "_service";

    private Object _serviceProxy;

    private ThreadEventNotifier _notifier;
   
    /** @since 1.1 */
   
    private Class _serviceInterface;

    public ThreadedServiceModel(ConstructableServicePoint servicePoint)
    {
        super(servicePoint);
       
        _serviceInterface = servicePoint.getServiceInterface();
    }

    class CleanupListener implements ThreadCleanupListener
    {
        // The core itself
        private Object _core;

        CleanupListener(Object core)
        {
            _core = core;
        }

        public void threadDidCleanup()
        {
            // Orhpan this object
            _notifier.removeThreadCleanupListener(this);

            unbindServiceFromCurrentThread();

            if (_core instanceof Discardable)
            {
                Discardable d = (Discardable) _core;

                d.threadDidDiscardService();
            }
        }
    }

    /**
     * Used to store the active service for the current thread.
     */
    private ThreadLocal _activeService;

    /**
     * Always returns the service proxy.
     */
    public synchronized Object getService()
    {
        // _activeService will be null on first invocation; a good
        // time to create it, the proxy, and find the notifier.

        if (_activeService == null)
        {
            _activeService = new ThreadLocal();

            Module module = getServicePoint().getModule();

            _notifier = (ThreadEventNotifier) module.getService(
                    HiveMind.THREAD_EVENT_NOTIFIER_SERVICE,
                    ThreadEventNotifier.class);

            _serviceProxy = createServiceProxy();
        }

        // The result is an interceptor stack, where the final (most deeply nested) object
        // is the serviceProxy. The serviceProxy obtains the instance for the current thread
        // and delegates to it. This is a little bit different than SingletonServiceModel, which
        // creates a pair of proxies so as to defer creation of the interceptors as well. In both
        // cases, the interceptors are only created once.

        return _serviceProxy;
    }

    /**
     * Creates a proxy instance for the service, and returns it, wrapped in any interceptors for the
     * service.
     */
    private Object createServiceProxy()
    {
        ConstructableServicePoint servicePoint = getServicePoint();

        if (_log.isDebugEnabled())
            _log.debug("Creating ThreadedProxy for service " + servicePoint.getExtensionPointId());

        Object proxy = ProxyUtils.createDelegatingProxy(
                "ThreadedProxy",
                this,
                "getServiceImplementationForCurrentThread",
                servicePoint);

        Object intercepted = addInterceptors(proxy);

        RegistryShutdownListener outerProxy = ProxyUtils
                .createOuterProxy(intercepted, servicePoint);

        ShutdownCoordinator coordinator = servicePoint.getShutdownCoordinator();

        coordinator.addRegistryShutdownListener(outerProxy);

        return outerProxy;
    }

    /**
     * Invoked by the proxy to return the active service impl for this thread, constructing it as
     * necessary.
     */
    public Object getServiceImplementationForCurrentThread()
    {
        Object result = _activeService.get();

        if (result == null)
            result = constructServiceForCurrentThread();

        return result;
    }

    private synchronized Object constructServiceForCurrentThread()
    {
        try
        {
            Object core = constructCoreServiceImplementation();

            if (core instanceof RegistryShutdownListener)
                _log.error(ServiceModelMessages.registryCleanupIgnored(getServicePoint()));

            _notifier.addThreadCleanupListener(new CleanupListener(core));

            _activeService.set(core);

            // Once more ... with bean services, its possible that
            // the factory generated bean does not implement the (synthetic) service
            // interface, so create a bridge to it.

            if (!_serviceInterface.isInstance(core))
                core = constructBridgeProxy(core);

            return core;
        }
        catch (Exception ex)
        {
            throw new ApplicationRuntimeException(ServiceModelMessages.unableToConstructService(
                    getServicePoint(),
                    ex), ex);
        }
    }

    private void unbindServiceFromCurrentThread()
    {
        _activeService.set(null);
    }

    /**
     * Invokes {@link #getServiceImplementationForCurrentThread()} to force the creation of the
     * service implementation.
     */

    public void instantiateService()
    {
        getServiceImplementationForCurrentThread();
    }

}
TOP

Related Classes of org.apache.hivemind.impl.servicemodel.ThreadedServiceModel$CleanupListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.