KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > ecm > taskdefs > BuildJarTask


1 // ====================================================================
2
//
3
// ECM: The Extensible Container Model
4
// Copyright (C) 2004 THALES
5
// Contact: openccm-ecm@objectweb.org
6
//
7
// This library is free software; you can redistribute it and/or
8
// modify it under the terms of the GNU Lesser General Public
9
// License as published by the Free Software Foundation; either
10
// version 2.1 of the License, or any later version.
11
//
12
// This library is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
// Lesser General Public License for more details.
16
//
17
// You should have received a copy of the GNU Lesser General Public
18
// License along with this library; if not, write to the Free Software
19
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20
// USA
21
//
22
// Initial developer(s): Mathieu Vadet.
23
// Initial Funding: IST COACH European project (IST-2001-34445)
24
// http://www.ist-coach.org
25
//
26
// ====================================================================
27

28
29
30 package org.objectweb.ecm.taskdefs;
31
32 /**
33  ** <p>Build a jar archive from a source directory. This task may work in three ways:</p>
34  ** <ul>
35  ** <li>Compilation of source files only (compile-only mode).</li>
36  ** <li>Building of an archive from class files only (build-only mode).</li>
37  ** <li>Compilation of source files and building of an archive (twin mode).</li>
38  ** </ul>
39  **
40  ** <p>In the first case, you have to provide the <tt>srcdir</tt>, <tt>compileto</tt> and
41  ** <tt>bootclasspath</tt> attributes at least.
42  ** In the second case, you have to provide the <tt>archivename</tt> and <tt>buildto</tt>
43  ** attributes at least.
44  ** In the last case, the five attributes must be provided at least.</p>
45  **
46  ** <p><bold>Parameters</bold></p>
47  ** <tr>
48  ** <td><bold>Attribute</bold></td>
49  ** <td><bold>Description</bold></td>
50  ** <td><bold>Required</bold></td>
51  ** </tr>
52  ** <tr>
53  ** <td>srcdir</td>
54  ** <td>Directory of the source files.</td>
55  ** <td>Yes in compile-only and twin modes.</td>
56  ** </tr>
57  ** <tr>
58  ** <td>compileto</td>
59  ** <td>Directory of the class files.</td>
60  ** <td>Yes in compile-only and twin modes.</td>
61  ** </tr>
62  ** <tr>
63  ** <td>archivename</td>
64  ** <td>Name of the built archive.</td>
65  ** <td>Yes in build-only and twin modes.</td>
66  ** </tr>
67  ** <tr>
68  ** <td>buildto</td>
69  ** <td>Directory of the archive (jar) file.</td>
70  ** <td>Yes in build-only and twin modes.</td>
71  ** </tr>
72  ** <tr>
73  ** <td>classpathref (or classpathRef)</td>
74  ** <td>The reference to the classpath used for compilation.</td>
75  ** <td>No</td>
76  ** </tr>
77  ** <tr>
78  ** <td>bootclasspathref (or bootclasspathRef)</td>
79  ** <td>The reference to the bootclasspath used for compilation.</td>
80  ** <td>Yes in compile-only and twin modes and unless a nested <tt>bootclasspath</tt>
81  ** element is present.</td>
82  ** </tr>
83  ** <tr>
84  ** <td>verbose</td>
85  ** <td>Asks for verbose output. Defaults to no.</td>
86  ** <td>No</td>
87  ** </tr>
88  **
89  ** <p><bold>Parameters specified as nested elements</bold></p>
90  ** <p>This task support the <tt>classpath</tt> and <tt>bootclasspath</tt> attributes also
91  ** as nested elements in the form of path-like structures (unlike the attributes which are
92  ** path references).</p>
93  **
94  ** <p>This task support the nested <tt>libraries</tt> fileset-like structures. The included
95  ** files will be added to the build archive if any.</p>
96  **
97  ** <p>This task support the nested <tt>library</tt> (without an 's') element in the form of
98  ** a filename. The corresponding file will be added to the build archive if any.</p>
99  **
100  ** <p>This task support the nested <tt>classes</tt> element in the form of a fileset. Each included
101  ** file in this fileset will be added to the archive.</pp>
102  **/

103 public class BuildJarTask
104 extends org.apache.tools.ant.Task
105 {
106     // for compilation
107
private java.io.File JavaDoc _srcdir;
108     private java.io.File JavaDoc _classdir;
109     private java.io.File JavaDoc _compileto;
110     private String JavaDoc _packagedir;
111     private org.apache.tools.ant.types.Reference _classpath;
112     private org.apache.tools.ant.types.Reference _bootclasspath;
113     private boolean _bcpcreated;
114     private org.apache.tools.ant.taskdefs.Javac _javac;
115
116     // for build
117
private String JavaDoc _archive;
118     private java.io.File JavaDoc _buildto;
119     private org.apache.tools.ant.taskdefs.Jar _jar;
120     private java.util.ArrayList JavaDoc _library;
121
122     // common
123
static private int _UNKNOWN_MODE = 0;
124     static private int _COMPILE_ONLY_MODE = 1<<1;
125     static private int _BUILD_ONLY_MODE = 1<<2;
126     static private int _TWIN_MODE = _COMPILE_ONLY_MODE | _BUILD_ONLY_MODE;
127     private int _mode;
128     private boolean _verbose;
129
130
131     // default constructor
132
public
133     BuildJarTask()
134     {
135         // for compilation
136
_srcdir = null;
137         _classdir = null;
138         _compileto = null;
139         _packagedir = null;
140         _classpath = null;
141         _bootclasspath = null;
142         _bcpcreated = false;
143         _javac = null;
144
145         // for build
146
_archive = null;
147         _buildto = null;
148         _jar = null;
149         _library = new java.util.ArrayList JavaDoc();
150
151         // common
152
_verbose = false;
153         _mode = _UNKNOWN_MODE;
154     }
155
156     //
157
// internal operations
158
//
159

160
161     private org.apache.tools.ant.taskdefs.Javac
162     javac()
163     {
164         if (_javac==null) {
165             // NOTE: create Javac task now as it's used for nested classpath and bootclasspath creation
166
org.apache.tools.ant.Task task = super.project.createTask("javac");
167             _javac = (org.apache.tools.ant.taskdefs.Javac)task;
168         }
169
170         return _javac;
171     }
172
173     private org.apache.tools.ant.taskdefs.Jar
174     jar()
175     {
176         if (_jar==null) {
177             // NOTE: create Jar task now as it's used for nested libraries creation
178
org.apache.tools.ant.Task task = super.project.createTask("jar");
179             _jar = (org.apache.tools.ant.taskdefs.Jar)task;
180         }
181
182         return _jar;
183     }
184
185     private void
186     addLibrary()
187     {
188         // NOTE: add all file added in the nested "library" element to the jar
189
NestedElementWithFile[] libs = (NestedElementWithFile[])_library.toArray(new NestedElementWithFile[0]);
190         org.apache.tools.ant.types.FileSet set = null;
191         for (int i=0;i<libs.length;i++) {
192             set = new org.apache.tools.ant.types.FileSet();
193             set.setFile(libs[i].getFile());
194             jar().addZipGroupFileset(set);
195         }
196     }
197
198
199     // NOTE: check required attributes
200
private void
201     validateAttributes()
202     throws org.apache.tools.ant.BuildException
203     {
204         String JavaDoc msg = "";
205         // find mode
206
if ((_srcdir!=null) && (_archive==null)) {
207             _mode = _COMPILE_ONLY_MODE;
208             log("[validateAttributes] compile-only mode detected");
209         }
210
211         if ((_archive!=null) && (_srcdir==null)) {
212             _mode = _BUILD_ONLY_MODE;
213             log("[validateAttributes] build-only mode detected");
214         }
215
216         if ((_archive!=null) && (_srcdir!=null)) {
217             _mode = _TWIN_MODE;
218             log("[validateAttributes] twin mode detected");
219         }
220
221         if ((_srcdir==null) && (_archive==null)) {
222             msg = "either srcdir or archivename attribute must be set";
223             throw new org.apache.tools.ant.BuildException(msg);
224         }
225
226         if (((_mode&_COMPILE_ONLY_MODE)!=0) && (_compileto==null)) {
227             msg = "compileto attribute is missing";
228             throw new org.apache.tools.ant.BuildException(msg);
229         }
230
231         if (((_mode&_COMPILE_ONLY_MODE)!=0) &&
232             ((!_srcdir.exists()) || (!_srcdir.isDirectory()))) {
233             msg = "source directory does not exist or is not a directory";
234             throw new org.apache.tools.ant.BuildException(msg);
235         }
236
237         if (((_mode&_COMPILE_ONLY_MODE)!=0) &&
238             ((!_compileto.exists()) || (!_compileto.isDirectory()))) {
239             msg = "class directory does not exist or is not a directory";
240             throw new org.apache.tools.ant.BuildException(msg);
241         }
242
243         if (((_mode&_BUILD_ONLY_MODE)!=0) && (_buildto==null)) {
244             msg = "buildto attribute is missing";
245             throw new org.apache.tools.ant.BuildException(msg);
246         }
247
248         if (((_mode&_BUILD_ONLY_MODE)!=0) &&
249             ((!_buildto.exists()) || (!_buildto.isDirectory()))) {
250             msg = "archive directory does not exist or is not a directory";
251             throw new org.apache.tools.ant.BuildException(msg);
252         }
253
254         if (((_mode&_BUILD_ONLY_MODE)==0) && (_bootclasspath==null) && (!_bcpcreated)){
255             msg = "bootclasspath attribute or nested element required";
256             throw new org.apache.tools.ant.BuildException(msg);
257         }
258
259         if (_packagedir!=null) {
260             // build the full class dir (including package dir)
261
String JavaDoc classdirname = _compileto.getPath()+java.io.File.separator+_packagedir;
262             _classdir = new java.io.File JavaDoc(classdirname);
263         }
264     }
265
266     private boolean
267     classUpToDate()
268     {
269         if (_packagedir!=null) {
270             // first check that class dir exists
271
if ((!_classdir.exists()) || (!_classdir.isDirectory())) {
272                 return false;
273             }
274
275             // check that for each source file there's a newer class file
276
java.io.File JavaDoc[] sources = FileHelper.listFiles(_srcdir);
277             java.io.File JavaDoc[] classes = FileHelper.listFiles(_classdir);
278
279             /*
280             String srcfiles = "";
281             for (int i=0;i<sources.length;i++) {
282                 srcfiles = srcfiles+" "+sources[i].getName();
283             }
284             log("[classUpToDate] "+srcfiles);
285             */

286
287             for (int i=0;i<sources.length;i++) {
288                 //log("source "+i+": "+sources[i].getPath());
289

290                 // build equiv class file
291
String JavaDoc sname = sources[i].getName();
292                 int idx = sname.lastIndexOf('.');
293                 String JavaDoc classname = sname.substring(0, idx)+".class";
294                 java.io.File JavaDoc classfile = new java.io.File JavaDoc(_classdir, classname);
295
296                 // try to find
297
java.io.File JavaDoc foundclass = null;
298                 for (int j=0;j<classes.length;j++) {
299                     //log(" class "+j+": "+classes[j].getPath());
300
if (classes[j].equals(classfile)) {
301                         foundclass = classes[j];
302                         break;
303                     }
304                 }
305
306                 // a source is not compiled yet
307
if (foundclass==null) {
308                     return false;
309                 }
310
311                 // check timestamp
312
if (sources[i].lastModified()>foundclass.lastModified()) {
313                     return false;
314                 }
315             }
316
317             // all source files are ok
318
log("[classUpToDate] source classes are uptodate: "+_srcdir.getPath());
319             return true;
320         }
321
322         return false;
323     }
324
325     private boolean
326     jarUpToDate(java.io.File JavaDoc tmpdir)
327     {
328         // check if some source files were compiled
329
if (tmpdir.listFiles().length==0) {
330             return true;
331         }
332
333         return false;
334     }
335
336     //
337
// attribute setters
338
//
339

340     final public void
341     setSrcdir(java.io.File JavaDoc dir)
342     {
343         _srcdir = dir;
344     }
345
346     final public void
347     setCompileto(java.io.File JavaDoc dir)
348     {
349         _compileto = dir;
350     }
351
352     final public void
353     setPackagedir(String JavaDoc dir)
354     {
355         _packagedir = dir.replace('/', java.io.File.separatorChar);
356     }
357
358     final public void
359     setClasspathRef(org.apache.tools.ant.types.Reference cp)
360     {
361         _classpath = cp;
362     }
363
364     final public void
365     setClasspathref(org.apache.tools.ant.types.Reference cp)
366     {
367         _classpath = cp;
368     }
369
370     final public void
371     setBootclasspathRef(org.apache.tools.ant.types.Reference cp)
372     {
373         _bootclasspath = cp;
374     }
375
376     final public void
377     setBootclasspathref(org.apache.tools.ant.types.Reference cp)
378     {
379         _bootclasspath = cp;
380     }
381
382     final public org.apache.tools.ant.types.Path
383     createClasspath()
384     {
385         return javac().createClasspath();
386     }
387
388     final public org.apache.tools.ant.types.Path
389     createBootclasspath()
390     {
391         _bcpcreated = true;
392         return javac().createBootclasspath();
393     }
394
395     final public void
396     setArchivename(String JavaDoc name)
397     {
398         _archive = name;
399     }
400
401     final public void
402     setBuildto(java.io.File JavaDoc dir)
403     {
404         _buildto = dir;
405     }
406
407     final public void
408     addLibraries(org.apache.tools.ant.types.FileSet set)
409     {
410         jar().addZipGroupFileset(set);
411     }
412
413     final public NestedElementWithFile
414     createLibrary()
415     {
416         NestedElementWithFile lib = new NestedElementWithFile();
417         _library.add(lib);
418         return lib;
419     }
420
421     final public void
422     addClasses(org.apache.tools.ant.types.FileSet set)
423     {
424         jar().addFileset(set);
425     }
426
427     final public void
428     setVerbose(boolean verbose)
429     {
430         _verbose = verbose;
431     }
432
433     //
434
// org.apache.tools.ant.Task
435
//
436

437     final public void
438     execute()
439     throws org.apache.tools.ant.BuildException
440     {
441         //
442
validateAttributes();
443
444         java.io.File JavaDoc tmpdir = null;
445         if (_mode!=_BUILD_ONLY_MODE) {
446             // create temp directory
447
tmpdir = FileHelper.createTempDir();
448         }
449
450         // compile sources
451
// NOTE: if one class is not uptodate, then we're going to recompile every source file
452
// as javac will not be able to perform its checks (due to the fact that destdir is a
453
// temporary and empty directory)
454
// NOTE2: this could be better handled as the classUpToDate operation could provide
455
// the list of files which need to be recompiled
456
// NOTE3: do not try to compile in build-only mode
457
//if (_mode!=_BUILD_ONLY_MODE) {
458
if ((_mode!=_BUILD_ONLY_MODE) && (!classUpToDate())) {
459             // use javac task
460
// by default, include subdirectories for sources
461
log("[execute] compiling sources: "+_srcdir.getPath());
462             org.apache.tools.ant.types.Path srcpath = new org.apache.tools.ant.types.Path(super.project);
463             srcpath.createPathElement().setLocation(_srcdir);
464             javac().setSrcdir(srcpath);
465             javac().setDestdir(tmpdir);
466             javac().setIncludes("*.java **/*.java");
467             javac().setDebug(true);
468             javac().setClasspathRef(_classpath);
469             javac().setBootClasspathRef(_bootclasspath);
470             // NOTE: add compileto to the classpath
471
org.apache.tools.ant.types.Path cp = javac().createClasspath();
472             cp.setPath(_compileto.getPath());
473
474             // verbose output
475
javac().setVerbose(_verbose);
476
477             javac().execute();
478         }
479         
480         // build jar
481
// NOTE: in build-only mode, the base dir for source is not the temporary directory;
482
// this is why we've separated in two cases
483
if (_mode==_BUILD_ONLY_MODE) {
484             // use jar task
485
log("[execute] building jar (build-only): "+_buildto.getPath()+"/"+_archive);
486             jar().setDestFile(new java.io.File JavaDoc(_buildto, _archive));
487             jar().setUpdate(true);
488             org.apache.tools.ant.types.FileSet set = new org.apache.tools.ant.types.FileSet();
489             set.setDir(_buildto);
490             set.setIncludes("*.class **/*.class");
491             jar().addFileset(set);
492             addLibrary();
493             jar().execute();
494         }
495         // NOTE: do not build in compile-only
496
else if ((_mode==_TWIN_MODE) && (!jarUpToDate(tmpdir))) {
497             // use jar task
498
log("[execute] building jar (: "+_buildto.getPath()+"/"+_archive);
499             jar().setDestFile(new java.io.File JavaDoc(_buildto, _archive));
500             jar().setUpdate(true);
501             org.apache.tools.ant.types.FileSet set = new org.apache.tools.ant.types.FileSet();
502             set.setDir(tmpdir);
503             set.setIncludes("*.class **/*.class");
504             jar().addFileset(set);
505             addLibrary();
506             jar().execute();
507         }
508
509         if (_mode!=_BUILD_ONLY_MODE) {
510             // move files of temp dir to class dir
511
FileHelper.moveFiles(tmpdir.listFiles(), _compileto);
512
513             // delete temp directory
514
FileHelper.deleteDir(tmpdir);
515         }
516     }
517 }
518
Popular Tags