001: /*
002: * Spoon - http://spoon.gforge.inria.fr/
003: * Copyright (C) 2006 INRIA Futurs <renaud.pawlak@inria.fr>
004: *
005: * This software is governed by the CeCILL-C License under French law and
006: * abiding by the rules of distribution of free software. You can use, modify
007: * and/or redistribute the software under the terms of the CeCILL-C license as
008: * circulated by CEA, CNRS and INRIA at http://www.cecill.info.
009: *
010: * This program is distributed in the hope that it will be useful, but WITHOUT
011: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012: * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
013: *
014: * The fact that you are presently reading this means that you have had
015: * knowledge of the CeCILL-C license and that you accept its terms.
016: */
017:
018: package spoon;
019:
020: import java.io.File;
021: import java.util.ArrayList;
022: import java.util.List;
023: import java.util.Vector;
024:
025: import org.apache.tools.ant.BuildException;
026: import org.apache.tools.ant.DirectoryScanner;
027: import org.apache.tools.ant.taskdefs.Java;
028: import org.apache.tools.ant.types.FileSet;
029:
030: /**
031: * This class implements an Ant task for Spoon that encapsulates
032: * {@link spoon.Launcher}.
033: */
034: public class SpoonTask extends Java {
035:
036: /**
037: * Nested element to define a processor type.
038: */
039: public static class ProcessorType {
040: String type;
041:
042: /**
043: * Ant-required empty constructor.
044: */
045: public ProcessorType() {
046: }
047:
048: /**
049: * Constructs a new processor type.
050: *
051: * @param type
052: * the type's fully qualified name
053: */
054: public ProcessorType(String type) {
055: setType(type);
056: }
057:
058: /**
059: * Gets the processor type.
060: */
061: public String getType() {
062: return type;
063: }
064:
065: /**
066: * Sets the processor's type as a string representing the Java qualified
067: * name.
068: */
069: public void setType(String type) {
070: this .type = type;
071: }
072: }
073:
074: String classname;
075:
076: boolean compile = false;
077:
078: File input;
079:
080: int javaCompliance = 5;
081:
082: boolean nooutput = false;
083:
084: File output;
085:
086: File build;
087:
088: File spoonlet;
089:
090: Vector<FileSet> spoonletfileset = new Vector<FileSet>();
091:
092: List<ProcessorType> processorTypes = new ArrayList<ProcessorType>();
093:
094: File properties;
095:
096: Vector<FileSet> sourcefilesets = new Vector<FileSet>();
097:
098: boolean stats = false;
099:
100: File template;
101:
102: Vector<FileSet> templatefilesets = new Vector<FileSet>();
103:
104: boolean verbose = false;
105:
106: boolean debug = false;
107:
108: /**
109: * Constructor.
110: */
111: public SpoonTask() {
112: setClassname("spoon.Launcher");
113: setFailonerror(true);
114: }
115:
116: /**
117: * Adds a new processor type to be instantiated and used by Spoon when
118: * processing the code.
119: */
120: public void addProcessor(ProcessorType processorType) {
121: processorTypes.add(processorType);
122: }
123:
124: /**
125: * Adds a source set.
126: */
127: public void addSourceSet(FileSet set) {
128: sourcefilesets.addElement(set);
129: }
130:
131: /**
132: * Adds a template source set.
133: */
134: public void addTemplateSet(FileSet set) {
135: templatefilesets.addElement(set);
136: }
137:
138: public void addSpoonletSet(FileSet set) {
139: spoonletfileset.addElement(set);
140: }
141:
142: /**
143: * Executes the task.
144: */
145: @Override
146: public void execute() throws BuildException {
147:
148: setFork(true);
149:
150: // Verbose
151: if (verbose) {
152: createArg().setValue("-v");
153: }
154:
155: // debug
156: if (debug) {
157: createArg().setValue("--vvv");
158: }
159:
160: if (fragments) {
161: createArg().setValue("--fragments");
162: }
163:
164: if (tabs) {
165: createArg().setValue("--tabs");
166: }
167:
168: createArg().setValue("--tabsize");
169: createArg().setValue("" + tabSize);
170:
171: if (nooutput) {
172: createArg().setValue("--no");
173: } else {
174: if (compile) {
175: createArg().setValue("--compile");
176:
177: createArg().setValue("--build");
178:
179: createArg().setFile(build);
180:
181: }
182: }
183:
184: createArg().setValue("--compliance");
185: createArg().setValue("" + javaCompliance);
186:
187: // Input directories
188: if ((spoonlet != null) || (spoonletfileset.size() > 0)) {
189: createArg().setValue("-s");
190: String f = "";
191: if (spoonlet != null) {
192: f += spoonlet.getAbsolutePath() + File.pathSeparator;
193: }
194: for (int i = 0; i < spoonletfileset.size(); i++) {
195: FileSet fs = spoonletfileset.elementAt(i);
196: DirectoryScanner ds = fs
197: .getDirectoryScanner(getProject());
198: File dir = fs.getDir(getProject());
199: String[] srcs = ds.getIncludedFiles();
200: for (String element : srcs) {
201: f += dir.getAbsolutePath() + File.separatorChar
202: + element + File.pathSeparator;
203: }
204: }
205: createArg().setValue(f);
206: }
207:
208: // output directory
209: if (output != null) {
210: if (output.exists() && !output.isDirectory()) {
211: throw new BuildException("Output must be a directory");
212: }
213: createArg().setValue("-o");
214: createArg().setValue(output.getAbsolutePath());
215: }
216: // Input directories
217: if ((input != null) || (sourcefilesets.size() > 0)) {
218: createArg().setValue("-i");
219: String f = "";
220: if (input != null) {
221: f += input.getAbsolutePath() + File.pathSeparator;
222: }
223: for (int i = 0; i < sourcefilesets.size(); i++) {
224: FileSet fs = sourcefilesets.elementAt(i);
225: DirectoryScanner ds = fs
226: .getDirectoryScanner(getProject());
227: File dir = fs.getDir(getProject());
228: String[] srcs = ds.getIncludedFiles();
229: for (String element : srcs) {
230: f += dir.getAbsolutePath() + File.separatorChar
231: + element + File.pathSeparator;
232: }
233: }
234: createArg().setValue(f);
235: }
236:
237: // Template directories
238: if ((template != null) || (templatefilesets.size() > 0)) {
239: createArg().setValue("-t");
240: String f = "";
241: if (template != null) {
242: if (!template.exists()) {
243: throw new BuildException(
244: "template file or directory does not exist ("
245: + template.getAbsolutePath() + ")");
246: }
247: f += template.getAbsolutePath() + File.pathSeparator;
248: }
249: for (int i = 0; i < templatefilesets.size(); i++) {
250: FileSet fs = templatefilesets.elementAt(i);
251: DirectoryScanner ds = fs
252: .getDirectoryScanner(getProject());
253: File dir = fs.getDir(getProject());
254: String[] srcs = ds.getIncludedFiles();
255: for (String element : srcs) {
256: f += dir.getAbsolutePath() + File.separatorChar
257: + element + File.pathSeparator;
258: }
259: }
260: createArg().setValue(f);
261: }
262:
263: // properties directory
264: if (properties != null) {
265: createArg().setValue("--properties");
266: if (!properties.exists()) {
267: throw new BuildException(
268: "properties directory does not exist ("
269: + properties.getAbsolutePath() + ")");
270: }
271: createArg().setValue(properties.getAbsolutePath());
272: }
273:
274: // processors
275: if ((processorTypes != null) && (processorTypes.size() > 0)) {
276: createArg().setValue("-p");
277: String process = "";
278: for (ProcessorType t : processorTypes) {
279: process += t.type + File.pathSeparator;
280: }
281: createArg().setValue(process);
282: }
283:
284: if (classname != null) {
285: createArg().setValue(classname);
286: }
287:
288: super .execute();
289:
290: }
291:
292: /**
293: * Sets the name of the laucher to be used.
294: */
295: public void setClassName(String classname) {
296: this .classname = classname;
297: }
298:
299: /**
300: * Sets Spoon to be in verbose mode.
301: */
302: public void setCompile(boolean compile) {
303: this .compile = compile;
304: }
305:
306: /**
307: * Sets a file or a directory to be processed (no templates, see
308: * {@link #setTemplate(File)}).
309: */
310: @Override
311: public void setInput(File input) {
312: this .input = input;
313: }
314:
315: /**
316: * Sets a Spoolet to be deployed.
317: *
318: * @param spoonlet
319: * the deployment descriptor file (usually spoon.xml)
320: */
321: public void setSpoonlet(File spoonlet) {
322: this .spoonlet = spoonlet;
323: }
324:
325: /**
326: * Sets the java14 property (to be able to parse java 1.4 source files).
327: */
328: public void setJavaCompliance(int javaCompliance) {
329: this .javaCompliance = javaCompliance;
330: }
331:
332: /**
333: * Tells Spoon not to generate any files.
334: */
335: public void setNoOutput(boolean nooutput) {
336: this .nooutput = nooutput;
337: }
338:
339: /**
340: * Sets the output directory for generated sources.
341: */
342: @Override
343: public void setOutput(File output) {
344: this .output = output;
345: }
346:
347: /**
348: * Sets the output directory for generated sources.
349: */
350: public void setBuild(File build) {
351: this .build = build;
352: }
353:
354: /**
355: * Sets the root directory where the processors' properties XML
356: * configuration files are located.
357: */
358: public void setProperties(File properties) {
359: this .properties = properties;
360: }
361:
362: /**
363: * Enables/disable printing out statistics on Spoon execution time.
364: */
365: public void setStats(boolean stats) {
366: this .stats = stats;
367: }
368:
369: /**
370: * Sets a file or a directory to be processed (only templates, see
371: * {@link #setInput(File)}).
372: */
373: public void setTemplate(File template) {
374: this .template = template;
375: }
376:
377: /**
378: * Sets Spoon to be in verbose mode.
379: */
380: public void setVerbose(boolean verbose) {
381: this .verbose = verbose;
382: }
383:
384: /**
385: * Sets Spoon to be in debug mode.
386: */
387: public void setDebug(boolean debug) {
388: this .debug = debug;
389: }
390:
391: boolean tabs = false;
392:
393: /**
394: * Sets Spoon to use tabulations instead of spaces when printing source.
395: */
396: public void setTabs(boolean tabs) {
397: this .tabs = tabs;
398: }
399:
400: boolean fragments = false;
401:
402: /**
403: * Sets Spoon to use source code fragment driven generation technique
404: * (preserves original formatting).
405: */
406: public void setFragments(boolean fragments) {
407: this .fragments = fragments;
408: }
409:
410: int tabSize = 4;
411:
412: /**
413: * Sets the tabulation size (default is 4 spaces).
414: */
415: public void setTabSize(int tabSize) {
416: this.tabSize = tabSize;
417: }
418:
419: }
|