Hi there

Here is the reworking of Rmic taskdef as a matching task. The matching
task searches the base dir (the directory where classes are) and matches
files ending with .class. I have added the functionality that I discussed
in my previous email. The verify property is new and will check to ensure
that the class implements java.rmi.Remote or implements an interface that
extends java.rmi.Remote. The verify will try to do a Class.forName
however, the default class loader will not find the class with
Class.forName even though the directory is in the classpath on
startup. This is due to the directory not existing. If the directory
exists on startup and no class files are present but are created by javac,
then Class.forName will succeed. The solution to this would be to create a
custom class loader to handle class loads.

Without further comments, here is the patch (see end of message)

Cheers
David

-- 
_________________________________________
David Maclean
[EMAIL PROTECTED]
CCH Software Development
67 Old Fort Road
Durban, 4001
South Africa
Phone: +27 31 306 9777
Fax:   +27 31 306 9770

-------------------------- Patch starts here -------------------------------
*** jakarta-ant-cvs/src/main/org/apache/tools/ant/taskdefs/Rmic.java    Wed Feb 
16 16:31:45 2000
--- jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Rmic.java        Fri Jun 
30 15:05:17 2000
***************
*** 57,62 ****
--- 57,64 ----
  import org.apache.tools.ant.*;
  import java.io.*;
  import java.util.StringTokenizer;
+ import java.util.Vector;
+ import java.util.Date;
  
  /**
   * Task to compile RMI stubs and skeletons. This task can take the following
***************
*** 68,81 ****
   * <li>sourceBase: The base directory for the generated stubs and skeletons
   * <li>classpath: Additional classpath, appended before the system classpath
   * </ul>
!  * Of these arguments, the <b>base</b> and <b>class</b> are required.
   * <p>
   *
   * @author [EMAIL PROTECTED]
   * @author [EMAIL PROTECTED]
   */
  
! public class Rmic extends Task {
  
      private String base;
      private String classname;
--- 70,86 ----
   * <li>sourceBase: The base directory for the generated stubs and skeletons
   * <li>classpath: Additional classpath, appended before the system classpath
   * </ul>
!  * Of these arguments, <b>base</b> is required.
   * <p>
+  * If classname is specified then only that classname will be compiled. If it
+  * is absent, then <b>base</b> is traversed for classes according to patterns.
+  * <p>
   *
   * @author [EMAIL PROTECTED]
   * @author [EMAIL PROTECTED]
   */
  
! public class Rmic extends MatchingTask {
  
      private String base;
      private String classname;
***************
*** 82,89 ****
--- 87,97 ----
      private String sourceBase;
      private String stubVersion;
      private String compileClasspath;
+     private String verify;
      private boolean filtering = false;
  
+     private Vector compileList = new Vector();
+ 
      public void setBase(String base) {
          this.base = base;
      }
***************
*** 118,143 ****
          compileClasspath = project.translatePath(classpath);
      }
  
      public void execute() throws BuildException {
!         File baseFile = project.resolveFile(base);
          File sourceBaseFile = null;
          if (null != sourceBase)
              sourceBaseFile = project.resolveFile(sourceBase);
!         String classpath = getCompileClasspath(baseFile);
          // XXX
          // need to provide an input stream that we read in from!
  
          sun.rmi.rmic.Main compiler = new sun.rmi.rmic.Main(System.out, 
"rmic");
!             int argCount = 5;
          int i = 0;
          if (null != stubVersion) argCount++;
          if (null != sourceBase) argCount++;
          String[] args = new String[argCount];
          args[i++] = "-d";
!         args[i++] = baseFile.getAbsolutePath();
          args[i++] = "-classpath";
          args[i++] = classpath;
-         args[i++] = classname;
          if (null != stubVersion) {
              if ("1.1".equals(stubVersion))
                  args[i++] = "-v1.1";
--- 126,181 ----
          compileClasspath = project.translatePath(classpath);
      }
  
+     /**
+      * Indicates that the classes found by the directory match should be
+      * checked to see if they implement java.rmi.Remote.
+      * This defaults to false if not set.
+      */
+     public void setVerify(String verify) {
+         this.verify = verify;
+     }
+ 
      public void execute() throws BuildException {
!         File baseDir = project.resolveFile(base);
!         if (baseDir == null) {
!             throw new BuildException("base attribute must be set!");
!         }
!         if (!baseDir.exists()) {
!             throw new BuildException("base does not exist!");
!         }
!         boolean shouldVerify = false;
!         Boolean tmpBool = new Boolean(verify);
!         shouldVerify = tmpBool.booleanValue();
!         if (shouldVerify) {
!             project.log("Verify has been turned on.", project.MSG_INFO);
!         }
          File sourceBaseFile = null;
          if (null != sourceBase)
              sourceBaseFile = project.resolveFile(sourceBase);
!         String classpath = getCompileClasspath(baseDir);
! 
!         // scan base dirs to build up compile lists
! 
!         DirectoryScanner ds = this.getDirectoryScanner(baseDir);
! 
!         String[] files = ds.getIncludedFiles();
! 
!         scanDir(baseDir, files, shouldVerify);
! 
          // XXX
          // need to provide an input stream that we read in from!
  
          sun.rmi.rmic.Main compiler = new sun.rmi.rmic.Main(System.out, 
"rmic");
!         int argCount = 5;
          int i = 0;
          if (null != stubVersion) argCount++;
          if (null != sourceBase) argCount++;
+         if (compileList.size() > 0) argCount += compileList.size() - 1;
          String[] args = new String[argCount];
          args[i++] = "-d";
!         args[i++] = baseDir.getAbsolutePath();
          args[i++] = "-classpath";
          args[i++] = classpath;
          if (null != stubVersion) {
              if ("1.1".equals(stubVersion))
                  args[i++] = "-v1.1";
***************
*** 148,182 ****
          }
          if (null != sourceBase) args[i++] = "-keepgenerated";
  
!         compiler.compile(args);
  
          // Move the generated source file to the base directory
          if (null != sourceBase) {
!                 String stubFileName = classname.replace('.', '/') + 
"_Stub.java";
!             File oldStubFile = new File(baseFile, stubFileName);
!             File newStubFile = new File(sourceBaseFile, stubFileName);
              try {
!                 project.copyFile(oldStubFile, newStubFile, filtering);
!                 oldStubFile.delete();
              } catch (IOException ioe) {
!                 String msg = "Failed to copy " + oldStubFile + " to " +
!                              newStubFile + " due to " + ioe.getMessage();
                  throw new BuildException(msg);
              }
!             if (!"1.2".equals(stubVersion)) {
!                 String skelFileName = classname.replace('.', '/') + 
"_Skel.java";
!                 File oldSkelFile = new File(baseFile, skelFileName);
!                 File newSkelFile = new File(sourceBaseFile, skelFileName);
!                 try {
!                     project.copyFile(oldSkelFile, newSkelFile, filtering);
!                     oldSkelFile.delete();
!                 } catch (IOException ioe) {
!                     String msg = "Failed to copy " + oldSkelFile + " to " +
!                                   newSkelFile + " due to " + ioe.getMessage();
!                     throw new BuildException(msg);
                  }
              }
          }
      }
  
      /**
--- 186,359 ----
          }
          if (null != sourceBase) args[i++] = "-keepgenerated";
  
!         if (classname != null) {
!             if (shouldCompile(new File(baseDir, classname.replace('.', 
File.separatorChar)))) {
!                 args[i++] = classname;
!                 compiler.compile(args);
!             }
!         } else {
!             if (compileList.size() > 0) {
!                 project.log("RMI Compiling " + compileList.size() +
!                         " classes to " + baseDir);
  
+                 for (int j = 0; j < compileList.size(); j++) {
+                     args[i++] = (String) compileList.elementAt(j);
+                 }
+                 compiler.compile(args);
+             }
+         }
+ 
          // Move the generated source file to the base directory
          if (null != sourceBase) {
!             if (classname != null) {
!                 moveGeneratedFile(baseDir, sourceBaseFile, classname);
!             } else {
!                 for (int j = 0; j < compileList.size(); j++) {
!                     moveGeneratedFile(baseDir, sourceBaseFile, (String) 
compileList.elementAt(j));
!                 }
!             }
!         }
!     }
! 
!     /**
!      * Move the generated source file(s) to the base directory
!      *
!      * @exception org.apache.tools.ant.BuildException When error 
copying/removing files.
!      */
!     private void moveGeneratedFile (File baseDir, File sourceBaseFile, String 
classname)
!             throws BuildException {
!         String stubFileName = classname.replace('.', File.separatorChar) + 
"_Stub.java";
!         File oldStubFile = new File(baseDir, stubFileName);
!         File newStubFile = new File(sourceBaseFile, stubFileName);
!         try {
!             project.copyFile(oldStubFile, newStubFile, filtering);
!             oldStubFile.delete();
!         } catch (IOException ioe) {
!             String msg = "Failed to copy " + oldStubFile + " to " +
!                          newStubFile + " due to " + ioe.getMessage();
!             throw new BuildException(msg);
!         }
!         if (!"1.2".equals(stubVersion)) {
!             String skelFileName = classname.replace('.', '/') + "_Skel.java";
!             File oldSkelFile = new File(baseDir, skelFileName);
!             File newSkelFile = new File(sourceBaseFile, skelFileName);
              try {
!                 project.copyFile(oldSkelFile, newSkelFile, filtering);
!                 oldSkelFile.delete();
              } catch (IOException ioe) {
!                 String msg = "Failed to copy " + oldSkelFile + " to " +
!                               newSkelFile + " due to " + ioe.getMessage();
                  throw new BuildException(msg);
              }
!         }
!     }
! 
!     /**
!      * Scans the directory looking for class files to be compiled.
!      * The result is returned in the class variable compileList.
!      */
! 
!     protected void scanDir(File baseDir, String files[], boolean 
shouldVerify) {
!         compileList.removeAllElements();
!         for (int i = 0; i < files.length; i++) {
!             File baseFile = new File(baseDir, files[i]);
!             if (files[i].endsWith(".class") &&
!                      !files[i].endsWith("_Stub.class") &&
!                      !files[i].endsWith("_Skel.class")) {
!                 if (shouldCompile(baseFile)) {
!                     String classname = files[i].replace(File.separatorChar, 
'.');
!                     classname = classname.substring(0, 
classname.indexOf(".class"));
!                     boolean shouldAdd = true;
!                     if (shouldVerify) {
!                         try {
!                             Class testClass = Class.forName(classname);
!                             // One cannot RMIC an interface
!                             if (testClass.isInterface() || 
!isValidRmiRemote(testClass)) {
!                                 shouldAdd = false;
!                             }
!                         } catch (ClassNotFoundException e) {
!                             project.log("Unable to verify class " + classname 
+ 
!                                     ". It could not be found.", 
project.MSG_WARN);
!                         } catch (NoClassDefFoundError e) {
!                             project.log("Unable to verify class " + classname 
+ 
!                                     ". It is not defined.", project.MSG_WARN);
!                         }
!                     }
!                     if (shouldAdd) {
!                         project.log("Adding: " + classname + " to compile 
list",
!                                 project.MSG_VERBOSE);
!                         compileList.addElement(classname);
!                     }
                  }
              }
          }
+     }
+ 
+     /**
+      * Check to see if the class or superclasses/interfaces implement
+      * java.rmi.Remote.
+      */
+     private boolean isValidRmiRemote (Class testClass) {
+         Class rmiRemote = java.rmi.Remote.class;
+ 
+         if (rmiRemote.equals(testClass)) {
+             // This class is java.rmi.Remote
+             return true;
+         }
+ 
+         Class [] interfaces = testClass.getInterfaces();
+         if (interfaces != null) {
+             for (int i = 0; i < interfaces.length; i++) {
+                 if (rmiRemote.equals(interfaces[i])) {
+                     // This class directly implements java.rmi.Remote
+                     return true;
+                 }
+                 if (isValidRmiRemote(interfaces[i])) {
+                     return true;
+                 }
+             }
+         }
+         return false;
+     }
+ 
+     /**
+      * Determine whether the class needs to be RMI compiled. It looks at the 
_Stub.class
+      * and _Skel.class files' last modification date and compares it with the 
class' class file.
+      */
+     private boolean shouldCompile (File classFile) {
+         long now = (new Date()).getTime();
+         File stubFile = new File(classFile.getAbsolutePath().substring(0,
+                 classFile.getAbsolutePath().indexOf(".class")) + 
"_Stub.class");
+         File skelFile = new File(classFile.getAbsolutePath().substring(0,
+                 classFile.getAbsolutePath().indexOf(".class")) + 
"_Skel.class");
+         if (classFile.exists()) {
+             if (classFile.lastModified() > now) {
+                 project.log("Warning: file modified in the future: " +
+                         classFile, project.MSG_WARN);
+             }
+ 
+             if (classFile.lastModified() > stubFile.lastModified()) {
+                 return true;
+             } else if (classFile.lastModified() > skelFile.lastModified()) {
+                 return true;
+             } else {
+                 return false;
+             }
+         }
+         return true;
+     }
+ 
+     private String translateClassToFilename(String classname) {
+         StringTokenizer st = new StringTokenizer(classname, ".");
+         StringBuffer classFilename = new StringBuffer(classname.length());
+         while (st.hasMoreTokens()) {
+             classFilename.append(st.nextToken());
+             if (st.hasMoreTokens()) {
+                 classFilename.append(File.separator);
+             }
+         }
+         classFilename.append(".class");
+         return classFilename.toString();
      }
  
      /**


Reply via email to