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