/* * ALMA - Atacama Large Millimiter Array * (c) European Southern Observatory, 2004 * Copyright by ESO (in the framework of the ALMA collaboration), * All rights reserved * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ package alma.acs.eclipse.utils.pluginbuilder; import java.io.File; import java.io.FileOutputStream; import java.util.Vector; import java.util.jar.Attributes; import java.util.jar.Manifest; import java.util.logging.Logger; import alma.acs.eclipse.utils.jar.JarFileHelper; import alma.acs.eclipse.utils.jar.JarFolder; /** * Write the <code>MANIFEST>MF</code> of the plugin * * @author acaproni * */ public class ManifestWriter { /** * The logger */ private final Logger logger; /** * The manifest that objects from this class write in the pugin folder */ private final Manifest manifest = new Manifest(); /** * The name of the manifest file */ private static final String manifestName = "MANIFEST.MF"; /** * The folder to write the manifest into */ private final File manifestFolder; /** * The root folder of the plugin */ private final File pluginFolder; /** * The bundle name is dynamically generated by appending <code>pluginBundleName</code> * to the plugin root name */ private static final String pluginBundleName=" ACS Plug-in"; /** * The attribute name for Bundle-ManifestVersion */ private final Attributes.Name bundleManifestVersionName = new Attributes.Name("Bundle-ManifestVersion"); /** * The attribute name for Bundle-SymbolicName */ private final Attributes.Name bundleSymbolicName = new Attributes.Name("Bundle-SymbolicName"); /** * The attribute name for Bundle-ActivationPolicy * <P> * This is also used to add dependencies */ private final Attributes.Name bundleActivationPolicyName= new Attributes.Name("Bundle-ActivationPolicy"); /** * The attribute name for Bundle-ActivationPolicy */ private final Attributes.Name requireBundleName= new Attributes.Name("Require-bundle"); /** * The activation policy */ public static final String activationPolicy = "lazy"; /** * The attribute name for Bundle-Name */ private final Attributes.Name bundleName = new Attributes.Name("Bundle-Name"); /** * The attribute name for Bundle-Vendor */ private final Attributes.Name bundleVendorName= new Attributes.Name("Bundle-Vendor"); /** * The attribute name for Bundle-Version */ private final Attributes.Name bundleVersionName= new Attributes.Name("Bundle-Version"); /** * The bundle version */ private String bundleVersion; /** * The attribute name for Bundle-ClassPath * (i.e. the list of ACS jar files in the plugin). * <P> * The classpath is built by reading the jar files in the plugin folder */ private final Attributes.Name bundleClasspathName= new Attributes.Name("Bundle-ClassPath"); /** * The attribute name for Export-Package * (i.e. the list of java packages exported by all the jar files contained in the * plugin) * <P> * The export package is built be reading, for each jar file in the plugin root * folder, the list of the java packages */ private final Attributes.Name exportPackageName= new Attributes.Name("Export-Package"); /** Used when doing bundling by reference */ private boolean bundlingByReference; private String[] finalJarsLocations; /** * The dependencies of this plugin */ private final String[] dependencies; /** * The vendor i.e ESO */ private static final String vendor = "European Southern Observatory"; /** * Constructor * * @param folder The folder to write the manifest into * @param pluginFolder The root folder of the plugin * @param finalJarsLocations * @param bundleByReference * @param dependencies The plugins this plugin depends on * @param Logger The logger */ public ManifestWriter( File folder, File pluginFolder, boolean bundleByReference, String[] finalJarsLocations, String[] dependencies, String bundleVersion, Logger logger) { if (folder==null || !folder.canWrite()) { throw new IllegalArgumentException("Invalid folder for the manifest"); } if (pluginFolder==null || !pluginFolder.canRead()) { throw new IllegalArgumentException("Invalid plugin folder"); } if (logger==null) { throw new IllegalArgumentException("The logger can't be null"); } this.bundlingByReference = bundleByReference; this.finalJarsLocations = finalJarsLocations; this.dependencies=dependencies; if (bundleVersion != null && !bundleVersion.trim().isEmpty()) { this.bundleVersion = bundleVersion; } else { this.bundleVersion = "1.0.0"; } this.logger=logger; manifestFolder=folder; this.pluginFolder=pluginFolder; } /** * Set the attributes of the manifest * * @param attrs The attributes * @throws Exception In case of error */ private void setAttributes(Attributes attrs) throws Exception { if (attrs==null) { throw new IllegalArgumentException("the attributes can't be null"); } attrs.clear(); attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0"); attrs.put(bundleManifestVersionName, "2"); attrs.put(bundleName, pluginFolder.getName()+pluginBundleName); attrs.put(bundleSymbolicName, pluginFolder.getName()+"; singleton=true"); attrs.put(bundleVersionName, bundleVersion); attrs.put(bundleVendorName, vendor); attrs.put(bundleActivationPolicyName,activationPolicy); // Add the classpath i.e. the jar files in the root plugin folder JarFolder pluginJarFolder = new JarFolder(pluginFolder); // String acsroot = System.getenv("ACSROOT"); // String introot = System.getenv("INTROOT"); String[] jars = null; if( bundlingByReference ) jars = finalJarsLocations; else jars = pluginJarFolder.getJars(); StringBuilder classpath = new StringBuilder(); if (jars!=null && jars.length>0) { for (int t=0; t<jars.length; t++) { // If we are bundling by reference, then write the reference, no the actual jarfile if( bundlingByReference ) { // String tmp = ""; String prefix = "external:"; // if( jars[t].contains( acsroot ) ) { // tmp = jars[t].replaceAll(acsroot, ""); // prefix = "external:$ACSROOT$/"; // } // else if( jars[t].contains( introot ) ) { // tmp = jars[t].replaceAll(introot, ""); // prefix = "external:$INTROOT$/"; // } classpath.append(prefix); // classpath.append(tmp); classpath.append(jars[t]); } else classpath.append(jars[t]); if (t<jars.length-1) classpath.append(", "); logger.finer("Adding "+jars[t]+" to "+bundleClasspathName+" attribute of "+manifestName); } attrs.put(bundleClasspathName, classpath.toString()); } // Add the exported java packages Vector<String> javaPkgs = new Vector<String>(); for (int i=0; i!= jars.length; i++) { File jarFile = null; if( bundlingByReference ) { jarFile = new File(jars[i]); } else jarFile = new File(pluginFolder.getAbsolutePath()+File.separator+jars[i]); JarFileHelper jarFileHelper = new JarFileHelper(jarFile); int n=jarFileHelper.getPackages(javaPkgs); if (n>0) { logger.finer("Found "+n+" java packages in "+jars[i]); } else { logger.warning("Found "+n+" java packages in "+jars[i]); } } StringBuilder pkgs = new StringBuilder(); if (javaPkgs.size()>0) { for (int t=0; t<javaPkgs.size(); t++) { pkgs.append(javaPkgs.elementAt(t)); if (t<javaPkgs.size()-1) { pkgs.append(','); pkgs.append(' '); } logger.finer("Adding "+javaPkgs.elementAt(t)+" to "+exportPackageName+" attribute of "+manifestName); } attrs.put(exportPackageName,pkgs.toString()); } // Add the dependencies if any StringBuilder deps = new StringBuilder("system.bundle"); for (String dep: dependencies) { deps.append(','); deps.append(' '); if (dep.contains("_")) { // a version is present String[] tmp=dep.split("_"); deps.append(tmp[0]); deps.append(";bundle-version=\""); deps.append(tmp[1]); deps.append('\"'); } else { deps.append(dep); } } attrs.put(requireBundleName, deps.toString()); } /** * Write the manifest * * @throws Exception In case of error */ public void write() throws Exception { File manifestFile = new File(manifestFolder.getAbsolutePath()+File.separator+manifestName); FileOutputStream outStream = new FileOutputStream(manifestFile,false); Attributes attributes = manifest.getMainAttributes(); setAttributes(attributes); manifest.write(outStream); } }