/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>&lt;classpath&gt;</code> element. 
91    * <p/> 
92    * &lt;pack&gt; 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>&lt;additionalclass&gt;</b> and 
98    * <b>&lt;additionalfileset&gt;</b> elements. 
99    * <p/> 
100   * <b>&lt;additionalclass&gt;</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   * &lt;additionalclass name="javax.transaction.TransactionManager"/&gt; 
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>&lt;additionalfileset&gt;</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   *   &lt;additionalfileset dir="${basedir}"&gt; 
123   *    &lt;include name="META-INF/services/*"/&gt; 
124   *   &lt;/additionalfileset&gt; 
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