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   * <p/>
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       *
99       * @param pattern
100      */
101     public void setCopytodest(String pattern) {
102         m_includePattern = pattern;
103     }
104 
105     /***
106      * <task destdir=..>
107      *
108      * @param destdir
109      */
110     public void setDestdir(File destdir) {
111         m_destdir = destdir;
112     }
113 
114     //-- <properties .., <src .., <sourcepath.. and srcdir=.. sourcepathref=..
115 
116     public Path createProperties() {
117         if (m_propertiesNested == null) {
118             m_propertiesNested = new Path(getProject());
119         }
120         return m_propertiesNested.createPath();
121     }
122 
123     public Path createSrc() {
124         if (m_src == null) {
125             m_src = new Path(getProject());
126         }
127         return m_src.createPath();
128     }
129 
130     public void setSrcdir(Path srcDir) {
131         if (m_src == null) {
132             m_src = srcDir;
133         } else {
134             m_src.append(srcDir);
135         }
136     }
137 
138     public void setSourcepath(Path sourcepath) {
139         if (m_src == null) {
140             m_src = sourcepath;
141         } else {
142             m_src.append(sourcepath);
143         }
144     }
145 
146     public Path createSourcepath() {
147         if (m_src == null) {
148             m_src = new Path(getProject());
149         }
150         return m_src.createPath();
151     }
152 
153     public void setSourcepathRef(Reference r) {
154         createSourcepath().setRefid(r);
155     }
156 
157 
158     //--- classpath
159 
160     public void setClasspath(Path classpath) {
161         if (m_classpath == null) {
162             m_classpath = classpath;
163         } else {
164             m_classpath.append(classpath);
165         }
166     }
167 
168     public Path createClasspath() {
169         if (m_classpath == null) {
170             m_classpath = new Path(getProject());
171         }
172         return m_classpath.createPath();
173     }
174 
175     public void setClasspathRef(Reference r) {
176         createClasspath().setRefid(r);
177     }
178 
179     //---- fileset for source files
180 
181     public void addFileset(FileSet fileset) {
182         m_filesets.add(fileset);
183     }
184 
185     //-- Ant task
186 
187     public void execute() throws BuildException {
188         try {
189             if (m_classpath == null) {
190                 throw new BuildException("No classes specified [<classpath, classpath=.. classpathref=..]");
191             }
192             if (m_destdir == null && m_classpath.list().length > 1) {
193                 throw new BuildException(
194                         "When using more than one classpath directory, it is mandatory to specify [destdir=..]"
195                 );
196             }
197             if (m_filesets.size() == 0 && (m_src == null || m_src.size() == 0)) {
198                 throw new BuildException("No source specified [<include, <sourcepath, srcdir=..]");
199             }
200             if (m_properties != null && !m_properties.exists() && !m_properties.isFile()) {
201                 throw new BuildException("properties file specified but not a valid file [" + m_properties + "]");
202             }
203             List allProperties = new ArrayList();
204             if (m_properties != null) {
205                 allProperties.add(m_properties.getAbsolutePath());
206             }
207             if (m_propertiesNested != null) {
208                 allProperties.addAll(getDirectories(m_propertiesNested));
209             }
210 
211             // compute source directory list
212             List srcDirs = getDirectories(m_src);
213             List srcFiles = getFilesetFiles(m_filesets);
214             List classpathDirs = getDirectories(m_classpath);
215 
216             if (m_verbose) {
217                 System.out.println("Source dir   : " + dump(srcDirs));
218                 System.out.println("Source files : " + dump(srcFiles));
219                 System.out.println("Classpath    : " + dump(classpathDirs));
220                 System.out.println("Destdir      : " + m_destdir);
221                 System.out.println("Properties   : " + dump(allProperties));
222                 System.out.println("Copytodest   : " + m_includePattern);
223             }
224 
225             AnnotationC.compile(
226                     m_verbose,
227                     (String[]) srcDirs.toArray(new String[]{}),
228                     (String[]) srcFiles.toArray(new String[]{}),
229                     (String[]) classpathDirs.toArray(new String[]{}),
230                     m_destdir == null ? null : m_destdir.getAbsolutePath(),
231                     (String[]) allProperties.toArray(new String[]{})
232                     //,getClass().getClassLoader()
233             );
234 
235             if (m_destdir != null) {
236                 if (m_verbose) {
237                     System.out.println("Copying residual files to dest dir...");
238                 }
239                 copySourcesToDest();
240             }
241 
242         } catch (Exception e) {
243             e.printStackTrace();
244             throw new BuildException(e);
245         }
246     }
247 
248     private List getFilesetFiles(List filesets) throws BuildException {
249         List files = new ArrayList();
250         for (Iterator iterator = filesets.iterator(); iterator.hasNext();) {
251             FileSet fileset = (FileSet) iterator.next();
252             DirectoryScanner ds = fileset.getDirectoryScanner(getProject());
253             for (int i = 0; i < ds.getIncludedFiles().length; i++) {
254                 String file = ds.getIncludedFiles()[i];
255                 files.add(ds.getBasedir() + File.separator + file);
256             }
257         }
258         return files;
259     }
260 
261     private List getDirectories(Path path) throws BuildException {
262         List dirs = new ArrayList();
263         if (path == null) {
264             return dirs;
265         }
266         for (int i = 0; i < path.list().length; i++) {
267             File dir = getProject().resolveFile(path.list()[i]);
268             if (!dir.exists()) {
269                 throw new BuildException(" \"" + dir.getPath() + "\" does not exist!", getLocation());
270             }
271             dirs.add(dir.getAbsolutePath());
272         }
273         return dirs;
274     }
275 
276     private String dump(List strings) {
277         StringBuffer sb = new StringBuffer();
278         for (Iterator iterator = strings.iterator(); iterator.hasNext();) {
279             Object o = (Object) iterator.next();
280             sb.append(o.toString()).append(File.pathSeparator);
281         }
282         return sb.toString();
283     }
284 
285     private void copySourcesToDest() throws BuildException {
286         Copy copy = new Copy();
287 
288         copy.setProject(getProject());
289         copy.setTodir(m_destdir);
290         copy.setOverwrite(false);
291         copy.setTaskName("copy");
292         copy.setVerbose(m_verbose);
293 
294         List sourceDir = getDirectories(m_src);
295         for (Iterator iterator = sourceDir.iterator(); iterator.hasNext();) {
296             String dir = (String) iterator.next();
297             FileSet anonFs = new FileSet();
298             anonFs.setIncludes(CLASS_PATTERN);
299             if (m_includePattern != null) {
300                 anonFs.setIncludes(m_includePattern);
301             }
302             anonFs.setDir(new File(dir));
303             copy.addFileset(anonFs);
304         }
305         copy.execute();
306     }
307 
308 }