View Javadoc
1   /*
2    * Copyright (c) 2009, 2012, 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 }