blob: ba89d57cd7f62d8d5f22171bf1b3fce2d7539190 [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.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import org.eclipse.jdt.core.util.IModifierConstants;
import org.eclipse.wtp.releng.tools.component.CommandOptionParser;
import org.eclipse.wtp.releng.tools.component.IClazz;
import org.eclipse.wtp.releng.tools.component.IClazzVisitor;
import org.eclipse.wtp.releng.tools.component.ILocation;
import org.eclipse.wtp.releng.tools.component.IPluginXML;
import org.eclipse.wtp.releng.tools.component.api.ClassAPI;
import org.eclipse.wtp.releng.tools.component.api.ClassUse;
import org.eclipse.wtp.releng.tools.component.api.ComponentAPI;
import org.eclipse.wtp.releng.tools.component.api.ComponentAPIEmitter;
import org.eclipse.wtp.releng.tools.component.api.ComponentUse;
import org.eclipse.wtp.releng.tools.component.api.ComponentUseEmitter;
import org.eclipse.wtp.releng.tools.component.api.MethodAPI;
import org.eclipse.wtp.releng.tools.component.api.MethodUse;
import org.eclipse.wtp.releng.tools.component.api.PackageAPI;
import org.eclipse.wtp.releng.tools.component.api.Source;
import org.eclipse.wtp.releng.tools.component.api.TestCoverage;
import org.eclipse.wtp.releng.tools.component.internal.AbstractEmitter;
import org.eclipse.wtp.releng.tools.component.internal.ComponentEntry;
import org.eclipse.wtp.releng.tools.component.internal.ComponentSummary;
import org.eclipse.wtp.releng.tools.component.internal.ComponentXML;
import org.eclipse.wtp.releng.tools.component.internal.FileLocation;
import org.eclipse.wtp.releng.tools.component.internal.Package;
import org.eclipse.wtp.releng.tools.component.internal.Plugin;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class APITestCoverageEmitter extends AbstractEmitter
{
public static final String OPTION_ECLIPSE_DIR = "eclipseDir";
public static final String OPTION_TEST_DIR = "testDir";
public static final String OPTION_COMPONENT_XML_DIR = "compXMLDir";
public static final String OPTION_COMPONENT_API_DIR = "compAPIDir";
public static final String OPTION_API_AGENT_OUTPUT ="apiAgentOutput";
public static final String OPTION_TIMESTAMP = "timestamp";
public static final String OPTION_GEN_HTML = "genHTML";
private String compAPIDir;
private Map id2Plugin;
private Map id2Fragment;
private Map id2TestPlugin;
private Map id2TestFragment;
private Map compLoc2CompXML;
private String apiAgentOutput;
private List apiAgentMethodrefs;
private String timestamp;
private boolean genHTML;
private ComponentAPIEmitter compAPIEmitter;
public APITestCoverageEmitter(String compAPIDir)
{
this.compAPIDir = addTrailingSeperator(compAPIDir);
genHTML = false;
}
public void init(List eclipseDirs, List testDirs, List compXMLDirs)
{
id2Plugin = new HashMap();
id2Fragment = new HashMap();
for (Iterator it = eclipseDirs.iterator(); it.hasNext();)
{
File eclipseFile = new File(addTrailingSeperator((String)it.next()));
if (eclipseFile.exists())
harvestPlugins(eclipseFile, id2Plugin, id2Fragment);
}
linkPluginsAndFragments(id2Plugin, id2Fragment);
id2TestPlugin = new HashMap();
id2TestFragment = new HashMap();
for (Iterator it = testDirs.iterator(); it.hasNext();)
{
File testFile = new File(addTrailingSeperator((String)it.next()));
if (testFile.exists())
harvestPlugins(testFile, id2TestPlugin, id2TestFragment);
}
linkPluginsAndFragments(id2TestPlugin, id2TestFragment);
compLoc2CompXML = new HashMap();
for (Iterator it = compXMLDirs.iterator(); it.hasNext();)
{
File compXMLFile = new File(addTrailingSeperator((String)it.next()));
if (compXMLFile.exists())
harvestComponents(compXMLFile, compLoc2CompXML);
}
init();
}
public void init(Map compLoc2CompXML, Map id2Plugin, Map id2Fragment, Map id2TestPlugin, Map id2TestFragment)
{
this.compLoc2CompXML = compLoc2CompXML;
this.id2Plugin = id2Plugin;
this.id2Fragment = id2Fragment;
this.id2TestPlugin = id2TestPlugin;
this.id2TestFragment = id2TestFragment;
init();
}
private void init()
{
compAPIEmitter = new ComponentAPIEmitter(null);
if (timestamp != null)
compAPIEmitter.setTimestamp(timestamp);
else
timestamp = compAPIEmitter.getTimestamp();
compAPIEmitter.init(compLoc2CompXML, id2Plugin, id2Fragment);
}
public String getAPIAgentOutput()
{
return apiAgentOutput;
}
public void setAPIAgentOutput(String apiAgentOutput)
{
this.apiAgentOutput = apiAgentOutput;
}
public String getTimestamp()
{
return timestamp;
}
public void setTimestamp(String timestamp)
{
this.timestamp = timestamp;
}
/**
* @return Returns the genHTML.
*/
public boolean isGenHTML()
{
return genHTML;
}
/**
* @param genHTML The genHTML to set.
*/
public void setGenHTML(boolean genHTML)
{
this.genHTML = genHTML;
}
protected String getComponentSummaryXML()
{
return ComponentSummary.INDEX_COMPONENT_SUMMARY_XML;
}
protected String getSummaryXML()
{
return "index-api-tc.xml";
}
protected String getSummaryHTML()
{
return "index-api-tc.html";
}
protected String getSummaryXSL()
{
return "org/eclipse/wtp/releng/tools/component/xsl/component-api-tc-summary.xsl";
}
protected String getCoverageXML()
{
return ComponentAPI.CONST_COMPONENT_API;
}
protected String getCoverageHTML()
{
return "component-api-tc.html";
}
protected String getCoverageXSL()
{
return "org/eclipse/wtp/releng/tools/component/xsl/component-api-tc.xsl";
}
public void genAPITestCoverageXML() throws IOException
{
ComponentSummary compSummary = new ComponentSummary();
APITestCoverageSummary summary = new APITestCoverageSummary(getCoverageHTML());
compSummary.setTimestamp(timestamp);
summary.setTimestamp(timestamp);
List includes = new ArrayList();
for (Iterator it = compLoc2CompXML.values().iterator(); it.hasNext();)
harvestPackages((ComponentXML)it.next(), includes);
ComponentUseEmitter compUseEmitter = newComponentUseEmitter(id2TestPlugin, id2TestFragment, includes);
ComponentUse compUse = compUseEmitter.genAll();
for (Iterator it = compLoc2CompXML.keySet().iterator(); it.hasNext();)
{
String compLoc = (String)it.next();
ComponentAPI compAPI = compAPIEmitter.genComponentApiXml(compLoc);
summary.add(genAPITestCoverageXML(compLoc, compUse, compAPI));
ComponentEntry entry = new ComponentEntry();
entry.setCompName(compAPI.getName());
entry.setRef(compAPI.getLocation().getAbsolutePath());
compSummary.add(entry);
}
if (compAPIDir != null)
{
compSummary.save(new FileLocation(new File(compAPIDir + getComponentSummaryXML())));
summary.save(new FileLocation(new File(compAPIDir + getSummaryXML())));
if (genHTML)
{
try
{
summary.saveAsHTML(getSummaryXSL(), new FileLocation(new File(compAPIDir + getSummaryHTML())));
}
catch (TransformerConfigurationException e)
{
e.printStackTrace();
}
catch (TransformerException e)
{
e.printStackTrace();
}
}
}
}
public ComponentAPI genAPITestCoverageXML(String compLoc) throws IOException
{
List includes = new ArrayList();
ComponentXML componentXML = (ComponentXML)compLoc2CompXML.get(compLoc);
if (componentXML != null)
harvestPackages(componentXML, includes);
ComponentUseEmitter compUseEmitter = newComponentUseEmitter(id2TestPlugin, id2TestFragment, includes);
ComponentUse compUse = compUseEmitter.genAll();
ComponentAPI compAPI = compAPIEmitter.genComponentApiXml(compLoc);
compAPI.save();
return genAPITestCoverageXML(compLoc, compUse, compAPI);
}
private ComponentAPI genAPITestCoverageXML(String compLoc, ComponentUse compUse, ComponentAPI compAPI) throws IOException
{
ComponentXML componentXML = (ComponentXML)compLoc2CompXML.get(compLoc);
if (componentXML != null)
{
componentXML.load();
final Hashtable interface2implClasses = new Hashtable();
if (apiAgentOutput != null)
{
for (Iterator it = componentXML.getPlugins().iterator(); it.hasNext();)
{
String pluginId = ((Plugin)it.next()).getId();
IPluginXML plugin = (IPluginXML)id2Plugin.get(pluginId);
if (plugin != null)
{
plugin.accept
(
new IClazzVisitor()
{
public boolean visit(IClazz clazz)
{
String[] interfaces = clazz.getInterfaces();
for (int i = 0; i < interfaces.length; i++)
{
StringBuffer sb = new StringBuffer();
String implClasses = (String)interface2implClasses.get(interfaces[i]);
if (implClasses != null)
sb.append(implClasses);
sb.append(clazz.getName());
sb.append('#');
interface2implClasses.put(interfaces[i], sb.toString());
}
return true;
}
}
);
}
}
}
for (Iterator it = compAPI.getPackageAPIs().iterator(); it.hasNext();)
{
PackageAPI pkgAPI = (PackageAPI)it.next();
for (Iterator it2 = pkgAPI.getClassAPIs().iterator(); it2.hasNext();)
{
ClassAPI classAPI = (ClassAPI)it2.next();
int classAccess = classAPI.getAccess();
if ((isBit(classAccess, IModifierConstants.ACC_PUBLIC) || isBit(classAccess, IModifierConstants.ACC_PROTECTED)) && classAPI.isReference())
{
for (Iterator it3 = classAPI.getMethodAPIs().iterator(); it3.hasNext();)
{
MethodAPI methodAPI = (MethodAPI)it3.next();
methodAPI.setTestCoverage(getTestCoverage(compUse, classAPI.getName(), methodAPI, interface2implClasses));
}
}
}
}
if (compAPIDir != null)
{
String compName = componentXML.getName();
StringBuffer sb = new StringBuffer(compAPIDir);
sb.append(compName);
sb.append('/');
ILocation location = new FileLocation(new File(sb.toString() + getCoverageXML()));
compAPI.setLocation(location);
System.out.println("Writing " + getCoverageXML() + " for " + compName);
compAPI.save();
if (genHTML)
{
try
{
ILocation html = new FileLocation(new File(sb.toString() + getCoverageHTML()));
compAPI.saveAsHTML(html, getCoverageXSL());
copyImages();
}
catch (TransformerConfigurationException e)
{
e.printStackTrace();
}
catch (TransformerException e)
{
e.printStackTrace();
}
}
}
}
return compAPI;
}
private void harvestPackages(ComponentXML compXML, List includes) throws IOException
{
compXML.load();
Collection pkgs = compXML.getPackages();
for (Iterator it = pkgs.iterator(); it.hasNext();)
{
String pkgName = ((Package)it.next()).getName();
if (!includes.contains(pkgName))
includes.add(pkgName);
}
}
private ComponentUseEmitter newComponentUseEmitter(Map plugins, Map fragments, List includes)
{
ComponentUseEmitter compUseEmitter = new ComponentUseEmitter(null);
compUseEmitter.setDebug(false);
compUseEmitter.setClassUseIncludes(includes);
compUseEmitter.init(new HashMap(0), plugins, fragments);
return compUseEmitter;
}
private boolean isBit(int flag, int bit)
{
return ((flag & bit) == bit);
}
private TestCoverage getTestCoverage(ComponentUse compUse, String className, MethodAPI methodAPI, Hashtable interface2implClasses)
{
List testcases = new ArrayList();
for (Iterator sourcesIt = compUse.getSources().iterator(); sourcesIt.hasNext();)
{
Source source = (Source)sourcesIt.next();
for (Iterator classUsesIt = source.getClassUses().iterator(); classUsesIt.hasNext();)
{
ClassUse classUse = (ClassUse)classUsesIt.next();
if (classUse.getName().equals(className))
{
for (Iterator methodUsesIt = classUse.getMethodUses().iterator(); methodUsesIt.hasNext();)
{
MethodUse methodUse = (MethodUse)methodUsesIt.next();
if (methodUse.getName().equals(methodAPI.getName()) && methodUse.getDescriptor().equals(methodAPI.getDescriptor()))
{
testcases.add(source.getName());
}
}
}
}
}
if (apiAgentOutput != null)
{
if (apiAgentMethodrefs == null)
{
apiAgentMethodrefs = new ArrayList();
getAPIAgentMethodRefs(new File(apiAgentOutput), apiAgentMethodrefs);
}
StringBuffer methodref = new StringBuffer();
methodref.append('#');
methodref.append(methodAPI.getName());
methodref.append('#');
methodref.append(methodAPI.getDescriptor());
if (apiAgentMethodrefs.contains(className + methodref.toString()))
testcases.add("apiagent");
String implClasses = (String)interface2implClasses.get(className);
if (implClasses != null)
{
StringTokenizer st = new StringTokenizer(implClasses, "#");
while (st.hasMoreTokens())
if (apiAgentMethodrefs.contains(st.nextToken() + methodref.toString()))
testcases.add("apiagent");
}
}
if (testcases.size() > 0)
{
TestCoverage testCoverage = new TestCoverage();
testCoverage.addTests(testcases);
return testCoverage;
}
else
return null;
}
private void getAPIAgentMethodRefs(File file, List apiAgentMethodRefs)
{
if (file.exists())
{
if (file.isDirectory())
{
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++)
getAPIAgentMethodRefs(files[i], apiAgentMethodRefs);
}
else if (file.getName().endsWith(".trcxml"))
{
try
{
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(false);
factory.setValidating(false);
SAXParser parser = factory.newSAXParser();
parser.parse(new InputSource(new BufferedInputStream(new FileInputStream(file))), new TRCXMLHandler(apiAgentMethodRefs));
}
catch (ParserConfigurationException pce)
{
pce.printStackTrace();
}
catch (SAXException saxe)
{
saxe.printStackTrace();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
}
private void copyImages()
{
StringBuffer outputDir = new StringBuffer(compAPIDir).append('/');
File ok = new File(outputDir.toString() + "OK.gif");
if (!ok.exists())
{
try
{
copyImage("org/eclipse/wtp/releng/tools/component/images/OK.gif", ok);
}
catch (IOException e)
{
e.printStackTrace();
}
}
File fail = new File(outputDir.toString() + "FAIL.gif");
if (!fail.exists())
{
try
{
copyImage("org/eclipse/wtp/releng/tools/component/images/FAIL.gif", fail);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
CommandOptionParser optionParser = new CommandOptionParser(args);
Map options = optionParser.getOptions();
List eclipseDir = (List)options.get(APITestCoverageEmitter.OPTION_ECLIPSE_DIR);
List testDir = (List)options.get(APITestCoverageEmitter.OPTION_TEST_DIR);
List compXMLDir = (List)options.get(APITestCoverageEmitter.OPTION_COMPONENT_XML_DIR);
List compAPIDir = (List)options.get(APITestCoverageEmitter.OPTION_COMPONENT_API_DIR);
List apiAgentOutput = (List)options.get(APITestCoverageEmitter.OPTION_API_AGENT_OUTPUT);
List timestamp = (List)options.get(APITestCoverageEmitter.OPTION_TIMESTAMP);
List genHTML = (List)options.get(APITestCoverageEmitter.OPTION_GEN_HTML);
if (eclipseDir == null || testDir == null || compXMLDir == null || compAPIDir == null || eclipseDir.size() < 1 || testDir.size() < 1 || compXMLDir.size() < 1 || compAPIDir.size() < 1)
{
printUsage();
System.exit(-1);
}
APITestCoverageEmitter apiTestCoverageEmitter = new APITestCoverageEmitter((String)compAPIDir.get(0));
if (apiAgentOutput != null && apiAgentOutput.size() > 0)
apiTestCoverageEmitter.setAPIAgentOutput((String)apiAgentOutput.get(0));
if (timestamp != null && timestamp.size() > 0)
apiTestCoverageEmitter.setTimestamp((String)timestamp.get(0));
apiTestCoverageEmitter.setGenHTML(genHTML != null);
apiTestCoverageEmitter.init(eclipseDir, testDir, compXMLDir);
try
{
apiTestCoverageEmitter.genAPITestCoverageXML();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
private static void printUsage()
{
System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.api.testcoverage.APITestCoverageEmitter -eclipseDir <eclipseDir> -testDir <testDir> -compXMLDir <compXMLDir> -compAPIDir <compAPIDir> [-options]");
System.out.println("");
System.out.println("\t-eclipseDir\t<eclipseDir>\tspace seperated list of directories containing Eclipse plugins");
System.out.println("\t-testDir\t<testDir>\tspace separated list of directories containing test plugins");
System.out.println("\t-compXMLDir\t<compXMLDir>\tdirectories containing component.xml that will be checked for API test coverage");
System.out.println("\t-compAPIDir\t<compVioDir>\toutput directory of component-api-tc.xml");
System.out.println("");
System.out.println("where options include:");
System.out.println("");
System.out.println("\t-apiAgentOutput\tdirectory containing output from the PI Agent");
System.out.println("\t-timestamp\ttimestamp");
System.out.println("\t-genHTML\tgenerate test coverage report in HTML");
}
private class TRCXMLHandler extends DefaultHandler
{
private Map classRefs;
private List methodRefs;
public TRCXMLHandler(List methodRefs)
{
this.classRefs = new HashMap();
this.methodRefs = methodRefs;
}
public void startElement(String uri, String elementName, String qName, Attributes attributes) throws SAXException
{
if (elementName.equals("classDef") || qName.equals("classDef"))
{
String id = attributes.getValue("classId");
String name = attributes.getValue("name");
if (id != null && name != null)
{
classRefs.put(id, name);
}
}
else if (elementName.equals("methodDef") || qName.equals("methodDef"))
{
String classId = attributes.getValue("classIdRef");
if (classId != null)
{
String className = (String)classRefs.get(classId);
if (className != null)
{
String methodName = attributes.getValue("name");
String signature = attributes.getValue("signature");
if (methodName != null & signature != null)
{
if (methodName.equals("-init-"))
methodName = "&lt;init>";
else if (methodName.equals("-clinit-"))
methodName = "&lt;clinit>";
StringBuffer sb = new StringBuffer();
sb.append(className);
sb.append("#");
sb.append(methodName);
sb.append("#");
sb.append(signature);
methodRefs.add(sb.toString());
}
}
}
}
}
}
}