KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > exolab > jms > plugins > proxygen > ProxyGeneratorTask


1 /**
2  * Redistribution and use of this software and associated documentation
3  * ("Software"), with or without modification, are permitted provided
4  * that the following conditions are met:
5  *
6  * 1. Redistributions of source code must retain copyright
7  * statements and notices. Redistributions must also contain a
8  * copy of this document.
9  *
10  * 2. Redistributions in binary form must reproduce the
11  * above copyright notice, this list of conditions and the
12  * following disclaimer in the documentation and/or other
13  * materials provided with the distribution.
14  *
15  * 3. The name "Exolab" must not be used to endorse or promote
16  * products derived from this Software without prior written
17  * permission of Exoffice Technologies. For written permission,
18  * please contact info@exolab.org.
19  *
20  * 4. Products derived from this Software may not be called "Exolab"
21  * nor may "Exolab" appear in their names without prior written
22  * permission of Exoffice Technologies. Exolab is a registered
23  * trademark of Exoffice Technologies.
24  *
25  * 5. Due credit should be given to the Exolab Project
26  * (http://www.exolab.org/).
27  *
28  * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32  * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39  * OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * Copyright 2003-2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42  *
43  * $Id: ProxyGeneratorTask.java,v 1.3 2005/05/07 14:01:44 tanderson Exp $
44  */

45 package org.exolab.jms.plugins.proxygen;
46
47 import java.io.File JavaDoc;
48 import java.io.FileOutputStream JavaDoc;
49 import java.io.IOException JavaDoc;
50 import java.util.ArrayList JavaDoc;
51 import java.util.Iterator JavaDoc;
52 import java.util.List JavaDoc;
53 import java.util.StringTokenizer JavaDoc;
54
55 import org.apache.tools.ant.AntClassLoader;
56 import org.apache.tools.ant.BuildException;
57 import org.apache.tools.ant.DirectoryScanner;
58 import org.apache.tools.ant.Project;
59 import org.apache.tools.ant.taskdefs.Javac;
60 import org.apache.tools.ant.taskdefs.MatchingTask;
61 import org.apache.tools.ant.types.Path;
62 import org.apache.tools.ant.types.Reference;
63 import org.apache.tools.ant.util.FileNameMapper;
64 import org.apache.tools.ant.util.GlobPatternMapper;
65 import org.apache.tools.ant.util.SourceFileScanner;
66
67
68 /**
69  * Ant task to generate proxies.
70  *
71  * @author <a HREF="mailto:tma@netspace.net.au">Tim Anderson</a>
72  * @version $Revision: 1.3 $ $Date: 2005/05/07 14:01:44 $
73  */

74 public class ProxyGeneratorTask extends MatchingTask {
75
76     /**
77      * The base directory to store compiled classes.
78      */

79     private File JavaDoc _base;
80
81     /**
82      * The base directory to store generated sources. If not set, defaults to
83      * _base.
84      */

85     private File JavaDoc _sourceBase;
86
87     /**
88      * The class name to generate source for.
89      */

90     private String JavaDoc _classname;
91
92     /**
93      * A set of class names for adapters of Throwable.
94      */

95     private List JavaDoc _adapters = new ArrayList JavaDoc();
96
97     /**
98      * Indicates whether source should be compiled with debug information;
99      * defaults to off.
100      */

101     private boolean _debug = false;
102
103     /**
104      * Compile class path.
105      */

106     private Path _compileClasspath;
107
108
109     /**
110      * Construct a new <code>ProxyGeneratorTask</code>.
111      */

112     public ProxyGeneratorTask() {
113     }
114
115     /**
116      * Sets the location to store compiled classes; required.
117      *
118      * @param base the base directory
119      */

120     public void setBase(File JavaDoc base) {
121         _base = base;
122     }
123
124     /**
125      * Returns the base directory to compiled classes.
126      *
127      * @return the base directory to compiled classes
128      */

129     public File JavaDoc getBase() {
130         return _base;
131     }
132
133     /**
134      * Sets the the class to run this task against; optional.
135      *
136      * @param classname the class name
137      */

138     public void setClassname(String JavaDoc classname) {
139         _classname = classname;
140     }
141
142     /**
143      * Returns the class name to compile.
144      *
145      * @return the class name to compile
146      */

147     public String JavaDoc getClassname() {
148         return _classname;
149     }
150
151     /**
152      * Sets list of ThrowableAdapter clases to use.
153      *
154      * @param adapters a comma-separated list of ThrowableAdapter class names
155      */

156     public void setAdapters(String JavaDoc adapters) {
157         StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc(adapters, ",");
158         while (tokens.hasMoreTokens()) {
159             String JavaDoc classname = tokens.nextToken();
160             Adapter adapter = new Adapter();
161             adapter.setClassname(classname);
162             addConfiguredAdapter(adapter);
163         }
164     }
165
166     /**
167      * Add a nested adapter class name.
168      *
169      * @param adapter the adapter
170      */

171     public void addConfiguredAdapter(Adapter adapter) {
172         _adapters.add(adapter.getClassname());
173     }
174
175     /**
176      * Optional directory to save generated source files to.
177      *
178      * @param sourceBase the directory to save generated source files to
179      */

180     public void setSourceBase(File JavaDoc sourceBase) {
181         _sourceBase = sourceBase;
182     }
183
184     /**
185      * Returns the directory to save generated source files to.
186      *
187      * @return the directory to save generated source files to
188      */

189     public File JavaDoc getSourceBase() {
190         return _sourceBase;
191     }
192
193
194     /**
195      * Indicates whether source should be compiled with debug information;
196      * defaults to off.
197      *
198      * @param debug if <code>true</code> enable debug information
199      */

200     public void setDebug(boolean debug) {
201         _debug = debug;
202     }
203
204     /**
205      * Returns the debug flag.
206      *
207      * @return the debug flag
208      */

209     public boolean getDebug() {
210         return _debug;
211     }
212
213     /**
214      * Set the classpath to be used for this compilation.
215      *
216      * @param classpath the classpath
217      */

218     public void setClasspath(Path classpath) {
219         if (_compileClasspath == null) {
220             _compileClasspath = classpath;
221         } else {
222             _compileClasspath.append(classpath);
223         }
224     }
225
226     /**
227      * Creates a nested classpath element.
228      *
229      * @return a nested classpath element
230      */

231     public Path createClasspath() {
232         if (_compileClasspath == null) {
233             _compileClasspath = new Path(project);
234         }
235         return _compileClasspath.createPath();
236     }
237
238     /**
239      * Adds to the classpath a reference to a &lt;path&gt; defined elsewhere.
240      *
241      * @param reference the reference
242      */

243     public void setClasspathRef(Reference reference) {
244         createClasspath().setRefid(reference);
245     }
246
247     /**
248      * Returns the classpath.
249      *
250      * @return the classpath
251      */

252     public Path getClasspath() {
253         return _compileClasspath;
254     }
255
256     /**
257      * Execute the task.
258      *
259      * @throws BuildException if the build fails
260      */

261     public void execute() throws BuildException {
262         if (_base == null) {
263             throw new BuildException("base attribute must be set!", location);
264         }
265         if (!_base.exists()) {
266             throw new BuildException("base does not exist", location);
267         }
268         if (!_base.isDirectory()) {
269             throw new BuildException("base is not a directory", location);
270         }
271
272         if (_sourceBase != null) {
273             if (!_sourceBase.exists()) {
274                 throw new BuildException("sourceBase does not exist",
275                                          location);
276             }
277             if (!_sourceBase.isDirectory()) {
278                 throw new BuildException("sourceBase is not a directory",
279                                          location);
280             }
281         } else {
282             _sourceBase = _base;
283         }
284
285         String JavaDoc[] files;
286         String JavaDoc[] generateList;
287
288         if (_classname == null) {
289             // scan base dir to build up generation lists only if a
290
// specific classname is not given
291
DirectoryScanner scanner = getDirectoryScanner(_base);
292             files = scanner.getIncludedFiles();
293         } else {
294             // otherwise perform a timestamp comparison - at least
295
files = new String JavaDoc[]{
296                 _classname.replace('.', File.separatorChar) + ".class"};
297         }
298         generateList = scanDir(files);
299
300         int count = generateList.length;
301         if (count > 0) {
302             log("Generating " + count + " prox" + (count > 1 ? "ies" : "y")
303                 + " to " + _base, Project.MSG_INFO);
304
305             Path classpath = getCompileClasspath();
306             AntClassLoader loader = new AntClassLoader(project, classpath);
307
308             for (int i = 0; i < count; ++i) {
309                 generate(generateList[i], loader);
310             }
311
312             Javac javac = new Javac();
313             javac.setProject(project);
314             javac.createSrc().setLocation(_sourceBase);
315             javac.setDestdir(_base);
316             javac.setDebug(_debug);
317             javac.setClasspath(classpath);
318             javac.execute();
319         }
320     }
321
322     /**
323      * Helper class for specifying nested ThrowableAdapter implementations.
324      */

325     public static final class Adapter {
326
327         /**
328          * The class name.
329          */

330         private String JavaDoc _classname;
331
332         /**
333          * Sets the adapter class name.
334          *
335          * @param classname the adapter class name
336          */

337         public void setClassname(String JavaDoc classname) {
338             _classname = classname;
339         }
340
341         /**
342          * Returns the adapter class name.
343          *
344          * @return the adapter class name
345          */

346         public String JavaDoc getClassname() {
347             return _classname;
348         }
349     }
350
351     /**
352      * Generate the proxy source.
353      *
354      * @param classname the name of the class
355      * @param loader the classloader to locate the class and its
356      * dependencies
357      * @return the path of the generated source
358      * @throws BuildException if the source generation fails
359      */

360     protected String JavaDoc generate(String JavaDoc classname, ClassLoader JavaDoc loader)
361             throws BuildException {
362
363         String JavaDoc path = classname.replace('.', File.separatorChar)
364                 + "__Proxy.java";
365         File JavaDoc file = new File JavaDoc(_sourceBase, path);
366         File JavaDoc parent = file.getParentFile();
367         if (parent.exists()) {
368             if (!parent.isDirectory()) {
369                 throw new BuildException("Cannot generate sources to "
370                                          + parent
371                                          + ": path is not a directory", location);
372             }
373         } else if (!parent.mkdirs()) {
374             throw new BuildException("Failed to create directory " + parent,
375                                      location);
376         }
377
378         log("Generating proxy " + file, Project.MSG_DEBUG);
379
380         FileOutputStream JavaDoc stream = null;
381         try {
382             stream = new FileOutputStream JavaDoc(file);
383             Class JavaDoc clazz = loader.loadClass(classname);
384             Class JavaDoc[] adapters = getAdapters(loader);
385             ProxyGenerator generator = new ProxyGenerator(clazz, adapters);
386             generator.generate(stream);
387             stream.close();
388         } catch (ClassNotFoundException JavaDoc exception) {
389             throw new BuildException("proxygen failed - class not found: "
390                                      + exception.getMessage(), exception,
391                                      location);
392         } catch (IOException JavaDoc exception) {
393             throw new BuildException(
394                     "proxygen failed - I/O error: " + exception.getMessage(),
395                     exception, location);
396         } catch (Exception JavaDoc exception) {
397             throw new BuildException(
398                     "proxygen failed: " + exception.getMessage(),
399                     exception, location);
400         } finally {
401             if (stream != null) {
402                 try {
403                     stream.close();
404                 } catch (IOException JavaDoc exception) {
405                     throw new BuildException("proxygen failed - I/O error: "
406                                              + exception.getMessage(),
407                                              exception, location);
408                 }
409             }
410         }
411         return path;
412     }
413
414     /**
415      * Returns the class path for compilation.
416      *
417      * @return the compilation classpath
418      */

419     protected Path getCompileClasspath() {
420         Path classpath = new Path(project);
421
422         // add dest dir to classpath so that previously compiled and
423
// untouched classes are on classpath
424
classpath.setLocation(_base);
425
426         if (getClasspath() == null) {
427             classpath.addExisting(Path.systemClasspath);
428         } else {
429             classpath.addExisting(getClasspath().concatSystemClasspath("last"));
430         }
431
432         return classpath;
433     }
434
435     /**
436      * Scans the base directory looking for class files to generate proxies
437      * for.
438      *
439      * @param files the file paths
440      * @return a list of class names to generate proxies for
441      */

442     protected String JavaDoc[] scanDir(String JavaDoc[] files) {
443         ArrayList JavaDoc result = new ArrayList JavaDoc();
444         String JavaDoc[] newFiles = files;
445
446         SourceFileScanner scanner = new SourceFileScanner(this);
447         FileNameMapper mapper = new GlobPatternMapper();
448         mapper.setFrom("*.class");
449         mapper.setTo("*__Proxy.java");
450         newFiles = scanner.restrict(files, _base, _sourceBase, mapper);
451
452         for (int i = 0; i < newFiles.length; i++) {
453             String JavaDoc classname = newFiles[i].replace(File.separatorChar, '.');
454             classname = classname.substring(0, classname.lastIndexOf(".class"));
455             result.add(classname);
456         }
457         return (String JavaDoc[]) result.toArray(new String JavaDoc[0]);
458     }
459
460     /**
461      * Returns the adapter classes.
462      *
463      * @param loader the class loader to use
464      * @return the adapter classes
465      * @throws ClassNotFoundException if an adapter class can't be found
466      */

467     private Class JavaDoc[] getAdapters(ClassLoader JavaDoc loader)
468             throws ClassNotFoundException JavaDoc {
469         Class JavaDoc[] result = new Class JavaDoc[_adapters.size()];
470         Iterator JavaDoc iterator = _adapters.iterator();
471         for (int i = 0; iterator.hasNext(); ++i) {
472             String JavaDoc classname = (String JavaDoc) iterator.next();
473             Class JavaDoc adapter = loader.loadClass(classname);
474             result[i] = adapter;
475         }
476         return result;
477     }
478 }
479
480
Popular Tags