0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.nbbuild;
0043:
0044: import java.io.BufferedReader;
0045: import java.io.File;
0046: import java.io.FileReader;
0047: import java.io.FileWriter;
0048: import java.io.IOException;
0049: import java.util.ArrayList;
0050: import java.util.Enumeration;
0051: import java.util.HashSet;
0052: import java.util.Hashtable;
0053: import java.util.Iterator;
0054: import java.util.LinkedList;
0055: import java.util.StringTokenizer;
0056: import java.util.Vector;
0057: import org.apache.tools.ant.BuildException;
0058: import org.apache.tools.ant.DirectoryScanner;
0059: import org.apache.tools.ant.Project;
0060: import org.apache.tools.ant.taskdefs.Ant;
0061: import org.apache.tools.ant.taskdefs.Delete;
0062: import org.apache.tools.ant.taskdefs.GZip;
0063: import org.apache.tools.ant.taskdefs.MatchingTask;
0064: import org.apache.tools.ant.taskdefs.Tar;
0065: import org.apache.tools.ant.types.FileSet;
0066:
0067: /**
0068: * This task was created to create L10N kits.
0069: * The xml to call this task might look like:
0070: * <l10nTask topdirs="${f4jroot} ${nbroot}" modules="${all_modules}"
0071: * localizableFile="${localizableF}" generatedFile="${genFile}"
0072: * changedFile="${changedFile}" buildDir="${l10n-build}"
0073: * distDir="${l10n-dist}" buildNumber="${buildnumber}"
0074: * globalFile=""/>
0075: *
0076: *
0077: * Each resulting kit will be a tar file containing one directory
0078: * for each repository examined.
0079: * Each repository_directory will contain one tar-file
0080: * for each module with changed localizable files.
0081: * The structure of the tar file is as follows:
0082: * repository_dir/
0083: * module_tar/
0084: * generatedFile
0085: * contentFile
0086: * localizableFile1.html
0087: * localizableFile2.gif...
0088: *
0089: * 1. All localizable files (as defined in "localizableFile")
0090: * "localizableFile" is a list of file patterns difining all localizable source files.
0091: * "localizableFile" itself is not included in the kit.
0092: * 2. A content file (as named in "contentFile")
0093: * This is a list of the names of all localizable files which need to be (re)localized.
0094: * 3. A generated file (as named in "generatedFile")
0095: * This is a list of the names of all localizable files with the most recent
0096: * CVS revision number.
0097: *
0098: * The generated file need not be committed to cvs until the files come back
0099: * localized. (This is a change from the procedure followed in late 2001).
0100: *
0101: * As of version 1.1.2, converted Gzip methods to use ant 1.4.1, and added ability to
0102: * 1) embed exclude patterns in the l10n.list file
0103: * (must use keyword "exclude " followed by the pattern.)
0104: * 2) add ability to embed reading of additional files
0105: * (must use the keyword "read " followed by the path to the file)
0106: * The special case "read global" will read the file set by the property globalFile
0107: * 3) add the ability to embed properties in the patterns. i
0108: * The special case "l10n-module" property will be set from within L10nTask
0109: *
0110: * @author Erica Grevemeyer
0111: * @version 1.1, Feb 4 11:21:09 PST 2002
0112: * @version 1.1.2 Aug 29 15:23:51 PDT 2002
0113: */
0114: public class L10nTask extends MatchingTask {
0115: private Hashtable<String, HashSet<String>> modules = new Hashtable<String, HashSet<String>>();
0116: private String[] allmodules;
0117: private String[] topdirs;
0118: private String localizableFile, generatedFile, changedFile,
0119: globalFile;
0120: private String allFile = "l10n.list.all";
0121: private String excludePattern = "";
0122: private String includePattern = "";
0123: // Sets the set of exclude patterns.
0124: // Patterns may be separated by a comma or a space.
0125: // The first instance which necessitated this addition was
0126: // "**/ja/**"
0127: private String buildDir;
0128: private String distDir;
0129: private Vector error = new Vector();
0130: private Hashtable<String, String> changed = new Hashtable<String, String>();
0131: private Hashtable<String, String> generatedFileHash = new Hashtable<String, String>();
0132: private Hashtable<String, String> fullPropHash = null;
0133: private HashSet<String> localizableHash = new HashSet<String>();
0134: private Project p;
0135: static boolean DEBUG = false;
0136: boolean cont = false;
0137: private String buildNumber;
0138: String[] localizableFiles;
0139:
0140: public void execute() throws BuildException {
0141: // 1. Check that settable variables have been set.
0142: // If they have not been, abandon ship!
0143:
0144: if (modules == null) {
0145: throw new BuildException(
0146: "Required variable not set. Set 'modules' in the calling .xml file");
0147: }
0148: if (topdirs == null) {
0149: throw new BuildException(
0150: "Required variable not set. Set 'topdirs' in the calling .xml file");
0151: }
0152: if (distDir == null) {
0153: throw new BuildException(
0154: "Required variable not set. Set 'distDir' in the calling .xml file");
0155: }
0156:
0157: if (buildDir == null) {
0158: throw new BuildException(
0159: "Required variable not set. Set 'buildDir' in the calling .xml file");
0160: }
0161: if (localizableFile == null) {
0162: throw new BuildException(
0163: "Required variable not set. Set 'localizableFile' in the calling .xml file");
0164: }
0165: if (globalFile == null) {
0166: throw new BuildException(
0167: "Required variable not set. Set 'globaFile' in the calling .xml file");
0168: }
0169: if (generatedFile == null) {
0170: throw new BuildException(
0171: "Required variable not set. Set 'generatedFile' in the calling .xml file");
0172: }
0173: if (changedFile == null) {
0174: throw new BuildException(
0175: "Required variable not set. Set 'changedFile' in the calling .xml file");
0176: }
0177: if (buildNumber == null) {
0178: throw new BuildException(
0179: "Required variable not set. Set 'buildNumber' in the calling .xml file");
0180: }
0181:
0182: //if the dir doesn't exist, make it.
0183: // if the dir still doesn't exist, fail.
0184: File dd = new File(distDir);
0185: if (!dd.exists()) {
0186: dd.mkdirs();
0187: }
0188:
0189: ArrayList<String> sb = new ArrayList<String>();
0190: for (int i = 0; i < topdirs.length; i++) {
0191: sb.add(topdirs[i]);
0192: }
0193: log("topdirs: " + sb.toString(), Project.MSG_INFO);
0194: sb = new ArrayList<String>();
0195: for (int i = 0; i < allmodules.length; i++) {
0196: sb.add(allmodules[i]);
0197: }
0198: log("modules: " + sb.toString(), Project.MSG_INFO);
0199: log("distDir: " + distDir, Project.MSG_INFO);
0200: log("buildDir: " + buildDir, Project.MSG_INFO);
0201: log("localizableFile: " + localizableFile, Project.MSG_INFO);
0202: log("generatedFile: " + generatedFile, Project.MSG_INFO);
0203: log("changedFile: " + changedFile, Project.MSG_INFO);
0204: log("globalFile: " + globalFile, Project.MSG_INFO);
0205: log("buildNumber: " + buildNumber, Project.MSG_INFO);
0206:
0207: p = this .getProject();
0208:
0209: for (int i = 0; i < topdirs.length; i++) {
0210: log("STARTING TOPDIR " + topdirs[i], Project.MSG_VERBOSE);
0211: Iterator<String> keyIt = modules.keySet().iterator();
0212: while (keyIt.hasNext()) {
0213: String topModule = keyIt.next();
0214: Delete df = (Delete) this .getProject().createTask(
0215: "delete");
0216: df.setDir(new File(topdirs[i] + File.separator
0217: + topModule));
0218: df.setIncludes(topModule + "." + localizableFile + ", "
0219: + topModule + "." + generatedFile + ", "
0220: + topModule + "." + changedFile + ", "
0221: + topModule + "." + allFile + "*");
0222: df.execute();
0223:
0224: @SuppressWarnings("unchecked")
0225: Hashtable<String, String> props = p.getProperties();
0226: fullPropHash = props;
0227:
0228: generatedFileHash.clear();
0229: changed.clear();
0230: localizableHash.clear();
0231: //localizableFiles.
0232: log("IN TOPLEVEL MODULE " + topModule,
0233: Project.MSG_VERBOSE);
0234: @SuppressWarnings("unchecked")
0235: Iterator<String> modIt = modules.get(topModule)
0236: .iterator();
0237: while (modIt.hasNext()) {
0238: String subModule = modIt.next();
0239: log("STARTING SUBMODULE " + subModule,
0240: Project.MSG_VERBOSE);
0241:
0242: File f = new File(topdirs[i]
0243: + File.separator
0244: + subModule
0245: .replace('/', File.separatorChar)
0246: + File.separator + localizableFile);
0247: log("Localizable file is: " + f.getAbsolutePath(),
0248: Project.MSG_VERBOSE);
0249: /*
0250: if ( ! (f.exists()) ) {
0251: log("FILE does not exists "+topdirs[i]+File.separator+subModule.replace('/', File.separatorChar)+File.separator+localizableFile);
0252: }
0253: */
0254: File topDir = new File(topdirs[i]);
0255: File modDir = new File(topdirs[i]
0256: + File.separator
0257: + subModule
0258: .replace('/', File.separatorChar));
0259:
0260: // moved getGeneratedFiles from here to only getGeneratedFiles
0261: // if there are localizableFiles.
0262:
0263: localizableFiles = getLocalizableFiles(topDir,
0264: subModule);
0265: if (localizableFiles == null) {
0266: log("No Localizable Files for this module. "
0267: + topDir
0268: + File.separator
0269: + subModule.replace('/',
0270: File.separatorChar),
0271: Project.MSG_VERBOSE);
0272: } else {
0273: for (int k = 0; k < localizableFiles.length; k++) {
0274: localizableHash.add(localizableFiles[k]);
0275: }
0276: //don't look for the generated Files if there are no localizableFiles
0277: Hashtable<String, String> gfh = new Hashtable<String, String>();
0278: //generatedFileHash
0279: gfh = getGeneratedFiles(topDir, subModule);
0280: if (gfh == null) {
0281: log("GENFILEHASH is null (" + topDir + ", "
0282: + subModule + ")",
0283: Project.MSG_DEBUG);
0284: } else {
0285: generatedFileHash.putAll(gfh);
0286: }
0287: } // if localizableFiles is not null
0288: } // while submodules
0289: /* XXX obsolete:
0290: Iterator<String> it = localizableHash.iterator();
0291: while (it.hasNext()) {
0292: String oneLocalizableFile =it.next();
0293:
0294: // DO SOME PRE-PROCESSING HERE. CACHE DIR REACTION (don't check for existance of same dir over & over again).
0295:
0296:
0297: int lastSlashIndex = oneLocalizableFile.lastIndexOf(File.separator);
0298: String parentDirFullPath = oneLocalizableFile.substring(0, lastSlashIndex);
0299:
0300: // Check that the CVS/ dir exists.
0301: // If it does not, assume we are dealing with a generated dir
0302: // which does not need to be examined by me.
0303: if ( ! new File(parentDirFullPath+"/CVS").exists() ) {
0304: log("CVSDIR doesn't exist ["+parentDirFullPath+"/CVS ]", Project.MSG_DEBUG);
0305: // skip to the end of this loop
0306: //HEY! there must be a cleaner way!!
0307: log("This dir is a generated dir with no CVS dir "+parentDirFullPath, Project.MSG_INFO);
0308:
0309: } else {
0310:
0311: ce = cvsEntriesCache.get(parentDirFullPath);
0312:
0313: if ( ce == null ) {
0314: ce = new CvsEntries(parentDirFullPath); //passing parentDirFullPath
0315: cvsEntriesCache.put(parentDirFullPath, ce);
0316: }
0317:
0318: if ( generatedFileHash == null ) {
0319: generatedFileHash=new Hashtable<String, String>();
0320: }
0321:
0322:
0323: String localizableFileOnly = oneLocalizableFile.substring(oneLocalizableFile.lastIndexOf(File.separator)+1);
0324: if (localizableFileOnly == null) { log("NULL LOCALIZABLE FILE"); }
0325:
0326: String ceRev = ce.getRevnoByFileName(localizableFileOnly);
0327:
0328: if ( ceRev == null ) {
0329: // If this file is NOT in ce (doesn't exist in CVS/Entries)
0330: // there is something wrong with the build working directory.
0331: // We will collect these file names & report at the end.
0332:
0333: //Maybe we don't want to add them. THe build generates lots of files which aren't in CVS.
0334: // error.add(localizableFiles[k]);
0335:
0336: } else {
0337: log("CEREV: "+ceRev, Project.MSG_DEBUG);
0338: // compare revnos
0339:
0340: String genRev = generatedFileHash.get(oneLocalizableFile);
0341: log("GENREV "+genRev + "\tFN: "+oneLocalizableFile, Project.MSG_DEBUG);
0342:
0343: if ( genRev == null || ! ceRev.equals(genRev)) {
0344: //Update changed fileHash
0345: changed.put(oneLocalizableFile, ceRev);
0346:
0347: //Update generatedFileHash
0348: generatedFileHash.put(oneLocalizableFile, ceRev);
0349:
0350: log("I got this far, but there was nothing CHANGED: "+oneLocalizableFile, Project.MSG_DEBUG);
0351: }
0352: }
0353: }
0354:
0355: } //for localizable files
0356: */
0357:
0358: // PRINT TO "allfiles" list.
0359: boolean success = false;
0360: success = printToAllFile(topdirs[i], topModule,
0361: localizableHash.toArray(localizableFiles));
0362: if (!success) {
0363: log("ERROR: Print to All File in " + topdirs[i]
0364: + ", " + topModule + " failed.",
0365: Project.MSG_ERR);
0366: }
0367:
0368: //make tar here
0369: // FILTER ALL FILE, KEEP ONLY UNIQUE LINES
0370: success = filterAllFile(topdirs[i], topModule);
0371: if (!success) {
0372: log(
0373: "ERROR: Cannot filter ${module}.l10n.list.all file for "
0374: + topdirs[i] + ", " + topModule,
0375: Project.MSG_ERR);
0376: }
0377:
0378: // IN HERE PRINT TO GENERATED FILE.
0379: success = printToFile(topdirs[i], topModule);
0380:
0381: if (!success) {
0382: log("ERROR: Print to File in " + topdirs[i] + ", "
0383: + topModule + " failed.", Project.MSG_ERR);
0384: }
0385:
0386: // toDir should be build/topDir
0387: // baseDir should be fullpathtoTopDir
0388: log("BUILDDIR " + buildDir, Project.MSG_VERBOSE);
0389: File tDir = new File(buildDir + File.separator
0390: + topdirs[i]);
0391: int lio = topdirs[i].lastIndexOf(File.separator);
0392: String shortTopdir = topdirs[i].substring(lio + 1);
0393:
0394: // make a tar no matter what.
0395: // At a minimum it will have
0396: // file module.l10n.list.all.
0397: // THEN delete files.
0398:
0399: mkTars(topdirs[i] + File.separator, buildDir
0400: + File.separator + shortTopdir + File.separator
0401: + topModule + ".tar", topdirs[i]
0402: + File.separator + topModule + File.separator
0403: + topModule + "." + allFile, topModule);
0404: Delete delete = (Delete) p.createTask("delete");
0405: FileSet fs = new FileSet();
0406: fs.setDir(new File(topdirs[i] + File.separator
0407: + topModule));
0408: String includes = topModule + "." + generatedFile + ","
0409: + topModule + "." + changedFile + ","
0410: + topModule + "." + allFile;
0411: fs.setIncludes(includes);
0412: delete.addFileset(fs);
0413:
0414: delete.setVerbose(true);
0415: delete.execute();
0416:
0417: // Clean up before moving on.
0418:
0419: log("CLEARING " + topdirs[i] + " " + topModule,
0420: Project.MSG_VERBOSE);
0421: generatedFileHash.clear();
0422: changed.clear();
0423: error.clear();
0424:
0425: } // while modules
0426: } //for topdirs
0427:
0428: // Tar everything
0429: log("ABOUT TO MAKE THE BIG TAR: " + distDir + "/l10n-"
0430: + buildNumber + ".tar.gz", Project.MSG_INFO);
0431:
0432: // Check to make sure that the build dir exists,
0433: // & that there are little tars to tar... or we get a "basedir dne"
0434: // exception.
0435:
0436: File bd = new File(buildDir);
0437: if (bd.exists()) {
0438: File tarFile = new File(buildDir + "/l10n-" + buildNumber
0439: + ".tar");
0440:
0441: Tar tar = (Tar) p.createTask("tar");
0442: tar.setBasedir(bd);
0443: tar.setDestFile(tarFile);
0444: Tar.TarLongFileMode mode = new Tar.TarLongFileMode();
0445: mode.setValue(Tar.TarLongFileMode.GNU);
0446: tar.setLongfile(mode);
0447: ////// automatically includes all in the basedir
0448: tar.execute();
0449:
0450: if (tarFile.exists()) {
0451: GZip gzip = (GZip) p.createTask("gzip");
0452: gzip.setSrc(new File(buildDir + "/l10n-" + buildNumber
0453: + ".tar"));
0454: gzip.setZipfile(new File(distDir + "/l10n-"
0455: + buildNumber + ".tar.gz"));
0456: gzip.execute();
0457: } else {
0458: log("NO tar file, can't gzip" + buildDir + "/l10n-"
0459: + buildNumber + ".tar", Project.MSG_WARN);
0460: }
0461: } else {
0462: log("No files in builddir. No kit to build",
0463: Project.MSG_WARN);
0464: }
0465:
0466: } // execute()
0467:
0468: public void mkTars(String srcDir, String fullTarfilePath,
0469: String fullIncludesFilePath, String module) {
0470: //String td = srcDir.substring(srcDir.lastIndexOf(File.separator)+1);
0471: log("SRCDIR = " + srcDir, Project.MSG_VERBOSE);
0472: log("FULL TARFILE PATH = " + fullTarfilePath,
0473: Project.MSG_VERBOSE);
0474:
0475: File incBaseDir = new File(srcDir);
0476: Tar tar = (Tar) p.createTask("tar");
0477: tar.setBasedir(new File(srcDir));
0478: File tarFile = new File(fullTarfilePath);
0479: tar.setDestFile(tarFile);
0480: File destDir = tarFile.getParentFile();
0481: if ((!destDir.exists()) && (!destDir.isDirectory())) {
0482: destDir.mkdirs();
0483: }
0484:
0485: File incFile = new File(fullIncludesFilePath);
0486:
0487: if (incFile.exists()) {
0488: tar.setIncludes(module + File.separator + module + "."
0489: + allFile);
0490: tar.setIncludes(module + File.separator + module + "."
0491: + generatedFile);
0492: tar.setIncludes(module + File.separator + module + "."
0493: + changedFile);
0494: tar.setIncludesfile(incFile);
0495: Tar.TarLongFileMode mode = new Tar.TarLongFileMode();
0496: mode.setValue(Tar.TarLongFileMode.GNU);
0497: tar.setLongfile(mode);
0498: tar.execute();
0499: } else {
0500: log("Cannot make tarfile " + fullTarfilePath
0501: + ", because include list file "
0502: + fullIncludesFilePath + " does not exist",
0503: Project.MSG_WARN);
0504: }
0505:
0506: }
0507:
0508: /** Filter content of ALL FILE to contain only unique lines
0509: * @param fullTopDir
0510: * @param module
0511: * @return true if file I/O operations were successfull, false otherwise
0512: */
0513: private boolean filterAllFile(String fullTopDir, String module) {
0514: String topModule = null;
0515: int firstSlashIndex = module.indexOf('/');
0516: if (firstSlashIndex < 0) {
0517: topModule = module;
0518: } else {
0519: topModule = module.substring(0, firstSlashIndex);
0520: }
0521: String allFilename = fullTopDir + File.separator + topModule
0522: + File.separator + topModule + "." + allFile;
0523: try {
0524: BufferedReader br = new BufferedReader(new FileReader(
0525: allFilename + ".tmp"));
0526: String line = null;
0527: HashSet<String> hs = new HashSet<String>();
0528: while ((line = br.readLine()) != null) {
0529: hs.add(line);
0530: }
0531: br.close();
0532: LinkedList<String> ll = new LinkedList<String>();
0533: ll.addAll(hs);
0534: java.util.Collections.sort(ll);
0535: FileWriter allWrite = new FileWriter(allFilename, false);
0536: Iterator<String> it = ll.listIterator();
0537: while (it.hasNext()) {
0538: allWrite.write(it.next() + "\n");
0539: }
0540: allWrite.close();
0541: Delete df = (Delete) this .getProject().createTask("delete");
0542: df
0543: .setDir(new File(fullTopDir + File.separator
0544: + topModule));
0545: df.setIncludes(topModule + "." + allFile + ".tmp");
0546: df.execute();
0547: } catch (IOException ioe) {
0548: // consider throwing BuildException instead
0549: log("IN filterAllFile() - TOPDIR: " + fullTopDir
0550: + " MODULE: " + module + " IOException " + ioe,
0551: Project.MSG_ERR);
0552: return false;
0553:
0554: }
0555: return true;
0556: }
0557:
0558: /**
0559: * Prints list of all localizable files found in respective module
0560: * @param fullTopDir - filesystem path to root of you working repository
0561: * @param module - directory path name for which this call is being done
0562: * @param localizables - list of localizable files
0563: * @return true if file i/o operations were successful
0564: */
0565: public boolean printToAllFile(String fullTopDir, String module,
0566: String[] localizables) {
0567: try {
0568: int lastSlashIndex = fullTopDir.lastIndexOf('/');
0569: String topDir = fullTopDir.substring(lastSlashIndex + 1);
0570: String topModule = null;
0571: int firstSlashIndex = module.indexOf('/');
0572: if (firstSlashIndex < 0) {
0573: topModule = module;
0574: } else {
0575: topModule = module.substring(0, firstSlashIndex);
0576: }
0577: File f = new File(buildDir + File.separator + topDir);
0578: f.mkdirs();
0579: String allFilename = fullTopDir + File.separator
0580: + topModule + File.separator + topModule + "."
0581: + allFile + ".tmp";
0582: log("Writing to All File: " + allFilename,
0583: Project.MSG_DEBUG);
0584:
0585: if (localizables != null) {
0586: FileWriter allWrite = new FileWriter(allFilename, true);
0587: for (int i = 0; i < localizables.length; i++) {
0588: if (localizables[i] == null) {
0589: // found null, thus the rest of array is also null
0590: // assumption based on HashSet.toArray(String[] s) javadoc
0591: break;
0592: }
0593: int lio = localizables[i].lastIndexOf(fullTopDir);
0594: if (lio >= 0) {
0595: String moduleFileName = localizables[i]
0596: .substring(
0597: lio + fullTopDir.length() + 1)
0598: .replace(File.separatorChar, '/');
0599: allWrite.write(moduleFileName + "\n");
0600: } else {
0601: log("Error: NO TOPDIR HERE: " + localizables[i]
0602: + " FTD: " + fullTopDir + " LIO: "
0603: + lio, Project.MSG_ERR);
0604: }
0605:
0606: }
0607: allWrite.close();
0608: }
0609:
0610: } catch (IOException ioe) {
0611: // consider throwing BuildException instead
0612: log("IN printToAllFile() - TOPDIR: " + fullTopDir
0613: + " MODULE: " + module + " IOException " + ioe,
0614: Project.MSG_ERR);
0615: return false;
0616: }
0617: return true;
0618: }
0619:
0620: public boolean printToFile(String fullTopDir, String module) {
0621: String topModule = null;
0622: int firstSlashIndex = module.indexOf('/');
0623: if (firstSlashIndex < 0) {
0624: topModule = module;
0625: } else {
0626: topModule = module.substring(0, firstSlashIndex);
0627: }
0628:
0629: log("IN printToFile FULLTOPDIR " + fullTopDir + ", MODULE "
0630: + module + ", TOPMODULE " + topModule,
0631: Project.MSG_DEBUG);
0632:
0633: try {
0634:
0635: int lastSlashIndex = fullTopDir.lastIndexOf('/');
0636: String topDir = fullTopDir.substring(lastSlashIndex + 1);
0637:
0638: /* No need to mkdirs now - printToAllFile is making them.
0639: File f = new File(buildDir+ File.separator +topDir );
0640: f.mkdirs();
0641: */
0642:
0643: String genFilename = fullTopDir + File.separator
0644: + topModule + File.separator + topModule + "."
0645: + generatedFile;
0646: FileWriter genWrite = new FileWriter(genFilename, true);
0647: log("Writing Generated File: " + genFilename,
0648: Project.MSG_VERBOSE);
0649: String changedFilename = fullTopDir + File.separator
0650: + topModule + File.separator + topModule + "."
0651: + changedFile;
0652: FileWriter changedWrite = new FileWriter(changedFilename,
0653: true);
0654: log("Writing Changed File: " + changedFilename,
0655: Project.MSG_VERBOSE);
0656:
0657: if (generatedFileHash == null) {
0658: generatedFileHash = new Hashtable<String, String>();
0659: } else {
0660: // sort the generatedFiles list
0661: LinkedList<String> ll = new LinkedList<String>();
0662: ll.addAll(generatedFileHash.keySet());
0663: java.util.Collections.sort(ll);
0664: Iterator<String> it = ll.listIterator();
0665: while (it.hasNext()) {
0666: String genFileKey = it.next();
0667: int lioTopDir = genFileKey.lastIndexOf(topDir);
0668: String moduleFileName = genFileKey.substring(
0669: lioTopDir + topDir.length() + 1).replace(
0670: File.separatorChar, '/');
0671:
0672: genWrite.write(moduleFileName + "\t"
0673: + generatedFileHash.get(genFileKey) + "\n");
0674: }
0675:
0676: // sort the changedFiles list
0677: ll = new LinkedList<String>();
0678: ll.addAll(changed.keySet());
0679: java.util.Collections.sort(ll);
0680: it = null;
0681: it = ll.listIterator();
0682: while (it.hasNext()) {
0683: String changedFileKey = it.next();
0684:
0685: int lio = changedFileKey.lastIndexOf(topDir
0686: + File.separator + topModule);
0687: String moduleFileName;
0688: if (lio >= 0) {
0689:
0690: moduleFileName = changedFileKey.substring(
0691: changedFileKey.lastIndexOf(topDir
0692: + File.separator + topModule)
0693: + topDir.length() + 1).replace(
0694: File.separatorChar, '/');
0695: changedWrite.write(moduleFileName + "\n");
0696: } else {
0697: // If we get here, the cache is probably not really being cleared.
0698:
0699: //The cache is not being cleared
0700: // OR we have wild-card characters
0701: // consider throwing BuildException instead
0702: log(
0703: "WARNING: L10n.list file error. Each item in your list should"
0704: + " reference the current module. If this is a global l10n file"
0705: + " used over several modules use the property ${l10n-module}"
0706: + " as a place-holder. This error occurred in "
0707: + module + ".",
0708: Project.MSG_WARN);
0709: log("Contact program administrator.\r\t"
0710: + changedFileKey + "\r\tTD " + topDir
0711: + File.separator + module + " LIO "
0712: + lio, Project.MSG_VERBOSE);
0713: }
0714:
0715: //changedWrite.write(changedFileKey+"\n");
0716: //Changed should have a list of fullpath in order to do copy
0717: }
0718: }
0719:
0720: if (!error.isEmpty()) {
0721: String errorFileName = buildDir + File.separator
0722: + "l10n-errors.txt";
0723: FileWriter errorWrite = new FileWriter(errorFileName,
0724: true);
0725: log("Writing following errors to a log file "
0726: + errorFileName, Project.MSG_ERR);
0727: for (Enumeration e = error.elements(); e
0728: .hasMoreElements();) {
0729: String ee = (String) e.nextElement();
0730: errorWrite.write(ee + "\n");
0731: log("Error: " + ee, Project.MSG_ERR);
0732: }
0733: log("Finished writing errors to a log file "
0734: + errorFileName, Project.MSG_ERR);
0735: errorWrite.close();
0736: }
0737:
0738: genWrite.close();
0739: changedWrite.close();
0740:
0741: } catch (IOException ioe) {
0742: log("IOException printToFile()" + ioe, Project.MSG_ERR);
0743: return false;
0744: }
0745: return true;
0746: }
0747:
0748: /** You can use this function independently of "execute()", but
0749: * you have to set these attributes: localizableFile,
0750: * globalFile (if "read global" is used in any l10n.list
0751: * files), excludePattern (if desired), includePattern (if
0752: * desired)
0753: * @param topRoot
0754: * @param module
0755: * @return String[]
0756: */
0757: public String[] getLocalizableFiles(File topRoot, String module) {
0758: String[] lfs = null;
0759: StringBuffer[] sbholder = new StringBuffer[2];
0760: StringBuffer sbi = new StringBuffer();
0761: StringBuffer sbe = new StringBuffer();
0762: String includeS = "";
0763: String excludeS = "";
0764: log("IN getLocalizableFiles(File " + topRoot.getName() + ", "
0765: + module.replace('/', File.separatorChar) + ")",
0766: Project.MSG_DEBUG);
0767:
0768: if (fullPropHash == null) {
0769: p = getProject();
0770: @SuppressWarnings("unchecked")
0771: Hashtable<String, String> props = p.getProperties();
0772: fullPropHash = props;
0773: }
0774: fullPropHash.put("l10n-module", module);
0775:
0776: /** Look for local L10N list (localizableFile), if not found, look
0777: * for global include file, first in path relative to project basedir
0778: * and then without specifying a path
0779: */
0780: boolean incres = false; // includes file resolved
0781: File includes = new File(topRoot.getAbsolutePath()
0782: + File.separator
0783: + module.replace('/', File.separatorChar)
0784: + File.separator + localizableFile);
0785: if (!includes.exists() || includes.length() <= 0) {
0786: log("FILE IS too short to mess with " + module,
0787: Project.MSG_DEBUG);
0788: if (globalFile == null) {
0789: return lfs;
0790: }
0791: includes = new File(this .getProject().getBaseDir(),
0792: globalFile.replace('/', File.separatorChar));
0793: if (!includes.exists() || includes.length() <= 0) {
0794: log("Global file " + includes.getAbsolutePath()
0795: + "does not exist", Project.MSG_DEBUG);
0796: includes = new File(globalFile.replace('/',
0797: File.separatorChar));
0798: if (!includes.exists() || includes.length() <= 0) {
0799: log("Global file " + includes.getAbsolutePath()
0800: + "does not exist", Project.MSG_DEBUG);
0801: } else {
0802: incres = true;
0803: }
0804: } else {
0805: incres = true;
0806: }
0807: } else {
0808: incres = true;
0809: }
0810: if (!incres) {
0811: return lfs;
0812: }
0813:
0814: try {
0815: sbholder = processListFile(topRoot, includes, module);
0816: } catch (java.io.IOException ioe) {
0817: log("Error processing file. " + ioe, Project.MSG_WARN);
0818: }
0819:
0820: if (sbholder != null) {
0821: sbi = sbholder[0];
0822: sbe = sbholder[1];
0823:
0824: sbe.append(" " + excludePattern);
0825: sbi.append(" " + includePattern);
0826:
0827: log("INC " + sbi.toString(), Project.MSG_DEBUG);
0828: log("EXC " + sbe.toString(), Project.MSG_DEBUG);
0829: }
0830:
0831: this .fileset = new FileSet();
0832:
0833: if (sbi != null) {
0834: this .setIncludes(sbi.toString());
0835: }
0836:
0837: if (sbe != null) {
0838: this .setExcludes(sbe.toString());
0839: }
0840:
0841: DirectoryScanner ds = this .getDirectoryScanner(topRoot);
0842:
0843: ds.scan();
0844: lfs = ds.getIncludedFiles();
0845:
0846: for (int k = 0; k < lfs.length; k++) {
0847: log("LFS " + topRoot + File.separator + lfs[k],
0848: Project.MSG_DEBUG);
0849: lfs[k] = topRoot + File.separator + lfs[k].trim();
0850: }
0851:
0852: log("THERE ARE " + lfs.length + " FILES in INCL FILES",
0853: Project.MSG_DEBUG);
0854: return lfs;
0855: }
0856:
0857: public Hashtable<String, String> getGeneratedFiles(File topDir,
0858: String mod) {
0859: // NOTE: This method will return 'null' 100% of the time if there
0860: // are no l10n.list.generated files.
0861: // At this writing, this functionality is not used.
0862: // EG 1/03
0863:
0864: Hashtable<String, String> h = new Hashtable<String, String>();
0865: // Read generated File
0866: try {
0867:
0868: String topDirFullPath = topDir.getAbsolutePath();
0869: log("topDirFullPath: " + topDirFullPath, Project.MSG_DEBUG);
0870:
0871: BufferedReader inBuff = new BufferedReader(new FileReader(
0872: new File(topDir + File.separator
0873: + mod.replace('/', File.separatorChar),
0874: generatedFile)));
0875: boolean eof = false;
0876: while (!eof) {
0877: String line = inBuff.readLine();
0878: if (line == null) {
0879: eof = true;
0880: } else {
0881: log("LL " + line, Project.MSG_DEBUG);
0882:
0883: int tabIndex = line.indexOf("\t");
0884: if (tabIndex > 0) {
0885: String filename = line.substring(0, tabIndex);
0886: String revision = line.substring(tabIndex + 1);
0887: h.put(topDirFullPath + File.separator
0888: + filename, revision);
0889: } else {
0890: log("There's no tab in this line" + "[" + line
0891: + "]", Project.MSG_INFO);
0892: }
0893:
0894: }
0895:
0896: } //while
0897: } catch (java.io.FileNotFoundException e) {
0898: // Warning: Generated File: "+generatedFile+" in "+
0899: // topDir+File.separator+mod+" not found.
0900: // Adding all files to changed list."
0901: return (null);
0902: } catch (java.io.IOException e) {
0903: log("IN getGeneratedFiles('" + topDir + "','" + mod
0904: + "'); - IOException " + e.getMessage(),
0905: Project.MSG_WARN);
0906: }
0907:
0908: return h;
0909: }
0910:
0911: // Accessor Methods
0912:
0913: public void setTopdirs(String s) {
0914: StringTokenizer st = new StringTokenizer(s);
0915: String[] tops = new String[st.countTokens()];
0916: int i = 0;
0917: while (st.hasMoreTokens()) {
0918: tops[i++] = st.nextToken();
0919: }
0920:
0921: if (false) {
0922: for (int j = 0; j < tops.length; j++) {
0923: log("TOPS " + tops[j], Project.MSG_INFO);
0924: }
0925: }
0926:
0927: this .topdirs = tops;
0928:
0929: }
0930:
0931: public void setModules(String s) {
0932: StringTokenizer st = new StringTokenizer(s, ",");
0933: HashSet<String> modSet = null;
0934:
0935: modules = new Hashtable<String, HashSet<String>>();
0936: int modCnt = 0;
0937: while (st.hasMoreTokens()) {
0938: String fullMod = st.nextToken().trim();
0939: String topMod = null;
0940: log("ITEM IN MODLIST: " + fullMod, Project.MSG_DEBUG);
0941: int index = fullMod.indexOf('/');
0942: if (index >= 0) {
0943: topMod = fullMod.substring(0, index);
0944: } else {
0945: topMod = fullMod;
0946: }
0947: log("Top module is " + topMod, Project.MSG_DEBUG);
0948: if (modules.containsKey(topMod)) {
0949: modSet = modules.get(topMod);
0950: modSet.add(fullMod);
0951: } else {
0952: modSet = new HashSet<String>();
0953: modSet.add(fullMod);
0954: modules.put(topMod, modSet);
0955: }
0956: modCnt++;
0957: }
0958: allmodules = new String[modCnt];
0959: int i = 0;
0960: Iterator<String> keyit = modules.keySet().iterator();
0961: while (keyit.hasNext()) {
0962: String key = keyit.next();
0963: HashSet sm = modules.get(key);
0964: @SuppressWarnings("unchecked")
0965: Iterator<String> valit = sm.iterator();
0966: while (valit.hasNext()) {
0967: allmodules[i] = valit.next();
0968: i++;
0969: }
0970: }
0971: }
0972:
0973: private String resolveProperties(String line) {
0974: boolean skipit = false;
0975: while (line.indexOf("${") >= 0 && skipit == false) {
0976:
0977: String propertyName;
0978: String value = "";
0979: String res = "";
0980: String pre = "";
0981:
0982: propertyName = line.substring(line.indexOf("${") + 2, line
0983: .indexOf("}"));
0984:
0985: if (fullPropHash.containsKey(propertyName)) {
0986:
0987: value = fullPropHash.get(propertyName);
0988: res = line.substring(line.indexOf("}") + 1);
0989: pre = line.substring(0, line.indexOf("{") - 1);
0990: line = pre + value + res;
0991: log("LINE is now " + line, Project.MSG_VERBOSE);
0992: } else {
0993: log("Uninterpretable property in line: '" + line
0994: + "', property '" + propertyName
0995: + "'. Interpreting the entire line literally.",
0996: Project.MSG_WARN);
0997: skipit = true;
0998: }
0999: }
1000: return line;
1001: }
1002:
1003: public void executeLocalTarget(File topRoot, String module,
1004: String target) throws BuildException {
1005: log("Going to execute custom target '" + target
1006: + "' in directory '" + topRoot.getAbsolutePath()
1007: + File.separator
1008: + module.replace('/', File.separatorChar) + "'",
1009: Project.MSG_INFO);
1010:
1011: Ant ant = (Ant) this .getProject().createTask("ant");
1012: ant.setDir(new File(topRoot, module.replace('/',
1013: File.separatorChar)));
1014: ant.setTarget(target);
1015: ant.setTaskName("custom-call-" + module + "-" + target);
1016: ant.execute();
1017: log("Finished execution of custom target '" + target
1018: + "' in directory '" + topRoot.getAbsolutePath()
1019: + File.separator
1020: + module.replace('/', File.separatorChar) + "'",
1021: Project.MSG_INFO);
1022: }
1023:
1024: public StringBuffer[] processListFile(File topRoot, File inc,
1025: String module) throws IOException, BuildException {
1026: log("Reading " + module + "'s list file: " + inc.toString(),
1027: Project.MSG_INFO);
1028: StringBuffer[] sbholder = new StringBuffer[2];
1029: StringBuffer sbi = new StringBuffer();
1030: StringBuffer sbe = new StringBuffer();
1031:
1032: if (inc.exists() && inc.length() > 0) {
1033: //Read Includes File.
1034: BufferedReader br = new BufferedReader(new FileReader(inc));
1035: String line;
1036: while ((line = br.readLine()) != null) {
1037: boolean skipit = false;
1038: // For each line check if there are any properties which
1039: // should be interpreted first.
1040: line = resolveProperties(line);
1041: if (line.trim().indexOf("#") == 0) {
1042: log("Skipping commented-out line: '" + line + "'",
1043: Project.MSG_DEBUG);
1044: } else if (line.indexOf("exclude") >= 0) {
1045: sbe.append(" "
1046: + line.trim().substring(
1047: "exclude".length() + 1));
1048: log("Added exclude: '"
1049: + line.trim().substring(
1050: "exclude".length() + 1) + "'",
1051: Project.MSG_DEBUG);
1052: } else if (line.indexOf("antcall") >= 0) {
1053: String target = line.trim().substring(
1054: "antcall".length() + 1).trim();
1055: executeLocalTarget(topRoot, module, target);
1056: } else if (line.indexOf("read global") >= 0) {
1057: if (globalFile != null
1058: && !globalFile.equals("")
1059: && !(inc.getAbsolutePath()
1060: .equals((new File(globalFile))
1061: .getAbsolutePath()))) {
1062: log(
1063: "Loading and interpreting global includes/excludes file "
1064: + globalFile + " for module "
1065: + module, Project.MSG_INFO);
1066: StringBuffer[] globalarray = processListFile(
1067: topRoot, new File(globalFile), module);
1068: if (globalarray[0] != null) {
1069: sbi.append(" " + globalarray[0]);
1070: }
1071: if (globalarray[1] != null) {
1072: sbe.append(" " + globalarray[1]);
1073: }
1074: }
1075: } else if (line.trim().startsWith("read")) {
1076: String l = line.trim();
1077: l = l.substring(4);
1078: l = l.trim();
1079: StringBuffer[] sbarr = processListFile(topRoot,
1080: new File(l), module);
1081: if (sbarr[0] != null) {
1082: sbi.append(" " + sbarr[0]);
1083: }
1084: if (sbarr[1] != null) {
1085: sbe.append(" " + sbarr[1]);
1086: }
1087: } else {
1088: sbi.append(" " + line);
1089: }
1090: if (DEBUG) {
1091: log("GLOBAL " + line.indexOf("read global")
1092: + " EXCLUDES " + line.indexOf("exclude")
1093: + " FILE " + inc.toString(),
1094: Project.MSG_DEBUG);
1095: }
1096: }
1097: br.close();
1098: }
1099: sbholder[0] = sbi;
1100: sbholder[1] = sbe;
1101: return sbholder;
1102: }
1103:
1104: public void setDistDir(String s) {
1105: log("DIST DIR SHOULD BE: " + s, Project.MSG_DEBUG);
1106: this .distDir = s;
1107: }
1108:
1109: public void setBuildDir(String s) {
1110: this .buildDir = s;
1111: }
1112:
1113: public void setDebug(boolean s) {
1114: this .DEBUG = s;
1115: }
1116:
1117: public void setLocalizableFile(String s) {
1118: this .localizableFile = s;
1119: }
1120:
1121: public void setExcludePattern(String s) {
1122: this .excludePattern = s;
1123: }
1124:
1125: public void setIncludePattern(String s) {
1126: this .includePattern = s;
1127: }
1128:
1129: public void setBuildNumber(String s) {
1130: this .buildNumber = s;
1131: }
1132:
1133: public void setGeneratedFile(String s) {
1134: this .generatedFile = s;
1135: }
1136:
1137: public void setChangedFile(String s) {
1138: this .changedFile = s;
1139: }
1140:
1141: public void setGlobalFile(String s) {
1142: this.globalFile = s;
1143: }
1144: }
|