Package org.apache.hivemind.impl

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

// 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.io.Serializable;
import java.lang.reflect.Modifier;

import org.apache.hivemind.internal.Module;
import org.apache.hivemind.internal.ser.ServiceSerializationHelper;
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;

/**
* Class used to assist extension points in creating proxies.
*
* @author Howard Lewis Ship
*/
public final class ProxyBuilder
{
    private Class _serviceInterface;

    private ClassFab _classFab;

    private String _type;

    /**
     * Constructs a new builder. The type will be incorporated into value returned by the
     * <code>toString()</code> method.
     * The generated proxy has an constructor that expects the extension point id as single parameter.
     *
     * @param type
     *            used as part of the <code>toString()</code> method's return value
     * @param module
     *            the module that constructs the proxy
     * @param serviceInterface
     *            the interface of the proxied class. 
     * @param declaredInterface
     *            the interface of the proxied class or the class itself if the proxied class is actually a POJO.
     * @param outerProxy
     *            if false, then the proxy can extend the configuration points service interface always.
     *            If true and the declared interface is actually a bean class (not
     *            an interface), then the proxy will be a subclass of that bean.
     */
    public ProxyBuilder(String type, Module module, Class serviceInterface, Class declaredInterface, boolean outerProxy)
    {
        _type = type;
        _serviceInterface = serviceInterface;

        ClassFactory factory = (ClassFactory) module.getService(
                "hivemind.ClassFactory",
                ClassFactory.class);

        boolean extendBeanClass = outerProxy && !declaredInterface.isInterface();
        Class baseClass = extendBeanClass ? declaredInterface : Object.class;

        _classFab = factory.newClass(ClassFabUtils.generateClassName(_serviceInterface), baseClass);

        _classFab.addField("_extensionPointId", String.class);
       
        _classFab.addConstructor(new Class[] { String.class }, null, "{ _extensionPointId = $1; }");
       
        if (!extendBeanClass)
            _classFab.addInterface(_serviceInterface);

        // Not exactly certain this will work with non-interface beans that already
        // are serializable!

        if (outerProxy)
            addSerializable();
    }

    /** @since 1.1 */
    private void addSerializable()
    {
        _classFab.addInterface(Serializable.class);

        BodyBuilder bb = new BodyBuilder();

        bb.add(
                "return {0}.getServiceSerializationSupport().getServiceTokenForService(_extensionPointId);",
                ServiceSerializationHelper.class.getName());

        MethodSignature sig = new MethodSignature(Object.class, "writeReplace", null, null);

        _classFab.addMethod(Modifier.PRIVATE, sig, bb.toString());
    }

    public ClassFab getClassFab()
    {
        return _classFab;
    }
   
    /**
     * @see #addServiceMethods(String, boolean)
     */
    public void addServiceMethods(String indirection)
    {
        addServiceMethods(indirection, true);
    }

    /**
     * Creates the service methods for the class.
     *
     * @param indirection
     *            the name of a variable, or a method invocation snippet, used to redirect the
     *            invocation on the proxy to the actual service implementation.
     * @param addToString if true, a implementation of the toString method is generated that
     *    returns some info about the proxy
     */
    public void addServiceMethods(String indirection, boolean addToString)
    {
        BodyBuilder builder = new BodyBuilder();

        MethodIterator mi = new MethodIterator(_serviceInterface);
        while (mi.hasNext())
        {
            MethodSignature m = mi.next();
            if( !_classFab.containsMethod( m ) )
            {
                builder.clear();
                builder.begin();
                builder.add("return ($r) ");
                builder.add(indirection);
                builder.add(".");
                builder.add(m.getName());
                builder.addln("($$);");
                builder.end();
                _classFab.addMethod(Modifier.PUBLIC, m, builder.toString());
            }
        }

        if (!mi.getToString() && addToString)
            ClassFabUtils.addToStringMethod(_classFab, "<" + _type + " for \" + _extensionPointId + \""
                    + "(" + _serviceInterface.getName() + ")>");
    }
}
TOP

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

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.