Package org.apache.tuscany.binding.rmi

Source Code of org.apache.tuscany.binding.rmi.RMIService$RMIServiceClassLoader

/**
*
* Copyright 2006 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.tuscany.binding.rmi;

import java.lang.reflect.Method;
import java.rmi.Remote;
import java.rmi.server.UnicastRemoteObject;

import net.sf.cglib.asm.ClassWriter;
import net.sf.cglib.asm.Constants;
import net.sf.cglib.asm.Type;
import net.sf.cglib.proxy.Enhancer;

import org.apache.tuscany.host.rmi.RMIHost;
import org.apache.tuscany.host.rmi.RMIHostException;
import org.apache.tuscany.spi.component.CompositeComponent;
import org.apache.tuscany.spi.extension.ServiceExtension;
import org.apache.tuscany.spi.wire.WireService;

/**
* @version $Rev: 453762 $ $Date: 2006-10-06 14:07:14 -0700 (Fri, 06 Oct 2006) $
*/
public class RMIService<T extends Remote> extends ServiceExtension {

    public static final String URI_PREFIX = "//localhost";
    public static final String SLASH = "/";
    public static final String COLON = ":";
    //private final String host;
    private final String port;
    private final String serviceName;
    private RMIHost rmiHost;

    // need this member to morph the service interface to extend from Remote if it does not
    // the base class's member variable interfaze is to be maintained to enable the connection
    // of the service outbound to the component's inbound wire which requires that the service
    // and the component match in their service contracts.
    private Class serviceInterface;

    public RMIService(String name,
                      CompositeComponent parent,
                      WireService wireService,
                      RMIHost rHost,
                      String host,
                      String port,
                      String svcName,
                      Class<T> service) {
        super(name, service, parent, wireService);

        this.serviceInterface = service;
        this.rmiHost = rHost;
        //this.host = host;
        this.port = port;
        this.serviceName = svcName;
    }

    public void start() {
        super.start();
        Remote rmiProxy = createRmiService();

        try {
            // startRMIRegistry();
            rmiHost.registerService(serviceName,
                getPort(port),
                rmiProxy);
            // bindRmiService(uri,rmiProxy);
        } catch (RMIHostException e) {
            throw new NoRemoteServiceException(e);
        }
    }

    public void stop() {
        try {
            rmiHost.unregisterService(serviceName, getPort(port));
        } catch (RMIHostException e) {
            throw new NoRemoteServiceException(e.getMessage());
        }
        super.stop();
    }

    protected Remote createRmiService() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UnicastRemoteObject.class);
        enhancer.setCallback(new RemoteMethodHandler(getHandler(), interfaze));

        if (!Remote.class.isAssignableFrom(serviceInterface)) {
            RMIServiceClassLoader classloader =
                new RMIServiceClassLoader(getClass().getClassLoader());
            final byte[] byteCode = generateRemoteInterface(serviceInterface);
            serviceInterface = classloader.defineClass(byteCode);
            enhancer.setClassLoader(classloader);
        }
        enhancer.setInterfaces(new Class[]{serviceInterface});
        return (Remote) enhancer.create();
    }

    protected int getPort(String port) {
        int portNumber = RMIHost.RMI_DEFAULT_PORT;
        if (port != null && port.length() > 0) {
            portNumber = Integer.decode(port);
        }

        return portNumber;
    }

    // if the interface of the component whose services must be exposed as RMI Service, does not
    // implement java.rmi.Remote, then generate such an interface. This method will stop with
    // just generating the bytecode. Defining the class from the byte code must tbe the responsibility
    // of the caller of this method, since it requires a classloader to be created to define and load
    // this interface.
    protected byte[] generateRemoteInterface(Class serviceInterface) {
        String interfazeName = serviceInterface.getCanonicalName();
        ClassWriter cw = new ClassWriter(false);

        String simpleName = serviceInterface.getSimpleName();
        cw.visit(Constants.V1_5, Constants.ACC_PUBLIC + Constants.ACC_ABSTRACT + Constants.ACC_INTERFACE,
            interfazeName.replace('.', '/'), "java/lang/Object", new String[]{"java/rmi/Remote"}, simpleName + ".java");

        StringBuffer argsAndReturn = null;
        Method[] methods = serviceInterface.getMethods();
        for (Method method : methods) {
            argsAndReturn = new StringBuffer("(");
            Class[] paramTypes = method.getParameterTypes();
            Class returnType = method.getReturnType();

            for (Class paramType : paramTypes) {
                argsAndReturn.append(Type.getType(paramType));
            }
            argsAndReturn.append(")");
            argsAndReturn.append(Type.getType(returnType));

            cw.visitMethod(Constants.ACC_PUBLIC + Constants.ACC_ABSTRACT, method.getName(), argsAndReturn.toString(),
                new String[]{"java/rmi/RemoteException"}, null);
        }
        cw.visitEnd();
        return cw.toByteArray();
    }

    private class RMIServiceClassLoader extends ClassLoader {
        public RMIServiceClassLoader(ClassLoader parent) {
            super(parent);
        }
        public Class defineClass(byte[] byteArray) {
            return defineClass(null, byteArray, 0, byteArray.length);
        }
    }
}
TOP

Related Classes of org.apache.tuscany.binding.rmi.RMIService$RMIServiceClassLoader

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.