Package org.apache.hivemind.lib.impl

Source Code of org.apache.hivemind.lib.impl.ServicePropertyFactory

// 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.lib.impl;

import java.lang.reflect.Modifier;

import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.ServiceImplementationFactory;
import org.apache.hivemind.ServiceImplementationFactoryParameters;
import org.apache.hivemind.internal.ServicePoint;
import org.apache.hivemind.service.BodyBuilder;
import org.apache.hivemind.service.ClassFab;
import org.apache.hivemind.service.ClassFabUtils;
import org.apache.hivemind.service.ClassFactory;
import org.apache.hivemind.service.MethodIterator;
import org.apache.hivemind.service.MethodSignature;
import org.apache.hivemind.util.ConstructorUtils;
import org.apache.hivemind.util.PropertyAdaptor;
import org.apache.hivemind.util.PropertyUtils;

/**
* Factory that dynamically exposes a property of another service. A proxy is constructed that
* accesses the target service and obtains a property from that. The service interface of the
* constructed service must match the type of the exposed property.
*
* @author Howard Lewis Ship
*/
public class ServicePropertyFactory implements ServiceImplementationFactory
{
    private ClassFactory _classFactory;

    public Object createCoreServiceImplementation(
            ServiceImplementationFactoryParameters factoryParameters)
    {
        ServicePropertyFactoryParameter p = (ServicePropertyFactoryParameter) factoryParameters
                .getFirstParameter();

        ServicePoint targetServicePoint = p.getServicePoint();
        final Class targetServiceInterface = targetServicePoint.getServiceInterface();
    final Object targetService = targetServicePoint.getService( targetServiceInterface );
        String propertyName = p.getPropertyName();

        PropertyAdaptor pa = PropertyUtils.getPropertyAdaptor(targetService, propertyName);

        String readMethodName = pa.getReadMethodName();

        if (readMethodName == null)
            throw new ApplicationRuntimeException(ImplMessages.servicePropertyNotReadable(
                    propertyName,
                    targetService), null, p.getLocation(), null);
        Class serviceInterface = factoryParameters.getServiceInterface();

        if (!(serviceInterface.isAssignableFrom(pa.getPropertyType())))
            throw new ApplicationRuntimeException(ImplMessages.servicePropertyWrongType(
                    propertyName,
                    targetService,
                    pa.getPropertyType(),
                    serviceInterface), p.getLocation(), null);

        // Now we're good to go.

        String name = ClassFabUtils.generateClassName(serviceInterface);

        ClassFab cf = _classFactory.newClass(name, Object.class);

        addInfrastructure(cf, targetService, serviceInterface, targetServiceInterface, propertyName, readMethodName);

        addMethods(
                cf,
                factoryParameters.getServiceId(),
                serviceInterface,
                propertyName,
                targetService);

        Class proxyClass = cf.createClass();

        try
        {
            return ConstructorUtils.invokeConstructor(proxyClass, new Object[]
            { targetService });
        }
        catch (Throwable ex)
        {
            throw new ApplicationRuntimeException(ex.getMessage(), p.getLocation(), ex);
        }
    }

    private void addInfrastructure(ClassFab cf, Object targetService, Class serviceInterface, Class targetServiceInterface,
            String propertyName, String readPropertyMethodName)
    {
        cf.addInterface(serviceInterface);

        Class targetServiceClass = ClassFabUtils.getInstanceClass(cf, targetService, targetServiceInterface);
       
        cf.addField("_targetService", targetServiceClass);

        cf.addConstructor(new Class[]
        { targetServiceClass }, null, "{ super(); _targetService = $1; }");

        BodyBuilder b = new BodyBuilder();

        b.begin();
        b.addln(
                "{0} property = _targetService.{1}();",
                serviceInterface.getName(),
                readPropertyMethodName);

        b.addln("if (property == null)");
        b.add("  throw new java.lang.NullPointerException(");
        b.addQuoted(ImplMessages.servicePropertyWasNull(propertyName, targetService));
        b.addln(");");

        b.addln("return property;");

        b.end();

        MethodSignature sig = new MethodSignature(serviceInterface, "_targetServiceProperty", null,
                null);
        cf.addMethod(Modifier.FINAL | Modifier.PRIVATE, sig, b.toString());
    }

    private void addMethods(ClassFab cf, String serviceId, Class serviceInterface,
            String propertyName, Object targetService)
    {
        MethodIterator mi = new MethodIterator(serviceInterface);

        while (mi.hasNext())
        {
            MethodSignature sig = mi.next();

            String body = "return ($r) _targetServiceProperty()." + sig.getName() + "($$);";

            cf.addMethod(Modifier.PUBLIC, sig, body);
        }

        if (!mi.getToString())
            ClassFabUtils.addToStringMethod(cf, ImplMessages.servicePropertyToString(
                    serviceId,
                    serviceInterface,
                    propertyName,
                    targetService));
    }

    public void setClassFactory(ClassFactory factory)
    {
        _classFactory = factory;
    }
}
TOP

Related Classes of org.apache.hivemind.lib.impl.ServicePropertyFactory

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.