View Javadoc

1   /*************1**************************************************************************
2    * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved.                 *
3    * http://aspectwerkz.codehaus.org                                                    *
4    * ---------------------------------------------------------------------------------- *
5    * The software in this package is published under the terms of the LGPL license      *
6    * a copy of which has been included with this distribution in the license.txt file.  *
7    **************************************************************************************/
8   package org.codehaus.aspectwerkz.annotation;
9   
10  
11  import java.io.BufferedReader;
12  import java.io.File;
13  import java.io.FileReader;
14  import java.io.IOException;
15  import java.util.ArrayList;
16  import java.util.List;
17  import java.util.Iterator;
18  
19  import org.apache.tools.ant.BuildException;
20  import org.apache.tools.ant.DirectoryScanner;
21  import org.apache.tools.ant.Project;
22  import org.apache.tools.ant.Task;
23  import org.apache.tools.ant.taskdefs.MatchingTask;
24  import org.apache.tools.ant.taskdefs.Copy;
25  import org.apache.tools.ant.types.FileSet;
26  import org.apache.tools.ant.types.Path;
27  import org.apache.tools.ant.types.Reference;
28  
29  /***
30   * AnnotationC Ant task.
31   *
32   * Use the following parameters to configure the task:
33   * <ul>
34   * <li>verbose: [optional] flag marking the task verbosity [true / false]</li>
35   * <li>properties: [optional] path to a properties file when user-defined annoations are to be used</li>
36   * <li>destdir: [optional unless input classes are in more than one path] directory where to put annnotated class files</li>
37   * <li>copytodest: [optional] filename pattern to copy extra resources like dtd, xml, or properties files that were found
38   *      in the input classes path(s). By defaults, only ".class" files will be handled. It is ignored if "destdir" is not set.</li>
39   * </ul>
40   * <p/>
41   * Use the following parameters to configure the classpath to point to the classes to be weaved. Those can be specified
42   * with nested elements as well / instead:
43   * <ul>
44   * <li>properties path=..: extra path to a properties file when user-defined annoations are to be used</li>
45   * <li>classpath: classpath of classes to annotated, as well as classpath to discover user-defined annotations if any</li>
46   * <li>classpathref: classpath reference of classes to annotated, as well as classpath to discover user-defined annotations if any</li>
47   * <li>srcdir: directory where to find annotated java source files</li>
48   * <li>sourcepath: path where to find annotated java source files</li>
49   * <li>sourcepathref: path reference where to find annotated java source files</li>
50   * </ul>
51   * <p/>
52   * Nested elements are similar to the "javac" task when you configure a classpath and a sourcepath:
53   * <ul>
54   * <li>classpath: Path-like structure of classes to annotated, as well as classpath to discover user-defined annotations if any</li>
55   * <li>src: single path entry of annotated java source files</li>
56   * <li>sourcepath: Path-like structure of annotated java source files</li>
57   * <li>fileset: fileset to contain annotated java source files</li>
58   * </ul>
59   * <p/>
60   *
61   * @author <a href='mailto:the_mindstorm@evolva.ro'>the_mindstorm(at)evolva(dot)ro</a>
62   * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
63   */
64  public class AnnotationCTask extends Task {
65  
66      private final static String CLASS_PATTERN = "**/*.class";
67  
68  
69      private boolean m_verbose;
70      private String m_includePattern;
71      private Path m_classpath;
72      private Path m_src;
73      private File m_properties;
74      private Path m_propertiesNested;
75      private File m_destdir;
76      private List m_filesets = new ArrayList();
77  
78      /***
79       * <task properties=..>
80       *
81       * @param annotationFile
82       */
83      public void setProperties(File annotationFile) {
84          m_properties = annotationFile;
85      }
86  
87      /***
88       * <task verbose=..>
89       *
90       * @param isVerbose
91       */
92      public void setVerbose(boolean isVerbose) {
93          m_verbose = isVerbose;
94      }
95  
96      /***
97       * <task copytodest="** slash *">
98       * @param pattern
99       */
100     public void setCopytodest(String pattern) {
101         m_includePattern = pattern;
102     }
103 
104     /***
105      * <task destdir=..>
106      *
107      * @param destdir
108      */
109     public void setDestdir(File destdir) {
110         m_destdir = destdir;
111     }
112 
113     //-- <properties .., <src .., <sourcepath.. and srcdir=.. sourcepathref=..
114 
115     public Path createProperties() {
116         if (m_propertiesNested == null)
117             m_propertiesNested = new Path(getProject());
118         return m_propertiesNested.createPath();
119     }
120 
121     public Path createSrc() {
122         if (m_src == null)
123             m_src = new Path(getProject());
124         return m_src.createPath();
125     }
126 
127     public void setSrcdir(Path srcDir) {
128         if (m_src == null)
129             m_src = srcDir;
130         else
131             m_src.append(srcDir);
132     }
133 
134     public void setSourcepath(Path sourcepath) {
135         if (m_src == null)
136             m_src = sourcepath;
137         else
138             m_src.append(sourcepath);
139     }
140 
141     public Path createSourcepath() {
142         if (m_src == null)
143             m_src = new Path(getProject());
144         return m_src.createPath();
145     }
146 
147     public void setSourcepathRef(Reference r) {
148         createSourcepath().setRefid(r);
149     }
150 
151 
152     //--- classpath
153 
154     public void setClasspath(Path classpath) {
155         if (m_classpath == null)
156             m_classpath = classpath;
157         else
158             m_classpath.append(classpath);
159     }
160 
161     public Path createClasspath() {
162         if (m_classpath == null)
163             m_classpath = new Path(getProject());
164         return m_classpath.createPath();
165     }
166 
167     public void setClasspathRef(Reference r) {
168         createClasspath().setRefid(r);
169     }
170 
171     //---- fileset for source files
172 
173     public void addFileset(FileSet fileset) {
174         m_filesets.add(fileset);
175     }
176 
177     //-- Ant task
178 
179     public void execute() throws BuildException {
180         try {
181             if (m_classpath == null) {
182                 throw new BuildException("No classes specified [<classpath, classpath=.. classpathref=..]");
183             }
184             if (m_destdir == null && m_classpath.list().length > 1) {
185                 throw new BuildException(
186                         "When using more than one classpath directory, it is mandatory to specify [destdir=..]"
187                 );
188             }
189             if (m_filesets.size() == 0 && (m_src == null || m_src.size() == 0)) {
190                 throw new BuildException("No source specified [<include, <sourcepath, srcdir=..]");
191             }
192             if (m_properties != null && !m_properties.exists() && !m_properties.isFile()) {
193                 throw new BuildException("properties file specified but not a valid file [" + m_properties + "]");
194             }
195             List allProperties = new ArrayList();
196             allProperties.add(m_properties.getAbsolutePath());
197             allProperties.addAll(getDirectories(m_propertiesNested));
198 
199             // compute source directory list
200             List srcDirs = getDirectories(m_src);
201             List srcFiles = getFilesetFiles(m_filesets);
202             List classpathDirs = getDirectories(m_classpath);
203 
204             if (m_verbose) {
205                 System.out.println("Source dir   : " + dump(srcDirs));
206                 System.out.println("Source files : " + dump(srcFiles));
207                 System.out.println("Classpath    : " + dump(classpathDirs));
208                 System.out.println("Destdir      : " + m_destdir);
209                 System.out.println("Properties   : " + dump(allProperties));
210                 System.out.println("Copytodest   : " + m_includePattern);
211             }
212 
213             AnnotationC.compile(
214                     m_verbose,
215                     (String[])srcDirs.toArray(new String[]{}),
216                     (String[])srcFiles.toArray(new String[]{}),
217                     (String[])classpathDirs.toArray(new String[]{}),
218                     m_destdir == null ? null : m_destdir.getAbsolutePath(),
219                     (String[])allProperties.toArray(new String[]{})
220             );
221 
222             if (m_destdir != null) {
223                 if (m_verbose) {
224                     System.out.println("Copying residual files to dest dir...");
225                 }
226                 copySourcesToDest();
227             }
228 
229         } catch (Exception e) {
230             e.printStackTrace();
231             throw new BuildException(e);
232         }
233     }
234 
235     private List getFilesetFiles(List filesets) throws BuildException {
236         List files = new ArrayList();
237         for (Iterator iterator = filesets.iterator(); iterator.hasNext();) {
238             FileSet fileset = (FileSet) iterator.next();
239             DirectoryScanner ds = fileset.getDirectoryScanner(getProject());
240             for (int i = 0; i < ds.getIncludedFiles().length; i++) {
241                 String file = ds.getIncludedFiles()[i];
242                 files.add(ds.getBasedir() + File.separator + file);
243             }
244         }
245         return files;
246     }
247 
248     private List getDirectories(Path path) throws BuildException {
249         List dirs = new ArrayList();
250         if (path == null)
251             return dirs;
252         for (int i = 0; i < path.list().length; i++) {
253             File dir = getProject().resolveFile(path.list()[i]);
254             if (!dir.exists()) {
255                 throw new BuildException(" \"" + dir.getPath() + "\" does not exist!", getLocation());
256             }
257             dirs.add(dir.getAbsolutePath());
258         }
259         return dirs;
260     }
261 
262     private String dump(List strings) {
263         StringBuffer sb = new StringBuffer();
264         for (Iterator iterator = strings.iterator(); iterator.hasNext();) {
265             Object o = (Object) iterator.next();
266             sb.append(o.toString()).append(File.pathSeparator);
267         }
268         return sb.toString();
269     }
270 
271     private void copySourcesToDest() throws BuildException {
272         Copy copy = new Copy();
273 
274         copy.setProject(getProject());
275         copy.setTodir(m_destdir);
276         copy.setOverwrite(false);
277         copy.setTaskName("copy");
278         copy.setVerbose(m_verbose);
279 
280         List sourceDir = getDirectories(m_src);
281         for (Iterator iterator = sourceDir.iterator(); iterator.hasNext();) {
282             String dir = (String) iterator.next();
283             FileSet anonFs  = new FileSet();
284             anonFs.setIncludes(CLASS_PATTERN);
285             if (m_includePattern != null) {
286                 anonFs.setIncludes(m_includePattern);
287             }
288             anonFs.setDir(new File(dir));
289             copy.addFileset(anonFs);
290         }
291         copy.execute();
292     }
293 
294 }