DynamicMethodMarshallerImpl.java revision 608:7e06bf1dcb09
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 26package com.sun.corba.se.impl.presentation.rmi ; 27 28import java.io.Serializable ; 29import java.io.Externalizable ; 30 31import javax.rmi.PortableRemoteObject ; 32import javax.rmi.CORBA.Util ; 33 34import org.omg.CORBA.portable.IDLEntity ; 35 36import org.omg.CORBA_2_3.portable.InputStream ; 37import org.omg.CORBA_2_3.portable.OutputStream ; 38import org.omg.CORBA.portable.ApplicationException ; 39 40import java.lang.reflect.Method ; 41 42import java.rmi.RemoteException ; 43 44import com.sun.corba.se.spi.orb.ORB ; 45 46import com.sun.corba.se.spi.presentation.rmi.DynamicMethodMarshaller ; 47 48public 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 boolean value = is.read_boolean() ; 136 return new Boolean( value ) ; 137 } 138 139 public void write( OutputStream os, Object value ) 140 { 141 Boolean val = (Boolean)value ; 142 os.write_boolean( val.booleanValue() ) ; 143 } 144 } ; 145 146 private static ReaderWriter byteRW = new ReaderWriterBase( "byte" ) 147 { 148 public Object read( InputStream is ) 149 { 150 byte value = is.read_octet() ; 151 return new Byte( value ) ; 152 } 153 154 public void write( OutputStream os, Object value ) 155 { 156 Byte val = (Byte)value ; 157 os.write_octet( val.byteValue() ) ; 158 } 159 } ; 160 161 private static ReaderWriter charRW = new ReaderWriterBase( "char" ) 162 { 163 public Object read( InputStream is ) 164 { 165 char value = is.read_wchar() ; 166 return new Character( value ) ; 167 } 168 169 public void write( OutputStream os, Object value ) 170 { 171 Character val = (Character)value ; 172 os.write_wchar( val.charValue() ) ; 173 } 174 } ; 175 176 private static ReaderWriter shortRW = new ReaderWriterBase( "short" ) 177 { 178 public Object read( InputStream is ) 179 { 180 short value = is.read_short() ; 181 return new Short( value ) ; 182 } 183 184 public void write( OutputStream os, Object value ) 185 { 186 Short val = (Short)value ; 187 os.write_short( val.shortValue() ) ; 188 } 189 } ; 190 191 private static ReaderWriter intRW = new ReaderWriterBase( "int" ) 192 { 193 public Object read( InputStream is ) 194 { 195 int value = is.read_long() ; 196 return new Integer( value ) ; 197 } 198 199 public void write( OutputStream os, Object value ) 200 { 201 Integer val = (Integer)value ; 202 os.write_long( val.intValue() ) ; 203 } 204 } ; 205 206 private static ReaderWriter longRW = new ReaderWriterBase( "long" ) 207 { 208 public Object read( InputStream is ) 209 { 210 long value = is.read_longlong() ; 211 return new Long( value ) ; 212 } 213 214 public void write( OutputStream os, Object value ) 215 { 216 Long val = (Long)value ; 217 os.write_longlong( val.longValue() ) ; 218 } 219 } ; 220 221 private static ReaderWriter floatRW = new ReaderWriterBase( "float" ) 222 { 223 public Object read( InputStream is ) 224 { 225 float value = is.read_float() ; 226 return new Float( value ) ; 227 } 228 229 public void write( OutputStream os, Object value ) 230 { 231 Float val = (Float)value ; 232 os.write_float( val.floatValue() ) ; 233 } 234 } ; 235 236 private static ReaderWriter doubleRW = new ReaderWriterBase( "double" ) 237 { 238 public Object read( InputStream is ) 239 { 240 double value = is.read_double() ; 241 return new Double( value ) ; 242 } 243 244 public void write( OutputStream os, Object value ) 245 { 246 Double val = (Double)value ; 247 os.write_double( val.doubleValue() ) ; 248 } 249 } ; 250 251 private static ReaderWriter corbaObjectRW = new ReaderWriterBase( 252 "org.omg.CORBA.Object" ) 253 { 254 public Object read( InputStream is ) 255 { 256 return is.read_Object() ; 257 } 258 259 public void write( OutputStream os, Object value ) 260 { 261 os.write_Object( (org.omg.CORBA.Object)value ) ; 262 } 263 } ; 264 265 private static ReaderWriter anyRW = new ReaderWriterBase( "any" ) 266 { 267 public Object read( InputStream is ) 268 { 269 return Util.readAny(is) ; 270 } 271 272 public void write( OutputStream os, Object value ) 273 { 274 Util.writeAny( os, value ) ; 275 } 276 } ; 277 278 private static ReaderWriter abstractInterfaceRW = new ReaderWriterBase( 279 "abstract_interface" ) 280 { 281 public Object read( InputStream is ) 282 { 283 return is.read_abstract_interface() ; 284 } 285 286 public void write( OutputStream os, Object value ) 287 { 288 Util.writeAbstractObject( os, value ) ; 289 } 290 } ; 291 292 293 public static ReaderWriter makeReaderWriter( final Class cls ) 294 { 295 if (cls.equals( boolean.class )) 296 return booleanRW ; 297 else if (cls.equals( byte.class )) 298 return byteRW ; 299 else if (cls.equals( char.class )) 300 return charRW ; 301 else if (cls.equals( short.class )) 302 return shortRW ; 303 else if (cls.equals( int.class )) 304 return intRW ; 305 else if (cls.equals( long.class )) 306 return longRW ; 307 else if (cls.equals( float.class )) 308 return floatRW ; 309 else if (cls.equals( double.class )) 310 return doubleRW ; 311 else if (java.rmi.Remote.class.isAssignableFrom( cls )) 312 return new ReaderWriterBase( "remote(" + cls.getName() + ")" ) 313 { 314 public Object read( InputStream is ) 315 { 316 return PortableRemoteObject.narrow( is.read_Object(), 317 cls ) ; 318 } 319 320 public void write( OutputStream os, Object value ) 321 { 322 Util.writeRemoteObject( os, value ) ; 323 } 324 } ; 325 else if (cls.equals(org.omg.CORBA.Object.class)) 326 return corbaObjectRW ; 327 else if (org.omg.CORBA.Object.class.isAssignableFrom( cls )) 328 return new ReaderWriterBase( "org.omg.CORBA.Object(" + 329 cls.getName() + ")" ) 330 { 331 public Object read( InputStream is ) 332 { 333 return is.read_Object(cls) ; 334 } 335 336 public void write( OutputStream os, Object value ) 337 { 338 os.write_Object( (org.omg.CORBA.Object)value ) ; 339 } 340 } ; 341 else if (isAnyClass(cls)) 342 return anyRW ; 343 else if (isAbstractInterface(cls)) 344 return abstractInterfaceRW ; 345 346 // For anything else, just read it as a value type. 347 return new ReaderWriterBase( "value(" + cls.getName() + ")" ) 348 { 349 public Object read( InputStream is ) 350 { 351 return is.read_value(cls) ; 352 } 353 354 public void write( OutputStream os, Object value ) 355 { 356 os.write_value( (Serializable)value, cls ) ; 357 } 358 } ; 359 } 360 361 public DynamicMethodMarshallerImpl( Method method ) 362 { 363 this.method = method ; 364 ehandler = new ExceptionHandlerImpl( method.getExceptionTypes() ) ; 365 needsArgumentCopy = false ; 366 367 Class[] argTypes = method.getParameterTypes() ; 368 hasArguments = argTypes.length > 0 ; 369 if (hasArguments) { 370 argRWs = new ReaderWriter[ argTypes.length ] ; 371 for (int ctr=0; ctr<argTypes.length; ctr++ ) { 372 // This could be further optimized to avoid 373 // copying if argTypes contains at most one 374 // immutable object type. 375 if (!argTypes[ctr].isPrimitive()) 376 needsArgumentCopy = true ; 377 argRWs[ctr] = makeReaderWriter( argTypes[ctr] ) ; 378 } 379 } 380 381 Class resultType = method.getReturnType() ; 382 needsResultCopy = false ; 383 hasVoidResult = resultType.equals( void.class ) ; 384 if (!hasVoidResult) { 385 needsResultCopy = !resultType.isPrimitive() ; 386 resultRW = makeReaderWriter( resultType ) ; 387 } 388 } 389 390 public Method getMethod() 391 { 392 return method ; 393 } 394 395 public Object[] copyArguments( Object[] args, 396 ORB orb ) throws RemoteException 397 { 398 if (needsArgumentCopy) 399 return Util.copyObjects( args, orb ) ; 400 else 401 return args ; 402 } 403 404 public Object[] readArguments( InputStream is ) 405 { 406 Object[] result = null ; 407 408 if (hasArguments) { 409 result = new Object[ argRWs.length ] ; 410 for (int ctr=0; ctr<argRWs.length; ctr++ ) 411 result[ctr] = argRWs[ctr].read( is ) ; 412 } 413 414 return result ; 415 } 416 417 public void writeArguments( OutputStream os, Object[] args ) 418 { 419 if (hasArguments) { 420 if (args.length != argRWs.length) 421 throw new IllegalArgumentException( "Expected " + argRWs.length + 422 " arguments, but got " + args.length + " arguments." ) ; 423 424 for (int ctr=0; ctr<argRWs.length; ctr++ ) 425 argRWs[ctr].write( os, args[ctr] ) ; 426 } 427 } 428 429 public Object copyResult( Object result, ORB orb ) throws RemoteException 430 { 431 if (needsResultCopy) 432 return Util.copyObject( result, orb ) ; 433 else 434 return result ; 435 } 436 437 public Object readResult( InputStream is ) 438 { 439 if (hasVoidResult) 440 return null ; 441 else 442 return resultRW.read( is ) ; 443 } 444 445 public void writeResult( OutputStream os, Object result ) 446 { 447 if (!hasVoidResult) 448 resultRW.write( os, result ) ; 449 } 450 451 public boolean isDeclaredException( Throwable thr ) 452 { 453 return ehandler.isDeclaredException( thr.getClass() ) ; 454 } 455 456 public void writeException( OutputStream os, Exception ex ) 457 { 458 ehandler.writeException( os, ex ) ; 459 } 460 461 public Exception readException( ApplicationException ae ) 462 { 463 return ehandler.readException( ae ) ; 464 } 465} 466