blob: 2c7fb8418bb325fbc33bde3e8d008116a9f442cf [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.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)));
}
}
}
}
}