OSDN Git Service

2003-09-18 Dalibor Topic <robilad@kaffe.org>
[pf3gnuchains/gcc-fork.git] / libjava / gnu / java / rmi / rmic / RMIC.java
1 /*
2   Copyright (c) 1996, 1997, 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10  
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 package gnu.java.rmi.rmic;
39
40 import java.io.File;
41 import java.io.FileWriter;
42 import java.io.PrintWriter;
43 import java.io.IOException;
44 import java.lang.reflect.Method;
45 import java.lang.reflect.Modifier;
46 import java.rmi.RemoteException;
47 import java.util.HashSet;
48 import java.util.Iterator;
49 import java.util.Arrays;
50 import java.util.Set;
51
52 import gnu.java.rmi.server.RMIHashes;
53
54 public class RMIC {
55
56 private String[] args;
57 private int next;
58 private Exception exception;
59
60 private boolean keep = false;
61 private boolean need11Stubs = true;
62 private boolean need12Stubs = true;
63 private boolean compile = true;
64 private boolean verbose;
65 private String destination;
66
67 private PrintWriter out;
68 private TabbedWriter ctrl;
69
70 private Class clazz;
71 private String classname;
72 private String fullclassname;
73 private MethodRef[] remotemethods;
74 private String stubname;
75 private String skelname;
76 private int errorCount = 0;
77
78 private Class mRemoteInterface;
79 public RMIC(String[] a) {
80         args = a;
81 }
82
83 public static void main(String args[]) {
84         RMIC r = new RMIC(args);
85         if (r.run() == false) {
86                 Exception exception = r.getException();
87                 if (exception != null) {
88                         exception.printStackTrace();
89                 }
90                 else {
91                         System.exit(1);
92                 }
93         }
94 }
95
96 public boolean run() {
97         parseOptions();
98         if (next >= args.length) {
99                 error("no class names found");
100         }
101         for (int i = next; i < args.length; i++) {
102                 try {
103                         if (verbose) {
104                                 System.out.println("[Processing class " + args[i] + ".class]");
105                         }
106                         processClass(args[i].replace(File.separatorChar, '.'));
107                 }
108                 catch (Exception e) {
109                         exception = e;
110                         return (false);
111                 }
112         }
113         return (true);
114 }
115
116 private boolean processClass(String classname) throws Exception {
117         errorCount = 0;
118         analyzeClass(classname);
119         if(errorCount > 0) {
120                 System.exit(1);
121         }
122         generateStub();
123         if (need11Stubs) {
124                 generateSkel();
125         }
126         if (compile) {
127                 compile(stubname.replace('.', File.separatorChar) + ".java");
128                 if (need11Stubs) {
129                         compile(skelname.replace('.', File.separatorChar) + ".java");
130                 }
131         }
132         if (!keep) {
133                 (new File(stubname.replace('.', File.separatorChar) + ".java")).delete();
134                 if (need11Stubs) {
135                         (new File(skelname.replace('.', File.separatorChar) + ".java")).delete();
136                 }
137         }
138         return (true);
139 }
140
141 private void analyzeClass(String cname) throws Exception {
142         if(verbose){
143                         System.out.println("[analyze class "+cname+"]");
144                 }
145         int p = cname.lastIndexOf('.');
146         if (p != -1) {
147                 classname = cname.substring(p+1);
148         }
149         else {
150                 classname = cname;
151         }
152         fullclassname = cname;
153
154         
155         HashSet rmeths = new HashSet();
156         findClass();
157         
158         // get the remote interface
159         mRemoteInterface = getRemoteInterface(clazz);
160         if(mRemoteInterface == null)
161                 return;
162         if(verbose){
163                 System.out.println("[implements "+mRemoteInterface.getName()+"]");
164         }
165
166         // check if the methods of the remote interface declare RemoteExceptions
167         Method[] meths = mRemoteInterface.getDeclaredMethods();
168         for (int i = 0; i < meths.length; i++) {
169                 Class[] exceptions = meths[i].getExceptionTypes();
170                 int index = 0;
171                 for(;index < exceptions.length; index++){
172                         if(exceptions[index].equals(RemoteException.class)){
173                                 break;
174                         }
175                 }
176                 if (index < exceptions.length) {
177                         rmeths.add(meths[i]);
178                 } else {
179                         logError("Method "+meths[i]+" does not throw a java.rmi.RemoteException");
180                 }
181         }
182
183
184         // Convert into a MethodRef array and sort them
185         remotemethods = new MethodRef[rmeths.size()];
186         int c = 0;
187         for (Iterator i = rmeths.iterator(); i.hasNext(); ) {
188                 remotemethods[c++] = new MethodRef((Method)i.next());
189         }
190         Arrays.sort(remotemethods);
191 }
192
193 public Exception getException() {
194         return (exception);
195 }
196
197 private void findClass() throws ClassNotFoundException {
198         clazz = Class.forName(fullclassname, true, ClassLoader.getSystemClassLoader());
199 }
200
201 private void generateStub() throws IOException {
202         stubname = fullclassname + "_Stub";
203         String stubclassname = classname + "_Stub";
204         ctrl = new TabbedWriter(new FileWriter((destination == null ? "" : destination + File.separator)
205                                                + stubname.replace('.', File.separatorChar)
206                                                + ".java"));
207         out = new PrintWriter(ctrl);
208
209         if (verbose) {
210                 System.out.println("[Generating class " + stubname + ".java]");
211         }
212
213         out.println("// Stub class generated by rmic - DO NOT EDIT!");
214         out.println();
215         if (fullclassname != classname) {
216                 String pname = fullclassname.substring(0, fullclassname.lastIndexOf('.'));
217                 out.println("package " + pname + ";");
218                 out.println();
219         }
220
221         out.print("public final class " + stubclassname);
222         ctrl.indent();
223         out.println("extends java.rmi.server.RemoteStub");
224         
225         // Output interfaces we implement
226         out.print("implements ");
227         /* Scan implemented interfaces, and only print remote interfaces. */ 
228         Class[] ifaces = clazz.getInterfaces(); 
229         Set remoteIfaces = new HashSet();
230         for (int i = 0; i < ifaces.length; i++) {
231                 Class iface = ifaces[i];
232                 if (java.rmi.Remote.class.isAssignableFrom(iface)) {
233                         remoteIfaces.add(iface);
234                 }
235         }
236         Iterator iter = remoteIfaces.iterator();
237         while (iter.hasNext()) {
238                 /* Print remote interface. */
239                 Class iface = (Class) iter.next();
240                 out.print(iface.getName());
241
242                 /* Print ", " if more remote interfaces follow. */
243                 if (iter.hasNext()) {
244                         out.print(", ");
245                 }
246         }
247         ctrl.unindent();
248         out.print("{");
249         ctrl.indent();
250
251         // UID
252         if (need12Stubs) {
253                 out.println("private static final long serialVersionUID = 2L;");
254                 out.println();
255         }
256
257         // InterfaceHash - don't know how to calculate this - XXX
258         if (need11Stubs) {
259                 out.println("private static final long interfaceHash = " + RMIHashes.getInterfaceHash(clazz) + "L;");
260                 out.println();
261                 if (need12Stubs) {
262                         out.println("private static boolean useNewInvoke;");
263                         out.println();
264                 }
265
266                 // Operation table
267                 out.print("private static final java.rmi.server.Operation[] operations = {");
268
269                 ctrl.indent();
270                 for (int i = 0; i < remotemethods.length; i++) {
271                         Method m = remotemethods[i].meth;
272                         out.print("new java.rmi.server.Operation(\"");
273                         out.print(getPrettyName(m.getReturnType()) + " ");
274                         out.print(m.getName() + "(");
275                         // Output signature
276                         Class[] sig = m.getParameterTypes();
277                         for (int j = 0; j < sig.length; j++) {
278                                 out.print(getPrettyName(sig[j]));
279                                 if (j+1 < sig.length) {
280                                         out.print(", ");
281                                 }
282                         }
283                         out.print(")\")");
284                         if (i + 1 < remotemethods.length) {
285                                 out.println(",");
286                         }
287                 }
288                 ctrl.unindent();
289                 out.println("};");
290                 out.println();
291         }
292
293         // Set of method references.
294         if (need12Stubs) {
295                 for (int i = 0; i < remotemethods.length; i++) {
296                         Method m = remotemethods[i].meth;
297                         out.println("private static java.lang.reflect.Method $method_" + m.getName() + "_" + i + ";");
298                 }
299
300                 // Initialize the methods references.
301                 out.println();
302                 out.print("static {");
303                 ctrl.indent();
304
305                 out.print("try {");
306                 ctrl.indent();
307
308                 if (need11Stubs) {
309                         out.println("java.rmi.server.RemoteRef.class.getMethod(\"invoke\", new java.lang.Class[] { java.rmi.Remote.class, java.lang.reflect.Method.class, java.lang.Object[].class, long.class });");
310                         out.println("useNewInvoke = true;");
311                 }
312
313                 for (int i = 0; i < remotemethods.length; i++) {
314                         Method m = remotemethods[i].meth;
315                         out.print("$method_" + m.getName() + "_" + i + " = ");
316                         out.print(mRemoteInterface.getName() + ".class.getMethod(\"" + m.getName() + "\"");
317                         out.print(", new java.lang.Class[] {");
318                         // Output signature
319                         Class[] sig = m.getParameterTypes();
320                         for (int j = 0; j < sig.length; j++) {
321                                 out.print(getPrettyName(sig[j]) + ".class");
322                                 if (j+1 < sig.length) {
323                                         out.print(", ");
324                                 }
325                         }
326                         out.println("});");
327                 }
328                 ctrl.unindent();
329                 out.println("}");
330                 out.print("catch (java.lang.NoSuchMethodException e) {");
331                 ctrl.indent();
332                 if (need11Stubs) {
333                         out.print("useNewInvoke = false;");
334                 }
335                 else {
336                         out.print("throw new java.lang.NoSuchMethodError(\"stub class initialization failed\");");
337                 }
338
339                 ctrl.unindent();
340                 out.print("}");
341
342                 ctrl.unindent();
343                 out.println("}");
344                 out.println();
345         }
346
347         // Constructors
348         if (need11Stubs) {
349                 out.print("public " + stubclassname + "() {");
350                 ctrl.indent();
351                 out.print("super();");
352                 ctrl.unindent();
353                 out.println("}");
354         }
355
356         if (need12Stubs) {
357                 out.print("public " + stubclassname + "(java.rmi.server.RemoteRef ref) {");
358                 ctrl.indent();
359                 out.print("super(ref);");
360                 ctrl.unindent();
361                 out.println("}");
362         }
363
364         // Method implementations
365         for (int i = 0; i < remotemethods.length; i++) {
366                 Method m = remotemethods[i].meth;
367                 Class[] sig = m.getParameterTypes();
368                 Class returntype = m.getReturnType();
369                 Class[] except = sortExceptions(m.getExceptionTypes());
370
371                 out.println();
372                 out.print("public " + getPrettyName(returntype) + " " + m.getName() + "(");
373                 for (int j = 0; j < sig.length; j++) {
374                         out.print(getPrettyName(sig[j]));
375                         out.print(" $param_" + j);
376                         if (j+1 < sig.length) {
377                                 out.print(", ");
378                         }
379                 }
380                 out.print(") ");
381                 out.print("throws ");
382                 for (int j = 0; j < except.length; j++) {
383                         out.print(getPrettyName(except[j]));
384                         if (j+1 < except.length) {
385                                 out.print(", ");
386                         }
387                 }
388                 out.print(" {");
389                 ctrl.indent();
390
391                 out.print("try {");
392                 ctrl.indent();
393
394                 if (need12Stubs) {
395                         if (need11Stubs) {
396                                 out.print("if (useNewInvoke) {");
397                                 ctrl.indent();
398                         }
399                         if (returntype != Void.TYPE) {
400                                 out.print("java.lang.Object $result = ");
401                         }
402                         out.print("ref.invoke(this, $method_" + m.getName() + "_" + i + ", ");
403                         if (sig.length == 0) {
404                                 out.print("null, ");
405                         }
406                         else {
407                                 out.print("new java.lang.Object[] {");
408                                 for (int j = 0; j < sig.length; j++) {
409                                         if (sig[j] == Boolean.TYPE) {
410                                                 out.print("new java.lang.Boolean($param_" + j + ")");
411                                         }
412                                         else if (sig[j] == Byte.TYPE) {
413                                                 out.print("new java.lang.Byte($param_" + j + ")");
414                                         }
415                                         else if (sig[j] == Character.TYPE) {
416                                                 out.print("new java.lang.Character($param_" + j + ")");
417                                         }
418                                         else if (sig[j] == Short.TYPE) {
419                                                 out.print("new java.lang.Short($param_" + j + ")");
420                                         }
421                                         else if (sig[j] == Integer.TYPE) {
422                                                 out.print("new java.lang.Integer($param_" + j + ")");
423                                         }
424                                         else if (sig[j] == Long.TYPE) {
425                                                 out.print("new java.lang.Long($param_" + j + ")");
426                                         }
427                                         else if (sig[j] == Float.TYPE) {
428                                                 out.print("new java.lang.Float($param_" + j + ")");
429                                         }
430                                         else if (sig[j] == Double.TYPE) {
431                                                 out.print("new java.lang.Double($param_" + j + ")");
432                                         }
433                                         else {
434                                                 out.print("$param_" + j);
435                                         }
436                                         if (j+1 < sig.length) {
437                                                 out.print(", ");
438                                         }
439                                 }
440                                 out.print("}, ");
441                         }
442                         out.print(Long.toString(remotemethods[i].hash) + "L");
443                         out.print(");");
444
445                         if (returntype != Void.TYPE) {
446                                 out.println();
447                                 out.print("return (");
448                                 if (returntype == Boolean.TYPE) {
449                                         out.print("((java.lang.Boolean)$result).booleanValue()");
450                                 }
451                                 else if (returntype == Byte.TYPE) {
452                                         out.print("((java.lang.Byte)$result).byteValue()");
453                                 }
454                                 else if (returntype == Character.TYPE) {
455                                         out.print("((java.lang.Character)$result).charValue()");
456                                 }
457                                 else if (returntype == Short.TYPE) {
458                                         out.print("((java.lang.Short)$result).shortValue()");
459                                 }
460                                 else if (returntype == Integer.TYPE) {
461                                         out.print("((java.lang.Integer)$result).intValue()");
462                                 }
463                                 else if (returntype == Long.TYPE) {
464                                         out.print("((java.lang.Long)$result).longValue()");
465                                 }
466                                 else if (returntype == Float.TYPE) {
467                                         out.print("((java.lang.Float)$result).floatValue()");
468                                 }
469                                 else if (returntype == Double.TYPE) {
470                                         out.print("((java.lang.Double)$result).doubleValue()");
471                                 }
472                                 else {
473                                         out.print("(" + getPrettyName(returntype) + ")$result");
474                                 }
475                                 out.print(");");
476                         }
477
478                         if (need11Stubs) {
479                                 ctrl.unindent();
480                                 out.println("}");
481                                 out.print("else {");
482                                 ctrl.indent();
483                         }
484                 }
485
486                 if (need11Stubs) {
487                         out.println("java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject)this, operations, " + i + ", interfaceHash);");
488                         out.print("try {");
489                         ctrl.indent();
490                         out.print("java.io.ObjectOutput out = call.getOutputStream();");
491                         for (int j = 0; j < sig.length; j++) {
492                                 out.println();
493                                 if (sig[j] == Boolean.TYPE) {
494                                         out.print("out.writeBoolean(");
495                                 }
496                                 else if (sig[j] == Byte.TYPE) {
497                                         out.print("out.writeByte(");
498                                 }
499                                 else if (sig[j] == Character.TYPE) {
500                                         out.print("out.writeChar(");
501                                 }
502                                 else if (sig[j] == Short.TYPE) {
503                                         out.print("out.writeShort(");
504                                 }
505                                 else if (sig[j] == Integer.TYPE) {
506                                         out.print("out.writeInt(");
507                                 }
508                                 else if (sig[j] == Long.TYPE) {
509                                         out.print("out.writeLong(");
510                                 }
511                                 else if (sig[j] == Float.TYPE) {
512                                         out.print("out.writeFloat(");
513                                 }
514                                 else if (sig[j] == Double.TYPE) {
515                                         out.print("out.writeDouble(");
516                                 }
517                                 else {
518                                         out.print("out.writeObject(");
519                                 }
520                                 out.print("$param_" + j + ");");
521                         }
522                         ctrl.unindent();
523                         out.println("}");
524                         out.print("catch (java.io.IOException e) {");
525                         ctrl.indent();
526                         out.print("throw new java.rmi.MarshalException(\"error marshalling arguments\", e);");
527                         ctrl.unindent();
528                         out.println("}");
529                         out.println("ref.invoke(call);");
530                         if (returntype != Void.TYPE) {
531                                 out.println(getPrettyName(returntype) + " $result;");
532                         }
533                         out.print("try {");
534                         ctrl.indent();
535                         out.print("java.io.ObjectInput in = call.getInputStream();");
536                         boolean needcastcheck = false;
537                         if (returntype != Void.TYPE) {
538                                 out.println();
539                                 out.print("$result = ");
540                                 if (returntype == Boolean.TYPE) {
541                                         out.print("in.readBoolean();");
542                                 }
543                                 else if (returntype == Byte.TYPE) {
544                                         out.print("in.readByte();");
545                                 }
546                                 else if (returntype == Character.TYPE) {
547                                         out.print("in.readChar();");
548                                 }
549                                 else if (returntype == Short.TYPE) {
550                                         out.print("in.readShort();");
551                                 }
552                                 else if (returntype == Integer.TYPE) {
553                                         out.print("in.readInt();");
554                                 }
555                                 else if (returntype == Long.TYPE) {
556                                         out.print("in.readLong();");
557                                 }
558                                 else if (returntype == Float.TYPE) {
559                                         out.print("in.readFloat();");
560                                 }
561                                 else if (returntype == Double.TYPE) {
562                                         out.print("in.readDouble();");
563                                 }
564                                 else {
565                                         if (returntype != Object.class) {
566                                                 out.print("(" + getPrettyName(returntype) + ")");
567                                         }
568                                         else {
569                                                 needcastcheck = true;
570                                         }
571                                         out.print("in.readObject();");
572                                 }
573                                 out.println();
574                                 out.print("return ($result);");
575                         }
576                         ctrl.unindent();
577                         out.println("}");
578                         out.print("catch (java.io.IOException e) {");
579                         ctrl.indent();
580                         out.print("throw new java.rmi.UnmarshalException(\"error unmarshalling return\", e);");
581                         ctrl.unindent();
582                         out.println("}");
583                         if (needcastcheck) {
584                                 out.print("catch (java.lang.ClassNotFoundException e) {");
585                                 ctrl.indent();
586                                 out.print("throw new java.rmi.UnmarshalException(\"error unmarshalling return\", e);");
587                                 ctrl.unindent();
588                                 out.println("}");
589                         }
590                         out.print("finally {");
591                         ctrl.indent();
592                         out.print("ref.done(call);");
593                         ctrl.unindent();
594                         out.print("}");
595
596                         if (need12Stubs && need11Stubs) {
597                                 ctrl.unindent();
598                                 out.print("}");
599                         }
600                 }
601
602                 ctrl.unindent();
603                 out.print("}");
604
605                 boolean needgeneral = true;
606                 for (int j = 0; j < except.length; j++) {
607                         out.println();
608                         out.print("catch (" + getPrettyName(except[j]) + " e) {");
609                         ctrl.indent();
610                         out.print("throw e;");
611                         ctrl.unindent();
612                         out.print("}");
613                         if (except[j] == Exception.class) {
614                                 needgeneral = false;
615                         }
616                 }
617                 if (needgeneral) {
618                         out.println();
619                         out.print("catch (java.lang.Exception e) {");
620                         ctrl.indent();
621                         out.print("throw new java.rmi.UnexpectedException(\"undeclared checked exception\", e);");
622                         ctrl.unindent();
623                         out.print("}");
624                 }
625
626                 ctrl.unindent();
627                 out.print("}");
628                 out.println();
629         }
630
631         ctrl.unindent();
632         out.println("}");
633
634         out.close();
635 }
636
637 private void generateSkel() throws IOException {
638         skelname = fullclassname + "_Skel";
639         String skelclassname = classname + "_Skel";
640         ctrl = new TabbedWriter(new FileWriter((destination == null ? "" : destination + File.separator)
641                                                + skelname.replace('.', File.separatorChar)
642                                                + ".java"));
643         out = new PrintWriter(ctrl);
644
645         if (verbose) {
646                 System.out.println("[Generating class " + skelname + ".java]");
647         }
648
649         out.println("// Skel class generated by rmic - DO NOT EDIT!");
650         out.println();
651         if (fullclassname != classname) {
652                 String pname = fullclassname.substring(0, fullclassname.lastIndexOf('.'));
653                 out.println("package " + pname + ";");
654                 out.println();
655         }
656
657         out.print("public final class " + skelclassname);
658         ctrl.indent();
659         
660         // Output interfaces we implement
661         out.print("implements java.rmi.server.Skeleton");
662
663         ctrl.unindent();
664         out.print("{");
665         ctrl.indent();
666
667         // Interface hash - don't know how to calculate this - XXX
668         out.println("private static final long interfaceHash = " + RMIHashes.getInterfaceHash(clazz) + "L;");
669         out.println();
670
671         // Operation table
672         out.print("private static final java.rmi.server.Operation[] operations = {");
673
674         ctrl.indent();
675         for (int i = 0; i < remotemethods.length; i++) {
676                 Method m = remotemethods[i].meth;
677                 out.print("new java.rmi.server.Operation(\"");
678                 out.print(getPrettyName(m.getReturnType()) + " ");
679                 out.print(m.getName() + "(");
680                 // Output signature
681                 Class[] sig = m.getParameterTypes();
682                 for (int j = 0; j < sig.length; j++) {
683                         out.print(getPrettyName(sig[j]));
684                         if (j+1 < sig.length) {
685                                 out.print(", ");
686                         }
687                 }
688                 out.print("\")");
689                 if (i + 1 < remotemethods.length) {
690                         out.println(",");
691                 }
692         }
693         ctrl.unindent();
694         out.println("};");
695
696         out.println();
697
698         // getOperations method
699         out.print("public java.rmi.server.Operation[] getOperations() {");
700         ctrl.indent();
701         out.print("return ((java.rmi.server.Operation[]) operations.clone());");
702         ctrl.unindent();
703         out.println("}");
704
705         out.println();
706
707         // Dispatch method
708         out.print("public void dispatch(java.rmi.Remote obj, java.rmi.server.RemoteCall call, int opnum, long hash) throws java.lang.Exception {");
709         ctrl.indent();
710
711         out.print("if (opnum < 0) {");
712         ctrl.indent();
713
714         for (int i = 0; i < remotemethods.length; i++) {
715                 out.print("if (hash == " + Long.toString(remotemethods[i].hash) + "L) {");
716                 ctrl.indent();
717                 out.print("opnum = " + i + ";");
718                 ctrl.unindent();
719                 out.println("}");
720                 out.print("else ");
721         }
722         out.print("{");
723         ctrl.indent();
724         out.print("throw new java.rmi.server.SkeletonMismatchException(\"interface hash mismatch\");");
725         ctrl.unindent();
726         out.print("}");
727
728         ctrl.unindent();
729         out.println("}");
730         out.print("else if (hash != interfaceHash) {");
731         ctrl.indent();
732         out.print("throw new java.rmi.server.SkeletonMismatchException(\"interface hash mismatch\");");
733         ctrl.unindent();
734         out.println("}");
735
736         out.println();
737
738         out.println(fullclassname + " server = (" + fullclassname + ")obj;");
739         out.println("switch (opnum) {");
740
741         // Method dispatch
742         for (int i = 0; i < remotemethods.length; i++) {
743                 Method m = remotemethods[i].meth;
744                 out.println("case " + i + ":");
745                 out.print("{");
746                 ctrl.indent();
747
748                 Class[] sig = m.getParameterTypes();
749                 for (int j = 0; j < sig.length; j++) {
750                         out.print(getPrettyName(sig[j]));
751                         out.println(" $param_" + j + ";");
752                 }
753
754                 out.print("try {");
755                 boolean needcastcheck = false;
756                 ctrl.indent();
757                 out.println("java.io.ObjectInput in = call.getInputStream();");
758                 for (int j = 0; j < sig.length; j++) {
759                         out.print("$param_" + j + " = ");
760                         if (sig[j] == Boolean.TYPE) {
761                                 out.print("in.readBoolean();");
762                         }
763                         else if (sig[j] == Byte.TYPE) {
764                                 out.print("in.readByte();");
765                         }
766                         else if (sig[j] == Character.TYPE) {
767                                 out.print("in.readChar();");
768                         }
769                         else if (sig[j] == Short.TYPE) {
770                                 out.print("in.readShort();");
771                         }
772                         else if (sig[j] == Integer.TYPE) {
773                                 out.print("in.readInt();");
774                         }
775                         else if (sig[j] == Long.TYPE) {
776                                 out.print("in.readLong();");
777                         }
778                         else if (sig[j] == Float.TYPE) {
779                                 out.print("in.readFloat();");
780                         }
781                         else if (sig[j] == Double.TYPE) {
782                                 out.print("in.readDouble();");
783                         }
784                         else {
785                                 if (sig[j] != Object.class) {
786                                         out.print("(" + getPrettyName(sig[j]) + ")");
787                                         needcastcheck = true;
788                                 }
789                                 out.print("in.readObject();");
790                         }
791                         out.println();
792                 }
793                 ctrl.unindent();
794                 out.println("}");
795                 out.print("catch (java.io.IOException e) {");
796                 ctrl.indent();
797                 out.print("throw new java.rmi.UnmarshalException(\"error unmarshalling arguments\", e);");
798                 ctrl.unindent();
799                 out.println("}");
800                 if (needcastcheck) {
801                         out.print("catch (java.lang.ClassCastException e) {");
802                         ctrl.indent();
803                         out.print("throw new java.rmi.UnmarshalException(\"error unmarshalling arguments\", e);");
804                         ctrl.unindent();
805                         out.println("}");
806                 }
807                 out.print("finally {");
808                 ctrl.indent();
809                 out.print("call.releaseInputStream();");
810                 ctrl.unindent();
811                 out.println("}");
812
813                 Class returntype = m.getReturnType();
814                 if (returntype != Void.TYPE) {
815                         out.print(getPrettyName(returntype) + " $result = ");
816                 }
817                 out.print("server." + m.getName() + "(");
818                 for (int j = 0; j < sig.length; j++) {
819                         out.print("$param_" + j);
820                         if (j + 1 < sig.length) {
821                                 out.print(", ");
822                         }
823                 }
824                 out.println(");");
825
826                 out.print("try {");
827                 ctrl.indent();
828                 out.print("java.io.ObjectOutput out = call.getResultStream(true);");
829                 if (returntype != Void.TYPE) {
830                         out.println();
831                         if (returntype == Boolean.TYPE) {
832                                 out.print("out.writeBoolean($result);");
833                         }
834                         else if (returntype == Byte.TYPE) {
835                                 out.print("out.writeByte($result);");
836                         }
837                         else if (returntype == Character.TYPE) {
838                                 out.print("out.writeChar($result);");
839                         }
840                         else if (returntype == Short.TYPE) {
841                                 out.print("out.writeShort($result);");
842                         }
843                         else if (returntype == Integer.TYPE) {
844                                 out.print("out.writeInt($result);");
845                         }
846                         else if (returntype == Long.TYPE) {
847                                 out.print("out.writeLong($result);");
848                         }
849                         else if (returntype == Float.TYPE) {
850                                 out.print("out.writeFloat($result);");
851                         }
852                         else if (returntype == Double.TYPE) {
853                                 out.print("out.writeDouble($result);");
854                         }
855                         else {
856                                 out.print("out.writeObject($result);");
857                         }
858                 }
859                 ctrl.unindent();
860                 out.println("}");
861                 out.print("catch (java.io.IOException e) {");
862                 ctrl.indent();
863                 out.print("throw new java.rmi.MarshalException(\"error marshalling return\", e);");
864                 ctrl.unindent();
865                 out.println("}");
866                 out.print("break;");
867
868                 ctrl.unindent();
869                 out.println("}");
870                 out.println();
871         }
872
873         out.print("default:");
874         ctrl.indent();
875         out.print("throw new java.rmi.UnmarshalException(\"invalid method number\");");
876         ctrl.unindent();
877         out.print("}");
878
879         ctrl.unindent();
880         out.print("}");
881
882         ctrl.unindent();
883         out.println("}");
884
885         out.close();
886 }
887
888 private void compile(String name) throws Exception {
889         Compiler comp = Compiler.getInstance();
890         if (verbose) {
891                 System.out.println("[Compiling class " + name + "]");
892         }
893         comp.setDestination(destination);
894         comp.compile(name);
895 }
896
897 private static String getPrettyName(Class cls) {
898         StringBuffer str = new StringBuffer();
899         for (int count = 0;; count++) {
900                 if (!cls.isArray()) {
901                         str.append(cls.getName());
902                         for (; count > 0; count--) {
903                                 str.append("[]");
904                         }
905                         return (str.toString());
906                 }
907                 cls = cls.getComponentType();
908         }
909 }
910
911 /**
912  * Sort exceptions so the most general go last.
913  */
914 private Class[] sortExceptions(Class[] except) {
915         for (int i = 0; i < except.length; i++) {
916                 for (int j = i+1; j < except.length; j++) {
917                         if (except[i].isAssignableFrom(except[j])) {
918                                 Class tmp = except[i];
919                                 except[i] = except[j];
920                                 except[j] = tmp;
921                         }
922                 }
923         }
924         return (except);
925 }
926
927 /**
928  * Process the options until we find the first argument.
929  */
930 private void parseOptions() {
931         for (;;) {
932                 if (next >= args.length || args[next].charAt(0) != '-') {
933                         break;
934                 }
935                 String arg = args[next];
936                 next++;
937
938                 // Accept `--' options if they look long enough.
939                 if (arg.length() > 3 && arg.charAt(0) == '-'
940                     && arg.charAt(1) == '-')
941                   arg = arg.substring(1);
942
943                 if (arg.equals("-keep")) {
944                         keep = true;
945                 }
946                 else if (arg.equals("-keepgenerated")) {
947                         keep = true;
948                 }
949                 else if (arg.equals("-v1.1")) {
950                         need11Stubs = true;
951                         need12Stubs = false;
952                 }
953                 else if (arg.equals("-vcompat")) {
954                         need11Stubs = true;
955                         need12Stubs = true;
956                 }
957                 else if (arg.equals("-v1.2")) {
958                         need11Stubs = false;
959                         need12Stubs = true;
960                 }
961                 else if (arg.equals("-g")) {
962                 }
963                 else if (arg.equals("-depend")) {
964                 }
965                 else if (arg.equals("-nowarn")) {
966                 }
967                 else if (arg.equals("-verbose")) {
968                         verbose = true;
969                 }
970                 else if (arg.equals("-nocompile")) {
971                         compile = false;
972                 }
973                 else if (arg.equals("-classpath")) {
974                         next++;
975                 }
976                 else if (arg.equals("-help")) {
977                         usage();
978                 }
979                 else if (arg.equals("-version")) {
980                         System.out.println("rmic ("
981                                            + System.getProperty("java.vm.name")
982                                            + ") "
983                                            + System.getProperty("java.vm.version"));
984                         System.out.println();
985                         System.out.println("Copyright 2002 Free Software Foundation, Inc.");
986                         System.out.println("This is free software; see the source for copying conditions.  There is NO");
987                         System.out.println("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
988                         System.exit(0);
989                 }
990                 else if (arg.equals("-d")) {
991                         destination = args[next];
992                         next++;
993                 }
994                 else if (arg.charAt(1) == 'J') {
995                 }
996                 else {
997                         error("unrecognized option `" + arg + "'");
998                 }
999         }
1000 }
1001
1002 /**
1003  * Looks for the java.rmi.Remote interface that that is implemented by theClazz.
1004  * @param theClazz the class to look in  
1005  * @return the Remote interface of theClazz or null if theClazz does not implement a Remote interface
1006  */
1007 private Class getRemoteInterface(Class theClazz)
1008 {
1009         Class[] interfaces = theClazz.getInterfaces();
1010         for (int i = 0; i < interfaces.length; i++)
1011         {
1012                 if (java.rmi.Remote.class.isAssignableFrom(interfaces[i]))
1013                 {
1014                         return interfaces[i];
1015                 }
1016         }
1017         logError("Class "+ theClazz.getName()
1018                         + " is not a remote object. It does not implement an interface that is a java.rmi.Remote-interface.");
1019         return null;
1020 }
1021         
1022 /**
1023  * Prints an error to System.err and increases the error count.
1024  * @param theError
1025  */
1026 private void logError(String theError){
1027         errorCount++;
1028         System.err.println("error:"+theError);
1029 }
1030
1031 private static void error(String message) {
1032         System.err.println("rmic: " + message);
1033         System.err.println("Try `rmic --help' for more information.");
1034         System.exit(1);
1035 }
1036
1037 private static void usage() {
1038         System.out.println(
1039 "Usage: rmic [OPTION]... CLASS...\n" +
1040 "\n" +
1041 "       -keep                   Don't delete any intermediate files\n" +
1042 "       -keepgenerated          Same as -keep\n" +
1043 "       -v1.1                   Java 1.1 style stubs only\n" +
1044 "       -vcompat                Java 1.1 & Java 1.2 stubs\n" +
1045 "       -v1.2                   Java 1.2 style stubs only\n" +
1046 "       -g *                    Generated debugging information\n" +
1047 "       -depend *               Recompile out-of-date files\n" +
1048 "       -nowarn *               Suppress warning messages\n" +
1049 "       -nocompile              Don't compile the generated files\n" +
1050 "       -verbose                Output what's going on\n" +
1051 "       -classpath <path> *     Use given path as classpath\n" +
1052 "       -d <directory>          Specify where to place generated classes\n" +
1053 "       -J<flag> *              Pass flag to Java\n" +
1054 "       -help                   Print this help, then exit\n" +
1055 "       -version                Print version number, then exit\n" +
1056 "\n" +
1057 "  * Option currently ignored\n" +
1058 "Long options can be used with `--option' form as well."
1059         );
1060         System.exit(0);
1061 }
1062
1063 static class MethodRef
1064         implements Comparable {
1065
1066 Method meth;
1067 String sig;
1068 long hash;
1069
1070 MethodRef(Method m) {
1071         meth = m;
1072         // We match on the name - but what about overloading? - XXX
1073         sig = m.getName();
1074         hash = RMIHashes.getMethodHash(m);
1075 }
1076
1077 public int compareTo(Object obj) {
1078         MethodRef that = (MethodRef)obj;
1079         return (this.sig.compareTo(that.sig));
1080 }
1081
1082 }
1083
1084 }