| /* |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
| * |
| * Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved. |
| * |
| * The contents of this file are subject to the terms of either the GNU |
| * General Public License Version 2 only ("GPL") or the Common |
| * Development and Distribution License("CDDL") (collectively, the |
| * "License"). You may not use this file except in compliance with the |
| * License. You can obtain a copy of the License at |
| * http://www.netbeans.org/cddl-gplv2.html |
| * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the |
| * specific language governing permissions and limitations under the |
| * License. When distributing the software, include this License Header |
| * Notice in each file and include the License file at |
| * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Sun in the GPL Version 2 section of the License file that |
| * accompanied this code. If applicable, add the following below the |
| * License Header, with the fields enclosed by brackets [] replaced by |
| * your own identifying information: |
| * "Portions Copyrighted [year] [name of copyright owner]" |
| * |
| * Contributor(s): |
| * |
| * The Original Software is NetBeans. The Initial Developer of the Original |
| * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun |
| * Microsystems, Inc. All Rights Reserved. |
| * |
| * If you wish your version of this file to be governed by only the CDDL |
| * or only the GPL Version 2, indicate your decision by adding |
| * "[Contributor] elects to include this software in this distribution |
| * under the [CDDL or GPL Version 2] license." If you do not indicate a |
| * single choice of license, a recipient has the option to distribute |
| * your version of this file under either the CDDL, the GPL Version 2 or |
| * to extend the choice of license to its licensees as provided above. |
| * However, if you add GPL Version 2 code and therefore, elected the GPL |
| * Version 2 license, then the option applies only if the new code is |
| * made subject to such option by the copyright holder. |
| */ |
| package org.netbeans.l10n; |
| |
| import java.io.BufferedOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.util.HashMap; |
| import java.util.Properties; |
| import java.util.StringTokenizer; |
| import java.util.Vector; |
| import java.util.jar.JarFile; |
| import java.util.zip.ZipEntry; |
| import org.netbeans.nbbuild.XMLUtil; |
| import org.netbeans.nbbuild.AutoUpdate; |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.DirectoryScanner; |
| import org.apache.tools.ant.Project; |
| import org.apache.tools.ant.Task; |
| import org.apache.tools.ant.taskdefs.Copy; |
| import org.apache.tools.ant.taskdefs.Delete; |
| import org.apache.tools.ant.taskdefs.Jar; |
| import org.apache.tools.ant.taskdefs.Mkdir; |
| import org.apache.tools.ant.taskdefs.SignJar; |
| import org.apache.tools.ant.types.Path; |
| import org.apache.tools.ant.types.ZipFileSet; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.xml.sax.ErrorHandler; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXParseException; |
| |
| public class Package extends Task { |
| |
| private Path classpath; |
| private boolean pError = false; |
| HashMap<String, Vector<String>> nbms = new HashMap<String, Vector<String>>(); |
| File srcDir = null; |
| private String jarSignerMaxMemory = "96m"; |
| |
| /** Set the location of <samp>jhall.jar</samp> or <samp>jsearch.jar</samp> (JavaHelp tools library). */ |
| public Path createClasspath() { |
| // JavaHelp release notes say jhtools.jar is enough, but class NoClassDefFoundError |
| // on javax.help.search.IndexBuilder when I tried it... |
| if (classpath == null) { |
| classpath = new Path(getProject()); |
| } |
| return classpath.createPath(); |
| } |
| |
| public void setSrc(File f) { |
| srcDir = f; |
| } |
| File distDir = null; |
| |
| public void setDist(File d) { |
| distDir = d; |
| } |
| File nbmsDistDir = null; |
| |
| public void setNbmsDist(File d) { |
| nbmsDistDir = d; |
| } |
| String locales; |
| |
| /** Set a comma-separated list of locales. */ |
| public void setLocales(String l) { |
| locales = l; |
| } |
| File nbmsLocation = null; |
| |
| public void setNBMs(File f) { |
| nbmsLocation = f; |
| } |
| public File keystore; |
| public String storepass, alias; |
| |
| /** Path to the keystore (private key). */ |
| public void setKeystore(File f) { |
| keystore = f; |
| } |
| |
| /** Password for the keystore. |
| * If a question mark (<samp>?</samp>), the NBM will not be signed |
| * and a warning will be printed. |
| */ |
| public void setStorepass(String s) { |
| storepass = s; |
| } |
| |
| /** Alias for the private key. */ |
| public void setAlias(String s) { |
| alias = s; |
| } |
| |
| public void execute() throws BuildException { |
| |
| // Create all localized jars |
| StringTokenizer tokenizer = new StringTokenizer(locales.trim(), ", "); |
| while (tokenizer.hasMoreTokens()) { |
| String loc = tokenizer.nextToken(); |
| processLocale(loc); |
| } |
| |
| // Deal with NBMs creation |
| DirectoryScanner ds = new DirectoryScanner(); |
| ds.setBasedir(nbmsLocation); |
| ds.setIncludes(new String[]{"**/*.nbm"}); |
| ds.scan(); |
| Mkdir mkdir = (Mkdir) getProject().createTask("mkdir"); |
| Copy copy = (Copy) getProject().createTask("copy"); |
| File tmpDir = new File("tmp"); |
| tmpDir.mkdir(); |
| for (String nbm : ds.getIncludedFiles()) { |
| String nbmName = nbm.substring(nbm.lastIndexOf(File.separator) + 1, nbm.lastIndexOf(".")); |
| Vector<String> nbmFiles = nbms.get(nbmName); |
| if (nbmFiles == null) { |
| log("There is no localization content for NBM: " + nbmName); |
| continue; |
| } |
| String cluster = nbm.substring(0, nbm.indexOf(File.separator)); |
| File destNbmDir = new File(nbmsDistDir, cluster); |
| File destNbmFile = new File(destNbmDir, nbmName + ".nbm"); |
| if (!destNbmDir.isDirectory()) { |
| mkdir.setDir(destNbmDir); |
| mkdir.execute(); |
| } |
| copy.setFile(new File(nbmsLocation, nbm)); |
| copy.setTodir(destNbmDir); |
| copy.execute(); |
| |
| Jar jar = (Jar) getProject().createTask("jar"); |
| jar.setUpdate(true); |
| jar.setDestFile(destNbmFile); |
| ZipFileSet zfs = new ZipFileSet(); |
| zfs.setDir(new File(distDir, cluster)); |
| zfs.setPrefix("netbeans"); |
| zfs.appendIncludes(nbmFiles.toArray(new String[]{""})); |
| jar.addFileset(zfs); |
| |
| //Process InfoXMLs |
| tokenizer = new StringTokenizer(locales.trim(), ", "); |
| while (tokenizer.hasMoreTokens()) { |
| String loc = tokenizer.nextToken(); |
| try { |
| File jarF = new File(distDir, cluster + File.separator + "modules" + File.separator + "locale" + File.separator + nbmName + "_" + loc + ".jar"); |
| if (!jarF.isFile()) { |
| log("No " + loc + " localization for " + nbmName); |
| continue; |
| } |
| //Find localized bundle |
| JarFile jarFile = new JarFile(new File(distDir, cluster + File.separator + "modules" + File.separator + "locale" + File.separator + nbmName + "_" + loc + ".jar")); |
| Properties p = new Properties(); |
| ZipEntry bundleentry = jarFile.getEntry(nbmName.replace('-', '/') + File.separator + "Bundle_" + loc + ".properties"); |
| if (bundleentry == null) { |
| //Read it from the NBM and module's jar manifest |
| JarFile nbmFile = new JarFile(destNbmFile); |
| String jarEntryName = "netbeans/modules/" + nbmName + ".jar"; |
| ZipEntry ze = nbmFile.getEntry(jarEntryName); |
| InputStream is; |
| if(ze == null) { |
| //NBM is packed with pack200 |
| ze = nbmFile.getEntry(jarEntryName + ".pack.gz"); |
| if(ze!=null) { |
| File packedJar = File.createTempFile(nbmName, ".jar.pack.gz", tmpDir); |
| File unpackedJar = File.createTempFile(nbmName, ".jar", tmpDir); |
| unpackedJar.deleteOnExit(); |
| packedJar.deleteOnExit(); |
| InputStream fis = nbmFile.getInputStream(ze); |
| BufferedOutputStream bof = new BufferedOutputStream(new FileOutputStream(packedJar)); |
| byte [] buffer = new byte [4096]; |
| int read = 0; |
| while ((read = fis.read(buffer)) != -1) { |
| bof.write(buffer, 0, read); |
| } |
| bof.close(); |
| fis.close(); |
| AutoUpdate.unpack200(packedJar, unpackedJar); |
| is = new FileInputStream(unpackedJar); |
| } else { |
| throw new BuildException("Cannot find neither " + |
| jarEntryName + ".pack.gz nor " + |
| jarEntryName + " entry in " + nbmFile.getName()); |
| } |
| } else { |
| is = nbmFile.getInputStream(ze); |
| } |
| |
| File tmpJar = File.createTempFile("module", ".jar", tmpDir); |
| BufferedOutputStream bof = new BufferedOutputStream(new FileOutputStream(tmpJar)); |
| int ch = 0; |
| while ((ch = is.read()) != -1) { |
| bof.write(ch); |
| } |
| bof.close(); |
| is.close(); |
| JarFile moduleJar = new JarFile(tmpJar); |
| String bundlename = moduleJar.getManifest().getMainAttributes().getValue("OpenIDE-Module-Localizing-Bundle"); |
| String bfname = bundlename.substring(0, bundlename.lastIndexOf('.')); |
| String bfext = bundlename.substring(bundlename.lastIndexOf('.')); |
| bundlename = bfname + "_" + loc + bfext; |
| bundleentry = jarFile.getEntry(bundlename); |
| moduleJar.close(); |
| tmpJar.delete(); |
| } |
| if (bundleentry != null) { |
| InputStream is = jarFile.getInputStream(bundleentry); |
| try { |
| p.load(is); |
| } finally { |
| is.close(); |
| } |
| // Open the original info XML |
| JarFile nbmFile = new JarFile(destNbmFile); |
| Document doc = XMLUtil.parse(new InputSource(nbmFile.getInputStream(nbmFile.getEntry("Info/info.xml"))), false, false, new ErrorCatcher(), null); |
| Element manifest = (Element) doc.getElementsByTagName("manifest").item(0); |
| |
| // Now pick up attributes from the bundle and put them to the info.xml |
| for (String attr : new String[]{"OpenIDE-Module-Name", "OpenIDE-Module-Display-Category", "OpenIDE-Module-Short-Description", "OpenIDE-Module-Long-Description"}) { |
| String value = p.getProperty(attr); |
| if (value != null) { |
| manifest.setAttribute(attr, value); |
| } |
| } |
| File infofile = new File(tmpDir, "info_" + loc + ".xml"); |
| OutputStream infoStream = new FileOutputStream(infofile); |
| XMLUtil.write(doc, infoStream); |
| infoStream.close(); |
| zfs = new ZipFileSet(); |
| zfs.setDir(tmpDir); |
| zfs.setPrefix("Info/locale"); |
| zfs.appendIncludes(new String[]{"info_" + loc + ".xml"}); |
| jar.addFileset(zfs); |
| } else { |
| log("Can't find localizing bundle for " + nbmName); |
| } |
| } catch (IOException ex) { |
| log("Problems with reading localization bundles for " + loc + ", NBM: " + nbmName, ex, Project.MSG_WARN); |
| |
| } catch (SAXException saxe) { |
| log("Problem with creating localized info.xml for " + loc + ", NBM: " + nbmName, saxe, Project.MSG_WARN); |
| } |
| |
| } |
| jar.execute(); |
| |
| if (keystore != null && storepass != null && alias != null) { |
| if (!keystore.isFile()) { |
| continue; |
| } |
| SignJar signjar = (SignJar) getProject().createTask("signjar"); |
| try { // Signatures changed in various Ant versions. |
| |
| try { |
| SignJar.class.getMethod("setKeystore", File.class).invoke(signjar, keystore); |
| } catch (NoSuchMethodException x) { |
| SignJar.class.getMethod("setKeystore", String.class).invoke(signjar, keystore.getAbsolutePath()); |
| } |
| try { |
| SignJar.class.getMethod("setJar", File.class).invoke(signjar, destNbmFile); |
| } catch (NoSuchMethodException x) { |
| SignJar.class.getMethod("setJar", String.class).invoke(signjar, destNbmFile.getAbsolutePath()); |
| } |
| } catch (BuildException x) { |
| throw x; |
| } catch (Exception x) { |
| throw new BuildException(x); |
| } |
| signjar.setStorepass(storepass); |
| signjar.setAlias(alias); |
| signjar.setLocation(getLocation()); |
| signjar.setMaxmemory(this.jarSignerMaxMemory); |
| signjar.init(); |
| signjar.execute(); |
| } |
| } |
| Delete delete = (Delete) getProject().createTask("delete"); |
| delete.setDir(tmpDir); |
| delete.execute(); |
| } |
| |
| void processLocale(String locale) throws BuildException { |
| DirectoryScanner ds = new DirectoryScanner(); |
| File baseSrcDir = new File(srcDir, locale); |
| if (!baseSrcDir.exists()) { |
| log("No files for locale: " + locale); |
| return; |
| } |
| ds.setBasedir(baseSrcDir); |
| String[] includes = new String[]{"*/*/*", "*/*/ext/*", "*/*/ext/locale/*", "*/*/netbeans/*/*", "*/*/netbeans/*/locale/*", "*/*/netbeans/*/nblib/*", "*/*/netbeans/*/extra/*", "*/*/docs/*", "*/*/locale/*", "*/*/netbeans/config/*/*"}; |
| String[] excludes = new String[]{"other/**", "*/*/netbeans", "*/*/netbeans/*", "*/*/netbeans/*/locale", "*/*/netbeans/*/nblib", "*/*/netbeans/*/extra", "*/*/docs", "*/*/ext", "*/*/ext/locale", "*/*/locale", "*/*/netbeans/config/*"}; |
| ds.setIncludes(includes); |
| ds.setExcludes(excludes); |
| ds.scan(); |
| Jar jar = (Jar) getProject().createTask("jar"); |
| Mkdir mkdir = (Mkdir) getProject().createTask("mkdir"); |
| Task locJH = getProject().createTask("locjhindexer"); |
| for (String dir : ds.getIncludedDirectories()) { |
| String name = dir.substring(dir.lastIndexOf(File.separator) + 1); |
| name = name.replaceAll("^vw-rh", "visualweb-ravehelp-rave_nbpack"); |
| name = name.replaceAll("^vw-", "visualweb-"); |
| String nbm = dir.substring(dir.indexOf(File.separator) + 1); |
| nbm = nbm.substring(0, nbm.indexOf(File.separator)); |
| String cluster = dir.substring(0, dir.indexOf(File.separator)); |
| String subPath = dir.substring((cluster + File.separator + nbm + File.separator).length() - 1, dir.lastIndexOf(File.separator)); |
| if (!subPath.startsWith(File.separator + "netbeans")) { |
| subPath = File.separator + "modules" + subPath; |
| if (!name.startsWith("org-") && !(subPath.endsWith(File.separator + "ext") || subPath.endsWith(File.separator + "ext" + File.separator + "locale"))) { |
| name = "org-netbeans-modules-" + name; |
| } else { |
| // Handle exception from ext/ |
| if (name.startsWith("web-httpmonitor") || name.startsWith("deployment-deviceanywhere")) { |
| name = "org-netbeans-modules-" + name; |
| } |
| } |
| } else { |
| subPath = subPath.substring((File.separator + "netbeans").length()); |
| //Handle exceptions form nblib |
| if (name.startsWith("j2ee-ant") || name.startsWith("deployment-deviceanywhere") || name.startsWith("mobility-project") || name.startsWith("java-j2seproject-copylibstask")) { |
| name = "org-netbeans-modules-" + name; |
| } |
| } |
| nbm = nbm.replaceAll("^vw-rh", "visualweb-ravehelp-rave_nbpack"); |
| nbm = nbm.replaceAll("^vw-", "visualweb-"); |
| if (!nbm.startsWith("org-") && !nbm.startsWith("com-")) { |
| nbm = "org-netbeans-modules-" + nbm; |
| } |
| cluster = cluster.replaceAll("^vw", "visualweb"); |
| if (subPath.matches(".*/docs$")) { |
| ds.setBasedir(new File(baseSrcDir, dir)); |
| ds.setIncludes(new String[]{"**/*.hs"}); |
| ds.setExcludes(new String[]{""}); |
| ds.scan(); |
| if (ds.getIncludedFilesCount() != 1) { |
| throw new BuildException("Can't find .hs file for " + name + " module."); |
| } |
| File hsFile = new File(new File(baseSrcDir, dir), ds.getIncludedFiles()[0]); |
| File baseJHDir = hsFile.getParentFile(); |
| |
| try { |
| System.out.println("Basedir: " + baseJHDir.getAbsolutePath()); |
| locJH.getClass().getMethod("setBasedir", File.class).invoke(locJH, baseJHDir); |
| locJH.getClass().getMethod("setLocales", String.class).invoke(locJH, locale); |
| locJH.getClass().getMethod("setDbdir", String.class).invoke(locJH, "JavaHelpSearch"); |
| ((Path)locJH.getClass().getMethod("createClasspath").invoke(locJH)).add(classpath); |
| |
| } catch (Exception ex) { |
| throw new BuildException("Can't run locJHInxeder", ex); |
| } |
| locJH.execute(); |
| } |
| if (!subPath.endsWith("locale")) { |
| subPath += File.separator + "locale"; |
| } |
| String jarFileName = name + "_" + locale + ".jar"; |
| File distJarDir = new File(distDir.getAbsolutePath(), cluster + subPath); |
| mkdir.setDir(distJarDir); |
| mkdir.execute(); |
| jar.setBasedir(new File(baseSrcDir, dir)); |
| jar.setDestFile(new File(distJarDir, jarFileName)); |
| jar.execute(); |
| Vector<String> nbmFiles = nbms.get(nbm); |
| if (nbmFiles == null) { |
| nbmFiles = new Vector<String>(); |
| nbms.put(nbm, nbmFiles); |
| } |
| nbmFiles.add(subPath.substring(1) + File.separator + jarFileName); |
| } |
| ds.setBasedir(baseSrcDir); |
| ds.setIncludes(includes); |
| ds.setExcludes(excludes); |
| ds.scan(); |
| Copy copy = (Copy) getProject().createTask("copy"); |
| for (String file : ds.getIncludedFiles()) { |
| String name = file.substring(file.lastIndexOf(File.separator) + 1); |
| name = name.replaceAll("^vw-rh", "visualweb-ravehelp-rave_nbpack"); |
| name = name.replaceAll("^vw-", "visualweb-"); |
| String nbm = file.substring(file.indexOf(File.separator) + 1); |
| nbm = nbm.substring(0, nbm.indexOf(File.separator)); |
| String cluster = file.substring(0, file.indexOf(File.separator)); |
| String subPath = file.substring((cluster + File.separator + nbm + File.separator).length() - 1, file.lastIndexOf(File.separator)); |
| if (!subPath.startsWith(File.separator + "netbeans")) { |
| subPath = File.separator + "modules" + subPath; |
| } else { |
| subPath = subPath.substring((File.separator + "netbeans").length()); |
| } |
| nbm = nbm.replaceAll("^vw-rh", "visualweb-ravehelp-rave_nbpack"); |
| nbm = nbm.replaceAll("^vw-", "visualweb-"); |
| if (!nbm.startsWith("org") || !nbm.startsWith("com")) { |
| nbm = "org-netbeans-modules-" + nbm; |
| } |
| cluster = cluster.replaceAll("^vw", "visualweb"); |
| File distFileDir = new File(distDir.getAbsolutePath(), cluster + subPath); |
| mkdir.setDir(distFileDir); |
| mkdir.execute(); |
| copy.setFile(new File(baseSrcDir, file)); |
| copy.setTodir(distFileDir); |
| copy.execute(); |
| Vector<String> nbmFiles = nbms.get(nbm); |
| if (nbmFiles == null) { |
| nbmFiles = new Vector<String>(); |
| nbms.put(nbm, nbmFiles); |
| } |
| nbmFiles.add(subPath.substring(1) + File.separator + file); |
| } |
| } |
| |
| class ErrorCatcher implements ErrorHandler { |
| |
| public void error(SAXParseException e) { |
| // normally a validity error |
| pError = true; |
| } |
| |
| public void warning(SAXParseException e) { |
| //parseFailed = true; |
| } |
| |
| public void fatalError(SAXParseException e) { |
| pError = true; |
| } |
| } |
| } |