| /******************************************************************************* |
| * Copyright (c) 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.wtp.releng.tools.component.api.progress; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Calendar; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.transform.Transformer; |
| import javax.xml.transform.TransformerConfigurationException; |
| import javax.xml.transform.TransformerException; |
| import javax.xml.transform.TransformerFactory; |
| import javax.xml.transform.stream.StreamResult; |
| import javax.xml.transform.stream.StreamSource; |
| |
| import org.eclipse.wtp.releng.tools.component.CommandOptionParser; |
| import org.eclipse.wtp.releng.tools.component.ILocation; |
| import org.eclipse.wtp.releng.tools.component.internal.AbstractEmitter; |
| import org.eclipse.wtp.releng.tools.component.internal.ComponentXML; |
| import org.eclipse.wtp.releng.tools.component.internal.Description; |
| import org.eclipse.wtp.releng.tools.component.internal.FileLocation; |
| import org.eclipse.wtp.releng.tools.component.internal.Plugin; |
| import org.xml.sax.SAXException; |
| |
| public class APIProgressEmitter extends AbstractEmitter |
| { |
| public static final String OPTION_COMPONENT_INDEX = "compIndex"; |
| public static final String OPTION_REF_COMP_INDEX_DIR = "refCompIndexDir"; |
| public static final String OPTION_ECLIPSE_DIR = "eclipseDir"; |
| public static final String OPTION_COMPONENT_XML = "compXMLDir"; |
| public static final String OPTION_OUTPUT_DIR = "outputDir"; |
| private static final String NAME_INDEX_COMP_SUMMARY = "index-comp-summary.xml"; |
| |
| private String compIndex; |
| private List refCompIndexDirs; |
| private List eclipseDirs; |
| private List compXMLDirs; |
| private String outputDir; |
| |
| public APIProgressEmitter(String compIndex, List refCompIndexDirs, List eclipseDirs, List compXMLDirs, String outputDir) |
| { |
| this.compIndex = compIndex; |
| this.refCompIndexDirs = refCompIndexDirs; |
| this.eclipseDirs = eclipseDirs; |
| this.compXMLDirs = compXMLDirs; |
| this.outputDir = addTrailingSeperator(outputDir); |
| } |
| |
| public void genAPIProgress() throws ParserConfigurationException, SAXException, IOException, TransformerConfigurationException, TransformerException |
| { |
| Map loc2RefCompIndex = new HashMap(); |
| if (refCompIndexDirs != null) |
| { |
| for (Iterator it = refCompIndexDirs.iterator(); it.hasNext();) |
| { |
| File refCompIndexFile = new File(addTrailingSeperator((String)it.next())); |
| if (refCompIndexFile.exists()) |
| harvestCompIndexes(refCompIndexFile, loc2RefCompIndex); |
| } |
| } |
| Map pluginId2Plugin = new HashMap(); |
| Map fragmentId2Fragment = new HashMap(); |
| for (Iterator it = eclipseDirs.iterator(); it.hasNext();) |
| { |
| File eclipseFile = new File(addTrailingSeperator((String)it.next())); |
| if (eclipseFile.exists()) |
| harvestPlugins(eclipseFile, pluginId2Plugin, fragmentId2Fragment); |
| } |
| Map compLoc2CompXML = new HashMap(); |
| for (Iterator it = compXMLDirs.iterator(); it.hasNext();) |
| { |
| File compXMLFile = new File(addTrailingSeperator((String)it.next())); |
| if (compXMLFile.exists()) |
| harvestComponents(compXMLFile, compLoc2CompXML); |
| } |
| APIProgressSummary summary = new APIProgressSummary(); |
| summary.load(new FileLocation(new File(compIndex))); |
| List pluginsDeclared = new ArrayList(); |
| List missingPlugins = new ArrayList(); |
| List dupPlugins = new ArrayList(); |
| for (Iterator it = compLoc2CompXML.values().iterator(); it.hasNext();) |
| { |
| ComponentXML compXML = (ComponentXML)it.next(); |
| compXML.load(); |
| APIProgressEntry entry = (APIProgressEntry)summary.getEntry(compXML.getName()); |
| if (entry != null) |
| { |
| Description desc = compXML.getDescription(); |
| if (desc != null) |
| { |
| entry.setOverviewDoc(desc.getUrl()); |
| } |
| } |
| Collection plugins = compXML.getPlugins(); |
| for (Iterator pluginIt = plugins.iterator(); pluginIt.hasNext();) |
| { |
| Plugin plugin = (Plugin)pluginIt.next(); |
| String pluginId = plugin.getId(); |
| if (pluginsDeclared.contains(pluginId)) |
| { |
| dupPlugins.add(pluginId); |
| } |
| else if (plugin.isFragment()) |
| { |
| if (!fragmentId2Fragment.containsKey(pluginId)) |
| { |
| missingPlugins.add(pluginId); |
| } |
| } |
| else |
| { |
| if (!pluginId2Plugin.containsKey(pluginId)) |
| { |
| missingPlugins.add(pluginId); |
| } |
| } |
| pluginsDeclared.add(pluginId); |
| } |
| } |
| summary.addMissingPlugins(missingPlugins); |
| summary.addDupPlugins(dupPlugins); |
| List pluginsWithoutComp = new ArrayList(); |
| for (Iterator it = pluginId2Plugin.keySet().iterator(); it.hasNext();) |
| { |
| String pluginId = (String)it.next(); |
| if (!hasPlugin(pluginId, false, compLoc2CompXML)) |
| { |
| pluginsWithoutComp.add(pluginId); |
| } |
| } |
| for (Iterator it = fragmentId2Fragment.keySet().iterator(); it.hasNext();) |
| { |
| String fragmentId = (String)it.next(); |
| if (!hasPlugin(fragmentId, true, compLoc2CompXML)) |
| { |
| pluginsWithoutComp.add(fragmentId); |
| } |
| } |
| summary.addPluginsWithoutComp(pluginsWithoutComp); |
| List loaders = new ArrayList(); |
| for (Iterator it = summary.getEntries().iterator(); it.hasNext();) |
| { |
| APIProgressEntry entry = (APIProgressEntry)it.next(); |
| if (entry.getOverviewDoc() == null) |
| { |
| OverviewDocLoader loader = new OverviewDocLoader(entry); |
| loader.start(); |
| loaders.add(loader); |
| } |
| } |
| for (Iterator it = loaders.iterator(); it.hasNext();) |
| { |
| ((OverviewDocLoader)it.next()).waitFor(); |
| } |
| copyImages(); |
| for (Iterator it = summary.getEntries().iterator(); it.hasNext();) |
| genAPIProgress(compIndex, (APIProgressEntry)it.next(), summary.getTimestamp(), loc2RefCompIndex, outputDir); |
| genAPIProgress(compIndex, summary.getTimestamp(), loc2RefCompIndex, outputDir); |
| xslt(summary.toString(), "org/eclipse/wtp/releng/tools/component/xsl/api-progress.xsl", outputDir + "api-progress.html"); |
| } |
| |
| private void genAPIProgress(String baseLocation, APIProgressEntry entry, String timestamp, Map loc2RefCompIndex, String outputDir) |
| { |
| StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); |
| String compName = entry.getCompName(); |
| sb.append("<component name=\""); |
| sb.append(compName); |
| sb.append("\">"); |
| List sortedTimestamps = new ArrayList(); |
| List sortedSummaries = new ArrayList(); |
| for (Iterator it = loc2RefCompIndex.keySet().iterator(); it.hasNext();) |
| { |
| ILocation location = (ILocation)it.next(); |
| String absPath = location.getAbsolutePath(); |
| APIProgressSummary summary = (APIProgressSummary)loc2RefCompIndex.get(location); |
| String summaryTimestamp = summary.getTimestamp(); |
| int insertIndex = sortedTimestamps.size(); |
| try |
| { |
| Integer thisTimestamp = Integer.valueOf(summaryTimestamp); |
| while (insertIndex > 0) |
| { |
| Integer i = (Integer)sortedTimestamps.get(insertIndex - 1); |
| if (thisTimestamp.intValue() > i.intValue()) |
| break; |
| else |
| insertIndex--; |
| } |
| sortedTimestamps.add(insertIndex, thisTimestamp); |
| } |
| catch (NumberFormatException e) |
| { |
| e.printStackTrace(); |
| } |
| sortedSummaries.add(insertIndex, toString(absPath, summaryTimestamp)); |
| } |
| for (Iterator it = sortedSummaries.iterator(); it.hasNext();) |
| sb.append((String)it.next()); |
| sb.append(toString(baseLocation, timestamp)); |
| sb.append("</component>"); |
| try |
| { |
| StringBuffer output = new StringBuffer(outputDir); |
| output.append("svg/"); |
| output.append(compName); |
| output.append(".svg"); |
| xslt(sb.toString(), "org/eclipse/wtp/releng/tools/component/xsl/api-progress-svg.xsl", output.toString()); |
| } |
| catch (Throwable t) |
| { |
| t.printStackTrace(); |
| } |
| } |
| |
| private void genAPIProgress(String baseLocation, String timestamp, Map loc2RefCompIndex, String outputDir) |
| { |
| StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); |
| sb.append("<total>"); |
| List sortedTimestamps = new ArrayList(); |
| List sortedTotals = new ArrayList(); |
| for (Iterator it = loc2RefCompIndex.keySet().iterator(); it.hasNext();) |
| { |
| ILocation location = (ILocation)it.next(); |
| String absPath = location.getAbsolutePath(); |
| APIProgressSummary summary = (APIProgressSummary)loc2RefCompIndex.get(location); |
| String summaryTimestamp = summary.getTimestamp(); |
| int insertIndex = sortedTimestamps.size(); |
| try |
| { |
| Integer thisTimestamp = Integer.valueOf(summaryTimestamp); |
| while (insertIndex > 0) |
| { |
| Integer i = (Integer)sortedTimestamps.get(insertIndex - 1); |
| if (thisTimestamp.intValue() > i.intValue()) |
| break; |
| else |
| insertIndex--; |
| } |
| sortedTimestamps.add(insertIndex, thisTimestamp); |
| } |
| catch (NumberFormatException e) |
| { |
| e.printStackTrace(); |
| } |
| sortedTotals.add(insertIndex, toStringTotal(absPath, summaryTimestamp)); |
| } |
| for (Iterator it = sortedTotals.iterator(); it.hasNext();) |
| sb.append((String)it.next()); |
| sb.append(toStringTotal(baseLocation, timestamp)); |
| sb.append("</total>"); |
| try |
| { |
| StringBuffer output = new StringBuffer(outputDir); |
| output.append("svg/total.svg"); |
| xslt(sb.toString(), "org/eclipse/wtp/releng/tools/component/xsl/api-progress-svg-total.xsl", output.toString()); |
| } |
| catch (Throwable t) |
| { |
| t.printStackTrace(); |
| } |
| } |
| |
| private void xslt(String content, String xsl, String output) throws SAXException, ParserConfigurationException, TransformerConfigurationException, TransformerException, FileNotFoundException |
| { |
| File outputFile = new File(output); |
| outputFile.getParentFile().mkdirs(); |
| xslt(new ByteArrayInputStream(content.getBytes()), xsl, new FileOutputStream(outputFile)); |
| } |
| |
| private void xslt(InputStream is, String xsl, OutputStream os) throws SAXException, ParserConfigurationException, TransformerConfigurationException, TransformerException, FileNotFoundException |
| { |
| String user_dir = "user.dir"; |
| String currUserDir = System.getProperty(user_dir); |
| System.setProperty(user_dir, (new File(compIndex)).getParentFile().getAbsolutePath()); |
| TransformerFactory factory = TransformerFactory.newInstance(); |
| Transformer transformer = factory.newTransformer(new StreamSource(ClassLoader.getSystemResourceAsStream(xsl))); |
| transformer.transform(new StreamSource(is), new StreamResult(os)); |
| System.setProperty(user_dir, currUserDir); |
| } |
| |
| private String toString(String baseLocation, String timestamp) |
| { |
| baseLocation = toAbsolutePath(baseLocation); |
| StringBuffer sb = new StringBuffer("<timestamp id=\""); |
| sb.append(timestamp); |
| sb.append("\">"); |
| sb.append("<testcoverage ref=\""); |
| sb.append(baseLocation + "index-api-tc.xml"); |
| sb.append("\"/>"); |
| sb.append("<javadoccoverage ref=\""); |
| sb.append(baseLocation + "index-api-javadoc.xml"); |
| sb.append("\"/>"); |
| sb.append("</timestamp>"); |
| return sb.toString(); |
| } |
| |
| private String toStringTotal(String baseLocation, String timestamp) |
| { |
| baseLocation = toAbsolutePath(baseLocation); |
| StringBuffer sb = new StringBuffer(); |
| try |
| { |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| xslt(new FileInputStream(baseLocation + "index-api-tc.xml"), "org/eclipse/wtp/releng/tools/component/xsl/component-api-util.xsl", baos); |
| Properties p = new Properties(); |
| p.load(new ByteArrayInputStream(baos.toByteArray())); |
| String apiCount = p.getProperty("api-count"); |
| String testCoverageCount = p.getProperty("test-coverage-count"); |
| |
| baos = new ByteArrayOutputStream(); |
| xslt(new FileInputStream(baseLocation + "index-api-javadoc.xml"), "org/eclipse/wtp/releng/tools/component/xsl/component-api-util.xsl", baos); |
| p = new Properties(); |
| p.load(new ByteArrayInputStream(baos.toByteArray())); |
| String methodApiCount = p.getProperty("method-api-count"); |
| String classJavadocCount = p.getProperty("class-javadoc-count"); |
| String methodJavadocCount = p.getProperty("method-javadoc-count"); |
| |
| sb.append("<timestamp id=\""); |
| sb.append(timestamp); |
| sb.append("\""); |
| sb.append(" api-count=\""); |
| sb.append(apiCount); |
| sb.append("\""); |
| sb.append(" test-coverage-count=\""); |
| sb.append(testCoverageCount); |
| sb.append("\""); |
| sb.append(" method-api-count=\""); |
| sb.append(methodApiCount); |
| sb.append("\""); |
| sb.append(" class-javadoc-count=\""); |
| sb.append(classJavadocCount); |
| sb.append("\""); |
| sb.append(" method-javadoc-count=\""); |
| sb.append(methodJavadocCount); |
| sb.append("\""); |
| sb.append("/>"); |
| } |
| catch (Throwable t) |
| { |
| t.printStackTrace(); |
| } |
| return sb.toString(); |
| } |
| |
| private String toAbsolutePath(String s) |
| { |
| s = s.replace('\\', '/'); |
| int i = s.lastIndexOf('/'); |
| if (i != -1) |
| s = s.substring(0, i); |
| s = addTrailingSeperator(s); |
| return s; |
| } |
| |
| private void harvestCompIndexes(File file, Map loc2RefCompIndex) |
| { |
| if (file.isDirectory()) |
| { |
| File[] files = file.listFiles(); |
| for (int i = 0; i < files.length; i++) |
| harvestCompIndexes(files[i], loc2RefCompIndex); |
| } |
| else if (NAME_INDEX_COMP_SUMMARY.equalsIgnoreCase(file.getName())) |
| { |
| APIProgressSummary summary = new APIProgressSummary(); |
| try |
| { |
| ILocation location = new FileLocation(file); |
| summary.load(location); |
| loc2RefCompIndex.put(location, summary); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| catch (SAXException e) |
| { |
| e.printStackTrace(); |
| } |
| catch (ParserConfigurationException e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| } |
| |
| private boolean hasPlugin(String pluginId, boolean isFragment, Map compLoc2CompXML) |
| { |
| for (Iterator compXMLIt = compLoc2CompXML.values().iterator(); compXMLIt.hasNext();) |
| { |
| ComponentXML compXML = (ComponentXML)compXMLIt.next(); |
| Collection plugins = compXML.getPlugins(); |
| for (Iterator pluginIt = plugins.iterator(); pluginIt.hasNext();) |
| { |
| Plugin plugin = (Plugin)pluginIt.next(); |
| if (pluginId.equals(plugin.getId()) && isFragment == plugin.isFragment()) |
| { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| private void copyImages() |
| { |
| try |
| { |
| copyImage("org/eclipse/wtp/releng/tools/component/images/green.gif", new File(outputDir + "green.gif")); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| try |
| { |
| copyImage("org/eclipse/wtp/releng/tools/component/images/grey.gif", new File(outputDir + "grey.gif")); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| try |
| { |
| copyImage("org/eclipse/wtp/releng/tools/component/images/Idea.jpg", new File(outputDir + "Idea.jpg")); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| try |
| { |
| copyImage("org/eclipse/wtp/releng/tools/component/images/orange.gif", new File(outputDir + "orange.gif")); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| try |
| { |
| copyImage("org/eclipse/wtp/releng/tools/component/images/red.gif", new File(outputDir + "red.gif")); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| try |
| { |
| copyImage("org/eclipse/wtp/releng/tools/component/images/space.gif", new File(outputDir + "space.gif")); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| try |
| { |
| copyImage("org/eclipse/wtp/releng/tools/component/images/yellow.gif", new File(outputDir + "yellow.gif")); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| try |
| { |
| copyImage("org/eclipse/wtp/releng/tools/component/images/twistopened.gif", new File(outputDir + "twistopened.gif")); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| try |
| { |
| copyImage("org/eclipse/wtp/releng/tools/component/images/twistclosed.gif", new File(outputDir + "twistclosed.gif")); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| try |
| { |
| copyImage("org/eclipse/wtp/releng/tools/component/images/viewsvg.gif", new File(outputDir + "viewsvg.gif")); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| |
| public static void main(String[] args) |
| { |
| CommandOptionParser optionParser = new CommandOptionParser(args); |
| Map options = optionParser.getOptions(); |
| List compIndex = (List)options.get(APIProgressEmitter.OPTION_COMPONENT_INDEX); |
| List eclipseDirs = (List)options.get(APIProgressEmitter.OPTION_ECLIPSE_DIR); |
| List compXMLDirs = (List)options.get(APIProgressEmitter.OPTION_COMPONENT_XML); |
| List outputDir = (List)options.get(APIProgressEmitter.OPTION_OUTPUT_DIR); |
| List refCompIndexDirs = (List)options.get(APIProgressEmitter.OPTION_REF_COMP_INDEX_DIR); |
| if (compIndex == null || eclipseDirs == null || compXMLDirs == null || outputDir == null || compIndex.size() < 1 || eclipseDirs.size() < 1 || compXMLDirs.size() < 1 || outputDir.size() < 1) |
| { |
| printUsage(); |
| System.exit(-1); |
| } |
| APIProgressEmitter emitter = new APIProgressEmitter((String)compIndex.get(0), refCompIndexDirs, eclipseDirs, compXMLDirs, (String)outputDir.get(0)); |
| try |
| { |
| emitter.genAPIProgress(); |
| } |
| catch (ParserConfigurationException pce) |
| { |
| pce.printStackTrace(); |
| } |
| catch (SAXException saxe) |
| { |
| saxe.printStackTrace(); |
| } |
| catch (IOException ioe) |
| { |
| ioe.printStackTrace(); |
| } |
| catch (TransformerConfigurationException tce) |
| { |
| tce.printStackTrace(); |
| } |
| catch (TransformerException te) |
| { |
| te.printStackTrace(); |
| } |
| } |
| |
| private static void printUsage() |
| { |
| System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.api.progress.APIProgressEmitter -compIndex <compIndex> -eclipseDir <eclipseDir> -compXMLDir <compXMLDir> -outputDir <outputDir>"); |
| System.out.println(""); |
| System.out.println("\t-compIndex\t<compIndex>\tlocation of index-comp-summary.xml"); |
| System.out.println("\t-eclipseDir\t<eclipseDir>\tspace seperated list of directories containing Eclipse plugins"); |
| System.out.println("\t-compXMLDir\t<compXMLDir>\tspace seperated lits of directories containing component.xml files"); |
| System.out.println("\t-outputDir\t<compXMLDir>\toutput directory of the API progress report"); |
| } |
| |
| private class OverviewDocLoader extends Thread |
| { |
| private APIProgressEntry entry; |
| private boolean done; |
| |
| public OverviewDocLoader(APIProgressEntry entry) |
| { |
| this.entry = entry; |
| this.done = false; |
| } |
| |
| public void run() |
| { |
| try |
| { |
| String compName = entry.getCompName(); |
| String subproject = null; |
| String component = null; |
| if (compName.startsWith("org.eclipse.")) |
| { |
| compName = compName.substring(12); |
| int index = compName.indexOf('.'); |
| if (index != -1) |
| { |
| subproject = compName.substring(0, index); |
| component = compName.substring(index + 1); |
| } |
| } |
| if (subproject != null && component != null) |
| { |
| StringBuffer url = new StringBuffer("http://eclipse.org/webtools/"); |
| url.append(subproject); |
| url.append("/components/"); |
| url.append(component); |
| url.append("/overview.html"); |
| URL overviewDoc = new URL(url.toString()); |
| InputStream is = overviewDoc.openStream(); |
| is.close(); |
| entry.setOverviewDoc(url.toString()); |
| } |
| } |
| catch (Throwable t) |
| { |
| } |
| finally |
| { |
| done = true; |
| } |
| } |
| |
| public void waitFor() |
| { |
| long start = Calendar.getInstance().getTimeInMillis(); |
| while (!done && (Calendar.getInstance().getTimeInMillis() - start) < 60000) |
| Thread.yield(); |
| } |
| } |
| } |