mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 20:01:22 -05:00
2006-04-05 Archit Shah <ashah@redhat.com> PR java/25414 * gnu/java/rmi/rmic/CompilerProcess.java (computeTypicalArguments): Add classpath argument. * gnu/java/rmi/rmic/Compile_gcj.java (computeArguments): Adjust caller. * gnu/java/rmi/rmic/Compile_jikes.java (computeArguments): Likewise. * gnu/java/rmi/rmic/Compile_kjc.java (computeArguments): Likewise. * gnu/java/rmi/rmic/Compiler.java (getClasspath, setClasspath): New. * gnu/java/rmi/rmic/RMIC.java: Set classpath for compiler, call mkdirs for destination directory, correct handling of superclasses and interfaces of the remote class, correct handling of exceptions declared by remote methods. From-SVN: r112699
1226 lines
34 KiB
Java
1226 lines
34 KiB
Java
/* RMIC.java --
|
|
Copyright (c) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006
|
|
Free Software Foundation, Inc.
|
|
|
|
This file is part of GNU Classpath.
|
|
|
|
GNU Classpath is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
any later version.
|
|
|
|
GNU Classpath is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GNU Classpath; see the file COPYING. If not, write to the
|
|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
02110-1301 USA.
|
|
|
|
Linking this library statically or dynamically with other modules is
|
|
making a combined work based on this library. Thus, the terms and
|
|
conditions of the GNU General Public License cover the whole
|
|
combination.
|
|
|
|
As a special exception, the copyright holders of this library give you
|
|
permission to link this library with independent modules to produce an
|
|
executable, regardless of the license terms of these independent
|
|
modules, and to copy and distribute the resulting executable under
|
|
terms of your choice, provided that you also meet, for each linked
|
|
independent module, the terms and conditions of the license of that
|
|
module. An independent module is a module which is not derived from
|
|
or based on this library. If you modify this library, you may extend
|
|
this exception to your version of the library, but you are not
|
|
obligated to do so. If you do not wish to do so, delete this
|
|
exception statement from your version. */
|
|
|
|
|
|
package gnu.java.rmi.rmic;
|
|
|
|
import gnu.java.rmi.server.RMIHashes;
|
|
|
|
import java.io.File;
|
|
import java.io.FileWriter;
|
|
import java.io.IOException;
|
|
import java.io.PrintWriter;
|
|
import java.lang.reflect.Method;
|
|
import java.net.MalformedURLException;
|
|
import java.net.URL;
|
|
import java.net.URLClassLoader;
|
|
import java.rmi.Remote;
|
|
import java.rmi.RemoteException;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.StringTokenizer;
|
|
|
|
|
|
public class RMIC
|
|
{
|
|
private String[] args;
|
|
private int next;
|
|
private Exception exception;
|
|
private boolean keep = false;
|
|
private boolean need11Stubs = true;
|
|
private boolean need12Stubs = true;
|
|
private boolean compile = true;
|
|
private boolean verbose;
|
|
private String destination;
|
|
private PrintWriter out;
|
|
private TabbedWriter ctrl;
|
|
private Class clazz;
|
|
private String classname;
|
|
private String fullclassname;
|
|
private String fullstubname;
|
|
private String fullskelname;
|
|
private MethodRef[] remotemethods;
|
|
private String stubname;
|
|
private String skelname;
|
|
private ClassLoader loader;
|
|
private String classpath;
|
|
private int errorCount = 0;
|
|
private List mRemoteInterfaces;
|
|
|
|
public RMIC(String[] a)
|
|
{
|
|
args = a;
|
|
}
|
|
|
|
public static void main(String[] args)
|
|
{
|
|
RMIC r = new RMIC(args);
|
|
if (r.run() == false)
|
|
{
|
|
Exception e = r.getException();
|
|
if (e != null)
|
|
e.printStackTrace();
|
|
else
|
|
System.exit(1);
|
|
}
|
|
}
|
|
|
|
public boolean run()
|
|
{
|
|
parseOptions();
|
|
if (next >= args.length)
|
|
error("no class names found");
|
|
for (int i = next; i < args.length; i++)
|
|
{
|
|
try
|
|
{
|
|
if (verbose)
|
|
System.out.println("[Processing class " + args[i] + ".class]");
|
|
processClass(args[i].replace(File.separatorChar, '.'));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
exception = e;
|
|
return (false);
|
|
}
|
|
}
|
|
return (true);
|
|
}
|
|
|
|
private boolean processClass(String cls) throws Exception
|
|
{
|
|
// reset class specific vars
|
|
clazz = null;
|
|
classname = null;
|
|
fullclassname = null;
|
|
remotemethods = null;
|
|
stubname = null;
|
|
fullstubname = null;
|
|
skelname = null;
|
|
fullskelname = null;
|
|
mRemoteInterfaces = new ArrayList();
|
|
|
|
errorCount = 0;
|
|
|
|
analyzeClass(cls);
|
|
|
|
if (errorCount > 0)
|
|
System.exit(1);
|
|
generateStub();
|
|
if (need11Stubs)
|
|
generateSkel();
|
|
if (compile)
|
|
{
|
|
compile(fullstubname);
|
|
if (need11Stubs)
|
|
compile(fullskelname);
|
|
}
|
|
if (! keep)
|
|
{
|
|
(new File(fullstubname)).delete();
|
|
if (need11Stubs)
|
|
(new File(fullskelname)).delete();
|
|
}
|
|
return (true);
|
|
}
|
|
|
|
private void analyzeClass(String cname) throws Exception
|
|
{
|
|
if (verbose)
|
|
System.out.println("[analyze class " + cname + "]");
|
|
int p = cname.lastIndexOf('.');
|
|
if (p != -1)
|
|
classname = cname.substring(p + 1);
|
|
else
|
|
classname = cname;
|
|
fullclassname = cname;
|
|
|
|
findClass();
|
|
findRemoteMethods();
|
|
}
|
|
|
|
public Exception getException()
|
|
{
|
|
return (exception);
|
|
}
|
|
|
|
private void findClass() throws ClassNotFoundException
|
|
{
|
|
try
|
|
{
|
|
ClassLoader cl = (loader == null
|
|
? ClassLoader.getSystemClassLoader()
|
|
: loader);
|
|
clazz = Class.forName(fullclassname, false, cl);
|
|
}
|
|
catch (ClassNotFoundException cnfe)
|
|
{
|
|
System.err.println(fullclassname + " not found in " + classpath);
|
|
throw new RuntimeException(cnfe);
|
|
}
|
|
|
|
if (! Remote.class.isAssignableFrom(clazz))
|
|
{
|
|
logError("Class " + clazz.getName() + " is not a remote object. "
|
|
+ "It does not implement an interface that is a "
|
|
+ "java.rmi.Remote-interface.");
|
|
throw new RuntimeException
|
|
("Class " + clazz.getName() + " is not a remote object. "
|
|
+ "It does not implement an interface that is a "
|
|
+ "java.rmi.Remote-interface.");
|
|
}
|
|
}
|
|
|
|
private void generateStub() throws IOException
|
|
{
|
|
stubname = fullclassname + "_Stub";
|
|
String stubclassname = classname + "_Stub";
|
|
fullstubname = (destination == null ? "" : destination + File.separator)
|
|
+ stubname.replace('.', File.separatorChar) + ".java";
|
|
File file = new File(fullstubname);
|
|
if (file.getParentFile() != null)
|
|
file.getParentFile().mkdirs();
|
|
ctrl =
|
|
new TabbedWriter(new FileWriter(file));
|
|
out = new PrintWriter(ctrl);
|
|
|
|
if (verbose)
|
|
System.out.println("[Generating class " + stubname + ".java]");
|
|
|
|
out.println("// Stub class generated by rmic - DO NOT EDIT!");
|
|
out.println();
|
|
if (fullclassname != classname)
|
|
{
|
|
String pname =
|
|
fullclassname.substring(0, fullclassname.lastIndexOf('.'));
|
|
out.println("package " + pname + ";");
|
|
out.println();
|
|
}
|
|
|
|
out.print("public final class " + stubclassname);
|
|
ctrl.indent();
|
|
out.println("extends java.rmi.server.RemoteStub");
|
|
|
|
// Output interfaces we implement
|
|
out.print("implements ");
|
|
Iterator iter = mRemoteInterfaces.iterator();
|
|
while (iter.hasNext())
|
|
{
|
|
/* Print remote interface. */
|
|
Class iface = (Class) iter.next();
|
|
out.print(iface.getName());
|
|
|
|
/* Print ", " if more remote interfaces follow. */
|
|
if (iter.hasNext())
|
|
out.print(", ");
|
|
}
|
|
ctrl.unindent();
|
|
out.print("{");
|
|
ctrl.indent();
|
|
|
|
// UID
|
|
if (need12Stubs)
|
|
{
|
|
out.println("private static final long serialVersionUID = 2L;");
|
|
out.println();
|
|
}
|
|
|
|
// InterfaceHash - don't know how to calculate this - XXX
|
|
if (need11Stubs)
|
|
{
|
|
out.println("private static final long interfaceHash = "
|
|
+ RMIHashes.getInterfaceHash(clazz) + "L;");
|
|
out.println();
|
|
if (need12Stubs)
|
|
{
|
|
out.println("private static boolean useNewInvoke;");
|
|
out.println();
|
|
}
|
|
|
|
// Operation table
|
|
out.print("private static final java.rmi.server.Operation[] operations = {");
|
|
|
|
ctrl.indent();
|
|
for (int i = 0; i < remotemethods.length; i++)
|
|
{
|
|
Method m = remotemethods[i].meth;
|
|
out.print("new java.rmi.server.Operation(\"");
|
|
out.print(getPrettyName(m.getReturnType()) + " ");
|
|
out.print(m.getName() + "(");
|
|
// Output signature
|
|
Class[] sig = m.getParameterTypes();
|
|
for (int j = 0; j < sig.length; j++)
|
|
{
|
|
out.print(getPrettyName(sig[j]));
|
|
if (j + 1 < sig.length)
|
|
out.print(", ");
|
|
}
|
|
out.print(")\")");
|
|
if (i + 1 < remotemethods.length)
|
|
out.println(",");
|
|
}
|
|
ctrl.unindent();
|
|
out.println("};");
|
|
out.println();
|
|
}
|
|
|
|
// Set of method references.
|
|
if (need12Stubs)
|
|
{
|
|
for (int i = 0; i < remotemethods.length; i++)
|
|
{
|
|
Method m = remotemethods[i].meth;
|
|
out.println("private static java.lang.reflect.Method $method_"
|
|
+ m.getName() + "_" + i + ";");
|
|
}
|
|
|
|
// Initialize the methods references.
|
|
out.println();
|
|
out.print("static {");
|
|
ctrl.indent();
|
|
|
|
out.print("try {");
|
|
ctrl.indent();
|
|
|
|
if (need11Stubs)
|
|
{
|
|
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 });");
|
|
out.println("useNewInvoke = true;");
|
|
}
|
|
|
|
for (int i = 0; i < remotemethods.length; i++)
|
|
{
|
|
Method m = remotemethods[i].meth;
|
|
out.print("$method_" + m.getName() + "_" + i + " = ");
|
|
out.print(m.getDeclaringClass().getName() + ".class.getMethod(\""
|
|
+ m.getName() + "\"");
|
|
out.print(", new java.lang.Class[] {");
|
|
// Output signature
|
|
Class[] sig = m.getParameterTypes();
|
|
for (int j = 0; j < sig.length; j++)
|
|
{
|
|
out.print(getPrettyName(sig[j]) + ".class");
|
|
if (j + 1 < sig.length)
|
|
out.print(", ");
|
|
}
|
|
out.println("});");
|
|
}
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
out.print("catch (java.lang.NoSuchMethodException e) {");
|
|
ctrl.indent();
|
|
if (need11Stubs)
|
|
out.print("useNewInvoke = false;");
|
|
else
|
|
out.print("throw new java.lang.NoSuchMethodError(\"stub class initialization failed\");");
|
|
|
|
ctrl.unindent();
|
|
out.print("}");
|
|
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
out.println();
|
|
}
|
|
|
|
// Constructors
|
|
if (need11Stubs)
|
|
{
|
|
out.print("public " + stubclassname + "() {");
|
|
ctrl.indent();
|
|
out.print("super();");
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
}
|
|
|
|
if (need12Stubs)
|
|
{
|
|
out.print("public " + stubclassname
|
|
+ "(java.rmi.server.RemoteRef ref) {");
|
|
ctrl.indent();
|
|
out.print("super(ref);");
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
}
|
|
|
|
// Method implementations
|
|
for (int i = 0; i < remotemethods.length; i++)
|
|
{
|
|
Method m = remotemethods[i].meth;
|
|
Class[] sig = m.getParameterTypes();
|
|
Class returntype = m.getReturnType();
|
|
Class[] except = sortExceptions(m.getExceptionTypes());
|
|
|
|
out.println();
|
|
out.print("public " + getPrettyName(returntype) + " " + m.getName()
|
|
+ "(");
|
|
for (int j = 0; j < sig.length; j++)
|
|
{
|
|
out.print(getPrettyName(sig[j]));
|
|
out.print(" $param_" + j);
|
|
if (j + 1 < sig.length)
|
|
out.print(", ");
|
|
}
|
|
out.print(") ");
|
|
out.print("throws ");
|
|
for (int j = 0; j < except.length; j++)
|
|
{
|
|
out.print(getPrettyName(except[j]));
|
|
if (j + 1 < except.length)
|
|
out.print(", ");
|
|
}
|
|
out.print(" {");
|
|
ctrl.indent();
|
|
|
|
out.print("try {");
|
|
ctrl.indent();
|
|
|
|
if (need12Stubs)
|
|
{
|
|
if (need11Stubs)
|
|
{
|
|
out.print("if (useNewInvoke) {");
|
|
ctrl.indent();
|
|
}
|
|
if (returntype != Void.TYPE)
|
|
out.print("java.lang.Object $result = ");
|
|
out.print("ref.invoke(this, $method_" + m.getName() + "_" + i
|
|
+ ", ");
|
|
if (sig.length == 0)
|
|
out.print("null, ");
|
|
else
|
|
{
|
|
out.print("new java.lang.Object[] {");
|
|
for (int j = 0; j < sig.length; j++)
|
|
{
|
|
if (sig[j] == Boolean.TYPE)
|
|
out.print("new java.lang.Boolean($param_" + j + ")");
|
|
else if (sig[j] == Byte.TYPE)
|
|
out.print("new java.lang.Byte($param_" + j + ")");
|
|
else if (sig[j] == Character.TYPE)
|
|
out.print("new java.lang.Character($param_" + j + ")");
|
|
else if (sig[j] == Short.TYPE)
|
|
out.print("new java.lang.Short($param_" + j + ")");
|
|
else if (sig[j] == Integer.TYPE)
|
|
out.print("new java.lang.Integer($param_" + j + ")");
|
|
else if (sig[j] == Long.TYPE)
|
|
out.print("new java.lang.Long($param_" + j + ")");
|
|
else if (sig[j] == Float.TYPE)
|
|
out.print("new java.lang.Float($param_" + j + ")");
|
|
else if (sig[j] == Double.TYPE)
|
|
out.print("new java.lang.Double($param_" + j + ")");
|
|
else
|
|
out.print("$param_" + j);
|
|
if (j + 1 < sig.length)
|
|
out.print(", ");
|
|
}
|
|
out.print("}, ");
|
|
}
|
|
out.print(Long.toString(remotemethods[i].hash) + "L");
|
|
out.print(");");
|
|
|
|
if (returntype != Void.TYPE)
|
|
{
|
|
out.println();
|
|
out.print("return (");
|
|
if (returntype == Boolean.TYPE)
|
|
out.print("((java.lang.Boolean)$result).booleanValue()");
|
|
else if (returntype == Byte.TYPE)
|
|
out.print("((java.lang.Byte)$result).byteValue()");
|
|
else if (returntype == Character.TYPE)
|
|
out.print("((java.lang.Character)$result).charValue()");
|
|
else if (returntype == Short.TYPE)
|
|
out.print("((java.lang.Short)$result).shortValue()");
|
|
else if (returntype == Integer.TYPE)
|
|
out.print("((java.lang.Integer)$result).intValue()");
|
|
else if (returntype == Long.TYPE)
|
|
out.print("((java.lang.Long)$result).longValue()");
|
|
else if (returntype == Float.TYPE)
|
|
out.print("((java.lang.Float)$result).floatValue()");
|
|
else if (returntype == Double.TYPE)
|
|
out.print("((java.lang.Double)$result).doubleValue()");
|
|
else
|
|
out.print("(" + getPrettyName(returntype) + ")$result");
|
|
out.print(");");
|
|
}
|
|
|
|
if (need11Stubs)
|
|
{
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
out.print("else {");
|
|
ctrl.indent();
|
|
}
|
|
}
|
|
|
|
if (need11Stubs)
|
|
{
|
|
out.println("java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject)this, operations, "
|
|
+ i + ", interfaceHash);");
|
|
out.print("try {");
|
|
ctrl.indent();
|
|
out.print("java.io.ObjectOutput out = call.getOutputStream();");
|
|
for (int j = 0; j < sig.length; j++)
|
|
{
|
|
out.println();
|
|
if (sig[j] == Boolean.TYPE)
|
|
out.print("out.writeBoolean(");
|
|
else if (sig[j] == Byte.TYPE)
|
|
out.print("out.writeByte(");
|
|
else if (sig[j] == Character.TYPE)
|
|
out.print("out.writeChar(");
|
|
else if (sig[j] == Short.TYPE)
|
|
out.print("out.writeShort(");
|
|
else if (sig[j] == Integer.TYPE)
|
|
out.print("out.writeInt(");
|
|
else if (sig[j] == Long.TYPE)
|
|
out.print("out.writeLong(");
|
|
else if (sig[j] == Float.TYPE)
|
|
out.print("out.writeFloat(");
|
|
else if (sig[j] == Double.TYPE)
|
|
out.print("out.writeDouble(");
|
|
else
|
|
out.print("out.writeObject(");
|
|
out.print("$param_" + j + ");");
|
|
}
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
out.print("catch (java.io.IOException e) {");
|
|
ctrl.indent();
|
|
out.print("throw new java.rmi.MarshalException(\"error marshalling arguments\", e);");
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
out.println("ref.invoke(call);");
|
|
if (returntype != Void.TYPE)
|
|
out.println(getPrettyName(returntype) + " $result;");
|
|
out.print("try {");
|
|
ctrl.indent();
|
|
out.print("java.io.ObjectInput in = call.getInputStream();");
|
|
boolean needcastcheck = false;
|
|
if (returntype != Void.TYPE)
|
|
{
|
|
out.println();
|
|
out.print("$result = ");
|
|
if (returntype == Boolean.TYPE)
|
|
out.print("in.readBoolean();");
|
|
else if (returntype == Byte.TYPE)
|
|
out.print("in.readByte();");
|
|
else if (returntype == Character.TYPE)
|
|
out.print("in.readChar();");
|
|
else if (returntype == Short.TYPE)
|
|
out.print("in.readShort();");
|
|
else if (returntype == Integer.TYPE)
|
|
out.print("in.readInt();");
|
|
else if (returntype == Long.TYPE)
|
|
out.print("in.readLong();");
|
|
else if (returntype == Float.TYPE)
|
|
out.print("in.readFloat();");
|
|
else if (returntype == Double.TYPE)
|
|
out.print("in.readDouble();");
|
|
else
|
|
{
|
|
if (returntype != Object.class)
|
|
out.print("(" + getPrettyName(returntype) + ")");
|
|
else
|
|
needcastcheck = true;
|
|
out.print("in.readObject();");
|
|
}
|
|
out.println();
|
|
out.print("return ($result);");
|
|
}
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
out.print("catch (java.io.IOException e) {");
|
|
ctrl.indent();
|
|
out.print("throw new java.rmi.UnmarshalException(\"error unmarshalling return\", e);");
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
if (needcastcheck)
|
|
{
|
|
out.print("catch (java.lang.ClassNotFoundException e) {");
|
|
ctrl.indent();
|
|
out.print("throw new java.rmi.UnmarshalException(\"error unmarshalling return\", e);");
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
}
|
|
out.print("finally {");
|
|
ctrl.indent();
|
|
out.print("ref.done(call);");
|
|
ctrl.unindent();
|
|
out.print("}");
|
|
|
|
if (need12Stubs && need11Stubs)
|
|
{
|
|
ctrl.unindent();
|
|
out.print("}");
|
|
}
|
|
}
|
|
|
|
ctrl.unindent();
|
|
out.print("}");
|
|
|
|
boolean needgeneral = true;
|
|
for (int j = 0; j < except.length; j++)
|
|
{
|
|
out.println();
|
|
out.print("catch (" + getPrettyName(except[j]) + " e) {");
|
|
ctrl.indent();
|
|
out.print("throw e;");
|
|
ctrl.unindent();
|
|
out.print("}");
|
|
if (except[j] == Exception.class)
|
|
needgeneral = false;
|
|
}
|
|
if (needgeneral)
|
|
{
|
|
out.println();
|
|
out.print("catch (java.lang.Exception e) {");
|
|
ctrl.indent();
|
|
out.print("throw new java.rmi.UnexpectedException(\"undeclared checked exception\", e);");
|
|
ctrl.unindent();
|
|
out.print("}");
|
|
}
|
|
|
|
ctrl.unindent();
|
|
out.print("}");
|
|
out.println();
|
|
}
|
|
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
|
|
out.close();
|
|
}
|
|
|
|
private void generateSkel() throws IOException
|
|
{
|
|
skelname = fullclassname + "_Skel";
|
|
String skelclassname = classname + "_Skel";
|
|
fullskelname = (destination == null ? "" : destination + File.separator)
|
|
+ skelname.replace('.', File.separatorChar) + ".java";
|
|
File file = new File(fullskelname);
|
|
if (file.getParentFile() != null)
|
|
file.getParentFile().mkdirs();
|
|
ctrl =
|
|
new TabbedWriter(new FileWriter(file));
|
|
out = new PrintWriter(ctrl);
|
|
|
|
if (verbose)
|
|
System.out.println("[Generating class " + skelname + ".java]");
|
|
|
|
out.println("// Skel class generated by rmic - DO NOT EDIT!");
|
|
out.println();
|
|
if (fullclassname != classname)
|
|
{
|
|
String pname =
|
|
fullclassname.substring(0, fullclassname.lastIndexOf('.'));
|
|
out.println("package " + pname + ";");
|
|
out.println();
|
|
}
|
|
|
|
out.print("public final class " + skelclassname);
|
|
ctrl.indent();
|
|
|
|
// Output interfaces we implement
|
|
out.print("implements java.rmi.server.Skeleton");
|
|
|
|
ctrl.unindent();
|
|
out.print("{");
|
|
ctrl.indent();
|
|
|
|
// Interface hash - don't know how to calculate this - XXX
|
|
out.println("private static final long interfaceHash = "
|
|
+ RMIHashes.getInterfaceHash(clazz) + "L;");
|
|
out.println();
|
|
|
|
// Operation table
|
|
out.print("private static final java.rmi.server.Operation[] operations = {");
|
|
|
|
ctrl.indent();
|
|
for (int i = 0; i < remotemethods.length; i++)
|
|
{
|
|
Method m = remotemethods[i].meth;
|
|
out.print("new java.rmi.server.Operation(\"");
|
|
out.print(getPrettyName(m.getReturnType()) + " ");
|
|
out.print(m.getName() + "(");
|
|
// Output signature
|
|
Class[] sig = m.getParameterTypes();
|
|
for (int j = 0; j < sig.length; j++)
|
|
{
|
|
out.print(getPrettyName(sig[j]));
|
|
if (j + 1 < sig.length)
|
|
out.print(", ");
|
|
}
|
|
out.print("\")");
|
|
if (i + 1 < remotemethods.length)
|
|
out.println(",");
|
|
}
|
|
ctrl.unindent();
|
|
out.println("};");
|
|
|
|
out.println();
|
|
|
|
// getOperations method
|
|
out.print("public java.rmi.server.Operation[] getOperations() {");
|
|
ctrl.indent();
|
|
out.print("return ((java.rmi.server.Operation[]) operations.clone());");
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
|
|
out.println();
|
|
|
|
// Dispatch method
|
|
out.print("public void dispatch(java.rmi.Remote obj, java.rmi.server.RemoteCall call, int opnum, long hash) throws java.lang.Exception {");
|
|
ctrl.indent();
|
|
|
|
out.print("if (opnum < 0) {");
|
|
ctrl.indent();
|
|
|
|
for (int i = 0; i < remotemethods.length; i++)
|
|
{
|
|
out.print("if (hash == " + Long.toString(remotemethods[i].hash)
|
|
+ "L) {");
|
|
ctrl.indent();
|
|
out.print("opnum = " + i + ";");
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
out.print("else ");
|
|
}
|
|
out.print("{");
|
|
ctrl.indent();
|
|
out.print("throw new java.rmi.server.SkeletonMismatchException(\"interface hash mismatch\");");
|
|
ctrl.unindent();
|
|
out.print("}");
|
|
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
out.print("else if (hash != interfaceHash) {");
|
|
ctrl.indent();
|
|
out.print("throw new java.rmi.server.SkeletonMismatchException(\"interface hash mismatch\");");
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
|
|
out.println();
|
|
|
|
out.println(fullclassname + " server = (" + fullclassname + ")obj;");
|
|
out.println("switch (opnum) {");
|
|
|
|
// Method dispatch
|
|
for (int i = 0; i < remotemethods.length; i++)
|
|
{
|
|
Method m = remotemethods[i].meth;
|
|
out.println("case " + i + ":");
|
|
out.print("{");
|
|
ctrl.indent();
|
|
|
|
Class[] sig = m.getParameterTypes();
|
|
for (int j = 0; j < sig.length; j++)
|
|
{
|
|
out.print(getPrettyName(sig[j]));
|
|
out.println(" $param_" + j + ";");
|
|
}
|
|
|
|
out.print("try {");
|
|
boolean needcastcheck = false;
|
|
ctrl.indent();
|
|
out.println("java.io.ObjectInput in = call.getInputStream();");
|
|
for (int j = 0; j < sig.length; j++)
|
|
{
|
|
out.print("$param_" + j + " = ");
|
|
if (sig[j] == Boolean.TYPE)
|
|
out.print("in.readBoolean();");
|
|
else if (sig[j] == Byte.TYPE)
|
|
out.print("in.readByte();");
|
|
else if (sig[j] == Character.TYPE)
|
|
out.print("in.readChar();");
|
|
else if (sig[j] == Short.TYPE)
|
|
out.print("in.readShort();");
|
|
else if (sig[j] == Integer.TYPE)
|
|
out.print("in.readInt();");
|
|
else if (sig[j] == Long.TYPE)
|
|
out.print("in.readLong();");
|
|
else if (sig[j] == Float.TYPE)
|
|
out.print("in.readFloat();");
|
|
else if (sig[j] == Double.TYPE)
|
|
out.print("in.readDouble();");
|
|
else
|
|
{
|
|
if (sig[j] != Object.class)
|
|
{
|
|
out.print("(" + getPrettyName(sig[j]) + ")");
|
|
needcastcheck = true;
|
|
}
|
|
out.print("in.readObject();");
|
|
}
|
|
out.println();
|
|
}
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
out.print("catch (java.io.IOException e) {");
|
|
ctrl.indent();
|
|
out.print("throw new java.rmi.UnmarshalException(\"error unmarshalling arguments\", e);");
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
if (needcastcheck)
|
|
{
|
|
out.print("catch (java.lang.ClassCastException e) {");
|
|
ctrl.indent();
|
|
out.print("throw new java.rmi.UnmarshalException(\"error unmarshalling arguments\", e);");
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
}
|
|
out.print("finally {");
|
|
ctrl.indent();
|
|
out.print("call.releaseInputStream();");
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
|
|
Class returntype = m.getReturnType();
|
|
if (returntype != Void.TYPE)
|
|
out.print(getPrettyName(returntype) + " $result = ");
|
|
out.print("server." + m.getName() + "(");
|
|
for (int j = 0; j < sig.length; j++)
|
|
{
|
|
out.print("$param_" + j);
|
|
if (j + 1 < sig.length)
|
|
out.print(", ");
|
|
}
|
|
out.println(");");
|
|
|
|
out.print("try {");
|
|
ctrl.indent();
|
|
out.print("java.io.ObjectOutput out = call.getResultStream(true);");
|
|
if (returntype != Void.TYPE)
|
|
{
|
|
out.println();
|
|
if (returntype == Boolean.TYPE)
|
|
out.print("out.writeBoolean($result);");
|
|
else if (returntype == Byte.TYPE)
|
|
out.print("out.writeByte($result);");
|
|
else if (returntype == Character.TYPE)
|
|
out.print("out.writeChar($result);");
|
|
else if (returntype == Short.TYPE)
|
|
out.print("out.writeShort($result);");
|
|
else if (returntype == Integer.TYPE)
|
|
out.print("out.writeInt($result);");
|
|
else if (returntype == Long.TYPE)
|
|
out.print("out.writeLong($result);");
|
|
else if (returntype == Float.TYPE)
|
|
out.print("out.writeFloat($result);");
|
|
else if (returntype == Double.TYPE)
|
|
out.print("out.writeDouble($result);");
|
|
else
|
|
out.print("out.writeObject($result);");
|
|
}
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
out.print("catch (java.io.IOException e) {");
|
|
ctrl.indent();
|
|
out.print("throw new java.rmi.MarshalException(\"error marshalling return\", e);");
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
out.print("break;");
|
|
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
out.println();
|
|
}
|
|
|
|
out.print("default:");
|
|
ctrl.indent();
|
|
out.print("throw new java.rmi.UnmarshalException(\"invalid method number\");");
|
|
ctrl.unindent();
|
|
out.print("}");
|
|
|
|
ctrl.unindent();
|
|
out.print("}");
|
|
|
|
ctrl.unindent();
|
|
out.println("}");
|
|
|
|
out.close();
|
|
}
|
|
|
|
private void compile(String name) throws Exception
|
|
{
|
|
Compiler comp = Compiler.getInstance();
|
|
if (verbose)
|
|
System.out.println("[Compiling class " + name + "]");
|
|
comp.setDestination(destination);
|
|
if (classpath != null)
|
|
comp.setClasspath(classpath);
|
|
comp.compile(name);
|
|
}
|
|
|
|
private static String getPrettyName(Class cls)
|
|
{
|
|
StringBuffer str = new StringBuffer();
|
|
for (int count = 0;; count++)
|
|
{
|
|
if (! cls.isArray())
|
|
{
|
|
str.append(cls.getName());
|
|
for (; count > 0; count--)
|
|
str.append("[]");
|
|
return (str.toString());
|
|
}
|
|
cls = cls.getComponentType();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sort exceptions so the most general go last.
|
|
*/
|
|
private Class[] sortExceptions(Class[] except)
|
|
{
|
|
for (int i = 0; i < except.length; i++)
|
|
{
|
|
for (int j = i + 1; j < except.length; j++)
|
|
{
|
|
if (except[i].isAssignableFrom(except[j]))
|
|
{
|
|
Class tmp = except[i];
|
|
except[i] = except[j];
|
|
except[j] = tmp;
|
|
}
|
|
}
|
|
}
|
|
return (except);
|
|
}
|
|
|
|
/**
|
|
* Process the options until we find the first argument.
|
|
*/
|
|
private void parseOptions()
|
|
{
|
|
for (;;)
|
|
{
|
|
if (next >= args.length || args[next].charAt(0) != '-')
|
|
break;
|
|
String arg = args[next];
|
|
next++;
|
|
|
|
// Accept `--' options if they look long enough.
|
|
if (arg.length() > 3 && arg.charAt(0) == '-' && arg.charAt(1) == '-')
|
|
arg = arg.substring(1);
|
|
|
|
if (arg.equals("-keep"))
|
|
keep = true;
|
|
else if (arg.equals("-keepgenerated"))
|
|
keep = true;
|
|
else if (arg.equals("-v1.1"))
|
|
{
|
|
need11Stubs = true;
|
|
need12Stubs = false;
|
|
}
|
|
else if (arg.equals("-vcompat"))
|
|
{
|
|
need11Stubs = true;
|
|
need12Stubs = true;
|
|
}
|
|
else if (arg.equals("-v1.2"))
|
|
{
|
|
need11Stubs = false;
|
|
need12Stubs = true;
|
|
}
|
|
else if (arg.equals("-g"))
|
|
{
|
|
}
|
|
else if (arg.equals("-depend"))
|
|
{
|
|
}
|
|
else if (arg.equals("-nowarn"))
|
|
{
|
|
}
|
|
else if (arg.equals("-verbose"))
|
|
verbose = true;
|
|
else if (arg.equals("-nocompile"))
|
|
compile = false;
|
|
else if (arg.equals("-classpath"))
|
|
{
|
|
classpath = args[next];
|
|
next++;
|
|
StringTokenizer st =
|
|
new StringTokenizer(classpath, File.pathSeparator);
|
|
URL[] u = new URL[st.countTokens()];
|
|
for (int i = 0; i < u.length; i++)
|
|
{
|
|
String path = st.nextToken();
|
|
File f = new File(path);
|
|
try
|
|
{
|
|
u[i] = f.toURL();
|
|
}
|
|
catch (MalformedURLException mue)
|
|
{
|
|
error("malformed classpath component " + path);
|
|
}
|
|
}
|
|
loader = new URLClassLoader(u);
|
|
}
|
|
else if (arg.equals("-help"))
|
|
usage();
|
|
else if (arg.equals("-version"))
|
|
{
|
|
System.out.println("rmic (" + System.getProperty("java.vm.name")
|
|
+ ") " + System.getProperty("java.vm.version"));
|
|
System.out.println();
|
|
System.out.println("Copyright 2006 Free Software Foundation, Inc.");
|
|
System.out.println("This is free software; see the source for copying conditions. There is NO");
|
|
System.out.println("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
|
|
System.exit(0);
|
|
}
|
|
else if (arg.equals("-d"))
|
|
{
|
|
destination = args[next];
|
|
next++;
|
|
}
|
|
else if (arg.charAt(1) == 'J')
|
|
{
|
|
}
|
|
else
|
|
error("unrecognized option `" + arg + "'");
|
|
}
|
|
}
|
|
|
|
private void findRemoteMethods() {
|
|
List rmeths = new ArrayList();
|
|
for (Class cur = clazz; cur != null; cur = cur.getSuperclass())
|
|
{
|
|
Class[] interfaces = cur.getInterfaces();
|
|
for (int i = 0; i < interfaces.length; i++)
|
|
{
|
|
if (java.rmi.Remote.class.isAssignableFrom(interfaces[i]))
|
|
{
|
|
Class remoteInterface = interfaces[i];
|
|
if (verbose)
|
|
System.out.println
|
|
("[implements " + remoteInterface.getName() + "]");
|
|
|
|
// check if the methods declare RemoteExceptions
|
|
Method[] meths = remoteInterface.getMethods();
|
|
for (int j = 0; j < meths.length; j++)
|
|
{
|
|
Method m = meths[j];
|
|
Class[] exs = m.getExceptionTypes();
|
|
|
|
boolean throwsRemote = false;
|
|
for (int k = 0; k < exs.length; k++)
|
|
{
|
|
if (exs[k].isAssignableFrom(RemoteException.class))
|
|
throwsRemote = true;
|
|
}
|
|
|
|
if (! throwsRemote)
|
|
{
|
|
logError("Method " + m
|
|
+ " does not throw a RemoteException");
|
|
continue;
|
|
}
|
|
|
|
rmeths.add(m);
|
|
}
|
|
|
|
mRemoteInterfaces.add(remoteInterface);
|
|
}
|
|
}
|
|
}
|
|
|
|
// intersect exceptions for doubly inherited methods
|
|
boolean[] skip = new boolean[rmeths.size()];
|
|
for (int i = 0; i < skip.length; i++)
|
|
skip[i] = false;
|
|
List methrefs = new ArrayList();
|
|
for (int i = 0; i < rmeths.size(); i++)
|
|
{
|
|
if (skip[i]) continue;
|
|
Method current = (Method) rmeths.get(i);
|
|
MethodRef ref = new MethodRef(current);
|
|
for (int j = i+1; j < rmeths.size(); j++)
|
|
{
|
|
Method other = (Method) rmeths.get(j);
|
|
if (ref.isMatch(other))
|
|
{
|
|
ref.intersectExceptions(other);
|
|
skip[j] = true;
|
|
}
|
|
}
|
|
methrefs.add(ref);
|
|
}
|
|
|
|
// Convert into a MethodRef array and sort them
|
|
remotemethods = (MethodRef[])
|
|
methrefs.toArray(new MethodRef[methrefs.size()]);
|
|
Arrays.sort(remotemethods);
|
|
}
|
|
|
|
/**
|
|
* Prints an error to System.err and increases the error count.
|
|
* @param theError
|
|
*/
|
|
private void logError(String theError)
|
|
{
|
|
errorCount++;
|
|
System.err.println("error:" + theError);
|
|
}
|
|
|
|
private static void error(String message)
|
|
{
|
|
System.err.println("rmic: " + message);
|
|
System.err.println("Try `rmic --help' for more information.");
|
|
System.exit(1);
|
|
}
|
|
|
|
private static void usage()
|
|
{
|
|
System.out.println("Usage: rmic [OPTION]... CLASS...\n" + "\n"
|
|
+ " -keep Don't delete any intermediate files\n"
|
|
+ " -keepgenerated Same as -keep\n"
|
|
+ " -v1.1 Java 1.1 style stubs only\n"
|
|
+ " -vcompat Java 1.1 & Java 1.2 stubs\n"
|
|
+ " -v1.2 Java 1.2 style stubs only\n"
|
|
+ " -g * Generated debugging information\n"
|
|
+ " -depend * Recompile out-of-date files\n"
|
|
+ " -nowarn * Suppress warning messages\n"
|
|
+ " -nocompile Don't compile the generated files\n"
|
|
+ " -verbose Output what's going on\n"
|
|
+ " -classpath <path> * Use given path as classpath\n"
|
|
+ " -d <directory> Specify where to place generated classes\n"
|
|
+ " -J<flag> * Pass flag to Java\n"
|
|
+ " -help Print this help, then exit\n"
|
|
+ " -version Print version number, then exit\n" + "\n"
|
|
+ " * Option currently ignored\n"
|
|
+ "Long options can be used with `--option' form as well.");
|
|
System.exit(0);
|
|
}
|
|
|
|
private static class MethodRef
|
|
implements Comparable
|
|
{
|
|
Method meth;
|
|
long hash;
|
|
List exceptions;
|
|
private String sig;
|
|
|
|
MethodRef(Method m)
|
|
{
|
|
meth = m;
|
|
sig = m.getName(); // XXX should be full signature used to compute hash
|
|
hash = RMIHashes.getMethodHash(m);
|
|
// add exceptions removing subclasses
|
|
exceptions = removeSubclasses(m.getExceptionTypes());
|
|
}
|
|
|
|
public int compareTo(Object obj)
|
|
{
|
|
MethodRef that = (MethodRef) obj;
|
|
int name = this.meth.getName().compareTo(that.meth.getName());
|
|
if (name == 0) {
|
|
return this.sig.compareTo(that.sig);
|
|
}
|
|
return name;
|
|
}
|
|
|
|
public boolean isMatch(Method m)
|
|
{
|
|
if (!meth.getName().equals(m.getName()))
|
|
return false;
|
|
|
|
Class[] params1 = meth.getParameterTypes();
|
|
Class[] params2 = m.getParameterTypes();
|
|
if (params1.length != params2.length)
|
|
return false;
|
|
|
|
for (int i = 0; i < params1.length; i++)
|
|
if (!params1[i].equals(params2[i])) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
private static List removeSubclasses(Class[] classes)
|
|
{
|
|
List list = new ArrayList();
|
|
for (int i = 0; i < classes.length; i++)
|
|
{
|
|
Class candidate = classes[i];
|
|
boolean add = true;
|
|
for (int j = 0; j < classes.length; j++)
|
|
{
|
|
if (classes[j].equals(candidate))
|
|
continue;
|
|
else if (classes[j].isAssignableFrom(candidate))
|
|
add = false;
|
|
}
|
|
if (add) list.add(candidate);
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
public void intersectExceptions(Method m)
|
|
{
|
|
List incoming = removeSubclasses(m.getExceptionTypes());
|
|
|
|
List updated = new ArrayList();
|
|
|
|
for (int i = 0; i < exceptions.size(); i++)
|
|
{
|
|
Class outer = (Class) exceptions.get(i);
|
|
boolean addOuter = false;
|
|
for (int j = 0; j < incoming.size(); j++)
|
|
{
|
|
Class inner = (Class) incoming.get(j);
|
|
|
|
if (inner.equals(outer) || inner.isAssignableFrom(outer))
|
|
addOuter = true;
|
|
else if (outer.isAssignableFrom(inner))
|
|
updated.add(inner);
|
|
}
|
|
|
|
if (addOuter)
|
|
updated.add(outer);
|
|
}
|
|
|
|
exceptions = updated;
|
|
}
|
|
}
|
|
}
|