📄 bundlehtmlextractortask.java
字号:
/* * Copyright (c) 2003, 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 org.apache.tools.ant.Task;import org.apache.tools.ant.BuildException;import org.apache.tools.ant.Project;import org.apache.tools.ant.DirectoryScanner;import org.apache.tools.ant.types.FileSet;import org.apache.tools.ant.util.FileUtils;import org.apache.tools.ant.util.StringUtils;import org.apache.tools.ant.util.JavaEnvUtils;import org.apache.bcel.Constants;import org.apache.bcel.classfile.*;import org.apache.bcel.generic.Type;import org.apache.bcel.generic.BasicType;import java.io.*;import java.util.*;import java.util.jar.*;import java.util.zip.*;/** * <p> * Task that analyzes a set of bundle jar files and builds HTML documentation * from these bundles. Also creates cross-references to bundle dependecies. * </p> * * <p> * All generated HTML will be stored in the same directory stucture as * the scanned jars, e.g a jar file * <pre> * jars/log/log-api.jar * </pre> * will have a corresponding * <pre> * jars/log/log-api.html * </pre> * * <p> * Bundle jar files files are analyzed using the static manifest attributes. * </p> * * <h3>Parameters</h3> * * <table border=> * <tr> * <td valign=top><b>Attribute</b></td> * <td valign=top><b>Description</b></td> * <td valign=top><b>Required</b></td> * </tr> * <tr> * <td valign=top>javadocRelPath</td> * <td valign=top>Relative path (from baseDir) to javadocs. * </td> * <td valign=top>No.<br> Default value is "."</td> * </tr> * <tr> * <td valign=top>baseDir</td> * <td valign=top> * Base directory for scanning for jar files. * </td> * <td valign=top>No.<br> Default value is "."</td> * </tr> * <td valign=top>templateHTMLDir</td> * <td valign=top> * Directory containing HTML template files. This directory must * contain the files: * <pre> * bundle_index.html * bundle_list.html * bundle_main.html * style.css * </pre> * </td> * </td> * <td valign=top>No.<br> Default value is "."</td> * </tr> * * <tr> * <td valign=top>systemPackageSet</td> * <td valign=top> * Comma-spearated set of packages which are system packages and * thus globally available. * These are not cross-referenced. * </td> * <td valign=top>No.<br> * Default value is "javax.swing,javax.accessibility,javax.servlet,javax.xml,org.xml,org.w3c,java,com.sun" </td> * * <tr> * <td valign=top>skipAttribSet</td> * <td valign=top> * Comma-spearated set of manifest attributes which shouldn't be printed. * </td> * <td valign=top>No.<br> * Default value is "Manifest-Version,Ant-Version,Bundle-Config,Created-By,Built-From" </td> * * </table> * * <h3>Parameters specified as nested elements</h3> * <h4>fileset</h4> * * (required)<br> * <p> * All jar files must be specified as a fileset. No jar files * are ignored. * </p> * * <h3>Examples</h3> * * <pre> * <bundlehtml templateHTMLDir = "${ant.dir}/html_template" * baseDir = "${release.dir}/jars" * javadocRelPath = "../javadoc" * > * * <fileset dir="${release.dir}/jars"> * <include name = "**/*.jar"/> * </fileset> * </pre> * */public class BundleHTMLExtractorTask extends Task { private Vector filesets = new Vector(); private FileUtils fileUtils; private File templateHTMLDir = new File("."); private String listSeparator = "<br>\n"; private File baseDir = new File("."); private String javadocRelPath = null; private String indexListRow = "<a target=\"bundle_main\" href=\"${bundledoc}\">${FILE.short}</a><br>"; private String indexMainRow = "<tr>" + "<td><a target=\"bundle_main\" href=\"${bundledoc}\">${FILE.short}</a></td><td>" + "<td>${Bundle-Description}</td>" + "</tr>\n"; private String bundleRow = "<tr><td><a href=\"${bundledoc}\">${FILE.short}</a></td><td>${what}</td></tr>\n"; private String missingRow = "<tr><td>${name}</td><td>${version}</td></tr>\n"; private String rowHTML = "<a href=\"${bundle.uri}\">${FILE.short}</a><br>\n"; private String pkgHTML = "${namelink} ${version}<br>"; private boolean bCheckJavaDoc = true; Map jarMap = new TreeMap(); Map globalVars = new TreeMap(); Map missingDocs = new TreeMap(); public BundleHTMLExtractorTask() { fileUtils = FileUtils.newFileUtils(); setListProps("Export-Package," + "Import-Package," + "Import-Service," + "Export-Service"); setSystemPackageSet("javax.swing," + "javax.accessibility," + "javax.servlet," + "javax.xml," + "org.xml," + "org.w3c," + "java," + "com.sun"); setSkipAttribSet("Manifest-Version," + "Ant-Version," + "Bundle-Config," + "Created-By" // "Built-From", ); setAlwaysProps("Bundle-Activator," + "Bundle-Vendor," + "Bundle-Name," + "Bundle-Description," + "Export-Package," + "Import-Package," + "Import-Service," + "Export-Service," + "Main-class," + "Build-Date," + "Bundle-DocURL," + "Bundle-Classpath," + "Bundle-ContactAddress," + "Bundle-Activator"); } public void setCheckJavaDoc(String s) { this.bCheckJavaDoc = "true".equals(s); } public void setTemplateHTMLDir(String s) { this.templateHTMLDir = new File(s); if(!templateHTMLDir.exists()) { throw new BuildException("templateHTMLDir: " + s + " does not exist"); } if(!templateHTMLDir.isDirectory()) { throw new BuildException("templateHTMLDir: " + s + " is not a directory"); } } File getBundleInfoTemplate() { return new File(templateHTMLDir, "bundle_info.html"); } File getBundleCSSTemplate() { return new File(templateHTMLDir, "style.css"); } File getBundleListTemplate() { return new File(templateHTMLDir, "bundle_list.html"); } File getBundleMainTemplate() { return new File(templateHTMLDir, "bundle_main.html"); } File getBundleIndexTemplate() { return new File(templateHTMLDir, "bundle_index.html"); } public void setBaseDir(String s) { this.baseDir = new File((new File(s)).getAbsolutePath()); } public void setJavadocRelPath(String s) { this.javadocRelPath = s; } public void addFileset(FileSet set) { filesets.addElement(set); } Set listPropSet = new HashSet(); Set skipAttribSet = new HashSet(); Set alwaysPropSet = new HashSet(); Set systemPackageSet = new HashSet(); public void setListProps(String s) { listPropSet = Util.makeSetFromStringList(s); } public void setAlwaysProps(String s) { alwaysPropSet = Util.makeSetFromStringList(s); } public void setSkipAttribSet(String s) { skipAttribSet = Util.makeSetFromStringList(s); } public void setSystemPackageSet(String s) { systemPackageSet = Util.makeSetFromStringList(s); } // Implements Task public void execute() throws BuildException { if (filesets.size() == 0) { throw new BuildException("No fileset specified"); } try { for (int i = 0; i < filesets.size(); i++) { FileSet fs = (FileSet) filesets.elementAt(i); DirectoryScanner ds = fs.getDirectoryScanner(project); File projDir = fs.getDir(project); String[] srcFiles = ds.getIncludedFiles(); String[] srcDirs = ds.getIncludedDirectories(); for (int j = 0; j < srcFiles.length ; j++) { File file = new File(projDir, srcFiles[j]); if(file.getName().endsWith(".jar")) { jarMap.put(file, new BundleInfo(file)); } } } System.out.println("analyzing " + jarMap.size() + " bundles"); for(Iterator it = jarMap.keySet().iterator(); it.hasNext();) { File file = (File)it.next(); BundleInfo info = (BundleInfo)jarMap.get(file); info.load(); } System.out.println("writing bundle info html pages"); for(Iterator it = jarMap.keySet().iterator(); it.hasNext();) { File file = (File)it.next(); BundleInfo info = (BundleInfo)jarMap.get(file); info.writeInfo(); } makeListPage(getBundleMainTemplate(), new File(baseDir, "main.html"), indexMainRow); makeListPage(getBundleListTemplate(), new File(baseDir, "list.html"), indexListRow); copyFile(getBundleIndexTemplate(), new File(baseDir, "index.html")); copyFile(getBundleCSSTemplate(), new File(baseDir, "style.css")); for(Iterator it = missingDocs.keySet().iterator(); it.hasNext();) { String name = (String)it.next(); System.out.println("Missing javadoc for " + name); } } catch (Exception e) { e.printStackTrace(); throw new BuildException("Failed to extract bundle info: " + e, e); } } void makeListPage(File templateFile, File outFile, String rowTemplate) throws IOException { int unresolvedCount = 0; String html = Util.loadFile(templateFile.getAbsolutePath()); StringBuffer sb = new StringBuffer(); for(Iterator it = jarMap.keySet().iterator(); it.hasNext();) { File file = (File)it.next(); BundleInfo info = (BundleInfo)jarMap.get(file); unresolvedCount += info.unresolvedMap.size(); String row = rowTemplate; row = info.stdReplace(row, false); row = replace(row, "${bundledoc}", replace(info.path, ".jar", ".html")); sb.append(row); } html = replace(html, "${bundle.list}", sb.toString()); sb = new StringBuffer(); if(unresolvedCount > 0) { sb.append("<table>\n"); sb.append("<tr>\n" + " <td colspan=2 class=\"mfheader\">Unresolved packages</td>\n" + "</tr>\n"); for(Iterator it = jarMap.keySet().iterator(); it.hasNext();) { File file = (File)it.next(); BundleInfo info = (BundleInfo)jarMap.get(file); if(info.unresolvedMap.size() > 0) { sb.append("<tr>\n" + " <td>" + info.file.getName() + "</td>\n"); sb.append("<td>"); for(Iterator it2 = info.unresolvedMap.keySet().iterator(); it2.hasNext();) { String pkgName = (String)it2.next(); ArrayInt version = (ArrayInt)info.unresolvedMap.get(pkgName); sb.append(pkgName + " " + version + "<br>\n"); } sb.append("</td>"); sb.append("<tr>"); } } sb.append("</table>\n"); } html = replace(html, "${unresolved.list}", sb.toString()); Util.writeStringToFile(outFile, html); System.out.println("wrote " + outFile); } void copyFile(File templateFile, File outFile) throws IOException { String src = Util.loadFile(templateFile.getAbsolutePath()); Util.writeStringToFile(outFile, src); System.out.println("copied " + outFile); } interface MapSelector { public Map getMap(BundleInfo info); } class BundleInfo { File file; Attributes attribs; Map vars = new TreeMap(); // String (package name) -> ArrayInt (version) Map pkgImportMap = new TreeMap(); Map pkgExportMap = new TreeMap(); Map serviceExportMap = new TreeMap(); Map serviceImportMap = new TreeMap(); String relPath = ""; String path = ""; Map unresolvedMap = new TreeMap(); public BundleInfo(File file) throws IOException { this.file = file; relPath = ""; File dir = file.getParentFile(); while(dir != null && !dir.equals(baseDir)) { // System.out.println("** ! " + dir + " || " + baseDir); relPath += "../"; dir = dir.getParentFile(); } if(dir == null) { throw new BuildException(baseDir.getAbsolutePath() + " is not parent of " + file.getAbsolutePath()); } if(relPath.equals("")) { // relPath = "."; } path = replace(file.getCanonicalPath().substring(1 + baseDir.getCanonicalPath().length()), "\\", "/"); // System.out.println(file + ", " + relPath + ", " + baseDir.getAbsolutePath() + ", path=" + path); } public void load() throws Exception { JarFile jarFile = new JarFile(file); Manifest mf = jarFile.getManifest(); attribs = mf.getMainAttributes(); vars.put("html.file", replace(file.toString(), ".jar", ".html")); String absBase = baseDir.getCanonicalPath(); String htmlFilename = (String)vars.get("html.file"); File htmlFile = new File(htmlFilename); String absFile = htmlFile.getCanonicalPath(); if(!absFile.startsWith(absBase)) { System.out.println("*** base dir is not parent of html file"); System.out.println("base dir: " + absBase); System.out.println("html file: " + absFile); } else { String relPath = absFile.substring(absBase.length() + 1); // System.out.println("absFile=" + absFile); // System.out.println("relPath=" + relPath); vars.put("html.uri", replace(relPath, "\\", "/")); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -