1. /*
  2. * @(#)ExceptionHandlerImpl.java 1.10 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 java.rmi.RemoteException ;
  13. import java.rmi.UnexpectedException ;
  14. import org.omg.CORBA.UserException ;
  15. import org.omg.CORBA_2_3.portable.InputStream ;
  16. import org.omg.CORBA_2_3.portable.OutputStream ;
  17. import org.omg.CORBA.portable.ApplicationException ;
  18. import java.lang.reflect.Method ;
  19. import com.sun.corba.se.spi.logging.CORBALogDomains ;
  20. import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
  21. public class ExceptionHandlerImpl implements ExceptionHandler
  22. {
  23. private ExceptionRW[] rws ;
  24. private final ORBUtilSystemException wrapper ;
  25. ///////////////////////////////////////////////////////////////////////////////
  26. // ExceptionRW interface and implementations.
  27. // Used to read and write exceptions.
  28. ///////////////////////////////////////////////////////////////////////////////
  29. public interface ExceptionRW
  30. {
  31. Class getExceptionClass() ;
  32. String getId() ;
  33. void write( OutputStream os, Exception ex ) ;
  34. Exception read( InputStream is ) ;
  35. }
  36. public abstract class ExceptionRWBase implements ExceptionRW
  37. {
  38. private Class cls ;
  39. private String id ;
  40. public ExceptionRWBase( Class cls )
  41. {
  42. this.cls = cls ;
  43. }
  44. public Class getExceptionClass()
  45. {
  46. return cls ;
  47. }
  48. public String getId()
  49. {
  50. return id ;
  51. }
  52. void setId( String id )
  53. {
  54. this.id = id ;
  55. }
  56. }
  57. public class ExceptionRWIDLImpl extends ExceptionRWBase
  58. {
  59. private Method readMethod ;
  60. private Method writeMethod ;
  61. public ExceptionRWIDLImpl( Class cls )
  62. {
  63. super( cls ) ;
  64. String helperName = cls.getName() + "Helper" ;
  65. ClassLoader loader = cls.getClassLoader() ;
  66. Class helperClass ;
  67. try {
  68. helperClass = Class.forName( helperName, true, loader ) ;
  69. Method idMethod = helperClass.getDeclaredMethod( "id", null ) ;
  70. setId( (String)idMethod.invoke( null, null ) ) ;
  71. } catch (Exception ex) {
  72. throw wrapper.badHelperIdMethod( ex, helperName ) ;
  73. }
  74. try {
  75. Class[] argTypes = new Class[] {
  76. org.omg.CORBA.portable.OutputStream.class, cls } ;
  77. writeMethod = helperClass.getDeclaredMethod( "write",
  78. argTypes ) ;
  79. } catch (Exception ex) {
  80. throw wrapper.badHelperWriteMethod( ex, helperName ) ;
  81. }
  82. try {
  83. Class[] argTypes = new Class[] {
  84. org.omg.CORBA.portable.InputStream.class } ;
  85. readMethod = helperClass.getDeclaredMethod( "read", argTypes ) ;
  86. } catch (Exception ex) {
  87. throw wrapper.badHelperReadMethod( ex, helperName ) ;
  88. }
  89. }
  90. public void write( OutputStream os, Exception ex )
  91. {
  92. try {
  93. Object[] args = new Object[] { os, ex } ;
  94. writeMethod.invoke( null, args ) ;
  95. } catch (Exception exc) {
  96. throw wrapper.badHelperWriteMethod( exc,
  97. writeMethod.getDeclaringClass().getName() ) ;
  98. }
  99. }
  100. public Exception read( InputStream is )
  101. {
  102. try {
  103. Object[] args = new Object[] { is } ;
  104. return (Exception)readMethod.invoke( null, args ) ;
  105. } catch (Exception ex) {
  106. throw wrapper.badHelperReadMethod( ex,
  107. readMethod.getDeclaringClass().getName() ) ;
  108. }
  109. }
  110. }
  111. public class ExceptionRWRMIImpl extends ExceptionRWBase
  112. {
  113. public ExceptionRWRMIImpl( Class cls )
  114. {
  115. super( cls ) ;
  116. setId( IDLNameTranslatorImpl.getExceptionId( cls ) ) ;
  117. }
  118. public void write( OutputStream os, Exception ex )
  119. {
  120. os.write_string( getId() ) ;
  121. os.write_value( ex, getExceptionClass() ) ;
  122. }
  123. public Exception read( InputStream is )
  124. {
  125. is.read_string() ; // read and ignore!
  126. return (Exception)is.read_value( getExceptionClass() ) ;
  127. }
  128. }
  129. ///////////////////////////////////////////////////////////////////////////////
  130. public ExceptionHandlerImpl( Class[] exceptions )
  131. {
  132. wrapper = ORBUtilSystemException.get(
  133. CORBALogDomains.RPC_PRESENTATION ) ;
  134. int count = 0 ;
  135. for (int ctr=0; ctr<exceptions.length; ctr++) {
  136. Class cls = exceptions[ctr] ;
  137. if (!RemoteException.class.isAssignableFrom(cls))
  138. count++ ;
  139. }
  140. rws = new ExceptionRW[count] ;
  141. int index = 0 ;
  142. for (int ctr=0; ctr<exceptions.length; ctr++) {
  143. Class cls = exceptions[ctr] ;
  144. if (!RemoteException.class.isAssignableFrom(cls)) {
  145. ExceptionRW erw = null ;
  146. if (UserException.class.isAssignableFrom(cls))
  147. erw = new ExceptionRWIDLImpl( cls ) ;
  148. else
  149. erw = new ExceptionRWRMIImpl( cls ) ;
  150. /* The following check is not performed
  151. * in order to maintain compatibility with
  152. * rmic. See bug 4989312.
  153. // Check for duplicate repository ID
  154. String repositoryId = erw.getId() ;
  155. int duplicateIndex = findDeclaredException( repositoryId ) ;
  156. if (duplicateIndex > 0) {
  157. ExceptionRW duprw = rws[duplicateIndex] ;
  158. String firstClassName =
  159. erw.getExceptionClass().getName() ;
  160. String secondClassName =
  161. duprw.getExceptionClass().getName() ;
  162. throw wrapper.duplicateExceptionRepositoryId(
  163. firstClassName, secondClassName, repositoryId ) ;
  164. }
  165. */
  166. rws[index++] = erw ;
  167. }
  168. }
  169. }
  170. private int findDeclaredException( Class cls )
  171. {
  172. for (int ctr = 0; ctr < rws.length; ctr++) {
  173. Class next = rws[ctr].getExceptionClass() ;
  174. if (next.isAssignableFrom(cls))
  175. return ctr ;
  176. }
  177. return -1 ;
  178. }
  179. private int findDeclaredException( String repositoryId )
  180. {
  181. for (int ctr=0; ctr<rws.length; ctr++) {
  182. // This may occur when rws has not been fully
  183. // populated, in which case the search should just fail.
  184. if (rws[ctr]==null)
  185. return -1 ;
  186. String rid = rws[ctr].getId() ;
  187. if (repositoryId.equals( rid ))
  188. return ctr ;
  189. }
  190. return -1 ;
  191. }
  192. public boolean isDeclaredException( Class cls )
  193. {
  194. return findDeclaredException( cls ) >= 0 ;
  195. }
  196. public void writeException( OutputStream os, Exception ex )
  197. {
  198. int index = findDeclaredException( ex.getClass() ) ;
  199. if (index < 0)
  200. throw wrapper.writeUndeclaredException( ex,
  201. ex.getClass().getName() ) ;
  202. rws[index].write( os, ex ) ;
  203. }
  204. public Exception readException( ApplicationException ae )
  205. {
  206. // Note that the exception ID is present in both ae
  207. // and in the input stream from ae. The exception
  208. // reader must actually read the exception ID from
  209. // the stream.
  210. InputStream is = (InputStream)ae.getInputStream() ;
  211. String excName = ae.getId() ;
  212. int index = findDeclaredException( excName ) ;
  213. if (index < 0) {
  214. excName = is.read_string() ;
  215. Exception res = new UnexpectedException( excName ) ;
  216. res.initCause( ae ) ;
  217. return res ;
  218. }
  219. return rws[index].read( is ) ;
  220. }
  221. // This is here just for the dynamicrmiiiop test
  222. public ExceptionRW getRMIExceptionRW( Class cls )
  223. {
  224. return new ExceptionRWRMIImpl( cls ) ;
  225. }
  226. }