blob: 75e6201a400841af9bfa591c73fed3f471af7acb [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.adopters;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.eclipse.jdt.core.util.ClassFormatException;
import org.eclipse.jdt.core.util.IClassFileReader;
import org.eclipse.jdt.internal.core.util.ClassFileReader;
import org.eclipse.wtp.releng.tools.component.IFileLocation;
import org.eclipse.wtp.releng.tools.component.ILocation;
import org.eclipse.wtp.releng.tools.component.ILocationChildrenIterator;
import org.eclipse.wtp.releng.tools.component.ILocationVisitor;
import org.eclipse.wtp.releng.tools.component.IZipLocation;
import org.eclipse.wtp.releng.tools.component.classes.IClassVisitor;
import org.eclipse.wtp.releng.tools.component.internal.Bundle;
import org.eclipse.wtp.releng.tools.component.internal.FileLocation;
import org.eclipse.wtp.releng.tools.component.internal.Location;
import org.eclipse.wtp.releng.tools.component.java.Java2API;
import org.eclipse.wtp.releng.tools.component.model.ComponentDepends;
import org.eclipse.wtp.releng.tools.component.model.ComponentXML;
import org.eclipse.wtp.releng.tools.component.model.Package;
import org.eclipse.wtp.releng.tools.component.model.Plugin;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class Plugin2API implements ILocationVisitor, IClassVisitor
{
private Collection src;
private String outputDir;
private Map lib2pluginId;
private boolean visitPlugins;
private List visitedPlugins;
public Plugin2API()
{
this.lib2pluginId = new HashMap();
}
public String getOutputDir()
{
return outputDir;
}
public void setOutputDir(String outputDir)
{
this.outputDir = addTrailingSeperator(outputDir);
}
public Collection getSrc()
{
return src;
}
public void setSrc(String src)
{
this.src = new ArrayList(1);
this.src.add(src);
}
public void setSrc(Collection src)
{
this.src = src;
}
public void execute()
{
Java2API java2API = new Java2API();
java2API.setOutputDir(outputDir);
java2API.setDefaultExclusive(false);
for (Iterator it = src.iterator(); it.hasNext();)
{
java2API.setSrc((String)it.next());
java2API.execute();
}
visitedPlugins = java2API.getVisitedPlugins();
for (Iterator it = src.iterator(); it.hasNext();)
{
visitPlugins = true;
ILocation srcLocation = Location.createLocation(new File((String)it.next()));
srcLocation.accept(this);
visitPlugins = false;
srcLocation.accept(this);
}
}
public boolean visit(String pluginId, ILocation classLoc)
{
try
{
IClassFileReader reader = read(classLoc);
String className = new String(reader.getClassName()).replace('/', '.');
int i = className.lastIndexOf('.');
String pkgName = i != -1 ? className.substring(0, i) : "";
ComponentXML compXML = getComponentXML(pluginId);
if (compXML.getPackage(pkgName) == null)
{
Package pkg = new Package();
pkg.setName(pkgName);
pkg.setApi(Boolean.TRUE);
pkg.setExclusive(Boolean.FALSE);
compXML.addPackage(pkg);
}
}
catch (IOException ioe)
{
throw new RuntimeException(ioe);
}
catch (ClassFormatException cfe)
{
throw new RuntimeException(cfe);
}
return true;
}
private IClassFileReader read(ILocation classLoc) throws IOException, ClassFormatException
{
InputStream is = null;
ByteArrayOutputStream baos = null;
try
{
byte[] b = new byte[8192];
baos = new ByteArrayOutputStream(8192);
is = classLoc.getInputStream();
for (int read = is.read(b); read != -1; read = is.read(b))
{
baos.write(b, 0, read);
}
is.close();
baos.close();
return new ClassFileReader(baos.toByteArray(), IClassFileReader.CONSTANT_POOL | IClassFileReader.METHOD_INFOS | IClassFileReader.METHOD_BODIES | IClassFileReader.FIELD_INFOS | IClassFileReader.SUPER_INTERFACES);
}
finally
{
if (is != null)
{
try
{
is.close();
}
catch (IOException e)
{
}
}
if (baos != null)
{
try
{
baos.close();
}
catch (IOException e)
{
}
}
}
}
private ComponentXML cachedCompXML;
private ComponentXML getComponentXML(String id) throws IOException
{
if (cachedCompXML != null)
{
if (cachedCompXML.getName().equals(id))
{
return cachedCompXML;
}
else
{
cachedCompXML.save();
}
}
StringBuffer sb = new StringBuffer(outputDir);
sb.append(id);
sb.append("/component.xml");
File file = new File(sb.toString());
cachedCompXML = new ComponentXML();
cachedCompXML.setName(id);
cachedCompXML.setLocation(new FileLocation(file));
Plugin plugin = new Plugin();
plugin.setId(id);
cachedCompXML.addPlugin(plugin);
ComponentDepends compDepends = new ComponentDepends();
compDepends.setUnrestricted(Boolean.TRUE);
cachedCompXML.setComponentDepends(compDepends);
if (file.exists())
cachedCompXML.load();
return cachedCompXML;
}
public boolean accept(ILocation location)
{
String locationName = location.getName();
if (visitPlugins)
{
if (locationName.endsWith("plugin.xml"))
{
acceptPluginXML(location);
}
else if (locationName.endsWith("fragment.xml"))
{
acceptFragmentXML(location);
}
else if (locationName.endsWith("MANIFEST.MF"))
{
acceptManifest(location);
}
else if (Location.isArchive(locationName))
{
return acceptSingleJar(location);
}
else if (locationName.endsWith(".classpath"))
{
acceptDotClasspath(location);
}
}
else
{
String idTemp = (String)lib2pluginId.get(locationName.replace('\\', '/'));
if (idTemp == null)
idTemp = (String)lib2pluginId.get(location.getAbsolutePath().replace('\\', '/'));
final String id = idTemp;
if (id != null)
{
location.accept
(
new ILocationVisitor()
{
public boolean accept(ILocation location)
{
if (location.getName().endsWith(".class"))
visit(id, location);
return true;
}
}
);
/*
ILocationChildrenIterator it = location.childIterator();
for (ILocation child = it.next(); child != null; child = it.next())
{
if (child.getName().endsWith(".class"))
{
classVisitor.visit(id, child);
}
}
*/
}
}
if (location instanceof IZipLocation)
return true;
else if ((location instanceof IFileLocation) && ((IFileLocation)location).getFile().isDirectory())
return true;
else
return false;
}
private void acceptPluginXML(ILocation location)
{
String locationName = location.getName();
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(location.getInputStream());
Element root = doc.getDocumentElement();
if (root.getTagName().equals("plugin"))
{
String pluginId = root.getAttribute("id");
if (pluginId != null && pluginId.length() > 0 && !visitedPlugins.contains(pluginId))
{
NodeList runtimes = root.getElementsByTagName("runtime");
for (int i = 0; i < runtimes.getLength(); i++)
{
Element runtime = (Element)runtimes.item(i);
NodeList libraries = runtime.getElementsByTagName("library");
for (int j = 0; j < libraries.getLength(); j++)
{
Element library = (Element)libraries.item(j);
String path = library.getAttribute("name");
if (path != null && path.length() > 0)
{
StringBuffer sb = new StringBuffer();
if (locationName.equalsIgnoreCase("plugin.xml"))
locationName = location.getAbsolutePath();
sb.append(locationName.substring(0, locationName.length() - "plugin.xml".length() - 1));
sb.append("/");
sb.append(path);
lib2pluginId.put(sb.toString().replace('\\', '/'), pluginId);
}
}
}
}
}
}
catch (Throwable e)
{
}
}
private void acceptFragmentXML(ILocation location)
{
String locationName = location.getName();
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(location.getInputStream());
Element root = doc.getDocumentElement();
if (root.getTagName().equals("fragment"))
{
String fragmentId = root.getAttribute("id");
if (fragmentId != null && fragmentId.length() > 0 && !visitedPlugins.contains(fragmentId))
{
NodeList runtimes = root.getElementsByTagName("runtime");
for (int i = 0; i < runtimes.getLength(); i++)
{
Element runtime = (Element)runtimes.item(i);
NodeList libraries = runtime.getElementsByTagName("library");
for (int j = 0; j > libraries.getLength(); j++)
{
Element library = (Element)libraries.item(j);
String path = library.getAttribute("name");
if (path != null && path.length() > 0)
{
StringBuffer sb = new StringBuffer();
if (locationName.equalsIgnoreCase("fragment.xml"))
locationName = location.getAbsolutePath();
sb.append(locationName.substring(0, locationName.length() - "fragment.xml".length() - 1));
sb.append("/");
sb.append(path);
lib2pluginId.put(sb.toString().replace('\\', '/'), fragmentId);
}
}
}
}
}
}
catch (Throwable e)
{
}
}
private void acceptManifest(ILocation location)
{
String locationName = location.getName();
try
{
Manifest manifest = new Manifest(location.getInputStream());
java.util.jar.Attributes attrs = manifest.getMainAttributes();
String bundleNameAttr = attrs.getValue(new java.util.jar.Attributes.Name(Bundle.CONST_BUNDLE_NAME));
if (bundleNameAttr != null)
{
String bundleName = (new StringTokenizer(bundleNameAttr, ";")).nextToken().trim();
if (!visitedPlugins.contains(bundleName))
{
String bundleCPAttr = attrs.getValue(Bundle.CONST_BUNDLE_CLASSPATH);
if (bundleCPAttr != null)
{
StringTokenizer cp = new StringTokenizer(bundleCPAttr, ",");
while (cp.hasMoreTokens())
{
String path = cp.nextToken().trim();
if (path != null && path.length() > 0)
{
StringBuffer sb = new StringBuffer();
if (locationName.equalsIgnoreCase("MANIFEST.MF"))
locationName = location.getAbsolutePath();
sb.append(locationName.substring(0, locationName.length() - "META-INF/MANIFEST.MF".length() - 1));
sb.append("/");
sb.append(path);
lib2pluginId.put(sb.toString().replace('\\', '/'), bundleName);
}
}
}
}
}
}
catch (IOException e)
{
}
}
private boolean acceptSingleJar(ILocation location)
{
ILocationChildrenIterator it = location.childIterator();
for (ILocation child = it.next(); child != null; child = it.next())
{
String name = child.getName();
if (name.equalsIgnoreCase("META-INF/MANIFEST.MF"))
{
try
{
Manifest manifest = new Manifest(child.getInputStream());
java.util.jar.Attributes attrs = manifest.getMainAttributes();
String bundleName = attrs.getValue(new java.util.jar.Attributes.Name(Bundle.CONST_BUNDLE_NAME));
if (bundleName != null)
{
bundleName = (new StringTokenizer(bundleName, ";")).nextToken().trim();
if (!visitedPlugins.contains(bundleName))
{
lib2pluginId.put(location.getName().replace('\\', '/'), bundleName);
return false;
}
}
}
catch (IOException e)
{
}
}
else if (name.endsWith("plugin.xml"))
{
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(location.getInputStream());
Element root = doc.getDocumentElement();
if (root.getTagName().equals("plugin"))
{
String id = root.getAttribute("id");
if (id != null && id.length() > 0 && !visitedPlugins.contains(id))
{
lib2pluginId.put(location.getName().replace('\\', '/'), id);
return false;
}
}
}
catch (Throwable e)
{
}
}
else if (name.endsWith("fragment.xml"))
{
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(location.getInputStream());
Element root = doc.getDocumentElement();
if (root.getTagName().equals("fragment"))
{
String id = root.getAttribute("id");
if (id != null && id.length() > 0 && !visitedPlugins.contains(id))
{
lib2pluginId.put(location.getName().replace('\\', '/'), id);
return false;
}
}
}
catch (Throwable e)
{
}
}
}
if (Location.getExtension(location.getName()).equalsIgnoreCase("jar"))
{
try
{
JarInputStream jis = new JarInputStream(location.getInputStream());
Manifest manifest = jis.getManifest();
if (manifest != null)
{
java.util.jar.Attributes attrs = manifest.getMainAttributes();
String bundleNameAttr = attrs.getValue(new java.util.jar.Attributes.Name(Bundle.CONST_BUNDLE_NAME));
if (bundleNameAttr != null && !visitedPlugins.contains(bundleNameAttr))
{
String bundleName = (new StringTokenizer(bundleNameAttr, ";")).nextToken().trim();
if (bundleName != null)
{
bundleName = (new StringTokenizer(bundleName, ";")).nextToken().trim();
lib2pluginId.put(location.getName().replace('\\', '/'), bundleName);
return false;
}
}
}
}
catch (IOException ioe)
{
}
}
return true;
}
private void acceptDotClasspath(ILocation location)
{
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(location.getInputStream());
Element root = doc.getDocumentElement();
if (root.getTagName().equals("classpath"))
{
NodeList cpEntries = root.getElementsByTagName("classpathentry");
for (int i = 0; i < cpEntries.getLength(); i++)
{
Element cpEntry = (Element)cpEntries.item(i);
String kind = cpEntry.getAttribute("kind");
if (kind != null && kind.equals("output"))
{
String path = cpEntry.getAttribute("path");
String absPath = location.getAbsolutePath().replace('\\', '/');
StringBuffer lib = new StringBuffer();
int j = absPath.lastIndexOf('/');
String s = absPath.substring(0, j);
String id = s.substring(s.lastIndexOf('/') + 1, j);
if (!visitedPlugins.contains(id))
{
lib.append(s);
lib.append('/');
lib.append(path);
lib2pluginId.put(lib.toString(), id);
}
}
}
}
}
catch (Throwable e)
{
}
}
protected String addTrailingSeperator(String s)
{
if (s != null && !s.endsWith("/") && !s.endsWith("\\"))
{
StringBuffer sb = new StringBuffer(s);
sb.append('/');
return sb.toString();
}
else
{
return s;
}
}
}