1 /* 2 * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.corba.se.impl.presentation.rmi ; 27 28 import java.io.Serializable ; 29 import java.io.Externalizable ; 30 31 import javax.rmi.PortableRemoteObject ; 32 import javax.rmi.CORBA.Util ; 33 34 import org.omg.CORBA.portable.IDLEntity ; 35 36 import org.omg.CORBA_2_3.portable.InputStream ; 37 import org.omg.CORBA_2_3.portable.OutputStream ; 38 import org.omg.CORBA.portable.ApplicationException ; 39 40 import java.lang.reflect.Method ; 41 42 import java.rmi.RemoteException ; 43 44 import com.sun.corba.se.spi.orb.ORB ; 45 46 import com.sun.corba.se.spi.presentation.rmi.DynamicMethodMarshaller ; 47 48 public class DynamicMethodMarshallerImpl implements DynamicMethodMarshaller 49 { 50 Method method ; 51 ExceptionHandler ehandler ; 52 boolean hasArguments = true ; 53 boolean hasVoidResult = true ; 54 boolean needsArgumentCopy ; // true if copyObjects call needs for args 55 boolean needsResultCopy ; // true if copyObject call needs for result 56 ReaderWriter[] argRWs = null ; 57 ReaderWriter resultRW = null ; 58 59 private static boolean isAnyClass( Class cls ) 60 { 61 return cls.equals( Object.class ) || cls.equals( Serializable.class ) || 62 cls.equals( Externalizable.class ) ; 63 } 64 65 // Assume that cls is not Remote, !isAnyClass(cls), and 66 // !org.omg.CORBA.Object.class.isAssignableFrom( cls ). 67 // Then return whether cls is an RMI-IIOP abstract interface. 68 private static boolean isAbstractInterface( Class cls ) 69 { 70 // Either cls is an interface that extends IDLEntity, or else 71 // cls does not extend java.rmi.Remote and all of its methods 72 // throw RemoteException. 73 if (IDLEntity.class.isAssignableFrom( cls )) 74 return cls.isInterface() ; 75 else 76 return cls.isInterface() && allMethodsThrowRemoteException( cls ) ; 77 } 78 79 private static boolean allMethodsThrowRemoteException( Class cls ) 80 { 81 Method[] methods = cls.getMethods() ; 82 83 // Check that all methods (other than those declared in java.lang.Object) 84 // throw an exception that is a subclass of RemoteException. 85 for (int ctr=0; ctr<methods.length; ctr++) { 86 Method method = methods[ctr] ; 87 if (method.getDeclaringClass() != Object.class) 88 if (!throwsRemote( method )) 89 return false ; 90 } 91 92 return true ; 93 } 94 95 private static boolean throwsRemote( Method method ) 96 { 97 Class[] exceptionTypes = method.getExceptionTypes() ; 98 99 // Check that some exceptionType is a subclass of RemoteException 100 for (int ctr=0; ctr<exceptionTypes.length; ctr++) { 101 Class exceptionType = exceptionTypes[ctr] ; 102 if (java.rmi.RemoteException.class.isAssignableFrom( exceptionType )) 103 return true ; 104 } 105 106 return false ; 107 } 108 109 public interface ReaderWriter 110 { 111 Object read( InputStream is ) ; 112 113 void write( OutputStream os, Object value ) ; 114 } 115 116 abstract static class ReaderWriterBase implements ReaderWriter 117 { 118 String name ; 119 120 public ReaderWriterBase( String name ) 121 { 122 this.name = name ; 123 } 124 125 public String toString() 126 { 127 return "ReaderWriter[" + name + "]" ; 128 } 129 } 130 131 private static ReaderWriter booleanRW = new ReaderWriterBase( "boolean" ) 132 { 133 public Object read( InputStream is ) 134 { 135 return is.read_boolean() ; 136 } 137 138 public void write( OutputStream os, Object value ) 139 { 140 Boolean val = (Boolean)value ; 141 os.write_boolean( val.booleanValue() ) ; 142 } 143 } ; 144 145 private static ReaderWriter byteRW = new ReaderWriterBase( "byte" ) 146 { 147 public Object read( InputStream is ) 148 { 149 byte value = is.read_octet() ; 150 return new Byte( value ) ; 151 } 152 153 public void write( OutputStream os, Object value ) 154 { 155 Byte val = (Byte)value ; 156 os.write_octet( val.byteValue() ) ; 157 } 158 } ; 159 160 private static ReaderWriter charRW = new ReaderWriterBase( "char" ) 161 { 162 public Object read( InputStream is ) 163 { 164 char value = is.read_wchar() ; 165 return new Character( value ) ; 166 } 167 168 public void write( OutputStream os, Object value ) 169 { 170 Character val = (Character)value ; 171 os.write_wchar( val.charValue() ) ; 172 } 173 } ; 174 175 private static ReaderWriter shortRW = new ReaderWriterBase( "short" ) 176 { 177 public Object read( InputStream is ) 178 { 179 short value = is.read_short() ; 180 return new Short( value ) ; 181 } 182 183 public void write( OutputStream os, Object value ) 184 { 185 Short val = (Short)value ; 186 os.write_short( val.shortValue() ) ; 187 } 188 } ; 189 190 private static ReaderWriter intRW = new ReaderWriterBase( "int" ) 191 { 192 public Object read( InputStream is ) 193 { 194 int value = is.read_long() ; 195 return new Integer( value ) ; 196 } 197 198 public void write( OutputStream os, Object value ) 199 { 200 Integer val = (Integer)value ; 201 os.write_long( val.intValue() ) ; 202 } 203 } ; 204 205 private static ReaderWriter longRW = new ReaderWriterBase( "long" ) 206 { 207 public Object read( InputStream is ) 208 { 209 long value = is.read_longlong() ; 210 return new Long( value ) ; 211 } 212 213 public void write( OutputStream os, Object value ) 214 { 215 Long val = (Long)value ; 216 os.write_longlong( val.longValue() ) ; 217 } 218 } ; 219 220 private static ReaderWriter floatRW = new ReaderWriterBase( "float" ) 221 { 222 public Object read( InputStream is ) 223 { 224 float value = is.read_float() ; 225 return new Float( value ) ; 226 } 227 228 public void write( OutputStream os, Object value ) 229 { 230 Float val = (Float)value ; 231 os.write_float( val.floatValue() ) ; 232 } 233 } ; 234 235 private static ReaderWriter doubleRW = new ReaderWriterBase( "double" ) 236 { 237 public Object read( InputStream is ) 238 { 239 double value = is.read_double() ; 240 return new Double( value ) ; 241 } 242 243 public void write( OutputStream os, Object value ) 244 { 245 Double val = (Double)value ; 246 os.write_double( val.doubleValue() ) ; 247 } 248 } ; 249 250 private static ReaderWriter corbaObjectRW = new ReaderWriterBase( 251 "org.omg.CORBA.Object" ) 252 { 253 public Object read( InputStream is ) 254 { 255 return is.read_Object() ; 256 } 257 258 public void write( OutputStream os, Object value ) 259 { 260 os.write_Object( (org.omg.CORBA.Object)value ) ; 261 } 262 } ; 263 264 private static ReaderWriter anyRW = new ReaderWriterBase( "any" ) 265 { 266 public Object read( InputStream is ) 267 { 268 return Util.readAny(is) ; 269 } 270 271 public void write( OutputStream os, Object value ) 272 { 273 Util.writeAny( os, value ) ; 274 } 275 } ; 276 277 private static ReaderWriter abstractInterfaceRW = new ReaderWriterBase( 278 "abstract_interface" ) 279 { 280 public Object read( InputStream is ) 281 { 282 return is.read_abstract_interface() ; 283 } 284 285 public void write( OutputStream os, Object value ) 286 { 287 Util.writeAbstractObject( os, value ) ; 288 } 289 } ; 290 291 292 public static ReaderWriter makeReaderWriter( final Class cls ) 293 { 294 if (cls.equals( boolean.class )) 295 return booleanRW ; 296 else if (cls.equals( byte.class )) 297 return byteRW ; 298 else if (cls.equals( char.class )) 299 return charRW ; 300 else if (cls.equals( short.class )) 301 return shortRW ; 302 else if (cls.equals( int.class )) 303 return intRW ; 304 else if (cls.equals( long.class )) 305 return longRW ; 306 else if (cls.equals( float.class )) 307 return floatRW ; 308 else if (cls.equals( double.class )) 309 return doubleRW ; 310 else if (java.rmi.Remote.class.isAssignableFrom( cls )) 311 return new ReaderWriterBase( "remote(" + cls.getName() + ")" ) 312 { 313 public Object read( InputStream is ) 314 { 315 return PortableRemoteObject.narrow( is.read_Object(), 316 cls ) ; 317 } 318 319 public void write( OutputStream os, Object value ) 320 { 321 Util.writeRemoteObject( os, value ) ; 322 } 323 } ; 324 else if (cls.equals(org.omg.CORBA.Object.class)) 325 return corbaObjectRW ; 326 else if (org.omg.CORBA.Object.class.isAssignableFrom( cls )) 327 return new ReaderWriterBase( "org.omg.CORBA.Object(" + 328 cls.getName() + ")" ) 329 { 330 public Object read( InputStream is ) 331 { 332 return is.read_Object(cls) ; 333 } 334 335 public void write( OutputStream os, Object value ) 336 { 337 os.write_Object( (org.omg.CORBA.Object)value ) ; 338 } 339 } ; 340 else if (isAnyClass(cls)) 341 return anyRW ; 342 else if (isAbstractInterface(cls)) 343 return abstractInterfaceRW ; 344 345 // For anything else, just read it as a value type. 346 return new ReaderWriterBase( "value(" + cls.getName() + ")" ) 347 { 348 public Object read( InputStream is ) 349 { 350 return is.read_value(cls) ; 351 } 352 353 public void write( OutputStream os, Object value ) 354 { 355 os.write_value( (Serializable)value, cls ) ; 356 } 357 } ; 358 } 359 360 public DynamicMethodMarshallerImpl( Method method ) 361 { 362 this.method = method ; 363 ehandler = new ExceptionHandlerImpl( method.getExceptionTypes() ) ; 364 needsArgumentCopy = false ; 365 366 Class[] argTypes = method.getParameterTypes() ; 367 hasArguments = argTypes.length > 0 ; 368 if (hasArguments) { 369 argRWs = new ReaderWriter[ argTypes.length ] ; 370 for (int ctr=0; ctr<argTypes.length; ctr++ ) { 371 // This could be further optimized to avoid 372 // copying if argTypes contains at most one 373 // immutable object type. 374 if (!argTypes[ctr].isPrimitive()) 375 needsArgumentCopy = true ; 376 argRWs[ctr] = makeReaderWriter( argTypes[ctr] ) ; 377 } 378 } 379 380 Class resultType = method.getReturnType() ; 381 needsResultCopy = false ; 382 hasVoidResult = resultType.equals( void.class ) ; 383 if (!hasVoidResult) { 384 needsResultCopy = !resultType.isPrimitive() ; 385 resultRW = makeReaderWriter( resultType ) ; 386 } 387 } 388 389 public Method getMethod() 390 { 391 return method ; 392 } 393 394 public Object[] copyArguments( Object[] args, 395 ORB orb ) throws RemoteException 396 { 397 if (needsArgumentCopy) 398 return Util.copyObjects( args, orb ) ; 399 else 400 return args ; 401 } 402 403 public Object[] readArguments( InputStream is ) 404 { 405 Object[] result = null ; 406 407 if (hasArguments) { 408 result = new Object[ argRWs.length ] ; 409 for (int ctr=0; ctr<argRWs.length; ctr++ ) 410 result[ctr] = argRWs[ctr].read( is ) ; 411 } 412 413 return result ; 414 } 415 416 public void writeArguments( OutputStream os, Object[] args ) 417 { 418 if (hasArguments) { 419 if (args.length != argRWs.length) 420 throw new IllegalArgumentException( "Expected " + argRWs.length + 421 " arguments, but got " + args.length + " arguments." ) ; 422 423 for (int ctr=0; ctr<argRWs.length; ctr++ ) 424 argRWs[ctr].write( os, args[ctr] ) ; 425 } 426 } 427 428 public Object copyResult( Object result, ORB orb ) throws RemoteException 429 { 430 if (needsResultCopy) 431 return Util.copyObject( result, orb ) ; 432 else 433 return result ; 434 } 435 436 public Object readResult( InputStream is ) 437 { 438 if (hasVoidResult) 439 return null ; 440 else 441 return resultRW.read( is ) ; 442 } 443 444 public void writeResult( OutputStream os, Object result ) 445 { 446 if (!hasVoidResult) 447 resultRW.write( os, result ) ; 448 } 449 450 public boolean isDeclaredException( Throwable thr ) 451 { 452 return ehandler.isDeclaredException( thr.getClass() ) ; 453 } 454 455 public void writeException( OutputStream os, Exception ex ) 456 { 457 ehandler.writeException( os, ex ) ; 458 } 459 460 public Exception readException( ApplicationException ae ) 461 { 462 return ehandler.readException( ae ) ; 463 } 464 }