View Javadoc

1   /*
2    * Spoon - http://spoon.gforge.inria.fr/
3    * Copyright (C) 2006 INRIA Futurs <renaud.pawlak@inria.fr>
4    *
5    * This software is governed by the CeCILL-C License under French law and
6    * abiding by the rules of distribution of free software. You can use, modify
7    * and/or redistribute the software under the terms of the CeCILL-C license as
8    * circulated by CEA, CNRS and INRIA at http://www.cecill.info.
9    *
10   * This program is distributed in the hope that it will be useful, but WITHOUT
11   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
13   *
14   * The fact that you are presently reading this means that you have had
15   * knowledge of the CeCILL-C license and that you accept its terms.
16   */
17  
18  package spoon;
19  
20  import java.io.File;
21  import java.util.ArrayList;
22  import java.util.List;
23  import java.util.Vector;
24  
25  import org.apache.tools.ant.BuildException;
26  import org.apache.tools.ant.DirectoryScanner;
27  import org.apache.tools.ant.taskdefs.Java;
28  import org.apache.tools.ant.types.FileSet;
29  
30  /**
31   * This class implements an Ant task for Spoon that encapsulates
32   * {@link spoon.Launcher}.
33   */
34  public class SpoonTask extends Java {
35  
36  	/**
37  	 * Nested element to define a processor type.
38  	 */
39  	public static class ProcessorType {
40  		String type;
41  
42  		/**
43  		 * Ant-required empty constructor.
44  		 */
45  		public ProcessorType() {
46  		}
47  
48  		/**
49  		 * Constructs a new processor type.
50  		 *
51  		 * @param type
52  		 *            the type's fully qualified name
53  		 */
54  		public ProcessorType(String type) {
55  			setType(type);
56  		}
57  
58  		/**
59  		 * Gets the processor type.
60  		 */
61  		public String getType() {
62  			return type;
63  		}
64  
65  		/**
66  		 * Sets the processor's type as a string representing the Java qualified
67  		 * name.
68  		 */
69  		public void setType(String type) {
70  			this.type = type;
71  		}
72  	}
73  
74  	String classname;
75  
76  	boolean compile = false;
77  
78  	File input;
79  
80  	int javaCompliance = 5;
81  
82  	boolean nooutput = false;
83  
84  	File output;
85  
86  	File build;
87  
88  	File spoonlet;
89  
90  	Vector<FileSet> spoonletfileset = new Vector<FileSet>();
91  
92  	List<ProcessorType> processorTypes = new ArrayList<ProcessorType>();
93  
94  	File properties;
95  
96  	Vector<FileSet> sourcefilesets = new Vector<FileSet>();
97  
98  	boolean stats = false;
99  
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.getDirectoryScanner(getProject());
197 				File dir = fs.getDir(getProject());
198 				String[] srcs = ds.getIncludedFiles();
199 				for (String element : srcs) {
200 					f += dir.getAbsolutePath() + File.separatorChar + element
201 							+ File.pathSeparator;
202 				}
203 			}
204 			createArg().setValue(f);
205 		}
206 
207 		// output directory
208 		if (output != null) {
209 			if (output.exists() && !output.isDirectory()) {
210 				throw new BuildException("Output must be a directory");
211 			}
212 			createArg().setValue("-o");
213 			createArg().setValue(output.getAbsolutePath());
214 		}
215 		// Input directories
216 		if ((input != null) || (sourcefilesets.size() > 0)) {
217 			createArg().setValue("-i");
218 			String f = "";
219 			if (input != null) {
220 				f += input.getAbsolutePath() + File.pathSeparator;
221 			}
222 			for (int i = 0; i < sourcefilesets.size(); i++) {
223 				FileSet fs = sourcefilesets.elementAt(i);
224 				DirectoryScanner ds = fs.getDirectoryScanner(getProject());
225 				File dir = fs.getDir(getProject());
226 				String[] srcs = ds.getIncludedFiles();
227 				for (String element : srcs) {
228 					f += dir.getAbsolutePath() + File.separatorChar + element
229 							+ File.pathSeparator;
230 				}
231 			}
232 			createArg().setValue(f);
233 		}
234 
235 		// Template directories
236 		if ((template != null) || (templatefilesets.size() > 0)) {
237 			createArg().setValue("-t");
238 			String f = "";
239 			if (template != null) {
240 				if (!template.exists()) {
241 					throw new BuildException(
242 							"template file or directory does not exist ("
243 									+ template.getAbsolutePath() + ")");
244 				}
245 				f += template.getAbsolutePath() + File.pathSeparator;
246 			}
247 			for (int i = 0; i < templatefilesets.size(); i++) {
248 				FileSet fs = templatefilesets.elementAt(i);
249 				DirectoryScanner ds = fs.getDirectoryScanner(getProject());
250 				File dir = fs.getDir(getProject());
251 				String[] srcs = ds.getIncludedFiles();
252 				for (String element : srcs) {
253 					f += dir.getAbsolutePath() + File.separatorChar + element
254 							+ File.pathSeparator;
255 				}
256 			}
257 			createArg().setValue(f);
258 		}
259 
260 		// properties directory
261 		if (properties != null) {
262 			createArg().setValue("--properties");
263 			if (!properties.exists()) {
264 				throw new BuildException(
265 						"properties directory does not exist ("
266 								+ properties.getAbsolutePath() + ")");
267 			}
268 			createArg().setValue(properties.getAbsolutePath());
269 		}
270 
271 		// processors
272 		if ((processorTypes != null) && (processorTypes.size() > 0)) {
273 			createArg().setValue("-p");
274 			String process = "";
275 			for (ProcessorType t : processorTypes) {
276 				process += t.type + File.pathSeparator;
277 			}
278 			createArg().setValue(process);
279 		}
280 
281 		if (classname != null) {
282 			createArg().setValue(classname);
283 		}
284 
285 		super.execute();
286 
287 	}
288 
289 	/**
290 	 * Sets the name of the laucher to be used.
291 	 */
292 	public void setClassName(String classname) {
293 		this.classname = classname;
294 	}
295 
296 	/**
297 	 * Sets Spoon to be in verbose mode.
298 	 */
299 	public void setCompile(boolean compile) {
300 		this.compile = compile;
301 	}
302 
303 	/**
304 	 * Sets a file or a directory to be processed (no templates, see
305 	 * {@link #setTemplate(File)}).
306 	 */
307 	@Override
308 	public void setInput(File input) {
309 		this.input = input;
310 	}
311 
312 	/**
313 	 * Sets a Spoolet to be deployed.
314 	 *
315 	 * @param spoonlet
316 	 *            the deployment descriptor file (usually spoon.xml)
317 	 */
318 	public void setSpoonlet(File spoonlet) {
319 		this.spoonlet = spoonlet;
320 	}
321 
322 	/**
323 	 * Sets the java14 property (to be able to parse java 1.4 source files).
324 	 */
325 	public void setJavaCompliance(int javaCompliance) {
326 		this.javaCompliance = javaCompliance;
327 	}
328 
329 	/**
330 	 * Tells Spoon not to generate any files.
331 	 */
332 	public void setNoOutput(boolean nooutput) {
333 		this.nooutput = nooutput;
334 	}
335 
336 	/**
337 	 * Sets the output directory for generated sources.
338 	 */
339 	@Override
340 	public void setOutput(File output) {
341 		this.output = output;
342 	}
343 
344 	/**
345 	 * Sets the output directory for generated sources.
346 	 */
347 	public void setBuild(File build) {
348 		this.build = build;
349 	}
350 
351 	/**
352 	 * Sets the root directory where the processors' properties XML
353 	 * configuration files are located.
354 	 */
355 	public void setProperties(File properties) {
356 		this.properties = properties;
357 	}
358 
359 	/**
360 	 * Enables/disable printing out statistics on Spoon execution time.
361 	 */
362 	public void setStats(boolean stats) {
363 		this.stats = stats;
364 	}
365 
366 	/**
367 	 * Sets a file or a directory to be processed (only templates, see
368 	 * {@link #setInput(File)}).
369 	 */
370 	public void setTemplate(File template) {
371 		this.template = template;
372 	}
373 
374 	/**
375 	 * Sets Spoon to be in verbose mode.
376 	 */
377 	public void setVerbose(boolean verbose) {
378 		this.verbose = verbose;
379 	}
380 
381 	/**
382 	 * Sets Spoon to be in debug mode.
383 	 */
384 	public void setDebug(boolean debug) {
385 		this.debug = debug;
386 	}
387 
388 	boolean tabs = false;
389 
390 	/**
391 	 * Sets Spoon to use tabulations instead of spaces when printing source.
392 	 */
393 	public void setTabs(boolean tabs) {
394 		this.tabs = tabs;
395 	}
396 
397 	boolean fragments = false;
398 
399 	/**
400 	 * Sets Spoon to use source code fragment driven generation technique
401 	 * (preserves original formatting).
402 	 */
403 	public void setFragments(boolean fragments) {
404 		this.fragments = fragments;
405 	}
406 
407 	int tabSize = 4;
408 
409 	/**
410 	 * Sets the tabulation size (default is 4 spaces).
411 	 */
412 	public void setTabSize(int tabSize) {
413 		this.tabSize = tabSize;
414 	}
415 
416 }