1 /*
   2  * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package anttasks;
  27 
  28 import genstubs.GenStubs;
  29 
  30 import java.io.*;
  31 import java.util.*;
  32 
  33 import org.apache.tools.ant.BuildException;
  34 import org.apache.tools.ant.DirectoryScanner;
  35 import org.apache.tools.ant.taskdefs.MatchingTask;
  36 import org.apache.tools.ant.types.Path;
  37 import org.apache.tools.ant.types.Reference;
  38 
  39 /**
  40  * Files are specified with an implicit fileset, using srcdir as a base directory.
  41  * The set of files to be included is specified with an includes attribute or
  42  * nested <includes> set. However, unlike a normal fileset, an empty includes attribute
  43  * means "no files" instead of "all files".  The Ant task also accepts "fork=true" and
  44  * classpath attribute or nested <classpath> element to run GenStubs in a separate VM
  45  * with the specified path. This is likely necessary if a JDK 7 parser is required to read the
  46  * JDK 7 input files.
  47  */
  48 public class GenStubsTask extends MatchingTask {
  49     private File srcDir;
  50     private File destDir;
  51     private boolean fork;
  52     private Path classpath;
  53     private String includes;
  54     
  55     public void setSrcDir(File dir) {
  56         this.srcDir = dir;
  57     }
  58     
  59     public void setDestDir(File dir) {
  60         this.destDir = dir;
  61     }
  62     
  63     public void setFork(boolean v) {
  64         this.fork = v;
  65     }
  66     
  67     public void setClasspath(Path cp) {
  68         if (classpath == null)
  69             classpath = cp;
  70         else
  71             classpath.append(cp);
  72     }
  73     
  74     public Path createClasspath() {
  75         if (classpath == null) {
  76             classpath = new Path(getProject());
  77         }
  78         return classpath.createPath();
  79     }
  80     
  81     public void setClasspathRef(Reference r) {
  82         createClasspath().setRefid(r);
  83     }
  84     
  85     public void setIncludes(String includes) {
  86         super.setIncludes(includes);
  87         this.includes = includes;
  88     }
  89     
  90     @Override
  91     public void execute() {
  92         if (includes != null && includes.trim().isEmpty())
  93             return;
  94         
  95         DirectoryScanner s = getDirectoryScanner(srcDir);
  96         String[] files = s.getIncludedFiles();
  97 //            System.err.println("Ant.execute: srcDir " + srcDir);
  98 //            System.err.println("Ant.execute: destDir " + destDir);
  99 //            System.err.println("Ant.execute: files " + Arrays.asList(files));
 100         
 101         files = filter(srcDir, destDir, files);
 102         if (files.length == 0)
 103             return;
 104         System.out.println("Generating " + files.length + " stub files to " + destDir);
 105         
 106         List<String> classNames = new ArrayList<String>();
 107         for (String file: files) {
 108             classNames.add(file.replaceAll(".java$", "").replace('/', '.'));
 109         }
 110         
 111         if (!fork) {
 112             GenStubs m = new GenStubs();
 113             boolean ok = m.run(srcDir.getPath(), destDir, classNames);
 114             if (!ok)
 115                 throw new BuildException("genstubs failed");
 116         } else {
 117             List<String> cmd = new ArrayList<String>();
 118             String java_home = System.getProperty("java.home");
 119             cmd.add(new File(new File(java_home, "bin"), "java").getPath());
 120             if (classpath != null)
 121                 cmd.add("-Xbootclasspath/p:" + classpath);
 122             cmd.add(GenStubs.class.getName());
 123             cmd.add("-sourcepath");
 124             cmd.add(srcDir.getPath());
 125             cmd.add("-s");
 126             cmd.add(destDir.getPath());
 127             cmd.addAll(classNames);
 128             //System.err.println("GenStubs exec " + cmd);
 129             ProcessBuilder pb = new ProcessBuilder(cmd);
 130             pb.redirectErrorStream(true);
 131             try {
 132                 Process p = pb.start();
 133                 BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
 134                 try {
 135                     String line;
 136                     while ((line = in.readLine()) != null)
 137                         System.out.println(line);
 138                 } finally {
 139                     in.close();
 140                 }
 141                 int rc = p.waitFor();
 142                 if (rc != 0)
 143                     throw new BuildException("genstubs failed");
 144             } catch (IOException e) {
 145                 throw new BuildException("genstubs failed", e);
 146             } catch (InterruptedException e) {
 147                 throw new BuildException("genstubs failed", e);
 148             }
 149         }
 150     }
 151     
 152     String[] filter(File srcDir, File destDir, String[] files) {
 153         List<String> results = new ArrayList<String>();
 154         for (String f: files) {
 155             long srcTime = new File(srcDir, f).lastModified();
 156             long destTime = new File(destDir, f).lastModified();
 157             if (srcTime > destTime)
 158                 results.add(f);
 159         }
 160         return results.toArray(new String[results.size()]);
 161     }
 162 }