| /******************************************************************************* |
| * 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 = "<init>"; |
| else if (methodName.equals("-clinit-")) |
| methodName = "<clinit>"; |
| StringBuffer sb = new StringBuffer(); |
| sb.append(className); |
| sb.append("#"); |
| sb.append(methodName); |
| sb.append("#"); |
| sb.append(signature); |
| methodRefs.add(sb.toString()); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |