2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.nbbuild;
47
import org.apache.tools.ant.* ;
48
import org.apache.tools.ant.taskdefs.* ;
49
import org.apache.tools.ant.types.* ;
51
/** Runs the makenbm task for each locale specified in the
52
* global property locmakenbm.locales.
53
* NOTE: Currently this runs makelnbm, since the new
54
* functionality in that hasn't been merged into makenbm
57
* @author Jerry Huth (email: jerry@solidstep.com)
59
public class LocMakeNBM extends Task {
61
protected String locales = null ;
62
protected String mainDir = null ;
63
protected File topDir = null ;
64
protected String fileName = null ;
65
protected String moduleName = null ;
66
protected String baseFileName = null ;
67
protected boolean deleteInfo = false ;
68
protected String nbmIncludes = null ;
69
protected String modInfo = null ;
70
protected String findLocBundle = "." ; // relative to the directory
71
// corresponding to the module's
73
protected File locBundle = null ; // path to localizing bundle - overrides
75
protected String locIncludes = null ; // comma-separated list of
76
// "<locale>:<pattern>" elements
78
public void setLocales( String s) {
81
public void setMainDir( String s) {
84
public void setTopDir( File f) {
87
public void setModule(String module) {
88
this.moduleName = module;
89
log("Setting moduleName = '"+moduleName+"'", Project.MSG_VERBOSE);
91
public void setFile( String s) {
93
log("Setting fileName = '"+fileName+"'", Project.MSG_VERBOSE);
94
if( !fileName.substring( fileName.length() - 4).equals( ".nbm")) { //NOI18N
95
throw new BuildException( "Incorrect NBM file name \""+ s+"\". NBM file name must end in '.nbm'") ;
97
baseFileName = fileName.substring( 0, fileName.length() - 4) ;
99
public void setDeleteInfo( boolean b) {
102
public void setNbmIncludes( String s) {
105
public void setModInfo( String s) {
108
public void setLocBundle( File f) {
111
public void setFindLocBundle( String s) {
114
public void setLocIncludes( String s) {
118
public void execute() throws BuildException {
122
} catch( BuildException be) {
123
be.printStackTrace();
128
public void really_execute() throws BuildException {
130
StringTokenizer stok ;
131
LinkedList<String> build_locales = new LinkedList<String>() ;
133
// Set default values. //
134
if( mainDir == null) {
135
mainDir = new String( "netbeans") ; //NOI18N
137
if( topDir == null) {
138
topDir = getProject().getBaseDir() ;
141
if (( modInfo == null) && (moduleName != null)) {
142
// load module info frommodule jarfile
143
File f = new File (topDir,moduleName.replace('/', File.separatorChar));
144
java.util.jar.JarFile jf;
146
jf= new java.util.jar.JarFile(f);
147
} catch (java.io.IOException ioe) {
148
throw new BuildException("I/O error during opening module jarfile", ioe, this.getLocation());
150
java.util.jar.Manifest mani;
152
mani = jf.getManifest();
153
} catch (java.io.IOException ioe) {
154
throw new BuildException("I/O error getting manifest from file '"+f.getAbsolutePath()+"'", ioe, this.getLocation());
156
if ( mani != null ) {
157
java.util.jar.Attributes attr = mani.getMainAttributes();
158
String cname = attr.getValue("OpenIDE-Module");
159
String sver = attr.getValue("OpenIDE-Module-Specification-Version");
160
if ((cname != null) && (!(cname.equals(""))) && (sver != null) && (!(sver.equals("")))) {
161
modInfo = cname + '/' + sver;
162
log("Gathered module information from module jarfile. Codename = '"+cname+"' and specification version = '"+sver+"'",Project.MSG_VERBOSE);
164
throw new BuildException("Module in file '"+f.getAbsolutePath()+"' does not have either OpenIDE-Module attribute or OpenIDE-Module-Specification-Version attributes or missing both.", this.getLocation());
169
// Print a warning and stop if the topDir doesn't exist. //
170
if( printMissingDirWarning()) {
174
locs = getLocales() ;
175
if( locs == null || locs.trim().equals( "")) { //NOI18N
176
throw new BuildException( "Must specify 1 or more locales.") ;
178
if( fileName == null) {
179
throw new BuildException( "Must specify the file attribute.") ;
182
// I couldn't get it to work unless I explicitly added the task def here. //
183
getProject().addTaskDefinition("makelnbm", MakeLNBM.class); //NOI18N
185
// Get a list of the locales for which localized files exist. //
186
stok = new StringTokenizer( locs, ",") ; //NOI18N
187
while( stok.hasMoreTokens()) {
188
loc = stok.nextToken() ;
189
log("Checking if module has files in locale '"+loc+"'", Project.MSG_VERBOSE);
190
if( hasFilesInLocale( loc)) {
191
build_locales.add( loc) ;
192
log("Module has files in locale '"+loc+"'", Project.MSG_VERBOSE);
194
log("Module has no files in locale '"+loc+"'", Project.MSG_VERBOSE);
198
// For each locale that we need to build an NBM for. //
199
ListIterator<String> iterator = build_locales.listIterator() ;
200
while( iterator.hasNext()) {
202
// Build the NBM for this locale. //
203
buildNbm( iterator.next()) ;
207
/** Build the NBM for this locale. */
208
protected void buildNbm( String locale) throws BuildException {
210
LinkedList<String> list = new LinkedList<String>() ;
211
String includes = new String() ;
216
// Delete the Info directory if desired. //
218
del = (Delete) getProject().createTask("delete"); //NOI18N
220
del.setDir( new File( topDir.getAbsolutePath() + File.separator + "Info")) ; //NOI18N
222
del.setDir( new File( topDir.getAbsolutePath() + File.separator + "Info_" + //NOI18N
228
// Move the Info_<locale> dir to Info. //
229
switchInfo( true, locale) ;
232
makenbm = (MakeLNBM) getProject().createTask("makelnbm"); //NOI18N
235
makenbm.setModInfo( modInfo) ;
236
makenbm.setLangCode( locale) ;
237
String fname = getLocalizedFileName( locale);
238
makenbm.setFile( new File( getProject().getBaseDir().getAbsolutePath() +
239
File.separator + fname)) ;
240
makenbm.setTopdir( topDir) ;
241
makenbm.setIsStandardInclude( false) ;
242
String distbase = getProject().getProperty("dist.base"); //NOI18N
243
if (distbase != null) {
245
int idx = fname.lastIndexOf('/');
246
makenbm.setDistribution(distbase + "/" + fname.substring(idx + 1)); //NOI18N
247
// } catch (MalformedURLException e) {
248
// throw new BuildException(e, getLocation());
251
licenseFile = getLicenseFile( locale) ;
252
if( licenseFile != null) {
253
MakeLNBM.Blurb blurb = makenbm.createLicense() ;
254
blurb.setFile( licenseFile) ;
257
// Set the localizing bundle specified, or look for it. //
258
if( locBundle != null) {
259
setLocBundle( makenbm, getSpecificLocBundleFile( locBundle, locale)) ;
262
setLocBundle( makenbm, findLocBundle( makenbm, locale)) ;
265
// Set up the signing data if it's specified. //
266
if( getKeystore() != null &&
267
getStorepass() != null &&
268
getAlias() != null) {
269
MakeLNBM.Signature sign = makenbm.createSignature() ;
270
sign.setKeystore( new File( getKeystore())) ;
271
sign.setStorepass( getStorepass()) ;
272
sign.setAlias( getAlias()) ;
275
// Get the list of include patterns for this locale. //
276
addLocalePatterns( list, locale) ;
278
// Create a comma-separated list of include patterns. //
280
for (String s1: list) {
282
includes += "," ; //NOI18N
287
// Add any extra includes that were specified. //
288
if( nbmIncludes != null && !nbmIncludes.trim().equals( "")) { //NOI18N
290
includes += "," ; //NOI18N
292
includes += nbmIncludes ;
294
makenbm.setIncludes( includes) ;
298
// Move the Info dir to Info_<locale>. //
299
switchInfo( false, locale) ;
302
/** Return the license file associated with this locale if there is
305
protected File getLicenseFile( String locale) {
306
String license_prop_name = locale + ".license.file" ; //NOI18N
307
String license_prop = getProject().getProperty(license_prop_name);
308
File license = null ;
309
if( license_prop != null) {
310
license = new File( license_prop ) ;
315
protected void switchInfo( boolean to_info,
320
dir = new File( topDir.getAbsolutePath() + File.separator + "Info_" + locale) ; //NOI18N
321
dir.renameTo( new File( topDir.getAbsolutePath() + File.separator + "Info")) ; //NOI18N
324
dir = new File( topDir.getAbsolutePath() + File.separator + "Info") ; //NOI18N
325
dir.renameTo( new File( topDir.getAbsolutePath() + File.separator + "Info_" + //NOI18N
330
/** Get the localized version of the NBM filename. */
331
protected String getLocalizedFileName( String locale) {
332
return( baseFileName + "_" + locale + ".nbm") ; //NOI18N
335
protected String getLocales() {
336
if( locales != null) {
339
return( getGlobalProp( "locmakenbm.locales")) ; //NOI18N
342
/** See if there are any files for the given locale. */
343
protected boolean hasFilesInLocale( String loc) {
347
// Setup a fileset to find files in this locale. //
350
addLocalePatterns( fs, loc) ;
352
// See if there are any localized files for this locale. //
353
String[] inc_files = fs.getDirectoryScanner(getProject()).getIncludedFiles();
354
if( inc_files.length == 0) {
361
/** Add the patterns to include the localized files for the given locale. */
362
protected void addLocalePatterns( FileSet fs,
364
LinkedList<String> list = new LinkedList<String>() ;
366
// Get the list of patterns for this locale. //
367
addLocalePatterns( list, loc) ;
369
for (String s: list) {
370
// Add it to the includes list. //
371
fs.createInclude().setName(s) ;
376
protected void addLocalePatterns( LinkedList<String> list,
378
// String dir = new String() ;
379
String re = new String() ;
382
// dir = mainDir ; // modified for clusterization
383
// re = dir + "/**/*_" + loc + ".*" ; // pattern is: ${dir}/**/*_${locale}.* //NOI18N
384
// list.add( new String( re)) ;
385
// re = dir + "/**/" + loc + "/" ; // pattern is: ${dir}/${locale}/ //NOI18N
386
// list.add( new String( re)) ;
388
re = "**/*_" + loc + ".*" ; // pattern is: ${dir}/**/*_${locale}.* //NOI18N
390
re = "**/" + loc + "/" ; // pattern is: ${dir}/${locale}/ //NOI18N
393
addLocIncludes( list, loc) ;
395
// For ja locale, include these other variants. //
396
if( loc.equals( "ja")) { //NOI18N
397
addLocalePatterns( list, "ja_JP.PCK") ; //NOI18N
398
addLocalePatterns( list, "ja_JP.eucJP") ; //NOI18N
399
addLocalePatterns( list, "ja_JP.SJIS") ; //NOI18N
400
addLocalePatterns( list, "ja_JP.UTF-8") ; //NOI18N
401
addLocalePatterns( list, "ja_JP.UTF8") ; //NOI18N
405
protected void addLocIncludes( LinkedList<String> list,
407
StringTokenizer tkzr ;
408
String locInc, incLocale, incPattern ;
411
if( locIncludes == null) {
415
// For each locale-specific include. //
416
tkzr = new StringTokenizer( locIncludes, ",\n\t ") ; //NOI18N
417
while( tkzr.hasMoreTokens()) {
418
locInc = tkzr.nextToken() ;
419
idx = locInc.indexOf( ":") ; //NOI18N
421
incLocale = locInc.substring( 0, idx) ;
422
incPattern = locInc.substring( idx+1) ;
423
if( incLocale.equals( loc)) {
424
list.add( incPattern) ;
433
protected String getGlobalProp( String name) {
435
ret = getProject().getProperty(name);
437
// Don't return empty strings or strings whose value contains a //
438
// property that isn't set. //
440
if( ret.trim().equals( "")) { //NOI18N
443
else if( ret.indexOf( "${") != -1) { //NOI18N
450
protected String getKeystore() {
451
return( getGlobalProp( "locmakenbm.keystore")) ; //NOI18N
454
protected String getStorepass() {
455
return( getGlobalProp( "locmakenbm.storepass")) ; //NOI18N
458
protected String getAlias() {
459
return( getGlobalProp( "locmakenbm.alias")) ; //NOI18N
462
/** If the topDir doesn't exist, warn the user and return true. */
463
protected boolean printMissingDirWarning() {
464
boolean ret = false ;
465
if( !topDir.exists()) {
466
log( "WARNING: Skipping this task: Directory " + topDir.getPath() +
473
/** If the localizing bundle is there, use it. */
474
protected void setLocBundle( MakeLNBM makenbm,
476
if( bundle != null && bundle.exists()) {
477
makenbm.setLocBundle( bundle) ;
480
log( "WARNING: Localizing bundle not found: " +
481
((bundle==null)?(""):(bundle.getPath())) ) ; //NOI18N
485
protected String getSrcDir( File file) {
486
InputStreamReader isr ;
487
FileInputStream fis ;
488
char[] buf = new char[ 200] ;
494
// Read the srcdir from the file that locjar wrote. //
495
fis = new FileInputStream( file) ;
496
isr = new InputStreamReader( fis) ;
497
len = isr.read( buf) ;
499
if( buf[ len-1] == '\n') { //NOI18N
502
s = new String( buf, 0, len) ;
503
idx = s.indexOf( "=") ; //NOI18N
505
s = s.substring( idx + 1) ;
513
catch( Exception e) {
514
System.out.println( "ERROR: " + e.getMessage()) ;
515
e.printStackTrace() ;
516
throw new BuildException() ;
521
protected File findLocBundle( MakeLNBM makenbm,
523
File srcdirfile, locdir ;
525
String s, srcdir = null ;
527
// See if the file containing the srcdir is there. //
528
srcdirfile = new File( topDir.getAbsolutePath() + File.separator +
529
"srcdir.properties") ; //NOI18N
530
if( srcdirfile.exists()) {
531
srcdir = getSrcDir( srcdirfile) ;
533
// if( srcdir == null) {
534
// throw new BuildException( "ERROR: Could not get source dir from: " + srcdirfile.getPath()) ;
537
// Get the codename of this module. //
538
index = modInfo.indexOf( "/") ; //NOI18N
540
s = modInfo.substring( 0, index) ;
543
s = new String( modInfo) ;
546
// Convert to pathname and set the loc bundle. //
547
s = s.replace( '.', '/') ; //NOI18N
548
locdir = new File( getRelPath( srcdir + "/" + s, findLocBundle). //NOI18N
549
replace( '/', File.separatorChar)) ; //NOI18N
550
return( getDefaultLocBundleFile( locdir, locale)) ;
553
protected File getDefaultLocBundleFile( File dir,
555
return( new File( dir.getPath() + File.separator + "Bundle_" + locale + ".properties")) ; //NOI18N
558
protected File getSpecificLocBundleFile( File enBundle,
560
String path = enBundle.getPath() ;
561
int idx = path.lastIndexOf( '.') ; //NOI18N
563
return( new File( path.substring( 0, idx) + "_" + locale + path.substring( idx))) ; //NOI18N
566
return( new File( path + "_" + locale)) ; //NOI18N
570
/** This supports ".." path elements at the start of path2. */
571
protected String getRelPath( String path1,
575
if( path2.equals( ".")) { //NOI18N
579
// For each ".." element in path2. //
581
idx2 = path2.indexOf( "..") ; //NOI18N
586
// Strip off the ".." //
587
path2 = path2.substring( 2) ;
589
// Strip off the slash if it starts with slash. //
590
idx2 = path2.indexOf( "/") ; //NOI18N
592
path2 = path2.substring( 1) ;
595
// Strip off the last element of path1. //
596
idx1 = path1.lastIndexOf( "/") ; //NOI18N
598
path1 = path1.substring( 0, idx1) ;
602
return( path1 + "/" + path2) ; //NOI18N