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 | |
| 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
| -rw-r--r-- | libjava/ChangeLog | 15 | ||||
| -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 | 
7 files changed, 293 insertions, 90 deletions
| diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 28b41f4..0134d2a 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,18 @@ +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. +  2006-04-04  Tom Tromey  <tromey@redhat.com>  	PR libgcj/26990: 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;      }    }  } | 
