1. /*
  2. * @(#)DynamicMethodMarshallerImpl.java 1.12 04/06/21
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.impl.presentation.rmi ;
  8. import java.io.Serializable ;
  9. import java.io.Externalizable ;
  10. import javax.rmi.PortableRemoteObject ;
  11. import javax.rmi.CORBA.Util ;
  12. import org.omg.CORBA.portable.IDLEntity ;
  13. import org.omg.CORBA_2_3.portable.InputStream ;
  14. import org.omg.CORBA_2_3.portable.OutputStream ;
  15. import org.omg.CORBA.portable.ApplicationException ;
  16. import java.lang.reflect.Method ;
  17. import java.rmi.RemoteException ;
  18. import com.sun.corba.se.spi.orb.ORB ;
  19. import com.sun.corba.se.spi.presentation.rmi.DynamicMethodMarshaller ;
  20. public class DynamicMethodMarshallerImpl implements DynamicMethodMarshaller
  21. {
  22. Method method ;
  23. ExceptionHandler ehandler ;
  24. boolean hasArguments = true ;
  25. boolean hasVoidResult = true ;
  26. boolean needsArgumentCopy ; // true if copyObjects call needs for args
  27. boolean needsResultCopy ; // true if copyObject call needs for result
  28. ReaderWriter[] argRWs = null ;
  29. ReaderWriter resultRW = null ;
  30. private static boolean isAnyClass( Class cls )
  31. {
  32. return cls.equals( Object.class ) || cls.equals( Serializable.class ) ||
  33. cls.equals( Externalizable.class ) ;
  34. }
  35. // Assume that cls is not Remote, !isAnyClass(cls), and
  36. // !org.omg.CORBA.Object.class.isAssignableFrom( cls ).
  37. // Then return whether cls is an RMI-IIOP abstract interface.
  38. private static boolean isAbstractInterface( Class cls )
  39. {
  40. // Either cls is an interface that extends IDLEntity, or else
  41. // cls does not extend java.rmi.Remote and all of its methods
  42. // throw RemoteException.
  43. if (IDLEntity.class.isAssignableFrom( cls ))
  44. return cls.isInterface() ;
  45. else
  46. return cls.isInterface() && allMethodsThrowRemoteException( cls ) ;
  47. }
  48. private static boolean allMethodsThrowRemoteException( Class cls )
  49. {
  50. Method[] methods = cls.getMethods() ;
  51. // Check that all methods (other than those declared in java.lang.Object)
  52. // throw an exception that is a subclass of RemoteException.
  53. for (int ctr=0; ctr<methods.length; ctr++) {
  54. Method method = methods[ctr] ;
  55. if (method.getDeclaringClass() != Object.class)
  56. if (!throwsRemote( method ))
  57. return false ;
  58. }
  59. return true ;
  60. }
  61. private static boolean throwsRemote( Method method )
  62. {
  63. Class[] exceptionTypes = method.getExceptionTypes() ;
  64. // Check that some exceptionType is a subclass of RemoteException
  65. for (int ctr=0; ctr<exceptionTypes.length; ctr++) {
  66. Class exceptionType = exceptionTypes[ctr] ;
  67. if (java.rmi.RemoteException.class.isAssignableFrom( exceptionType ))
  68. return true ;
  69. }
  70. return false ;
  71. }
  72. public interface ReaderWriter
  73. {
  74. Object read( InputStream is ) ;
  75. void write( OutputStream os, Object value ) ;
  76. }
  77. abstract static class ReaderWriterBase implements ReaderWriter
  78. {
  79. String name ;
  80. public ReaderWriterBase( String name )
  81. {
  82. this.name = name ;
  83. }
  84. public String toString()
  85. {
  86. return "ReaderWriter[" + name + "]" ;
  87. }
  88. }
  89. private static ReaderWriter booleanRW = new ReaderWriterBase( "boolean" )
  90. {
  91. public Object read( InputStream is )
  92. {
  93. boolean value = is.read_boolean() ;
  94. return new Boolean( value ) ;
  95. }
  96. public void write( OutputStream os, Object value )
  97. {
  98. Boolean val = (Boolean)value ;
  99. os.write_boolean( val.booleanValue() ) ;
  100. }
  101. } ;
  102. private static ReaderWriter byteRW = new ReaderWriterBase( "byte" )
  103. {
  104. public Object read( InputStream is )
  105. {
  106. byte value = is.read_octet() ;
  107. return new Byte( value ) ;
  108. }
  109. public void write( OutputStream os, Object value )
  110. {
  111. Byte val = (Byte)value ;
  112. os.write_octet( val.byteValue() ) ;
  113. }
  114. } ;
  115. private static ReaderWriter charRW = new ReaderWriterBase( "char" )
  116. {
  117. public Object read( InputStream is )
  118. {
  119. char value = is.read_wchar() ;
  120. return new Character( value ) ;
  121. }
  122. public void write( OutputStream os, Object value )
  123. {
  124. Character val = (Character)value ;
  125. os.write_wchar( val.charValue() ) ;
  126. }
  127. } ;
  128. private static ReaderWriter shortRW = new ReaderWriterBase( "short" )
  129. {
  130. public Object read( InputStream is )
  131. {
  132. short value = is.read_short() ;
  133. return new Short( value ) ;
  134. }
  135. public void write( OutputStream os, Object value )
  136. {
  137. Short val = (Short)value ;
  138. os.write_short( val.shortValue() ) ;
  139. }
  140. } ;
  141. private static ReaderWriter intRW = new ReaderWriterBase( "int" )
  142. {
  143. public Object read( InputStream is )
  144. {
  145. int value = is.read_long() ;
  146. return new Integer( value ) ;
  147. }
  148. public void write( OutputStream os, Object value )
  149. {
  150. Integer val = (Integer)value ;
  151. os.write_long( val.intValue() ) ;
  152. }
  153. } ;
  154. private static ReaderWriter longRW = new ReaderWriterBase( "long" )
  155. {
  156. public Object read( InputStream is )
  157. {
  158. long value = is.read_longlong() ;
  159. return new Long( value ) ;
  160. }
  161. public void write( OutputStream os, Object value )
  162. {
  163. Long val = (Long)value ;
  164. os.write_longlong( val.longValue() ) ;
  165. }
  166. } ;
  167. private static ReaderWriter floatRW = new ReaderWriterBase( "float" )
  168. {
  169. public Object read( InputStream is )
  170. {
  171. float value = is.read_float() ;
  172. return new Float( value ) ;
  173. }
  174. public void write( OutputStream os, Object value )
  175. {
  176. Float val = (Float)value ;
  177. os.write_float( val.floatValue() ) ;
  178. }
  179. } ;
  180. private static ReaderWriter doubleRW = new ReaderWriterBase( "double" )
  181. {
  182. public Object read( InputStream is )
  183. {
  184. double value = is.read_double() ;
  185. return new Double( value ) ;
  186. }
  187. public void write( OutputStream os, Object value )
  188. {
  189. Double val = (Double)value ;
  190. os.write_double( val.doubleValue() ) ;
  191. }
  192. } ;
  193. private static ReaderWriter corbaObjectRW = new ReaderWriterBase(
  194. "org.omg.CORBA.Object" )
  195. {
  196. public Object read( InputStream is )
  197. {
  198. return is.read_Object() ;
  199. }
  200. public void write( OutputStream os, Object value )
  201. {
  202. os.write_Object( (org.omg.CORBA.Object)value ) ;
  203. }
  204. } ;
  205. private static ReaderWriter anyRW = new ReaderWriterBase( "any" )
  206. {
  207. public Object read( InputStream is )
  208. {
  209. return Util.readAny(is) ;
  210. }
  211. public void write( OutputStream os, Object value )
  212. {
  213. Util.writeAny( os, value ) ;
  214. }
  215. } ;
  216. private static ReaderWriter abstractInterfaceRW = new ReaderWriterBase(
  217. "abstract_interface" )
  218. {
  219. public Object read( InputStream is )
  220. {
  221. return is.read_abstract_interface() ;
  222. }
  223. public void write( OutputStream os, Object value )
  224. {
  225. Util.writeAbstractObject( os, value ) ;
  226. }
  227. } ;
  228. public static ReaderWriter makeReaderWriter( final Class cls )
  229. {
  230. if (cls.equals( boolean.class ))
  231. return booleanRW ;
  232. else if (cls.equals( byte.class ))
  233. return byteRW ;
  234. else if (cls.equals( char.class ))
  235. return charRW ;
  236. else if (cls.equals( short.class ))
  237. return shortRW ;
  238. else if (cls.equals( int.class ))
  239. return intRW ;
  240. else if (cls.equals( long.class ))
  241. return longRW ;
  242. else if (cls.equals( float.class ))
  243. return floatRW ;
  244. else if (cls.equals( double.class ))
  245. return doubleRW ;
  246. else if (java.rmi.Remote.class.isAssignableFrom( cls ))
  247. return new ReaderWriterBase( "remote(" + cls.getName() + ")" )
  248. {
  249. public Object read( InputStream is )
  250. {
  251. return PortableRemoteObject.narrow( is.read_Object(),
  252. cls ) ;
  253. }
  254. public void write( OutputStream os, Object value )
  255. {
  256. Util.writeRemoteObject( os, value ) ;
  257. }
  258. } ;
  259. else if (cls.equals(org.omg.CORBA.Object.class))
  260. return corbaObjectRW ;
  261. else if (org.omg.CORBA.Object.class.isAssignableFrom( cls ))
  262. return new ReaderWriterBase( "org.omg.CORBA.Object(" +
  263. cls.getName() + ")" )
  264. {
  265. public Object read( InputStream is )
  266. {
  267. return is.read_Object(cls) ;
  268. }
  269. public void write( OutputStream os, Object value )
  270. {
  271. os.write_Object( (org.omg.CORBA.Object)value ) ;
  272. }
  273. } ;
  274. else if (isAnyClass(cls))
  275. return anyRW ;
  276. else if (isAbstractInterface(cls))
  277. return abstractInterfaceRW ;
  278. // For anything else, just read it as a value type.
  279. return new ReaderWriterBase( "value(" + cls.getName() + ")" )
  280. {
  281. public Object read( InputStream is )
  282. {
  283. return is.read_value(cls) ;
  284. }
  285. public void write( OutputStream os, Object value )
  286. {
  287. os.write_value( (Serializable)value, cls ) ;
  288. }
  289. } ;
  290. }
  291. public DynamicMethodMarshallerImpl( Method method )
  292. {
  293. this.method = method ;
  294. ehandler = new ExceptionHandlerImpl( method.getExceptionTypes() ) ;
  295. needsArgumentCopy = false ;
  296. Class[] argTypes = method.getParameterTypes() ;
  297. hasArguments = argTypes.length > 0 ;
  298. if (hasArguments) {
  299. argRWs = new ReaderWriter[ argTypes.length ] ;
  300. for (int ctr=0; ctr<argTypes.length; ctr++ ) {
  301. // This could be further optimized to avoid
  302. // copying if argTypes contains at most one
  303. // immutable object type.
  304. if (!argTypes[ctr].isPrimitive())
  305. needsArgumentCopy = true ;
  306. argRWs[ctr] = makeReaderWriter( argTypes[ctr] ) ;
  307. }
  308. }
  309. Class resultType = method.getReturnType() ;
  310. needsResultCopy = false ;
  311. hasVoidResult = resultType.equals( void.class ) ;
  312. if (!hasVoidResult) {
  313. needsResultCopy = !resultType.isPrimitive() ;
  314. resultRW = makeReaderWriter( resultType ) ;
  315. }
  316. }
  317. public Method getMethod()
  318. {
  319. return method ;
  320. }
  321. public Object[] copyArguments( Object[] args,
  322. ORB orb ) throws RemoteException
  323. {
  324. if (needsArgumentCopy)
  325. return Util.copyObjects( args, orb ) ;
  326. else
  327. return args ;
  328. }
  329. public Object[] readArguments( InputStream is )
  330. {
  331. Object[] result = null ;
  332. if (hasArguments) {
  333. result = new Object[ argRWs.length ] ;
  334. for (int ctr=0; ctr<argRWs.length; ctr++ )
  335. result[ctr] = argRWs[ctr].read( is ) ;
  336. }
  337. return result ;
  338. }
  339. public void writeArguments( OutputStream os, Object[] args )
  340. {
  341. if (hasArguments) {
  342. if (args.length != argRWs.length)
  343. throw new IllegalArgumentException( "Expected " + argRWs.length +
  344. " arguments, but got " + args.length + " arguments." ) ;
  345. for (int ctr=0; ctr<argRWs.length; ctr++ )
  346. argRWs[ctr].write( os, args[ctr] ) ;
  347. }
  348. }
  349. public Object copyResult( Object result, ORB orb ) throws RemoteException
  350. {
  351. if (needsResultCopy)
  352. return Util.copyObject( result, orb ) ;
  353. else
  354. return result ;
  355. }
  356. public Object readResult( InputStream is )
  357. {
  358. if (hasVoidResult)
  359. return null ;
  360. else
  361. return resultRW.read( is ) ;
  362. }
  363. public void writeResult( OutputStream os, Object result )
  364. {
  365. if (!hasVoidResult)
  366. resultRW.write( os, result ) ;
  367. }
  368. public boolean isDeclaredException( Throwable thr )
  369. {
  370. return ehandler.isDeclaredException( thr.getClass() ) ;
  371. }
  372. public void writeException( OutputStream os, Exception ex )
  373. {
  374. ehandler.writeException( os, ex ) ;
  375. }
  376. public Exception readException( ApplicationException ae )
  377. {
  378. return ehandler.readException( ae ) ;
  379. }
  380. }