KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > nbbuild > LocalizedJar


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.nbbuild;
21
22 import java.io.*;
23 import java.util.*;
24 import java.util.Map JavaDoc; // override org.apache.tools.ant.Map
25
import java.util.zip.*;
26 import java.util.jar.*;
27
28 import org.apache.tools.ant.*;
29 import org.apache.tools.ant.taskdefs.MatchingTask;
30 import org.apache.tools.ant.types.*;
31
32 /** Create a JAR file with locale variants.
33  * Whenever files are found which should be localized, or are the result
34  * of localization, places them in separate JAR files named according to the locale,
35  * in a <samp>locale/</samp> subdirectory of the directory containing the master JAR.
36  * Each sub-JAR gets a manifest which just has some informational tags
37  * indicating its purpose (locale and branding):
38  * <code>X-Informational-Archive-Locale</code> and/or <code>X-Informational-Archive-Branding</code>.
39  * The values may be e.g. <code>ja</code> or <code>f4j_ce</code>; or <code>-</code>
40  * if there is no suffix for this JAR.
41  * You can control the available locales; brandings; and set of files which should
42  * always be considered part of the localizable base kit.
43  * You can use the "branding" and "locale" subelements to control the branded
44  * and localized .jar files that will be produced. Also, you can set the global
45  * properties "locjar.brands" and "locjar.locales" to comma-separated
46  * lists of branding or locale identifiers so that NetBeans-based projects can
47  * brand or localize NetBeans without having to maintain modified versions of all
48  * the individual Ant scripts
49  * Originally this Ant task didn't recognize files below a directory with the
50  * same name as a locale as being localized. Now it does so by default.
51  * <p>Based on <code>&lt;zip&gt;</code> and <code>&lt;jar&gt;</code> tasks in Ant,
52  * but not feasible to simply subclass or compose them.
53  * @see <a HREF="http://www.netbeans.org/devhome/docs/i18n/index.html">NetBeans I18N documentation</a>
54  * @author Jesse Glick
55  */

56 public class LocalizedJar extends MatchingTask {
57
58     private List<FileSet> localeKits = new LinkedList<FileSet> ();
59     private List<LocaleOrB> locales = new LinkedList<LocaleOrB> ();
60     private List<LocaleOrB> brandings = new LinkedList<LocaleOrB> ();
61     private File jarFile;
62     private File baseDir;
63     private boolean doCompress = false;
64     private static long emptyCrc = new CRC32 ().getValue ();
65     private List<FileSet> filesets = new LinkedList<FileSet> ();
66     private File manifest;
67     private boolean checkPathLocale = true ;
68     private boolean warnMissingDir = false ;
69     private boolean warnMissingDirSet = false ;
70     private boolean preserveModuleJar = true;
71     private boolean alwaysIncludeManifest = false;
72
73     /** Locale or branding specifier.
74      * Represents a complete locale or branding suffix,
75      * e.g. <code>ja</code> or <code>ja_JP</code>
76      * (but not simply <code>JP</code>).
77      * For branding, e.g. <code>f4j</code> or <code>f4j_ce</code>.
78      * You must include all relevant suffixes if you expect them to match
79      * (but the task will handle a branding suffix combined with a locale
80      * suffix, in that order).
81      */

82     public class LocaleOrB {
83         String JavaDoc n;
84         /** The suffix. */
85         public void setName (String JavaDoc n) {
86             this.n = n;
87         }
88     }
89
90     /** Distinguish particular files that will be considered localizable.
91      * This nested <samp>&lt;localekit&gt;</samp> has the same syntax as a FileSet.
92      * So typically you will build a JAR from a fileset containing all build
93      * products within a given directory; the "locale kit" should be a fileset
94      * matching all properties files, for example, and maybe icons which you would
95      * expect someone to try to localize--in general, anything which will be referenced
96      * in code using a localized lookup (<code>NbBundle</code>).
97      * While files with recognized localized (or branded) suffixes automatically go into
98      * marked JARs in the <samp>locale/</samp> subdirectory, files considered part of the
99      * locale kit also always go into this subdirectory; if they have no suffix, they will
100      * be placed in a suffixless locale JAR.
101      * So localizers can simply look at this JAR file and brand/localize it as they see fit.
102      */

103     public void addLocalekit (FileSet fs) {
104         localeKits.add (fs);
105     }
106
107     /** Add a recognized locale suffix. */
108     public LocaleOrB createLocale () {
109         LocaleOrB l = new LocaleOrB ();
110         locales.add (l);
111         return l;
112     }
113
114     /** Add a recognized branding suffix. */
115     public LocaleOrB createBranding () {
116         LocaleOrB l = new LocaleOrB ();
117         brandings.add (l);
118         return l;
119     }
120
121     /** JAR file to create.
122      * In fact this is the location of the "base" JAR;
123      * locale-specific JARs may be created in the <samp>locale/</samp> subdirectory
124      * of the directory containing this JAR, and will be named according to the name
125      * of this JAR.
126      * Compare Ant's <samp>&lt;jar&gt;</samp> task.
127      */

128     public void setJarfile (File jarFile) {
129         if (! jarFile.getName ().endsWith (".jar")) {
130             throw new BuildException ("jarfile attribute must be a file with *.jar extension");
131         }
132         if (jarFile.getParentFile () == null) {
133             throw new BuildException ("jarfile attribute must have a containing directory");
134         }
135         this.jarFile = jarFile;
136     }
137
138     /** Base directory to JAR.
139      * Compare Ant's <samp>&lt;jar&gt;</samp> task.
140      */

141     public void setBasedir (File baseDir) {
142         this.baseDir = baseDir;
143     }
144
145     /** Turn on or off compression (default off).
146      * Compare Ant's <samp>&lt;jar&gt;</samp> task.
147      */

148     public void setCompress(boolean compress) {
149         doCompress = compress;
150     }
151
152     /** Turn on/off preserving original module jars with 'code'
153      * Set it to 'true' to not allow overwriting of module jars
154      * with localization/branding stuff
155      */

156     public void setPreserveModuleJar(boolean pmj) {
157         preserveModuleJar = pmj;
158     }
159
160     /** Turn on/off inclusion of manifest even for localized and/or branded
161      * jars. Set it to true if you want to add special manifest tags
162      * to all produced jarfiles
163      */

164     public void setAlwaysIncludeManifest(boolean aim) {
165         alwaysIncludeManifest = aim;
166     }
167
168     /** A set of files to JAR up.
169      * Compare Ant's <samp>&lt;jar&gt;</samp> task.
170      */

171     public void addFileset (FileSet set) {
172         filesets.add (set);
173     }
174
175     /** Manifest file for the JAR.
176      * Compare Ant's <samp>&lt;jar&gt;</samp> task.
177      */

178     public void setManifest (File manifest) {
179     this.manifest = manifest;
180     }
181
182     /** By default this is true. If set to false, then this task will
183      * not recognize files below a directory with the same name as a
184      * locale as being localized (unless the simple filename also
185      * includes the locale).
186      */

187     public void setCheckPathLocale( boolean doit) {
188       checkPathLocale = doit ;
189     }
190
191     /** This is false by default, in which case missing dirs in the
192      * filesets cause a BuildException to be thrown. If true, then
193      * a warning is printed but the build will continue.
194      * This task will also look for a global property
195      * "locjar.warnMissingDir" if this attribute isn't set.
196      */

197     public void setWarnMissingDir( boolean b) {
198       warnMissingDir = b ;
199       warnMissingDirSet = true ;
200     }
201
202     public void execute () throws BuildException {
203
204         // Sanity checks:
205
if (baseDir == null && filesets.size () == 0) {
206             throw new BuildException ("basedir attribute must be set, or at least one fileset must be given!");
207         }
208         if (jarFile == null) {
209             throw new BuildException ("You must specify the JAR file to create!");
210         }
211         if (manifest != null && ! manifest.isFile ()) {
212             throw new BuildException ("The specified manifest does not actually exist.");
213         }
214
215     // If needed, warn that directories are missing. //
216
if( shouldWarnMissingDir() && warnIfMissingDir()) {
217
218       // Stop if dirs were missing. //
219
return ;
220     }
221
222     // Look for global locales or brandings to use. //
223
addGlobalLocaleAndBranding() ;
224
225         //System.err.println ("Stage #1");
226
// First find out which files need to be archived.
227
Map JavaDoc<String JavaDoc, File> allFiles = new HashMap<String JavaDoc, File> (); // all files to do something with; Map<String,File> from JAR path to actual file
228
// Populate it.
229
{
230             List<FileScanner> scanners = new ArrayList<FileScanner> (filesets.size () + 1);
231             if (baseDir != null) {
232                 scanners.add (getDirectoryScanner (baseDir));
233             }
234             for (FileSet fs: filesets) {
235                 scanners.add(fs.getDirectoryScanner(getProject()));
236             }
237             for (FileScanner scanner: scanners) {
238                 File thisBaseDir = scanner.getBasedir ();
239                 String JavaDoc[] files = scanner.getIncludedFiles ();
240                 for (int i = 0; i < files.length; i++) {
241                     String JavaDoc name = files[i].replace (File.separatorChar, '/');
242                     if (name.equalsIgnoreCase ("META-INF/MANIFEST.MF")) {
243                         log ("Warning: ignoring META-INF/MANIFEST.MF found among scanned files", Project.MSG_WARN);
244                         continue;
245                     }
246                     allFiles.put (name, new File (thisBaseDir, files[i]));
247                 }
248             }
249         }
250
251         //System.err.println ("Stage #2");
252
// Now find all files which should always be put into a locale
253
// kit (e.g. dir/locale/name.jar, no special locale or
254
// branding, but distinguished as localizable/brandable).
255
Set<File> localeKitFiles = new HashSet<File> (); // all locale-kit files
256
// Populate this one.
257
{
258             for (FileSet fs: localeKits) {
259                 FileScanner scanner = fs.getDirectoryScanner(getProject());
260                 File thisBaseDir = scanner.getBasedir ();
261                 String JavaDoc[] files = scanner.getIncludedFiles ();
262                 for (int i = 0; i < files.length; i++) {
263                     localeKitFiles.add (new File (thisBaseDir, files[i]));
264                 }
265             }
266         }
267
268         //System.err.println ("Stage #3");
269
// Compute list of supported locales and brandings.
270
List<String JavaDoc> locales2 = new LinkedList<String JavaDoc> ();
271         List<String JavaDoc> brandings2 = new LinkedList<String JavaDoc> (); // all brandings
272
// Initialize above two.
273

274         for (LocaleOrB lob: locales) {
275             locales2.add (lob.n);
276         }
277         for (LocaleOrB lob: brandings) {
278             brandings2.add (lob.n);
279         }
280         class InverseLengthComparator implements Comparator<String JavaDoc> {
281             public int compare (String JavaDoc s1, String JavaDoc s2) {
282                 return s2.length () - s1.length ();
283             }
284         }
285         Collections.sort (locales2, new InverseLengthComparator ());
286         Collections.sort (brandings2, new InverseLengthComparator ());
287
288         //System.err.println ("Stage #4");
289
// Analyze where everything goes.
290
Set<File> jars = new HashSet<File> (); //JAR files to build
291
Map JavaDoc<File,String JavaDoc> localeMarks = new HashMap<File,String JavaDoc> (); // JAR files to locale (or null for basic JAR, "-" for blank)
292
Map JavaDoc<File,String JavaDoc> brandingMarks = new HashMap<File,String JavaDoc> (); // JAR files to branding (or null for basic JAR, "-" for blank)
293
Map JavaDoc<File,Map JavaDoc<String JavaDoc,File>> router = new HashMap<File,Map JavaDoc<String JavaDoc,File>> (); // JAR files to map of JAR path to actual file (file may be null for dirs)
294
{
295         String JavaDoc localeDir ;
296             for (Map.Entry JavaDoc<String JavaDoc, File> entry: allFiles.entrySet()) {
297                 String JavaDoc path = entry.getKey ();
298
299 log( "==> Examining file: " + path, Project.MSG_DEBUG) ;
300
301                 File file = entry.getValue ();
302                 // First see if it matches a known branding, locale, or pair of one of each.
303
String JavaDoc testpath = path;
304                 int idx = testpath.lastIndexOf ('/');
305                 if (idx != -1) testpath = testpath.substring (idx + 1);
306                 idx = testpath.lastIndexOf ('.');
307                 if (idx != -1) testpath = testpath.substring (0, idx);
308                 String JavaDoc thisLocale = null;
309                 Iterator it2 = locales2.iterator ();
310                 while (it2.hasNext ()) {
311                     String JavaDoc tryLocale = (String JavaDoc) it2.next ();
312                     if (testpath.endsWith ("_" + tryLocale)) {
313                         thisLocale = tryLocale;
314                         testpath = testpath.substring (0, testpath.length () - 1 - tryLocale.length ());
315                         break;
316                     }
317                 }
318                 String JavaDoc thisBranding = null;
319                 it2 = brandings2.iterator ();
320                 while (it2.hasNext ()) {
321                     String JavaDoc tryBranding = (String JavaDoc) it2.next ();
322                     if (testpath.endsWith ("_" + tryBranding)) {
323                         thisBranding = tryBranding;
324                         break;
325                     }
326                 }
327                 File thisjar = null; // JAR to send this file to
328

329         // Check if this file has a parent directory with the //
330
// same name as one of the locales. //
331
localeDir = checkInLocaleDir( file, locales2) ;
332         if( localeDir != null) {
333           thisLocale = localeDir ;
334         }
335
336
337                 if( thisLocale != null) {
338                     log( " Locale: " + thisLocale, Project.MSG_DEBUG) ;
339                 } else {
340                     log( " Locale not set", Project.MSG_DEBUG) ;
341                 }
342                 if( thisBranding != null) {
343                     log( " Branding: " + thisBranding, Project.MSG_DEBUG) ;
344                 } else {
345                     log( " Branding not set", Project.MSG_DEBUG) ;
346                 }
347                 if( localeKitFiles.contains( file)) {
348                     log( " Localizable file.", Project.MSG_DEBUG) ;
349                 }
350
351
352                 if (thisLocale != null || thisBranding != null || localeKitFiles.contains (file)) {
353                     String JavaDoc name = jarFile.getName ();
354                     // We know jarFile is a *.jar so this is safe:
355
name = name.substring (0, name.length () - 4);
356                     if (thisBranding != null) {
357                         name += '_' + thisBranding;
358                     }
359                     if (thisLocale != null) {
360                         name += '_' + thisLocale;
361                     }
362                     name += ".jar";
363                     if ((preserveModuleJar) && (thisBranding == null) && (thisLocale == null)) {
364                         thisjar = null;
365                         log(" Preserving module file (1): " + jarFile.getName(), Project.MSG_DEBUG);
366                     } else {
367                         thisjar = new File (new File (jarFile.getParentFile (), "locale"), name);
368                         localeMarks.put (thisjar, ((thisLocale != null) ? thisLocale : "-"));
369                         brandingMarks.put (thisjar, ((thisBranding != null) ? thisBranding : "-"));
370                     }
371                 } else {
372             if (preserveModuleJar) {
373                         thisjar = null;
374                         log(" Preserving module file (2): " + jarFile.getName(), Project.MSG_DEBUG);
375                     } else {
376                         thisjar = jarFile;
377                         localeMarks.put (thisjar, null);
378                         brandingMarks.put (thisjar, null);
379                     }
380                 }
381                 if (thisjar != null) {
382                 log(" Adding file " + thisjar.getName() + " to 'jars' HashSet", Project.MSG_DEBUG);
383                     jars.add (thisjar);
384                     Map JavaDoc<String JavaDoc, File> files = router.get (thisjar);
385                     if (files == null) {
386                         files = new TreeMap<String JavaDoc, File> ();
387                         router.put (thisjar, files);
388                     }
389                     files.put (path, file);
390                 }
391             }
392         }
393
394         //System.err.println ("Stage #5");
395
// Go through JARs one by one, and build them (if necessary).
396
{
397             List<File> jars2 = new ArrayList<File> (jars);
398             class FileNameComparator implements Comparator<File> {
399                 public int compare (File f1, File f2) {
400                     return f1.toString ().compareTo (f2.toString ());
401                 }
402             }
403             Collections.sort (jars2, new FileNameComparator ());
404             for (File jar: jars2) {
405                 Map JavaDoc<String JavaDoc, File> files = router.get (jar);
406                 if (jar.exists ()) {
407                     // Do an up-to-date check first.
408
long time = jar.lastModified ();
409                     if (manifest == null || manifest.lastModified () <= time) {
410                         boolean upToDate = true;
411                         Iterator it2 = files.values ().iterator ();
412                         while (it2.hasNext ()) {
413                             File f = (File) it2.next ();
414                             if (f.lastModified () > time) {
415                                 upToDate = false;
416                                 break;
417                             }
418                         }
419                         if (upToDate) {
420                             // Skip this JAR.
421
continue;
422                         }
423                     }
424                 }
425                 log ("Building localized/branded jar: " + jar);
426                 IOException closing = null;
427                 try {
428                     jar.getParentFile ().mkdirs ();
429                     ZipOutputStream out = new ZipOutputStream (new FileOutputStream (jar));
430                     try {
431                         out.setMethod (doCompress ? ZipOutputStream.DEFLATED : ZipOutputStream.STORED);
432                         String JavaDoc localeMark = localeMarks.get (jar);
433                         String JavaDoc brandingMark = brandingMarks.get (jar);
434                         Set<String JavaDoc> addedDirs = new HashSet<String JavaDoc> ();
435                         // Add the manifest.
436
InputStream is;
437                         long time;
438                         java.util.jar.Manifest JavaDoc mani;
439                         if (manifest != null && localeMark == null && brandingMark == null) {
440                             // Master JAR, and it has a manifest.
441
is = new FileInputStream (manifest);
442                             time = manifest.lastModified ();
443                             try {
444                                 mani = new java.util.jar.Manifest JavaDoc (is);
445                             } finally {
446                                 is.close ();
447                             }
448                         } else if ((manifest != null) && (alwaysIncludeManifest)) {
449                             // always include specified manifest in localized/branded jars
450
// such manifest must not contain attribute OpenIDE-Module
451
// check supplied manifest and if contains key OpenIDE-Module, issue warning
452
// and fallback to default Ant's manifest boilerplate (like no manifest was supplied)
453
is = new FileInputStream (manifest);
454                             time = manifest.lastModified ();
455                             try {
456                                 mani = new java.util.jar.Manifest JavaDoc (is);
457                             } finally {
458                                 is.close ();
459                             }
460                             Attributes attr = mani.getMainAttributes ();
461                             //check if it's not module manifest for jarfile with localized/branded resources
462
if ((attr.containsKey ("OpenIDE-Module")) && ((localeMark != null) || (brandingMark != null))){
463                                 String JavaDoc lbmsg = "";
464                                 if (localeMark != null) {
465                                     lbmsg = "locale: '"+localeMark+"' ";
466                                 }
467                                 if (brandingMark != null) {
468                                     lbmsg = "branding: '"+brandingMark+"' ";
469                                 }
470                                 log("WARNING: Ignoring supplied NetBeans module manifest for "+lbmsg+"jarfile '"+jar+"'. Using default Ant manifest bolilerplate. "
471                                    +"Use -verbose option to see more details.", Project.MSG_INFO);
472                                 log("WARNING(verbose): Supplied manifest file '"+manifest.getAbsolutePath()+"' contains "
473                                    +"key OpenIDE-Module, which cannot be included in manifest of localized "
474                                    +"and/or branded jar. Ignoring whole manifest for now. To fix this you have "
475                                    +"to avoid using NetBeans module manifest file together with attribute "
476                                    +"'allwaysincludemanifest' set to 'true' and non-empty properties 'locjar.locales' "
477                                    +"and 'locjar.brands'. You can accomplish that by i.e. using Ant's <jar> task "
478                                    +"for regular NetBeans module jarfile packaging and use NetBeans' Ant extension "
479                                    +"task <"+this.getTaskName()+"> for localized and/or branded jars. Using default "
480                                    +"Ant's manifest boilerplate instead.", Project.MSG_VERBOSE);
481                                 try {
482                                     is.close();
483                                 } finally {
484                                     is = MatchingTask.class.getResourceAsStream ("/org/apache/tools/ant/defaultManifest.mf");
485                                     time = System.currentTimeMillis ();
486                                     try {
487                                         mani = new java.util.jar.Manifest JavaDoc (is);
488                                     } finally {
489                                        is.close ();
490                                     }
491                                 }
492                             }
493                         } else {
494                             // Some subsidiary JAR.
495
is = MatchingTask.class.getResourceAsStream ("/org/apache/tools/ant/defaultManifest.mf");
496                             time = System.currentTimeMillis ();
497                             try {
498                                 mani = new java.util.jar.Manifest JavaDoc (is);
499                             } finally {
500                                 is.close ();
501                             }
502                         }
503                         Attributes attr = mani.getMainAttributes ();
504                         if (! attr.containsKey (Attributes.Name.MANIFEST_VERSION)) {
505                             attr.put (Attributes.Name.MANIFEST_VERSION, "1.0");
506                         }
507                         if (localeMark != null) {
508                             attr.putValue ("X-Informational-Archive-Locale", localeMark);
509                         }
510                         if (brandingMark != null) {
511                             attr.putValue ("X-Informational-Archive-Branding", brandingMark);
512                         }
513                         ByteArrayOutputStream baos = new ByteArrayOutputStream ();
514                         mani.write (baos);
515                         byte[] bytes = baos.toByteArray ();
516                         addToJar (new ByteArrayInputStream (bytes), new ByteArrayInputStream (bytes),
517                                   out, "META-INF/MANIFEST.MF", time, addedDirs);
518                         // Now regular files.
519
for (Map.Entry JavaDoc<String JavaDoc, File> entry: files.entrySet()) {
520                             String JavaDoc path = entry.getKey ();
521                             File file = entry.getValue ();
522                             addToJar (new FileInputStream (file), new FileInputStream (file),
523                                       out, path, file.lastModified (), addedDirs);
524                         }
525
526             // If desired, write the root of the srcDir to a file. //
527
writeSrcDir() ;
528                     } finally {
529                         try {
530                             out.close ();
531                         } catch (IOException ex) {
532                             closing = ex;
533                         }
534                     }
535
536                     if (closing != null) {
537                         // if there was a closing exception and no other one
538
throw closing;
539                     }
540                 } catch (IOException ioe) {
541                     String JavaDoc msg = "Problem creating JAR: " + ioe.getMessage ();
542                     if (! jar.delete ()) {
543                         msg += " (and the JAR is probably corrupt but I could not delete it)";
544                     }
545                     throw new BuildException(msg, ioe, getLocation());
546                 }
547             }
548         }
549
550     } // end execute()
551

552     private void addToJar (InputStream in1, InputStream in2, ZipOutputStream out,
553                            String JavaDoc path, long lastModified, Set<String JavaDoc> addedDirs) throws IOException {
554         try {
555             if (path.endsWith ("/")) {
556                 throw new IOException ("Bad path: " + path);
557             }
558             // Add parent dirs as needed:
559
int pos = -1;
560             while ((pos = path.indexOf ('/', pos + 1)) != -1) {
561                 String JavaDoc dir = path.substring (0, pos + 1);
562                 if (! addedDirs.contains (dir)) {
563                     addedDirs.add (dir);
564                     ZipEntry ze = new ZipEntry (dir);
565                     ze.setSize (0);
566                     ze.setMethod (ZipEntry.STORED);
567                     ze.setCrc (emptyCrc);
568                     ze.setTime (lastModified);
569                     out.putNextEntry (ze);
570                 }
571             }
572             // Add the file itself:
573
ZipEntry ze = new ZipEntry (path);
574             ze.setMethod (doCompress ? ZipEntry.DEFLATED : ZipEntry.STORED);
575             ze.setTime (lastModified);
576             long size = 0;
577             CRC32 crc = new CRC32 ();
578             byte[] buf = new byte[4096];
579             int read;
580             while ((read = in1.read (buf)) != -1) {
581                 crc.update (buf, 0, read);
582                 size += read;
583             }
584             in1.close ();
585             ze.setCrc (crc.getValue ());
586             ze.setSize (size);
587             out.putNextEntry (ze);
588             while ((read = in2.read (buf)) != -1) {
589                 out.write (buf, 0, read);
590             }
591         } finally {
592             in2.close ();
593             in1.close ();
594         }
595     } // end addToJar()
596

597
598   // If the name of any parent directory of this file is the same as //
599
// one of the locales, return the locale. //
600
protected String JavaDoc checkInLocaleDir( File file,
601                      List<String JavaDoc> locales) {
602
603     // See if this functionality is disabled. //
604
if( !checkPathLocale) {
605       return null ;
606     }
607
608     int idx ;
609     String JavaDoc locale_dir, ret = null ;
610     String JavaDoc path = file.getPath() ;
611
612     // For each locale. //
613
for (String JavaDoc loc: locales) {
614
615       // If the path contains a dir with the same name as the //
616
// locale. //
617
locale_dir = new String JavaDoc( file.separator) ;
618       locale_dir += loc ;
619       locale_dir += file.separator ;
620       idx = path.indexOf( locale_dir) ;
621       if( idx != -1) {
622
623     // Stop and return this locale. //
624
ret = loc ;
625     break ;
626       }
627     }
628
629     return( ret) ;
630   }
631
632   ////////////////////////////////////////////////////////////////////
633
// This section of code supports the feature that this class will //
634
// look for global properties that specify locales and brandings //
635
// that should be used. //
636
protected void addGlobalLocaleAndBranding() {
637     addGlobals( getGlobalLocaleVarName(), locales) ;
638     addGlobals( getOldGlobalLocaleVarName(), locales) ;
639     addGlobals( getGlobalBrandingVarName(), brandings) ;
640     addGlobals( getOldGlobalBrandingVarName(), brandings) ;
641   }
642
643   protected String JavaDoc getGlobalLocaleVarName() {
644     return( new String JavaDoc( "locjar.locales")) ;
645   }
646
647   protected String JavaDoc getGlobalBrandingVarName() {
648     return( new String JavaDoc( "locjar.brands")) ;
649   }
650
651   // For backwards compatibility. //
652
protected String JavaDoc getOldGlobalLocaleVarName() {
653     return( new String JavaDoc( "locjar_global_locales")) ;
654   }
655
656   // For backwards compatibility. //
657
protected String JavaDoc getOldGlobalBrandingVarName() {
658     return( new String JavaDoc( "locjar_global_brands")) ;
659   }
660
661   protected void addGlobals( String JavaDoc var_name,
662                  List<LocaleOrB> list) {
663     String JavaDoc prop = null ;
664     StringTokenizer tokenizer = null ;
665     String JavaDoc tok = null ;
666     LocaleOrB lorb = null ;
667
668     // Foreach string in the global list. //
669
prop = getProject().getProperty( var_name) ;
670     if( prop != null && !prop.equals( "")) {
671       tokenizer = new StringTokenizer( prop, ", ") ;
672       while( tokenizer.hasMoreTokens()) {
673     tok = tokenizer.nextToken() ;
674
675     // Add a new entry in the given list. //
676
lorb = new LocaleOrB() ;
677     lorb.setName( tok) ;
678     list.add( lorb) ;
679       }
680     }
681   }
682   //////////////////////////////////////////////////////////////////////
683

684   protected boolean shouldWarnMissingDir() {
685     String JavaDoc s ;
686     boolean ret = false ; // Default false. //
687

688     // If the attribute is set, use its value. //
689
if( warnMissingDirSet) {
690       ret = warnMissingDir ;
691     }
692
693     // Otherwise use the global property value, if set. //
694
else {
695       s = getProject().getProperty("locjar.warnMissingDir");
696       if( s != null && !s.trim().equals( "")) {
697     ret = getProject().toBoolean(s);
698       }
699     }
700
701     return( ret) ;
702   }
703
704   // If any dir's don't exist, warn the user and return true. //
705
protected boolean warnIfMissingDir() {
706     File dir ;
707     boolean ret = false ;
708
709     // Print warning if the basedir doesn't exist. //
710
if( baseDir != null && !baseDir.exists()) {
711       ret = true ;
712       printMissingDirWarning( baseDir) ;
713     }
714
715     // For each fileset. //
716
for (FileSet fileset: filesets) {
717     // Print warning if the dir doesn't exist. //
718
dir = fileset.getDir(getProject());
719     if( dir != null && !dir.exists()) {
720       ret = true ;
721       printMissingDirWarning( dir) ;
722     }
723       }
724     return( ret) ;
725   }
726
727   // Warn the user that the given dir doesn't exist. //
728
protected void printMissingDirWarning( File dir) {
729     log( "WARNING: Skipping this task: Directory " + dir.getPath() + " doesn't exist.") ;
730   }
731
732   protected boolean shouldWriteSrcDir() {
733     boolean ret = false ;
734     String JavaDoc s = getProject().getProperty("locjar.writeSrcDir");
735     if( s != null && getProject().toBoolean(s)) {
736       ret = true ;
737     }
738     return( ret) ;
739   }
740
741   protected void writeSrcDir() {
742     String JavaDoc name ;
743     int idx, fromIdx ;
744     OutputStreamWriter osw ;
745     FileOutputStream fos ;
746     File file ;
747
748     if( shouldWriteSrcDir() && jarFile != null && baseDir != null) {
749       name = jarFile.getPath() ;
750       fromIdx = getNetbeansStartIdx() ;
751       idx = name.indexOf( File.separator+"netbeans"+File.separator, fromIdx) ;
752       if( idx != -1) {
753     try {
754       file = new File( name.substring( 0, idx) + File.separator + "srcdir.properties") ;
755       fos = new FileOutputStream( file) ;
756       osw = new OutputStreamWriter( fos) ;
757       osw.write( "srcdir=" + baseDir + "\n") ;
758       osw.close() ;
759       fos.close() ;
760     }
761     catch( Exception JavaDoc e) {
762       System.out.println( "ERROR: " + e.getMessage()) ;
763       e.printStackTrace() ;
764       throw new BuildException() ;
765     }
766       }
767       else {
768     throw new BuildException( "ERROR: Couldn't find netbeans dir to write srcdir.properties to.") ;
769       }
770     }
771   }
772
773   // Return the index to start searching from to find the "netbeans"
774
// directory into which the "srcdir.properties" file will be
775
// written.
776
protected int getNetbeansStartIdx() {
777     int startIdx = 0 ;
778     int idx ;
779
780     idx = baseDir.getPath().lastIndexOf( File.separator+
781                      "netbeans"+File.separator) ;
782     if( idx != -1) {
783       startIdx = idx + 1 ;
784     }
785     return( startIdx) ;
786   }
787 }
788
Popular Tags