ExceptionHandlerImpl.java revision 608:7e06bf1dcb09
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
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 java.rmi.RemoteException ;
35import java.rmi.UnexpectedException ;
36
37import org.omg.CORBA.UserException ;
38
39import org.omg.CORBA_2_3.portable.InputStream ;
40import org.omg.CORBA_2_3.portable.OutputStream ;
41import org.omg.CORBA.portable.ApplicationException ;
42
43import java.lang.reflect.Method ;
44
45import com.sun.corba.se.spi.logging.CORBALogDomains ;
46import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
47
48public 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}
296