diff options
author | Archit Shah <ashah@redhat.com> | 2006-04-05 09:53:08 +0000 |
---|---|---|
committer | Andrew Haley <aph@gcc.gnu.org> | 2006-04-05 09:53:08 +0000 |
commit | 917173f4d24c2d6b004d74cf89c2776c556beab4 (patch) | |
tree | 1fb2f0f405b16b7bd558d6735496d8532b5b84d1 /libjava/gnu/java | |
parent | 6eee98936968c67edc8d9190b215819498840b57 (diff) | |
download | gcc-917173f4d24c2d6b004d74cf89c2776c556beab4.zip gcc-917173f4d24c2d6b004d74cf89c2776c556beab4.tar.gz gcc-917173f4d24c2d6b004d74cf89c2776c556beab4.tar.bz2 |
re PR libgcj/25414 (should update rmic)
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
Diffstat (limited to 'libjava/gnu/java')
-rw-r--r-- | libjava/gnu/java/rmi/rmic/Compile_gcj.java | 1 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/rmic/Compile_jikes.java | 1 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/rmic/Compile_kjc.java | 1 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/rmic/Compiler.java | 15 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/rmic/CompilerProcess.java | 31 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/rmic/RMIC.java | 319 |
6 files changed, 278 insertions, 90 deletions
diff --git a/libjava/gnu/java/rmi/rmic/Compile_gcj.java b/libjava/gnu/java/rmi/rmic/Compile_gcj.java index e55b2c3..e22611b 100644 --- a/libjava/gnu/java/rmi/rmic/Compile_gcj.java +++ b/libjava/gnu/java/rmi/rmic/Compile_gcj.java @@ -49,6 +49,7 @@ public class Compile_gcj extends CompilerProcess public String[] computeArguments (String filename) { return computeTypicalArguments(COMPILER_ARGS, + getClasspath(), getDestination(), filename); } diff --git a/libjava/gnu/java/rmi/rmic/Compile_jikes.java b/libjava/gnu/java/rmi/rmic/Compile_jikes.java index 2caf398..e70b50c 100644 --- a/libjava/gnu/java/rmi/rmic/Compile_jikes.java +++ b/libjava/gnu/java/rmi/rmic/Compile_jikes.java @@ -50,6 +50,7 @@ public class Compile_jikes extends CompilerProcess public String[] computeArguments (String filename)
{
return computeTypicalArguments(COMPILER_ARGS,
+ getClasspath(),
getDestination(),
filename);
}
diff --git a/libjava/gnu/java/rmi/rmic/Compile_kjc.java b/libjava/gnu/java/rmi/rmic/Compile_kjc.java index ce915ad6..79f1a84 100644 --- a/libjava/gnu/java/rmi/rmic/Compile_kjc.java +++ b/libjava/gnu/java/rmi/rmic/Compile_kjc.java @@ -50,6 +50,7 @@ public class Compile_kjc extends CompilerProcess public String[] computeArguments (String filename)
{
return computeTypicalArguments(COMPILER_ARGS,
+ getClasspath(),
getDestination(),
filename);
}
diff --git a/libjava/gnu/java/rmi/rmic/Compiler.java b/libjava/gnu/java/rmi/rmic/Compiler.java index d603804..fc1f846 100644 --- a/libjava/gnu/java/rmi/rmic/Compiler.java +++ b/libjava/gnu/java/rmi/rmic/Compiler.java @@ -82,12 +82,27 @@ public abstract class Compiler this.dest = dest; } + /** Get the classpath for compilation. */ + public String getClasspath () + { + return classpath; + } + + /** Set the classpath for compilation. */ + public void setClasspath (String classpath) + { + this.classpath = classpath; + } + /** Compile the given file. Throws exception on error. */ public abstract void compile (String name) throws Exception; /** The destination directory, or null if none set. */ protected String dest; + /** The classpath directory, or null if none set. */ + private String classpath; + /** Class prefix used when trying to find instance. */ private static final String classPrefix = "gnu.java.rmi.rmic.Compile_"; } diff --git a/libjava/gnu/java/rmi/rmic/CompilerProcess.java b/libjava/gnu/java/rmi/rmic/CompilerProcess.java index 09f8d9c..d7b2998 100644 --- a/libjava/gnu/java/rmi/rmic/CompilerProcess.java +++ b/libjava/gnu/java/rmi/rmic/CompilerProcess.java @@ -59,11 +59,27 @@ public abstract class CompilerProcess extends Compiler public static String[] computeTypicalArguments(String[] compilerArgs, String destination, String filename) { + return computeTypicalArguments(compilerArgs, null, destination, filename); + } + /** + * This is used to compute the command line for the process. + * Most compilers typically arrange their arguments as in + * <compiler name and arguments> <optional destination> <filename>. + * This method builds an argument array out that. It should be used + * to define computeArguments for those compilers that follow the + * argument convention described above. + */ + public static String[] computeTypicalArguments(String[] compilerArgs, + String classpath, + String destination, + String filename) + { /* length of compiler specific arguments */ - final int len = compilerArgs.length; + int len = compilerArgs.length; /* length of returned array of arguments */ - final int arglen = len + (destination == null ? 0 : 2) + 1; + final int arglen = len + (classpath == null ? 0 : 2) + + (destination == null ? 0 : 2) + 1; /* Allocate String array for computed arguments. */ String [] args = new String[arglen]; @@ -71,11 +87,18 @@ public abstract class CompilerProcess extends Compiler /* Fill in compiler arguments. */ System.arraycopy(compilerArgs, 0, args, 0, len); + /* Fill in classpath argument if necessary. */ + if (classpath != null) + { + args[len++] = "-classpath"; + args[len++] = classpath; + } + /* Fill in destination argument if necessary. */ if (destination != null) { - args[len] = "-d"; - args[len + 1] = destination; + args[len++] = "-d"; + args[len++] = destination; } /* Fill in filename */ diff --git a/libjava/gnu/java/rmi/rmic/RMIC.java b/libjava/gnu/java/rmi/rmic/RMIC.java index 27cd99b..33ec993 100644 --- a/libjava/gnu/java/rmi/rmic/RMIC.java +++ b/libjava/gnu/java/rmi/rmic/RMIC.java @@ -46,11 +46,18 @@ 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 @@ -69,11 +76,15 @@ public class RMIC 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 Class mRemoteInterface; + private List mRemoteInterfaces; public RMIC(String[] a) { @@ -115,10 +126,23 @@ public class RMIC return (true); } - private boolean processClass(String classname) throws Exception + 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(classname); + + analyzeClass(cls); + if (errorCount > 0) System.exit(1); generateStub(); @@ -126,16 +150,15 @@ public class RMIC generateSkel(); if (compile) { - compile(stubname.replace('.', File.separatorChar) + ".java"); + compile(fullstubname); if (need11Stubs) - compile(skelname.replace('.', File.separatorChar) + ".java"); + compile(fullskelname); } if (! keep) { - (new File(stubname.replace('.', File.separatorChar) + ".java")).delete(); + (new File(fullstubname)).delete(); if (need11Stubs) - (new File(skelname.replace('.', File.separatorChar) + ".java")) - .delete(); + (new File(fullskelname)).delete(); } return (true); } @@ -151,40 +174,8 @@ public class RMIC classname = cname; fullclassname = cname; - HashSet rmeths = new HashSet(); findClass(); - - // get the remote interface - mRemoteInterface = getRemoteInterface(clazz); - if (mRemoteInterface == null) - return; - if (verbose) - System.out.println("[implements " + mRemoteInterface.getName() + "]"); - - // check if the methods of the remote interface declare RemoteExceptions - Method[] meths = mRemoteInterface.getDeclaredMethods(); - for (int i = 0; i < meths.length; i++) - { - Class[] exceptions = meths[i].getExceptionTypes(); - int index = 0; - for (; index < exceptions.length; index++) - { - if (exceptions[index].equals(RemoteException.class)) - break; - } - if (index < exceptions.length) - rmeths.add(meths[i]); - else - logError("Method " + meths[i] - + " does not throw a java.rmi.RemoteException"); - } - - // Convert into a MethodRef array and sort them - remotemethods = new MethodRef[rmeths.size()]; - int c = 0; - for (Iterator i = rmeths.iterator(); i.hasNext();) - remotemethods[c++] = new MethodRef((Method) i.next()); - Arrays.sort(remotemethods); + findRemoteMethods(); } public Exception getException() @@ -194,21 +185,42 @@ public class RMIC private void findClass() throws ClassNotFoundException { - clazz = - Class.forName(fullclassname, true, ClassLoader.getSystemClassLoader()); + 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((destination == null ? "" - : destination - + File.separator) - + stubname.replace('.', - File.separatorChar) - + ".java")); + new TabbedWriter(new FileWriter(file)); out = new PrintWriter(ctrl); if (verbose) @@ -230,16 +242,7 @@ public class RMIC // Output interfaces we implement out.print("implements "); - /* Scan implemented interfaces, and only print remote interfaces. */ - Class[] ifaces = clazz.getInterfaces(); - Set remoteIfaces = new HashSet(); - for (int i = 0; i < ifaces.length; i++) - { - Class iface = ifaces[i]; - if (java.rmi.Remote.class.isAssignableFrom(iface)) - remoteIfaces.add(iface); - } - Iterator iter = remoteIfaces.iterator(); + Iterator iter = mRemoteInterfaces.iterator(); while (iter.hasNext()) { /* Print remote interface. */ @@ -328,7 +331,7 @@ public class RMIC { Method m = remotemethods[i].meth; out.print("$method_" + m.getName() + "_" + i + " = "); - out.print(mRemoteInterface.getName() + ".class.getMethod(\"" + out.print(m.getDeclaringClass().getName() + ".class.getMethod(\"" + m.getName() + "\""); out.print(", new java.lang.Class[] {"); // Output signature @@ -631,13 +634,13 @@ public class RMIC { 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((destination == null ? "" - : destination - + File.separator) - + skelname.replace('.', - File.separatorChar) - + ".java")); + new TabbedWriter(new FileWriter(file)); out = new PrintWriter(ctrl); if (verbose) @@ -882,6 +885,8 @@ public class RMIC if (verbose) System.out.println("[Compiling class " + name + "]"); comp.setDestination(destination); + if (classpath != null) + comp.setClasspath(classpath); comp.compile(name); } @@ -970,7 +975,27 @@ public class RMIC else if (arg.equals("-nocompile")) compile = false; else if (arg.equals("-classpath")) - next++; + { + 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")) @@ -996,22 +1021,75 @@ public class RMIC } } -/** - * Looks for the java.rmi.Remote interface that that is implemented by theClazz. - * @param theClazz the class to look in - * @return the Remote interface of theClazz or null if theClazz does not implement a Remote interface - */ - private Class getRemoteInterface(Class theClazz) - { - Class[] interfaces = theClazz.getInterfaces(); - for (int i = 0; i < interfaces.length; i++) + 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 (java.rmi.Remote.class.isAssignableFrom(interfaces[i])) - return interfaces[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); } - logError("Class " + theClazz.getName() - + " is not a remote object. It does not implement an interface that is a java.rmi.Remote-interface."); - return null; + + // Convert into a MethodRef array and sort them + remotemethods = (MethodRef[]) + methrefs.toArray(new MethodRef[methrefs.size()]); + Arrays.sort(remotemethods); } /** @@ -1054,25 +1132,94 @@ public class RMIC System.exit(0); } - static class MethodRef + private static class MethodRef implements Comparable { Method meth; - String sig; long hash; + List exceptions; + private String sig; MethodRef(Method m) { meth = m; - // We match on the name - but what about overloading? - XXX - sig = m.getName(); + 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; - return (this.sig.compareTo(that.sig)); + 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; } } } |