/* * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.corba.se.impl.presentation.rmi ; import java.io.Serializable ; import java.io.Externalizable ; import javax.rmi.PortableRemoteObject ; import javax.rmi.CORBA.Util ; import org.omg.CORBA.portable.IDLEntity ; import org.omg.CORBA_2_3.portable.InputStream ; import org.omg.CORBA_2_3.portable.OutputStream ; import org.omg.CORBA.portable.ApplicationException ; import java.lang.reflect.Method ; import java.rmi.RemoteException ; import com.sun.corba.se.spi.orb.ORB ; import com.sun.corba.se.spi.presentation.rmi.DynamicMethodMarshaller ; public class DynamicMethodMarshallerImpl implements DynamicMethodMarshaller { Method method ; ExceptionHandler ehandler ; boolean hasArguments = true ; boolean hasVoidResult = true ; boolean needsArgumentCopy ; // true if copyObjects call needs for args boolean needsResultCopy ; // true if copyObject call needs for result ReaderWriter[] argRWs = null ; ReaderWriter resultRW = null ; private static boolean isAnyClass( Class cls ) { return cls.equals( Object.class ) || cls.equals( Serializable.class ) || cls.equals( Externalizable.class ) ; } // Assume that cls is not Remote, !isAnyClass(cls), and // !org.omg.CORBA.Object.class.isAssignableFrom( cls ). // Then return whether cls is an RMI-IIOP abstract interface. private static boolean isAbstractInterface( Class cls ) { // Either cls is an interface that extends IDLEntity, or else // cls does not extend java.rmi.Remote and all of its methods // throw RemoteException. if (IDLEntity.class.isAssignableFrom( cls )) return cls.isInterface() ; else return cls.isInterface() && allMethodsThrowRemoteException( cls ) ; } private static boolean allMethodsThrowRemoteException( Class cls ) { Method[] methods = cls.getMethods() ; // Check that all methods (other than those declared in java.lang.Object) // throw an exception that is a subclass of RemoteException. for (int ctr=0; ctr<methods.length; ctr++) { Method method = methods[ctr] ; if (method.getDeclaringClass() != Object.class) if (!throwsRemote( method )) return false ; } return true ; } private static boolean throwsRemote( Method method ) { Class[] exceptionTypes = method.getExceptionTypes() ; // Check that some exceptionType is a subclass of RemoteException for (int ctr=0; ctr<exceptionTypes.length; ctr++) { Class exceptionType = exceptionTypes[ctr] ; if (java.rmi.RemoteException.class.isAssignableFrom( exceptionType )) return true ; } return false ; } public interface ReaderWriter { Object read( InputStream is ) ; void write( OutputStream os, Object value ) ; } abstract static class ReaderWriterBase implements ReaderWriter { String name ; public ReaderWriterBase( String name ) { this.name = name ; } public String toString() { return "ReaderWriter[" + name + "]" ; } } private static ReaderWriter booleanRW = new ReaderWriterBase( "boolean" ) { public Object read( InputStream is ) { boolean value = is.read_boolean() ; return new Boolean( value ) ; } public void write( OutputStream os, Object value ) { Boolean val = (Boolean)value ; os.write_boolean( val.booleanValue() ) ; } } ; private static ReaderWriter byteRW = new ReaderWriterBase( "byte" ) { public Object read( InputStream is ) { byte value = is.read_octet() ; return new Byte( value ) ; } public void write( OutputStream os, Object value ) { Byte val = (Byte)value ; os.write_octet( val.byteValue() ) ; } } ; private static ReaderWriter charRW = new ReaderWriterBase( "char" ) { public Object read( InputStream is ) { char value = is.read_wchar() ; return new Character( value ) ; } public void write( OutputStream os, Object value ) { Character val = (Character)value ; os.write_wchar( val.charValue() ) ; } } ; private static ReaderWriter shortRW = new ReaderWriterBase( "short" ) { public Object read( InputStream is ) { short value = is.read_short() ; return new Short( value ) ; } public void write( OutputStream os, Object value ) { Short val = (Short)value ; os.write_short( val.shortValue() ) ; } } ; private static ReaderWriter intRW = new ReaderWriterBase( "int" ) { public Object read( InputStream is ) { int value = is.read_long() ; return new Integer( value ) ; } public void write( OutputStream os, Object value ) { Integer val = (Integer)value ; os.write_long( val.intValue() ) ; } } ; private static ReaderWriter longRW = new ReaderWriterBase( "long" ) { public Object read( InputStream is ) { long value = is.read_longlong() ; return new Long( value ) ; } public void write( OutputStream os, Object value ) { Long val = (Long)value ; os.write_longlong( val.longValue() ) ; } } ; private static ReaderWriter floatRW = new ReaderWriterBase( "float" ) { public Object read( InputStream is ) { float value = is.read_float() ; return new Float( value ) ; } public void write( OutputStream os, Object value ) { Float val = (Float)value ; os.write_float( val.floatValue() ) ; } } ; private static ReaderWriter doubleRW = new ReaderWriterBase( "double" ) { public Object read( InputStream is ) { double value = is.read_double() ; return new Double( value ) ; } public void write( OutputStream os, Object value ) { Double val = (Double)value ; os.write_double( val.doubleValue() ) ; } } ; private static ReaderWriter corbaObjectRW = new ReaderWriterBase( "org.omg.CORBA.Object" ) { public Object read( InputStream is ) { return is.read_Object() ; } public void write( OutputStream os, Object value ) { os.write_Object( (org.omg.CORBA.Object)value ) ; } } ; private static ReaderWriter anyRW = new ReaderWriterBase( "any" ) { public Object read( InputStream is ) { return Util.readAny(is) ; } public void write( OutputStream os, Object value ) { Util.writeAny( os, value ) ; } } ; private static ReaderWriter abstractInterfaceRW = new ReaderWriterBase( "abstract_interface" ) { public Object read( InputStream is ) { return is.read_abstract_interface() ; } public void write( OutputStream os, Object value ) { Util.writeAbstractObject( os, value ) ; } } ; public static ReaderWriter makeReaderWriter( final Class cls ) { if (cls.equals( boolean.class )) return booleanRW ; else if (cls.equals( byte.class )) return byteRW ; else if (cls.equals( char.class )) return charRW ; else if (cls.equals( short.class )) return shortRW ; else if (cls.equals( int.class )) return intRW ; else if (cls.equals( long.class )) return longRW ; else if (cls.equals( float.class )) return floatRW ; else if (cls.equals( double.class )) return doubleRW ; else if (java.rmi.Remote.class.isAssignableFrom( cls )) return new ReaderWriterBase( "remote(" + cls.getName() + ")" ) { public Object read( InputStream is ) { return PortableRemoteObject.narrow( is.read_Object(), cls ) ; } public void write( OutputStream os, Object value ) { Util.writeRemoteObject( os, value ) ; } } ; else if (cls.equals(org.omg.CORBA.Object.class)) return corbaObjectRW ; else if (org.omg.CORBA.Object.class.isAssignableFrom( cls )) return new ReaderWriterBase( "org.omg.CORBA.Object(" + cls.getName() + ")" ) { public Object read( InputStream is ) { return is.read_Object(cls) ; } public void write( OutputStream os, Object value ) { os.write_Object( (org.omg.CORBA.Object)value ) ; } } ; else if (isAnyClass(cls)) return anyRW ; else if (isAbstractInterface(cls)) return abstractInterfaceRW ; // For anything else, just read it as a value type. return new ReaderWriterBase( "value(" + cls.getName() + ")" ) { public Object read( InputStream is ) { return is.read_value(cls) ; } public void write( OutputStream os, Object value ) { os.write_value( (Serializable)value, cls ) ; } } ; } public DynamicMethodMarshallerImpl( Method method ) { this.method = method ; ehandler = new ExceptionHandlerImpl( method.getExceptionTypes() ) ; needsArgumentCopy = false ; Class[] argTypes = method.getParameterTypes() ; hasArguments = argTypes.length > 0 ; if (hasArguments) { argRWs = new ReaderWriter[ argTypes.length ] ; for (int ctr=0; ctr<argTypes.length; ctr++ ) { // This could be further optimized to avoid // copying if argTypes contains at most one // immutable object type. if (!argTypes[ctr].isPrimitive()) needsArgumentCopy = true ; argRWs[ctr] = makeReaderWriter( argTypes[ctr] ) ; } } Class resultType = method.getReturnType() ; needsResultCopy = false ; hasVoidResult = resultType.equals( void.class ) ; if (!hasVoidResult) { needsResultCopy = !resultType.isPrimitive() ; resultRW = makeReaderWriter( resultType ) ; } } public Method getMethod() { return method ; } public Object[] copyArguments( Object[] args, ORB orb ) throws RemoteException { if (needsArgumentCopy) return Util.copyObjects( args, orb ) ; else return args ; } public Object[] readArguments( InputStream is ) { Object[] result = null ; if (hasArguments) { result = new Object[ argRWs.length ] ; for (int ctr=0; ctr<argRWs.length; ctr++ ) result[ctr] = argRWs[ctr].read( is ) ; } return result ; } public void writeArguments( OutputStream os, Object[] args ) { if (hasArguments) { if (args.length != argRWs.length) throw new IllegalArgumentException( "Expected " + argRWs.length + " arguments, but got " + args.length + " arguments." ) ; for (int ctr=0; ctr<argRWs.length; ctr++ ) argRWs[ctr].write( os, args[ctr] ) ; } } public Object copyResult( Object result, ORB orb ) throws RemoteException { if (needsResultCopy) return Util.copyObject( result, orb ) ; else return result ; } public Object readResult( InputStream is ) { if (hasVoidResult) return null ; else return resultRW.read( is ) ; } public void writeResult( OutputStream os, Object result ) { if (!hasVoidResult) resultRW.write( os, result ) ; } public boolean isDeclaredException( Throwable thr ) { return ehandler.isDeclaredException( thr.getClass() ) ; } public void writeException( OutputStream os, Exception ex ) { ehandler.writeException( os, ex ) ; } public Exception readException( ApplicationException ae ) { return ehandler.readException( ae ) ; } }