| /******************************************************************************* |
| * 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.compatibility; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| 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.wtp.releng.tools.component.CommandOptionParser; |
| import org.eclipse.wtp.releng.tools.component.ILocation; |
| import org.eclipse.wtp.releng.tools.component.api.ClassAPI; |
| import org.eclipse.wtp.releng.tools.component.api.ComponentAPI; |
| import org.eclipse.wtp.releng.tools.component.api.FieldAPI; |
| import org.eclipse.wtp.releng.tools.component.api.MethodAPI; |
| import org.eclipse.wtp.releng.tools.component.api.PackageAPI; |
| import org.eclipse.wtp.releng.tools.component.internal.AbstractEmitter; |
| import org.eclipse.wtp.releng.tools.component.internal.FileLocation; |
| import org.eclipse.wtp.releng.tools.component.internal.URLLocation; |
| import org.xml.sax.Attributes; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| public class APICompatibilityEmitter extends AbstractEmitter |
| { |
| public static final String CONST_COMPONENT_API_COMPATIBILITY_XML = "api-compatibility.xml"; |
| public static final String CONST_COMPONENT_API_COMPATIBILITY_HTML = "api-compatibility.html"; |
| public static final String OPTION_CURR_API_INDEX = "currAPIIndex"; |
| public static final String OPTION_REF_API_INDEX = "refAPIIndex"; |
| public static final String OPTION_OUTPUT_DIR = "outputDir"; |
| public static final String OPTION_GEN_HTML = "genHTML"; |
| |
| private String currAPIIndex; |
| private String refAPIIndex; |
| private String outputDir; |
| private boolean genHTML; |
| private Map currName2Loc; |
| private Map refName2Loc; |
| |
| public APICompatibilityEmitter(String currAPIIndex, String refAPIIndex, String outputDir) |
| { |
| this.currAPIIndex = currAPIIndex; |
| this.refAPIIndex = refAPIIndex; |
| this.outputDir = addTrailingSeperator(outputDir); |
| genHTML = false; |
| } |
| |
| public void init() |
| { |
| currName2Loc = new HashMap(); |
| harvestComponentLocations(currAPIIndex, currName2Loc); |
| refName2Loc = new HashMap(); |
| harvestComponentLocations(refAPIIndex, refName2Loc); |
| } |
| |
| private void harvestComponentLocations(String index, Map compName2Loc) |
| { |
| File file = new File(index); |
| if (file.exists()) |
| { |
| try |
| { |
| harvestComponentLocations(index, false, compName2Loc, new FileInputStream(file)); |
| } |
| catch (FileNotFoundException e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| else |
| { |
| try |
| { |
| URL url = new URL(index); |
| try |
| { |
| harvestComponentLocations(index, true, compName2Loc, url.openStream()); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| catch (MalformedURLException e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| } |
| |
| private void harvestComponentLocations(String index, boolean isURL, Map compName2Loc, InputStream is) |
| { |
| SAXParser saxParser = null; |
| try |
| { |
| SAXParserFactory factory = SAXParserFactory.newInstance(); |
| factory.setNamespaceAware(false); |
| factory.setValidating(false); |
| saxParser = factory.newSAXParser(); |
| } |
| catch (ParserConfigurationException e) |
| { |
| e.printStackTrace(); |
| } |
| catch (SAXException e) |
| { |
| e.printStackTrace(); |
| } |
| if (saxParser != null) |
| { |
| try |
| { |
| saxParser.parse(new InputSource(is), new ComponentSummaryHandler(index, isURL, compName2Loc)); |
| } |
| catch (SAXException e) |
| { |
| e.printStackTrace(); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| finally |
| { |
| if (is != null) |
| { |
| try |
| { |
| is.close(); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * @return Returns the genHTML. |
| */ |
| public boolean isGenHTML() |
| { |
| return genHTML; |
| } |
| |
| /** |
| * @param genHTML The genHTML to set. |
| */ |
| public void setGenHTML(boolean genHTML) |
| { |
| this.genHTML = genHTML; |
| } |
| |
| public void genAPICompatibilityXML() throws IOException |
| { |
| APICompatibilitySummary summary = new APICompatibilitySummary(); |
| List compNames = new ArrayList(currName2Loc.keySet()); |
| for (Iterator it = compNames.iterator(); it.hasNext();) |
| { |
| boolean gen = true; |
| String compName = (String)it.next(); |
| ILocation currCompLoc = (ILocation)currName2Loc.get(compName); |
| ILocation refCompLoc = (ILocation)refName2Loc.get(compName); |
| ComponentAPI currCompAPI = null; |
| if (currCompLoc != null) |
| { |
| try |
| { |
| currCompAPI = new ComponentAPI(); |
| currCompAPI.setLocation(currCompLoc); |
| currCompAPI.load(); |
| } |
| catch (Throwable t) |
| { |
| gen = false; |
| t.printStackTrace(); |
| } |
| } |
| ComponentAPI refCompAPI = null; |
| if (refCompLoc != null) |
| { |
| try |
| { |
| refCompAPI = new ComponentAPI(); |
| refCompAPI.setLocation(refCompLoc); |
| refCompAPI.load(); |
| } |
| catch (Throwable t) |
| { |
| gen = false; |
| t.printStackTrace(); |
| } |
| } |
| if (gen && currCompAPI != null && refCompAPI != null) |
| { |
| summary.add(genAPICompatibilityXML(currCompAPI, refCompAPI)); |
| currName2Loc.remove(compName); |
| refName2Loc.remove(compName); |
| } |
| } |
| for (Iterator it = currName2Loc.keySet().iterator(); it.hasNext();) |
| { |
| String compName = (String)it.next(); |
| APICompatibility apiCompatibility = saveAPICompatibility(compName, (ILocation)currName2Loc.get(compName), true); |
| if (apiCompatibility != null) |
| summary.add(apiCompatibility); |
| } |
| for (Iterator it = refName2Loc.keySet().iterator(); it.hasNext();) |
| { |
| String compName = (String)it.next(); |
| APICompatibility apiCompatibility = saveAPICompatibility(compName, (ILocation)refName2Loc.get(compName), false); |
| if (apiCompatibility != null) |
| summary.add(apiCompatibility); |
| } |
| if (outputDir != null) |
| { |
| summary.save(new FileLocation(new File(outputDir + "index-api-compatibility.xml"))); |
| if (genHTML) |
| { |
| try |
| { |
| summary.saveAsHTML(new FileLocation(new File(outputDir + "index-api-compatibility.html"))); |
| } |
| catch (TransformerConfigurationException e) |
| { |
| e.printStackTrace(); |
| } |
| catch (TransformerException e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |
| |
| private APICompatibility genAPICompatibilityXML(ComponentAPI currCompAPI, ComponentAPI refCompAPI) throws IOException |
| { |
| APICompatibility apiCompatibility = new APICompatibility(); |
| String compName = currCompAPI.getName(); |
| apiCompatibility.setName(compName); |
| List currPkgAPIs = new ArrayList(currCompAPI.getPackageAPIs()); |
| List refPkgAPIs = new ArrayList(refCompAPI.getPackageAPIs()); |
| for (int i = 0; i < currPkgAPIs.size(); i++) |
| { |
| PackageAPI currPkgAPI = (PackageAPI)currPkgAPIs.get(i); |
| for (int j = 0; j < refPkgAPIs.size(); j++) |
| { |
| PackageAPI refPkgAPI = (PackageAPI)refPkgAPIs.get(j); |
| if (currPkgAPI.getName().equals(refPkgAPI.getName())) |
| { |
| genAPICompatibilityXML(apiCompatibility, currPkgAPI, refPkgAPI); |
| currPkgAPIs.remove(i); |
| refPkgAPIs.remove(j); |
| i--; |
| j--; |
| break; |
| } |
| } |
| } |
| /* |
| for (Iterator it = currPkgAPIs.iterator(); it.hasNext();) |
| for (Iterator it2 = ((PackageAPI)it.next()).getClassAPIs().iterator(); it2.hasNext();) |
| apiCompatibility.addNewAPI((ClassAPI)it2.next()); |
| for (Iterator it = refPkgAPIs.iterator(); it.hasNext();) |
| for (Iterator it2 = ((PackageAPI)it.next()).getClassAPIs().iterator(); it2.hasNext();) |
| apiCompatibility.addRemovedAPI((ClassAPI)it2.next()); |
| */ |
| if (outputDir != null) |
| { |
| apiCompatibility.setLocation(getAPICompatibilityLocation(compName, true)); |
| System.out.println("Writing api-compatibility.xml for " + compName); |
| apiCompatibility.save(); |
| if (genHTML) |
| { |
| try |
| { |
| ILocation html = getAPICompatibilityLocation(compName, false); |
| apiCompatibility.saveAsHTML(html, "org/eclipse/wtp/releng/tools/component/xsl/api-compatibility.xsl"); |
| } |
| catch (TransformerConfigurationException e) |
| { |
| e.printStackTrace(); |
| } |
| catch (TransformerException e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| } |
| return apiCompatibility; |
| } |
| |
| private void genAPICompatibilityXML(APICompatibility apiCompatibility, PackageAPI currPkgAPI, PackageAPI refPkgAPI) |
| { |
| List currClassAPIs = new ArrayList(currPkgAPI.getClassAPIs()); |
| List refClassAPIs = new ArrayList(refPkgAPI.getClassAPIs()); |
| for (int i = 0; i < currClassAPIs.size(); i++) |
| { |
| ClassAPI currClassAPI = (ClassAPI)currClassAPIs.get(i); |
| for (int j = 0; j < refClassAPIs.size(); j++) |
| { |
| ClassAPI refClassAPI = (ClassAPI)refClassAPIs.get(j); |
| if (currClassAPI.getName().equals(refClassAPI.getName())) |
| { |
| genAPICompatibilityXML(apiCompatibility, currClassAPI, refClassAPI); |
| currClassAPIs.remove(i); |
| refClassAPIs.remove(j); |
| i--; |
| j--; |
| break; |
| } |
| } |
| } |
| /* |
| for (Iterator it = currClassAPIs.iterator(); it.hasNext();) |
| apiCompatibility.addNewAPI((ClassAPI)it.next()); |
| for (Iterator it = refClassAPIs.iterator(); it.hasNext();) |
| apiCompatibility.addRemovedAPI((ClassAPI)it.next()); |
| */ |
| } |
| |
| private void genAPICompatibilityXML(APICompatibility apiCompatibility, ClassAPI currClassAPI, ClassAPI refClassAPI) |
| { |
| List currMethodAPIs = new ArrayList(currClassAPI.getMethodAPIs()); |
| List refMethodAPIs = new ArrayList(refClassAPI.getMethodAPIs()); |
| for (int i = 0; i < currMethodAPIs.size(); i++) |
| { |
| MethodAPI currMethodAPI = (MethodAPI)currMethodAPIs.get(i); |
| for (int j = 0; j < refMethodAPIs.size(); j++) |
| { |
| MethodAPI refMethodAPI = (MethodAPI)refMethodAPIs.get(j); |
| if (currMethodAPI.getName().equals(refMethodAPI.getName()) && currMethodAPI.getDescriptor().equals(refMethodAPI.getDescriptor())) |
| { |
| currMethodAPIs.remove(i); |
| refMethodAPIs.remove(j); |
| i--; |
| j--; |
| break; |
| } |
| } |
| } |
| List currFieldAPIs = new ArrayList(currClassAPI.getFieldAPIs()); |
| List refFieldAPIs = new ArrayList(refClassAPI.getFieldAPIs()); |
| for (int i = 0; i < currFieldAPIs.size(); i++) |
| { |
| FieldAPI currFieldAPI = (FieldAPI)currFieldAPIs.get(i); |
| for (int j = 0; j < refFieldAPIs.size(); j++) |
| { |
| FieldAPI refFieldAPI = (FieldAPI)refFieldAPIs.get(j); |
| if (currFieldAPI.getName().equals(refFieldAPI.getName()) && currFieldAPI.getDescriptor().equals(refFieldAPI.getDescriptor())) |
| { |
| currFieldAPIs.remove(i); |
| refFieldAPIs.remove(j); |
| i--; |
| j--; |
| break; |
| } |
| } |
| } |
| /* |
| if (currMethodAPIs.size() != 0 || currFieldAPIs.size() != 0) |
| apiCompatibility.addNewAPI(currClassAPI); |
| if (refMethodAPIs.size() != 0 || refFieldAPIs.size() != 0) |
| apiCompatibility.addRemovedAPI(refClassAPI); |
| */ |
| } |
| |
| private ILocation getAPICompatibilityLocation(String compName, boolean isXML) |
| { |
| if (outputDir != null) |
| { |
| StringBuffer sb = new StringBuffer(outputDir); |
| sb.append(compName); |
| sb.append('/'); |
| if (isXML) |
| return new FileLocation(new File(sb.toString() + CONST_COMPONENT_API_COMPATIBILITY_XML)); |
| else |
| return new FileLocation(new File(sb.toString() + CONST_COMPONENT_API_COMPATIBILITY_HTML)); |
| } |
| else |
| return null; |
| } |
| |
| private APICompatibility saveAPICompatibility(String compName, ILocation compLoc, boolean isNewAPI) |
| { |
| try |
| { |
| APICompatibility apiCompatibility = new APICompatibility(); |
| apiCompatibility.setName(compName); |
| apiCompatibility.setLocation(getAPICompatibilityLocation(compName, true)); |
| ComponentAPI compAPI = new ComponentAPI(); |
| compAPI.setLocation(compLoc); |
| compAPI.load(); |
| /* |
| for (Iterator it = compAPI.getPackageAPIs().iterator(); it.hasNext();) |
| for (Iterator it2 = ((PackageAPI)it.next()).getClassAPIs().iterator(); it2.hasNext();) |
| if (isNewAPI) |
| apiCompatibility.addNewAPI((ClassAPI)it2.next()); |
| else |
| apiCompatibility.addRemovedAPI((ClassAPI)it2.next()); |
| */ |
| apiCompatibility.save(); |
| if (genHTML) |
| { |
| try |
| { |
| ILocation html = getAPICompatibilityLocation(compName, false); |
| apiCompatibility.saveAsHTML(html, "org/eclipse/wtp/releng/tools/component/xsl/api-compatibility.xsl"); |
| } |
| catch (TransformerConfigurationException e) |
| { |
| e.printStackTrace(); |
| } |
| catch (TransformerException e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| return apiCompatibility; |
| } |
| catch (Throwable t) |
| { |
| t.printStackTrace(); |
| return null; |
| } |
| } |
| |
| public static void main(String[] args) |
| { |
| CommandOptionParser optionParser = new CommandOptionParser(args); |
| Map options = optionParser.getOptions(); |
| List currAPIIndex = (List)options.get(APICompatibilityEmitter.OPTION_CURR_API_INDEX); |
| List refAPIIndex = (List)options.get(APICompatibilityEmitter.OPTION_REF_API_INDEX); |
| List outputDir = (List)options.get(APICompatibilityEmitter.OPTION_OUTPUT_DIR); |
| List genHTML = (List)options.get(APICompatibilityEmitter.OPTION_GEN_HTML); |
| if (currAPIIndex == null || refAPIIndex == null || outputDir == null || currAPIIndex.size() < 1 || refAPIIndex.size() < 1 || outputDir.size() < 1) |
| { |
| printUsage(); |
| System.exit(-1); |
| } |
| APICompatibilityEmitter apiCompatibilityEmitter = new APICompatibilityEmitter((String)currAPIIndex.get(0), (String)refAPIIndex.get(0), (String)outputDir.get(0)); |
| apiCompatibilityEmitter.setGenHTML(genHTML != null); |
| apiCompatibilityEmitter.init(); |
| try |
| { |
| apiCompatibilityEmitter.genAPICompatibilityXML(); |
| } |
| catch (IOException ioe) |
| { |
| ioe.printStackTrace(); |
| } |
| } |
| |
| private static void printUsage() |
| { |
| System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.api.compatibility.APICompatibilityEmitter -currAPIDir <currAPIDir> -refAPIDir <refAPIDir> -outputDir <outputDir> [-options]"); |
| System.out.println(""); |
| System.out.println("\t-currAPIIndex\t<eclipseDir>\tlocation of the current component API summary"); |
| System.out.println("\t-refAPIIndex\t<compXMLDir>\tlocation of the reference component API summary"); |
| System.out.println("\t-outputDir\t<outputDir>\toutput directory of component-api-compatibility.xml and component-api-compatibility.html"); |
| System.out.println(""); |
| System.out.println("where options include:"); |
| System.out.println(""); |
| System.out.println("\t-genHTML\tgenerate API compatibility report in HTML"); |
| } |
| |
| private class ComponentSummaryHandler extends DefaultHandler |
| { |
| private String baseLocation; |
| private boolean isURL; |
| private Map compName2Loc; |
| |
| public ComponentSummaryHandler(String baseLocation, boolean isURL, Map compName2Loc) |
| { |
| this.baseLocation = baseLocation.replace('\\', '/'); |
| int i = this.baseLocation.lastIndexOf('/'); |
| if (i != -1) |
| this.baseLocation = this.baseLocation.substring(0, i + 1); |
| this.isURL = isURL; |
| this.compName2Loc = compName2Loc; |
| } |
| |
| public void startElement(String uri, String elementName, String qName, Attributes attributes) throws SAXException |
| { |
| if (elementName.equals("component") || qName.equals("component")) |
| { |
| String compName = attributes.getValue("name"); |
| String ref = attributes.getValue("ref"); |
| if (compName != null && ref != null) |
| { |
| if (isURL) |
| { |
| try |
| { |
| compName2Loc.put(compName, new URLLocation(new URL(baseLocation + ref))); |
| } |
| catch (MalformedURLException e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| else |
| compName2Loc.put(compName, new FileLocation(new File(baseLocation + ref))); |
| } |
| } |
| } |
| } |
| } |