Package org.apache.hivemind.impl.servicemodel

Source Code of org.apache.hivemind.impl.servicemodel.PooledServiceModel$PooledService

// 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 java.util.ArrayList;
import java.util.List;

import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.HiveMind;
import org.apache.hivemind.PoolManageable;
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;

/**
* Similar to the
* {@link org.apache.hivemind.impl.servicemodel.ThreadedServiceModel threaded service model},
* except that, once created, services are pooled for later use.
*
* @author Howard Lewis Ship
*/
public class PooledServiceModel 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;

    private ThreadLocal _activeService;

    private List _servicePool;

    /** @since 1.1 */

    private Class _serviceInterface;

    /**
     * Shared, null implementation of PoolManageable.
     */
    private static final PoolManageable NULL_MANAGEABLE = new PoolManageable()
    {
        public void activateService()
        {
        }

        public void passivateService()
        {
        }
    };

    private class PooledService implements ThreadCleanupListener
    {
        private Object _core;

        private PoolManageable _managed;

        /**
         * @param service
         *            the full service implementation, including any interceptors
         * @param core
         *            the core service implementation, which may optionally implement
         *            {@link PoolManageable}
         */
        PooledService(Object core)
        {
            _core = core;

            if (core instanceof PoolManageable)
                _managed = (PoolManageable) core;
            else
                _managed = NULL_MANAGEABLE;
        }

        public void threadDidCleanup()
        {
            unbindPooledServiceFromCurrentThread(this);
        }

        void activate()
        {
            _managed.activateService();
        }

        void passivate()
        {
            _managed.passivateService();
        }

        /**
         * Returns the configured service implementation.
         */
        public Object getService()
        {
            return _core;
        }

    }

    public PooledServiceModel(ConstructableServicePoint servicePoint)
    {
        super(servicePoint);

        _serviceInterface = servicePoint.getServiceInterface();
    }

    public synchronized Object getService()
    {
        if (_notifier == null)
        {
            Module module = getServicePoint().getModule();

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

        if (_serviceProxy == null)
            _serviceProxy = constructServiceProxy();

        return _serviceProxy;
    }

    /**
     * Constructs the service proxy and returns it, wrapped in any interceptors.
     */
    private Object constructServiceProxy()
    {
        ConstructableServicePoint servicePoint = getServicePoint();

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

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

        Object intercepted = addInterceptors(proxy);

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

        ShutdownCoordinator coordinator = servicePoint.getShutdownCoordinator();

        coordinator.addRegistryShutdownListener(outerProxy);

        return outerProxy;
    }

    public synchronized Object getServiceImplementationForCurrentThread()
    {
        if (_activeService == null)
            _activeService = new ThreadLocal();

        PooledService pooled = (PooledService) _activeService.get();

        if (pooled == null)
        {
            pooled = obtainPooledService();

            pooled.activate();

            _notifier.addThreadCleanupListener(pooled);
            _activeService.set(pooled);
        }

        return pooled.getService();
    }

    private PooledService obtainPooledService()
    {
        PooledService result = getServiceFromPool();

        if (result == null)
            result = constructPooledService();

        return result;
    }

    private synchronized PooledService getServiceFromPool()
    {
        int count = _servicePool == null ? 0 : _servicePool.size();

        if (count == 0)
            return null;

        return (PooledService) _servicePool.remove(count - 1);
    }

    private synchronized void returnServiceToPool(PooledService pooled)
    {
        if (_servicePool == null)
            _servicePool = new ArrayList();

        _servicePool.add(pooled);
    }

    private synchronized PooledService constructPooledService()
    {
        try
        {
            Object core = constructCoreServiceImplementation();

            // This is related to bean services.

            if (!_serviceInterface.isInstance(core))
                core = constructBridgeProxy(core);
            if( core instanceof RegistryShutdownListener )
            {
                getShutdownCoordinatorService().addRegistryShutdownListener( ( RegistryShutdownListener )core );
            }
            return new PooledService(core);
        }
        catch (Exception ex)
        {
            throw new ApplicationRuntimeException(ServiceModelMessages.unableToConstructService(
                    getServicePoint(),
                    ex), ex);
        }
    }

    private void unbindPooledServiceFromCurrentThread(PooledService pooled)
    {
        _notifier.removeThreadCleanupListener(pooled);

        _activeService.set(null);

        pooled.passivate();

        returnServiceToPool(pooled);
    }

    /**
     * Invokes {@link #getServiceImplementationForCurrentThread()}to instantiate an instance of the
     * service.
     */
    public void instantiateService()
    {
        getServiceImplementationForCurrentThread();
    }

}
TOP

Related Classes of org.apache.hivemind.impl.servicemodel.PooledServiceModel$PooledService

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.