1 /*
   2  * Copyright (c) 2009, 2014, 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     @Override
  86     public void setIncludes(String includes) {
  87         super.setIncludes(includes);
  88         this.includes = includes;
  89     }
  90 
  91     @Override
  92     public void execute() {
  93         if (includes != null && includes.trim().isEmpty())
  94             return;
  95 
  96         DirectoryScanner s = getDirectoryScanner(srcDir);
  97         String[] files = s.getIncludedFiles();
  98 //            System.err.println("Ant.execute: srcDir " + srcDir);
  99 //            System.err.println("Ant.execute: destDir " + destDir);
 100 //            System.err.println("Ant.execute: files " + Arrays.asList(files));
 101 
 102         files = filter(srcDir, destDir, files);
 103         if (files.length == 0)
 104             return;
 105         System.out.println("Generating " + files.length + " stub files to " + destDir);
 106 
 107         List<String> classNames = new ArrayList<>();
 108         for (String file: files) {
 109             classNames.add(file.replaceAll(".java$", "").replace('/', '.'));
 110         }
 111 
 112         if (!fork) {
 113             GenStubs m = new GenStubs();
 114             boolean ok = m.run(srcDir.getPath(), destDir, classNames);
 115             if (!ok)
 116                 throw new BuildException("genstubs failed");
 117         } else {
 118             List<String> cmd = new ArrayList<>();
 119             String java_home = System.getProperty("java.home");
 120             cmd.add(new File(new File(java_home, "bin"), "java").getPath());
 121             if (classpath != null)
 122                 cmd.add("-Xbootclasspath/p:" + classpath);
 123             cmd.add(GenStubs.class.getName());
 124             cmd.add("-sourcepath");
 125             cmd.add(srcDir.getPath());
 126             cmd.add("-s");
 127             cmd.add(destDir.getPath());
 128             cmd.addAll(classNames);
 129             //System.err.println("GenStubs exec " + cmd);
 130             ProcessBuilder pb = new ProcessBuilder(cmd);
 131             pb.redirectErrorStream(true);
 132             try {
 133                 Process p = pb.start();
 134                 try (BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
 135                     String line;
 136                     while ((line = in.readLine()) != null)
 137                         System.out.println(line);
 138                 }
 139                 int rc = p.waitFor();
 140                 if (rc != 0)
 141                     throw new BuildException("genstubs failed");
 142             } catch (IOException | InterruptedException e) {
 143                 throw new BuildException("genstubs failed", e);
 144             }
 145         }
 146     }
 147 
 148     String[] filter(File srcDir, File destDir, String[] files) {
 149         List<String> results = new ArrayList<String>();
 150         for (String f: files) {
 151             long srcTime = new File(srcDir, f).lastModified();
 152             long destTime = new File(destDir, f).lastModified();
 153             if (srcTime > destTime)
 154                 results.add(f);
 155         }
 156         return results.toArray(new String[results.size()]);
 157     }
 158 }