📄 bundle.java
字号:
/* * Copyright (c) 2005, KNOPFLERFISH project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of the KNOPFLERFISH project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */package org.knopflerfish.ant.taskdefs.bundle;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.Enumeration;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import java.util.zip.ZipEntry;import java.util.zip.ZipFile;import org.apache.bcel.classfile.ClassParser;import org.apache.bcel.classfile.Constant;import org.apache.bcel.classfile.ConstantClass;import org.apache.bcel.classfile.ConstantPool;import org.apache.bcel.classfile.JavaClass;import org.apache.bcel.classfile.Utility;import org.apache.tools.ant.BuildException;import org.apache.tools.ant.DirectoryScanner;import org.apache.tools.ant.FileScanner;import org.apache.tools.ant.Project;import org.apache.tools.ant.taskdefs.Jar;import org.apache.tools.ant.taskdefs.Manifest;import org.apache.tools.ant.taskdefs.ManifestException;import org.apache.tools.ant.types.FileSet;import org.apache.tools.ant.types.ZipFileSet;/** * <p> * An extension of the * <a href="http://ant.apache.org/manual/CoreTasks/jar.html" target="_top">Jar</a> task that * builds an OSGi bundle. It can generate the Bundle-Activator, * Bundle-ClassPath and Import-Package manifest headers based on the content * specified in the task. * </p> * * <p> * <b>Note:</b> This task depends on the * <a href="http://jakarta.apache.org/bcel/">Apache Jakarta BCEL</a> library, * not included in the Ant distribution. * </p> * * <h3>Parameters</h3> * <table border="1px"> * <tr> * <th align="left">Attribute</th> * <th align="left">Description</th> * <th align="left">Required</th> * </tr> * <tr> * <td valign="top">file</td> * <td valign="top">The bundle file to create.</td> * <td valign="top">Yes</td> * </tr> * <tr> * <td valign="top">activator</td> * <td valign="top"> * The bundle activator class name. If set to "none" no Bundle-Activator * manifest header will be generated. If set to "auto" the bundle task * will try to find an activator in the included class files. * </td> * <td valign="top">No, default is "auto"</td> * </tr> * <tr> * <td valign="top">packageanalysis</td> * <td valign="top"> * Analyzes the class files of the bundle and the contents of the * <tt>exportpackage</tt> and <tt>importpackage</tt> nested elements. * <ul> * <li>none – no analysis is performed.</li> * <li>warn – a warning will be displayed for each referenced * package not found in the bundle or the <tt>importpackage</tt> nested * elements.</li> * <li>auto – each referenced package not found in the bundle or * the <tt>importpackage</tt> nested elements will be added to the * Import-Package manifest header. Packages exported by the bundle will * be added to the Import-Package manifest header with the version as * specified in the <tt>exportpackage</tt> nested element.</li> * </ul> * </td> * <td valign="top">No, default is "warn"</td> * </tr> * </table> * * <h3>Nested elements</h3> * * <h4>classes</h4> * <p> * The nested <tt>classes</tt> element specifies a * <a href="http://ant.apache.org/manual/CoreTypes/zipfileset.html" target="_top">ZipFileSet</a>. * The <tt>prefix</tt> attribute will be added to the Bundle-ClassPath manifest * header. The classes specified by the file set will be included in the class * analysis. * </p> * * <h4>lib</h4> * <p> * The nested <tt>lib</tt> element specifies a * <a href="http://ant.apache.org/manual/CoreTypes/zipfileset.html" target="_top">ZipFileSet</a>. * The locations of all files in the file set will be added to the * Bundle-ClassPath manifest header. All files of this file set must be either * zip or jar files. The classes available in the zip or jar files will be * included in the class analysis. * </p> * * <h4>exportpackage</h4> * <p> * The nested <tt>exportpackage</tt> element specifies the name and * specification version of a package to add to the Export-Package manifest * header. If package analysis is not turned off, a warning will be issued if * the specified package cannot be found in the bundle. * </p> * * <h4>importpackage</h4> * <p> * The nested <tt>importpackage</tt> element specifies the name and * specification version of a package to add to the Import-Package manifest * header. * </p> * * <h4>standardpackage</h4> * <p> * The nested <tt>standardpackage</tt> element specifies the name or prefix * of a package that should be excluded from the package analysis. It can * be used to avoid importing packages that are available in the underlying * runtime environment. * </p> * * <h3>Implicit fileset</h3> * <p> * The implicit fileset is specified by the <tt>baseDir</tt> attribute of the * bundle task and the nested <tt>include</tt> and <tt>exclude</tt> elements. * </p> * <p> * The implicit fileset of the <tt>bundle</tt> task will be included in the * class analysis and in the Bundle-ClassPath manifest header if needed. * </p> * * <h3>Examples</h3> * <pre> * <bundle activator="auto" * packageanalysis="auto" * file="out/${ant.project.name}.jar"> * * <standardpackage name="javax.imageio"/> * * <exportpackage name="se.weilenmann.bundle.test" version="1.0"/> * * <manifest> * <attribute name="Bundle-Name" value="testbundle"/> * <attribute name="Bundle-Version" value="1.0"/> * <attribute name="Bundle-Vendor" value="Kaspar Weilenmann"/> * </manifest> * * <classes dir="out/classes"> * <include name="se/weilenmann/bundle/test/**"/> * </classes> * <classes dir="out/classes" prefix="util"> * <include name="se/weilenmann/util/**"/> * </classes> * <classes src="osgi/jars/log/log_api.jar" prefix="log_api"> * <include name="**/*.class"/> * </classes> * * <lib dir="osgi/jars/cm" includes="cm_api.jar" prefix="osgi"/> * <lib dir="lib/commons" includes="commons-logging.jar" prefix="commons"/> * * </bundle> * </pre> * <p>Creates a bundle with the following manifest:<p> * <pre> * Manifest-Version: 1.0 * Ant-Version: Apache Ant 1.6.2 * Created-By: 1.4.2_02-b03 (Sun Microsystems Inc.) * Bundle-Name: testbundle * Bundle-Version: 1.0 * Bundle-Vendor: Kaspar Weilenmann * Bundle-Activator: se.weilenmann.bundle.test.Activator * Bundle-ClassPath: .,util,log_api,osgi/cm_api.jar,commons/commons-loggi * ng.jar * Import-Package: se.weilenmann.bundle.test;specification-version=1.0,or * g.osgi.framework * Export-Package: se.weilenmann.bundle.test;specification-version=1.0 * </pre> * * @author <a href="mailto:kaspar@weilenmann.se">Kaspar Weilenmann</a> */public class Bundle extends Jar { // private fields private static final String BUNDLE_CLASS_PATH_KEY = "Bundle-ClassPath"; private static final String BUNDLE_ACTIVATOR_KEY = "Bundle-Activator"; private static final String IMPORT_PACKAGE_KEY = "Import-Package"; private static final String EXPORT_PACKAGE_KEY = "Export-Package"; private static final String ACTIVATOR_NONE = "none"; private static final String ACTIVATOR_AUTO = "auto"; private static final String PACKAGE_ANALYSIS_NONE = "none"; private static final String PACKAGE_ANALYSIS_WARN = "warn"; private static final String PACKAGE_ANALYSIS_AUTO = "auto"; private String activator = ACTIVATOR_AUTO; private String packageAnalysis = PACKAGE_ANALYSIS_WARN; private Map importPackage = new HashMap(); private Map exportPackage = new HashMap(); private List libs = new ArrayList(); private List classes = new ArrayList(); private File baseDir = null; private List zipgroups = new ArrayList(); private List srcFilesets = new ArrayList(); private Manifest generatedManifest = new Manifest(); private Set activatorClasses = new HashSet(); private Set availablePackages = new HashSet(); private Set referencedPackages = new HashSet(); private Set standardPackagePrefixes = new HashSet(); { standardPackagePrefixes.add("java."); } // private methods private void analyze() { if (activator == ACTIVATOR_AUTO || packageAnalysis != PACKAGE_ANALYSIS_NONE) { addZipGroups(); addImplicitFileset(); for (Iterator i = srcFilesets.iterator(); i.hasNext();) { FileSet fileset = (FileSet) i.next(); File srcFile = getZipFile(fileset); if (srcFile == null) { File filesetBaseDir = fileset.getDir(getProject()); DirectoryScanner ds = fileset.getDirectoryScanner(getProject()); String[] files = ds.getIncludedFiles(); for (int j = 0; j < files.length; j++) { String fileName = files[j]; if (fileName.endsWith(".class")) { File file = new File(filesetBaseDir, fileName); try { analyzeClass(new ClassParser(file.getAbsolutePath())); } catch (IOException ioe) { throw new BuildException("Failed to parse class file: " + file.getAbsolutePath(), ioe); } } } } else { try { ZipFile zipFile = new ZipFile(srcFile); Enumeration files = zipFile.entries(); while (files.hasMoreElements()) { ZipEntry entry = (ZipEntry) files.nextElement(); String name = entry.getName(); if (name.endsWith(".class")) { try { analyzeClass(new ClassParser(zipFile.getInputStream(entry), name)); } catch (IOException ioe) { throw new BuildException("Failed to parse class file: " + name, ioe); } } } } catch (IOException ioe) { throw new BuildException("Failed to read zip file: " + zipFile.getAbsolutePath(), ioe); } } } Set publicPackages = exportPackage.keySet(); if (packageAnalysis != PACKAGE_ANALYSIS_NONE) { for (Iterator i = publicPackages.iterator(); i.hasNext();) { String packageName = (String) i.next(); if (!availablePackages.contains(packageName)) { log("Exported package not found in bundle: " + packageName, Project.MSG_WARN); } } } Set privatePackages = new HashSet(availablePackages); privatePackages.removeAll(publicPackages);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -