KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > iiop > rmi > marshal > strategy > SkeletonStrategy


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.iiop.rmi.marshal.strategy;
23
24 import java.lang.reflect.Method JavaDoc;
25
26 import java.rmi.RemoteException JavaDoc;
27
28 import org.omg.CORBA.UserException JavaDoc;
29 import org.omg.CORBA.portable.IDLEntity JavaDoc;
30 import org.omg.CORBA.portable.UnknownException JavaDoc;
31 import org.omg.CORBA_2_3.portable.InputStream JavaDoc;
32 import org.omg.CORBA_2_3.portable.OutputStream JavaDoc;
33
34 import org.jboss.iiop.rmi.ExceptionAnalysis;
35 import org.jboss.iiop.rmi.RMIIIOPViolationException;
36
37 import org.jboss.iiop.rmi.marshal.CDRStream;
38 import org.jboss.iiop.rmi.marshal.CDRStreamReader;
39 import org.jboss.iiop.rmi.marshal.CDRStreamWriter;
40
41 /**
42  * A <code>SkeletonStrategy</code> for a given method knows how to
43  * unmarshalthe sequence of method parameters from a CDR input stream, how to
44  * marshal into a CDR output stream the return value of the method, and how to
45  * marshal into a CDR output stream any exception thrown by the method.
46  *
47  * @author <a HREF="mailto:reverbel@ime.usp.br">Francisco Reverbel</a>
48  * @version $Revision: 37459 $
49  */

50 public class SkeletonStrategy
51 {
52    /**
53     * Each <code>CDRStreamReader</code> in the array unmarshals a method
54     * parameter.
55     */

56    private CDRStreamReader[] paramReaders;
57
58    /**
59     * A <code>Method</code> instance.
60     */

61    private Method JavaDoc m;
62
63    /**
64     * Each <code>ExceptionWriter</code> in the array knows how to marshal
65     * an exception that may be thrown be the method. The array is sorted so
66     * that no writer for a derived exception appears after the base
67     * exception writer.
68     */

69    private ExceptionWriter[] excepWriters;
70
71    /**
72     * A <code>CDRStreamWriter</code> that marshals the return value of the
73     * method.
74     */

75    private CDRStreamWriter retvalWriter;
76
77    // Public -----------------------------------------------------------------
78

79    /*
80     * Constructs a <code>SkeletonStrategy</code> for a given method.
81     */

82    public SkeletonStrategy(Method JavaDoc m)
83    {
84       // Keep the method
85
this.m = m;
86
87       // Initialize paramReaders
88
Class JavaDoc[] paramTypes = m.getParameterTypes();
89       int len = paramTypes.length;
90       paramReaders = new CDRStreamReader[len];
91       for (int i = 0; i < len; i++) {
92             paramReaders[i] = CDRStream.readerFor(paramTypes[i]);
93       }
94
95       // Initialize excepWriters
96
Class JavaDoc[] excepTypes = m.getExceptionTypes();
97       len = excepTypes.length;
98       int n = 0;
99       for (int i = 0; i < len; i++) {
100          if (!RemoteException JavaDoc.class.isAssignableFrom(excepTypes[i])) {
101             n++;
102          }
103       }
104       excepWriters = new ExceptionWriter[n];
105       int j = 0;
106       for (int i = 0; i < len; i++) {
107          if (!RemoteException JavaDoc.class.isAssignableFrom(excepTypes[i])) {
108             excepWriters[j++] = new ExceptionWriter(excepTypes[i]);
109          }
110       }
111       ExceptionWriter.arraysort(excepWriters);
112
113       // Initialize retvalWriter
114
retvalWriter = CDRStream.writerFor(m.getReturnType());
115    }
116
117    /**
118     * Unmarshals the sequence of method parameters from an input stream.
119     *
120     * @param in a CDR input stream
121     * @return an object array with the parameters.
122     */

123    public Object JavaDoc[] readParams(InputStream JavaDoc in)
124    {
125       int len = paramReaders.length;
126       Object JavaDoc[] params = new Object JavaDoc[len];
127       for (int i = 0; i < len; i++ ) {
128          params[i] = paramReaders[i].read(in);
129       }
130       return params;
131    }
132    
133    /**
134     * Returns this <code>SkeletonStrategy</code>'s method.
135     */

136    public Method JavaDoc getMethod()
137    {
138       return m;
139    }
140
141    /**
142     * Returns true if this <code>SkeletonStrategy</code>'s method
143     * is non void.
144     */

145    public boolean isNonVoid()
146    {
147       return (retvalWriter != null);
148    }
149
150    /**
151     * Marshals into an output stream the return value of the method.
152     *
153     * @param out a CDR output stream
154     * @param retVal the value to be written.
155     */

156    public void writeRetval(OutputStream JavaDoc out, Object JavaDoc retVal)
157    {
158       retvalWriter.write(out, retVal);
159    }
160
161    /**
162     * Marshals into an output stream an exception thrown by the method.
163     *
164     * @param out a CDR output stream
165     * @param e the exception to be written.
166     */

167    public void writeException(OutputStream JavaDoc out, Exception JavaDoc e)
168    {
169       int len = excepWriters.length;
170       for (int i = 0; i < len; i++) {
171          if (excepWriters[i].getExceptionClass().isInstance(e)) {
172             excepWriters[i].write(out, e);
173             return;
174          }
175       }
176       throw new UnknownException JavaDoc(e);
177    }
178
179    // Static inner class (private) --------------------------------------------
180

181    /**
182     * An <code>ExceptionWriter</code> knows how to write exceptions of a given
183     * class to a CDR output stream.
184     */

185    private static class ExceptionWriter
186          implements CDRStreamWriter
187    {
188       /**
189        * The exception class.
190        */

191       private Class JavaDoc clz;
192   
193       /*
194        * If the exception class corresponds to an IDL-defined exception, this
195        * field contains the write method of the associated helper class.
196        * A null value indicates that the exception class does not correspond
197        * to an IDL-defined exception.
198        */

199       private java.lang.reflect.Method JavaDoc writeMethod = null;
200
201       /**
202        * The CORBA repository id of the exception class. (This field is used
203        * if the exception class does not correspond to an IDL-defined
204        * exception. An IDL-generated helper class provides the repository id
205        * of an IDL-defined exception.)
206        */

207       private String JavaDoc reposId;
208       
209       /**
210        * Constructs an <code>ExceptionWriter</code> for a given exception
211        * class.
212        */

213       ExceptionWriter(Class JavaDoc clz)
214       {
215          this.clz = clz;
216          if (IDLEntity JavaDoc.class.isAssignableFrom(clz)
217              && UserException JavaDoc.class.isAssignableFrom(clz)) {
218
219             // This ExceptionWriter corresponds to an IDL-defined exception
220
String JavaDoc helperClassName = clz.getName() + "Helper";
221             try {
222                Class JavaDoc helperClass =
223                   clz.getClassLoader().loadClass(helperClassName);
224                Class JavaDoc[] paramTypes =
225                   { org.omg.CORBA.portable.OutputStream JavaDoc.class, clz };
226                writeMethod = helperClass.getMethod("write", paramTypes);
227             }
228             catch (ClassNotFoundException JavaDoc e) {
229                throw new RuntimeException JavaDoc("Error loading class "
230                                           + helperClassName + ": " + e);
231             }
232             catch (NoSuchMethodException JavaDoc e) {
233                 throw new RuntimeException JavaDoc("No write method in helper class "
234                                            + helperClassName + ": " + e);
235             }
236              
237          }
238          else {
239             // This ExceptionWriter does not correspond to an IDL-defined
240
// exception
241
try {
242                this.reposId = ExceptionAnalysis.getExceptionAnalysis(clz)
243                   .getExceptionRepositoryId();
244             }
245             catch (RMIIIOPViolationException e) {
246                throw new RuntimeException JavaDoc("Cannot obtain "
247                                           + "exception repository id for "
248                                           + clz.getName() + ":\n" + e);
249             }
250          }
251       }
252       
253       /**
254        * Gets the exception <code>Class</code>.
255        */

256       Class JavaDoc getExceptionClass()
257       {
258          return clz;
259       }
260       
261       /**
262        * Writes an exception to a CDR output stream.
263        */

264       public void write(OutputStream JavaDoc out, Object JavaDoc excep)
265       {
266          if (writeMethod != null) {
267             try {
268                writeMethod.invoke(null, new Object JavaDoc[] { out, excep });
269             }
270             catch (IllegalAccessException JavaDoc e) {
271                throw new RuntimeException JavaDoc("Internal error: " + e);
272             }
273             catch (java.lang.reflect.InvocationTargetException JavaDoc e) {
274                throw new RuntimeException JavaDoc("Exception marshaling IDLEntity: "
275                                           + e.getTargetException());
276             }
277          }
278          else {
279             out.write_string(reposId);
280             out.write_value((Exception JavaDoc)excep, clz);
281          }
282       }
283       
284       /**
285        * Sorts an <code>ExceptionWriter</code> array so that no derived
286        * exception strategy appears after a base exception strategy.
287        */

288       static void arraysort(ExceptionWriter[] a)
289       {
290          int len = a.length;
291          
292          for (int i = 0; i < len - 1; i++) {
293             for (int j = i + 1; j < len; j++) {
294                if (a[i].clz.isAssignableFrom(a[j].clz)) {
295                   ExceptionWriter tmp = a[i];
296                   
297                   a[i] = a[j];
298                   a[j] = tmp;
299                }
300             }
301          }
302       }
303       
304    } // end of inner class ExceptionWriter
305

306 }
307
Popular Tags