+2003-09-18 Dalibor Topic <robilad@kaffe.org>
+
+ * gnu/java/rmi/rmic/Compile_gcj.java (COMPILER_ARGS): New private
+ constant.
+ (computeArguments): use computeTypicalArguments.
+
+ * gnu/java/rmi/rmic/Makefile.am (EXTRA_DIST): Add Compile_kjc.java,
+ Compile_jikes.java and RMICException.java.
+ * gnu/java/rmi/rmic/Compile_kjc.java: New file.
+ * gnu/java/rmi/rmic/Compile_jikes.java: Likewise.
+ * gnu/java/rmi/rmic/RMICException.java: Likewise.
+
+ * gnu/java/rmi/rmic/Compiler.java (getDestination): New method.
+
+ * gnu/java/rmi/rmic/CompilerProcess.java: Import java.io.InputStream.
+ (computeTypicalArguments): New method.
+ (compile): Print compiler output to System.out. Collect compiler
+ error output and use it in exception message.
+
+ * gnu/java/rmi/rmic/RMIC.java: Import java.util.Set.
+ (destination): Initialize to null.
+ (run): Replace file separator with '.' when processing class.
+ (processClass): Replace '.' with file separator when compiling
+ classes.
+ (findClass): Use SystemClassLoader to load class.
+ (generateStub): Use full class name for generated stub, that puts
+ it in right path. Replace '.' with file separator when generating
+ stub file name. Write just the stub class name without package
+ information as class name, and constructor name. Write only
+ interface names for interfaces extending java.rmi.Remote as
+ implemented.
+ (generateSkel): Use full class name for generated skel, that puts
+ it in right path. Replace '.' with file separator when generating
+ stub file name. Write just the stub class name without package
+ information as class name.
+
+2003-09-18 Michael Koch <konqueror@gmx.de>
+
+ * Makefile.am (rmi_java_source_files):
+ Added gnu/java/rmi/rmic/Compile_kjc.java,
+ gnu/java/rmi/rmic/Compile_jikes.java and
+ gnu/java/rmi/rmic/RMICException.java
+ * Makefile.in: Regenerated.
+
2003-09-17 Graydon Hoare <graydon@redhat.com>
* gnu/java/awt/peer/gtk/GdkGraphics2D.java,
gnu/java/rmi/registry/RegistryImpl_Skel.java \
gnu/java/rmi/registry/RegistryImpl_Stub.java \
gnu/java/rmi/rmic/Compile_gcj.java \
+gnu/java/rmi/rmic/Compile_jikes.java \
+gnu/java/rmi/rmic/Compile_kjc.java \
gnu/java/rmi/rmic/Compiler.java \
gnu/java/rmi/rmic/CompilerProcess.java \
gnu/java/rmi/rmic/RMIC.java \
+gnu/java/rmi/rmic/RMICException.java \
gnu/java/rmi/rmic/TabbedWriter.java \
gnu/java/rmi/server/ConnectionRunnerPool.java \
gnu/java/rmi/server/ProtocolConstants.java \
gnu/java/rmi/registry/RegistryImpl_Skel.java \
gnu/java/rmi/registry/RegistryImpl_Stub.java \
gnu/java/rmi/rmic/Compile_gcj.java \
+gnu/java/rmi/rmic/Compile_jikes.java \
+gnu/java/rmi/rmic/Compile_kjc.java \
gnu/java/rmi/rmic/Compiler.java \
gnu/java/rmi/rmic/CompilerProcess.java \
gnu/java/rmi/rmic/RMIC.java \
+gnu/java/rmi/rmic/RMICException.java \
gnu/java/rmi/rmic/TabbedWriter.java \
gnu/java/rmi/server/ConnectionRunnerPool.java \
gnu/java/rmi/server/ProtocolConstants.java \
DATA = $(jar_DATA) $(pkgconfig_DATA) $(toolexecmainlib_DATA)
DIST_COMMON = README COPYING ChangeLog Makefile.am Makefile.in NEWS \
-THANKS acinclude.m4 aclocal.m4 configure configure.in \
-libgcj-test.spec.in libgcj.pc.in libgcj.spec.in
+THANKS acinclude.m4 aclocal.m4 config.guess config.sub configure \
+configure.in install-sh libgcj-test.spec.in libgcj.pc.in libgcj.spec.in \
+ltmain.sh missing mkinstalldirs
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-TAR = gtar
+TAR = tar
GZIP_ENV = --best
DIST_SUBDIRS = @DIRLTDL@ testsuite gcj include @DIRLTDL@ gcj include
DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
.deps/gnu/java/rmi/registry/RegistryImpl_Skel.P \
.deps/gnu/java/rmi/registry/RegistryImpl_Stub.P \
.deps/gnu/java/rmi/rmic/Compile_gcj.P \
+.deps/gnu/java/rmi/rmic/Compile_jikes.P \
+.deps/gnu/java/rmi/rmic/Compile_kjc.P \
.deps/gnu/java/rmi/rmic/Compiler.P \
.deps/gnu/java/rmi/rmic/CompilerProcess.P \
-.deps/gnu/java/rmi/rmic/RMIC.P .deps/gnu/java/rmi/rmic/TabbedWriter.P \
+.deps/gnu/java/rmi/rmic/RMIC.P .deps/gnu/java/rmi/rmic/RMICException.P \
+.deps/gnu/java/rmi/rmic/TabbedWriter.P \
.deps/gnu/java/rmi/server/ConnectionRunnerPool.P \
.deps/gnu/java/rmi/server/ProtocolConstants.P \
.deps/gnu/java/rmi/server/RMIDefaultSocketFactory.P \
/*
- Copyright (c) 2001 Free Software Foundation, Inc.
+ Copyright (c) 2001, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
/** Subclass of Compiler that can be used to invoke gcj. */
public class Compile_gcj extends CompilerProcess
{
+ private static final String [] COMPILER_ARGS =
+ {
+ "gcj",
+ "-C"
+ };
+
public String[] computeArguments (String filename)
{
- int len = 3 + (dest == null ? 0 : 2);
- String[] result = new String[len];
- int i = 0;
-
- result[i++] = "gcj";
- result[i++] = "-C";
- if (dest != null)
- {
- result[i++] = "-d";
- result[i++] = dest;
- }
- result[i++] = filename;
-
- return result;
+ return computeTypicalArguments(COMPILER_ARGS,
+ getDestination(),
+ filename);
}
}
--- /dev/null
+/*\r
+ Copyright (c) 2003 Free Software Foundation, Inc.\r
+\r
+This file is part of GNU Classpath.\r
+\r
+GNU Classpath is free software; you can redistribute it and/or modify\r
+it under the terms of the GNU General Public License as published by\r
+the Free Software Foundation; either version 2, or (at your option)\r
+any later version.\r
+ \r
+GNU Classpath is distributed in the hope that it will be useful, but\r
+WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with GNU Classpath; see the file COPYING. If not, write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA\r
+02111-1307 USA.\r
+\r
+Linking this library statically or dynamically with other modules is\r
+making a combined work based on this library. Thus, the terms and\r
+conditions of the GNU General Public License cover the whole\r
+combination.\r
+\r
+As a special exception, the copyright holders of this library give you\r
+permission to link this library with independent modules to produce an\r
+executable, regardless of the license terms of these independent\r
+modules, and to copy and distribute the resulting executable under\r
+terms of your choice, provided that you also meet, for each linked\r
+independent module, the terms and conditions of the license of that\r
+module. An independent module is a module which is not derived from\r
+or based on this library. If you modify this library, you may extend\r
+this exception to your version of the library, but you are not\r
+obligated to do so. If you do not wish to do so, delete this\r
+exception statement from your version. */\r
+\r
+package gnu.java.rmi.rmic;\r
+\r
+/** Subclass of Compiler that can be used to invoke jikes. */\r
+public class Compile_jikes extends CompilerProcess\r
+{\r
+ /** Compiler arguments to invoke jikes */\r
+ private static final String [] COMPILER_ARGS = \r
+ {\r
+ "jikes"\r
+ };\r
+\r
+ /** Compute the command line for the process. */\r
+ public String[] computeArguments (String filename)\r
+ {\r
+ return computeTypicalArguments(COMPILER_ARGS,\r
+ getDestination(),\r
+ filename);\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ Copyright (c) 2003 Free Software Foundation, Inc.\r
+\r
+This file is part of GNU Classpath.\r
+\r
+GNU Classpath is free software; you can redistribute it and/or modify\r
+it under the terms of the GNU General Public License as published by\r
+the Free Software Foundation; either version 2, or (at your option)\r
+any later version.\r
+ \r
+GNU Classpath is distributed in the hope that it will be useful, but\r
+WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with GNU Classpath; see the file COPYING. If not, write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA\r
+02111-1307 USA.\r
+\r
+Linking this library statically or dynamically with other modules is\r
+making a combined work based on this library. Thus, the terms and\r
+conditions of the GNU General Public License cover the whole\r
+combination.\r
+\r
+As a special exception, the copyright holders of this library give you\r
+permission to link this library with independent modules to produce an\r
+executable, regardless of the license terms of these independent\r
+modules, and to copy and distribute the resulting executable under\r
+terms of your choice, provided that you also meet, for each linked\r
+independent module, the terms and conditions of the license of that\r
+module. An independent module is a module which is not derived from\r
+or based on this library. If you modify this library, you may extend\r
+this exception to your version of the library, but you are not\r
+obligated to do so. If you do not wish to do so, delete this\r
+exception statement from your version. */\r
+\r
+package gnu.java.rmi.rmic;\r
+\r
+/** Subclass of Compiler that can be used to invoke kjc. */\r
+public class Compile_kjc extends CompilerProcess\r
+{\r
+ /** Compiler arguments to invoke kjc */\r
+ private static final String [] COMPILER_ARGS = \r
+ {\r
+ "kjc"\r
+ };\r
+\r
+ /** Compute the command line for the process. */\r
+ public String[] computeArguments (String filename)\r
+ {\r
+ return computeTypicalArguments(COMPILER_ARGS,\r
+ getDestination(),\r
+ filename);\r
+ }\r
+}\r
/*
- Copyright (c) 2001 Free Software Foundation, Inc.
+ Copyright (c) 2001, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
package gnu.java.rmi.rmic;
-/** A Compiler object can be used to compile a .java file into a
+/**
+ * A Compiler object can be used to compile a .java file into a
* .class file. This is an abstract class; the
* <code>getInstance()</code> method is used to obtain the actual
- * compiler object. */
+ * compiler object.
+ */
public abstract class Compiler
{
// Can't directly instantiate.
return null;
}
+ /** Get the directory where output files will be put. */
+ public String getDestination ()
+ {
+ return dest;
+ }
+
/** Set the directory where output files will be put. */
public void setDestination (String dest)
{
/*
- Copyright (c) 2001 Free Software Foundation, Inc.
+ Copyright (c) 2001, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
package gnu.java.rmi.rmic;
-/** Subclass of Compiler that can be subclassed to invoke a process to
- * do its work. */
+import java.io.InputStream;
+
+/**
+ * Subclass of Compiler that can be subclassed to invoke a process to
+ * do its work.
+ */
public abstract class CompilerProcess extends Compiler
{
/** This is used to compute the command line for the process. */
public abstract String[] computeArguments (String 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 destination, String filename)
+ {
+ /* length of compiler specific arguments */
+ final int len = compilerArgs.length;
+
+ /* length of returned array of arguments */
+ final int arglen = len + (destination == null ? 0 : 2) + 1;
+
+ /* Allocate String array for computed arguments. */
+ String [] args = new String[arglen];
+
+ /* Fill in compiler arguments. */
+ System.arraycopy(compilerArgs, 0, args, 0, len);
+
+ /* Fill in destination argument if necessary. */
+ if (destination != null)
+ {
+ args[len] = "-d";
+ args[len + 1] = destination;
+ }
+
+ /* Fill in filename */
+ args[arglen - 1] = filename;
+
+ return args;
+ }
+
public void compile (String name) throws Exception
{
String[] args = computeArguments (name);
Process p = Runtime.getRuntime ().exec (args);
- // FIXME: probably should collect compiler output here and then
- // put it into the exception message.
+
+ /* Print compiler output to System.out. */
+ InputStream procin = p.getInputStream();
+ for (int ch = procin.read(); ch != -1; ch = procin.read())
+ System.out.print((char) ch);
+
+ /* Collect compiler error output in a buffer.
+ * If compilation fails, it will be used for an error message.
+ */
+ StringBuffer stderr = new StringBuffer();
+ InputStream procerr = p.getErrorStream();
+ for (int ch = procerr.read(); ch != -1; ch = procerr.read())
+ stderr.append((char) ch);
+
int result;
while (true)
{
if (result != 0)
{
// FIXME: wrong exception class.
- throw new Exception ("compiler exited with status: " + result);
+ throw new Exception ("compiler exited with status: " + result,
+ new RMICException(stderr.toString()));
}
}
}
/*
- Copyright (c) 1996, 1997, 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (c) 1996, 1997, 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.rmi.RemoteException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Arrays;
-import java.lang.Comparable;
+import java.util.Set;
+
import gnu.java.rmi.server.RMIHashes;
public class RMIC {
private MethodRef[] remotemethods;
private String stubname;
private String skelname;
+private int errorCount = 0;
+private Class mRemoteInterface;
public RMIC(String[] a) {
args = a;
}
if (verbose) {
System.out.println("[Processing class " + args[i] + ".class]");
}
- processClass(args[i]);
+ processClass(args[i].replace(File.separatorChar, '.'));
}
catch (Exception e) {
exception = e;
}
private boolean processClass(String classname) throws Exception {
+ errorCount = 0;
analyzeClass(classname);
+ if(errorCount > 0) {
+ System.exit(1);
+ }
generateStub();
if (need11Stubs) {
generateSkel();
}
if (compile) {
- compile(stubname + ".java");
+ compile(stubname.replace('.', File.separatorChar) + ".java");
if (need11Stubs) {
- compile(skelname + ".java");
+ compile(skelname.replace('.', File.separatorChar) + ".java");
}
}
if (!keep) {
- (new File(stubname + ".java")).delete();
+ (new File(stubname.replace('.', File.separatorChar) + ".java")).delete();
if (need11Stubs) {
- (new File(skelname + ".java")).delete();
+ (new File(skelname.replace('.', File.separatorChar) + ".java")).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);
}
fullclassname = cname;
+
HashSet rmeths = new HashSet();
findClass();
- for (Class cls = clazz; cls != null; cls = cls.getSuperclass()) {
- // Keep going down the inheritence tree until we hit the system
- if (cls.getName().startsWith("java.")) {
- break;
- }
-
- Method[] meths = cls.getDeclaredMethods();
- for (int i = 0; i < meths.length; i++) {
- // Only include public methods
- int mods = meths[i].getModifiers();
- if (Modifier.isPublic(mods) && !Modifier.isStatic(mods)) {
- // Should check exceptions here. - XXX
+
+ // get the remote interface
+ mRemoteInterface = getRemoteInterface(clazz);
+ if(mRemoteInterface == null)
+ return;
+ if(verbose){
+ System.out.println("[implements "+mRemoteInterface.getName()+"]");
+ }
- // Add this one in.
- rmeths.add(meths[i]);
+ // 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;
}
private void findClass() throws ClassNotFoundException {
- clazz = Class.forName(fullclassname);
+ clazz = Class.forName(fullclassname, true, ClassLoader.getSystemClassLoader());
}
private void generateStub() throws IOException {
- stubname = classname + "_Stub";
- ctrl = new TabbedWriter(new FileWriter(stubname + ".java"));
+ stubname = fullclassname + "_Stub";
+ String stubclassname = classname + "_Stub";
+ ctrl = new TabbedWriter(new FileWriter((destination == null ? "" : destination + File.separator)
+ + stubname.replace('.', File.separatorChar)
+ + ".java"));
out = new PrintWriter(ctrl);
if (verbose) {
out.println();
}
- out.print("public final class " + stubname);
+ out.print("public final class " + stubclassname);
ctrl.indent();
out.println("extends java.rmi.server.RemoteStub");
// Output interfaces we implement
out.print("implements ");
- Class[] ifaces = clazz.getInterfaces();
- for (int i = 0; i < ifaces.length; i++) {
- out.print(ifaces[i].getName());
- if (i+1 < ifaces.length) {
+ /* 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();
+ 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();
for (int i = 0; i < remotemethods.length; i++) {
Method m = remotemethods[i].meth;
out.print("$method_" + m.getName() + "_" + i + " = ");
- out.print(fullclassname + ".class.getMethod(\"" + m.getName() + "\"");
+ out.print(mRemoteInterface.getName() + ".class.getMethod(\"" + m.getName() + "\"");
out.print(", new java.lang.Class[] {");
// Output signature
Class[] sig = m.getParameterTypes();
// Constructors
if (need11Stubs) {
- out.print("public " + stubname + "() {");
+ out.print("public " + stubclassname + "() {");
ctrl.indent();
out.print("super();");
ctrl.unindent();
}
if (need12Stubs) {
- out.print("public " + stubname + "(java.rmi.server.RemoteRef ref) {");
+ out.print("public " + stubclassname + "(java.rmi.server.RemoteRef ref) {");
ctrl.indent();
out.print("super(ref);");
ctrl.unindent();
}
private void generateSkel() throws IOException {
- skelname = classname + "_Skel";
- ctrl = new TabbedWriter(new FileWriter(skelname + ".java"));
+ skelname = fullclassname + "_Skel";
+ String skelclassname = classname + "_Skel";
+ ctrl = new TabbedWriter(new FileWriter((destination == null ? "" : destination + File.separator)
+ + skelname.replace('.', File.separatorChar)
+ + ".java"));
out = new PrintWriter(ctrl);
if (verbose) {
out.println();
}
- out.print("public final class " + skelname);
+ out.print("public final class " + skelclassname);
ctrl.indent();
// Output interfaces we implement
}
}
+/**
+ * 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++)
+ {
+ if (java.rmi.Remote.class.isAssignableFrom(interfaces[i]))
+ {
+ return interfaces[i];
+ }
+ }
+ logError("Class "+ theClazz.getName()
+ + " is not a remote object. It does not implement an interface that is a java.rmi.Remote-interface.");
+ return null;
+}
+
+/**
+ * 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.");
--- /dev/null
+/*\r
+ Copyright (c) 2003 Free Software Foundation, Inc.\r
+\r
+This file is part of GNU Classpath.\r
+\r
+GNU Classpath is free software; you can redistribute it and/or modify\r
+it under the terms of the GNU General Public License as published by\r
+the Free Software Foundation; either version 2, or (at your option)\r
+any later version.\r
+ \r
+GNU Classpath is distributed in the hope that it will be useful, but\r
+WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with GNU Classpath; see the file COPYING. If not, write to the\r
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA\r
+02111-1307 USA.\r
+\r
+Linking this library statically or dynamically with other modules is\r
+making a combined work based on this library. Thus, the terms and\r
+conditions of the GNU General Public License cover the whole\r
+combination.\r
+\r
+As a special exception, the copyright holders of this library give you\r
+permission to link this library with independent modules to produce an\r
+executable, regardless of the license terms of these independent\r
+modules, and to copy and distribute the resulting executable under\r
+terms of your choice, provided that you also meet, for each linked\r
+independent module, the terms and conditions of the license of that\r
+module. An independent module is a module which is not derived from\r
+or based on this library. If you modify this library, you may extend\r
+this exception to your version of the library, but you are not\r
+obligated to do so. If you do not wish to do so, delete this\r
+exception statement from your version. */\r
+\r
+package gnu.java.rmi.rmic;\r
+\r
+/**\r
+ * Thrown by the underlying compiler used by RMIC when it fails to compile a file.\r
+ *\r
+ * @author Dalibor Topic <robilad@kaffe.org>\r
+ */\r
+\r
+public class RMICException extends Exception {\r
+ /**\r
+ * Create an exception with a message. The cause remains uninitialized.\r
+ *\r
+ * @param s the message string\r
+ * @see #initCause(Throwable)\r
+ */\r
+ public RMICException(String message) {\r
+ super(message);\r
+ }\r
+\r
+ /**\r
+ * Create an exception with a message and a cause.\r
+ *\r
+ * @param s the message string\r
+ * @param cause the cause of this exception\r
+ */\r
+ public RMICException(String message, Throwable cause) {\r
+ super(message, cause);\r
+ }\r
+}\r