/Users/lyon/j4p/src/classUtils/pack/util/ant/Pack.java
|
1 /************************************************************************************
2 * Copyright (C) 2002 Cristiano Sadun crsadun@tin.it
3 *
4 * You can redistribute this program and/or
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation-
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 ************************************************************************************/
17
18 package classUtils.pack.util.ant;
19
20 import classUtils.pack.DependencyUtils;
21 import classUtils.pack.util.ClassPackageExplorer;
22 import classUtils.pack.util.SimpleClassPackageExplorer;
23 import classUtils.pack.util.util.CPoolReader;
24 import classUtils.pack.util.util.DynamicClassFileFinder;
25 import classUtils.pack.util.util.DynamicJDK12ClassFileFinder;
26 import classUtils.pack.util.util.DynamicResourceFileFinder;
27 import classUtils.putils.ClassPathUtils;
28 import collections.sortable.SortableVector;
29 import futils.Futil;
30 import gui.html.TextViewer;
31 import gui.run.RunMenu;
32 import gui.run.RunMenuItem;
33 import org.apache.tools.ant.BuildException;
34 import org.apache.tools.ant.DirectoryScanner;
35 import org.apache.tools.ant.Project;
36 import org.apache.tools.ant.Task;
37 import org.apache.tools.ant.types.FileSet;
38 import org.apache.tools.ant.types.Path;
39 import utils.StringUtils;
40
41 import javax.swing.JMenuBar;
42 import java.io.BufferedInputStream;
43 import java.io.BufferedOutputStream;
44 import java.io.ByteArrayInputStream;
45 import java.io.File;
46 import java.io.FileInputStream;
47 import java.io.FileOutputStream;
48 import java.io.IOException;
49 import java.io.InputStream;
50 import java.util.HashMap;
51 import java.util.HashSet;
52 import java.util.Iterator;
53 import java.util.Map;
54 import java.util.Set;
55 import java.util.StringTokenizer;
56 import java.util.jar.Attributes;
57 import java.util.jar.JarEntry;
58 import java.util.jar.JarOutputStream;
59 import java.util.jar.Manifest;
60
61 /**
62 * An ant task to pack dependencies on a given set
63 * of classes.
64 * <p/>
65 * The available attributes are: <ul>
66 * <li><b>classes</b>: a comma-separated list of
67 * classes to pack <li><b>packages</b>: a
68 * comma-separated list of packages to pack. Each
69 * class in the package will be included, together
70 * with its dependents. <li><b>classpath</b>:
71 * additional classpath to use when packing
72 * classes (optional) <li><b>targetJar</b>: the
73 * name of the jar file to produce <li><b>mainfestClasspath</b>:
74 * the (optional) manifest Class-Path entry
75 * <li><b>mainfestMainclass</b>: the (optional)
76 * manifest Main-Class entry <li><b>excludePkg</b>:
77 * a comma-separated list of package prefixes to
78 * exclude. Defaults to <b>java,javax,sun</b>
79 * <li><b>includePkg</b>: a comma-separated list
80 * of package prefixes to include. Only classes in
81 * matching packages will be included. Has lower
82 * precedence than excludePkg <li><b>resolveFiltered</b>:
83 * if <b>true</b>, allows resolution of classes
84 * which are filtered out. Defaults to
85 * <b>false</b>. <li><b>cacheClassFiles</b>: if
86 * <b>false</b>, disables classfile caching -
87 * slower packing but saving memory </ul>
88 * <p/>
89 * Additional classpath can be also specified by a
90 * nested <code><classpath></code> element.
91 * <p/>
92 * <pack> also supports inclusion of
93 * explicitly named additional classes and/or
94 * files in the jar. Dependencies for such
95 * additional classes will be computed and added
96 * too. This is done by declaring internal
97 * <b><additionalclass></b> and
98 * <b><additionalfileset></b> elements.
99 * <p/>
100 * <b><additionalclass></b> has a single
101 * <b>name</b> attribute which contains the fully
102 * qualified name of the class to include. The
103 * class must: <ul> <li> be in classpath; <li> not
104 * conflict with the filter established by
105 * <b>excludePkg/includePkg</b>. </ul>
106 * <p/>
107 * For example,
108 * <pre>
109 * <additionalclass name="javax.transaction.TransactionManager"/>
110 * </pre>
111 * will add the <code>javax.transaction.TransactionManager</code>
112 * class and all its dependent classes to the
113 * produced jar.
114 * <p/>
115 * <b><additionalfileset></b> is a standard
116 * Ant <code>FileSet</code> structure which
117 * specifies a set of files to unconditionally add
118 * to the produced jar.
119 * <p/>
120 * For example,
121 * <pre>
122 * <additionalfileset dir="${basedir}">
123 * <include name="META-INF/services/*"/>
124 * </additionalfileset>
125 * </pre>
126 * <p/>
127 * will add any file under the <code>META-INF/service</code>
128 * subdirectory of the current <code>${basedir}</code>
129 * directory.
130 * <p/>
131 * <p/>
132 * $Revision$
133 *
134 * @author Cristiano Sadun
135 * @version 1.6
136 */
137 public class Pack extends Task {
138
139 interface ClassFilter {
140 /**
141 * Return true if the given classfile is
142 * accepted
143 *
144 * @param pkgname the package name of
145 * the class
146 * @param clsName the class name
147 * @param classfile the {@link classUtils.pack.util.util.CPoolReader.classfile
148 * classfile object} for
149 * the class
150 * @return boolean <b>true</b> if the
151 * class is to be accepted
152 */
153 public boolean accept(String pkgname,
154 String clsName,
155 CPoolReader.classfile classfile);
156 }
157
158 static class PackagePrefixClassFilter
159 implements ClassFilter {
160
161 private String[] prefixes;
162 private boolean accept;
163
164 /**
165 * Creates a filter which will accept or
166 * refuse (depending on the <tt>accept</tt>
167 * parameter) classes whose package
168 * matches a given prefix
169 *
170 * @param prefixes
171 * @param accept
172 */
173 public PackagePrefixClassFilter(String[] prefixes,
174 boolean accept) {
175 this.prefixes = prefixes;
176 this.accept = accept;
177 }
178
179 /**
180 * Accepts the classes with or without one
181 * of the prefixes given at construction
182 */
183 public boolean accept(String pkgName,
184 String clsName,
185 CPoolReader.classfile classfile) {
186 for (int i = 0; i < prefixes.length; i++)
187 if (pkgName.startsWith(prefixes[i]))
188 return accept;
189 return !accept;
190 }
191
192 public String toString() {
193 StringBuffer sb = new StringBuffer("Filter ");
194 sb.append(accept ?
195 "includes" :
196 "excludes");
197 sb.append(" classes in packages whose name is prefixed with one of { ");
198 for (int i = 0; i < prefixes.length; i++) {
199 sb.append(prefixes[i]);
200 if (i < prefixes.length - 1)
201 sb.append(", ");
202 }
203 sb.append(" }");
204 return sb.toString();
205 }
206 }
207
208 private String classes;
209 private String packages;
210 private String targetJar;
211 private boolean resolveFiltered = false;
212 private String excludePkg;
213 private String includePkg;
214 private String classpath;
215 private Path cPath;
216 private String manifestClassPath;
217 private String manifestMainClass;
218 private boolean cacheClassFiles = true;
219 private boolean detectrmi = false;
220
221 private HashMap clsMap;
222 private DynamicClassFileFinder cff = new DynamicJDK12ClassFileFinder();
223 private DynamicResourceFileFinder rff = (DynamicJDK12ClassFileFinder) cff;
224 private CPoolReader cpoolreader = new CPoolReader(cff);
225 private ClassFilter filter;
226 private HashSet refusedNames;
227 private Set additionalFiles = new HashSet();
228 private Set additionalClasses = new HashSet();
229 private Set resources = new HashSet();
230
231 private Set ignorableClasses = new HashSet();
232
233 /**
234 * Execute the task.
235 *
236 * @see org.apache.tools.ant.Task#execute()
237 */
238 public void execute() throws BuildException {
239
240 Set ignorableClasses2 = new HashSet();
241 for (Iterator i = ignorableClasses.iterator(); i.hasNext();) {
242 ignorableClasses2.add(((ClassSpec) i.next()).name);
243 }
244
245 ignorableClasses = ignorableClasses2;
246
247 if (cacheClassFiles) {
248 ((DynamicJDK12ClassFileFinder) cff).setClassCacheOn(true);
249 }
250
251 if (targetJar == null)
252 throw new BuildException("Missing mandatory \"targetJar\" attribute");
253 if (classes == null && packages == null)
254 throw new BuildException("Missing mandatory \"classes\" or \"packages\" attribute");
255 if (classes != null && packages != null)
256 throw new BuildException("Only one of \"classes\" or \"packages\" can be specified");
257 if (classpath != null)
258 cff.addClassPathEntry(classpath);
259 if (cPath != null)
260 cff.addClassPathEntry(cPath.toString());
261 String[] clsNames;
262 if (classes != null) {
263 // "classes" is specified (it has precedence)
264 clsNames = getStringArray(classes);
265 } else {
266 // "package" is specified
267 // Explore the packages to find the relevant classes
268 String[] pkgNames = getStringArray(packages);
269 String cp2 = classpath;
270 //String cp2=System.getProperty("java.class.path");
271 /*if (classpath!=null)
272 cp2+=System.getProperty("path.separator")+classpath;*/
273 ClassPackageExplorer pkgExplorer = new SimpleClassPackageExplorer(cp2);
274 Set cls = new HashSet();
275 for (int i = 0; i < pkgNames.length; i++) {
276 log("Looking for classes in package " +
277 pkgNames[i] +
278 " using " +
279 cp2);
280 String[] tmp = pkgExplorer.listPackage(pkgNames[i]);
281 for (int j = 0; j < tmp.length; j++)
282 cls.add(tmp[j]);
283 }
284 clsNames = new String[cls.size()];
285 cls.toArray(clsNames);
286 log("Classes to pack computed from given packages list");
287 }
288 clsMap = new HashMap();
289 refusedNames = new HashSet();
290 if (includePkg == null) {
291 if (excludePkg == null)
292 excludePkg =
293 "java,javax,sun";
294 filter =
295 new PackagePrefixClassFilter(getStringArray(excludePkg),
296 false);
297 } else {
298 filter =
299 new PackagePrefixClassFilter(getStringArray(includePkg),
300 true);
301 }
302
303 if (excludePkg != null)
304 log("Excluding packages prefixed with " +
305 excludePkg);
306 if (includePkg != null)
307 log("Including only packages prefixed with " +
308 includePkg);
309
310 for (int i = 0; i < clsNames.length; i++)
311 try {
312 log("Calculating dependencies for " +
313 clsNames[i]);
314 log("Classpath is " +
315 cff.getClassPath(),
316 Project.MSG_VERBOSE);
317 // Find the dependecies for each class
318 findDependencies(clsNames[i],
319 clsMap);
320 } catch (ClassNotFoundException e) {
321 log("The current class path is " +
322 cff.getClassPath(),
323 Project.MSG_ERR);
324 throw new BuildException(e);
325 } catch (IOException e) {
326 e.printStackTrace();
327 throw new BuildException(e);
328 }
329
330 // Add any additional class
331 try {
332 for (Iterator i = additionalClasses.iterator(); i.hasNext();) {
333 ClassSpec cls = (ClassSpec) i.next();
334 log("Finding dependencies for additional class " +
335 cls.name,
336 Project.MSG_VERBOSE);
337 // Find the dependencies for each additional class
338 findDependencies(cls.name,
339 clsMap,
340 true);
341 }
342 } catch (ClassNotFoundException e) {
343 log("The current class path is " +
344 cff.getClassPath(),
345 Project.MSG_ERR);
346 throw new BuildException(e);
347 } catch (IOException e) {
348 throw new BuildException(e);
349 }
350
351 // Write the resulting target jar
352 try {
353 JarOutputStream jos = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(targetJar)));
354 if (manifestClassPath != null |
355 manifestMainClass != null) {
356 log("Creating manifest");
357 Manifest manifest = new Manifest();
358 manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION,
359 "1.0");
360 if (manifestClassPath != null) {
361 manifest.getMainAttributes()
362 .put(Attributes.Name.CLASS_PATH,
363 manifestClassPath);
364 }
365 if (manifestMainClass != null) {
366 manifest.getMainAttributes()
367 .put(Attributes.Name.MAIN_CLASS,
368 manifestMainClass);
369 }
370 JarEntry entry = new JarEntry("META-INF/MANIFEST.MF");
371 jos.putNextEntry(entry);
372 manifest.write(jos);
373 }
374
375 log("Packing " + targetJar);
376
377 processDependencies(jos);
378
379 // Also, determine and add additional files
380 if (additionalFiles.size() > 0) {
381 for (Iterator i = additionalFiles.iterator(); i.hasNext();) {
382 FileSet fs = (FileSet) i.next();
383 DirectoryScanner ds = fs.getDirectoryScanner(getProject());
384 ds.scan();
385 String[] includedFiles = ds.getIncludedFiles();
386 for (int j = 0; j <
387 includedFiles.length; j++) {
388 File f = new File(ds.getBasedir() +
389 File.separator +
390 includedFiles[j]);
391 log("Adding file " +
392 includedFiles[j],
393 Project.MSG_VERBOSE);
394 // Let's the jar entry have the same name as the file, minus the base directory
395 String fl = StringUtils.replaceAllSb(includedFiles[j],
396 File.separator,
397 "/");
398 JarEntry entry = new JarEntry(fl);
399 jos.putNextEntry(entry);
400 InputStream is = new BufferedInputStream(new FileInputStream(f));
401 int c;
402 while ((c = is.read()) !=
403 -1)
404 jos.write(c);
405 }
406 }
407 }
408
409 // And resources
410 for (Iterator i = resources.iterator(); i.hasNext();) {
411 Resource res = (Resource) i.next();
412 log("Adding resource " + res,
413 Project.MSG_VERBOSE);
414 InputStream is = rff.openResource(res.name);
415 if (is == null)
416 throw new BuildException("resource " +
417 res.name +
418 " not found. ClassPath is " +
419 rff.getClassPath());
420 JarEntry entry = new JarEntry(res.name);
421 jos.putNextEntry(entry);
422 int c;
423 while ((c = is.read()) != -1)
424 jos.write(c);
425 }
426
427 jos.close();
428 } catch (IOException e) {
429 e.printStackTrace();
430 throw new BuildException(e);
431 }
432 }
433
434 private void processDependencies(JarOutputStream jos)
435 throws IOException {
436 for (Iterator i = clsMap.keySet()
437 .iterator(); i.hasNext();) {
438 String clsName = (String) i.next();
439 String entryName = clsName.replace('.', '/') +
440 ".class";
441 JarEntry entry = new JarEntry(entryName);
442 jos.putNextEntry(entry);
443 byte[] bytecode = (byte[]) clsMap.get(clsName);
444 ByteArrayInputStream is = new ByteArrayInputStream(bytecode);
445 int c;
446 while ((c = is.read()) != -1)
447 jos.write(c);
448 }
449 }
450
451 public static void main(String args[]) {
452 Pack p = new Pack();
453
454 p.setClasses(security.WebStartUtils.class.getName());
455 p.printDependencies();
456 }
457
458 public void printDependencies() {
459 TextViewer tv = new TextViewer();
460 setMenuBar(tv);
461 SortableVector sv = new SortableVector();
462 for (Iterator i = clsMap.keySet()
463 .iterator(); i.hasNext();) {
464 String clsName = (String) i.next();
465 sv.addElement(clsName);
466
467 }
468 sv.sort();
469 tv.println("Dependencies:" + sv.size());
470 for (int i = 0; i < sv.size(); i++)
471 tv.println(sv.elementAt(i));
472 }
473
474 private void setMenuBar(final TextViewer tv) {
475 tv.hide();
476 JMenuBar jm = new JMenuBar();
477 RunMenu runMenu = new RunMenu("[Run");
478 runMenu.add(new RunMenuItem("[list classpaths^l") {
479 public void run() {
480 printClassPath(tv);
481 }
482 });
483 runMenu.add(new RunMenuItem("[add jars to classpaths^a") {
484 public void run() {
485 ClassPathUtils.addClassPath(Futil.getReadFiles(Futil.getFileFilter(".jar")));
486 printClassPath(tv);
487 }
488 });
489 runMenu.add(new RunMenuItem("run [again") {
490 public void run() {
491 DependencyUtils.main(null);
492 }
493 });
494 runMenu.add(new RunMenuItem("e[xit") {
495 public void run() {
496 System.exit(0);
497 }
498 });
499 jm.add(runMenu);
500 tv.setJMenuBar(jm);
501 tv.show();
502 }
503
504 private void printClassPath(TextViewer tv) {
505 String s[] = ClassPathUtils.getClassPaths();
506 for (int i = 0; i < s.length; i++)
507 tv.println(s[i]);
508 }
509
510 public void log(String o, int i) {
511 log(o);
512 }
513
514 public void log(String o) {
515 //System.out.println(o);
516 }
517
518 public void findDependencies(String clsName,
519 Map clsMap)
520 throws IOException,
521 ClassNotFoundException {
522 findDependencies(clsName, clsMap, false);
523 }
524
525 public void findDependencies(String clsName,
526 Map clsMap,
527 boolean failOnUnaccepted)
528 throws IOException,
529 ClassNotFoundException {
530
531 if (this.ignorableClasses.contains(clsName)) {
532 log(clsName +
533 " ignored as configured",
534 Project.MSG_VERBOSE);
535 return;
536 }
537
538 if (clsMap.keySet().contains(clsName)) {
539 //log(clsName+" already accepted.", project.MSG_VERBOSE);
540 return;
541 }
542 if (refusedNames.contains(clsName)) {
543 //log(clsName+" already refused.", project.MSG_VERBOSE);
544 return;
545 }
546 /* if (failOnUnaccepted)
547 throw new BuildException("The class "+clsName+" is not acceptable with the current includePkg/excludePkg settings ("+filter+")");
548 */
549 // Is the name an array? Try to find the component class and return
550 if (clsName.startsWith("[L")) {
551 String clsName2 = clsName.substring(2, clsName.length() - 1);
552 findDependencies(clsName2, clsMap);
553 return;
554 }
555 if (clsName.startsWith("[")) {
556 String clsName2 = clsName.substring(1);
557 if ("B".equals(clsName2))
558 return;
559 else if ("C".equals(clsName2))
560 return;
561 else if ("D".equals(clsName2))
562 return;
563 else if ("F".equals(clsName2))
564 return;
565 else if ("I".equals(clsName2))
566 return;
567 else if ("J".equals(clsName2))
568 return;
569 else if ("S".equals(clsName2))
570 return;
571 else if ("Z".equals(clsName2))
572 return;
573 else if ("V".equals(clsName2)) return;
574 findDependencies(clsName2, clsMap);
575 return;
576 }
577
578 // Load the class
579 byte[] bytecode = cff.getClassBytes(clsName);
580 CPoolReader.classfile cf = cpoolreader.readClassData(bytecode);
581 // Add it to the set, if not filtered out
582 String[] tmp = splitClassName(clsName);
583 boolean accepted = filter.accept(tmp[0],
584 tmp[1],
585 cf);
586 if (failOnUnaccepted && !accepted)
587 throw new BuildException("The class " +
588 tmp[0] +
589 "." +
590 tmp[1] +
591 " is not acceptable with the current includePkg/excludePkg settings (" +
592 filter +
593 ")");
594 if (accepted) {
595 clsMap.put(clsName, bytecode);
596 log(clsName + " accepted.",
597 Project.MSG_VERBOSE);
598 } else {
599 refusedNames.add(clsName);
600 log(clsName + " refused.",
601 Project.MSG_VERBOSE);
602 }
603 if (accepted || resolveFiltered) {
604 // If RMI detection is active and the class implements UnicastRemoteObject,
605 // try to find the stubs
606 if (detectrmi && cf.isInterface()) {
607 //System.out.println("Checking if "+clsName+" implements Remote...");
608 String superClass = cf.getSuperClass();
609 if (superClass.equals("java.rmi.Remote")) {
610 String stubClsName = clsName +
611 "_Stub";
612 byte[] stubBytecode = cff.getClassBytes(stubClsName);
613 clsMap.put(stubClsName,
614 stubBytecode);
615 }
616 }
617
618 // Browse trhu all the class names mentioned in the constant pool, and find all their dependencies
619 String[] usedClasses = cf.getUsedClasses();
620 for (int i = 0; i <
621 usedClasses.length; i++) {
622 String usedClassName = usedClasses[i].replace('/', '.');
623 findDependencies(usedClassName,
624 clsMap);
625 }
626 }
627 }
628
629
630 private static String[] splitClassName(String clsName) {
631 int i = clsName.lastIndexOf('.');
632 String[] result = new String[2];
633 if (i == -1) {
634 result[0] = "";
635 result[1] = clsName;
636 } else {
637 result[0] = clsName.substring(0, i);
638 result[1] = clsName.substring(i + 1);
639 }
640 return result;
641 }
642
643 private static String[] getStringArray(String classes) {
644 StringTokenizer st = new StringTokenizer(classes, ";, ");
645 String[] array = new String[st.countTokens()];
646 int i = 0;
647 while (st.hasMoreTokens())
648 array[i++] = st.nextToken();
649 return array;
650 }
651
652 /**
653 * Returns the classes.
654 *
655 * @return String
656 */
657 public String getClasses() {
658 return classes;
659 }
660
661 /**
662 * Sets the classes.
663 *
664 * @param classes The classes to set
665 */
666 public void setClasses(String classes) {
667 this.classes = classes;
668 }
669
670 /**
671 * Returns the targetJar.
672 *
673 * @return String
674 */
675 public String getTargetJar() {
676 return targetJar;
677 }
678
679 /**
680 * Sets the targetJar.
681 *
682 * @param targetJar The targetJar to set
683 */
684 public void setTargetJar(String targetJar) {
685 this.targetJar = targetJar;
686 }
687
688 /**
689 * Returns the resolveFiltered.
690 *
691 * @return boolean
692 */
693 public boolean getResolveFiltered() {
694 return resolveFiltered;
695 }
696
697 /**
698 * Sets the resolveFiltered.
699 *
700 * @param resolveFiltered The resolveFiltered
701 * to set
702 */
703 public void setResolveFiltered(boolean resolveFiltered) {
704 this.resolveFiltered = resolveFiltered;
705 }
706
707 /**
708 * Returns the excludePkg.
709 *
710 * @return String
711 */
712 public String getExcludePkg() {
713 return excludePkg;
714 }
715
716 /**
717 * Sets the excludePkg.
718 *
719 * @param excludePkg The excludePkg to set
720 */
721 public void setExcludePkg(String excludePkg) {
722 this.excludePkg = excludePkg;
723 }
724
725 /*
726 public static void main(String[] args) {
727 Pack p = new Pack();
728 p.classes="org.sadun.ant.tasks.Pack";
729 p.targetJar="c:\\temp\\test.jar";
730 p.execute();
731 }
732 */
733
734
735 /**
736 * Ant entry point for <code>classpath</code>
737 * subelements.
738 */
739 public Path createClassPath() {
740 if (cPath == null) {
741 cPath = new Path(getProject());
742 }
743 return cPath;
744 }
745
746 /**
747 * Returns the classpath.
748 *
749 * @return String
750 */
751 public String getClasspath() {
752 return classpath;
753 }
754
755 /**
756 * Sets the classpath.
757 *
758 * @param classpath The classpath to set
759 */
760 public void setClasspath(String classpath) {
761 this.classpath = classpath;
762 }
763
764 /**
765 * Returns the manifestClassPath.
766 *
767 * @return String
768 */
769 public String getManifestClassPath() {
770 return manifestClassPath;
771 }
772
773 /**
774 * Returns the manifestMainClass.
775 *
776 * @return String
777 */
778 public String getManifestMainClass() {
779 return manifestMainClass;
780 }
781
782 /**
783 * Sets the manifestClassPath.
784 *
785 * @param manifestClassPath The manifestClassPath
786 * to set
787 */
788 public void setManifestClassPath(String manifestClassPath) {
789 this.manifestClassPath =
790 manifestClassPath;
791 }
792
793 /**
794 * Sets the manifestMainClass.
795 *
796 * @param manifestMainClass The manifestMainClass
797 * to set
798 */
799 public void setManifestMainClass(String manifestMainClass) {
800 this.manifestMainClass =
801 manifestMainClass;
802 }
803
804 /**
805 * Returns the includePkg.
806 *
807 * @return String
808 */
809 public String getIncludePkg() {
810 return includePkg;
811 }
812
813 /**
814 * Sets the includePkg.
815 *
816 * @param includePkg The includePkg to set
817 */
818 public void setIncludePkg(String includePkg) {
819 this.includePkg = includePkg;
820 }
821
822 /**
823 * Ant entry point for <code>additionalfileset</code>
824 * subelements.
825 * <p/>
826 *
827 * @param fs the fileset object to add,
828 * created by Ant engine
829 */
830 public void addAdditionalFileSet(FileSet fs) {
831 additionalFiles.add(fs);
832 }
833
834 /**
835 * Ant entry point for <code>additionalClass</code>
836 * subelements.
837 * <p/>
838 *
839 * @return AdditionalClass an object
840 * containing info about the class to
841 * add
842 */
843 public ClassSpec createAdditionalClass() {
844 ClassSpec cls = new ClassSpec();
845 additionalClasses.add(cls);
846 return cls;
847 }
848
849 /**
850 * Ant entry point for <code>ignoreClass</code>
851 * subelements.
852 * <p/>
853 *
854 * @return AdditionalClass an object
855 * containing info about the class to
856 * add
857 */
858 public ClassSpec createIgnoreClass() {
859 ClassSpec cls = new ClassSpec();
860 ignorableClasses.add(cls);
861 return cls;
862 }
863
864 /**
865 * Ant entry point for <code>additionalClass</code>
866 * subelements.
867 * <p/>
868 *
869 * @return AdditionalClass an object
870 * containing info about the class to
871 * add
872 */
873 public Resource createResource() {
874 Resource res = new Resource();
875 resources.add(res);
876 return res;
877 }
878
879 /**
880 * Returns the cacheClassFiles.
881 *
882 * @return boolean
883 */
884 public boolean isCacheClassFiles() {
885 return cacheClassFiles;
886 }
887
888 /**
889 * Sets the cacheClassFiles.
890 *
891 * @param cacheClassFiles The cacheClassFiles
892 * to set
893 */
894 public void setCacheClassFiles(boolean cacheClassFiles) {
895 this.cacheClassFiles = cacheClassFiles;
896 }
897
898 /**
899 * Returns the packages.
900 *
901 * @return String
902 */
903 public String getPackages() {
904 return packages;
905 }
906
907 /**
908 * Sets the packages.
909 *
910 * @param packages The packages to set
911 */
912 public void setPackages(String packages) {
913 this.packages = packages;
914 }
915
916 }
917