Package org.apache.hivemind.impl

Source Code of org.apache.hivemind.impl.ServicePointImpl

// 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;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.HiveMind;
import org.apache.hivemind.Orderable;
import org.apache.hivemind.ShutdownCoordinator;
import org.apache.hivemind.definition.ImplementationConstructor;
import org.apache.hivemind.definition.ImplementationDefinition;
import org.apache.hivemind.definition.InterceptorDefinition;
import org.apache.hivemind.definition.ServicePointDefinition;
import org.apache.hivemind.events.RegistryShutdownListener;
import org.apache.hivemind.internal.Module;
import org.apache.hivemind.internal.ServiceModel;
import org.apache.hivemind.internal.ServiceModelFactory;
import org.apache.hivemind.order.Orderer;
import org.apache.hivemind.service.InterfaceSynthesizer;
import org.apache.hivemind.util.ToStringBuilder;

/**
* Abstract implementation of {@link org.apache.hivemind.internal.ServicePoint}. Provides some of
* the machinery for creating new service instances, delegating most of it to the
* {@link org.apache.hivemind.internal.ServiceModel} instace for the service.
*
* @author Howard Lewis Ship
*/
public final class ServicePointImpl extends AbstractExtensionPoint implements
        ConstructableServicePoint
{
    private Object _service;

    private boolean _building;

    private Class _serviceInterface;

    private Class _declaredInterface;

    private List _orderedInterceptorDefinitions;

    private boolean _interceptorsOrdered;

    private ShutdownCoordinator _shutdownCoordinator;

    private ServiceModel _serviceModelObject;
   
    public ServicePointImpl(Module module, ServicePointDefinition definition)
    {
        super(module, definition);
    }

    protected void extendDescription(ToStringBuilder builder)
    {
        if (_service != null)
            builder.append("service", _service);

        builder.append("serviceInterfaceName", getServiceInterfaceClassName());
        builder.append("serviceModel", getServiceModel());
        builder.append("interceptorDefinitions", getInterceptorDefinitions());

        if (_building)
            builder.append("building", _building);
    }

    public synchronized Class getServiceInterface()
    {
        if (_serviceInterface == null)
            _serviceInterface = lookupServiceInterface();

        return _serviceInterface;
    }

    public synchronized Class getDeclaredInterface()
    {
        if (_declaredInterface == null)
            _declaredInterface = lookupDeclaredInterface();

        return _declaredInterface;
    }

    public String getServiceInterfaceClassName()
    {
        return getServicePointDefinition().getInterfaceClassName();
    }

    private Object getInterceptorDefinitions()
    {
        return getServicePointDefinition().getInterceptors();
    }

    private Class lookupDeclaredInterface()
    {
        Class result = null;

        try
        {
            result = getModule().resolveType(getServiceInterfaceClassName());
        }
        catch (Exception ex)
        {
            throw new ApplicationRuntimeException(ImplMessages.badInterface(
                    getServiceInterfaceClassName(),
                    getExtensionPointId()), getLocation(), ex);
        }

        return result;
    }

    private Class lookupServiceInterface()
    {
        Class declaredInterface = getDeclaredInterface();

        if (declaredInterface.isInterface())
            return declaredInterface;

        // Not an interface ... a class. Synthesize an interface from the class itself.

        InterfaceSynthesizer is = (InterfaceSynthesizer) getModule().getService(
                HiveMind.INTERFACE_SYNTHESIZER_SERVICE,
                InterfaceSynthesizer.class);

        return is.synthesizeInterface(declaredInterface);
    }

    /**
     * Invoked by {@link #getService(Class)} to get a service implementation from the
     * {@link ServiceModel}.
     * <p>
     * TODO: I'm concerned that this synchronized method could cause a deadlock. It would take a LOT
     * (mutually dependent services in multiple threads being realized at the same time).
     */
    private synchronized Object getService()
    {
        if (_service == null)
        {

            if (_building)
                throw new ApplicationRuntimeException(ImplMessages.recursiveServiceBuild(this));

            _building = true;

            try
            {

                ServiceModelFactory factory = getModule().getServiceModelFactory(getServiceModel());

                _serviceModelObject = factory.createServiceModelForService(this);

                _service = _serviceModelObject.getService();
            }
            finally
            {
                _building = false;
            }
        }

        return _service;
    }

    public Object getService(Class serviceInterface)
    {
        Object result = getService();

        if (!serviceInterface.isAssignableFrom(result.getClass()))
        {
            throw new ApplicationRuntimeException(ImplMessages.serviceWrongInterface(
                    this,
                    serviceInterface), getLocation(), null);
        }

        return result;
    }

    public String getServiceModel()
    {
        if (getServicePointDefinition() == null)
            return null;

        return getImplementationDefinition().getServiceModel();
    }

    public void clearConstructorInformation()
    {
        _orderedInterceptorDefinitions = null;
    }

    // Hm. Does this need to be synchronized?

    /**
     * @return  Ordered list of {@link InterceptorDefinition}s
     */
   public List getOrderedInterceptorContributions()
    {
        if (!_interceptorsOrdered)
        {
            _orderedInterceptorDefinitions = orderInterceptors();
            _interceptorsOrdered = true;
        }

        return _orderedInterceptorDefinitions;
    }

    /**
     * @return  Ordered list of {@link InterceptorDefinition}s
     */
    private List orderInterceptors()
    {
        Collection interceptorDefinitions = getServicePointDefinition().getInterceptors();
        if (HiveMind.isEmpty(interceptorDefinitions))
            return null;

        // Any error logging should go to the extension point
        // we're constructing.

        Log log = LogFactory.getLog(getExtensionPointId());

        Orderer orderer = new Orderer(log, getModule().getErrorHandler(), ImplMessages
                .interceptorContribution());

        Iterator i = interceptorDefinitions.iterator();
        while (i.hasNext())
        {
            InterceptorDefinition sid = (InterceptorDefinition) i.next();

            // Sort them into runtime excecution order. When we build
            // the interceptor stack we'll apply them in reverse order,
            // building outward from the core service implementation.

            String precedingNames = null;
            String followingNames = null;
            // Check if info about ordering is available
            if (sid instanceof Orderable) {
                Orderable orderable = (Orderable) sid;
                precedingNames = orderable.getPrecedingNames();
                followingNames = orderable.getFollowingNames();
            }
           
            orderer.add(sid, sid.getName(), precedingNames, followingNames);
        }

        return orderer.getOrderedObjects();
    }

    public void setShutdownCoordinator(ShutdownCoordinator coordinator)
    {
        _shutdownCoordinator = coordinator;
    }

    public void addRegistryShutdownListener(RegistryShutdownListener listener)
    {
        _shutdownCoordinator.addRegistryShutdownListener(listener);
    }

    /**
     * Forces the service into existence.
     */
    public void forceServiceInstantiation()
    {
        getService();

        _serviceModelObject.instantiateService();
    }

    /**
     * Returns the service constructor.
     */

    public ImplementationConstructor getServiceConstructor()
    {
        return getImplementationDefinition().getServiceConstructor();
    }

    public ImplementationDefinition getImplementationDefinition()
    {
        if (getServicePointDefinition().getDefaultImplementation() == null)
            throw new ApplicationRuntimeException(ImplMessages.servicePointDefinitionWithoutImplementation(getServicePointDefinition()));
        return getServicePointDefinition().getDefaultImplementation();
    }
   
    /**
     * @return  the service point definition that describes this service point
     */
    public ServicePointDefinition getServicePointDefinition()
    {
        return (ServicePointDefinition) super.getDefinition();
    }


}
TOP

Related Classes of org.apache.hivemind.impl.ServicePointImpl

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.