OSDN Git Service

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