Package org.apache.geronimo.remoting

Source Code of org.apache.geronimo.remoting.MarshalingInterceptorsTest

/**
*
* Copyright 2003-2004 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.geronimo.remoting;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;

import junit.framework.TestCase;

import org.apache.geronimo.proxy.ProxyContainer;
import org.apache.geronimo.proxy.ReflexiveInterceptor;
import org.apache.geronimo.remoting.transport.BytesMarshalledObject;

/**
* Unit test for the Marshaling/DeMarshaling Interceptors
*
* This test uses 2 classloaders to mock 2 seperate
* application classloaders.
*
* @version $Revision: 1.4 $ $Date: 2004/03/10 09:59:20 $
*/

public class MarshalingInterceptorsTest extends TestCase {

    private static final String PERSON_CLASS = "org.apache.geronimo.remoting.Person";
    private static final String TRANSIENT_CLASS = "org.apache.geronimo.remoting.TransientValue";
    ArrayList severContainers = new ArrayList();
    URLClassLoader cl1, cl2;

    /**
     * creates the two classloaders that will be used during the tests.
     */
    public void setUp() throws MalformedURLException, IOException {
        URL url = new File("./target/mock-app").toURL();
        System.out.println("Setting up the CP to: " + url);

        cl1 = new URLClassLoader(new URL[] { url });
        cl2 = new URLClassLoader(new URL[] { url });
    }   

    /**
     * Verify that the classpath/classloader structure is
     * as expected.  If the application classes are in
     * the current classloader then that will throw all the
     * tests off.
     *
     * @throws Exception
     */
    public void testCheckClassLoaders() throws Exception {
        Class class1 = cl1.loadClass(PERSON_CLASS);
        Class class2 = cl2.loadClass(PERSON_CLASS);
        assertFalse("Classpath for this test was incorrect.  The '"+PERSON_CLASS+"' cannot be in the test's classpath.", class1.equals(class2));
    }

    /**
     * Verify that the helper methods used by this test work
     * as expected.  Everything should be ok when working in the
     * same classloader.
     *
     * @throws Throwable
     */
    public void testSetSpouseSameCL() throws Throwable {
        Class class1 = cl1.loadClass(PERSON_CLASS);
        Class class2 = cl1.loadClass(PERSON_CLASS);

        Object object1 = class1.newInstance();
        Object object2 = class2.newInstance();

        call(object1, "setSpouse", new Object[] { object2 });
    }

    /**
     * Verify that the helper methods used by this test work
     * as expected.  We should see problems when you start mixing
     * Objects from different classloaders.
     *
     * @throws Throwable
     */
    public void testSetSpouseOtherCL() throws Throwable {
        Class class1 = cl1.loadClass(PERSON_CLASS);
        Class class2 = cl2.loadClass(PERSON_CLASS);

        Object object1 = class1.newInstance();
        Object object2 = class2.newInstance();

        try {
            call(object1, "setSpouse", new Object[] { object2 });
            fail("Call should fail due to argument type mismatch.");
        } catch (IllegalArgumentException e) {
        }
    }

    /**
     * Verify that a proxy using working in a single app context works ok.
     *
     * @throws Throwable
     */
    public void testSetSpouseWithProxy() throws Throwable {
        Class class1 = cl1.loadClass(PERSON_CLASS);
        Object object1 = class1.newInstance();

        // Simulate App1 creating a proxy.
        Thread.currentThread().setContextClassLoader(cl1);
        Object proxy1 = createProxy(object1);
        call(proxy1, "setSpouse", new Object[] { object1 });
    }

    /**
     * App2 creates a proxy and serializes.  App1 context deserializes
     * the proxy and trys to use it.  Method calls should be getting
     * marshalled/demarshaled by the proxy to avoid getting an
     * IllegalArgumentException.
     *
     * @throws Throwable
     */
    public void testSetSpouseOtherCLWithSerializedProxy() throws Throwable {
        Class class1 = cl1.loadClass(PERSON_CLASS);
        Class class2 = cl2.loadClass(PERSON_CLASS);

        Object object1 = class1.newInstance();
        Object object2 = class2.newInstance();

        // Simulate App2 creating a proxy.
        Thread.currentThread().setContextClassLoader(cl2);
        Object proxy2 = createProxy(object2);
        MarshalledObject mo = new BytesMarshalledObject(proxy2);

        // Simulate App1 using the serialized proxy.   
        Thread.currentThread().setContextClassLoader(cl1);
        Object proxy1 = mo.get();
        call(proxy1, "setSpouse", new Object[] { object1 });
    }

    /**
     * App1 creates a proxy.  It then creates a Transient calls that holds
     * a "value" property that is transient when serialized.  This allows to
     * to see if the Transient object was serialized by getting the value back
     * and seeing if the "value" is null.  All this work is done in one classloader
     * so no serialization should occur.
     *
     * @throws Throwable
     */
    public void testSetTransientWithOptimizedProxy() throws Throwable {
        Thread.currentThread().setContextClassLoader(cl1);
        Class class1 = cl1.loadClass(PERSON_CLASS);
        Object object1 = class1.newInstance();

        Class class2 = cl1.loadClass(TRANSIENT_CLASS);
        Object object2 = class2.newInstance();
        call(object2, "setValue", new Object[] { "foo" });

        Object proxy1 = createProxy(object1);
        call(proxy1, "setValue", new Object[] { object2 });
        Object rc = call(proxy1, "getValue", new Object[] {
        });
        rc = call(rc, "getValue", new Object[] {
        });

        assertSame(rc, "foo");
    }

    /**
     * Same as testSetTransientWithOptimizedProxy() but, the proxy is serialized before it is used.
     * It should still result in the method call not being serialized.
     *
     * @throws Throwable
     */
    public void testSetTransientWithSerializedOptimizedProxy() throws Throwable {
        Thread.currentThread().setContextClassLoader(cl1);
        Class class1 = cl1.loadClass(PERSON_CLASS);
        Object object1 = class1.newInstance();

        Class class2 = cl1.loadClass(TRANSIENT_CLASS);
        Object object2 = class2.newInstance();
        call(object2, "setValue", new Object[] { "foo" });

        Object proxy1 = createProxy(object1);
        proxy1 = new BytesMarshalledObject(proxy1).get();
        call(proxy1, "setValue", new Object[] { object2 });
        Object rc = call(proxy1, "getValue", new Object[] {
        });
        rc = call(rc, "getValue", new Object[] {
        });

        assertSame(rc, "foo");
    }

    /**
     * Same as testSetTransientWithOptimizedProxy() but, the proxy is serialized before it is
     * by App2.  Since a different classloader is using the proxy, the metod call should
     * be serialized and we should see that the set "value" is null.
     *
     * @throws Throwable
     */
    public void testSetTransientWithSerializedNonOptimizedProxy() throws Throwable {
        Thread.currentThread().setContextClassLoader(cl1);
        Class class1 = cl1.loadClass(PERSON_CLASS);
        Object object1 = class1.newInstance();

        Object proxy1 = createProxy(object1);
        Thread.currentThread().setContextClassLoader(cl2);
        proxy1 = new BytesMarshalledObject(proxy1).get();

        Class class2 = cl2.loadClass(TRANSIENT_CLASS);
        Object object2 = class2.newInstance();
        call(object2, "setValue", new Object[] { "foo" });

        call(proxy1, "setValue", new Object[] { object2 });
        Object rc = call(proxy1, "getValue", new Object[] {
        });
        rc = call(rc, "getValue", new Object[] {
        });

        assertSame(rc, null);
    }

    /**
     * Does a reflexive call on object1 my calling method with the provided args.
     *
     * @param object1
     */
    private Object call(Object object1, String method, Object[] args) throws Throwable {
        try {
            Class argTypes[] = getArgTypes(object1.getClass().getClassLoader(), args);
            Method m = findMethod(object1.getClass(), method);
            return m.invoke(object1, args);
        } catch (InvocationTargetException e) {
            throw e.getTargetException();
        }
    }

    /**
     * Gets the Class[] for a given Object[] using the provided loader.
     *
     * @param args
     * @return
     */
    private Class[] getArgTypes(ClassLoader loader, Object[] args) throws Exception {
        Class rc[] = new Class[args.length];
        for (int i = 0; i < rc.length; i++) {
            rc[i] = loader.loadClass(args[i].getClass().getName());
        }
        return rc;
    }

    /**
     * Finds the first method in class c whose name is name.
     * @param c
     * @param name
     * @return
     */
    private Method findMethod(Class c, String name) {
        Method[] methods = c.getMethods();
        for (int i = 0; i < methods.length; i++) {
            if (methods[i].getName().equals(name))
                return methods[i];
        }
        return null;
    }

    /**
      * @return
      */
    private Object createProxy(Object target) throws Exception {
       
        // Setup the server side contianer..
        ReflexiveInterceptor ri = new ReflexiveInterceptor(target);
        DeMarshalingInterceptor demarshaller = new DeMarshalingInterceptor(ri, target.getClass().getClassLoader());
        ProxyContainer serverContainer = new ProxyContainer(demarshaller);

        // Configure the server side interceptors.
        Long dmiid = InterceptorRegistry.instance.register(demarshaller);
       
        // Setup the client side container..       
        IntraVMRoutingInterceptor localRouter = new IntraVMRoutingInterceptor(ri, dmiid, false);
        ProxyContainer clientContainer = new ProxyContainer(localRouter);
        return clientContainer.createProxy(target.getClass().getClassLoader(), target.getClass().getInterfaces());
    }

}
TOP

Related Classes of org.apache.geronimo.remoting.MarshalingInterceptorsTest

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.