You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by David Maclean <da...@cm.co.za> on 2000/06/23 14:19:08 UTC

[PATCH] Using classlist and conditional compile for Rmic taskdef

Hi there

First of all I would like say that I started using Ant a few weeks ago on
a project here at work. I found that Ant was simple yet easy to use and
setup to get a compile. The use of and was for nightly builds on the CVS
tree. Ant is great and keep it up, however I discovered a limitation?? in
ant for RMI compiling classes. The project that I used it on is RMI-based
and has 60+ classes that need to be rmic'ed. Ant only allows for a single
classname hence I would have had to place 60+ rmic lines in the build.xml
file. The other thing was that the Rmic task would always compile.

The changes that I have made (see patch at the end) addresses both
issues. One may specify a filename that contains a list of classes (one
class per line) to the Rmic task and it will generate the _Stud and/or
_Skel file if it needs to. The classname argument is ignored if the
classlistFilename argument is specified.

I have tested this under WindowNT 4.0 and JDK 1.2.2 as well as HP-UX 11.0
and JDK 1.2.2

I hope this path is useful and if so you may include it into Ant.

Cheers

_________________________________________
David Maclean
david@cm.co.za
CCH Software Development
67 Old Fort Road
Durban, 4001
South Africa
Phone: +27 31 306 9777
Fax:   +27 31 306 9770

Patch follows:
=========================================================================================
*** jakarta-ant-freshcvs/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 23 12:49:56 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
***************
*** 67,72 ****
--- 69,75 ----
   * <li>stubVersion: The version of the stub prototol to use (1.1, 1.2, compat)
   * <li>sourceBase: The base directory for the generated stubs and skeletons
   * <li>classpath: Additional classpath, appended before the system classpath
+  * <li>classlistFilename: A filename that contains a list of classes one on each line
   * </ul>
   * Of these arguments, the <b>base</b> and <b>class</b> are required.
   * <p>
***************
*** 82,89 ****
--- 85,95 ----
      private String sourceBase;
      private String stubVersion;
      private String compileClasspath;
+     private String classlistFilename;
      private boolean filtering = false;
  
+     protected Vector compileList = new Vector();
+ 
      public void setBase(String base) {
          this.base = base;
      }
***************
*** 99,104 ****
--- 105,114 ----
          this.classname = classname;
      }
  
+     public void setClasslistFilename(String filename) {
+         this.classlistFilename = filename;
+     }
+ 
      public void setSourceBase(String sourceBase) {
          this.sourceBase = sourceBase;
      }
***************
*** 124,129 ****
--- 134,142 ----
          if (null != sourceBase)
              sourceBaseFile = project.resolveFile(sourceBase);
          String classpath = getCompileClasspath(baseFile);
+         if (classlistFilename != null) {
+             scanFiles(baseFile, project.resolveFile(classlistFilename));
+         }
          // XXX
          // need to provide an input stream that we read in from!
  
***************
*** 132,143 ****
          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";
--- 145,156 ----
          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++] = baseFile.getAbsolutePath();
          args[i++] = "-classpath";
          args[i++] = classpath;
          if (null != stubVersion) {
              if ("1.1".equals(stubVersion))
                  args[i++] = "-v1.1";
***************
*** 148,157 ****
--- 161,202 ----
          }
          if (null != sourceBase) args[i++] = "-keepgenerated";
  
+         if (classlistFilename != null) {
+             if (compileList.size() > 0) {
+                 project.log("RMI Compiling " + compileList.size() +
+                         " classes to " + baseFile);
+ 
+                 for (int j = 0; j < compileList.size(); j++) {
+                     args[i++] = (String) compileList.elementAt(j);
+                 }
                  compiler.compile(args);
+             }
+         } else {
+             if (shouldCompile(baseFile, classname)) {
+                 args[i++] = classname;
+                 compiler.compile(args);
+             }
+         }
  
          // Move the generated source file to the base directory
          if (null != sourceBase) {
+             if (classlistFilename != null) {
+                 for (int j = 0; j < compileList.size(); j++) {
+                     moveGeneratedFile(baseFile, sourceBaseFile, (String) compileList.elementAt(j));
+                 }
+             } else {
+                 moveGeneratedFile(baseFile, sourceBaseFile, classname);
+             }
+         }
+     }
+ 
+     /**
+      * 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 baseFile, File sourceBaseFile, String classname) 
+             throws BuildException {
          String stubFileName = classname.replace('.', '/') + "_Stub.java";
          File oldStubFile = new File(baseFile, stubFileName);
          File newStubFile = new File(sourceBaseFile, stubFileName);
***************
*** 177,182 ****
--- 222,305 ----
              }
          }
      }
+ 
+     /**
+      * Checks all the classes listed in classlistFilename to determine whether it needs
+      * to be rmic'd. It assumes that the baseFile is where the classes are generated.
+      *
+      * @exception org.apache.tools.ant.BuildException if the classlistFilename could not
+      * be found.
+      */
+     private void scanFiles(File baseFile, File classlistFile) throws BuildException {
+         if (! classlistFile.exists()) {
+             throw new BuildException("The classlist file " + classlistFilename + " does not exist.");
+         }
+         compileList.removeAllElements();
+         BufferedReader classlist = null;
+         try {
+             classlist = new BufferedReader(new FileReader(classlistFile));
+             String line = null;
+             while ((line = classlist.readLine()) != null) {
+                 StringTokenizer st = new StringTokenizer(line);
+                 if (st.hasMoreTokens()) {
+                     String classname = st.nextToken();
+                     if (shouldCompile(baseFile, classname)) {
+                         compileList.addElement(classname); 
+                     }
+                 }
+             }
+         } catch (IOException ie) {
+             throw new BuildException(ie.getMessage());
+         } finally {
+             if (classlist != null) {
+                 try {
+                     classlist.close();
+                 } catch (IOException e) {
+                     project.log("Unable to close classlist file", Project.MSG_WARN);
+                 }
+             }
+         }
+     }
+ 
+     /**
+      * 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 baseFile, String classname) {
+         long now = (new Date()).getTime();
+         File classfile = new File(baseFile, translateClassToFilename(classname));
+         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();
      }
  
      /**