blob: ea6f8f9c360a78294231a560e1689d702b5c52e8 [file] [log] [blame]
/*******************************************************************************
* 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();
}
}
}