001: /************1**************************************************************************
002: * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
003: * http://aspectwerkz.codehaus.org *
004: * ---------------------------------------------------------------------------------- *
005: * The software in this package is published under the terms of the LGPL license *
006: * a copy of which has been included with this distribution in the license.txt file. *
007: **************************************************************************************/package org.codehaus.aspectwerkz.annotation;
008:
009: import java.io.BufferedReader;
010: import java.io.File;
011: import java.io.FileReader;
012: import java.io.IOException;
013: import java.util.ArrayList;
014: import java.util.List;
015: import java.util.Iterator;
016:
017: import org.apache.tools.ant.BuildException;
018: import org.apache.tools.ant.DirectoryScanner;
019: import org.apache.tools.ant.Project;
020: import org.apache.tools.ant.Task;
021: import org.apache.tools.ant.taskdefs.MatchingTask;
022: import org.apache.tools.ant.taskdefs.Copy;
023: import org.apache.tools.ant.types.FileSet;
024: import org.apache.tools.ant.types.Path;
025: import org.apache.tools.ant.types.Reference;
026:
027: /**
028: * AnnotationC Ant task.
029: * <p/>
030: * Use the following parameters to configure the task:
031: * <ul>
032: * <li>verbose: [optional] flag marking the task verbosity [true / false]</li>
033: * <li>properties: [optional] path to a properties file when user-defined annoations are to be used</li>
034: * <li>destdir: [optional unless input classes are in more than one path] directory where to put annnotated class files</li>
035: * <li>copytodest: [optional] filename pattern to copy extra resources like dtd, xml, or properties files that were found
036: * in the input classes path(s). By defaults, only ".class" files will be handled. It is ignored if "destdir" is not set.</li>
037: * </ul>
038: * <p/>
039: * Use the following parameters to configure the classpath to point to the classes to be weaved. Those can be specified
040: * with nested elements as well / instead:
041: * <ul>
042: * <li>properties path=..: extra path to a properties file when user-defined annoations are to be used</li>
043: * <li>classpath: classpath of classes to annotated, as well as classpath to discover user-defined annotations if any</li>
044: * <li>classpathref: classpath reference of classes to annotated, as well as classpath to discover user-defined annotations if any</li>
045: * <li>srcdir: directory where to find annotated java source files</li>
046: * <li>sourcepath: path where to find annotated java source files</li>
047: * <li>sourcepathref: path reference where to find annotated java source files</li>
048: * </ul>
049: * <p/>
050: * Nested elements are similar to the "javac" task when you configure a classpath and a sourcepath:
051: * <ul>
052: * <li>classpath: Path-like structure of classes to annotated, as well as classpath to discover user-defined annotations if any</li>
053: * <li>src: single path entry of annotated java source files</li>
054: * <li>sourcepath: Path-like structure of annotated java source files</li>
055: * <li>fileset: fileset to contain annotated java source files</li>
056: * </ul>
057: * <p/>
058: *
059: * @author <a href='mailto:the_mindstorm@evolva.ro'>the_mindstorm(at)evolva(dot)ro</a>
060: * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
061: */
062: public class AnnotationCTask extends Task {
063:
064: private final static String CLASS_PATTERN = "**/*.class";
065:
066: private boolean m_verbose;
067: private String m_includePattern;
068: private Path m_classpath;
069: private Path m_src;
070: private File m_properties;
071: private Path m_propertiesNested;
072: private File m_destdir;
073: private List m_filesets = new ArrayList();
074:
075: /**
076: * <task properties=..>
077: *
078: * @param annotationFile
079: */
080: public void setProperties(File annotationFile) {
081: m_properties = annotationFile;
082: }
083:
084: /**
085: * <task verbose=..>
086: *
087: * @param isVerbose
088: */
089: public void setVerbose(boolean isVerbose) {
090: m_verbose = isVerbose;
091: }
092:
093: /**
094: * <task copytodest="** slash *">
095: *
096: * @param pattern
097: */
098: public void setCopytodest(String pattern) {
099: m_includePattern = pattern;
100: }
101:
102: /**
103: * <task destdir=..>
104: *
105: * @param destdir
106: */
107: public void setDestdir(File destdir) {
108: m_destdir = destdir;
109: }
110:
111: //-- <properties .., <src .., <sourcepath.. and srcdir=.. sourcepathref=..
112:
113: public Path createProperties() {
114: if (m_propertiesNested == null) {
115: m_propertiesNested = new Path(getProject());
116: }
117: return m_propertiesNested.createPath();
118: }
119:
120: public Path createSrc() {
121: if (m_src == null) {
122: m_src = new Path(getProject());
123: }
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:
135: public void setSourcepath(Path sourcepath) {
136: if (m_src == null) {
137: m_src = sourcepath;
138: } else {
139: m_src.append(sourcepath);
140: }
141: }
142:
143: public Path createSourcepath() {
144: if (m_src == null) {
145: m_src = new Path(getProject());
146: }
147: return m_src.createPath();
148: }
149:
150: public void setSourcepathRef(Reference r) {
151: createSourcepath().setRefid(r);
152: }
153:
154: //--- classpath
155:
156: public void setClasspath(Path classpath) {
157: if (m_classpath == null) {
158: m_classpath = classpath;
159: } else {
160: m_classpath.append(classpath);
161: }
162: }
163:
164: public Path createClasspath() {
165: if (m_classpath == null) {
166: m_classpath = new Path(getProject());
167: }
168: return m_classpath.createPath();
169: }
170:
171: public void setClasspathRef(Reference r) {
172: createClasspath().setRefid(r);
173: }
174:
175: //---- fileset for source files
176:
177: public void addFileset(FileSet fileset) {
178: m_filesets.add(fileset);
179: }
180:
181: //-- Ant task
182:
183: public void execute() throws BuildException {
184: try {
185: if (m_classpath == null) {
186: throw new BuildException(
187: "No classes specified [<classpath, classpath=.. classpathref=..]");
188: }
189: if (m_destdir == null && m_classpath.list().length > 1) {
190: throw new BuildException(
191: "When using more than one classpath directory, it is mandatory to specify [destdir=..]");
192: }
193: if (m_filesets.size() == 0
194: && (m_src == null || m_src.size() == 0)) {
195: throw new BuildException(
196: "No source specified [<include, <sourcepath, srcdir=..]");
197: }
198: if (m_properties != null && !m_properties.exists()
199: && !m_properties.isFile()) {
200: throw new BuildException(
201: "properties file specified but not a valid file ["
202: + m_properties + "]");
203: }
204: List allProperties = new ArrayList();
205: if (m_properties != null) {
206: allProperties.add(m_properties.getAbsolutePath());
207: }
208: if (m_propertiesNested != null) {
209: allProperties
210: .addAll(getDirectories(m_propertiesNested));
211: }
212:
213: // compute source directory list
214: List srcDirs = getDirectories(m_src);
215: List srcFiles = getFilesetFiles(m_filesets);
216: List classpathDirs = getDirectories(m_classpath);
217:
218: if (m_verbose) {
219: System.out.println("Source dir : " + dump(srcDirs));
220: System.out.println("Source files : " + dump(srcFiles));
221: System.out.println("Classpath : "
222: + dump(classpathDirs));
223: System.out.println("Destdir : " + m_destdir);
224: System.out.println("Properties : "
225: + dump(allProperties));
226: System.out
227: .println("Copytodest : " + m_includePattern);
228: }
229:
230: AnnotationC.compile(m_verbose, (String[]) srcDirs
231: .toArray(new String[] {}), (String[]) srcFiles
232: .toArray(new String[] {}), (String[]) classpathDirs
233: .toArray(new String[] {}), m_destdir == null ? null
234: : m_destdir.getAbsolutePath(),
235: (String[]) allProperties.toArray(new String[] {})
236: //,getClass().getClassLoader()
237: );
238:
239: if (m_destdir != null) {
240: if (m_verbose) {
241: System.out
242: .println("Copying residual files to dest dir...");
243: }
244: copySourcesToDest();
245: }
246:
247: } catch (Exception e) {
248: e.printStackTrace();
249: throw new BuildException(e);
250: }
251: }
252:
253: private List getFilesetFiles(List filesets) throws BuildException {
254: List files = new ArrayList();
255: for (Iterator iterator = filesets.iterator(); iterator
256: .hasNext();) {
257: FileSet fileset = (FileSet) iterator.next();
258: DirectoryScanner ds = fileset
259: .getDirectoryScanner(getProject());
260: for (int i = 0; i < ds.getIncludedFiles().length; i++) {
261: String file = ds.getIncludedFiles()[i];
262: files.add(ds.getBasedir() + File.separator + file);
263: }
264: }
265: return files;
266: }
267:
268: private List getDirectories(Path path) throws BuildException {
269: List dirs = new ArrayList();
270: if (path == null) {
271: return dirs;
272: }
273: for (int i = 0; i < path.list().length; i++) {
274: File dir = getProject().resolveFile(path.list()[i]);
275: if (!dir.exists()) {
276: throw new BuildException(" \"" + dir.getPath()
277: + "\" does not exist!", getLocation());
278: }
279: dirs.add(dir.getAbsolutePath());
280: }
281: return dirs;
282: }
283:
284: private String dump(List strings) {
285: StringBuffer sb = new StringBuffer();
286: for (Iterator iterator = strings.iterator(); iterator.hasNext();) {
287: Object o = (Object) iterator.next();
288: sb.append(o.toString()).append(File.pathSeparator);
289: }
290: return sb.toString();
291: }
292:
293: private void copySourcesToDest() throws BuildException {
294: Copy copy = new Copy();
295:
296: copy.setProject(getProject());
297: copy.setTodir(m_destdir);
298: copy.setOverwrite(false);
299: copy.setTaskName("copy");
300: copy.setVerbose(m_verbose);
301:
302: List sourceDir = getDirectories(m_src);
303: for (Iterator iterator = sourceDir.iterator(); iterator
304: .hasNext();) {
305: String dir = (String) iterator.next();
306: FileSet anonFs = new FileSet();
307: anonFs.setIncludes(CLASS_PATTERN);
308: if (m_includePattern != null) {
309: anonFs.setIncludes(m_includePattern);
310: }
311: anonFs.setDir(new File(dir));
312: copy.addFileset(anonFs);
313: }
314: copy.execute();
315: }
316:
317: }
|