initial creation of tools project
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/.classpath b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/.classpath
new file mode 100644
index 0000000..065ac06
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/.cvsignore b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/.cvsignore
new file mode 100644
index 0000000..a9c4073
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/.cvsignore
@@ -0,0 +1,5 @@
+bin
+@dot
+build.xml
+org.eclipse.wtp.releng.tools.component.core_1.0.0.jar
+javaCompiler...args
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/.project b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/.project
new file mode 100644
index 0000000..7368702
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.wtp.releng.tools.component.core</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.PluginNature</nature>
+	</natures>
+</projectDescription>
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/META-INF/MANIFEST.MF b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..4a51d09
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/META-INF/MANIFEST.MF
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %bundleName
+Bundle-SymbolicName: org.eclipse.wtp.releng.tools.component.core; singleton:=true
+Bundle-Version: 1.0.0
+Bundle-Localization: plugin
+Export-Package: org.eclipse.wtp.releng.tools.component,
+ org.eclipse.wtp.releng.tools.component.adopters,
+ org.eclipse.wtp.releng.tools.component.api,
+ org.eclipse.wtp.releng.tools.component.api.compatibility,
+ org.eclipse.wtp.releng.tools.component.api.progress,
+ org.eclipse.wtp.releng.tools.component.api.violation,
+ org.eclipse.wtp.releng.tools.component.images,
+ org.eclipse.wtp.releng.tools.component.internal,
+ org.eclipse.wtp.releng.tools.component.xsl
+Require-Bundle: org.eclipse.jdt.core,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ org.eclipse.jface.text
+Eclipse-LazyStart: false
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/apiagent.c b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/apiagent.c
new file mode 100644
index 0000000..cd09e2c
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/apiagent.c
@@ -0,0 +1,193 @@
+#include <jvmpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static JVMPI_Interface *jvmpi_interface;
+static struct methodref *mrefs;
+static int msize = 0;
+static struct classref *crefs;
+static int csize = 0;
+static FILE *outputFile;
+static char *include;
+static char *exclude;
+
+int memSize;
+int i;
+int j;
+
+struct methodref
+{
+  jmethodID id;
+  char *name;
+  char *signature;
+  int classid;
+};
+
+struct classref
+{
+  char *name;
+};
+
+void addClassref(char *classname)
+{
+  memSize = sizeof(struct classref);
+  if (csize == 0)
+    crefs = (struct classref *)malloc(memSize);
+  else
+    crefs = (struct classref *)realloc(crefs, memSize * (csize + 1));
+  (crefs + csize)->name = (char *)malloc(strlen(classname) + 1);
+  strcpy((crefs + csize)->name, classname);
+  csize++;
+}
+
+void addMethodref(jmethodID id, char *name, char *signature, int classid)
+{
+  memSize = sizeof(struct methodref);
+  if (msize == 0)
+    mrefs = (struct methodref *)malloc(memSize);
+  else
+    mrefs = (struct methodref *)realloc(mrefs, memSize * (msize + 1));
+
+  for (j = 0; j < msize; j++)
+  {
+    if ((mrefs + j)->id > id)
+    {
+      break;
+    }
+  }
+  if (j != msize)
+  {
+    memmove((mrefs + j + 1), (mrefs + j), memSize * (msize - j));
+  }
+  (mrefs + j)->name = (char *)malloc(strlen(name) + 1);
+  (mrefs + j)->signature = (char *)malloc(strlen(signature) + 1);
+  (mrefs + j)->id = id;
+  strcpy((mrefs + j)->name, name);
+  strcpy((mrefs + j)->signature, signature);
+  (mrefs + j)->classid = classid;
+  msize++;
+  /*
+  (mrefs + msize)->name = (char *)malloc(strlen(name) + 1);
+  (mrefs + msize)->signature = (char *)malloc(strlen(signature) + 1);
+  (mrefs + msize)->id = id;
+  strcpy((mrefs + msize)->name, name);
+  strcpy((mrefs + msize)->signature, signature);
+  (mrefs + msize)->classid = classid;
+  msize++;
+  */
+}
+
+int lower;
+int upper;
+int middle;
+jmethodID lowerid;
+jmethodID upperid;
+jmethodID middleid;
+
+void addMethodID(jmethodID id)
+{
+  if (msize < 1)
+    return;
+  lower = 0;
+  upper = msize - 1;
+  lowerid = (mrefs + lower)->id;
+  upperid = (mrefs + upper)->id;
+  while (lowerid < id && id < upperid && (upper - lower) > 1)
+  {
+    middle = ((upper - lower) / 2) + lower;
+    middleid = (mrefs + middle)->id;
+    if (middleid > id)
+    {
+      upper = middle;
+      upperid = middleid;
+    }
+    else if (middleid < id)
+    {
+      lower = middle;
+      lowerid = middleid;
+    }
+    else
+    {
+      upper = middle;
+      upperid = middleid;
+      break;
+    }
+  }
+  if (lowerid == id)
+    middle = lower;
+  else if (upperid == id)
+    middle = upper;
+  else
+    middle = -1;
+  if (middle != -1)
+  {
+    fputs((crefs + (mrefs + middle)->classid)->name, outputFile);
+    fputs("#", outputFile);
+    fputs((mrefs + middle)->name, outputFile);
+    fputs("#", outputFile);
+    fputs((mrefs + middle)->signature, outputFile);
+    fputs(" ", outputFile);
+    if (middle != (msize - 1))
+      memmove((mrefs + middle), (mrefs + middle + 1), sizeof(struct methodref) * (msize - (middle + 1)));
+    msize--;
+    return;
+  }
+  /*
+  for (i = 0; i < msize; i++)
+  {
+    if ((mrefs + i)->id == id)
+    {
+      fputs((crefs + (mrefs + i)->classid)->name, outputFile);
+      fputs("#", outputFile);
+      fputs((mrefs + i)->name, outputFile);
+      fputs("#", outputFile);
+      fputs((mrefs + i)->signature, outputFile);
+      fputs(" ", outputFile);
+      memmove((mrefs + i), (mrefs + i + 1), sizeof(struct methodref) * (msize - (i + 1)));
+      msize--;
+      return;
+    }
+  }
+  */
+}
+
+void notifyEvent(JVMPI_Event *event)
+{
+  switch(event->event_type)
+  {
+    case JVMPI_EVENT_CLASS_LOAD:
+      if (strstr(event->u.class_load.class_name, include) != NULL && (exclude == NULL || strstr(event->u.class_load.class_name, exclude) == NULL))
+      {
+        addClassref((char *)event->u.class_load.class_name);
+        for (i = 0; i < event->u.class_load.num_methods; i++)
+        {
+          addMethodref(event->u.class_load.methods[i].method_id, (char *)event->u.class_load.methods[i].method_name, (char *)event->u.class_load.methods[i].method_signature, csize - 1);
+        }
+      }
+      break;
+    case JVMPI_EVENT_METHOD_ENTRY:
+      addMethodID(event->u.method.method_id);
+      break;
+    case JVMPI_EVENT_JVM_SHUT_DOWN:
+      fclose(outputFile);
+      break;
+  }
+}
+
+JNIEXPORT jint JNICALL
+JVM_OnLoad(JavaVM *jvm, char *options, void *reserved)
+{
+  if ((*jvm)->GetEnv(jvm, (void **)&jvmpi_interface, JVMPI_VERSION_1) < 0)
+    return JNI_ERR;
+  outputFile = fopen(getenv("apiagent_output"), "a");
+  include = getenv("apiagent_include");
+  exclude = getenv("apiagent_exclude");
+  if (outputFile != NULL && include != NULL)
+  {
+    jvmpi_interface->NotifyEvent = notifyEvent;
+    jvmpi_interface->EnableEvent(JVMPI_EVENT_CLASS_LOAD, NULL);
+    jvmpi_interface->EnableEvent(JVMPI_EVENT_METHOD_ENTRY, NULL);
+    jvmpi_interface->EnableEvent(JVMPI_EVENT_JVM_SHUT_DOWN, NULL);
+  }
+  return JNI_OK;
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/build.sh b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/build.sh
new file mode 100644
index 0000000..8b8cced
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/build.sh
@@ -0,0 +1,3 @@
+export LD_LIBRARY_PATH=$JAVA_HOME/jre/bin/java:$JAVA_HOME/jre/bin:$PWD
+gcc -c -I$JAVA_HOME/include -I$JAVA_HOME/include/linux apiagent.c
+ld -shared apiagent.o -o libapiagent.so
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/libapiagent.so b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/libapiagent.so
new file mode 100644
index 0000000..85da8a3
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/libapiagent.so
Binary files differ
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/libpiAgent.so b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/libpiAgent.so
new file mode 100644
index 0000000..2b8779c
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/libpiAgent.so
Binary files differ
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/piAgent.dll b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/piAgent.dll
new file mode 100644
index 0000000..31d20b2
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/piAgent.dll
Binary files differ
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/piagent_options.txt b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/piagent_options.txt
new file mode 100644
index 0000000..6db935d
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/apiagent/piagent_options.txt
@@ -0,0 +1,14 @@
+MONITOR_MODE=none
+FILTERS=false
+TRACK_GC_EVENT_TYPES=none
+* ID_STYLE=static
+OPTIONS=false
+TIMESTAMPS=false
+OBJ_ALLOC_IS_ARRAY=false
+STACK_INFORMATION=normal
+* BOUNDARY_DEPTH=0
+TICKET=false
+TRACE_MODE=noObjectCorrelation
+TRACE_ID_REFS=true
+METHOD_COUNTS=true
+METHOD_COUNTS_ONLY=true
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/build.properties b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/build.properties
new file mode 100644
index 0000000..51e7dc9
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/build.properties
@@ -0,0 +1,5 @@
+bin.includes = plugin.xml,\
+               .,\
+               META-INF/,\
+               plugin.properties
+source.. = src/
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/eclipse.properties b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/eclipse.properties
new file mode 100644
index 0000000..e151875
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/eclipse.properties
@@ -0,0 +1,98 @@
+Ant=org.eclipse.ant.core \
+ org.eclipse.ant.ui
+
+Cheatsheets=org.eclipse.ui.cheatsheets
+
+Compare=org.eclipse.compare
+
+Console=org.eclipse.ui.console
+
+Core_Expressions=org.eclipse.core.expressions
+
+Core_Filebuffers=org.eclipse.core.filebuffers
+
+Core_Variables=org.eclipse.core.variables
+
+CVS=org.eclipse.team.cvs.ssh \
+ org.eclipse.team.cvs.ssh2 \
+ org.eclipse.team.cvs.ui \
+ org.eclipse.team.cvs.core
+
+Help=org.eclipse.help \
+ org.eclipse.help.base \
+ org.eclipse.help.ui \
+ org.eclipse.help.webapp \
+ org.eclipse.help.appserver \
+ org.eclipse.help.ide
+
+JFace=org.eclipse.jface \
+ org.eclipse.jface.text
+
+Platform_Debug_Core=org.eclipse.debug.core
+
+Platform_Debug_UI=org.eclipse.debug.ui
+
+Platform_Resources=org.eclipse.core.resources \
+ org.eclipse.core.resources.win32 \
+ org.eclipse.core.resources.linux \
+ org.eclipse.core.resources.hpux \
+ org.eclipse.core.resources.macosx \
+ org.eclipse.core.resources.qnx
+
+Platform_Runtime=org.eclipse.core.runtime \
+ org.eclipse.core.boot
+
+Platform_Text=org.eclipse.text \
+ org.eclipse.ui.workbench.texteditor \
+ org.eclipse.ui.editors
+
+Platform_UI_IDE=org.eclipse.ui.ide \
+ org.eclipse.ui.workbench.compatibility
+
+Platform_UI_RCP=org.eclipse.ui \
+ org.eclipse.ui.workbench \
+ org.eclipse.ui.win32 \
+ org.eclipse.ui.workbench.texteditor \
+ org.eclipse.ui.editors \
+ org.eclipse.ui.externaltools \
+ org.eclipse.ui.presentations.r21 \
+ org.eclipse.ui.views
+
+Search=org.eclipse.search
+
+SWT=org.eclipse.swt \
+ org.eclipse.swt.win32
+
+Team=org.eclipse.team.core \
+ org.eclipse.team.ui
+
+UI_Forms=org.eclipse.ui.forms
+
+UI_Intro=org.eclipse.ui.intro
+
+Update=org.eclipse.update.core \
+ org.eclipse.update.core.win32 \
+ org.eclipse.update.configurator \
+ org.eclipse.update.scheduler \
+ org.eclipse.update.ui
+
+JDT_Core=org.eclipse.jdt.core
+
+JDT_Debug=org.eclipse.jdt.debug \
+ org.eclipse.jdt.debug.ui \
+ org.eclipse.jdt.launching
+
+JDT_UI=org.eclipse.jdt.ui \
+ org.eclipse.jdt.junit
+
+LTK_Core=org.eclipse.ltk.core.refactoring
+
+LTK_UI=org.eclipse.ltk.ui.refactoring
+
+PDE=org.eclipse.pde.core \
+ org.eclipse.pde.ui \
+ org.eclipse.pde.build
+
+OSGI=org.eclipse.osgi \
+ org.eclipse.osgi.util \
+ org.eclipse.osgi.services
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/emf.properties b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/emf.properties
new file mode 100644
index 0000000..882b584
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/emf.properties
@@ -0,0 +1,39 @@
+emf=org.eclipse.emf.codegen.ecore.ui \
+ org.eclipse.emf.codegen.ecore \
+ org.eclipse.emf.codegen.ui \
+ org.eclipse.emf.codegen \
+ org.eclipse.emf.common.ui \
+ org.eclipse.emf.common \
+ org.eclipse.emf.ecore.change.edit \
+ org.eclipse.emf.ecore.change \
+ org.eclipse.emf.ecore.edit \
+ org.eclipse.emf.ecore.editor \
+ org.eclipse.emf.ecore.xmi \
+ org.eclipse.emf.ecore \
+ org.eclipse.emf.edit.ui \
+ org.eclipse.emf.edit \
+ org.eclipse.emf.mapping.ecore2ecore.editor \
+ org.eclipse.emf.mapping.ecore2ecore \
+ org.eclipse.emf.mapping.ui \
+ org.eclipse.emf.mapping.xsd2ecore.editor \
+ org.eclipse.emf.mapping.xsd2ecore \
+ org.eclipse.emf.mapping \
+ org.eclipse.emf
+
+sdo=org.eclipse.emf.commonj.sdo \
+ org.eclipse.emf.ecore.sdo.edit \
+ org.eclipse.emf.ecore.sdo.editor \
+ org.eclipse.emf.ecore.sdo \
+
+xsd=org.eclipse.xsd.edit \
+ org.eclipse.xsd.editor \
+ org.eclipse.xsd
+
+jem=com.ibm.etools.emf.event \
+ com.ibm.wtp.common.util \
+ com.ibm.wtp.emf.workbench \
+ org.eclipse.jem.beaninfo \
+ org.eclipse.jem.proxy \
+ org.eclipse.jem.ui \
+ org.eclipse.jem.workbench \
+ org.eclipse.jem
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/gef.properties b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/gef.properties
new file mode 100644
index 0000000..557a324
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/gef.properties
@@ -0,0 +1,2 @@
+gef=org.eclipse.gef \
+ org.eclipse.draw2d
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/ve.properties b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/ve.properties
new file mode 100644
index 0000000..d7a64ab
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/ve.properties
@@ -0,0 +1,8 @@
+jem=com.ibm.etools.emf.event \
+ com.ibm.wtp.common.util \
+ com.ibm.wtp.emf.workbench \
+ org.eclipse.jem.beaninfo \
+ org.eclipse.jem.proxy \
+ org.eclipse.jem.ui \
+ org.eclipse.jem.workbench \
+ org.eclipse.jem
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/wtp.properties b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/wtp.properties
new file mode 100644
index 0000000..84cc52e
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/data/wtp.properties
@@ -0,0 +1,140 @@
+wst.command=org.eclipse.wst.command.env \
+ org.eclipse.wst.command.env.core \
+ org.eclipse.wst.command.env.ui
+
+wst.common=org.eclipse.wst.common.contentmodel \
+ org.eclipse.wst.common.emf \
+ org.eclipse.wst.common.emfworkbench.integration \
+ org.eclipse.wst.common.encoding \
+ org.eclipse.wst.common.frameworks \
+ org.eclipse.wst.common.frameworks.ui \
+ org.eclipse.wst.common.migration \
+ org.eclipse.wst.common.migration.ui \
+ org.eclipse.wst.common.navigator \
+ org.eclipse.wst.common.navigator.views \
+ org.eclipse.wst.common.navigator.workbench \
+ org.eclipse.wst.common.ui \
+ org.eclipse.wst.common.ui.properties \
+ org.eclipse.wst.common.uriresolver
+
+wst.css=org.eclipse.wst.css.core \
+ org.eclipse.wst.css.ui
+
+wst.dtd=org.eclipse.wst.dtd \
+ org.eclipse.wst.dtd.contentmodel \
+ org.eclipse.wst.dtd.core \
+ org.eclipse.wst.dtd.parser \
+ org.eclipse.wst.dtd.ui \
+ org.eclipse.wst.dtd.validation
+
+wst.html=org.eclipse.wst.html.core \
+ org.eclipse.wst.html.ui
+
+wst.internet=org.eclipse.wst.internet.monitor.core \
+ org.eclipse.wst.internet.monitor.ui \
+ org.eclipse.wst.internet.proxy \
+ org.eclipse.wst.internet.webbrowser
+
+wst.javascript=org.eclipse.wst.javascript.common.ui \
+ org.eclipse.wst.javascript.core \
+ org.eclipse.wst.javascript.ui
+
+wst.rdb=org.eclipse.wst.rdb.connection.ui \
+ org.eclipse.wst.rdb.core \
+ org.eclipse.wst.rdb.core.ui \
+ org.eclipse.wst.rdb.dbdefinition.db2.cloudscape \
+ org.eclipse.wst.rdb.dbdefinition.db2.iseries \
+ org.eclipse.wst.rdb.dbdefinition.db2.luw \
+ org.eclipse.wst.rdb.dbdefinition.db2.zseries \
+ org.eclipse.wst.rdb.dbdefinition.informix \
+ org.eclipse.wst.rdb.dbdefinition.oracle \
+ org.eclipse.wst.rdb.dbdefinition.sqlserver \
+ org.eclipse.wst.rdb.dbdefinition.sybase \
+ org.eclipse.wst.rdb.models.dbdefinition \
+ org.eclipse.wst.rdb.models.sql \
+ org.eclipse.wst.rdb.outputview \
+ org.eclipse.wst.rdb.server.ui \
+ org.eclipse.wst.rdb.sqlscrapbook
+
+wst.server=org.eclipse.wst.server.core \
+ org.eclipse.wst.server.ui \
+ org.eclipse.wst.server.util
+
+wst.sse=org.eclipse.wst.sse.core \
+ org.eclipse.wst.sse.snippets \
+ org.eclipse.wst.sse.ui
+
+wst.validation=org.eclipse.wst.validation \
+ org.eclipse.wst.validation.ui
+
+wst.web=org.eclipse.wst.web \
+ org.eclipse.wst.web.ui
+
+wst.ws=org.eclipse.wst.ws.parser
+
+wst.wsdl=org.eclipse.wst.wsdl \
+ org.eclipse.wst.wsdl.ui \
+ org.eclipse.wst.wsdl.validation
+
+wst.wsi=org.eclipse.wst.wsi.core \
+ org.eclipse.wst.wsi.ui \
+ org.eclipse.wst.wsi.validation
+
+wst.xml=org.eclipse.wst.xml.core \
+ org.eclipse.wst.xml.ui \
+ org.eclipse.wst.xml.uriresolver \
+ org.eclipse.wst.xml.uriresolver.ui \
+ org.eclipse.wst.xml.validation
+
+wst.xsd=org.eclipse.wst.xsd.contentmodel \
+ org.eclipse.wst.xsd.ui \
+ org.eclipse.wst.xsd.validation
+
+jst.common=org.eclipse.jst.common.annotations.controller \
+ org.eclipse.jst.common.annotations.core \
+ org.eclipse.jst.common.annotations.ui \
+ org.eclipse.jst.common.frameworks \
+ org.eclipse.jst.common.frameworks.ui \
+ org.eclipse.jst.common.launcher.ant \
+ org.eclipse.jst.common.navigator.java \
+ org.eclipse.jst.sample.web.project
+
+jst.ejb=org.eclipse.jst.ejb.ui
+
+jst.j2ee=org.eclipse.jst.j2ee \
+ org.eclipse.jst.j2ee.core \
+ org.eclipse.jst.j2ee.ejb \
+ org.eclipse.jst.j2ee.jca \
+ org.eclipse.jst.j2ee.jca.ui \
+ org.eclipse.jst.j2ee.navigator.ui \
+ org.eclipse.jst.j2ee.ui \
+ org.eclipse.jst.j2ee.web \
+ org.eclipse.jst.j2ee.webservice
+
+jst.jsp=org.eclipse.jst.jsp.core \
+ org.eclipse.jst.jsp.ui
+
+jst.server=org.eclipse.jst.server.core \
+ org.eclipse.jst.server.generic.core \
+ org.eclipse.jst.server.generic.modules \
+ org.eclipse.jst.server.generic.ui \
+ org.eclipse.jst.server.jboss.core \
+ org.eclipse.jst.server.jboss.ui \
+ org.eclipse.jst.server.tomcat.core \
+ org.eclipse.jst.server.tomcat.ui \
+ org.eclipse.jst.server.ui
+
+jst.servlet=org.eclipse.jst.servlet.ui
+
+jst.ws=org.eclipse.jst.ws \
+ org.eclipse.jst.ws.axis \
+ org.eclipse.jst.ws.axis.ant \
+ org.eclipse.jst.ws.axis.consumption.core \
+ org.eclipse.jst.ws.axis.consumption.ui \
+ org.eclipse.jst.ws.axis.creation.ui \
+ org.eclipse.jst.ws.consumption \
+ org.eclipse.jst.ws.consumption.ui \
+ org.eclipse.jst.ws.creation.ejb.ui \
+ org.eclipse.jst.ws.creation.ui \
+ org.eclipse.jst.ws.uddiregistry \
+ org.eclipse.jst.ws.ui
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/plugin.properties b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/plugin.properties
new file mode 100644
index 0000000..3a842c5
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/plugin.properties
@@ -0,0 +1,11 @@
+###############################################################################
+# Copyright (c) 2004, 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
+###############################################################################
+bundleName=Component Core
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/plugin.xml b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/plugin.xml
new file mode 100644
index 0000000..c7e3b22
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/plugin.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+   <extension
+      id="Java2API"
+      point="org.eclipse.core.runtime.applications">
+      <application>
+         <run
+            class="org.eclipse.wtp.releng.tools.component.adopters.Java2API">
+         </run>
+      </application>
+   </extension>
+   <extension
+      id="JavadocScanner"
+      point="org.eclipse.core.runtime.applications">
+      <application>
+         <run
+            class="org.eclipse.wtp.releng.tools.component.adopters.JavadocScanner">
+         </run>
+      </application>
+   </extension>
+   <extension
+      id="Class2Reference"
+      point="org.eclipse.core.runtime.applications">
+      <application>
+         <run
+            class="org.eclipse.wtp.releng.tools.component.api.violation.Class2Reference">
+         </run>
+      </application>
+   </extension>
+   <extension
+      id="SimpleClass2Reference"
+      point="org.eclipse.core.runtime.applications">
+      <application>
+         <run
+            class="org.eclipse.wtp.releng.tools.component.adopters.SimpleClass2Reference">
+         </run>
+      </application>
+   </extension>
+   <extension
+      id="APIRefCompatibilityScanner"
+      point="org.eclipse.core.runtime.applications">
+      <application>
+         <run
+            class="org.eclipse.wtp.releng.tools.component.adopters.APIRefCompatibilityScanner">
+         </run>
+      </application>
+   </extension>
+   <extension
+      id="ExtensionPointScanner"
+      point="org.eclipse.core.runtime.applications">
+      <application>
+         <run
+            class="org.eclipse.wtp.releng.tools.component.adopters.ExtensionPointScanner">
+         </run>
+      </application>
+   </extension>
+</plugin>
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/CodeCoverageScanner.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/CodeCoverageScanner.java
new file mode 100644
index 0000000..31ca3f0
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/CodeCoverageScanner.java
@@ -0,0 +1,509 @@
+/*******************************************************************************
+ * 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;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Collection;
+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 org.eclipse.wtp.releng.tools.component.api.API2ComponentAPI;
+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.MethodAPI;
+import org.eclipse.wtp.releng.tools.component.api.PackageAPI;
+import org.eclipse.wtp.releng.tools.component.api.TestCoverage;
+import org.eclipse.wtp.releng.tools.component.images.ImagesUtil;
+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.xsl.XSLUtil;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class CodeCoverageScanner implements ILocationVisitor
+{
+  private String api;
+  private Collection src;
+  private String trcxml;
+  private String outputDir;
+  private boolean skipAPIGen;
+  private Collection includes;
+  private Collection excludes;
+  private boolean includeAllTC;
+  private boolean html;
+  private String title;
+  private String xsl;
+
+  public String getOutputDir()
+  {
+    return outputDir;
+  }
+
+  public void setOutputDir(String outputDir)
+  {
+    this.outputDir = addTrailingSeperator(outputDir);
+  }
+
+  public String getApi()
+  {
+    return api;
+  }
+
+  public void setApi(String api)
+  {
+    this.api = api;
+  }
+
+  public Collection getSrc()
+  {
+    return src;
+  }
+
+  public void setSrc(Collection src)
+  {
+    this.src = src;
+  }
+
+  public String getTRCXML()
+  {
+    return trcxml;
+  }
+
+  public void setTRCXML(String trcxml)
+  {
+    this.trcxml = trcxml;
+  }
+
+  public boolean isSkipAPIGen()
+  {
+    return skipAPIGen;
+  }
+
+  public void setSkipAPIGen(boolean skipAPIGen)
+  {
+    this.skipAPIGen = skipAPIGen;
+  }
+
+  public Collection getIncludes()
+  {
+    return includes;
+  }
+
+  public void setIncludes(Collection includes)
+  {
+    this.includes = includes;
+  }
+
+  public Collection getExcludes()
+  {
+    return excludes;
+  }
+
+  public void setExcludes(Collection excludes)
+  {
+    this.excludes = excludes;
+  }
+
+  public boolean isIncludeAllTC()
+  {
+    return includeAllTC;
+  }
+
+  public void setIncludeAllTC(boolean includeAllTC)
+  {
+    this.includeAllTC = includeAllTC;
+  }
+
+  public boolean isHtml()
+  {
+    return html;
+  }
+
+  public void setHtml(boolean html)
+  {
+    this.html = html;
+  }
+
+  public String getTitle()
+  {
+    return title;
+  }
+
+  public void setTitle(String title)
+  {
+    this.title = title;
+  }
+
+  public String getXsl()
+  {
+    return xsl;
+  }
+
+  public void setXsl(String xsl)
+  {
+    this.xsl = xsl;
+  }
+
+  private API2ComponentAPI api2CompXML;
+
+  public void execute()
+  {
+    // Generate api-info.xml
+    api2CompXML = new API2ComponentAPI();
+    api2CompXML.setApi(api);
+    api2CompXML.setSrc(src);
+    api2CompXML.setOutputDir(outputDir);
+    api2CompXML.setIncludes(includes);
+    api2CompXML.setExcludes(excludes);
+    api2CompXML.setReadInterface(true);
+    api2CompXML.setSkipAPIGen(skipAPIGen);
+    api2CompXML.execute();
+
+    // Visit all .trcxml files that uses APIs
+    Location.createLocation(new File(trcxml)).accept(this);
+
+    // Generate HTML
+    if (isHtml())
+    {
+      ImagesUtil.copyAll(outputDir);
+      genHTML();
+    }
+  }
+
+  private void genHTML()
+  {
+    final StringBuffer summary = new StringBuffer();
+    summary.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    summary.append("<root>");
+    File f = new File(outputDir);
+    f.mkdirs();
+    ILocation outputLoc = Location.createLocation(new File(outputDir));
+    outputLoc.accept(new ILocationVisitor()
+    {
+      public boolean accept(ILocation location)
+      {
+        if (location.getName().endsWith("api-info.xml"))
+        {
+          try
+          {
+            XSLUtil.transform
+            (
+              xsl != null && xsl.length() > 0 ? Location.createLocation(new File(xsl)).getInputStream() : ClassLoader.getSystemResourceAsStream("org/eclipse/wtp/releng/tools/component/xsl/api-tc.xsl"),
+              location.getInputStream(),
+              new FileOutputStream(((FileLocation)location.createSibling("api-tc.html")).getFile())
+            );
+            summary.append("<api-info file=\"");
+            summary.append(location.getAbsolutePath().substring(outputDir.length()));
+            summary.append("\"/>");
+          }
+          catch (Throwable t)
+          {
+            t.printStackTrace();
+          }
+        }
+        return true;
+      }
+    });
+    summary.append("</root>");
+    try
+    {
+      if (isIncludeAllTC())
+        System.setProperty("includeAllTC", "true");
+      if (title != null)
+        System.setProperty("title", title);
+      XSLUtil.transform
+      (
+        ClassLoader.getSystemResourceAsStream("org/eclipse/wtp/releng/tools/component/xsl/api-tc-summary.xsl"),
+        new ByteArrayInputStream(summary.toString().getBytes()),
+        new FileOutputStream(new File(outputDir + "/api-tc-summary.html")),
+        outputDir
+      );
+    }
+    catch (Throwable e)
+    {
+      e.printStackTrace();
+    }
+  }
+
+  public boolean accept(ILocation location)
+  {
+    String locationName = location.getName();
+    if (locationName.endsWith(".trcxml"))
+      processTRCXML(location);
+    return true;
+  }
+
+  private void processTRCXML(ILocation location)
+  {
+    try
+    {
+      SAXParserFactory factory = SAXParserFactory.newInstance();
+      factory.setNamespaceAware(false);
+      factory.setValidating(false);
+      SAXParser parser = factory.newSAXParser();
+      TRCXMLHandler trcxmlHandler = new TRCXMLHandler();
+      parser.parse(new InputSource(new BufferedInputStream(location.getInputStream())), trcxmlHandler);
+      final String testcaseName = getTRCXMLTestcaseName(location);
+      final Map classMethodName2Count = trcxmlHandler.getClassMethodName2Count();
+      ILocation outputLoc = Location.createLocation(new File(outputDir));
+      outputLoc.accept(new ILocationVisitor()
+      {
+        public boolean accept(ILocation location)
+        {
+          if (location.getName().endsWith("api-info.xml"))
+          {
+            try
+            {
+              boolean dirty = false;
+              ComponentAPI compAPI = new ComponentAPI();
+              compAPI.setLocation(location);
+              compAPI.load();
+              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();
+                  StringBuffer qualifiedClassName = new StringBuffer();
+                  qualifiedClassName.append(pkgAPI.getName());
+                  qualifiedClassName.append(".");
+                  qualifiedClassName.append(classAPI.getName());
+                  for (Iterator it3 = classAPI.getMethodAPIs().iterator(); it3.hasNext();)
+                  {
+                    MethodAPI methodAPI = (MethodAPI)it3.next();
+                    String methodName = methodAPI.getName().replace('>', '-');
+                    if (methodName.startsWith("&lt;"))
+                      methodName = "-" + methodName.substring(4);
+                    String signature = methodAPI.getDescriptor();
+                    String classMethodName = getClassMethodName(qualifiedClassName.toString(), methodName, signature);
+                    String countString = (String)classMethodName2Count.get(classMethodName);
+                    // TODO
+                    if (countString != null)
+                    {
+                      TestCoverage tc = methodAPI.getTestCoverage();
+                      tc.addTest(testcaseName);
+                      dirty = true;
+                    }
+                    else
+                    {
+                      List implClasses = (List)api2CompXML.getImplClasses(qualifiedClassName.toString());
+                      for (Iterator it4 = implClasses.iterator(); it4.hasNext();)
+                      {
+                        classMethodName = getClassMethodName((String)it4.next(), methodName, signature);
+                        countString = (String)classMethodName2Count.get(classMethodName);
+                        // TODO
+                        if (countString != null)
+                        {
+                          TestCoverage tc = methodAPI.getTestCoverage();
+                          tc.addTest(testcaseName);
+                          dirty = true;
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+              if (dirty)
+              {
+                compAPI.save();
+              }
+            }
+            catch (IOException ioe)
+            {
+              ioe.printStackTrace();
+            }
+          }
+          return true;
+        }
+      });
+    }
+    catch (ParserConfigurationException pce)
+    {
+      pce.printStackTrace();
+    }
+    catch (SAXException saxe)
+    {
+      saxe.printStackTrace();
+    }
+    catch (IOException ioe)
+    {
+      ioe.printStackTrace();
+    }
+  }
+
+  private String getClassMethodName(String qualifiedClasName, String methodName, String signature)
+  {
+    StringBuffer classMethodName = new StringBuffer();
+    classMethodName.append(qualifiedClasName);
+    classMethodName.append("#");
+    classMethodName.append(methodName);
+    classMethodName.append("#");
+    classMethodName.append(signature);
+    return classMethodName.toString();
+  }
+
+  private String getTRCXMLTestcaseName(ILocation location)
+  {
+    String locationName = location.getName();
+    int i = locationName.lastIndexOf('-');
+    return locationName.substring(i + 1, locationName.length() - ".trcxml".length());
+  }
+
+  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;
+    }
+  }
+
+  private class TRCXMLHandler extends DefaultHandler
+  {
+	private static final String DOT = "."; //$NON-NLS-1$ 
+	private static final String FORWARD_SLASH = "/"; //$NON-NLS-1$
+    private final String CLASS_DEF = "classDef";
+    private final String METHOD_DEF = "methodDef";
+    private final String METHOD_COUNT = "methodCount";
+
+    private Map classMethodName2count = new HashMap();
+    private Map methodId2Name = new HashMap();
+    private Map methodId2ClassId = new HashMap();
+    private Map classId2Name = new HashMap();
+
+    public void startElement(String uri, String elementName, String qName, Attributes attributes) throws SAXException
+    {
+      if (elementName.equals(CLASS_DEF) || qName.equals(CLASS_DEF))
+      {
+        String id = attributes.getValue("classId");
+        String name = attributes.getValue("name");
+        classId2Name.put(id, name.replaceAll(FORWARD_SLASH, DOT)); 
+      }
+      else if (elementName.equals(METHOD_DEF) || qName.equals(METHOD_DEF))
+      {
+        String id = attributes.getValue("methodId");
+        String name = attributes.getValue("name");
+        String signature = attributes.getValue("signature");
+        String classIdRef = attributes.getValue("classIdRef");
+        StringBuffer sb = new StringBuffer();
+        sb.append(name);
+        sb.append("#");
+        sb.append(signature);
+        methodId2Name.put(id, sb.toString());
+        methodId2ClassId.put(id, classIdRef);
+      }
+      else if (elementName.equals(METHOD_COUNT) || qName.equals(METHOD_COUNT))
+      {
+        String methodIdRef = attributes.getValue("methodIdRef");
+        String count = attributes.getValue("count");
+        String methodName = (String)methodId2Name.get(methodIdRef);
+        if (methodName != null)
+        {
+          String classId = (String)methodId2ClassId.get(methodIdRef);
+          if (classId != null)
+          {
+            String className = (String)classId2Name.get(classId);
+            if (className != null)
+            {
+              StringBuffer sb = new StringBuffer();
+              sb.append(className);
+              sb.append("#");
+              sb.append(methodName);
+              classMethodName2count.put(sb.toString(), count);
+            }
+          }
+        }
+      }
+    }
+
+    public Map getClassMethodName2Count()
+    {
+      return classMethodName2count;
+    }
+  }
+
+  public static void main(String[] args)
+  {
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    Collection api = (Collection)options.get("api");
+    Collection src = (Collection)options.get("src");
+    Collection trcxml = (Collection)options.get("trcxml");
+    Collection outputDir = (Collection)options.get("outputDir");
+    Collection skipAPIGen = (Collection)options.get("skipAPIGen");
+    Collection includes = (Collection)options.get("includes");
+    Collection excludes = (Collection)options.get("excludes");
+    Collection includeAllTC = (Collection)options.get("includeAllTC");
+    Collection html = (Collection)options.get("html");
+    Collection title = (Collection)options.get("title");
+    Collection xsl = (Collection)options.get("xsl");
+    if (outputDir == null || outputDir.isEmpty())
+    {
+      printUsage();
+      System.exit(-1);
+    }
+    if ((src == null || api == null || src.isEmpty() || api.isEmpty()) && skipAPIGen == null)
+    {
+      printUsage();
+      System.exit(-1);
+    }
+    CodeCoverageScanner scanner = new CodeCoverageScanner();
+    scanner.setApi((String)api.iterator().next());
+    scanner.setSrc(src);
+    scanner.setTRCXML((String)trcxml.iterator().next());
+    scanner.setOutputDir((String)outputDir.iterator().next());
+    scanner.setSkipAPIGen(skipAPIGen != null);
+    scanner.setIncludes(includes);
+    scanner.setExcludes(excludes);
+    scanner.setIncludeAllTC(includeAllTC != null);
+    scanner.setHtml(html != null);
+    scanner.setTitle(title != null ? (String)title.iterator().next() : null);
+    scanner.setXsl(xsl != null && !xsl.isEmpty() ? (String)xsl.iterator().next() : null);
+    scanner.execute();
+  }
+
+  private static void printUsage()
+  {
+    System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.codecoverage.CodeCoverage -api <api> -src <src> -use <use> -outputDir <outputDir> [-options]");
+    System.out.println("");
+    System.out.println("\t-api\t\t<api>\t\tlocation of your component.xml");
+    System.out.println("\t-src\t\t<src>\t\tlocation of a Eclipse-based product (requires SDK build)");
+    System.out.println("\t-trcxml\t\t<trcxml>\tlocation of the *.trcxml files generated by TPTP");
+    System.out.println("\t-outputDir\t<outputDir>\toutput directory of component.xml files");
+    System.out.println("");
+    System.out.println("where options include:");
+    System.out.println("");
+    System.out.println("\t-skipAPIGen\t\t\tskip api-info.xml generation and use existing ones");
+    System.out.println("\t-includes\t<includes>\tspace seperated packages to include");
+    System.out.println("\t-excludes\t<excludes>\tspace seperated packages to exclude");
+    System.out.println("\t-includeAllTC\t\t\t\tinclude plug-ins with 100% test coverage");
+    System.out.println("\t-html\t\t\t\tgenerate HTML results");
+    System.out.println("\t-title\t\t<title>\ttitle of the generated HTML report");
+    System.out.println("\t-xsl\t\t<xsl>\t\tuse your own stylesheet. You must specify the -html option");
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/CommandOptionParser.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/CommandOptionParser.java
new file mode 100644
index 0000000..bc6d498
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/CommandOptionParser.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * This is a helper class used to parse the command line options into a
+ * map where each option can be returned or all options.
+ */
+public class CommandOptionParser {
+  
+  // Delimiter string
+  private static final String delimiter = "-"; //$NON-NLS-1$
+  
+  // Map of options
+  private Map options;
+
+  /**
+   * Default constructor
+   * @param args String[]
+   */
+  public CommandOptionParser(String[] args) {
+    parse(args);
+  }
+
+  /**
+   * @return Map of all command line options and values
+   */
+  public Map getOptions() {
+    return options;
+  }
+
+  /**
+   * Return the command line values for the specified command line key.
+   * 
+   * @param key String
+   * @return Collection of values
+   */
+  public Collection getOption(String key) {
+    return (Collection)options.get(key);
+  }
+
+  /**
+   * Get command line value as a string for specified option key.
+   * 
+   * @param key String
+   * @return String command line value
+   */
+  public String getOptionAsString(String key) {
+    Collection c = getOption(key);
+    if (c.isEmpty())
+      return null;
+    return (String) c.iterator().next();
+  }
+
+  /**
+   * Parse the string array of command line options and values into a map.
+   * 
+   * @param args String[]
+   */
+  private void parse(String[] args) {
+    options = new HashMap();
+    String option = null;
+    for (int i = 0; i < args.length; i++) {
+      if (args[i] != null) {
+        if (args[i].startsWith(delimiter)) {
+          option = args[i].substring(1);
+          options.put(option, new ArrayList(1));
+        } else if (option != null)
+          ((List)options.get(option)).add(args[i]);
+      }
+    }
+  }
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IClassVisitor.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IClassVisitor.java
new file mode 100644
index 0000000..1ebd819
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IClassVisitor.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * 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;
+
+
+public interface IClassVisitor
+{
+  public boolean visit(String pluginId, ILocation classLoc);
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IClazz.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IClazz.java
new file mode 100644
index 0000000..f7498b1
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IClazz.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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;
+
+import java.util.List;
+import java.util.Set;
+import org.eclipse.jdt.core.util.IConstantPoolEntry;
+import org.eclipse.jdt.core.util.IFieldInfo;
+import org.eclipse.jdt.core.util.IMethodInfo;
+
+public interface IClazz
+{
+  public Set getReferencedTypes();
+
+  public List getMethodRefs(List includes, List excludes, boolean genLineInfo);
+
+  public void resetMethodRefs();
+
+  public List getFieldRefs(List includes, List excludes, boolean genLineInfo);
+
+  public void resetFieldRefs();
+
+  public String getName();
+
+  public String getSuperClass();
+
+  public String[] getInterfaces();
+
+  public IFieldInfo[] getFieldInfo();
+
+  public IMethodInfo[] getMethodInfo();
+
+  public IConstantPoolEntry[] getConstantPoolEntries(int kind);
+
+  public boolean isInterface();
+
+  public int getAccessFlags();
+
+  public void resetClazz();
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IClazzVisitor.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IClazzVisitor.java
new file mode 100644
index 0000000..d1ae765
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IClazzVisitor.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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;
+
+public interface IClazzVisitor
+{
+  public boolean visit(IClazz clazz);
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IFileLocation.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IFileLocation.java
new file mode 100644
index 0000000..435931f
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IFileLocation.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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;
+
+import java.io.File;
+
+public interface IFileLocation extends ILocation
+{
+  public File getFile();
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IFragmentXML.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IFragmentXML.java
new file mode 100644
index 0000000..ca5fd67
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IFragmentXML.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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;
+
+import org.eclipse.wtp.releng.tools.component.internal.PluginXML;
+
+public interface IFragmentXML extends IPluginXML
+{
+  public static final String CONST_FRAGMENT_XML = "fragment.xml"; //$NON-NLS-1$
+
+  /**
+   * Answers the parent plugin of this fragment
+   * 
+   * @return Plugin the parent plugin of this fragment
+   */
+  public PluginXML getPlugin();
+
+  /**
+   * Answers the name of the plugin which contains this fragment.
+   * 
+   * @return String the name of the containing plugin, not <code>null</code>
+   */
+  public String getPluginName();
+
+  /**
+   * Answers the version of the plugin which contains this fragment.
+   * 
+   * @return String the version of the containing plugin, not <code>null</code>
+   */
+  public String getPluginVersion();
+
+  public String getFragmentName();
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IJavaVisitor.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IJavaVisitor.java
new file mode 100644
index 0000000..03e5eb1
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IJavaVisitor.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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;
+
+
+public interface IJavaVisitor
+{
+  public boolean visit(String pluginId, ILocation java);
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/ILibrary.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/ILibrary.java
new file mode 100644
index 0000000..d3c6d2c
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/ILibrary.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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;
+
+import java.util.Map;
+
+public interface ILibrary
+{
+  public static final String EXT_CLASS = "class"; //$NON-NLS-1$
+  /**
+   * Answers a mapping of (qualified) type names to <code>Type</code> objects
+   * which are found in this library.
+   * 
+   * @return Map a mapping of type names to <code>Type</code> objects.
+   */
+  public Map getTypes();
+
+  public void resetTypes();
+
+  public void accept(IClazzVisitor visitor);
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/ILocation.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/ILocation.java
new file mode 100644
index 0000000..b1ea925
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/ILocation.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An <code>ILocation</code> object is an abstraction on the idea of a file.
+ * ILocations can refer to files that are directly located in the filesystem, or
+ * they can refer to files that are housed in zip/jar files. Using an
+ * <code>ILocation</code>, clients can traverse zip/jar files like they are
+ * directories.
+ * <p>
+ * Clients can create <code>ILocation</code> objects using
+ * com.example.location.Location.createLocation(File file)
+ */
+public interface ILocation
+{
+  /**
+   * @return ILocation This location's parent, or <code>null</code> if this
+   *         location was created without a parent.
+   */
+  ILocation getParent();
+
+  /**
+   * @return String The name of this location.
+   */
+  String getName();
+
+  /**
+   * @return String The absolute path of this location, this path may not be
+   *         usable by new File(String) to create files because it may refer to
+   *         structures inside of zip/jar files.
+   */
+  String getAbsolutePath();
+
+  /**
+   * Answers the <code>InputStream</code>
+   * 
+   * @return InputStream
+   * @throws IOException
+   */
+  InputStream getInputStream() throws IOException;
+
+  /**
+   * @return ILocationChildrenIterator which iterates over the children of this
+   *         location.
+   */
+  ILocationChildrenIterator childIterator();
+
+  /**
+   * @return boolean <code>true</code> if this location has children.
+   */
+  boolean hasChildren();
+
+  /**
+   * Method accept.
+   * 
+   * @param visitor
+   */
+  void accept(ILocationVisitor visitor);
+
+  /**
+   * Method createChild.
+   * 
+   * @param relativePath
+   * @return ILocation
+   */
+  ILocation createChild(String relativePath);
+
+  /**
+   * Method createSibling.
+   * 
+   * @param relativePath
+   * @return ILocation
+   */
+  ILocation createSibling(String relativePath);
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/ILocationChildrenIterator.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/ILocationChildrenIterator.java
new file mode 100644
index 0000000..197e8fd
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/ILocationChildrenIterator.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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;
+
+/**
+ * The <code>ILocationChildrenIterator</code> is a simple iterator that
+ * iterates over the children of a location. A <code>null</code> is returned
+ * when the end of the children list is reached.
+ */
+
+public interface ILocationChildrenIterator
+{
+  /**
+   * Answers the next child location.
+   * 
+   * @return ILocation The next child location, or <code>null</code> if there
+   *         are no more children.
+   */
+  ILocation next();
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/ILocationVisitor.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/ILocationVisitor.java
new file mode 100644
index 0000000..a443e19
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/ILocationVisitor.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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;
+
+/**
+ * An <code>ILocationVisitor</code> can be used to traverse a tree of
+ * locations.
+ */
+public interface ILocationVisitor
+{
+  /**
+   * Allows this visitor to investigate the given location.
+   * 
+   * @param location
+   *          the current location in the traversal
+   * @return boolean <code>true</code> if the traversal should continue into
+   *         the children of the given location, <code>false</code> otherwise.
+   */
+  boolean accept(ILocation location);
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IPluginXML.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IPluginXML.java
new file mode 100644
index 0000000..7df2261
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IPluginXML.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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;
+
+import java.util.List;
+
+public interface IPluginXML
+{
+  public static final String CONST_PLUGIN_XML = "plugin.xml"; //$NON-NLS-1$
+
+  /**
+   * Answers the libraries that are declared in this plugin.
+   * 
+   * @return List libraries in this plugin
+   */
+  public List getLibraries();
+
+  /**
+   * Answers the name of this plugin. Plugin names do not contain the version
+   * identifier, for example, org.eclipse.core.resources.
+   * 
+   * @return String the name of the plugin, not <code>null</code>.
+   */
+  public String getName();
+
+  /**
+   * Answers the version identifier for the plugin. A version identifier is a
+   * '.' delimited set of numbers, for example, 2.0.1.5.
+   * 
+   * @return String the plugin version, not <code>null</code>.
+   */
+  public String getVersion();
+
+  /**
+   * The unique identifier is a concatination of the plugin name, and '_' and
+   * the plugin version.
+   * 
+   * @return String the unique identifier of the plugin.
+   */
+  public String getUniqueIdentifier();
+
+  public void accept(IClazzVisitor visitor);
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IZipLocation.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IZipLocation.java
new file mode 100644
index 0000000..6a0b987
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/IZipLocation.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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;
+
+import java.util.zip.ZipFile;
+
+public interface IZipLocation extends IFileLocation
+{
+  public ZipFile getZipFile();
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/APIRefCompatibilityScanner.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/APIRefCompatibilityScanner.java
new file mode 100644
index 0000000..676a1e0
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/APIRefCompatibilityScanner.java
@@ -0,0 +1,579 @@
+/*******************************************************************************
+ * 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.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+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 javax.xml.parsers.ParserConfigurationException;
+import org.eclipse.core.runtime.IPlatformRunnable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.wtp.releng.tools.component.CommandOptionParser;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.ILocationVisitor;
+import org.eclipse.wtp.releng.tools.component.api.API2ComponentAPI;
+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.Location;
+import org.eclipse.wtp.releng.tools.component.xsl.XSLUtil;
+import org.xml.sax.SAXException;
+
+public class APIRefCompatibilityScanner implements IPlatformRunnable
+{
+  private String use;
+  private String outputDir;
+
+  public String getOutputDir()
+  {
+    return outputDir;
+  }
+
+  public void setOutputDir(String outputDir)
+  {
+    this.outputDir = addTrailingSeperator(outputDir);
+  }
+
+  public String getUse()
+  {
+    return use;
+  }
+
+  public void setUse(String use)
+  {
+    this.use = use;
+  }
+
+  private Map pluginId2APIInfo = new HashMap();
+  private Map pkg2APIInfo = new HashMap();
+  private BreakageReport breakageReport = new BreakageReport();
+
+  public void execute()
+  {
+    ILocation apiInfoLoc = Location.createLocation(new File(outputDir + "_tmp_componentapiref"));
+    apiInfoLoc.accept(new ILocationVisitor()
+    {
+      public boolean accept(ILocation location)
+      {
+        if (location.getName().endsWith("api-info.xml"))
+        {
+          ComponentAPI compAPI = new ComponentAPI();
+          compAPI.setLocation(location);
+          try
+          {
+            compAPI.load();
+            pluginId2APIInfo.put(compAPI.getName(), location);
+            for (Iterator it = compAPI.getPackageAPIs().iterator(); it.hasNext();)
+            {
+              String pkgName = ((PackageAPI)it.next()).getName();
+              List locations = (List)pkg2APIInfo.get(pkgName);
+              if (locations == null)
+              {
+                locations = new ArrayList();
+                pkg2APIInfo.put(pkgName, locations);
+              }
+              locations.add(location);
+            }
+          }
+          catch (IOException ioe)
+          {
+            throw new RuntimeException(ioe);
+          }
+        }
+        return true;
+      }
+    });
+    ILocation useLoc = Location.createLocation(new File(use));
+    useLoc.accept(new ILocationVisitor()
+    {
+      public boolean accept(ILocation location)
+      {
+        if (location.getName().endsWith(".xml"))
+        {
+          try
+          {
+            References refs = new References();
+            refs.load(location.getInputStream());
+            for (Iterator it = refs.getPluginRefs().iterator(); it.hasNext();)
+            {
+              PluginRef pluginRef = (PluginRef)it.next();
+              String pluginId = pluginRef.getId();
+              ILocation loc = (ILocation)pluginId2APIInfo.get(pluginId);
+              if (loc != null)
+              {
+                ComponentAPI compAPI = new ComponentAPI();
+                compAPI.setLocation(loc);
+                compAPI.load();
+                for (Iterator it2 = pluginRef.getClassRefs().iterator(); it2.hasNext();)
+                {
+                  ClassRef classRef = (ClassRef)it2.next();
+                  String className = classRef.getName();
+                  if (className.endsWith("[]"))
+                    className = className.substring(0, className.length() - 2);
+                  int i = className.lastIndexOf('.');
+                  String pkgName = (i != -1) ? className.substring(0, i) : "";
+                  String localName = (i != -1) ? className.substring(i + 1) : className;
+                  PackageAPI pkgAPI = compAPI.getPackageAPI(pkgName);
+                  if (pkgAPI != null)
+                  {
+                    ClassAPI classAPI = pkgAPI.getClassAPI(localName);
+                    if (classAPI != null)
+                    {
+                      for (Iterator it3 = classRef.getMethodRefs().iterator(); it3.hasNext();)
+                      {
+                        MethodRef methodRef = (MethodRef)it3.next();
+                        String name = methodRef.getName();
+                        String desc = methodRef.getDescriptor();
+                        if (hasMethod(classAPI, name, desc))
+                        {
+                          classRef.removeMethodRef(name, desc);
+                        }
+                      }
+                      for (Iterator it3 = classRef.getFieldRefs().iterator(); it3.hasNext();)
+                      {
+                        FieldRef fieldRef = (FieldRef)it3.next();
+                        String name = fieldRef.getName();
+                        String desc = fieldRef.getDescriptor();
+                        if (hasField(classAPI, name))
+                        {
+                          classRef.removeFieldRef(name, desc);
+                        }
+                      }
+                      if (classRef.getMethodRefs().isEmpty() && classRef.getFieldRefs().isEmpty())
+                      {
+                        pluginRef.removeClassRef(classRef.getName());
+                      }
+                    }
+                  }
+                }
+                if (pluginRef.getClassRefs().isEmpty())
+                {
+                  refs.removePluginRef(pluginId);
+                }
+              }
+            }
+            if (!refs.getPluginRefs().isEmpty())
+            {
+              breakageReport.addRefs(refs);
+            }
+          }
+          catch (ParserConfigurationException pce)
+          {
+            throw new RuntimeException(pce);
+          }
+          catch (SAXException saxe)
+          {
+            throw new RuntimeException(saxe);
+          }
+          catch (IOException ioe)
+          {
+            throw new RuntimeException(ioe);
+          }
+        }
+        return true;
+      }
+    });
+    try
+    {
+      save();
+      genHTML();
+    }
+    catch (IOException ioe)
+    {
+      throw new RuntimeException(ioe);
+    }
+  }
+
+  private boolean hasMethod(ClassAPI classAPI, String name, String desc)
+  {
+    if (classAPI != null && name != null && desc != null)
+    {
+      if (classAPI.getMethodAPI(name, desc) != null)
+      {
+        return true;
+      }
+      else
+      {
+        String superClassName = classAPI.getSuperClass();
+        if (hasMethod(superClassName, name, desc))
+        {
+          return true;
+        }
+        else
+        {
+          for (Iterator it = classAPI.getInterfaces().iterator(); it.hasNext();)
+          {
+            if (hasMethod(it.next().toString(), name, desc))
+            {
+              return true;
+            }
+          }
+          return false;
+        }
+      }
+    }
+    return false;
+  }
+
+  private boolean hasMethod(String className, String name, String desc)
+  {
+    int i = className.lastIndexOf('.');
+    String pkgName = (i != -1) ? className.substring(0, i) : "";
+    String localName = (i != -1) ? className.substring(i + 1) : className;
+    List locations = (List)pkg2APIInfo.get(pkgName);
+    if (locations != null)
+    {
+      for (Iterator it = locations.iterator(); it.hasNext();)
+      {
+        ILocation location = (ILocation)it.next();
+        // ILocation location = (ILocation)pkg2APIInfo.get(pkgName);
+        // if (location != null)
+        // {
+        try
+        {
+          ComponentAPI compAPI = getComponentAPI(location);
+          if (compAPI != null)
+          {
+            PackageAPI pkgAPI = compAPI.getPackageAPI(pkgName);
+            if (pkgAPI != null)
+            {
+              ClassAPI superClassAPI = pkgAPI.getClassAPI(localName);
+              if (superClassAPI != null)
+              {
+                return hasMethod(superClassAPI, name, desc);
+              }
+            }
+          }
+        }
+        catch (IOException ioe)
+        {
+          ioe.printStackTrace();
+        }
+      }
+    }
+    else
+    {
+      // use reflection, needed for java.* packages
+      ClassAPI superClassAPI = loadClass(className);
+      if (superClassAPI != null)
+      {
+        return hasMethod(superClassAPI, name, desc);
+      }
+    }
+    return false;
+  }
+
+  private boolean hasField(ClassAPI classAPI, String name)
+  {
+    if (classAPI != null && name != null)
+    {
+      if (classAPI.getFieldAPI(name) != null)
+      {
+        return true;
+      }
+      else
+      {
+        String superClassName = classAPI.getSuperClass();
+        if (hasField(superClassName, name))
+        {
+          return true;
+        }
+        else
+        {
+          for (Iterator it = classAPI.getInterfaces().iterator(); it.hasNext();)
+          {
+            if (hasField(it.next().toString(), name))
+            {
+              return true;
+            }
+          }
+          return false;
+        }
+      }
+    }
+    return false;
+  }
+
+  private boolean hasField(String className, String name)
+  {
+    int i = className.lastIndexOf('.');
+    String pkgName = (i != -1) ? className.substring(0, i) : "";
+    String localName = (i != -1) ? className.substring(i + 1) : className;
+    List locations = (List)pkg2APIInfo.get(pkgName);
+    if (locations != null)
+    {
+      for (Iterator it = locations.iterator(); it.hasNext();)
+      {
+        ILocation location = (ILocation)it.next();
+        // ILocation location = (ILocation)pkg2APIInfo.get(pkgName);
+        // if (location != null)
+        // {
+        try
+        {
+          ComponentAPI compAPI = getComponentAPI(location);
+          if (compAPI != null)
+          {
+            PackageAPI pkgAPI = compAPI.getPackageAPI(pkgName);
+            if (pkgAPI != null)
+            {
+              ClassAPI superClassAPI = pkgAPI.getClassAPI(localName);
+              if (superClassAPI != null)
+              {
+                return hasField(superClassAPI, name);
+              }
+            }
+          }
+        }
+        catch (IOException ioe)
+        {
+          ioe.printStackTrace();
+        }
+      }
+    }
+    else
+    {
+      // use reflection, needed for java.* packages
+      ClassAPI superClassAPI = loadClass(className);
+      if (superClassAPI != null)
+      {
+        return hasField(superClassAPI, name);
+      }
+    }
+    return false;
+  }
+
+  private ClassAPI loadClass(String className)
+  {
+    // Use reflection to load other packages
+    try
+    {
+      Class clazz = ClassLoader.getSystemClassLoader().loadClass(className);
+      ClassAPI classAPI = new ClassAPI();
+      classAPI.setName(className);
+      if (className.equals("java.lang.Object"))
+        classAPI.setSuperClass("");
+      else
+        classAPI.setSuperClass("java.lang.Object");
+      // TODO: We need to add protected methods as well
+      Method[] publicMethods = clazz.getMethods();
+      Field[] publicFields = clazz.getFields();
+      for (int j = 0; j < publicMethods.length; j++)
+      {
+        MethodAPI methodAPI = new MethodAPI();
+        methodAPI.setName(publicMethods[j].getName());
+        StringBuffer descriptor = new StringBuffer();
+        descriptor.append('(');
+        Class[] params = publicMethods[j].getParameterTypes();
+        for (int k = 0; k < params.length; k++)
+        {
+          String paramName = params[k].getName().replace('.', '/');
+          if (paramName.charAt(0) == '[')
+            descriptor.append(paramName);
+          else
+            descriptor.append(Signature.createTypeSignature(paramName, true));
+          //descriptor.append(params[k].toString());
+        }
+        descriptor.append(')');
+        Class returnType = publicMethods[j].getReturnType();
+        if (returnType != null)
+        {
+          String returnTypeName = returnType.getName().replace('.', '/');
+          if (returnTypeName.charAt(0) == '[')
+            descriptor.append(returnTypeName);
+          else
+            descriptor.append(Signature.createTypeSignature(returnTypeName, true));
+          //descriptor.append(returnType.toString());
+        }
+        else
+        {
+          descriptor.append('V');
+        }
+        methodAPI.setDescriptor(descriptor.toString());
+        classAPI.addMethodAPI(methodAPI);
+      }
+      for (int j = 0; j < publicFields.length; j++)
+      {
+        FieldAPI fieldAPI = new FieldAPI();
+        fieldAPI.setName(publicFields[j].getName());
+        classAPI.addFieldAPI(fieldAPI);
+      }
+      return classAPI;
+    }
+    catch (ClassNotFoundException cnfe)
+    {
+      return null;
+      // do nothing
+    }
+  }
+
+  private int cacheSize = 20;
+  private List cachedIds = new ArrayList(cacheSize);
+  private List cachedCompAPIs = new ArrayList(cacheSize);
+
+  private ComponentAPI getComponentAPI(ILocation location) throws IOException
+  {
+    int index = cachedIds.indexOf(location);
+    if (index != -1)
+    {
+      ComponentAPI compAPI = (ComponentAPI)cachedCompAPIs.get(index);
+      if (index != 0)
+      {
+        cachedIds.remove(index);
+        cachedCompAPIs.remove(index);
+        cachedIds.add(0, location);
+        cachedCompAPIs.add(0, compAPI);
+      }
+      return compAPI;
+    }
+    ComponentAPI compAPI = new ComponentAPI();
+    compAPI.setLocation(location);
+    compAPI.load();
+    if (cachedCompAPIs.size() == cacheSize)
+    {
+      cachedIds.remove(cacheSize - 1);
+      cachedCompAPIs.remove(cacheSize - 1);
+    }
+    cachedIds.add(0, location);
+    cachedCompAPIs.add(0, compAPI);
+    return compAPI;
+  }
+
+  public void save() throws IOException
+  {
+    File file = new File(outputDir + "api-ref-compatibility.xml");
+    file.getParentFile().mkdirs();
+    breakageReport.save(new FileOutputStream(file));
+  }
+
+  private void genHTML()
+  {
+    try
+    {
+      XSLUtil.transform(Platform.getBundle("org.eclipse.wtp.releng.tools.component.core").getResource("org/eclipse/wtp/releng/tools/component/xsl/api-ref-compatibility.xsl").openStream(), new ByteArrayInputStream(breakageReport.toString().getBytes()), new FileOutputStream(new File(outputDir + "api-ref-compatibility.html")), outputDir);
+    }
+    catch (Throwable e)
+    {
+      throw new RuntimeException(e);
+    }
+  }
+
+  protected static String addTrailingSeperator(String s)
+  {
+    if (s != null && !s.endsWith("/") && !s.endsWith("\\"))
+    {
+      StringBuffer sb = new StringBuffer(s);
+      sb.append('/');
+      return sb.toString();
+    }
+    else
+    {
+      return s;
+    }
+  }
+
+  public Object run(Object arguments)
+  {
+    String src = System.getProperty("src");
+    String use = System.getProperty("use");
+    String outputDir = System.getProperty("outputDir");
+    List args = new ArrayList();
+    if (src != null)
+    {
+      args.add("-src");
+      args.addAll(tokenize(src));
+    }
+    if (use != null)
+    {
+      args.add("-use");
+      args.addAll(tokenize(use));
+    }
+    args.add("-outputDir");
+    args.add(outputDir);
+    try
+    {
+      main((String[])args.toArray(new String[0]));
+    }
+    catch (Throwable t)
+    {
+      t.printStackTrace();
+    }
+    return IPlatformRunnable.EXIT_OK;
+  }
+
+  private List tokenize(String s)
+  {
+    StringTokenizer st = new StringTokenizer(s, ",");
+    List tokens = new ArrayList(st.countTokens());
+    while(st.hasMoreTokens())
+      tokens.add(st.nextToken());
+    return tokens;
+  }
+
+  public static void main(String[] args)
+  {
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    Collection src = (Collection)options.get("src");
+    Collection use = (Collection)options.get("use");
+    Collection outputDir = (Collection)options.get("outputDir");
+    if (src == null || use == null || outputDir == null || src.isEmpty() || use.isEmpty() || outputDir.isEmpty())
+    {
+      printUsage();
+      System.exit(-1);
+    }
+    String outputDirString = addTrailingSeperator((String)outputDir.iterator().next());
+    String componentxmlref = outputDirString + "_tmp_componentxmlref";
+    String componentapiref = outputDirString + "_tmp_componentapiref";
+
+    Plugin2API plugin2API = new Plugin2API();
+    plugin2API.setSrc(src);
+    plugin2API.setOutputDir(componentxmlref);
+    plugin2API.execute();
+
+    API2ComponentAPI api2CompAPI = new API2ComponentAPI();
+    api2CompAPI.setApi(componentxmlref);
+    api2CompAPI.setOutputDir(componentapiref);
+    api2CompAPI.setIncludeInnerClass(true);
+    api2CompAPI.setIncludeInterfaces(true);
+    for (Iterator it = src.iterator(); it.hasNext();)
+    {
+      api2CompAPI.setSrc((String)it.next());
+      api2CompAPI.execute();
+    }
+
+    APIRefCompatibilityScanner scanner = new APIRefCompatibilityScanner();
+    scanner.setUse((String)use.iterator().next());
+    scanner.setOutputDir(outputDirString);
+    scanner.execute();
+  }
+
+  private static void printUsage()
+  {
+    System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.adopters.APIRefCompatibilityScanner -src <src> -use <use> -outputDir <outputDir> [-options]");
+    System.out.println("");
+    System.out.println("\t-src\t\t<src>\t\tlocation of your Eclipse-based product");
+    System.out.println("\t-use\t\t<use>\t\tlocation of adopters' API usage data");
+    System.out.println("\t-outputDir\t<outputDir>\toutput directory");
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/BreakageReport.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/BreakageReport.java
new file mode 100644
index 0000000..c13764d
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/BreakageReport.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.parsers.ParserConfigurationException;
+import org.xml.sax.SAXException;
+
+public class BreakageReport
+{
+  List refs;
+
+  public void addRefs(References ref)
+  {
+    if (refs == null)
+      refs = new ArrayList();
+    refs.add(ref);
+  }
+
+  public List getRefs()
+  {
+    if (refs == null)
+      return new ArrayList(0);
+    else
+      return new ArrayList(refs);
+  }
+
+  public void load(InputStream is) throws IOException, ParserConfigurationException, SAXException
+  {
+    byte[] b = new byte[1024];
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    int read = is.read(b);
+    while (read != -1)
+    {
+      baos.write(b, 0, read);
+      read = is.read(b);
+    }
+    is.close();
+    String content = baos.toString();
+    int start = content.indexOf("<references");
+    int end = content.indexOf("</references>");
+    int offset = "</references>".length();
+    while (start != -1 && end != -1)
+    {
+      String s = content.substring(start, end + offset);
+      References ref = new References();
+      ref.load(new ByteArrayInputStream(s.getBytes()));
+      addRefs(ref);
+      content = content.substring(end + offset);
+      start = content.indexOf("<references");
+      end = content.indexOf("</references>");
+    }
+  }
+
+  public void save(OutputStream os) throws IOException
+  {
+    byte[] content = toString().getBytes();
+    os.write(content);
+    os.close();
+  }
+
+  public String toString()
+  {
+    StringBuffer sb = new StringBuffer();
+    sb.append("<breakageReport>");
+    for (Iterator it = getRefs().iterator(); it.hasNext();)
+      sb.append(it.next().toString());
+    sb.append("</breakageReport>");
+    return sb.toString();
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/ClassRef.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/ClassRef.java
new file mode 100644
index 0000000..6bb92c6
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/ClassRef.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * The ClassRef class manages a class reference.  It holds the number of field references
+ * and method references as well as tracks the implementors, subclasses, and instantiators
+ * of the class.  It is a sub type of NamedRef.
+ */
+public class ClassRef extends NamedRef {
+  // Instance variables for various reference counts
+  private int implementCount;
+  private int subclassCount;
+  private int instantiateCount;
+  private Map methodRefs;
+  private Map fieldRefs;
+
+  /**
+   * @return int number of implementors
+   */
+  public int getImplementCount() {
+    return implementCount;
+  }
+  
+  /**
+   * Set the implementor count
+   * @param implementCount
+   */
+  public void setImplementCount(int implementCount) {
+    this.implementCount = implementCount;
+  }
+  
+  /**
+   * Increment the implementor count by 1
+   */
+  public void incImplementCount() {
+    this.implementCount++;
+  }
+  
+  /**
+   * @return int instantiator count
+   */
+  public int getInstantiateCount() {
+    return instantiateCount;
+  }
+  
+  /**
+   * Set the instantiator count
+   * @param int instantiateCount
+   */
+  public void setInstantiateCount(int instantiateCount) {
+    this.instantiateCount = instantiateCount;
+  }
+  
+  /**
+   * Increment the instantiator count by 1.
+   */
+  public void incInstantiateCount() {
+    this.instantiateCount++;
+  }
+  
+  /**
+   * @return int subclass count
+   */
+  public int getSubclassCount() {
+    return subclassCount;
+  }
+  
+  /**
+   * Set the subclass count.
+   * @param int subclassCount
+   */
+  public void setSubclassCount(int subclassCount) {
+    this.subclassCount = subclassCount;
+  }
+  
+  /**
+   * Increment the subclass count by 1.
+   */
+  public void incSubclassCount() {
+    this.subclassCount++;
+  }
+
+  /**
+   * @return the related method references for this class
+   */
+  public Collection getMethodRefs() {
+    if (methodRefs != null)
+      return new ArrayList(methodRefs.values());
+    return Collections.EMPTY_LIST;
+  }
+
+  /**
+   * @param name
+   * @param descriptor
+   * @return MethodRef for the given name and descriptor info
+   */
+  public MethodRef getMethodRef(String name, String descriptor) {
+    if (methodRefs != null)
+      return (MethodRef)methodRefs.get(encode(name, descriptor));
+    return null;
+  }
+
+  /**
+   * Add a method reference to the class reference.
+   * @param methodRef
+   */
+  public void addMethodRef(MethodRef methodRef) {
+    if (methodRefs == null)
+      methodRefs = new HashMap();
+    methodRefs.put(encode(methodRef.getName(), methodRef.getDescriptor()), methodRef);
+  }
+
+  /**
+   * Remove method ref with given name and descriptor info
+   * @param name
+   * @param descriptor
+   */
+  public void removeMethodRef (String name, String descriptor) {
+    if (methodRefs != null)
+      methodRefs.remove(encode(name, descriptor));
+  }
+
+  /**
+   * Get the field references for this class reference.
+   * @return Collection
+   */
+  public Collection getFieldRefs() {
+    if (fieldRefs != null)
+      return new ArrayList(fieldRefs.values());
+    return Collections.EMPTY_LIST;
+  }
+
+  /**
+   * @param name
+   * @param descriptor
+   * @return FieldRef
+   */
+  public FieldRef getFieldRef(String name, String descriptor) {
+    if (fieldRefs != null)
+      return (FieldRef)fieldRefs.get(encode(name, descriptor));
+    return null;
+  }
+
+  /**
+   * Add the FieldRef to the Class Reference.
+   * @param fieldRef
+   */
+  public void addFieldRef(FieldRef fieldRef) {
+    if (fieldRefs == null)
+      fieldRefs = new HashMap();
+    fieldRefs.put(encode(fieldRef.getName(), fieldRef.getDescriptor()), fieldRef);
+  }
+
+  /**
+   * Remove associated field reference.
+   * @param name
+   * @param descriptor
+   */
+  public void removeFieldRef(String name, String descriptor) {
+    if (fieldRefs != null)
+      fieldRefs.remove(encode(name, descriptor));
+  }
+  
+  /**
+   * Encode the given name and descriptor into a string
+   * @param name
+   * @param descriptor
+   * @return encoded String
+   */
+  private String encode(String name, String descriptor) {
+    StringBuffer sb = new StringBuffer();
+    sb.append(name);
+    sb.append('#');
+    sb.append(descriptor);
+    return sb.toString();
+  }
+
+  /**
+   * @return String toString override
+   */
+  public String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.append("<class name=\""); //$NON-NLS-1$
+    sb.append(getName());
+    sb.append("\" ref=\""); //$NON-NLS-1$
+    sb.append(getRefCount());
+    sb.append("\" impl=\""); //$NON-NLS-1$
+    sb.append(getImplementCount());
+    sb.append("\" subclass=\""); //$NON-NLS-1$
+    sb.append(getSubclassCount());
+    sb.append("\" instantiate=\""); //$NON-NLS-1$
+    sb.append(getInstantiateCount());
+    sb.append("\">"); //$NON-NLS-1$
+    for (Iterator it = getMethodRefs().iterator(); it.hasNext();)
+      sb.append(it.next().toString());
+    for (Iterator it = getFieldRefs().iterator(); it.hasNext();)
+      sb.append(it.next().toString());
+    sb.append("</class>"); //$NON-NLS-1$
+    return sb.toString();
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/CombineClass2Reference.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/CombineClass2Reference.java
new file mode 100644
index 0000000..3a934b6
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/CombineClass2Reference.java
@@ -0,0 +1,904 @@
+/*******************************************************************************
+ * 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.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.eclipse.wtp.releng.tools.component.CommandOptionParser;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.api.ComponentXMLVisitor;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentXML;
+import org.eclipse.wtp.releng.tools.component.internal.Location;
+import org.eclipse.wtp.releng.tools.component.internal.Package;
+import org.eclipse.wtp.releng.tools.component.internal.Plugin;
+import org.eclipse.wtp.releng.tools.component.internal.Type;
+import org.eclipse.wtp.releng.tools.component.xsl.XSLUtil;
+
+/**
+ * This class is used to take the output usage.xml files generated from SimpleClass2Reference
+ * and combine them into a helpful CSV or HTML file format displaying API and non-API internal
+ * usage for each logically grouped component team in WTP.  The main method can be invoked with
+ * the following three command line arguments:
+ * 
+ * "src" = the zip or folder location of the usage.xml files
+ * "api" = the zip or folder location of the component.xml files defining the API base
+ * "output" = the location of the output csv and html combined files
+ */
+public class CombineClass2Reference extends ComponentTeamScanner implements IOutputConstants {
+  // Command Line arguments	
+  public static final String ARG_SOURCE = "src"; //$NON-NLS-1$
+  public static final String ARG_OUTPUT = "output"; //$NON-NLS-1$
+  public static final String ARG_API = "api"; //$NON-NLS-1$
+  public static final String ARG_SHOW_ADOPTER_NUMBERS = "showAdopterNumbers"; //$NON-NLS-1$
+  public static final String ARG_SHOW_DETAILED_NUMBERS = "showDetailedNumbers"; //$NON-NLS-1$
+  
+  // Instance variables for command line arguments
+  private Collection src;
+  private String output;
+  private Collection api;
+  private boolean shouldShowIndividualAdopters = false;
+  private boolean shouldShowDetailedNumbers = false;
+  
+  private List contactNames;
+  
+  // Class variables for String values
+  private static final String CLASS_CVS_FILE_EXTENSION = ".class.csv"; //$NON-NLS-1$
+  private static final String PACKAGE_CVS_FILE_EXTENSION = ".pkg.csv"; //$NON-NLS-1$
+  private static final String PLUGIN_CVS_FILE_EXTENSION = ".plugin.csv"; //$NON-NLS-1$
+  private static final String CLASS_HTML_FILE_EXTENSION = ".class.html"; //$NON-NLS-1$
+  private static final String PACKAGE_HTML_FILE_EXTENSION = ".pkg.html"; //$NON-NLS-1$
+  private static final String PLUGIN_HTML_FILE_EXTENSION = ".plugin.html"; //$NON-NLS-1$
+  private static final String COMBINE_PLUGINS_FILE = "org/eclipse/wtp/releng/tools/component/xsl/combine-plugin2ref.xsl"; //$NON-NLS-1$
+  private static final String COMBINE_PACKAGES_FILE = "org/eclipse/wtp/releng/tools/component/xsl/combine-pkg2ref.xsl"; //$NON-NLS-1$
+  private static final String COMBINE_CLASSES_FILE = "org/eclipse/wtp/releng/tools/component/xsl/combine-class2ref.xsl"; //$NON-NLS-1$
+  
+  // Class variables for reference usage constants
+  private static final int CLASS_USAGE = 0;
+  private static final int PACKAGE_USAGE = 1;
+  private static final int PLUGIN_USAGE = 2;
+
+  /**
+   * The UsageCount class is a simple caching mechanism to track API and non API usages.
+   */
+  private class UsageCount {
+	/**
+	 * Uses in an accordance with API contract
+	 */  
+    public int apiUse = 0;
+    /**
+     * Internal or other non API usages outside API contract
+     */
+    public int nonAPIUse = 0;
+    
+    private HashMap methodRefs = null;
+    private HashMap fieldRefs = null;
+    
+    private HashMap nestedUsageCounts;
+    
+    /**
+     * @return HashMap of the nested MethodRefs for this class usage
+     */
+    public HashMap getMethodRefs() {
+    	if (methodRefs == null)
+    		methodRefs = new HashMap();
+    	return methodRefs;
+    }
+    
+    /**
+     * @return HashMap of nested FieldRefs for this class usage
+     */
+    public HashMap getFieldRefs() {
+    	if (fieldRefs == null)
+    		fieldRefs = new HashMap();
+    	return fieldRefs;
+    }
+    
+    /**
+     * @return HashMap of nested Usage Counts for specific product details
+     */
+    public HashMap getNestedUsageCounts() {
+    	if (nestedUsageCounts==null)
+    		nestedUsageCounts = new HashMap();
+    	return nestedUsageCounts;
+    }
+    
+    /**
+     * Get the nested usage count according to the string contact passed or create a new one.
+     * 
+     * @param contactInfo
+     * @return UsageCount
+     */
+    public UsageCount getNestedUsageCount(String contactInfo) {
+    	UsageCount usageCount = (UsageCount) getNestedUsageCounts().get(contactInfo);
+    	if (usageCount == null) {
+    		usageCount = new UsageCount();
+    		getNestedUsageCounts().put(contactInfo, usageCount);
+    	}
+    	return usageCount;
+    }
+    
+    /**
+     * Add the given method refs to the existing method refs
+     * @param someMethodRefs Collection
+     */
+    public void addMethodRefs(Collection someMethodRefs) {
+    	for (Iterator i = someMethodRefs.iterator(); i.hasNext();) {
+    		MethodRef aMethodRef = (MethodRef) i.next();
+    		if (!getMethodRefs().keySet().contains(aMethodRef.getName())) {
+    			getMethodRefs().put(aMethodRef.getName(), new Integer(aMethodRef.getRefCount()));
+    		} else {
+    			int updatedCount = aMethodRef.getRefCount()+ ((Integer)getMethodRefs().get(aMethodRef.getName())).intValue();
+    			getMethodRefs().put(aMethodRef.getName(), new Integer(updatedCount));
+    		}
+    	}
+    }
+    
+    /**
+     * Add the given field refs to the existing field refs
+     * @param someFieldRefs Collection
+     */
+    public void addFieldRefs(Collection someFieldRefs) {
+    	for (Iterator i = someFieldRefs.iterator(); i.hasNext();) {
+    		FieldRef aFieldRef = (FieldRef) i.next();
+    		if (!getFieldRefs().keySet().contains(aFieldRef.getName())) {
+    			getFieldRefs().put(aFieldRef.getName(), new Integer(aFieldRef.getRefCount()));
+    		} else {
+    			int updatedCount = aFieldRef.getRefCount()+ ((Integer)getFieldRefs().get(aFieldRef.getName())).intValue();
+    			getFieldRefs().put(aFieldRef.getName(), new Integer(updatedCount));
+    		}
+    	}
+    }
+    
+    /**
+     * Add the given methodrefs data into the existing method refs data
+     * @param someMethodRefs HashMap
+     */
+    public void addMethodRefs(HashMap someMethodRefs) {
+    	if (someMethodRefs == null)
+    		return;
+    	for (Iterator i = someMethodRefs.keySet().iterator(); i.hasNext();) {
+    		String aMethodRefName = (String) i.next();
+    		if (!getMethodRefs().keySet().contains(aMethodRefName)) {
+    			getMethodRefs().put(aMethodRefName, someMethodRefs.get(aMethodRefName));
+    		} else {
+    			int updatedCount = ((Integer)someMethodRefs.get(aMethodRefName)).intValue()+ ((Integer)getMethodRefs().get(aMethodRefName)).intValue();
+    			getMethodRefs().put(aMethodRefName, new Integer(updatedCount));
+    		}
+    	}
+    }
+    
+    /**
+     * Add the given field ref data into the existing field ref data
+     * @param someFieldRefs
+     */
+    public void addFieldRefs(HashMap someFieldRefs) {
+    	if (someFieldRefs == null)
+    		return;
+    	for (Iterator i = someFieldRefs.keySet().iterator(); i.hasNext();) {
+    		String aFieldRefName = (String) i.next();
+    		if (!getFieldRefs().keySet().contains(aFieldRefName)) {
+    			getFieldRefs().put(aFieldRefName, someFieldRefs.get(aFieldRefName));
+    		} else {
+    			int updatedCount = ((Integer)someFieldRefs.get(aFieldRefName)).intValue()+ ((Integer)getFieldRefs().get(aFieldRefName)).intValue();
+    			getFieldRefs().put(aFieldRefName, new Integer(updatedCount));
+    		}
+    	}
+    }
+  }
+
+  /**
+   * Default Constructor
+   */
+  public CombineClass2Reference() {
+    super();
+  }
+
+  /**
+   * @return Collection of source usage.xml files
+   */
+  public Collection getSrc() {
+    return src;
+  }
+
+  /**
+   * Cache the command line argument for where the source usage.xml files are
+   * @param src
+   */
+  public void setSrc(Collection src) {
+    this.src = src;
+  }
+
+  /**
+   * @return String location of the output for the generated files
+   */
+  public String getOutput() {
+    return output;
+  }
+
+  /**
+   * Cache the command line argument output location for the generated files
+   * @param output
+   */
+  public void setOutput(String output) {
+    this.output = output;
+  }
+
+  /**
+   * @return Collection of API locations for component.xml files
+   */
+  public Collection getApi() {
+    return api;
+  }
+
+  /**
+   * Cache the command line argument for where the API component.xml file locations are
+   * @param api
+   */
+  public void setApi(Collection api) {
+    this.api = api;
+  }
+
+  /**
+   * This is a helper method to create a map of plugin ids and associated component.xml files. 
+   * These component.xml files are the one specified by the collection in the "api" command
+   * line argument.
+   * 
+   * @return Map of plugin ids to component.xml files
+   */
+  private Map collectComponentXMLFiles() {
+	  Map pluginId2CompXML = new HashMap();
+	  if (getApi() != null) {
+	      for (Iterator i = getApi().iterator(); i.hasNext();) {
+	    	// For each API file or location, create a Location object
+	        ILocation apiLocation = Location.createLocation(new File((String)i.next()));
+	        // Create a visitor to traverse the location and collect all contained component.xml files
+	        ComponentXMLVisitor compXMLVisitor = new ComponentXMLVisitor();
+	        apiLocation.accept(compXMLVisitor);
+	        // For each component.xml found, find the plugins it corresponds to
+	        for (Iterator it = compXMLVisitor.getCompXMLs().iterator(); it.hasNext();) {
+	          ComponentXML compXML = (ComponentXML)it.next();
+	          // For each plugin, add a mapping for the plugin to the component.xml file
+	          for (Iterator it2 = compXML.getPlugins().iterator(); it2.hasNext();) {
+	            pluginId2CompXML.put(((Plugin)it2.next()).getId(), compXML);
+	          }
+	        }
+	      }
+	  }
+	  return pluginId2CompXML;
+  }
+  
+  /**
+   * This method drives the combination of the usages in the usage.xml files and based on the
+   * API information in the component.xml files in the given map, it will appropriately
+   * tabulate non-API and API usage information for class references, package references, and
+   * plugin references.
+   * 
+   * @param pluginId2CompXML
+   */
+  private void processUsages(Map pluginId2CompXML) {
+	// Iterate over all of the source usage.xml files provided by the "src" collection argument
+    for (Iterator it = getSrc().iterator(); it.hasNext();) {
+      FileInputStream fis = null;
+      try {
+    	// Open a file input stream on the current source usage.xml file  
+        String file = (String)it.next();
+        fis = new FileInputStream(file);
+        // Create a references object to parse the usage.xml file and cache the references
+        References refs = new References();
+        refs.load(fis);
+        String currentContactName = refs.getContactInfo();
+        // Only cache the adopter contact info if we are showing individual adopter usage info
+        if (isShouldShowIndividualAdopters())
+        	cacheContactName(currentContactName);
+        // Iterate through the list of plugins referenced in usage.xml file
+        for (Iterator it2 = refs.getPluginRefs().iterator(); it2.hasNext();) {
+          PluginRef pluginRef = (PluginRef)it2.next();
+          String pluginId = pluginRef.getId();
+          // Retrieve the corresponding component.xml file for the current plugin referenced
+          ComponentXML compXML = (ComponentXML)pluginId2CompXML.get(pluginId);
+          // Get the corresponding component team from that plugin id
+          ComponentTeam compTeam = getComponentTeam(pluginId);
+          // Iterate through the class references in that plugin reference
+          for (Iterator it3 = pluginRef.getClassRefs().iterator(); it3.hasNext();) {
+            ClassRef classRef = (ClassRef)it3.next();
+            // Update the component team's cached reference counts with the current class reference
+            updateComponentTeamUsageCounts(compTeam,compXML,classRef,pluginId,currentContactName);
+          }
+        }
+      } catch (Throwable t) {
+        throw new RuntimeException(t);
+      } finally {
+    	// Close the current file input stream  
+        if (fis != null) {
+          try {
+            fis.close();
+          } catch (IOException ioe) {}
+        }
+      }
+    }
+  }
+  
+  /**
+   * Cache a given contact for an adopter usage to show individual adopter usage
+   * @param aContactName String
+   */
+  private void cacheContactName(String aContactName) {
+	  if (!getContactNames().contains(aContactName))
+		  getContactNames().add(aContactName);
+  }
+  
+  /**
+   * @return List of all the known contact names.  This is empty if not showing adopter numbers.
+   */
+  private List getContactNames() {
+	  if (contactNames == null)
+		  contactNames = new ArrayList();
+	  return contactNames;
+  }
+  
+  /**
+   * The execute method drives the combination operation by collecting component.xml files
+   * from the "api" command line arugment, processing references in usage.xml files from the
+   * "src" command line argument, and then writing them out in CSV and HTML file format to
+   * a location specified by the "output" command line argument.
+   */
+  private void execute() {
+    // Collect the plugin to component.xml file map from the specified collection of 
+	// component.xml files in the "api" command line argument.
+    Map pluginId2CompXML = collectComponentXMLFiles();
+    // Process the usages in the usage.xml files provided by the "src" collection command arg
+    processUsages(pluginId2CompXML);
+    // Generate the output files for combined usage in CSV format
+    generateCSVFiles();
+    // Generate the output files for combined usage in HTML format
+    generateHTMLFiles();
+  }
+  
+  private List getOrderedReferencedCountKeys(final TreeMap referenceCounts) {
+	  String[] keys = (String[]) referenceCounts.keySet().toArray(new String[referenceCounts.keySet().size()]);
+	  Comparator nonAPIComparator = new Comparator() {
+			public int compare(Object o1, Object o2) {
+				UsageCount usageCount1 = (UsageCount) referenceCounts.get(o1);
+				UsageCount usageCount2 = (UsageCount) referenceCounts.get(o2);
+				return usageCount2.nonAPIUse-usageCount1.nonAPIUse;
+			}
+	  };
+	  Arrays.sort(keys,nonAPIComparator);
+	  return Arrays.asList(keys);
+  }
+  
+  /**
+   * Helper method to update the passed in component team's cached usage counts based on the 
+   * given class reference and known API's in the provided component.xml file.
+   *  
+   * @param compTeam
+   * @param compXML
+   * @param classRef
+   * @param pluginId
+   */
+  private void updateComponentTeamUsageCounts(ComponentTeam compTeam, ComponentXML compXML, ClassRef classRef, String pluginId, String contactInfo) {
+	  String name = classRef.getName();
+      String pkgName = getPackageName(name);
+      // Get the usage count object for the current referenced class
+      UsageCount usageCount = getUsageCount(compXML, classRef, pkgName, name.substring(pkgName.length() + 1));
+      // Get the component team's cached class reference usage count
+      UsageCount classUsageCount = (UsageCount)compTeam.getClassReferenceCounts().get(name);
+      if (classUsageCount == null)
+      	classUsageCount = new UsageCount();
+      classUsageCount.addMethodRefs(usageCount.getMethodRefs());
+      classUsageCount.addFieldRefs(usageCount.getFieldRefs());
+      UsageCount nestedClassUsageCount = classUsageCount.getNestedUsageCount(contactInfo);
+      // Update the component team's cached class usage count with the current usage count
+      classUsageCount.apiUse += usageCount.apiUse;
+      classUsageCount.nonAPIUse += usageCount.nonAPIUse;
+      nestedClassUsageCount.apiUse += usageCount.apiUse;
+      nestedClassUsageCount.nonAPIUse += usageCount.nonAPIUse;
+      // Put the updated nested class Usage count back into the cache
+      classUsageCount.getNestedUsageCounts().put(contactInfo, nestedClassUsageCount);
+      // Put the updated class Usage count back into the cache on the component team
+      compTeam.getClassReferenceCounts().put(name, classUsageCount);
+      // Get the component team's cached package reference usage count
+      UsageCount pkgUsageCount = (UsageCount)compTeam.getPackageReferenceCounts().get(pkgName);
+      if (pkgUsageCount == null)
+        pkgUsageCount = new UsageCount();
+      UsageCount nestedPkgUsageCount = pkgUsageCount.getNestedUsageCount(contactInfo);
+      // Update the component team's cached package reference count with current usage count
+      pkgUsageCount.apiUse += usageCount.apiUse;
+      pkgUsageCount.nonAPIUse += usageCount.nonAPIUse;
+      nestedPkgUsageCount.apiUse += usageCount.apiUse;
+      nestedPkgUsageCount.nonAPIUse += usageCount.nonAPIUse;
+      // Put the updated nested package usage count back into the cache 
+      pkgUsageCount.getNestedUsageCounts().put(contactInfo, nestedPkgUsageCount);
+      // Put the updated package usage count back into the cache on the component team
+      compTeam.getPackageReferenceCounts().put(pkgName, pkgUsageCount);
+      // Get the component team's cached plugin reference usage count
+      UsageCount pluginUsageCount = (UsageCount)compTeam.getPluginReferenceCounts().get(pluginId);
+      if (pluginUsageCount == null)
+        pluginUsageCount = new UsageCount();
+      UsageCount nestedPluginUsageCount = pluginUsageCount.getNestedUsageCount(contactInfo);
+      // Update the component team's cached plugin reference count with current usage count
+      pluginUsageCount.apiUse += usageCount.apiUse;
+      pluginUsageCount.nonAPIUse += usageCount.nonAPIUse;
+      nestedPluginUsageCount.apiUse += usageCount.apiUse;
+      nestedPluginUsageCount.nonAPIUse += usageCount.nonAPIUse;
+      // Put the update nested plugin usage count back into the cache
+      pluginUsageCount.getNestedUsageCounts().put(contactInfo, nestedPluginUsageCount);
+      // Put the update plugin usage count back into the cache on the component team
+      compTeam.getPluginReferenceCounts().put(pluginId, pluginUsageCount);
+  }
+
+  /**
+   * This method will cache and return the usages of the class reference into a UsageCount object.  
+   * It will check the passed in component.xml to see if the reference is using a qualified API 
+   * or if it is an internal usage.  The types of references which qualify are class references, 
+   * subclasses, implementers, or instantiators.
+   * 
+   * @param compXML
+   * @param classRef
+   * @param pkgName
+   * @param localName
+   * @return UsageCount
+   */
+  private UsageCount getUsageCount(ComponentXML compXML, ClassRef classRef, String pkgName, String localName) {
+	// Create UsageCount object
+	UsageCount usageCount = new UsageCount();
+	int refCount = classRef.getRefCount();
+	int subclassCount = classRef.getSubclassCount();
+	int implCount = classRef.getImplementCount();
+	int instantiateCount = classRef.getInstantiateCount();
+	// If the component.xml is null, or the package referenced does not exist in the component.xml
+	// we know the reference cannot be an API use, so just add all the references to the non-API 
+	// count and return.
+	if (compXML==null || compXML.getPackage(pkgName)==null) {
+	  usageCount.nonAPIUse = refCount + subclassCount + implCount + instantiateCount;
+	  usageCount.addMethodRefs(classRef.getMethodRefs());
+	  usageCount.addFieldRefs(classRef.getFieldRefs());
+	  return usageCount;
+	}
+	// Get the referenced package from the component.xml file
+	Package pkg = compXML.getPackage(pkgName);
+	// Get the references type from the references pckage in the component.xml file
+	Type type = pkg.getType(localName);
+	if (type == null) {
+		// If the type is null, but the package is an API package, update the API count
+	    if (pkg.isApi()) {
+	      usageCount.apiUse = refCount + subclassCount + implCount + instantiateCount;
+	      return usageCount;
+	    }
+	    // If the type is null, but the package is not API, update the non-API count
+	    usageCount.nonAPIUse = refCount + subclassCount + implCount + instantiateCount;
+	    return usageCount;
+	}
+	// Handle the cases where we have a valid component.xml package and type.
+	// If the type is not a valid API reference, increment the non-API ref count
+    if (!type.isReference()) {
+      usageCount.nonAPIUse += classRef.getRefCount();
+      usageCount.addMethodRefs(classRef.getMethodRefs());
+      usageCount.addFieldRefs(classRef.getFieldRefs());
+    } else {
+      // Otherwise, increment API ref count	
+      usageCount.apiUse += classRef.getRefCount();
+    }
+    // If the type is not a valid API subclass, increment the non-API subclass count
+    if (!type.isSubclass()) {
+      usageCount.nonAPIUse += classRef.getSubclassCount();
+    } else {
+      // Otherwise, increment API subclass count	
+      usageCount.apiUse += classRef.getSubclassCount();
+    }
+    // If the type is not a valid API implementor, increment the non-API implementor count
+    if (!type.isImplement()) {
+      usageCount.nonAPIUse += classRef.getImplementCount();
+    } else {
+      // Otherwise increment API implementor count	
+      usageCount.apiUse += classRef.getImplementCount();
+    }
+    // If the type is not a valid API instantiation, increment the non-API instantiation count
+    if (!type.isInstantiate()) {
+      usageCount.nonAPIUse += classRef.getInstantiateCount();
+    } else {
+      // Otherwise increment API instantation count	
+      usageCount.apiUse += classRef.getInstantiateCount();
+    }
+    // Return the usage count
+    return usageCount;
+  }
+
+  /**
+   * Given a fully qualified class name, return the package name.
+   * 
+   * @param a fully qualified className
+   * @return the package name
+   */
+  private String getPackageName(String className) {
+    int i = className.lastIndexOf('.');
+    if (i != -1) 
+      return className.substring(0, i);
+    return ""; //$NON-NLS-1$
+  }
+
+  /**
+   * Generate CSV format files displaying the combined internal and API usage for classes,
+   * packages, and plugins.
+   */
+  private void generateCSVFiles() {
+    FileWriter classWriter = null;
+    FileWriter pkgWriter = null;
+    FileWriter pluginWriter = null;
+    try {
+      // Create the file writers	
+      classWriter = new FileWriter(getOutput() + CLASS_CVS_FILE_EXTENSION);
+      pkgWriter = new FileWriter(getOutput() + PACKAGE_CVS_FILE_EXTENSION);
+      pluginWriter = new FileWriter(getOutput() + PLUGIN_CVS_FILE_EXTENSION);
+      // For each component team, write the CVS file content for the component's usage
+      for (int i=0; i<getComponentTeams().size(); i++) {
+    	  ComponentTeam compTeam = (ComponentTeam) getComponentTeams().get(i);
+    	  writeCompTeamCSV(compTeam, classWriter, pkgWriter, pluginWriter);
+      }
+    } catch (IOException ioe) {
+      throw new RuntimeException(ioe);
+    } finally {
+      // Close the class usage file writer	
+      if (classWriter != null) {
+        try {
+          classWriter.close();
+        } catch (IOException ioe) {}
+      }
+      // Close the package usage file writer
+      if (pkgWriter != null) {
+        try {
+          pkgWriter.close();
+        } catch (IOException ioe) {}
+      }
+      // Close the plugin usage file writer
+      if (pluginWriter != null) {
+        try {
+          pluginWriter.close();
+        } catch (IOException ioe) {}
+      }
+    }
+  }
+
+  /**
+   * This method drives the creation of the CSV file contents for the given component team
+   * and corresponding writers.
+   * 
+   * @param compTeam
+   * @param classWriter
+   * @param pkgWriter
+   * @param pluginWriter
+   * @throws IOException
+   */
+  private void writeCompTeamCSV(ComponentTeam compTeam, Writer classWriter, Writer pkgWriter, Writer pluginWriter) throws IOException {
+    writeCompTeamCSV(compTeam,classWriter,compTeam.getClassReferenceCounts());
+    writeCompTeamCSV(compTeam,pkgWriter,compTeam.getPackageReferenceCounts());
+    writeCompTeamCSV(compTeam,pluginWriter,compTeam.getPluginReferenceCounts());
+  }
+  
+  /**
+   * This is a helper method to write out the given component team's reference counts in
+   * a CSV file format.
+   * 
+   * @param compTeam
+   * @param writer
+   * @param referenceCounts
+   * @throws IOException
+   */
+  private void writeCompTeamCSV(ComponentTeam compTeam, Writer writer, TreeMap referenceCounts) throws IOException {
+	  // Write the team name
+	  writer.write(compTeam.getTeamName());
+	  writer.write(LINE_BREAK);
+	  // Order reference counts by usage type
+	  List orderedKeys = getOrderedReferencedCountKeys(referenceCounts);
+	  // For each name key, retrieve the corresponding usage count values
+	  for (Iterator it = orderedKeys.iterator(); it.hasNext();) {
+	      String name = (String)it.next();
+	      // Get the corresponding usage count for the name key
+	      UsageCount usageCount = (UsageCount)referenceCounts.get(name);
+	      // Write out the internal and api usages
+	      writer.write(name);
+	      writer.write(COMMA);
+	      writer.write(String.valueOf(usageCount.nonAPIUse));
+	      writer.write(COMMA);
+	      writer.write(String.valueOf(usageCount.apiUse));
+	      writer.write(LINE_BREAK);
+	    }
+	  writer.write(LINE_BREAK);
+  }
+
+  /**
+   * Generate the HTML files for comibined usage ref counts of classes, packages, and plugins.
+   */
+  private void generateHTMLFiles() {
+    try {
+      // Create a new output stream	
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      baos.write(XML_ROOT_BEGIN.getBytes());
+      // For each component team, write out the combined component team specific usage data
+      for (int i=0; i<getComponentTeams().size(); i++) {
+    	  ComponentTeam compTeam = (ComponentTeam) getComponentTeams().get(i);
+    	  writeCompTeamXML(compTeam, baos);
+      }
+      // Close the output stream
+      baos.write(XML_ROOT_END.getBytes());
+      baos.close();
+      // Create a byte array from the output stream contents
+      byte[] content = baos.toByteArray();
+      // Write out the byte array xml to a html file output stream for the plugin references
+      // This transform will do a XSLT operation using the file combine-plugin2ref.xsl
+      XSLUtil.transform (
+        ClassLoader.getSystemResourceAsStream(COMBINE_PLUGINS_FILE),
+        new ByteArrayInputStream(content),
+        new FileOutputStream(getOutput() + PLUGIN_HTML_FILE_EXTENSION)
+      );
+      // Write out the byte array xml to a html file output stream for the package references
+      // This transform will do a XSLT operation using the file combine-pkg2ref.xsl
+      XSLUtil.transform (
+        ClassLoader.getSystemResourceAsStream(COMBINE_PACKAGES_FILE),
+        new ByteArrayInputStream(content),
+        new FileOutputStream(getOutput() + PACKAGE_HTML_FILE_EXTENSION)
+      );
+      // Write out the byte array xml to a html file output stream for the class references
+      // This transform will do a XSLT operation using the file combine-class2ref.xsl
+      XSLUtil.transform (
+        ClassLoader.getSystemResourceAsStream(COMBINE_CLASSES_FILE),
+        new ByteArrayInputStream(content),
+        new FileOutputStream(getOutput() + CLASS_HTML_FILE_EXTENSION)
+      );
+    } catch (Throwable t) {
+      t.printStackTrace();
+      throw new RuntimeException(t);
+    }
+  }
+
+  /**
+   * This method will drive the combined output file html contents for the given component
+   * team in xml format.
+   * 
+   * @param compTeam
+   * @param baos
+   * @throws IOException
+   */
+  private void writeCompTeamXML(ComponentTeam compTeam, ByteArrayOutputStream baos) throws IOException {
+    baos.write("<team lead=\"".getBytes()); //$NON-NLS-1$
+    baos.write(compTeam.getTeamName().getBytes());
+    baos.write("\">".getBytes()); //$NON-NLS-1$
+    for (Iterator nestedKeys = getContactNames().iterator(); nestedKeys.hasNext();) {
+	      String currentKey = (String) nestedKeys.next();
+	      baos.write("<source name=\"".getBytes()); //$NON-NLS-1$
+	      baos.write(currentKey.getBytes());
+	      baos.write("\"/>".getBytes()); //$NON-NLS-1$
+    }
+    writeCompTeamXML(baos,CLASS_USAGE,compTeam.getClassReferenceCounts());
+    writeCompTeamXML(baos,PACKAGE_USAGE,compTeam.getPackageReferenceCounts());
+    writeCompTeamXML(baos,PLUGIN_USAGE,compTeam.getPluginReferenceCounts());
+    baos.write("</team>".getBytes()); //$NON-NLS-1$
+  }
+  
+  /**
+   * This method will write in xml format the combined output for the given component team for
+   * the non API and API usage for the class usage file, the package usage file, and the plugin
+   * usage file.
+   * 
+   * @param baos ByteArrayOutputStream
+   * @param usage class, package, or plugin?
+   * @param referenceCounts TreeMap
+   * @throws IOException
+   */
+  private void writeCompTeamXML(ByteArrayOutputStream baos, int usage, TreeMap referenceCounts) throws IOException {
+	  // Order reference counts by usage type
+	  List orderedKeys = getOrderedReferencedCountKeys(referenceCounts);
+	  // Iterate over the name keys of the references tree map
+	  for (Iterator it = orderedKeys.iterator(); it.hasNext();) {
+	      String name = (String)it.next();
+	      // Retrieve the appropriate UsageCount from the map given the current name key
+	      UsageCount usageCount = (UsageCount) referenceCounts.get(name);
+	      switch (usage) {
+	        // Class reference
+	      	case 0:
+	      		baos.write("<class name=\"".getBytes()); //$NON-NLS-1$
+	      		break;
+	        // Package reference
+			case 1:
+				baos.write("<package name=\"".getBytes()); //$NON-NLS-1$
+				break;
+			// Plugin reference
+			case 2:
+				baos.write("<plugin id=\"".getBytes()); //$NON-NLS-1$
+				break;
+		  }
+	      // Write the api and internal usage for the current reference
+	      baos.write(name.getBytes());
+	      baos.write("\" api=\"".getBytes()); //$NON-NLS-1$
+	      baos.write(String.valueOf(usageCount.apiUse).getBytes());
+	      baos.write("\" internal=\"".getBytes()); //$NON-NLS-1$
+	      baos.write(String.valueOf(usageCount.nonAPIUse).getBytes());
+	      baos.write("\">".getBytes()); //$NON-NLS-1$
+	      for (Iterator nestedKeys = getContactNames().iterator(); nestedKeys.hasNext();) {
+		      String currentKey = (String) nestedKeys.next();
+		      UsageCount nestedCount = usageCount.getNestedUsageCount(currentKey);
+	    	  // Add nested usages for each source
+		      baos.write("<source name=\"".getBytes()); //$NON-NLS-1$
+		      baos.write(currentKey.getBytes());
+		      baos.write("\" api=\"".getBytes()); //$NON-NLS-1$
+		      baos.write(String.valueOf(nestedCount.apiUse).getBytes());
+		      baos.write("\" internal=\"".getBytes()); //$NON-NLS-1$
+		      baos.write(String.valueOf(nestedCount.nonAPIUse).getBytes());
+		      baos.write("\"/>".getBytes()); //$NON-NLS-1$
+	      }
+	      // Add detailed sections for method and field information if necessary
+	      if (isShouldShowDetailedNumbers()) 
+	    	  showDetailedMethodAndFieldSections(baos, usageCount);
+	      // Close out current entry type
+	      switch (usage) {
+	        // Class reference
+	      	case 0:
+	      		baos.write("</class>".getBytes()); //$NON-NLS-1$
+	      		break;
+	        // Package reference
+			case 1:
+				baos.write("</package>".getBytes()); //$NON-NLS-1$
+				break;
+			// Plugin reference
+			case 2:
+				baos.write("</plugin>".getBytes()); //$NON-NLS-1$
+				break;
+		  }
+	  }
+  }
+  
+  /**
+   * This helper method will add the detailed numbers for the method and field usage for a particular
+   * class UsageCount.
+   * 
+   * @param baos
+   * @param usageCount
+   * @throws IOException
+   */
+  private void showDetailedMethodAndFieldSections(ByteArrayOutputStream baos, UsageCount usageCount) throws IOException {
+	  // Serialize out the method refs for the class usage report
+      for (Iterator nestedMethodRefs = usageCount.getMethodRefs().keySet().iterator(); nestedMethodRefs.hasNext();) {
+	      String currentKey = (String) nestedMethodRefs.next();
+	      int count = ((Integer)usageCount.getMethodRefs().get(currentKey)).intValue();
+    	  // Add nested usages for each source
+	      baos.write("<method name=\"".getBytes()); //$NON-NLS-1$
+	      baos.write(encode(currentKey).getBytes());
+	      baos.write("\" internal=\"".getBytes()); //$NON-NLS-1$
+	      baos.write(String.valueOf(count).getBytes()); 
+	      baos.write("\"/>".getBytes()); //$NON-NLS-1$
+      }
+      // Serialize out the field refs for the class usage report
+      for (Iterator nestedFieldRefs = usageCount.getFieldRefs().keySet().iterator(); nestedFieldRefs.hasNext();) {
+	      String currentKey = (String) nestedFieldRefs.next();
+	      int count = ((Integer)usageCount.getFieldRefs().get(currentKey)).intValue();
+    	  // Add nested usages for each source
+	      baos.write("<field name=\"".getBytes()); //$NON-NLS-1$
+	      baos.write(encode(currentKey).getBytes());
+	      baos.write("\" internal=\"".getBytes()); //$NON-NLS-1$
+	      baos.write(String.valueOf(count).getBytes()); 
+	      baos.write("\"/>".getBytes()); //$NON-NLS-1$
+      }
+  }
+  
+  /**
+   * Encode all occurences of "<" with "&lt;" in the given string
+   * 
+   * @param s String
+   * @return encoded String
+   */
+  protected String encode(String s) {
+    int index = s.indexOf('<');
+    if (index != -1) {
+      StringBuffer sb = new StringBuffer(s);
+      while (index != -1) {
+        sb.deleteCharAt(index);
+        sb.insert(index, new char[] {'&', 'l', 't', ';'}, 0, 4);
+        index = sb.toString().indexOf('<');
+      }
+      return sb.toString();
+    }
+    return s;
+  }
+
+
+  /**
+   * This is the static main method used for launching this reference usage combination
+   * application.  It will create and set up the class instance and then invoke the execute
+   * method to do the combination.
+   * 
+   * @param args
+   */
+  public static void main(String[] args) {
+	// Use the command option parser to parse the command line arguments  
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    Collection src = (Collection)options.get(ARG_SOURCE);
+    Collection output = (Collection)options.get(ARG_OUTPUT);
+    Collection api = (Collection)options.get(ARG_API);
+    Collection showAdopterNumbers = (Collection)options.get(ARG_SHOW_ADOPTER_NUMBERS);
+    Collection showDetailedNumbers = (Collection)options.get(ARG_SHOW_DETAILED_NUMBERS);
+    // If the usage is improper or arguments are not valid, prompt for proper usage
+    if (src == null || output == null || src.isEmpty() || output.isEmpty()) {
+      printUsage();
+      System.exit(-1);
+    }
+    // Create a new instance of the class and set the command line argument values
+    CombineClass2Reference class2Ref = new CombineClass2Reference();
+    class2Ref.setSrc(src);
+    class2Ref.setOutput((String)output.iterator().next());
+    class2Ref.setApi(api);
+    if (showAdopterNumbers!=null)
+    	class2Ref.setShouldShowIndividualAdopters(new Boolean((String)showAdopterNumbers.iterator().next()).booleanValue());
+    if (showDetailedNumbers!=null)
+    	class2Ref.setShouldShowDetailedNumbers(new Boolean((String)showDetailedNumbers.iterator().next()).booleanValue());
+    // Execute the combination method
+    class2Ref.execute();
+  }
+
+  /**
+   * This is a helper method to the user to print out an error message of the proper usage of 
+   * the arguments to be passed and the location of the output files.  
+   * See IOutputConstants for messages.
+   */
+  private static void printUsage() {
+    System.out.println(PRINT_USAGE_COMBINED);
+    System.out.println(""); //$NON-NLS-1$
+    System.out.println(PRINT_SOURCE_LOCATION);
+    System.out.println(PRINT_OUTPUT_LOCATION);
+    System.out.println(PRINT_COMPONENT_XML_API_LOCATION);
+  }
+
+  /**
+   * @return boolean should show individual adopter numbers
+   */
+  public boolean isShouldShowIndividualAdopters() {
+	return shouldShowIndividualAdopters;
+  }
+
+  /**
+   * Set whether or not to show individual adopter numbers in combined report
+   * @param shouldShowIndividualAdopters
+   */
+  public void setShouldShowIndividualAdopters(boolean shouldShowIndividualAdopters) {
+	this.shouldShowIndividualAdopters = shouldShowIndividualAdopters;
+  }
+
+  /**
+   * @return boolean should show method and field detailed numbers
+   */
+  public boolean isShouldShowDetailedNumbers() {
+	return shouldShowDetailedNumbers;
+  }
+
+  /**
+   * Set whether or not to show method and field detailed numbers
+   * @param shouldShowDetailedNumbers
+   */
+  public void setShouldShowDetailedNumbers(boolean shouldShowDetailedNumbers) {
+	this.shouldShowDetailedNumbers = shouldShowDetailedNumbers;
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/CombineExtensionPointScans.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/CombineExtensionPointScans.java
new file mode 100644
index 0000000..7016656
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/CombineExtensionPointScans.java
@@ -0,0 +1,227 @@
+package org.eclipse.wtp.releng.tools.component.adopters;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.wtp.releng.tools.component.CommandOptionParser;
+import org.eclipse.wtp.releng.tools.component.xsl.XSLUtil;
+
+/**
+ * This class is used to combine multiple adopter extension point scan results created by
+ * running the ExtensionPointScanner into one html report.  The output folder location must
+ * exist before running and there are two command line parameters to be passed to the main
+ * method for appropriate execution:
+ *   sourceFiles - the input html files from adopter extension pt usage scans
+ *   output - a string location of where the combinedExtpt.html file should go
+ */
+public class CombineExtensionPointScans extends ComponentTeamScanner implements IOutputConstants {
+
+	// Command Line arguments	
+	private static final String ARG_SOURCE = "sourceFiles"; //$NON-NLS-1$
+	private static final String ARG_OUTPUT = "output"; //$NON-NLS-1$
+	
+	 // Instance variables for command line arguments
+	private Collection sourceFiles;
+	private String output;
+	
+	// Class variables for string values
+	private static final String EXTENSION_POINT_USAGE_FILE = "org/eclipse/wtp/releng/tools/component/xsl/extpt.xsl"; //$NON-NLS-1$
+	private static final String HTML_OUTPUT_EXTENSION = "/combinedExtPtUsage.html"; //$NON-NLS-1$
+	private static final String ORG_ECLIPSE = "org.eclipse."; //$NON-NLS-1$
+	private static final String BEGIN_TD = "<td>"; //$NON-NLS-1$
+	private static final String END_TD = "</td>"; //$NON-NLS-1$
+	
+	/**
+	 * This is the static main method used for launching this combinatorial class routine. The
+	 * command line arguments used are:
+	 *   sourceFiles - the input html files from adopter extension pt usage scans
+	 *   output - a string location of where the combinedExtpt.html file should go
+	 * @param args
+	 */
+	public static void main(String[] args) {
+		// Parse the command line options
+	    CommandOptionParser optionParser = new CommandOptionParser(args);
+	    Map options = optionParser.getOptions();
+	    Collection src = (Collection)options.get(ARG_SOURCE);
+	    Collection output = (Collection)options.get(ARG_OUTPUT);
+	    // If the usage is improper or arguments are not valid, prompt for proper usage
+	    if (src == null || output == null) {
+	      printUsage();
+	      System.exit(-1);
+	    }
+		//Use the args to set up the CombineExtensionPointScans instance
+		CombineExtensionPointScans combineExtPtUsage = new CombineExtensionPointScans();
+		combineExtPtUsage.setOutput((String)output.iterator().next());
+		combineExtPtUsage.setSourceFiles(src);
+		combineExtPtUsage.execute();
+	}
+	
+	/**
+	 * The execute method drives the processing of this class.  It will read the files in, calculate
+	 * total usage using the ComponentTeam class and then generate an XML file and translate it
+	 * to HTML using XSLT.
+	 */
+	public void execute() {
+		// Iterate over all the source extpt.html files provided by the "sourceFiles" collection arg
+	    for (Iterator sourceFilesIterator = getSourceFiles().iterator(); sourceFilesIterator.hasNext();) {
+	    	String file = (String)sourceFilesIterator.next();
+	    	// Read and process the extension pt usages in the html file
+	    	processFile(file);
+	    }
+	    // Generate the output combined html file
+		generateHTMLFile();
+	}
+	
+	/**
+	 * This gets a FileInputStream on the file location passed in.  It will read and parse the file
+	 * line by line, finding extension point usages to cache and update in the ComponentTeam map.
+	 * 
+	 * @param fileLocation String
+	 */
+	private void processFile(String fileLocation) {
+		try {
+			// Open input streams and buffered reader stream on the source html file
+			FileInputStream fstream = new FileInputStream(fileLocation);
+			DataInputStream in = new DataInputStream(fstream);
+			BufferedReader br = new BufferedReader(new InputStreamReader(in));
+			String currentLine;
+			String extensionPointName;
+			int useCount = 0;
+			while ((currentLine = br.readLine()) != null) {
+				// If the html current line contains "org.eclipse", assume it is an extension point
+				if (currentLine.indexOf(ORG_ECLIPSE)>=0) {
+					// Calculate the extension point string by removing the <td> and </td> tags
+					int beginExtPtName = currentLine.indexOf(BEGIN_TD)+4;
+					int endExtPtName = currentLine.indexOf(END_TD);
+					extensionPointName = currentLine.substring(beginExtPtName, endExtPtName);
+					// Calculate the use count by removing the last <td> and </td> tags on the line
+					int beginUseCount = currentLine.lastIndexOf(BEGIN_TD)+4;
+					int endUseCount = currentLine.lastIndexOf(END_TD);
+					useCount = Integer.parseInt(currentLine.substring(beginUseCount, endUseCount));
+					 // Get the associated component team for the extension point's plugin
+		            ComponentTeam compTeam = getComponentTeam(extensionPointName);
+		            // Update the extension point reference counts with the result of this extenion point scan
+		            String previousCount = (String) compTeam.getExtensionPointReferenceCounts().get(extensionPointName);
+		            // If this is the first time this extension pt is referenced, add it to the map
+		            if (previousCount == null)
+		            	compTeam.getExtensionPointReferenceCounts().put(extensionPointName, String.valueOf(useCount));
+		            // Else, add the current use to the previous total use count and update map
+		            else 
+		            	compTeam.getExtensionPointReferenceCounts().put(extensionPointName, String.valueOf(Integer.parseInt(previousCount)+useCount));
+				}
+			}
+			// Close the streams.
+			in.close();
+			fstream.close();
+			br.close();
+		} catch (Exception e) {
+			  System.err.println(e.getMessage());
+		} 
+	}
+	
+	/**
+	   * This method creates an XML formatted stream of the resulting extension point reference data
+	   * and then transforms it to HTML using an XSL transformation.
+	   *
+	   */
+	  private void generateHTMLFile() {
+	    try {
+	      // Get an output stream to write results in XML format
+	      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+	      baos.write(XML_ROOT_BEGIN.getBytes());
+	      // For each component team, write out the extension point usage
+	      for (int i=0; i<getComponentTeams().size(); i++) {
+	    	  ComponentTeam compTeam = (ComponentTeam) getComponentTeams().get(i);
+	    	  writeCompTeamXML(compTeam, baos);
+	      }
+	      baos.write(XML_ROOT_END.getBytes());
+	      // Close the XML output stream
+	      baos.close();
+	      // Write out the byte array xml to a html file output stream for the extension pt references
+	      // This transform will do a XSLT operation using the file extpt.xsl
+	      XSLUtil.transform (
+	    	ClassLoader.getSystemResourceAsStream(EXTENSION_POINT_USAGE_FILE),
+	    	new ByteArrayInputStream(baos.toByteArray()),
+	        new FileOutputStream(getOutput() + HTML_OUTPUT_EXTENSION)
+	      );
+	    } catch (Throwable t) {
+	      t.printStackTrace();
+	      throw new RuntimeException(t);
+	    }
+	  }
+	  
+	  /**
+	   * This method will write out, in xml format, the component team's extension point references.
+	   * 
+	   * @param compTeam
+	   * @param baos
+	   * @throws IOException
+	   */
+	  private void writeCompTeamXML(ComponentTeam compTeam, ByteArrayOutputStream baos) throws IOException {
+	    baos.write("<team lead=\"".getBytes()); //$NON-NLS-1$
+	    baos.write(compTeam.getTeamName().getBytes());
+	    baos.write("\">".getBytes()); //$NON-NLS-1$
+	    // For each extension pt in the component team's scope, write its reference information
+	    for (Iterator it = compTeam.getExtensionPointReferenceCounts().keySet().iterator(); it.hasNext();) {
+	      String id = (String)it.next();
+	      String refCount = (String)compTeam.getExtensionPointReferenceCounts().get(id);
+	      baos.write("<extpt id=\"".getBytes()); //$NON-NLS-1$
+	      baos.write(id.getBytes());
+	      baos.write("\" ref=\"".getBytes()); //$NON-NLS-1$
+	      baos.write(refCount.getBytes());
+	      baos.write("\"/>".getBytes()); //$NON-NLS-1$
+	    }
+	    baos.write("</team>".getBytes()); //$NON-NLS-1$
+	  }
+
+	/**
+	 * @return Collection of input html files
+	 */
+	public Collection getSourceFiles() {
+		return sourceFiles;
+	}
+
+	/**
+	 * Set the collection of input html files
+	 * @param sourceFiles Collection
+	 */
+	public void setSourceFiles(Collection sourceFiles) {
+		this.sourceFiles = sourceFiles;
+	}
+
+	/**
+	 * @return String output location
+	 */
+	public String getOutput() {
+		return output;
+	}
+
+	/**
+	 * Set the output location string
+	 * @param output String
+	 */
+	public void setOutput(String output) {
+		this.output = output;
+	}
+	
+	/**
+     * This is a helper method to the user to print out an error message of the proper usage of 
+     * the arguments to be passed and the location of the output files.  
+     * See IOutputConstants for messages.
+     */
+     private static void printUsage() {
+    	 System.out.println(PRINT_USAGE_COMBINED_EXT_PT);
+    	 System.out.println(""); //$NON-NLS-1$
+    	 System.out.println(PRINT_SOURCE_FILES_LOCATION);
+    	 System.out.println(PRINT_OUTPUT_LOCATION);
+     }
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/ComponentTeamScanner.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/ComponentTeamScanner.java
new file mode 100644
index 0000000..e3b1731
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/ComponentTeamScanner.java
@@ -0,0 +1,206 @@
+package org.eclipse.wtp.releng.tools.component.adopters;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeMap;
+
+/**
+ * This abstract base class for scanning operations which make use of logical WTP component teams.
+ * This class will manage which plugins are associated with which component team.
+ */
+public abstract class ComponentTeamScanner implements IComponentConstants {
+
+	  // Instance variable for which plugins are associated with which logical component team grouping
+	  private HashMap plugin2compTeam;
+	  
+	  // Instance variable for cache of WTP component teams
+	  private List componentTeams;
+	  
+	  /**
+	   * The ComponentTeam class manages applicable reference counts per logical grouping of 
+	   * plugins.
+	   */
+	  public class ComponentTeam {
+	    private String teamName;
+	    private TreeMap extpt2RefCounts;
+	    private TreeMap class2refCounts;
+		private TreeMap pkg2refCounts;
+		private TreeMap plugin2refCounts;
+
+	    /**
+	     * Simple Constructor
+	     * @param teamName
+	     */
+	    public ComponentTeam(String teamName) {
+	      this.teamName = teamName;
+	    }
+	    
+	    /**
+		 * @return String component team's name
+		 */
+	    public String getTeamName() {
+	    	return teamName;
+	    }
+	    
+	    /**
+	     * @return TreeMap of Extension Point references
+	     */
+	    public TreeMap getExtensionPointReferenceCounts() {
+	    	if (extpt2RefCounts==null)
+	    		extpt2RefCounts = new TreeMap();
+	    	return extpt2RefCounts;
+	    }
+	    
+	    /**
+		 * @return TreeMap of class reference counts
+		 */
+		public TreeMap getClassReferenceCounts() {
+			if (class2refCounts==null)
+				class2refCounts = new TreeMap();
+			return class2refCounts;
+		}
+		
+		/**
+		 * @return TreeMap of package reference counts
+		 */
+		public TreeMap getPackageReferenceCounts() {
+			if (pkg2refCounts==null)
+				pkg2refCounts = new TreeMap();
+			return pkg2refCounts;
+		}
+		
+		/**
+		 * @return TreeMap of plugin reference counts
+		 */
+		public TreeMap getPluginReferenceCounts() {
+			if (plugin2refCounts==null)
+				plugin2refCounts = new TreeMap();
+			return plugin2refCounts;
+		}
+	  }
+	  
+	  /**
+	   * @return HashMap of plugin keys and associated component team values
+	   */
+	  private HashMap getPluginComponentMap() {
+		  if (plugin2compTeam==null) {
+			  plugin2compTeam = new HashMap();
+			  initializeComponentTeams();
+		  }
+		  return plugin2compTeam;
+	  }
+	  
+	  /**
+	   * Initialize the component teams list with the appropriate regular expressions to link plugins 
+	   * to the known set of component teams.
+	   */
+	  private void initializeComponentTeams() {
+		componentTeams = new ArrayList();
+		
+		// Create the JEE team with associated plugins
+		ComponentTeam javaEE = new ComponentTeam(COMPONENT_TEAM_JAVA_EE);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_J2EE, javaEE);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_EJB, javaEE);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_SERVLET, javaEE);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_WEB, javaEE);
+		componentTeams.add(javaEE);
+		
+		// Create the Common team with associated plugins
+		ComponentTeam common = new ComponentTeam(COMPONENT_TEAM_COMMON);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_COMMAND, common);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_COMMON, common);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_VALIDATION, common);
+		componentTeams.add(common);
+		
+		// Create the Editors team with associated plugins
+		ComponentTeam editors = new ComponentTeam(COMPONENT_TEAM_EDITORS);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_JSP, editors);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_CSS, editors);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_DTD, editors);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_HTML, editors);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_JAVASCRIPT, editors);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_SSE, editors);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_XML, editors);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_XSD, editors);
+		componentTeams.add(editors);
+		
+		// Create the RDB team with associated plugins
+		ComponentTeam rdb = new ComponentTeam(COMPONENT_TEAM_RDB);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_RDB, rdb);
+		componentTeams.add(rdb);
+		
+		// Create the Web Services team with associated plugins
+		ComponentTeam webServices = new ComponentTeam(COMPONENT_TEAM_WEB_SERVICES);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_WS, webServices);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_WSDL, webServices);
+		componentTeams.add(webServices);
+		
+		// Create the Server team with associated plugins
+		ComponentTeam server = new ComponentTeam(COMPONENT_TEAM_SERVER);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_SERVER, server);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_INTERNET, server);
+		componentTeams.add(server);
+		
+		// Create the JEM team with associated plugins
+		ComponentTeam jem = new ComponentTeam(COMPONENT_TEAM_JEM);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_JEM,jem);
+		componentTeams.add(jem);
+		
+		// Create the JSF team with associated plugins
+		ComponentTeam jsf = new ComponentTeam(COMPONENT_TEAM_JSF);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_JSF,jsf);
+		componentTeams.add(jsf);
+		
+		// Create the JPA team with associated plugins
+		ComponentTeam jpa = new ComponentTeam(COMPONENT_TEAM_JPA);
+		getPluginComponentMap().put(PLUGIN_EXPRESSION_JPA,jpa);
+		componentTeams.add(jpa);
+		
+		// Add a "team" for the unknown references
+		ComponentTeam unknown = new ComponentTeam(COMPONENT_TEAM_UNKNOWN);
+		componentTeams.add(unknown);
+	  }
+	  
+	  /**
+	   * Helper method to find the corresponding component team for a given plugin id.  If one is
+	   * not found, the unknown component is returned.
+	   * 
+	   * @param pluginId
+	   * @return ComponentTeam for specified plugin
+	   */
+	  protected ComponentTeam getComponentTeam(String pluginId) {
+	      // Try and match the proper component team to the referenced plugin from the 
+	      // map of plugins to component teams
+	      for (Iterator it3 = getPluginComponentMap().keySet().iterator(); it3.hasNext();) {
+	        String regex = (String)it3.next();
+	        if (pluginId.matches(regex)) {
+	          return (ComponentTeam)getPluginComponentMap().get(regex);
+	        }
+	      }
+	      // Otherwise return the unknown component
+	      return getUnknownComponent();
+	  }
+	  
+	  /**
+	   * @return the unknown component where a plugin's logical component is not known
+	   */
+	  private ComponentTeam getUnknownComponent() {
+		  for (int i=0; i<getComponentTeams().size(); i++) {
+			  ComponentTeam compTeam = (ComponentTeam) getComponentTeams().get(i);
+			  if (compTeam.getTeamName().equals(COMPONENT_TEAM_UNKNOWN))
+				  return compTeam;
+		  }
+		  return null;
+	  }
+	  
+	  /**
+	   * @return the list of component teams
+	   */
+	  protected List getComponentTeams() {
+		  if (componentTeams == null)
+			  initializeComponentTeams();
+		  return componentTeams;
+	  }
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/ExtensionPointScanner.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/ExtensionPointScanner.java
new file mode 100644
index 0000000..7c413b6
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/ExtensionPointScanner.java
@@ -0,0 +1,347 @@
+/*******************************************************************************
+ * 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.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IPlatformRunnable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wtp.releng.tools.component.CommandOptionParser;
+import org.eclipse.wtp.releng.tools.component.xsl.XSLUtil;
+
+/**
+ * ExtensionPointScanner is a scanning mechanism for extension point usage in an eclipse environment.
+ * This class will collect all of the loaded extensions in a the running workbench, and
+ * then process the extension point usage based on the command line arguments:
+ * 
+ * extpt: Regular expressions for filtering which extension point's extensions will be scanned.
+ * output: The output directory of the usage files.
+ * includes: Optional regular expression for which plugins containing extensions should be included.
+ * excludes: Optional regular expression for which plugins containing extensions should be excluded.
+ *
+ */
+public class ExtensionPointScanner extends ComponentTeamScanner implements IPlatformRunnable, IOutputConstants  {
+  
+  // Command Line arguments	
+  public static final String ARG_FILTERS = "extpt"; //$NON-NLS-1$
+  public static final String ARG_OUTPUT = "output"; //$NON-NLS-1$
+  public static final String ARG_INCLUDES = "includes"; //$NON-NLS-1$
+  public static final String ARG_EXCLUDES = "excludes"; //$NON-NLS-1$
+
+  // Instance variables for command line argument values	
+  private Collection filters;
+  private String output;
+  private Collection includes;
+  private Collection excludes;
+  
+  // Class variables for string values
+  private static final String EXTENSION_POINT_USAGE_FILE = "org/eclipse/wtp/releng/tools/component/xsl/extpt.xsl"; //$NON-NLS-1$
+  private static final String HTML_OUTPUT_EXTENSION = "/extpt.html"; //$NON-NLS-1$
+  
+  /**
+   * Default Constructor
+   */
+  public ExtensionPointScanner() {
+    super();
+  }
+
+  /**
+   * @return Collection of regular expressions defining which extension points to consider
+   */
+  public Collection getFilters() {
+    return filters;
+  }
+
+  /**
+   * Set the collection of regular expressions defining which extension points to consider.
+   * @param someFilters
+   */
+  public void setFilters(Collection someFilters) {
+    filters = someFilters;
+  }
+
+  /**
+   * @return String value of the output folder location to write the html file
+   */
+  public String getOutput() {
+    return output;
+  }
+
+  /**
+   * Set the output folder location to the string value parameter
+   * @param anOutput
+   */
+  public void setOutput(String anOutput) {
+    output = anOutput;
+  }
+
+  /**
+   * @return optional collection of regular expressions defining which plugin extensions to ignore
+   */
+  public Collection getExcludes() {
+    return excludes;
+  }
+
+  /**
+   * Set the optional collection of regular expressions defining which plugin extensions to ignore.
+   * @param someExcludes
+   */
+  public void setExcludes(Collection someExcludes) {
+    excludes = someExcludes;
+  }
+
+  /**
+   * @return optional collection of regular expressions defining which plugin extensions to include
+   */
+  public Collection getIncludes() {
+    return includes;
+  }
+
+  /**
+   * Set the optional collection of regular expressions defining which plugin extensions to include.
+   * @param someIncludes
+   */
+  public void setIncludes(Collection someIncludes) {
+    includes = someIncludes;
+  }
+
+  /**
+   * This is a helper method to determine if a plugin extension meets the inclusion and exclusion
+   * critera set in the optional command line arguments "includes" and "excludes".
+   * 
+   * @param s
+   * @return boolean should the string pattern be included?
+   */
+  private boolean include(String s) {
+	// If the string matchs any of the excludes, return false  
+    if (getExcludes()!=null && !getExcludes().isEmpty()) {
+      for (Iterator it = getExcludes().iterator(); it.hasNext();) {
+        if (s.matches((String)it.next()))
+          return false;
+      }
+    }
+    // If there are includes, make sure the string matchs one of them
+    if (includes != null && !includes.isEmpty()) {
+      for (Iterator it = includes.iterator(); it.hasNext();) {
+        if (s.matches((String)it.next()))
+          return true;
+      }
+      // If there are includes and the string does not match any, return false
+      return false;
+    }
+    // If there are not includes, and the excludes don't match, return true
+    return true;
+  }
+
+  /**
+   * This is the execute method for the extension point scanning which will drive the operation
+   * and ouput of the result html file based on command line arguments.  It will load all the
+   * known extension points in the eclipse environment and match the references accordingly.
+   */
+  public void execute() {
+	// Get and iterate over all known extension points in the eclipse environment. 
+    IExtensionPoint[] extpts = Platform.getExtensionRegistry().getExtensionPoints();
+    for (int i = 0; i < extpts.length; i++) {
+      String extPtId = extpts[i].getUniqueIdentifier();
+      String pluginId = extpts[i].getNamespaceIdentifier();
+      if (extPtId != null) {
+    	// Iterate over the known filters to see if this extension pt should be scanned for refs  
+        for (Iterator it = getFilters().iterator(); it.hasNext();) {
+          if (extPtId.matches((String)it.next())) {
+            int extptRefCount = 0;
+            // Get all extensions for the current extension point
+            IExtension[] exts = extpts[i].getExtensions();
+            for (int j = 0; j < exts.length; j++) {
+              // If the reference should be included, increment the count	
+              if (include(exts[j].getNamespaceIdentifier()))
+            	  extptRefCount++;
+            }
+            // Get the associated component team for the extension point's plugin
+            ComponentTeam compTeam = getComponentTeam(pluginId);
+            // Update the extension point reference counts with the result of this extenion point scan
+            compTeam.getExtensionPointReferenceCounts().put(extPtId, String.valueOf(extptRefCount));
+            break;
+          }
+        }
+      }
+    }
+    // Generate the output html file.
+    generateHTMLFile();
+  }
+
+  /**
+   * This method creates an XML formatted stream of the resulting extension point reference data
+   * and then transforms it to HTML using an XSL transformation.
+   *
+   */
+  private void generateHTMLFile() {
+    try {
+      // Get an output stream to write results in XML format
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      baos.write(XML_ROOT_BEGIN.getBytes());
+      // For each component team, write out the extension point usage
+      for (int i=0; i<getComponentTeams().size(); i++) {
+    	  ComponentTeam compTeam = (ComponentTeam) getComponentTeams().get(i);
+    	  writeCompTeamXML(compTeam, baos);
+      }
+      baos.write(XML_ROOT_END.getBytes());
+      // Close the XML output stream
+      baos.close();
+      // Write out the byte array xml to a html file output stream for the extension pt references
+      // This transform will do a XSLT operation using the file extpt.xsl
+      XSLUtil.transform (
+    	Platform.getBundle(WTP_SCANNING_PLUGIN).getResource(EXTENSION_POINT_USAGE_FILE).openStream(),
+    	new ByteArrayInputStream(baos.toByteArray()),
+        new FileOutputStream(getOutput() + HTML_OUTPUT_EXTENSION)
+      );
+    } catch (Throwable t) {
+      t.printStackTrace();
+      throw new RuntimeException(t);
+    }
+  }
+
+  /**
+   * This method will write out, in xml format, the component team's extension point references.
+   * 
+   * @param compTeam
+   * @param baos
+   * @throws IOException
+   */
+  private void writeCompTeamXML(ComponentTeam compTeam, ByteArrayOutputStream baos) throws IOException {
+    baos.write("<team lead=\"".getBytes()); //$NON-NLS-1$
+    baos.write(compTeam.getTeamName().getBytes());
+    baos.write("\">".getBytes()); //$NON-NLS-1$
+    // For each extension pt in the component team's scope, write its reference information
+    for (Iterator it = compTeam.getExtensionPointReferenceCounts().keySet().iterator(); it.hasNext();) {
+      String id = (String)it.next();
+      String refCount = (String)compTeam.getExtensionPointReferenceCounts().get(id);
+      baos.write("<extpt id=\"".getBytes()); //$NON-NLS-1$
+      baos.write(id.getBytes());
+      baos.write("\" ref=\"".getBytes()); //$NON-NLS-1$
+      baos.write(refCount.getBytes());
+      baos.write("\"/>".getBytes()); //$NON-NLS-1$
+    }
+    baos.write("</team>".getBytes()); //$NON-NLS-1$
+  }
+
+  /**
+   * Runs this runnable calling main with the given args and returns the result.
+   * @param arguments
+   */
+  public Object run(Object arguments) {
+    String vmExtpt = System.getProperty(ARG_FILTERS);
+    String vmOutput = System.getProperty(ARG_OUTPUT);
+    String vmIncludes = System.getProperty(ARG_INCLUDES);
+    String vmExcludes = System.getProperty(ARG_EXCLUDES);
+    List args = new ArrayList();
+    // extpt is required, add its value to command line argument values
+    args.add(HYPHEN+ARG_FILTERS);
+    args.addAll(tokenize(vmExtpt));
+    // output is required, add its value to command line argument values
+    args.add(HYPHEN+ARG_OUTPUT);
+    args.add(vmOutput);
+    // If includes are set, add the command line argument values
+    if (vmIncludes != null) {
+      args.add(HYPHEN+ARG_INCLUDES);
+      args.addAll(tokenize(vmIncludes));
+    }
+    // If excludes are set, add the command line argument values
+    if (vmExcludes != null) {
+      args.add(HYPHEN+ARG_EXCLUDES);
+      args.addAll(tokenize(vmExcludes));
+    }
+    // Run the main method with the current command line arguments
+    try {
+      main((String[])args.toArray(new String[0]));
+    } catch (Throwable t) {
+      t.printStackTrace();
+    } 
+    return IPlatformRunnable.EXIT_OK;
+  }
+
+  /**
+   * Helper method to tokenize the given string into a list of tokens.
+   * 
+   * @param s
+   * @return List of tokenized Strings
+   */
+  private List tokenize(String s) {
+    StringTokenizer st = new StringTokenizer(s, COMMA);
+    List tokens = new ArrayList(st.countTokens());
+    while(st.hasMoreTokens()) {
+      tokens.add(st.nextToken());
+    }
+    return tokens;
+  }
+
+  /**
+   * This is the main method which is invoked when running the run method of this runnable.  It will
+   * set up the Scanner instance, set the command line arguments, and call execute to calculate
+   * the extension point reference usages based on the given argument values:
+   * 
+   * extpt: Regular expressions for filtering which extension point's extensions will be scanned.
+   * output: The output directory of the usage files.
+   * includes: Optional regular expression for which plugins containing extensions should be included.
+   * excludes: Optional regular expression for which plugins containing extensions should be excluded.
+   * 
+   * @param args
+   */
+  public static void main(String[] args) {
+	// Parse the command line options
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    Collection optionsExtpt = (Collection)options.get(ARG_FILTERS);
+    Collection optionsOutput = (Collection)options.get(ARG_OUTPUT);
+    Collection optionsIncludes = (Collection)options.get(ARG_INCLUDES);
+    Collection optionsExcludes = (Collection)options.get(ARG_EXCLUDES);
+    // If improper arguments or argument values are specified, prompt for proper usage.
+    if (optionsExtpt == null || optionsOutput == null || optionsExtpt.isEmpty() || optionsOutput.isEmpty()) {
+      printUsage();
+      System.exit(-1);
+    }
+    // Create a new instance of the scanner class and set the command line arguments
+    ExtensionPointScanner scanner = new ExtensionPointScanner();
+    scanner.setFilters(optionsExtpt);
+    scanner.setOutput((String)optionsOutput.iterator().next());
+    scanner.setIncludes(optionsIncludes);
+    scanner.setExcludes(optionsExcludes);
+    // Invoke the execute method to run the extension point usage scan and output result file
+    scanner.execute();
+  }
+
+  /**
+   * This is a helper method to the user to print out an error message of the proper usage of 
+   * the arguments to be passed and the location of the output files.  
+   * See IOutputConstants for messages.
+   */
+  private static void printUsage() {
+    System.out.println(PRINT_USAGE_EXTENSION_POINT);
+    System.out.println(""); //$NON-NLS-1$
+    System.out.println(PRINT_EXTPT);
+    System.out.println(PRINT_OUTPUT_EXTENSION_POINT);
+    System.out.println(""); //$NON-NLS-1$
+    System.out.println(OPTIONS);
+    System.out.println(""); //$NON-NLS-1$
+    System.out.println(PRINT_INCLUDES);
+    System.out.println(PRINT_EXCLUDES);
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/FieldRef.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/FieldRef.java
new file mode 100644
index 0000000..ffa0733
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/FieldRef.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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;
+
+/**
+ * This encapsulates a field reference sub type of NamedRef.
+ */
+public class FieldRef extends NamedRef {
+  
+  /**
+   * Override the toString method to return information specific to field references
+   */
+  public String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.append("<field name=\""); //$NON-NLS-1$
+    sb.append(getName());
+    sb.append("\" desc=\""); //$NON-NLS-1$
+    sb.append(getDescriptor());
+    sb.append("\" ref=\""); //$NON-NLS-1$
+    sb.append(getRefCount());
+    sb.append("\"/>"); //$NON-NLS-1$
+    return sb.toString();
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/IComponentConstants.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/IComponentConstants.java
new file mode 100644
index 0000000..cb1e25a
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/IComponentConstants.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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;
+
+public interface IComponentConstants {
+	
+	public static final String WTP_SCANNING_PLUGIN = "org.eclipse.wtp.releng.tools.component.core"; //$NON-NLS-1$
+	
+	// ComponentTeam Names
+	public static final String COMPONENT_TEAM_JAVA_EE = "Java EE"; //$NON-NLS-1$
+	public static final String COMPONENT_TEAM_COMMON = "Common"; //$NON-NLS-1$
+	public static final String COMPONENT_TEAM_EDITORS = "XML/JSP"; //$NON-NLS-1$
+	public static final String COMPONENT_TEAM_RDB = "RDB"; //$NON-NLS-1$
+	public static final String COMPONENT_TEAM_WEB_SERVICES = "Web Services"; //$NON-NLS-1$
+	public static final String COMPONENT_TEAM_SERVER = "Server"; //$NON-NLS-1$
+	public static final String COMPONENT_TEAM_JEM = "Jem"; //$NON-NLS-1$
+	public static final String COMPONENT_TEAM_JSF = "JSF"; //$NON-NLS-1$
+	public static final String COMPONENT_TEAM_JPA = "JPA"; //$NON-NLS-1$
+	public static final String COMPONENT_TEAM_UNKNOWN = "Unknown"; //$NON-NLS-1$
+	
+	// General Expressions for plugin name matching
+	public static final String PLUGIN_EXPRESSION_J2EE = "org.eclipse..st.j2ee.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_EJB = "org.eclipse..st.ejb.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_SERVLET = "org.eclipse..st.servlet.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_WEB = "org.eclipse..st.web.*"; //$NON-NLS-1$
+	
+	public static final String PLUGIN_EXPRESSION_COMMAND = "org.eclipse..st.command.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_COMMON = "org.eclipse..st.common.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_VALIDATION = "org.eclipse..st.validation.*"; //$NON-NLS-1$
+	
+	public static final String PLUGIN_EXPRESSION_JSP = "org.eclipse..st.jsp.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_CSS = "org.eclipse..st.css.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_DTD = "org.eclipse..st.dtd.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_HTML = "org.eclipse..st.html.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_JAVASCRIPT = "org.eclipse..st.javascript.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_SSE = "org.eclipse..st.sse.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_XML = "org.eclipse..st.xml.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_XSD = "org.eclipse..st.xsd.*"; //$NON-NLS-1$
+	
+	public static final String PLUGIN_EXPRESSION_RDB = "org.eclipse..st.rdb.*"; //$NON-NLS-1$
+	
+	public static final String PLUGIN_EXPRESSION_WS = "org.eclipse..st.ws.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_WSDL = "org.eclipse..st.wsdl.*"; //$NON-NLS-1$
+	
+	public static final String PLUGIN_EXPRESSION_SERVER = "org.eclipse..st.server.*"; //$NON-NLS-1$
+	public static final String PLUGIN_EXPRESSION_INTERNET = "org.eclipse..st.internet.*"; //$NON-NLS-1$
+	
+	public static final String PLUGIN_EXPRESSION_JEM = "org.eclipse.jem.*"; //$NON-NLS-1$
+	
+	public static final String PLUGIN_EXPRESSION_JSF = "org.eclipse.jst.jsf.*"; //$NON-NLS-1$
+	
+	public static final String PLUGIN_EXPRESSION_JPA = "org.eclipse.jpa.*"; //$NON-NLS-1$
+	
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/IOutputConstants.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/IOutputConstants.java
new file mode 100644
index 0000000..61a8222
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/IOutputConstants.java
@@ -0,0 +1,25 @@
+package org.eclipse.wtp.releng.tools.component.adopters;
+
+public interface IOutputConstants {
+
+	public static final String LINE_BREAK = "\n"; //$NON-NLS-1$
+	public static final String COMMA = ","; //$NON-NLS-1$
+	public static final String HYPHEN = "-"; //$NON-NLS-1$
+	
+	public static final String XML_ROOT_BEGIN = "<root>"; //$NON-NLS-1$
+	public static final String XML_ROOT_END = "</root>" ; //$NON-NLS-1$
+	
+	public static final String PRINT_SOURCE_LOCATION = "\t-src\t\t<src>\t\tlocation of your usage reports"; //$NON-NLS-1$
+	public static final String PRINT_OUTPUT_LOCATION = "\t-output\t<output>\t\tlocation of the output file"; //$NON-NLS-1$
+	public static final String PRINT_COMPONENT_XML_API_LOCATION = "\t-api\t\t<api>\t\tlocation of your component.xml"; //$NON-NLS-1$
+	public static final String PRINT_USAGE_COMBINED = "Usage: java org.eclipse.wtp.releng.tools.component.adopters.CombineClass2Reference -src <src> -output <output>"; //$NON-NLS-1$
+	public static final String PRINT_USAGE_COMBINED_EXT_PT = "Usage: java org.eclipse.wtp.releng.tools.component.adopters.CombineExtensionPointScans -sourceFiles <sourcFiles> -output <output>"; //$NON-NLS-1$
+	public static final String PRINT_SOURCE_FILES_LOCATION = "\t-sourceFiles\t\t<sourceFiles>\t\tlocation of your extension point usage reports"; //$NON-NLS-1$
+	
+	public static final String PRINT_USAGE_EXTENSION_POINT = "Usage: java org.eclipse.wtp.releng.tools.component.adopters.ExtensionPointScanner -extpt -output [options]";//$NON-NLS-1$
+	public static final String PRINT_EXTPT = "\t-extpt\t\t<extpt>\t\tregular expressions for filtering your extension points"; //$NON-NLS-1$
+	public static final String PRINT_OUTPUT_EXTENSION_POINT = "\t-output\t\t<output>\t\toutput directory"; //$NON-NLS-1$
+	public static final String OPTIONS = "where options include:"; //$NON-NLS-1$
+	public static final String PRINT_INCLUDES = "\t-includes\t<includes>\tspace seperated extensions to include"; //$NON-NLS-1$
+	public static final String PRINT_EXCLUDES = "\t-excludes\t<excludes>\tspace seperated extensions to exclude"; //$NON-NLS-1$
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/Java2API.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/Java2API.java
new file mode 100644
index 0000000..a4887cd
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/Java2API.java
@@ -0,0 +1,300 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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.CharArrayWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.core.runtime.IPlatformRunnable;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.wtp.releng.tools.component.CommandOptionParser;
+import org.eclipse.wtp.releng.tools.component.IJavaVisitor;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentDepends;
+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.Location;
+import org.eclipse.wtp.releng.tools.component.internal.Plugin;
+
+public class Java2API implements IJavaVisitor, IPlatformRunnable
+{
+  private String src;
+  private String outputDir;
+  private Collection includes;
+  private Collection excludes;
+  private Collection excludePlugins;
+  private boolean defaultExclusive;
+  private List visitedPlugins = new ArrayList();
+
+  public String getOutputDir()
+  {
+    return outputDir;
+  }
+
+  public void setOutputDir(String outputDir)
+  {
+    this.outputDir = addTrailingSeperator(outputDir);
+  }
+
+  public String getSrc()
+  {
+    return src;
+  }
+
+  public void setSrc(String src)
+  {
+    this.src = src;
+  }
+
+  public Collection getIncludes()
+  {
+    return includes;
+  }
+
+  public void setIncludes(Collection includes)
+  {
+    this.includes = includes;
+  }
+
+  public Collection getExcludes()
+  {
+    return excludes;
+  }
+
+  public void setExcludes(Collection excludes)
+  {
+    this.excludes = excludes;
+  }
+
+  public Collection getExcludePlugins()
+  {
+    return excludePlugins;
+  }
+
+  public void setExcludePlugins(Collection excludePlugins)
+  {
+    this.excludePlugins = excludePlugins;
+  }
+
+  public boolean isDefaultExclusive()
+  {
+    return defaultExclusive;
+  }
+
+  public void setDefaultExclusive(boolean defaultExclusive)
+  {
+    this.defaultExclusive = defaultExclusive;
+  }
+
+  public List getVisitedPlugins()
+  {
+    return new ArrayList(visitedPlugins);
+  }
+
+  public void execute()
+  {
+    ILocation srcLocation = Location.createLocation(new File(src));
+    PDESourceVisitor pdeSrcVisitor = new PDESourceVisitor();
+    pdeSrcVisitor.setExcludes(excludePlugins);
+    srcLocation.accept(pdeSrcVisitor);
+    pdeSrcVisitor.setJavaVisitor(this);
+    srcLocation.accept(pdeSrcVisitor);
+    try
+    {
+      if (cachedCompXML != null)
+        cachedCompXML.save();
+    }
+    catch (IOException e)
+    {
+      throw new RuntimeException(e);
+    }
+  }
+  private ASTParser astParser;
+
+  public boolean visit(String pluginId, ILocation java)
+  {
+    if (!visitedPlugins.contains(pluginId))
+    {
+      visitedPlugins.add(pluginId);
+    }
+    if (include(java.getName()))
+    {
+      InputStreamReader isr = null;
+      CharArrayWriter caw = null;
+      try
+      {
+        ComponentXML compXML = getComponentXML(pluginId);
+        isr = new InputStreamReader(java.getInputStream());
+        caw = new CharArrayWriter();
+        char[] c = new char[2048];
+        for (int read = isr.read(c); read != -1; read = isr.read(c))
+          caw.write(c, 0, read);
+        isr.close();
+        caw.close();
+        if (astParser == null)
+          astParser = ASTParser.newParser(AST.JLS3);
+        astParser.setSource(caw.toCharArray());
+        ASTNode node = astParser.createAST(null);
+        node.accept(new Java2APIVisitor(compXML, defaultExclusive));
+      }
+      catch (IOException e)
+      {
+        throw new RuntimeException(e);
+      }
+      finally
+      {
+        if (isr != null)
+        {
+          try
+          {
+            isr.close();
+          }
+          catch (IOException e)
+          {
+          }
+        }
+        if (caw != null)
+          caw.close();
+      }
+    }
+    return true;
+  }
+
+  private boolean include(String name)
+  {
+    name = name.replace('/', '.');
+    name = name.replace('\\', '.');
+    if (excludes != null && !excludes.isEmpty())
+      for (Iterator it = excludes.iterator(); it.hasNext();)
+        if (name.matches((String)it.next()))
+          return false;
+    if (includes != null && !includes.isEmpty())
+    {
+      for (Iterator it = includes.iterator(); it.hasNext();)
+        if (name.matches((String)it.next()))
+          return true;
+      return false;
+    }
+    return true;
+  }
+
+  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;
+  }
+
+  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;
+    }
+  }
+
+  public Object run(Object arguments)
+  {
+    String src = System.getProperty("src");
+    String outputDir = System.getProperty("outputDir");
+    String includes = System.getProperty("includes");
+    String excludes = System.getProperty("excludes");
+    try
+    {
+    main(new String[]{"-src", src, "-outputDir", outputDir, "-includes", includes, "-excludes", excludes});
+    }
+    catch (Throwable t)
+    {
+      t.printStackTrace();
+    }
+    return IPlatformRunnable.EXIT_OK;
+  }
+
+  public static void main(String[] args)
+  {
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    Collection src = (Collection)options.get("src");
+    Collection outputDir = (Collection)options.get("outputDir");
+    Collection includes = (Collection)options.get("includes");
+    Collection excludes = (Collection)options.get("excludes");
+    Collection excludePlugins = (Collection)options.get("excludePlugins");
+    Collection defaultExclusive = (Collection)options.get("defaultExclusive");
+    if (src == null || outputDir == null || src.isEmpty() || outputDir.isEmpty())
+    {
+      printUsage();
+      System.exit(-1);
+    }
+    Java2API java2API = new Java2API();
+    java2API.setSrc((String)src.iterator().next());
+    java2API.setOutputDir((String)outputDir.iterator().next());
+    java2API.setIncludes(includes);
+    java2API.setExcludes(excludes);
+    java2API.setExcludePlugins(excludePlugins);
+    java2API.setDefaultExclusive(defaultExclusive != null);
+    java2API.execute();
+  }
+
+  private static void printUsage()
+  {
+    System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.java.Java2API -src <src> -outputDir <outputDir> [-options]");
+    System.out.println("");
+    System.out.println("\t-src\t\t<src>\t\tlocation of a Eclipse-based product (requires SDK build)");
+    System.out.println("\t-outputDir\t<outputDir>\toutput directory of component.xml files");
+    System.out.println("");
+    System.out.println("where options include:");
+    System.out.println("");
+    System.out.println("\t-includes\t<includes>\tspace seperated packages to include");
+    System.out.println("\t-excludes\t<excludes>\tspace seperated packages to exclude");
+    System.out.println("\t-excludePlugins\t<excludePlugins>\tspace seperated plugins to exclude");
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/Java2APIVisitor.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/Java2APIVisitor.java
new file mode 100644
index 0000000..c690f15
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/Java2APIVisitor.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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 org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.PackageDeclaration;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentXML;
+import org.eclipse.wtp.releng.tools.component.internal.Package;
+
+public class Java2APIVisitor extends ASTVisitor
+{
+  private ComponentXML compXML;
+  private String packageName;
+  private boolean defaultExclusive;
+
+  public Java2APIVisitor(ComponentXML compXML)
+  {
+    this(compXML, true);
+  }
+
+  public Java2APIVisitor(ComponentXML compXML, boolean defaultExclusive)
+  {
+    super(false);
+    this.compXML = compXML;
+    this.packageName = null;
+    this.defaultExclusive = defaultExclusive;
+  }
+
+  public boolean visit(PackageDeclaration node)
+  {
+    packageName = node.getName().getFullyQualifiedName();
+    return true;
+  }
+
+  public boolean visit(TypeDeclaration node)
+  {
+    if (packageName != null)
+    {
+      Package pkg = compXML.getPackage(packageName);
+      if (pkg == null)
+      {
+        pkg = new Package();
+        pkg.setName(packageName);
+        pkg.setApi(Boolean.TRUE);
+        if (!defaultExclusive)
+          pkg.setExclusive(Boolean.FALSE);
+        compXML.addPackage(pkg);
+      }
+    }
+    return false;
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/JavadocScanner.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/JavadocScanner.java
new file mode 100644
index 0000000..9dfce6f
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/JavadocScanner.java
@@ -0,0 +1,427 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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.ByteArrayInputStream;
+import java.io.CharArrayWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.eclipse.core.runtime.IPlatformRunnable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.wtp.releng.tools.component.CommandOptionParser;
+import org.eclipse.wtp.releng.tools.component.IJavaVisitor;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.ILocationVisitor;
+import org.eclipse.wtp.releng.tools.component.api.API2ComponentAPI;
+import org.eclipse.wtp.releng.tools.component.api.ComponentAPI;
+import org.eclipse.wtp.releng.tools.component.api.ComponentXMLVisitor;
+import org.eclipse.wtp.releng.tools.component.images.ImagesUtil;
+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.Location;
+import org.eclipse.wtp.releng.tools.component.internal.Package;
+import org.eclipse.wtp.releng.tools.component.internal.Plugin;
+import org.eclipse.wtp.releng.tools.component.internal.Type;
+import org.eclipse.wtp.releng.tools.component.xsl.XSLUtil;
+
+public class JavadocScanner implements IJavaVisitor, IPlatformRunnable
+{
+  private Collection src;
+  private String api;
+  private String outputDir;
+  private Collection includes;
+  private Collection excludes;
+  private boolean skipAPIGen;
+  private boolean html;
+  private String xsl;
+
+  public String getOutputDir()
+  {
+    return outputDir;
+  }
+
+  public void setOutputDir(String outputDir)
+  {
+    this.outputDir = addTrailingSeperator(outputDir);
+  }
+
+  public Collection getSrc()
+  {
+    return src;
+  }
+
+  public void setSrc(Collection src)
+  {
+    this.src = src;
+  }
+
+  public String getApi()
+  {
+    return api;
+  }
+
+  public void setApi(String api)
+  {
+    this.api = api;
+  }
+
+  public Collection getIncludes()
+  {
+    return includes;
+  }
+
+  public void setIncludes(Collection includes)
+  {
+    this.includes = includes;
+  }
+
+  public Collection getExcludes()
+  {
+    return excludes;
+  }
+
+  public void setExcludes(Collection excludes)
+  {
+    this.excludes = excludes;
+  }
+
+  public boolean isSkipAPIGen()
+  {
+    return skipAPIGen;
+  }
+
+  public void setSkipAPIGen(boolean skipAPIGen)
+  {
+    this.skipAPIGen = skipAPIGen;
+  }
+
+  public boolean isHtml()
+  {
+    return html;
+  }
+
+  public void setHtml(boolean html)
+  {
+    this.html = html;
+  }
+
+  public String getXsl()
+  {
+    return xsl;
+  }
+
+  public void setXsl(String xsl)
+  {
+    this.xsl = xsl;
+  }
+
+  private Map pluginId2CompXML = new HashMap();
+
+  public void execute()
+  {
+    // Generate api-info.xml
+    if (!skipAPIGen)
+    {
+      API2ComponentAPI api2CompXML = new API2ComponentAPI();
+      api2CompXML.setApi(api);
+      api2CompXML.setSrc(src);
+      api2CompXML.setOutputDir(outputDir);
+      api2CompXML.setIncludes(includes);
+      api2CompXML.setExcludes(excludes);
+      api2CompXML.setReadInterface(true);
+      api2CompXML.setSkipAPIGen(skipAPIGen);
+      api2CompXML.execute();
+    }
+
+    // Collection component.xml files
+    ILocation apiLocation = Location.createLocation(new File(api));
+    ComponentXMLVisitor compXMLVisitor = new ComponentXMLVisitor();
+    apiLocation.accept(compXMLVisitor);
+    for (Iterator it = compXMLVisitor.getCompXMLs().iterator(); it.hasNext();)
+    {
+      ComponentXML compXML = (ComponentXML)it.next();
+      for (Iterator it2 = compXML.getPlugins().iterator(); it2.hasNext();)
+      {
+        pluginId2CompXML.put(((Plugin)it2.next()).getId(), compXML);
+      }
+    }
+
+    // visit .java
+    scanJavaSources();
+
+    // Save report
+    try
+    {
+      if (cachedCompAPI != null)
+        cachedCompAPI.save();
+    }
+    catch (IOException e)
+    {
+      throw new RuntimeException(e);
+    }
+    if (isHtml())
+    {
+      ImagesUtil.copyAllFromBundle(Platform.getBundle("org.eclipse.wtp.releng.tools.component.core"), outputDir);
+      genHTML();
+    }
+  }
+
+  protected void scanJavaSources()
+  {
+    for (Iterator it = src.iterator(); it.hasNext();)
+    {
+      ILocation srcLocation = Location.createLocation(new File((String)it.next()));
+      PDESourceVisitor pdeSrcVisitor = new PDESourceVisitor();
+      srcLocation.accept(pdeSrcVisitor);
+      pdeSrcVisitor.setJavaVisitor(this);
+      srcLocation.accept(pdeSrcVisitor);
+    }
+  }
+
+  private void genHTML()
+  {
+    final StringBuffer summary = new StringBuffer();
+    summary.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    summary.append("<root>");
+    File f = new File(outputDir);
+    f.mkdirs();
+    ILocation outputLoc = Location.createLocation(f);
+    outputLoc.accept(new ILocationVisitor()
+      {
+        public boolean accept(ILocation location)
+        {
+          if (location.getName().endsWith("api-info.xml"))
+          {
+            try
+            {
+              XSLUtil.transform
+              (
+                xsl != null && xsl.length() > 0 ? Location.createLocation(new File(xsl)).getInputStream() : Platform.getBundle("org.eclipse.wtp.releng.tools.component.core").getResource("org/eclipse/wtp/releng/tools/component/xsl/api-javadoc.xsl").openStream(),
+                location.getInputStream(),
+                new FileOutputStream(((FileLocation)location.createSibling("api-javadoc.html")).getFile())
+              );
+              summary.append("<api-info file=\"");
+              summary.append(location.getAbsolutePath().substring(outputDir.length()));
+              summary.append("\"/>");
+            }
+            catch (Throwable e)
+            {
+              e.printStackTrace();
+            }
+          }
+          return true;
+        }
+      }
+    );
+    summary.append("</root>");
+    try
+    {
+      XSLUtil.transform
+      (
+        Platform.getBundle("org.eclipse.wtp.releng.tools.component.core").getResource("org/eclipse/wtp/releng/tools/component/xsl/api-javadoc-summary.xsl").openStream(),
+        new ByteArrayInputStream(summary.toString().getBytes()),
+        new FileOutputStream(new File(outputDir + "/api-javadoc-summary.html")),
+        outputDir
+      );
+    }
+    catch (Throwable e)
+    {
+      e.printStackTrace();
+    }
+  }
+
+  protected ASTParser astParser;
+
+  public boolean visit(String pluginId, ILocation java)
+  {
+    String name = java.getName();
+    if (include(name) && isAPI(pluginId, name))
+    {
+      try
+      {
+        ComponentAPI compAPI = getComponentAPI(pluginId);
+        InputStreamReader isr = new InputStreamReader(java.getInputStream());
+        CharArrayWriter caw = new CharArrayWriter();
+        char[] c = new char[2048];
+        for (int read = isr.read(c); read != -1; read = isr.read(c))
+          caw.write(c, 0, read);
+        isr.close();
+        caw.close();
+        if (astParser == null)
+          astParser = ASTParser.newParser(AST.JLS3);
+        astParser.setSource(caw.toCharArray());
+        ASTNode node = astParser.createAST(null);
+        node.accept(new JavadocVisitor(compAPI, pluginId));
+      }
+      catch (IOException e)
+      {
+        throw new RuntimeException(e);
+      }
+    }
+    return true;
+  }
+
+  protected boolean isAPI(String pluginId, String name)
+  {
+    ComponentXML compXML = (ComponentXML)pluginId2CompXML.get(pluginId);
+    if (compXML != null)
+    {
+      name = name.substring(0, name.length() - ".java".length());
+      name = name.replace('/', '.');
+      name = name.replace('\\', '.');
+      int i = name.lastIndexOf('.');
+      String packageName = (i != -1) ? name.substring(0, i) : "";
+      String localName = (i != -1) ? name.substring(i + 1) : name;
+      Package pkg = compXML.getPackage(packageName);
+      if (pkg != null)
+      {
+        Type type = pkg.getType(localName);
+        if (type != null)
+        {
+          return type.isReference() || type.isSubclass() || type.isImplement() || type.isInstantiate();
+        }
+        else
+        {
+          return pkg.isApi();
+        }
+      }
+    }
+    return false;
+  }
+
+  protected boolean include(String name)
+  {
+    name = name.replace('/', '.');
+    name = name.replace('\\', '.');
+    if (excludes != null && !excludes.isEmpty())
+      for (Iterator it = excludes.iterator(); it.hasNext();)
+        if (name.matches((String)it.next()))
+          return false;
+    if (includes != null && !includes.isEmpty())
+    {
+      for (Iterator it = includes.iterator(); it.hasNext();)
+        if (name.matches((String)it.next()))
+          return true;
+      return false;
+    }
+    return true;
+  }
+  private ComponentAPI cachedCompAPI;
+
+  protected ComponentAPI getComponentAPI(String id) throws IOException
+  {
+    if (cachedCompAPI != null)
+    {
+      if (cachedCompAPI.getName().equals(id))
+      {
+        return cachedCompAPI;
+      }
+      else
+      {
+        cachedCompAPI.save();
+      }
+    }
+    StringBuffer sb = new StringBuffer(outputDir);
+    sb.append(id);
+    sb.append("/api-info.xml");
+    File file = new File(sb.toString());
+    cachedCompAPI = new ComponentAPI();
+    cachedCompAPI.setName(id);
+    cachedCompAPI.setLocation(new FileLocation(file));
+    if (file.exists())
+      cachedCompAPI.load();
+    return cachedCompAPI;
+  }
+
+  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;
+    }
+  }
+
+  public Object run(Object arguments)
+  {
+    String src = System.getProperty("src");
+    String api = System.getProperty("api");
+    String outputDir = System.getProperty("outputDir");
+    String includes = System.getProperty("includes");
+    String excludes = System.getProperty("excludes");
+    String skipAPIGen = System.getProperty("skipAPIGen");
+    String html = System.getProperty("html");
+    String xsl = System.getProperty("xsl");
+    main(new String[]{"-src", src, "-api", api, "-outputDir", outputDir, "-includes", includes, "-excludes", excludes, skipAPIGen != null ? "-skipAPIGen" : "", html != null ? "-html" : "", "-xsl", xsl});
+    return IPlatformRunnable.EXIT_OK;
+  }
+
+  public static void main(String[] args)
+  {
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    Collection src = (Collection)options.get("src");
+    Collection api = (Collection)options.get("api");
+    Collection outputDir = (Collection)options.get("outputDir");
+    Collection includes = (Collection)options.get("includes");
+    Collection excludes = (Collection)options.get("excludes");
+    Collection skipAPIGen = (Collection)options.get("skipAPIGen");
+    Collection html = (Collection)options.get("html");
+    Collection xsl = (Collection)options.get("xsl");
+    if (src == null || api == null || outputDir == null || src.isEmpty() || api.isEmpty() || outputDir.isEmpty())
+    {
+      printUsage();
+      System.exit(-1);
+    }
+    JavadocScanner javadocScanner = new JavadocScanner();
+    javadocScanner.setSrc(src);
+    javadocScanner.setApi((String)api.iterator().next());
+    javadocScanner.setOutputDir((String)outputDir.iterator().next());
+    javadocScanner.setIncludes(includes);
+    javadocScanner.setExcludes(excludes);
+    javadocScanner.setSkipAPIGen(skipAPIGen != null);
+    javadocScanner.setHtml(html != null);
+    javadocScanner.setXsl(xsl != null && !xsl.isEmpty() ? (String)xsl.iterator().next() : null);
+    javadocScanner.execute();
+  }
+
+  protected static void printUsage()
+  {
+    System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.java.JavadocScanner -src <src> -api <api> -outputDir <outputDir> [-options]");
+    System.out.println("");
+    System.out.println("\t-src\t\t<src>\t\tlocation of a Eclipse-based product (requires SDK build)");
+    System.out.println("\t-api\t\t<api>\t\tlocation of your component.xml");
+    System.out.println("\t-outputDir\t<outputDir>\toutput directory of component.xml files");
+    System.out.println("");
+    System.out.println("where options include:");
+    System.out.println("");
+    System.out.println("\t-includes\t<includes>\tspace seperated packages to include");
+    System.out.println("\t-excludes\t<excludes>\tspace seperated packages to exclude");
+    System.out.println("\t-skipAPIGen\t\t\tskip api-info.xml generation and use existing ones");
+    System.out.println("\t-html\t\t\tgenerate HTML results");
+    System.out.println("\t-xsl\t<xsl>\tuse your own stylesheet. You must specify the -html option");
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/JavadocVisitor.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/JavadocVisitor.java
new file mode 100644
index 0000000..ad696be
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/JavadocVisitor.java
@@ -0,0 +1,380 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.FieldDeclaration;
+import org.eclipse.jdt.core.dom.ImportDeclaration;
+import org.eclipse.jdt.core.dom.Javadoc;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.MethodRef;
+import org.eclipse.jdt.core.dom.Modifier;
+import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jdt.core.dom.PackageDeclaration;
+import org.eclipse.jdt.core.dom.PrimitiveType;
+import org.eclipse.jdt.core.dom.SimpleName;
+import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.core.dom.TagElement;
+import org.eclipse.jdt.core.dom.Type;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
+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.JavadocCoverage;
+import org.eclipse.wtp.releng.tools.component.api.MethodAPI;
+import org.eclipse.wtp.releng.tools.component.api.PackageAPI;
+import org.osgi.framework.Bundle;
+
+public class JavadocVisitor extends ASTVisitor
+{
+  private ComponentAPI compAPI;
+  private String pluginId;
+  private String packageName;
+  private Map imports;
+  private List classAPIs;
+
+  public JavadocVisitor(ComponentAPI compAPI, String pluginId)
+  {
+    super(true);
+    this.compAPI = compAPI;
+    this.pluginId = pluginId;
+    this.packageName = null;
+    this.imports = new HashMap();
+    this.classAPIs = new ArrayList();
+  }
+
+  public boolean visit(PackageDeclaration node)
+  {
+    packageName = node.getName().getFullyQualifiedName();
+    return true;
+  }
+
+  public boolean visit(ImportDeclaration node)
+  {
+    String fullName = node.getName().getFullyQualifiedName();
+    int i = fullName.lastIndexOf('.');
+    String localName = (i != -1) ? fullName.substring(i + 1) : fullName;
+    imports.put(localName, fullName);
+    return true;
+  }
+
+  public boolean visit(TypeDeclaration node)
+  {
+    int modifiers = node.getModifiers();
+    if (!Modifier.isPrivate(modifiers))
+    {
+      PackageAPI pkgAPI = compAPI.getPackageAPI(packageName);
+      if (pkgAPI != null)
+      {
+        String className = getClassName(node.getName().getFullyQualifiedName());
+        ClassAPI classAPI = pkgAPI.getClassAPI(className);
+        if (classAPI != null)
+        {
+          classAPIs.add(classAPI);
+          Javadoc javadoc = node.getJavadoc();
+          if (javadoc != null)
+          {
+            for (Iterator it = javadoc.tags().iterator(); it.hasNext();)
+            {
+              TagElement tag = (TagElement)it.next();
+              String tagName = tag.getTagName();
+              if (tagName != null && tagName.equals(TagElement.TAG_SINCE))
+              {
+                // do nothing because default is true
+                return true;
+              }
+            }
+          }
+          classAPI.getJavadocCoverage().setHasSince(Boolean.FALSE);
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  public void endVisit(TypeDeclaration node)
+  {
+    int modifiers = node.getModifiers();
+    if (!Modifier.isPrivate(modifiers))
+    {
+      PackageAPI pkgAPI = compAPI.getPackageAPI(packageName);
+      if (pkgAPI != null)
+      {
+        String className = getClassName(node.getName().getFullyQualifiedName());
+        ClassAPI classAPI = pkgAPI.getClassAPI(className);
+        if (classAPI != null)
+        {
+          classAPIs.remove(classAPIs.size() - 1);
+        }
+      }
+    }
+  }
+
+  private String getClassName(String name)
+  {
+    StringBuffer sb = new StringBuffer();
+    for (int i = 0; i < classAPIs.size(); i++)
+    {
+      sb.append(((ClassAPI)classAPIs.get(i)).getName());
+      sb.append('$');
+    }
+    sb.append(name);
+    return sb.toString();
+  }
+
+  public boolean visit(MethodDeclaration node)
+  {
+    if (node.getParent().getNodeType() == ASTNode.ANONYMOUS_CLASS_DECLARATION)
+      return false;
+    ClassAPI classAPI = (ClassAPI)classAPIs.get(classAPIs.size() - 1);
+    if (classAPI != null && !Modifier.isPrivate(node.getModifiers()))
+    {
+      boolean isConstructor = node.isConstructor();
+      String methodName = isConstructor ? "&lt;init>" : node.getName().getFullyQualifiedName();
+
+      // input parameters
+      List parameters = node.parameters();
+      List params = new ArrayList(parameters.size());
+      List inputs = new ArrayList(parameters.size());
+      for (Iterator it = parameters.iterator(); it.hasNext();)
+      {
+        SingleVariableDeclaration parameter = (SingleVariableDeclaration)it.next();
+        params.add(parameter.getName().getIdentifier());
+        inputs.add(getTypeString(parameter));
+      }
+
+      // return type
+      boolean hasReturn = isConstructor;
+      Type returnType = node.getReturnType2();
+      String returnTypeString = !isConstructor ? returnType.toString() : PrimitiveType.VOID.toString();
+      if (!hasReturn && returnType instanceof PrimitiveType)
+        if (((PrimitiveType)returnType).getPrimitiveTypeCode() == PrimitiveType.VOID)
+          hasReturn = true;
+
+      // exceptions
+      List exs = node.thrownExceptions();
+      List thrownExceptions = new ArrayList(exs.size());
+      for (Iterator it = exs.iterator(); it.hasNext();)
+      {
+        Name name = (Name)it.next();
+        thrownExceptions.add(name.getFullyQualifiedName());
+      }
+
+      // MethodAPI
+      MethodAPI methodAPI = classAPI.getMethodAPI(methodName, inputs, returnTypeString);
+
+      // javadoc
+      boolean hasJavadoc = false;
+      Javadoc javadoc = node.getJavadoc();
+      if (javadoc != null)
+      {
+        hasJavadoc = true;
+        for (Iterator it = javadoc.tags().iterator(); it.hasNext();)
+        {
+          TagElement tag = (TagElement)it.next();
+          String tagName = tag.getTagName();
+          if (tagName != null)
+          {
+            if (tagName.equals(TagElement.TAG_RETURN))
+              hasReturn = tag.fragments().size() > 0;
+            else if (tagName.equals(TagElement.TAG_PARAM))
+            {
+              List fragments = tag.fragments();
+              if (fragments.size() > 1)
+              {
+                Object fragment = fragments.get(0);
+                if (fragment instanceof SimpleName)
+                {
+                  params.remove(((SimpleName)fragment).getIdentifier());
+                }
+              }
+            }
+            else if (tagName.equals(TagElement.TAG_THROWS) || tagName.equals(TagElement.TAG_EXCEPTION))
+            {
+              List fragments = tag.fragments();
+              if (fragments.size() > 1)
+              {
+                Object fragment = fragments.get(0);
+                if (fragment instanceof Name)
+                {
+                  thrownExceptions.remove(((Name)fragment).getFullyQualifiedName());
+                }
+              }
+            }
+            else if (tagName.equals(TagElement.TAG_SEE))
+            {
+              List fragments = tag.fragments();
+              if (fragments.size() > 0)
+              {
+                Object fragment = fragments.get(0);
+                if (fragment instanceof MethodRef)
+                {
+                  MethodRef methodRef = (MethodRef)fragment;
+                  if (methodName.equals(methodRef.getName().getFullyQualifiedName()))
+                  {
+                    return true;
+                  }
+                }
+              }
+            }
+            else if (tagName.equals(TagElement.TAG_INHERITDOC))
+            {
+              return true;
+            }
+          }
+        }
+      }
+      else if (methodAPI != null && !isConstructor)
+      {
+        StringBuffer qualifiedClassName = new StringBuffer();
+        qualifiedClassName.append(packageName);
+        qualifiedClassName.append('.');
+        qualifiedClassName.append(classAPI.getName());
+        if (inheritJavadoc(qualifiedClassName.toString(), methodName, inputs))
+        {
+          return true;
+        }
+      }
+
+      if (methodAPI != null && (!hasJavadoc || !hasReturn || params.size() > 0 || thrownExceptions.size() > 0))
+      {
+        JavadocCoverage javadocCoverage = methodAPI.getJavadocCoverage();
+        if (!hasJavadoc)
+        {
+          javadocCoverage.setHasDoc(Boolean.FALSE);
+        }
+        if (!hasReturn)
+        {
+          javadocCoverage.setHasReturn(Boolean.FALSE);
+        }
+        if (params.size() > 0)
+        {
+          for (Iterator it = params.iterator(); it.hasNext();)
+          {
+            javadocCoverage.addMissingParam((String)it.next());
+          }
+        }
+        if (thrownExceptions.size() > 0)
+        {
+          for (Iterator it = thrownExceptions.iterator(); it.hasNext();)
+          {
+            javadocCoverage.addMissingThrow((String)it.next());
+          }
+        }
+      }
+    }
+    return true;
+  }
+
+  private boolean inheritJavadoc(String className, String methodName, List params)
+  {
+    if (pluginId != null)
+    {
+      Bundle bundle = Platform.getBundle(pluginId);
+      if (bundle != null)
+      {
+        try
+        {
+          Class clazz = bundle.loadClass(className);
+          if (clazz != null)
+          {
+            Class[] interfaces = clazz.getInterfaces();
+            for (int i = 0; i < interfaces.length; i++)
+              if (hasMethod(interfaces[i], methodName, params))
+                return true;
+            return hasMethod(clazz.getSuperclass(), methodName, params);
+          }
+        }
+        catch (ClassNotFoundException cnfe)
+        {
+        }
+      }
+    }
+    return false;
+  }
+
+  private boolean hasMethod(Class clazz, String methodName, List params)
+  {
+    if (clazz == null)
+      return false;
+    Method[] methods = clazz.getDeclaredMethods();
+    for (int i = 0; i < methods.length; i++)
+    {
+      if (methods[i].getName().equals(methodName))
+      {
+        Class[] paramClasses = methods[i].getParameterTypes();
+        if (paramClasses.length == params.size())
+        {
+          boolean paramsMatched = true;
+          for (int j = 0; j < paramClasses.length; j++)
+          {
+            if (!paramClasses[j].getName().endsWith((String)params.get(j)))
+            {
+              paramsMatched = false;
+              break;
+            }
+          }
+          if (paramsMatched)
+            return true;
+        }
+      }
+    }
+    if (!clazz.getName().equals("java.lang.Object"))
+    {
+      Class[] interfaces = clazz.getInterfaces();
+      for (int i = 0; i < interfaces.length; i++)
+        if (hasMethod(interfaces[i], methodName, params))
+          return true;
+      return hasMethod(clazz.getSuperclass(), methodName, params);
+    }
+    else
+    {
+      return false;
+    }
+  }
+
+  private String getTypeString(SingleVariableDeclaration svd)
+  {
+    int dim = svd.getExtraDimensions();
+    StringBuffer sb = new StringBuffer();
+    sb.append(svd.getType().toString());
+    for (int i = 0; i < dim; i++)
+      sb.append("[]");
+    return sb.toString();
+  }
+
+  public boolean visit(FieldDeclaration node)
+  {
+    ClassAPI classAPI = (ClassAPI)classAPIs.get(classAPIs.size() - 1);
+    if (classAPI != null && !Modifier.isPrivate(node.getModifiers()))
+    {
+      VariableDeclarationFragment varDeclFragment = (VariableDeclarationFragment)node.fragments().iterator().next();
+      String fieldName = varDeclFragment.getName().getFullyQualifiedName();
+      FieldAPI fieldAPI = classAPI.getFieldAPI(fieldName);
+      if (fieldAPI != null && node.getJavadoc() == null)
+      {
+        fieldAPI.setJavadocCoverage(new JavadocCoverage());
+      }
+    }
+    return true;
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/MethodRef.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/MethodRef.java
new file mode 100644
index 0000000..4294f47
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/MethodRef.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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;
+
+/**
+ * This class encapsulates information about a method reference.  It is a sub type of NamedRef.
+ */
+public class MethodRef extends NamedRef {
+  
+  /**
+   * Overrides the toString method to return specifics for the method reference
+   */
+  public String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.append("<method name=\""); //$NON-NLS-1$
+    sb.append(encode(getName()));
+    sb.append("\" desc=\""); //$NON-NLS-1$
+    sb.append(getDescriptor());
+    sb.append("\" ref=\""); //$NON-NLS-1$
+    sb.append(getRefCount());
+    sb.append("\"/>"); //$NON-NLS-1$
+    return sb.toString();
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/NamedRef.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/NamedRef.java
new file mode 100644
index 0000000..50a518d
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/NamedRef.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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;
+
+/**
+ * This is a base class for caching information about named references.
+ */
+public class NamedRef {
+  // class variable for strings	
+  private static final String LESS_THAN = "&lt;"; //$NON-NLS-1$
+  
+  // Instance variables detailing information about the reference
+  private String name;
+  private String descriptor;
+  private int refCount = 0;
+  
+  /**
+   * @return String descriptor
+   */
+  public String getDescriptor() {
+    return descriptor;
+  }
+
+  /**
+   * Set the descriptor.
+   * @param String descriptor
+   */
+  public void setDescriptor(String descriptor) {
+    this.descriptor = descriptor;
+  }
+
+  /**
+   * @return String name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Set the name string.
+   * @param String name
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+  
+  /**
+   * @return int reference count
+   */
+  public int getRefCount() {
+    return refCount;
+  }
+
+  /**
+   * Set the reference count.
+   * @param aRefCount int
+   */
+  public void setRefCount(int aRefCount) {
+    refCount = aRefCount;
+  }
+
+  /**
+   * Increment the current reference count by 1.
+   */
+  public void incRefCount() {
+    this.refCount++;
+  }
+
+  /**
+   * Encode all occurences of "<" with "&lt;" in the given string
+   * 
+   * @param s String
+   * @return encoded String
+   */
+  protected String encode(String s) {
+    int index = s.indexOf('<');
+    if (index != -1) {
+      StringBuffer sb = new StringBuffer(s);
+      while (index != -1) {
+        sb.deleteCharAt(index);
+        sb.insert(index, new char[] {'&', 'l', 't', ';'}, 0, 4);
+        index = sb.toString().indexOf('<');
+      }
+      return sb.toString();
+    }
+    return s;
+  }
+
+  /**
+   * Decode all occurences of "&lt;" with "<" in the given string
+   * 
+   * @param s String
+   * @return decoded String
+   */
+  protected String decode(String s) {
+    int index = s.indexOf(LESS_THAN);
+    if (index != -1) {
+      StringBuffer sb = new StringBuffer(s);
+      while (index != -1) {
+        sb.delete(index, index + 4);
+        sb.insert(index, '<');
+        index = sb.toString().indexOf(LESS_THAN);
+      }
+      return sb.toString();
+    }
+    return s;
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/PDESourceVisitor.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/PDESourceVisitor.java
new file mode 100644
index 0000000..322ac67
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/PDESourceVisitor.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * 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.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.eclipse.wtp.releng.tools.component.IFileLocation;
+import org.eclipse.wtp.releng.tools.component.IJavaVisitor;
+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.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+public class PDESourceVisitor implements ILocationVisitor
+{
+  private IJavaVisitor javaVisitor;
+  private List srcs;
+  private Collection excludes;
+
+  public PDESourceVisitor()
+  {
+    this.javaVisitor = null;
+    this.srcs = new ArrayList();
+  }
+
+  public void setJavaVisitor(IJavaVisitor javaVisitor)
+  {
+    this.javaVisitor = javaVisitor;
+  }
+
+  public void setExcludes(Collection excludes)
+  {
+    this.excludes = excludes;
+  }
+
+  public boolean accept(ILocation location)
+  {
+    String locationName = location.getName();
+    String absPath = location.getAbsolutePath();
+    if (javaVisitor == null && (locationName.endsWith("plugin.xml") || locationName.endsWith("fragment.xml")))
+    {
+      try
+      {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder builder = factory.newDocumentBuilder();
+        Document doc = builder.parse(location.getInputStream());
+        Element root = doc.getDocumentElement();
+        NodeList exts = root.getElementsByTagName("extension");
+        for (int i = 0; i < exts.getLength(); i++)
+        {
+          Element ext = (Element)exts.item(i);
+          if ("org.eclipse.pde.core.source".equals(ext.getAttribute("point")))
+          {
+            NodeList locs = ext.getElementsByTagName("location");
+            for (int j = 0; j < locs.getLength(); j++)
+            {
+              Element loc = (Element)locs.item(j);
+              String path = loc.getAttribute("path");
+              if (path != null && path.length() > 0)
+              {
+                StringBuffer sb = new StringBuffer();
+                if (locationName.endsWith("plugin.xml"))
+                  //sb.append(locationName.substring(0, locationName.length() - "plugin.xml".length() - 1));
+                  sb.append(absPath.substring(0, absPath.length() - "plugin.xml".length() - 1));
+                else
+                  //sb.append(locationName.substring(0, locationName.length() - "fragment.xml".length() - 1));
+                  sb.append(absPath.substring(0, absPath.length() - "fragment.xml".length() - 1));
+                sb.append("/");
+                sb.append(path);
+                srcs.add(sb.toString());
+              }
+            }
+          }
+        }
+      }
+      catch (Throwable e)
+      {
+      }
+    }
+    else if (javaVisitor != null && locationName.endsWith("src.zip"))
+    {
+      //String pluginId = getPluginId(locationName);
+      String pluginId = getPluginId(absPath);
+      if (pluginId != null && (excludes == null || !excludes.contains(pluginId)))
+      {
+        ILocationChildrenIterator it = location.childIterator();
+        for (ILocation child = it.next(); child != null; child = it.next())
+        {
+          if (child.getName().endsWith(".java"))
+          {
+            javaVisitor.visit(pluginId, child);
+          }
+        }
+      }
+    }
+    if (location instanceof IZipLocation)
+      return true;
+    else if ((location instanceof IFileLocation) && ((IFileLocation)location).getFile().isDirectory())
+      return true;
+    else
+      return false;
+  }
+
+  private String getPluginId(String name)
+  {
+    for (Iterator it = srcs.iterator(); it.hasNext();)
+    {
+      String src = (String)it.next();
+      if (name.startsWith(src))
+      {
+        int startIndex = src.length() + 1;
+        int endIndex = name.indexOf('/', startIndex);
+        if (endIndex == -1)
+          endIndex = name.indexOf('\\', startIndex);
+        if (endIndex != -1)
+        {
+          String id = name.substring(startIndex, endIndex);
+          int versionIndex = id.indexOf('_');
+          if (versionIndex != -1)
+            id = id.substring(0, versionIndex);
+          return id;
+        }
+      }
+    }
+    return null;
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/Plugin2API.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/Plugin2API.java
new file mode 100644
index 0000000..15debb5
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/Plugin2API.java
@@ -0,0 +1,429 @@
+/*******************************************************************************
+ * 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.Attributes;
+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.IClassVisitor;
+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.internal.Bundle;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentDepends;
+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.Location;
+import org.eclipse.wtp.releng.tools.component.internal.Package;
+import org.eclipse.wtp.releng.tools.component.internal.Plugin;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * The Plugin2API executable class will iterate over all of the plguins in the src location
+ * and determine the API's the classes in the those plugins provide.  It uses Java2API to do
+ * this calculation and it will output this information to the outputDir provided.
+ */
+public class Plugin2API implements ILocationVisitor, IClassVisitor {
+  // Arguments which should be set
+  private Collection src;
+  private String outputDir;
+  
+  // Instance variables
+  private Map lib2pluginId = new HashMap();
+  private boolean visitPlugins;
+  private List visitedPlugins;
+  private ComponentXML cachedCompXML;
+  
+  // String constants
+  private static final String COMPONENT_XML = "/component.xml"; //$NON-NLS-1$
+  private static final String PLUGIN_XML = "plugin.xml"; //$NON-NLS-1$
+  private static final String FRAGMENT_XML = "fragment.xml"; //$NON-NLS-1$
+  private static final String MANIFEST_MF = "MANIFEST.MF"; //$NON-NLS-1$
+  private static final String DOT_CLASSPATH = ".classpath"; //$NON-NLS-1$
+  private static final String CLASS = ".class"; //$NON-NLS-1$
+  private static final String PLUGIN = "plugin"; //$NON-NLS-1$
+  private static final String ID = "id"; //$NON-NLS-1$
+  private static final String RUNTIME = "runtime"; //$NON-NLS-1$
+  private static final String LIBRARY = "library"; //$NON-NLS-1$
+  private static final String NAME = "name"; //$NON-NLS-1$
+  private static final String FRAGMENT = "fragment"; //$NON-NLS-1$
+  private static final String META_INF_MANIFEST = "META-INF/" + MANIFEST_MF; //$NON-NLS-1$
+  private static final String CLASSPATH = "classpath"; //$NON-NLS-1$
+  private static final String CLASSPATHENTRY = "classpathentry"; //$NON-NLS-1$
+  private static final String KIND = "kind"; //$NON-NLS-1$
+  private static final String OUTPUT = "output"; //$NON-NLS-1$
+  private static final String PATH = "path"; //$NON-NLS-1$
+  private static final String JAR = "jar"; //$NON-NLS-1$
+
+  /**
+   * @return String output location
+   */
+  public String getOutputDir() {
+    return outputDir;
+  }
+
+  /**
+   * Set the output location.
+   * @param String outputDir
+   */
+  public void setOutputDir(String outputDir) {
+    this.outputDir = addTrailingSeperator(outputDir);
+  }
+  
+  /**
+   * Helper method to add a trailing seperator to the given string.
+   * @param s
+   * @return String
+   */
+  protected String addTrailingSeperator(String s) {
+	// If the string does not already end with a seperator, add one
+    if (s != null && !s.endsWith("/") && !s.endsWith("\\")) { //$NON-NLS-1$ //$NON-NLS-2$
+      StringBuffer sb = new StringBuffer(s);
+      sb.append('/');
+      return sb.toString();
+    }
+    return s;
+  }
+
+  /**
+   * @return src Collection
+   */
+  public Collection getSrc() {
+    return src;
+  }
+
+  /**
+   * Set the collection to a new collection with only the src argument passed.
+   * @param aSrc String
+   */
+  public void setSrc(String aSrc) {
+    src = new ArrayList(1);
+    src.add(aSrc);
+  }
+
+  /**
+   * Set the source collection field.
+   * @param aSrc Collection
+   */
+  public void setSrc(Collection aSrc) {
+    src = aSrc;
+  }
+
+  /**
+   * The execute method drives the operation of this class by forwarding each source
+   * location to the Java2API class.  Then, visit all appropriate plugins to cache
+   * the API information provided.
+   */
+  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();
+    }
+    // Get all the visited plugins which have API
+    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);
+    }
+  }
+
+  /**
+   * The visit implemention drives the visitor design for the given plugin and class location.
+   * @return boolean
+   */
+  public boolean visit(String pluginId, ILocation classLoc) {
+    try {
+      IClassFileReader reader = read(classLoc);
+      // Get the fully qualified class name.
+      String className = new String(reader.getClassName()).replace('/', '.');
+      int i = className.lastIndexOf('.');
+      // Get the package name.
+      String pkgName = i != -1 ? className.substring(0, i) : ""; //$NON-NLS-1$
+      // Find the component xml for the given plugin id
+      ComponentXML compXML = getComponentXML(pluginId);
+      // If the package does not exist, we need to add it to the component.xml API list.
+      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;
+  }
+
+  /**
+   * The read method will return an IClassFileReader for the given class location.
+   * 
+   * @param classLoc
+   * @return IClassFileReader
+   * @throws IOException
+   * @throws ClassFormatException
+   */
+  private IClassFileReader read(ILocation classLoc) throws IOException, ClassFormatException {
+    InputStream is = null;
+    ByteArrayOutputStream baos = null;
+    try {
+      byte[] b = new byte[8192];
+      baos = new ByteArrayOutputStream(8192);
+      // Get input stream on class location and write the output stream
+      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 the ClassFileReader
+      return new ClassFileReader(baos.toByteArray(), IClassFileReader.CONSTANT_POOL | IClassFileReader.METHOD_INFOS | IClassFileReader.METHOD_BODIES | IClassFileReader.FIELD_INFOS | IClassFileReader.SUPER_INTERFACES);
+    } finally {
+      // Ensure the input stream is closed
+      if (is != null) {
+        try {
+          is.close();
+        } catch (IOException e) {}
+      }
+      // Ensure the output stream is closed
+      if (baos != null) {
+        try {
+          baos.close();
+        } catch (IOException e) {}
+      }
+    }
+  }
+
+  /**
+   * Get the component xml for the given plugin id, check the cache first.
+   * @param id
+   * @return ComponentXML
+   * @throws IOException
+   */
+  private ComponentXML getComponentXML(String id) throws IOException {
+    if (cachedCompXML != null) {
+      if (cachedCompXML.getName().equals(id))
+        return cachedCompXML;
+      cachedCompXML.save();
+    }
+    // Get a new component.xml file based on output location
+    StringBuffer sb = new StringBuffer(outputDir);
+    sb.append(id);
+    sb.append(COMPONENT_XML);
+    File file = new File(sb.toString());
+    // Update the cache with a new component xml file
+    cachedCompXML = new ComponentXML();
+    cachedCompXML.setName(id);
+    cachedCompXML.setLocation(new FileLocation(file));
+    // Update the plugin id
+    Plugin plugin = new Plugin();
+    plugin.setId(id);
+    cachedCompXML.addPlugin(plugin);
+    // Update the component dependencies
+    ComponentDepends compDepends = new ComponentDepends();
+    compDepends.setUnrestricted(Boolean.TRUE);
+    cachedCompXML.setComponentDepends(compDepends);
+    // Load the component xml file if it exists
+    if (file.exists())
+      cachedCompXML.load();
+    return cachedCompXML;
+  }
+
+  /**
+   * This will forward to the appropriate accept method depending on the current location.
+   * @return boolean
+   */
+  public boolean accept(ILocation location) {
+    String locationName = location.getName();
+    if (visitPlugins) {
+      if (locationName.endsWith(MANIFEST_MF)) {
+        acceptManifest(location);
+      } else if (Location.isArchive(locationName)) {
+        return acceptSingleJar(location);
+      } else if (locationName.endsWith(DOT_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 aLocation) {
+              if (aLocation.getName().endsWith(CLASS))
+                visit(id, aLocation);
+              return true;
+            }
+          }
+        );
+      }
+    }
+    if (location instanceof IZipLocation)
+      return true;
+    else if ((location instanceof IFileLocation) && ((IFileLocation)location).getFile().isDirectory())
+      return true;
+    else
+      return false;
+  }
+
+  /**
+   * Handle a manifest location of MANIFEST.MF
+   * @param location
+   */
+  private void acceptManifest(ILocation location) {
+    String locationName = location.getName();
+    try {
+      Manifest manifest = new Manifest(location.getInputStream());
+      Attributes attrs = manifest.getMainAttributes();
+      String bundleNameAttr = attrs.getValue(new Attributes.Name(Bundle.CONST_BUNDLE_NAME));
+      if (bundleNameAttr != null) {
+        String bundleName = (new StringTokenizer(bundleNameAttr, ";")).nextToken().trim(); //$NON-NLS-1$
+        if (!visitedPlugins.contains(bundleName)) {
+          String bundleCPAttr = attrs.getValue(Bundle.CONST_BUNDLE_CLASSPATH);
+          if (bundleCPAttr != null) {
+            StringTokenizer cp = new StringTokenizer(bundleCPAttr, ","); //$NON-NLS-1$
+            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.length() - 1));
+                sb.append("/"); //$NON-NLS-1$
+                sb.append(path);
+                lib2pluginId.put(sb.toString().replace('\\', '/'), bundleName);
+              }
+            }
+          }
+        }
+      }
+    } catch (IOException e) {}
+  }
+
+  	/**
+  	 * Handle a jar location.
+  	 * @param location
+  	 * @return boolean
+  	 */
+  	private boolean acceptSingleJar(ILocation location) {
+		ILocationChildrenIterator it = location.childIterator();
+		for (ILocation child = it.next(); child != null; child = it.next()) {
+			String name = child.getName();
+			// If it is a manifest, see if its bundle name is in map
+			if (name.equalsIgnoreCase(META_INF_MANIFEST)) {
+				try {
+					Manifest manifest = new Manifest(child.getInputStream());
+					Attributes attrs = manifest.getMainAttributes();
+					String bundleName = attrs.getValue(new Attributes.Name(Bundle.CONST_BUNDLE_NAME));
+					if (bundleName != null) {
+						bundleName = (new StringTokenizer(bundleName, ";")).nextToken().trim(); //$NON-NLS-1$
+						if (!visitedPlugins.contains(bundleName)) {
+							lib2pluginId.put(location.getName().replace('\\', '/'), bundleName);
+							return false;
+						}
+					}
+				} catch (IOException e) {
+				}
+			}
+		}
+		// If the location is a jar file, get its associated manifest, and check to add bundle id to map
+		if (Location.getExtension(location.getName()).equalsIgnoreCase(JAR)) {
+			try {
+				JarInputStream jis = new JarInputStream(location.getInputStream());
+				Manifest manifest = jis.getManifest();
+				if (manifest != null) {
+					Attributes attrs = manifest.getMainAttributes();
+					String bundleNameAttr = attrs.getValue(new Attributes.Name(Bundle.CONST_BUNDLE_NAME));
+					if (bundleNameAttr != null && !visitedPlugins.contains(bundleNameAttr)) {
+						String bundleName = (new StringTokenizer(bundleNameAttr, ";")).nextToken().trim(); //$NON-NLS-1$
+						if (bundleName != null) {
+							bundleName = (new StringTokenizer(bundleName, ";")).nextToken().trim(); //$NON-NLS-1$
+							lib2pluginId.put(location.getName().replace('\\', '/'), bundleName);
+							return false;
+						}
+					}
+				}
+			} catch (IOException ioe) {
+			}
+		}
+		return true;
+	}
+
+  /**
+	 * Handle a classpath location of .classpath
+	 * 
+	 * @param location
+	 */
+  private void acceptDotClasspath(ILocation location) {
+    try {
+      // Build up the DOM object tree from the file
+      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+      DocumentBuilder builder = factory.newDocumentBuilder();
+      Document doc = builder.parse(location.getInputStream());
+      Element root = doc.getDocumentElement();
+      // For each classpath entry check to see if we have an output kind, and check its path
+      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 visited plugins does not contain id, add the library location key and id value to
+            // the library to plugin id map
+            if (!visitedPlugins.contains(id)) {
+              lib.append(s);
+              lib.append('/');
+              lib.append(path);
+              lib2pluginId.put(lib.toString(), id);
+            }
+          }
+        }
+      }
+    } catch (Throwable e) {}
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/PluginRef.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/PluginRef.java
new file mode 100644
index 0000000..c309526
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/PluginRef.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * The class PluginRef manages a plugin reference including all of the related class references
+ * and those field and method references related to those classes.
+ */
+public class PluginRef {
+  // Instance variables
+  private String id;
+  private Map classRefs;
+
+  /**
+   * Get the class references for this plugin reference.
+   * @return Collection
+   */
+  public Collection getClassRefs() {
+    if (classRefs != null)
+    	return new ArrayList(classRefs.values());
+    return Collections.EMPTY_LIST;  
+  }
+
+  /**
+   * Get the associated class reference with the given name
+   * @param className
+   * @return ClassRef
+   */
+  public ClassRef getClassRef(String className) {
+    if (classRefs != null)
+    	return (ClassRef)classRefs.get(className);
+    return null;  
+  }
+
+  /**
+   * Add the given class reference to the plugin reference.
+   * @param classRef
+   */
+  public void addClassRef(ClassRef classRef) {
+    if (classRefs == null)
+      classRefs = new HashMap();
+    classRefs.put(classRef.getName(), classRef);
+  }
+
+  /**
+   * Remove the associated class reference for the given class name.
+   * @param className
+   */
+  public void removeClassRef(String className) {
+    if (classRefs != null)
+      classRefs.remove(className);
+  }
+
+  /**
+   * @return String plugin id
+   */
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * Set the plugin id
+   * @param String id
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * @return String override toString()
+   */
+  public String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.append("<plugin id=\""); //$NON-NLS-1$
+    sb.append(getId());
+    sb.append("\">"); //$NON-NLS-1$
+    for (Iterator it = getClassRefs().iterator(); it.hasNext();)
+      sb.append(it.next().toString());
+    sb.append("</plugin>"); //$NON-NLS-1$
+    return sb.toString();
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/References.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/References.java
new file mode 100644
index 0000000..d65a1de
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/References.java
@@ -0,0 +1,279 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+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 org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class References
+{
+  private Map pluginRefs;
+  private String name;
+  private String contactInfo;
+  private String refBuildId;
+  private String includes;
+  private String excludes;
+  private String includePlugins;
+  private String excludePlugins;
+
+  public String getContactInfo()
+  {
+    return contactInfo;
+  }
+
+  public void setContactInfo(String contactInfo)
+  {
+    this.contactInfo = contactInfo;
+  }
+
+  public String getRefBuildId()
+  {
+    return refBuildId;
+  }
+
+  public void setRefBuildId(String refBuildId)
+  {
+    this.refBuildId = refBuildId;
+  }
+
+  public List getPluginRefs()
+  {
+    if (pluginRefs != null)
+      return new ArrayList(pluginRefs.values());
+    else
+      return new ArrayList(0);
+  }
+
+  public PluginRef getPluginRef(String id)
+  {
+    if (pluginRefs != null)
+      return (PluginRef)pluginRefs.get(id);
+    else
+      return null;
+  }
+
+  public void addPluginRef(PluginRef pluginRef)
+  {
+    if (pluginRefs == null)
+      pluginRefs = new HashMap();
+    pluginRefs.put(pluginRef.getId(), pluginRef);
+  }
+
+  public void removePluginRef(String id)
+  {
+    if (pluginRefs != null)
+      pluginRefs.remove(id);
+  }
+
+  public String getName()
+  {
+    return name;
+  }
+
+  public void setName(String name)
+  {
+    this.name = name;
+  }
+
+  public String getExcludes()
+  {
+    return excludes;
+  }
+
+  public void setExcludes(String excludes)
+  {
+    this.excludes = excludes;
+  }
+
+  public String getIncludes()
+  {
+    return includes;
+  }
+
+  public void setIncludes(String includes)
+  {
+    this.includes = includes;
+  }
+
+  public String getExcludePlugins()
+  {
+    return excludePlugins;
+  }
+
+  public void setExcludePlugins(String excludePlugins)
+  {
+    this.excludePlugins = excludePlugins;
+  }
+
+  public String getIncludePlugins()
+  {
+    return includePlugins;
+  }
+
+  public void setIncludePlugins(String includePlugins)
+  {
+    this.includePlugins = includePlugins;
+  }
+
+  public void load(InputStream is) throws ParserConfigurationException, SAXException, IOException
+  {
+    SAXParserFactory factory = SAXParserFactory.newInstance();
+    factory.setNamespaceAware(false);
+    factory.setValidating(false);
+    SAXParser parser = factory.newSAXParser();
+    parser.parse(new InputSource(is), new ReferencesHandler());
+  }
+
+  public String toString()
+  {
+    StringBuffer sb = new StringBuffer();
+    sb.append("<references name=\"");
+    sb.append(getName());
+    sb.append("\" contactInfo=\"");
+    sb.append(getContactInfo());
+    sb.append("\" refBuildId=\"");
+    sb.append(getRefBuildId());
+    sb.append("\" includes=\"");
+    sb.append(getIncludes());
+    sb.append("\" excludes=\"");
+    sb.append(getExcludes());
+    sb.append("\" includePlugins=\"");
+    sb.append(getIncludePlugins());
+    sb.append("\" excludePlugins=\"");
+    sb.append(getExcludePlugins());
+    sb.append("\">");
+    for (Iterator it = getPluginRefs().iterator(); it.hasNext();)
+      sb.append(it.next().toString());
+    sb.append("</references>");
+    return sb.toString();
+  }
+
+  public void write(OutputStream os) throws IOException
+  {
+    try
+    {
+      os.write("<references name=\"".getBytes());
+      String s = getName();
+      if (s != null)
+        os.write(s.getBytes());
+      os.write("\" contactInfo=\"".getBytes());
+      s = getContactInfo();
+      if (s != null)
+        os.write(s.getBytes());
+      os.write("\" refBuildId=\"".getBytes());
+      s = getRefBuildId();
+      if (s != null)
+        os.write(s.getBytes());
+      os.write("\" includes=\"".getBytes());
+      s = getIncludes();
+      if (s != null)
+        os.write(s.getBytes());
+      os.write("\" excludes=\"".getBytes());
+      s = getExcludes();
+      if (s != null)
+        os.write(s.getBytes());
+      os.write("\" includePlugins=\"".getBytes());
+      s = getIncludePlugins();
+      if (s != null)
+        os.write(s.getBytes());
+      os.write("\" excludePlugins=\"".getBytes());
+      s = getExcludePlugins();
+      if (s != null)
+        os.write(s.getBytes());
+      os.write("\">".getBytes());
+      for (Iterator it = getPluginRefs().iterator(); it.hasNext();)
+        os.write(it.next().toString().getBytes());
+      os.write("</references>".getBytes());
+    }
+    finally
+    {
+      os.close();
+    }
+  }
+
+  private class ReferencesHandler extends DefaultHandler
+  {
+    private PluginRef pluginRef;
+    private ClassRef classRef;
+
+    public void startElement(String uri, String elementName, String qName, Attributes attributes) throws SAXException
+    {
+      if (elementName.equals("references") || qName.equals("references"))
+      {
+        setName(attributes.getValue("name"));
+        setContactInfo(attributes.getValue("contactInfo"));
+        setRefBuildId(attributes.getValue("refBuildId"));
+        setIncludes(attributes.getValue("includes"));
+        setExcludes(attributes.getValue("excludes"));
+        setIncludePlugins(attributes.getValue("includePlugins"));
+        setExcludePlugins(attributes.getValue("excludePlugins"));
+      }
+      else if (elementName.equals("plugin") || qName.equals("plugin"))
+      {
+        pluginRef = new PluginRef();
+        pluginRef.setId(attributes.getValue("id"));
+        addPluginRef(pluginRef);
+      }
+      else if (elementName.equals("class") || qName.equals("class"))
+      {
+        classRef = new ClassRef();
+        classRef.setName(attributes.getValue("name"));
+        classRef.setRefCount(Integer.parseInt(attributes.getValue("ref")));
+        classRef.setSubclassCount(Integer.parseInt(attributes.getValue("subclass")));
+        classRef.setImplementCount(Integer.parseInt(attributes.getValue("impl")));
+        classRef.setInstantiateCount(Integer.parseInt(attributes.getValue("instantiate")));
+        pluginRef.addClassRef(classRef);
+      }
+      else if (elementName.equals("method") || qName.equals("method"))
+      {
+        MethodRef methodRef = new MethodRef();
+        methodRef.setName(attributes.getValue("name"));
+        methodRef.setDescriptor(attributes.getValue("desc"));
+        methodRef.setRefCount(Integer.parseInt(attributes.getValue("ref")));
+        classRef.addMethodRef(methodRef);
+      }
+      else if (elementName.equals("field") || qName.equals("field"))
+      {
+        FieldRef fieldRef = new FieldRef();
+        fieldRef.setName(attributes.getValue("name"));
+        fieldRef.setDescriptor(attributes.getValue("desc"));
+        fieldRef.setRefCount(Integer.parseInt(attributes.getValue("ref")));
+        classRef.addFieldRef(fieldRef);
+      }
+    }
+
+    public void endElement(String uri, String elementName, String qName, Attributes attributes) throws SAXException
+    {
+      if (elementName.equals("plugin") || qName.equals("plugin"))
+      {
+        pluginRef = null;
+      }
+      else if (elementName.equals("class") || qName.equals("class"))
+      {
+        classRef = null;
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/SimpleClass2Reference.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/SimpleClass2Reference.java
new file mode 100644
index 0000000..a3cb360
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/adopters/SimpleClass2Reference.java
@@ -0,0 +1,739 @@
+/*******************************************************************************
+ * 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.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.eclipse.core.runtime.IPlatformRunnable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IClassFileReader;
+import org.eclipse.jdt.core.util.ICodeAttribute;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IConstantPoolConstant;
+import org.eclipse.jdt.core.util.IConstantPoolEntry;
+import org.eclipse.jdt.core.util.IFieldInfo;
+import org.eclipse.jdt.core.util.ILineNumberAttribute;
+import org.eclipse.jdt.core.util.IMethodInfo;
+import org.eclipse.jdt.internal.core.util.ClassFileReader;
+import org.eclipse.wtp.releng.tools.component.CommandOptionParser;
+import org.eclipse.wtp.releng.tools.component.IClassVisitor;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.api.API2ComponentAPI;
+import org.eclipse.wtp.releng.tools.component.api.ComponentAPI;
+import org.eclipse.wtp.releng.tools.component.api.ComponentAPICache;
+import org.eclipse.wtp.releng.tools.component.api.violation.LibVisitor;
+import org.eclipse.wtp.releng.tools.component.internal.FieldRef;
+import org.eclipse.wtp.releng.tools.component.internal.InternalByteCodeVisitor;
+import org.eclipse.wtp.releng.tools.component.internal.Location;
+import org.eclipse.wtp.releng.tools.component.internal.MethodRef;
+import org.eclipse.wtp.releng.tools.component.xsl.XSLUtil;
+
+public class SimpleClass2Reference implements IPlatformRunnable, IClassVisitor
+{
+  private Collection src;
+  private String base;
+  private String output;
+  private String contactInfo;
+  private ComponentAPICache compAPICache;
+  private String html;
+  private Collection includes;
+  private Collection excludes;
+  private Collection includePlugins;
+  private Collection excludePlugins;
+
+  public void setCompAPIDir(String compAPIDir)
+  {
+    compAPICache = new ComponentAPICache(compAPIDir);
+  }
+
+  public String getContactInfo()
+  {
+    return contactInfo;
+  }
+
+  public void setContactInfo(String contactInfo)
+  {
+    this.contactInfo = contactInfo;
+  }
+
+  public String getBase()
+  {
+    return base;
+  }
+
+  public void setBase(String base)
+  {
+    this.base = base;
+  }
+
+  public String getOutput()
+  {
+    return output;
+  }
+
+  public void setOutput(String output)
+  {
+    this.output = addTrailingSeperator(output);
+  }
+
+  public String getHTML()
+  {
+    return html;
+  }
+
+  public void setHTML(String html)
+  {
+    this.html = html;
+  }
+
+  public Collection getSrc()
+  {
+    return src;
+  }
+
+  public void setSrc(Collection src)
+  {
+    this.src = new ArrayList(src);
+  }
+
+  public Collection getIncludes()
+  {
+    return includes;
+  }
+
+  public void setIncludes(Collection includes)
+  {
+    this.includes = includes;
+  }
+
+  public Collection getExcludes()
+  {
+    return excludes;
+  }
+
+  public void setExcludes(Collection excludes)
+  {
+    this.excludes = excludes;
+  }
+
+  public Collection getExcludePlugins()
+  {
+    return excludePlugins;
+  }
+
+  public void setExcludePlugins(Collection excludePlugins)
+  {
+    this.excludePlugins = excludePlugins;
+  }
+
+  public Collection getIncludePlugins()
+  {
+    return includePlugins;
+  }
+
+  public void setIncludePlugins(Collection includePlugins)
+  {
+    this.includePlugins = includePlugins;
+  }
+
+  private References refs;
+
+  public void execute()
+  {
+    refs = new References();
+    refs.setName(src.toString());
+    refs.setRefBuildId(base);
+    refs.setContactInfo(contactInfo);
+    if (includes != null)
+      refs.setIncludes(includes.toString());
+    if (excludes != null)
+      refs.setExcludes(excludes.toString());
+    if (includePlugins != null)
+      refs.setIncludePlugins(includePlugins.toString());
+    if (excludePlugins != null)
+      refs.setExcludePlugins(excludePlugins.toString());
+    for (Iterator it = src.iterator(); it.hasNext();)
+    {
+      ILocation srcLocation = Location.createLocation(new File((String)it.next()));
+      LibVisitor libVisitor = new LibVisitor();
+      srcLocation.accept(libVisitor);
+      libVisitor.setClassVisitor(this);
+      srcLocation.accept(libVisitor);
+    }
+    try
+    {
+      save();
+    }
+    catch (IOException e)
+    {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public void save() throws IOException
+  {
+    File file = new File(output);
+    file.getParentFile().mkdirs();
+    FileOutputStream fos = new FileOutputStream(file);
+    refs.write(fos);
+    fos.close();
+    if (html != null)
+      genHTML(file);
+  }
+
+  private void genHTML(File f)
+  {
+    try
+    {
+      int i = html.replace('\\', '/').lastIndexOf("/");
+      String htmlDir = i != -1 ? html.substring(0, i + 1) : html;
+      XSLUtil.transform(Platform.getBundle("org.eclipse.wtp.releng.tools.component.core").getResource("org/eclipse/wtp/releng/tools/component/xsl/api-ref-compatibility.xsl").openStream(), f, new FileOutputStream(html), htmlDir);
+    }
+    catch (Throwable e)
+    {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public boolean visit(String pluginId, ILocation classLoc)
+  {
+    if (includePlugins(pluginId))
+    {
+      try
+      {
+        visit(classLoc);
+      }
+      catch (IOException e)
+      {
+        throw new RuntimeException(e);
+      }
+      catch (ClassFormatException e)
+      {
+        System.err.println("Plugin: " + pluginId + " Class: " + classLoc.getAbsolutePath());
+        //throw new RuntimeException(e);
+      }
+    }
+    return true;
+  }
+
+  public References visit(ILocation classLoc) throws IOException, ClassFormatException
+  {
+    IClassFileReader reader = read(classLoc);
+    String className = new String(reader.getClassName()).replace('/', '.');
+    // use: reference
+    for (Iterator it = getReferencedTypes(reader).iterator(); it.hasNext();)
+    {
+      String refClassName = (String)it.next();
+      if (!className.equals(refClassName) && include(refClassName))
+      {
+        getClassRef(refClassName).incRefCount();
+      }
+    }
+    // method info & field info
+    setMethodAndFieldInfoUses(reader);
+    // method ref
+    List methodRefs = new ArrayList();
+    List fieldRefs = new ArrayList();
+    getRefs(reader, false, methodRefs, fieldRefs);
+    for (Iterator it = methodRefs.iterator(); it.hasNext();)
+    {
+      MethodRef methodRef = (MethodRef)it.next();
+      String refClassName = methodRef.getClassName();
+      if (!className.equals(refClassName) && include(refClassName))
+      {
+        String methodName = methodRef.getMethodName();
+        String methodDesc = methodRef.getMethodDescriptor();
+        ClassRef classRef = getClassRef(refClassName);
+        if (methodRef.isConstructor())
+        {
+          // use: instantiate
+          classRef.incInstantiateCount();
+        }
+        else
+        {
+          // use: reference
+          classRef.incRefCount();
+        }
+        getMethodRef(classRef, methodName, methodDesc).incRefCount();
+      }
+    }
+    methodRefs = null;
+    // field ref
+    for (Iterator it = fieldRefs.iterator(); it.hasNext();)
+    {
+      FieldRef fieldRef = (FieldRef)it.next();
+      String refClassName = fieldRef.getClassName();
+      if (!className.equals(refClassName) && include(refClassName))
+      {
+        getFieldRef(getClassRef(refClassName), fieldRef.getFieldName(), fieldRef.getFieldDescriptor()).incRefCount();
+      }
+    }
+    fieldRefs = null;
+    // use: subclass
+    String superClass = new String(reader.getSuperclassName()).replace('/', '.');
+    if (superClass != null && include(superClass))
+    {
+      getClassRef(superClass).incSubclassCount();
+    }
+    // use: implement
+    char[][] interfaceNames = reader.getInterfaceNames();
+    String[] interfaces = new String[interfaceNames.length];
+    for (int i = 0; i < interfaces.length; i++)
+      interfaces[i] = new String(interfaceNames[i]).replace('/', '.');
+    for (int i = 0; i < interfaces.length; i++)
+      if (include(interfaces[i]))
+        getClassRef(interfaces[i]).incImplementCount();
+    return refs;
+  }
+
+  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 Set getReferencedTypes(IClassFileReader reader)
+  {
+    Set types = new HashSet();
+    IConstantPool constantPool = reader.getConstantPool();
+    int poolSize = constantPool.getConstantPoolCount();
+    for (int i = 0; i < poolSize; i++)
+    {
+      // Extract the constant's referenced class (if that is even relevant)
+      if (constantPool.getEntryKind(i) == IConstantPoolConstant.CONSTANT_Class)
+      {
+        IConstantPoolEntry classEntry = constantPool.decodeEntry(i);
+        String signature = new String(classEntry.getClassInfoName());
+        int index = signature.lastIndexOf('[');
+        if (index > -1)
+        {
+          // could be an array of a primitive type
+          if (signature.length() - (index + 1) == 1)
+            continue;
+          signature = Signature.toString(signature);
+          signature = signature.substring(0, signature.length() - 2 * (index + 1));
+          signature = signature.replace('.', '$');
+        }
+        String typeName = signature.replace('/', '.');
+        types.add(typeName);
+      }
+    }
+    return types;
+  }
+
+  private void getRefs(IClassFileReader reader, boolean debug, List methodRefs, List fieldRefs)
+  {
+    String className = new String(reader.getClassName()).replace('/', '.');
+    IConstantPoolEntry[] refs = getConstantPoolEntries(reader, IConstantPoolConstant.CONSTANT_Methodref);
+    for (int i = 0; i < refs.length; i++)
+    {
+      String refClassName = new String(refs[i].getClassName()).replace('/', '.');
+      if (!className.equals(refClassName) && include(refClassName))
+      {
+        MethodRef methodRef = new MethodRef();
+        methodRef.setPoolEntry(refs[i]);
+        methodRefs.add(methodRef);
+      }
+    }
+    refs = getConstantPoolEntries(reader, IConstantPoolConstant.CONSTANT_InterfaceMethodref);
+    for (int i = 0; i < refs.length; i++)
+    {
+      String refClassName = new String(refs[i].getClassName()).replace('/', '.');
+      if (!className.equals(refClassName) && include(refClassName))
+      {
+        MethodRef methodRef = new MethodRef();
+        methodRef.setPoolEntry(refs[i]);
+        methodRefs.add(methodRef);
+      }
+    }
+    refs = getConstantPoolEntries(reader, IConstantPoolConstant.CONSTANT_Fieldref);
+    for (int i = 0; i < refs.length; i++)
+    {
+      String refClassName = new String(refs[i].getClassName()).replace('/', '.');
+      if (!className.equals(refClassName) && include(refClassName))
+      {
+        FieldRef fieldRef = new FieldRef();
+        fieldRef.setPoolEntry(refs[i]);
+        fieldRefs.add(fieldRef);
+      }
+    }
+    if (debug)
+    {
+      IMethodInfo[] methodInfos = reader.getMethodInfos();
+      for (int i = 0; i < methodInfos.length; i++)
+      {
+        ICodeAttribute codeAttr = methodInfos[i].getCodeAttribute();
+        if (codeAttr != null)
+        {
+          ILineNumberAttribute lineNumAttr = codeAttr.getLineNumberAttribute();
+          if (lineNumAttr != null)
+          {
+            InternalByteCodeVisitor byteCodeVisitor = new InternalByteCodeVisitor(methodRefs, fieldRefs, lineNumAttr);
+            try
+            {
+              codeAttr.traverse(byteCodeVisitor);
+            }
+            catch (ClassFormatException e)
+            {
+              e.printStackTrace();
+            }
+          }
+        }
+      }
+    }
+  }
+
+  private void setMethodAndFieldInfoUses(IClassFileReader reader)
+  {
+    String className = new String(reader.getClassName()).replace('/', '.');
+    IMethodInfo[] methodInfos = reader.getMethodInfos();
+    for (int i = 0; i < methodInfos.length; i++)
+    {
+      String desc = new String(methodInfos[i].getDescriptor());
+      String returnTypeDesc = Signature.getReturnType(desc);
+      String returnType = toFullyQualifiedName(returnTypeDesc);
+      if (Signature.getTypeSignatureKind(returnTypeDesc) != Signature.BASE_TYPE_SIGNATURE && !className.equals(returnType) && include(returnType))
+      {
+        getClassRef(returnType).incRefCount();
+      }
+      String[] params = Signature.getParameterTypes(desc);
+      for (int j = 0; j < params.length; j++)
+      {
+        String param = toFullyQualifiedName(params[j]);
+        if (Signature.getTypeSignatureKind(params[j]) != Signature.BASE_TYPE_SIGNATURE && !className.equals(param) && include(param))
+        {
+          getClassRef(param).incRefCount();
+        }
+      }
+      String[] throwTypes = Signature.getThrownExceptionTypes(desc);
+      for (int j = 0; j < throwTypes.length; j++)
+      {
+        String throwType = toFullyQualifiedName(throwTypes[j]);
+        if (Signature.getTypeSignatureKind(throwTypes[j]) != Signature.BASE_TYPE_SIGNATURE && !className.equals(throwType) && include(throwType))
+        {
+          getClassRef(throwType).incRefCount();
+        }
+      }
+    }
+    IFieldInfo[] fieldInfos = reader.getFieldInfos();
+    for (int i = 0; i < fieldInfos.length; i++)
+    {
+      String desc = new String(fieldInfos[i].getDescriptor());
+      String field = toFullyQualifiedName(desc);
+      if (Signature.getTypeSignatureKind(desc) != Signature.BASE_TYPE_SIGNATURE && !className.equals(field) && include(field))
+      {
+        getClassRef(field).incRefCount();
+      }
+    }
+  }
+
+  private String toFullyQualifiedName(String descriptor)
+  {
+    StringBuffer sb = new StringBuffer();
+    descriptor = descriptor.replace('/', '.');
+    sb.append(Signature.getSignatureQualifier(descriptor));
+    sb.append('.');
+    sb.append(Signature.getSignatureSimpleName(descriptor).replace('.', '$'));
+    return sb.toString();
+  }
+
+  private IConstantPoolEntry[] getConstantPoolEntries(IClassFileReader reader, int kind)
+  {
+    List entries = new Vector();
+    IConstantPool pool = reader.getConstantPool();
+    int poolSize = pool.getConstantPoolCount();
+    for (int i = 0; i < poolSize; i++)
+      if (pool.getEntryKind(i) == kind)
+        entries.add(pool.decodeEntry(i));
+    return (IConstantPoolEntry[])entries.toArray(new IConstantPoolEntry[0]);
+  }
+
+  private ClassRef getClassRef(String name)
+  {
+    ComponentAPI compAPI = compAPICache.getComponentAPIByClassName(name);
+    String pluginId = compAPI != null ? compAPI.getName() : "unknown";
+    PluginRef pluginRef = refs.getPluginRef(pluginId);
+    if (pluginRef == null)
+    {
+      pluginRef = new PluginRef();
+      pluginRef.setId(pluginId);
+      refs.addPluginRef(pluginRef);
+    }
+    ClassRef classRef = pluginRef.getClassRef(name);
+    if (classRef == null)
+    {
+      classRef = new ClassRef();
+      classRef.setName(name);
+      pluginRef.addClassRef(classRef);
+    }
+    return classRef;
+  }
+
+  private org.eclipse.wtp.releng.tools.component.adopters.MethodRef getMethodRef(ClassRef classRef, String name, String descriptor)
+  {
+    org.eclipse.wtp.releng.tools.component.adopters.MethodRef methodRef = classRef.getMethodRef(name, descriptor);
+    if (methodRef == null)
+    {
+      methodRef = new org.eclipse.wtp.releng.tools.component.adopters.MethodRef();
+      methodRef.setName(name);
+      methodRef.setDescriptor(descriptor);
+      classRef.addMethodRef(methodRef);
+    }
+    return methodRef;
+  }
+
+  private org.eclipse.wtp.releng.tools.component.adopters.FieldRef getFieldRef(ClassRef classRef, String name, String descriptor)
+  {
+    org.eclipse.wtp.releng.tools.component.adopters.FieldRef fieldRef = classRef.getFieldRef(name, descriptor);
+    if (fieldRef == null)
+    {
+      fieldRef = new org.eclipse.wtp.releng.tools.component.adopters.FieldRef();
+      fieldRef.setName(name);
+      fieldRef.setDescriptor(descriptor);
+      classRef.addFieldRef(fieldRef);
+    }
+    return fieldRef;
+  }
+
+  private boolean include(String name)
+  {
+    name = name.replace('/', '.');
+    name = name.replace('\\', '.');
+    if (excludes != null && !excludes.isEmpty())
+      for (Iterator it = excludes.iterator(); it.hasNext();)
+        if (name.matches((String)it.next()))
+          return false;
+    if (includes != null && !includes.isEmpty())
+    {
+      for (Iterator it = includes.iterator(); it.hasNext();)
+        if (name.matches((String)it.next()))
+          return true;
+      return false;
+    }
+    return true;
+  }
+
+  private boolean includePlugins(String id)
+  {
+    id = id.replace('/', '.');
+    id = id.replace('\\', '.');
+    if (excludePlugins != null && !excludePlugins.isEmpty())
+      for (Iterator it = excludePlugins.iterator(); it.hasNext();)
+        if (id.matches((String)it.next()))
+          return false;
+    if (includePlugins != null && !includePlugins.isEmpty())
+    {
+      for (Iterator it = includePlugins.iterator(); it.hasNext();)
+        if (id.matches((String)it.next()))
+          return true;
+      return false;
+    }
+    return true;
+  }
+
+  protected static String addTrailingSeperator(String s)
+  {
+    if (s != null && !s.endsWith("/") && !s.endsWith("\\"))
+    {
+      StringBuffer sb = new StringBuffer(s);
+      sb.append('/');
+      return sb.toString();
+    }
+    else
+    {
+      return s;
+    }
+  }
+
+  public Object run(Object arguments)
+  {
+    String src = System.getProperty("src");
+    String base = System.getProperty("base");
+    String output = System.getProperty("output");
+    String contactInfo = System.getProperty("contactInfo");
+    String html = System.getProperty("html");
+    String includes = System.getProperty("includes");
+    String excludes = System.getProperty("excludes");
+    String includePlugins = System.getProperty("includePlugins");
+    String excludePlugins = System.getProperty("excludePlugins");
+    List args = new ArrayList();
+    args.add("-src");
+    args.addAll(tokenize(src));
+    args.add("-base");
+    args.add(base);
+    args.add("-output");
+    args.add(output);
+    args.add("-contactInfo");
+    args.add(contactInfo);
+    args.add("-html");
+    args.add(html);
+    if (includes != null)
+    {
+      args.add("-includes");
+      args.addAll(tokenize(includes));
+    }
+    if (excludes != null)
+    {
+      args.add("-excludes");
+      args.addAll(tokenize(excludes));
+    }
+    if (includePlugins != null)
+    {
+      args.add("-includePlugins");
+      args.addAll(tokenize(includePlugins));
+    }
+    if (excludePlugins != null)
+    {
+      args.add("-excludePlugins");
+      args.addAll(tokenize(excludePlugins));
+    }
+    try
+    {
+      main((String[])args.toArray(new String[0]));
+    }
+    catch (Throwable t)
+    {
+      t.printStackTrace();
+    }
+    return IPlatformRunnable.EXIT_OK;
+  }
+
+  private List tokenize(String s)
+  {
+    StringTokenizer st = new StringTokenizer(s, ",");
+    List tokens = new ArrayList(st.countTokens());
+    while(st.hasMoreTokens())
+      tokens.add(st.nextToken());
+    return tokens;
+  }
+
+  public static void main(String[] args)
+  {
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    Collection src = (Collection)options.get("src");
+    Collection base = (Collection)options.get("base");
+    Collection output = (Collection)options.get("output");
+    Collection contactInfo = (Collection)options.get("contactInfo");
+    Collection html = (Collection)options.get("html");
+    Collection includes = (Collection)options.get("includes");
+    Collection excludes = (Collection)options.get("excludes");
+    Collection includePlugins = (Collection)options.get("includePlugins");
+    Collection excludePlugins = (Collection)options.get("excludePlugins");
+    if (src == null || base == null || output == null || contactInfo == null || src.isEmpty() || base.isEmpty() || output.isEmpty() || contactInfo.isEmpty())
+    {
+      printUsage();
+      System.exit(-1);
+    }
+
+    String outputString = (String)output.iterator().next();
+    int i = outputString.replace('\\', '/').lastIndexOf('/');
+    String outputDir = outputString.substring(0, i + 1);
+    String componentxml = outputDir + "_tmp_componentxml";
+    String componentapi = outputDir + "_tmp_componentapi";
+
+    Plugin2API plugin2API = new Plugin2API();
+    plugin2API.setSrc(base);
+    plugin2API.setOutputDir(componentxml);
+    plugin2API.execute();
+
+    API2ComponentAPI api2CompAPI = new API2ComponentAPI();
+    api2CompAPI.setApi(componentxml);
+    api2CompAPI.setSrc(base);
+    api2CompAPI.setOutputDir(componentapi);
+    api2CompAPI.setIncludeInnerClass(true);
+    api2CompAPI.setIncludeInterfaces(true);
+    api2CompAPI.execute();
+
+    SimpleClass2Reference class2Ref = new SimpleClass2Reference();
+    class2Ref.setSrc(src);
+    class2Ref.setBase((String)base.iterator().next());
+    class2Ref.setOutput(outputString);
+    class2Ref.setContactInfo((String)contactInfo.iterator().next());
+    class2Ref.setCompAPIDir(componentapi);
+    if (!html.isEmpty())
+      class2Ref.setHTML((String)html.iterator().next());
+    class2Ref.setIncludes(includes);
+    class2Ref.setExcludes(excludes);
+    class2Ref.setIncludePlugins(includePlugins);
+    class2Ref.setExcludePlugins(excludePlugins);
+    class2Ref.execute();
+  }
+
+  private static void printUsage()
+  {
+    System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.adopters.SimpleClass2Reference -src <src> -output <output> [-options]");
+    System.out.println("");
+    System.out.println("\t-src\t\t<src>\t\tlocation of your Eclipse-based product");
+    System.out.println("\t-base\t\t<base>\t\tlocation of your base build");
+    System.out.println("\t-output\t\t<output>\toutput file");
+    System.out.println("\t-contactInfo\t<contactInfo>\tadopter contact information");
+    System.out.println("");
+    System.out.println("where options include:");
+    System.out.println("");
+    System.out.println("\t-includes\t<includes>\tspace seperated packages to include");
+    System.out.println("\t-excludes\t<excludes>\tspace seperated packages to exclude");
+    System.out.println("\t-includePlugins\t<includePlugins>\tspace seperated plugins to include");
+    System.out.println("\t-excludePlugins\t<excludePlugins>\tspace seperated plugins to exclude");
+    System.out.println("\t-html\t\t\t\t<html>\toutput HTML file");
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/API2ComponentAPI.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/API2ComponentAPI.java
new file mode 100644
index 0000000..973332c
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/API2ComponentAPI.java
@@ -0,0 +1,699 @@
+/*******************************************************************************
+ * 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;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+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 org.eclipse.jdt.core.dom.Modifier;
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IClassFileReader;
+import org.eclipse.jdt.core.util.IExceptionAttribute;
+import org.eclipse.jdt.core.util.IFieldInfo;
+import org.eclipse.jdt.core.util.IMethodInfo;
+import org.eclipse.jdt.internal.core.util.ClassFileReader;
+import org.eclipse.wtp.releng.tools.component.CommandOptionParser;
+import org.eclipse.wtp.releng.tools.component.IClassVisitor;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.ILocationVisitor;
+import org.eclipse.wtp.releng.tools.component.api.violation.LibVisitor;
+import org.eclipse.wtp.releng.tools.component.images.ImagesUtil;
+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.Location;
+import org.eclipse.wtp.releng.tools.component.internal.Package;
+import org.eclipse.wtp.releng.tools.component.internal.Plugin;
+import org.eclipse.wtp.releng.tools.component.internal.Type;
+import org.eclipse.wtp.releng.tools.component.xsl.XSLUtil;
+
+public class API2ComponentAPI implements IClassVisitor
+{
+  private Collection api;
+  private Collection src;
+  private String outputDir;
+  private Collection includes;
+  private Collection excludes;
+  private boolean html;
+  private boolean readInterface = true;
+  private boolean skipAPIGen = false;
+  private Map interface2ImplClasses = new HashMap(0);
+  private Map super2SubClasses = new HashMap(0);
+  private boolean includeInnerClass = false;
+  private boolean includeInterfaces = false;
+
+  public Collection getApi()
+  {
+    return api;
+  }
+
+  public void setApi(String api)
+  {
+    this.api = new ArrayList(1);
+    this.api.add(api);
+  }
+
+  public void setApi(Collection api)
+  {
+    this.api = api;
+  }
+
+  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 String getOutputDir()
+  {
+    return outputDir;
+  }
+
+  public void setOutputDir(String outputDir)
+  {
+    this.outputDir = addTrailingSeperator(outputDir);
+  }
+
+  public Collection getIncludes()
+  {
+    return includes;
+  }
+
+  public void setIncludes(Collection includes)
+  {
+    this.includes = includes;
+  }
+
+  public Collection getExcludes()
+  {
+    return excludes;
+  }
+
+  public void setExcludes(Collection excludes)
+  {
+    this.excludes = excludes;
+  }
+
+  public boolean isHtml()
+  {
+    return html;
+  }
+
+  public void setHtml(boolean html)
+  {
+    this.html = html;
+  }
+
+  public boolean isReadInterface()
+  {
+    return readInterface;
+  }
+
+  public void setReadInterface(boolean readInterface)
+  {
+    this.readInterface = readInterface;
+  }
+
+  public boolean isSkipAPIGen()
+  {
+    return skipAPIGen;
+  }
+
+  public void setSkipAPIGen(boolean skipAPIGen)
+  {
+    this.skipAPIGen = skipAPIGen;
+  }
+
+  public boolean isIncludeInnerClass()
+  {
+    return includeInnerClass;
+  }
+
+  public void setIncludeInnerClass(boolean includeInnerClass)
+  {
+    this.includeInnerClass = includeInnerClass;
+  }
+
+  public boolean isIncludeInterfaces()
+  {
+    return includeInterfaces;
+  }
+
+  public void setIncludeInterfaces(boolean includeInterfaces)
+  {
+    this.includeInterfaces = includeInterfaces;
+  }
+
+  public List getImplClasses(String interfaceName)
+  {
+    List list = new ArrayList();
+    getImplClasses(interfaceName, list);
+    return list;
+  }
+
+  private void getImplClasses(String interfaceName, List list)
+  {
+    List implClasses = (List)interface2ImplClasses.get(interfaceName);
+    if (implClasses != null)
+    {
+      list.addAll(implClasses);
+      for (Iterator it = implClasses.iterator(); it.hasNext();)
+      {
+        String className = (String)it.next();
+        if (interface2ImplClasses.get(className) != null)
+          getImplClasses(className, list);
+        else
+        {
+          getSubClasses(className, list);
+          getSuperClasses(className, list);
+        }
+      }
+    }
+  }
+
+  private void getSuperClasses(String className, List list)
+  {
+    ClassHierarchyInfo info = (ClassHierarchyInfo)super2SubClasses.get(className);
+    if (info != null)
+    {
+      String superClassName = info.getSuperClass();
+      while (superClassName != null)
+      {
+        list.add(superClassName);
+        superClassName = null;
+        info = (ClassHierarchyInfo)super2SubClasses.get(superClassName);
+        if (info != null)
+          superClassName = info.getSuperClass();
+      }
+    }
+  }
+
+  private void getSubClasses(String className, List list)
+  {
+    ClassHierarchyInfo info = (ClassHierarchyInfo)super2SubClasses.get(className);
+    if (info != null)
+    {
+      List subClasses = info.getSubClass();
+      if (subClasses != null)
+      {
+        list.addAll(subClasses);
+        for (Iterator it = subClasses.iterator(); it.hasNext();)
+          getSubClasses((String)it.next(), list);
+      }
+    }
+  }
+
+  private Map pluginId2CompXML = new HashMap();
+
+  public void execute()
+  {
+    // Collection component.xml files
+    for (Iterator i = api.iterator(); i.hasNext();)
+    {
+      ILocation apiLocation = Location.createLocation(new File((String)i.next()));
+      ComponentXMLVisitor compXMLVisitor = new ComponentXMLVisitor();
+      apiLocation.accept(compXMLVisitor);
+      for (Iterator it = compXMLVisitor.getCompXMLs().iterator(); it.hasNext();)
+      {
+        ComponentXML compXML = (ComponentXML)it.next();
+        for (Iterator it2 = compXML.getPlugins().iterator(); it2.hasNext();)
+        {
+          pluginId2CompXML.put(((Plugin)it2.next()).getId(), compXML);
+        }
+      }
+    }
+    // Generate api-info.xml files
+    for (Iterator it = src.iterator(); it.hasNext();)
+    {
+      ILocation srcLocation = Location.createLocation(new File((String)it.next()));
+      LibVisitor libVisitor = new LibVisitor();
+      if (srcLocation != null) {
+    	  srcLocation.accept(libVisitor);
+    	  libVisitor.setClassVisitor(this);
+    	  srcLocation.accept(libVisitor);
+      } else {
+    	  System.out.println("Null source location found, continuing."); 
+      }
+    }
+    try
+    {
+      if (cachedCompAPI != null)
+        cachedCompAPI.save();
+    }
+    catch (IOException e)
+    {
+      throw new RuntimeException(e);
+    }
+    // Generate HTML
+    if (isHtml())
+      genHTML();
+  }
+
+  private void genHTML()
+  {
+    ImagesUtil.copyAll(outputDir);
+    final StringBuffer summary = new StringBuffer();
+    summary.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    summary.append("<root>");
+    ILocation outputLoc = Location.createLocation(new File(outputDir));
+    outputLoc.accept(new ILocationVisitor()
+    {
+      public boolean accept(ILocation location)
+      {
+        if (location.getName().endsWith("api-info.xml"))
+        {
+          summary.append("<api-info file=\"");
+          summary.append(location.getAbsolutePath().substring(outputDir.length()));
+          summary.append("\"/>");
+        }
+        return true;
+      }
+    });
+    summary.append("</root>");
+    try
+    {
+      XSLUtil.transform(ClassLoader.getSystemResourceAsStream("org/eclipse/wtp/releng/tools/component/xsl/api-info-summary.xsl"), new ByteArrayInputStream(summary.toString().getBytes()), new FileOutputStream(new File(outputDir + "/api-info-summary.html")), outputDir);
+    }
+    catch (Throwable e)
+    {
+      e.printStackTrace();
+    }
+  }
+
+  public boolean visit(String pluginId, ILocation classLoc)
+  {
+    try
+    {
+      IClassFileReader reader = read(classLoc);
+      String className = new String(reader.getClassName()).replace('/', '.');
+      if (include(className))
+      {
+        int i = className.lastIndexOf('.');
+        String packageName = (i != -1) ? className.substring(0, i) : "";
+        String localName = (i != -1) ? className.substring(i + 1) : className;
+        ClassAPIInfo classAPIInfo = isAPI(reader, pluginId, packageName, localName);
+        boolean isAPI = classAPIInfo.api;
+        if (readInterface)
+        {
+          String superClassName = new String(reader.getSuperclassName()).replace('/', '.');
+          ClassHierarchyInfo info = new ClassHierarchyInfo();
+          info.setSuperClass(superClassName);
+          super2SubClasses.put(className, info);
+          info = (ClassHierarchyInfo)super2SubClasses.get(superClassName);
+          if (info == null)
+          {
+            info = new ClassHierarchyInfo();
+            super2SubClasses.put(superClassName, info);
+          }
+          info.addSubClass(className);
+          char[][] names = reader.getInterfaceNames();
+          for (int j = 0; j < names.length; j++)
+          {
+            String interfaceName = new String(names[j]).replace('/', '.');
+            List implClasses = (List)interface2ImplClasses.get(interfaceName);
+            if (implClasses == null)
+            {
+              implClasses = new ArrayList(1);
+              interface2ImplClasses.put(interfaceName, implClasses);
+            }
+            implClasses.add(className);
+          }
+        }
+        if (!isSkipAPIGen() && isAPI)
+        {
+          try
+          {
+            ComponentAPI compAPI = getComponentAPI(pluginId);
+            PackageAPI pkgAPI = (PackageAPI)compAPI.getPackageAPI(packageName);
+            if (pkgAPI == null)
+            {
+              pkgAPI = new PackageAPI();
+              pkgAPI.setName(packageName);
+              compAPI.addPackageAPI(pkgAPI);
+            }
+            ClassAPI classAPI = pkgAPI.getClassAPI(localName);
+            if (classAPI == null)
+            {
+              boolean isExclusive = isExclusive(pluginId, packageName);
+              if (reader == null)
+                reader = read(classLoc);
+              classAPI = new ClassAPI();
+              classAPI.setName(localName);
+              classAPI.setAccess(reader.getAccessFlags());
+              classAPI.setSuperClass(new String(reader.getSuperclassName()).replace('/', '.'));
+              if (includeInterfaces)
+              {
+                char[][] names = reader.getInterfaceNames();
+                for (int j = 0; j < names.length; j++)
+                {
+                  classAPI.addInterface(new String(names[j]).replace('/', '.'));
+                }
+              }
+              pkgAPI.addClassAPI(classAPI);
+              IMethodInfo[] methods = reader.getMethodInfos();
+              for (int j = 0; j < methods.length; j++)
+              {
+                int methodAccessFlag = methods[j].getAccessFlags();
+                if (!Modifier.isPrivate(methodAccessFlag))
+                {
+                  if (!isExclusive || Modifier.isPublic(methodAccessFlag) || (classAPIInfo.subclass && Modifier.isProtected(methodAccessFlag)))
+                  {
+                    MethodAPI methodAPI = new MethodAPI();
+                    methodAPI.setName(new String(methods[j].getName()));
+                    methodAPI.setAccess(methodAccessFlag);
+                    methodAPI.setDescriptor(new String(methods[j].getDescriptor()));
+                    IExceptionAttribute exceptionAttr = methods[j].getExceptionAttribute();
+                    if (exceptionAttr != null)
+                    {
+                      char[][] exceptionNames = exceptionAttr.getExceptionNames();
+                      List exceptions = new ArrayList(exceptionNames.length);
+                      for (int k = 0; k < exceptionNames.length; k++)
+                      {
+                        exceptions.add(new String(exceptionNames[k]).replace('/', '.'));
+                      }
+                      methodAPI.addThrows(exceptions);
+                    }
+                    classAPI.addMethodAPI(methodAPI);
+                  }
+                }
+              }
+              IFieldInfo[] fields = reader.getFieldInfos();
+              for (int j = 0; j < fields.length; j++)
+              {
+                int fieldAccessFlag = fields[j].getAccessFlags();
+                if (!Modifier.isPrivate(fieldAccessFlag))
+                {
+                  if (!isExclusive || Modifier.isPublic(fieldAccessFlag) || Modifier.isProtected(fieldAccessFlag))
+                  {
+                    FieldAPI fieldAPI = new FieldAPI();
+                    fieldAPI.setName(new String(fields[j].getName()));
+                    fieldAPI.setAccess(fieldAccessFlag);
+                    fieldAPI.setDescriptor(new String(fields[j].getDescriptor()));
+                    classAPI.addFieldAPI(fieldAPI);
+                  }
+                }
+              }
+            }
+          }
+          catch (IOException e)
+          {
+            throw new RuntimeException(e);
+          }
+          catch (ClassFormatException e)
+          {
+            throw new RuntimeException(e);
+          }
+        }
+      }
+    }
+    catch (IOException ioe)
+    {
+      ioe.printStackTrace();
+    }
+    catch (ClassFormatException cfe)
+    {
+      cfe.printStackTrace();
+    }
+    return true;
+  }
+
+  private ClassAPIInfo isAPI(IClassFileReader reader, String pluginId, String packageName, String localName)
+  {
+    boolean innerClass = localName.indexOf('$') != -1;
+    int classAccessFlag = reader.getAccessFlags();
+    if (Modifier.isPrivate(classAccessFlag))
+    {
+      return new ClassAPIInfo(false, false);
+    }
+    else if (!includeInnerClass && innerClass && !Modifier.isPublic(classAccessFlag) && !Modifier.isProtected(classAccessFlag))
+    {
+      return new ClassAPIInfo(false, false);
+    }
+    else
+    {
+      ComponentXML compXML = (ComponentXML)pluginId2CompXML.get(pluginId);
+      if (compXML != null)
+      {
+        Package pkg = compXML.getPackage(packageName);
+        if (pkg != null)
+        {
+          // package protected, check exclusive
+          if (pkg.isExclusive() && !Modifier.isPublic(classAccessFlag) && !Modifier.isProtected(classAccessFlag))
+          {
+            return new ClassAPIInfo(false, false);
+          }
+          Type type;
+          int innerClassSep = localName.indexOf('$');
+          if (innerClassSep == -1)
+            type = pkg.getType(localName);
+          else
+            type = pkg.getType(localName.substring(0, innerClassSep));
+          if (type != null)
+          {
+            if (!type.isReference() && !type.isSubclass() && !type.isImplement() && !type.isInstantiate())
+            {
+              return new ClassAPIInfo(false, false);
+            }
+            else
+            {
+              return new ClassAPIInfo(true, type.isSubclass());
+            }
+          }
+          else
+          {
+            return new ClassAPIInfo(pkg.isApi(), true);
+          }
+        }
+        else
+        {
+          return new ClassAPIInfo(false, false);
+        }
+      }
+      else
+      {
+        return new ClassAPIInfo(false, false);
+      }
+    }
+  }
+
+  private boolean isExclusive(String pluginId, String packageName)
+  {
+    ComponentXML compXML = (ComponentXML)pluginId2CompXML.get(pluginId);
+    if (compXML != null)
+    {
+      Package pkg = compXML.getPackage(packageName);
+      if (pkg != null)
+      {
+        return pkg.isExclusive();
+      }
+    }
+    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.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 boolean include(String name)
+  {
+    name = name.replace('/', '.');
+    name = name.replace('\\', '.');
+    if (excludes != null && !excludes.isEmpty())
+      for (Iterator it = excludes.iterator(); it.hasNext();)
+        if (name.matches((String)it.next()))
+          return false;
+    if (includes != null && !includes.isEmpty())
+    {
+      for (Iterator it = includes.iterator(); it.hasNext();)
+        if (name.matches((String)it.next()))
+          return true;
+      return false;
+    }
+    return true;
+  }
+  private ComponentAPI cachedCompAPI;
+
+  private ComponentAPI getComponentAPI(String id) throws IOException
+  {
+    if (cachedCompAPI != null)
+    {
+      if (cachedCompAPI.getName().equals(id))
+      {
+        return cachedCompAPI;
+      }
+      else
+      {
+        cachedCompAPI.save();
+      }
+    }
+    StringBuffer sb = new StringBuffer(outputDir);
+    sb.append(id);
+    sb.append("/api-info.xml");
+    File file = new File(sb.toString());
+    cachedCompAPI = new ComponentAPI();
+    cachedCompAPI.setName(id);
+    cachedCompAPI.setLocation(new FileLocation(file));
+    if (file.exists())
+      cachedCompAPI.load();
+    return cachedCompAPI;
+  }
+
+  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;
+    }
+  }
+
+  private class ClassAPIInfo
+  {
+    public boolean api;
+    public boolean subclass;
+
+    public ClassAPIInfo(boolean api, boolean subclass)
+    {
+      this.api = api;
+      this.subclass = subclass;
+    }
+  }
+
+  private class ClassHierarchyInfo
+  {
+    private String superClass;
+    private List subClass;
+
+    public List getSubClass()
+    {
+      return subClass;
+    }
+
+    public void addSubClass(String subClass)
+    {
+      if (this.subClass == null)
+        this.subClass = new ArrayList(1);
+      this.subClass.add(subClass);
+    }
+
+    public String getSuperClass()
+    {
+      return superClass;
+    }
+
+    public void setSuperClass(String superClass)
+    {
+      this.superClass = superClass;
+    }
+  }
+
+  public static void main(String[] args)
+  {
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    Collection api = (Collection)options.get("api");
+    Collection src = (Collection)options.get("src");
+    Collection outputDir = (Collection)options.get("outputDir");
+    Collection includes = (Collection)options.get("includes");
+    Collection excludes = (Collection)options.get("excludes");
+    Collection html = (Collection)options.get("html");
+    if (api == null || src == null || outputDir == null || api.isEmpty() || src.isEmpty() || outputDir.isEmpty())
+    {
+      printUsage();
+      System.exit(-1);
+    }
+    API2ComponentAPI api2CompAPI = new API2ComponentAPI();
+    api2CompAPI.setApi(api);
+    api2CompAPI.setSrc(src);
+    api2CompAPI.setOutputDir((String)outputDir.iterator().next());
+    api2CompAPI.setIncludes(includes);
+    api2CompAPI.setExcludes(excludes);
+    api2CompAPI.setHtml(html != null);
+    api2CompAPI.execute();
+  }
+
+  private static void printUsage()
+  {
+    System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.api.API2ComponentAPI -api <api> -src <src> -outputDir <outputDir> [-options]");
+    System.out.println("");
+    System.out.println("\t-api\t\t<api>\t\tlocation of your component.xml");
+    System.out.println("\t-src\t\t<src>\t\tlocation of a Eclipse-based product");
+    System.out.println("\t-outputDir\t<outputDir>\toutput directory of component.xml files");
+    System.out.println("");
+    System.out.println("where options include:");
+    System.out.println("");
+    System.out.println("\t-includes\t<includes>\tspace seperated packages to include");
+    System.out.println("\t-excludes\t<excludes>\tspace seperated packages to exclude");
+    System.out.println("\t-html\t\t\t\t\tgenerate HTML output");
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ClassAPI.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ClassAPI.java
new file mode 100644
index 0000000..6cb77f4
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ClassAPI.java
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * 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;
+
+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 org.eclipse.wtp.releng.tools.component.internal.Type;
+
+public class ClassAPI extends Type
+{
+  private String superClass;
+  private List interfaces;
+  private int access;
+  private Map methodAPIs;
+  private Map fieldAPIs;
+  private JavadocCoverage javadocCoverage;
+
+  public ClassAPI()
+  {
+    access = -1;
+  }
+
+  public String getSuperClass()
+  {
+    return superClass;
+  }
+
+  public void setSuperClass(String superClass)
+  {
+    this.superClass = superClass;
+  }
+
+  /**
+   * @return Returns the access.
+   */
+  public int getAccess()
+  {
+    return access;
+  }
+
+  /**
+   * @param access The access to set.
+   */
+  public void setAccess(int access)
+  {
+    this.access = access;
+  }
+
+  public void addInterface(String interfaz)
+  {
+    if (interfaces == null)
+      interfaces = new ArrayList();
+    interfaces.add(interfaz);
+  }
+
+  public Collection getInterfaces()
+  {
+    if (interfaces == null)
+      return new ArrayList(0);
+    else
+      return new ArrayList(interfaces);
+  }
+
+  /**
+   * @return Returns the fieldAPIs.
+   */
+  public Collection getFieldAPIs()
+  {
+    if (fieldAPIs == null)
+      fieldAPIs = new HashMap(1);
+    return fieldAPIs.values();
+  }
+
+  public FieldAPI getFieldAPI(String name)
+  {
+    if (fieldAPIs == null)
+      return null;
+    else
+      return (FieldAPI)fieldAPIs.get(name);
+  }
+
+  public void addFieldAPI(FieldAPI fieldAPI)
+  {
+    if (fieldAPIs == null)
+      fieldAPIs = new HashMap(1);
+    fieldAPIs.put(fieldAPI.getName(), fieldAPI);
+  }
+
+  public void removeFieldAPI(FieldAPI fieldAPI)
+  {
+    fieldAPIs.remove(fieldAPI.getName());
+  }
+
+  public int sizeFieldAPIs()
+  {
+    return fieldAPIs != null ? fieldAPIs.size() : 0;
+  }
+
+  /**
+   * @return Returns the methodAPIs.
+   */
+  public Collection getMethodAPIs()
+  {
+    if (methodAPIs == null)
+      methodAPIs = new HashMap(1);
+    return methodAPIs.values();
+  }
+
+  public MethodAPI getMethodAPI(String name, String descriptor)
+  {
+    if (methodAPIs == null)
+      return null;
+    StringBuffer key = new StringBuffer();
+    key.append(name);
+    key.append(" "); //$NON-NLS-1$
+    key.append(descriptor);
+    MethodAPI result = (MethodAPI)methodAPIs.get(key.toString());
+    if (result != null)
+    	return result;
+    if (name.indexOf("<")>-1) //$NON-NLS-1$
+    	return getMethodAPI(name.replaceFirst("<", "&lt;"),descriptor); //$NON-NLS-1$ //$NON-NLS-2$
+    return null;
+  }
+
+  public MethodAPI getMethodAPI(String name, List inputs, String returnType)
+  {
+    for (Iterator it = methodAPIs.values().iterator(); it.hasNext();)
+    {
+      MethodAPI methodAPI = (MethodAPI)it.next();
+      if (name.equals(methodAPI.getName()))
+      {
+        if (match(inputs, methodAPI.getInputs()))
+        {
+          if (methodAPI.getReturn().endsWith(returnType))
+          {
+            return methodAPI;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  private boolean match(List list1, List list2)
+  {
+    if (list1.size() == list2.size())
+    {
+      for (int i = 0; i < list1.size(); i++)
+      {
+        String x = (String)list1.get(0);
+        String y = (String)list2.get(0);
+        if (!y.endsWith(x))
+        {
+          return false;
+        }
+      }
+      return true;
+    }
+    return false;
+  }
+
+  public void addMethodAPI(MethodAPI methodAPI)
+  {
+    if (methodAPIs == null)
+      methodAPIs = new HashMap(1);
+    StringBuffer key = new StringBuffer();
+    key.append(methodAPI.getName());
+    key.append(" ");
+    key.append(methodAPI.getDescriptor());
+    methodAPIs.put(key.toString(), methodAPI);
+  }
+
+  public void removeMethodAPI(MethodAPI methodAPI)
+  {
+    StringBuffer key = new StringBuffer();
+    key.append(methodAPI.getName());
+    key.append(" ");
+    key.append(methodAPI.getDescriptor());
+    methodAPIs.remove(key.toString());
+  }
+
+  public int sizeMethodAPIs()
+  {
+    return methodAPIs != null ? methodAPIs.size() : 0;
+  }
+
+  public JavadocCoverage getJavadocCoverage()
+  {
+    if (javadocCoverage == null)
+      javadocCoverage = new JavadocCoverage();
+    return javadocCoverage;
+  }
+
+  public void setJavadocCoverage(JavadocCoverage javadocCoverage)
+  {
+    this.javadocCoverage = javadocCoverage;
+  }
+
+  public boolean isSetJavadocCoverage()
+  {
+    return javadocCoverage != null;
+  }
+
+  public String toString()
+  {
+    StringBuffer sb = new StringBuffer();
+    sb.append("<class-api");
+    sb.append(toAttribute("name", getName()));
+    sb.append(toAttribute("super", getSuperClass()));
+    if (interfaces != null)
+    {
+      StringBuffer interfacesAttr = new StringBuffer();
+      Iterator it = interfaces.iterator();
+      boolean hasNext = it.hasNext();
+      while (hasNext)
+      {
+        interfacesAttr.append((String)it.next());
+        hasNext = it.hasNext();
+        if (hasNext)
+        {
+          interfacesAttr.append(" ");
+        }
+      }
+      sb.append(toAttribute("interfaces", interfacesAttr.toString()));
+    }
+    int access = getAccess();
+    if (access != -1)
+      sb.append(toAttribute("access", String.valueOf(access)));
+    if (getReference() != null)
+      sb.append(toAttribute("reference", String.valueOf(isReference())));
+    if (getImplement() != null)
+      sb.append(toAttribute("implement", String.valueOf(isImplement())));
+    if (getSubclass() != null)
+      sb.append(toAttribute("subclass", String.valueOf(isSubclass())));
+    if (getInstantiate() != null)
+      sb.append(toAttribute("instantiate", String.valueOf(isInstantiate())));
+    sb.append(">");
+    if (javadocCoverage != null)
+      sb.append(javadocCoverage.toString());
+    if (sizeMethodAPIs() > 0)
+      for (Iterator it = getMethodAPIs().iterator(); it.hasNext();)
+        sb.append(((MethodAPI)it.next()).toString());
+    if (sizeFieldAPIs() > 0)
+      for (Iterator it = getFieldAPIs().iterator(); it.hasNext();)
+        sb.append(((FieldAPI)it.next()).toString());
+    sb.append("</class-api>");
+    return sb.toString();
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ClassUse.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ClassUse.java
new file mode 100644
index 0000000..efd0c5c
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ClassUse.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class ClassUse extends ClassAPI
+{
+  private List lines;
+
+  public ClassUse()
+  {
+    setReference(Boolean.FALSE);
+    setSubclass(Boolean.FALSE);
+    setImplement(Boolean.FALSE);
+    setInstantiate(Boolean.FALSE);
+  }
+
+  /**
+   * @return Returns the lines.
+   */
+  public Collection getLines()
+  {
+    if (lines == null)
+      return new ArrayList(0);
+    else
+      return new ArrayList(lines);
+  }
+
+  public void addLine(int line)
+  {
+    if (lines == null)
+      lines = new ArrayList(1);
+    lines.add(String.valueOf(line));
+  }
+
+  public void addLines(Collection l)
+  {
+    if (lines == null)
+      lines = new ArrayList(l);
+    else
+      lines.addAll(l);
+  }
+
+  public int sizeLines()
+  {
+    return lines != null ? lines.size() : 0;
+  }
+
+  public Collection getMethodUses()
+  {
+    return super.getMethodAPIs();
+  }
+
+  public int sizeMethodUses()
+  {
+    return super.sizeMethodAPIs();
+  }
+
+  public Collection getFieldUses()
+  {
+    return super.getFieldAPIs();
+  }
+
+  public int sizeFieldUses()
+  {
+    return super.sizeFieldAPIs();
+  }
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentAPI.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentAPI.java
new file mode 100644
index 0000000..505e60e
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentAPI.java
@@ -0,0 +1,393 @@
+/*******************************************************************************
+ * 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;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+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.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentObject;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class ComponentAPI extends ComponentObject
+{
+  public static final String CONST_COMPONENT_API = "component-api.xml";
+  private static final String ELEMENT_COMPONENT_API = "component-api";
+  private static final String ELEMENT_PACKAGE_API = "package-api";
+  private static final String ELEMENT_CLASS_API = "class-api";
+  private static final String ELEMENT_METHOD_API = "method-api";
+  private static final String ELEMENT_FIELD_API = "field-api";
+  private static final String ELEMENT_TEST_COVERAGE = "test-coverage";
+  private static final String ELEMENT_TEST = "test";
+  private static final String ELEMENT_JAVADOC_COVERAGE = "javadoc-coverage";
+  private static final String ELEMENT_PARAM = "param";
+  private static final String ELEMENT_THROW = "throw";
+  private static final String ATTR_ACCESS = "access";
+  private static final String ATTR_NAME = "name";
+  private static final String ATTR_SUPER = "super";
+  private static final String ATTR_INTERFACES = "interfaces";
+  private static final String ATTR_TIMESTAMP = "timestamp";
+  private static final String ATTR_DESCRIPTOR = "descriptor";
+  private static final String ATTR_REFERENCE = "reference";
+  private static final String ATTR_IMPLEMENT = "implement";
+  private static final String ATTR_SUBCLASS = "subclass";
+  private static final String ATTR_INSTANTIATE = "instantiate";
+  private static final String ATTR_THROWS = "throws";
+  private static final String ATTR_SINCE = "since";
+  private static final String ATTR_RETURN = "return";
+
+  protected ILocation location;
+  protected String name;
+  protected String timestamp;
+  private Map packageAPIs;
+  private boolean reload;
+
+  public ComponentAPI()
+  {
+    reload = false;
+  }
+
+  /**
+   * @return Returns the location.
+   */
+  public ILocation getLocation()
+  {
+    return location;
+  }
+
+  /**
+   * @param location The location to set.
+   */
+  public void setLocation(ILocation location)
+  {
+    this.location = location;
+    reload = true;
+  }
+
+  /**
+   * @return Returns the name.
+   */
+  public String getName()
+  {
+    return name;
+  }
+
+  /**
+   * @param name The name to set.
+   */
+  public void setName(String name)
+  {
+    this.name = name;
+  }
+
+  public String getTimestamp()
+  {
+    return timestamp;
+  }
+
+  public void setTimestamp(String timestamp)
+  {
+    this.timestamp = timestamp;
+  }
+
+  /**
+   * @return Returns the packageAPIs.
+   */
+  public Collection getPackageAPIs()
+  {
+    if (packageAPIs == null)
+      packageAPIs = new HashMap(1);
+    return packageAPIs.values();
+  }
+
+  public PackageAPI getPackageAPI(String name)
+  {
+    if (packageAPIs == null)
+      return null;
+    else
+      return (PackageAPI)packageAPIs.get(name);
+  }
+
+  public void addPackageAPI(PackageAPI pkgAPI)
+  {
+    if (packageAPIs == null)
+      packageAPIs = new HashMap(1);
+    packageAPIs.put(pkgAPI.getName(), pkgAPI);
+  }
+
+  public void load() throws IOException, FileNotFoundException
+  {
+    if (reload)
+    {
+      try
+      {
+        SAXParserFactory factory = SAXParserFactory.newInstance();
+        factory.setNamespaceAware(false);
+        factory.setValidating(false);
+        SAXParser parser = factory.newSAXParser();
+        parser.parse(new InputSource(new BufferedInputStream(location.getInputStream())), new ComponentAPIHandler(this));
+      }
+      catch (ParserConfigurationException pce)
+      {
+        pce.printStackTrace();
+      }
+      catch (SAXException saxe)
+      {
+        saxe.printStackTrace();
+      }
+      reload = false;
+    }
+  }
+
+  public void saveAsHTML(ILocation html, String xsl) throws TransformerConfigurationException, TransformerException, IOException
+  {
+    TransformerFactory factory = TransformerFactory.newInstance();
+    Transformer transformer = factory.newTransformer(new StreamSource(ClassLoader.getSystemResourceAsStream(xsl)));
+    transformer.transform(new StreamSource(new ByteArrayInputStream(toString().getBytes())), new StreamResult(new FileOutputStream(new File(html.getAbsolutePath()))));
+  }
+
+  public void save() throws IOException
+  {
+    if (location != null)
+    {
+      File file = new File(location.getAbsolutePath());
+      file.getParentFile().mkdirs();
+      FileOutputStream fos = new FileOutputStream(file);
+      fos.write(toString().getBytes());
+      fos.close();
+    }
+  }
+
+  public String toString()
+  {
+    StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    sb.append("<component-api ");
+    sb.append(toAttribute("name", getName()));
+    sb.append(toAttribute("timestamp", getTimestamp()));
+    sb.append(">");
+    for (Iterator it = getPackageAPIs().iterator(); it.hasNext();)
+      sb.append(it.next().toString());
+    sb.append("</component-api>");
+    return sb.toString();
+  }
+
+  protected static class ComponentAPIHandler extends DefaultHandler
+  {
+    private ComponentAPI compAPI;
+    private PackageAPI packageAPI;
+    private ClassAPI classAPI;
+    private MethodAPI methodAPI;
+    private FieldAPI fieldAPI;
+    private TestCoverage testCoverage;
+    private JavadocCoverage javadocCoverage;
+    private boolean classJavadoc;
+    private boolean methodJavadoc;
+    private boolean fieldJavadoc;
+    
+    public ComponentAPIHandler(ComponentAPI compAPI)
+    {
+      this.compAPI = compAPI;
+      classJavadoc = true;
+      methodJavadoc = false;
+      fieldJavadoc = false;
+    }
+
+    public void startElement(String uri, String elementName, String qName, Attributes attributes) throws SAXException
+    {
+      if (elementName.equals(ELEMENT_TEST_COVERAGE) || qName.equals(ELEMENT_TEST_COVERAGE))
+      {
+        if (methodAPI != null)
+        {
+          testCoverage = new TestCoverage();
+          methodAPI.setTestCoverage(testCoverage);
+        }
+      }
+      else if (elementName.equals(ELEMENT_TEST) || qName.equals(ELEMENT_TEST))
+      {
+        if (testCoverage != null)
+        {
+          String name = attributes.getValue(ATTR_NAME);
+          if (name != null)
+            testCoverage.addTest(name);
+        }
+      }
+      else if (elementName.equals(ELEMENT_JAVADOC_COVERAGE) || qName.equals(ELEMENT_JAVADOC_COVERAGE))
+      {
+        javadocCoverage = new JavadocCoverage();
+        String hasSince = attributes.getValue(ATTR_SINCE);
+        if (hasSince != null)
+          javadocCoverage.setHasSince(Boolean.valueOf(hasSince));
+        String hasReturn = attributes.getValue(ATTR_RETURN);
+        if (hasReturn != null)
+          javadocCoverage.setHasReturn(Boolean.valueOf(hasReturn));
+        if (classJavadoc && classAPI != null)
+          classAPI.setJavadocCoverage(javadocCoverage);
+        else if (methodJavadoc && methodAPI != null)
+          methodAPI.setJavadocCoverage(javadocCoverage);
+        else if (fieldJavadoc && fieldAPI != null)
+          fieldAPI.setJavadocCoverage(javadocCoverage);
+      }
+      else if (elementName.equals(ELEMENT_PARAM) || qName.equals(ELEMENT_PARAM))
+      {
+        if (javadocCoverage != null)
+        {
+          String name = attributes.getValue(ATTR_NAME);
+          if (name != null)
+            javadocCoverage.addMissingParam(name);
+        }
+      }
+      else if (elementName.equals(ELEMENT_THROW) || qName.equals(ELEMENT_THROW))
+      {
+        if (javadocCoverage != null)
+        {
+          String name = attributes.getValue(ATTR_NAME);
+          if (name != null)
+            javadocCoverage.addMissingThrow(name);
+        }
+      }
+      else if (elementName.equals(ELEMENT_METHOD_API) || qName.equals(ELEMENT_METHOD_API))
+      {
+        classJavadoc = false;
+        methodJavadoc = true;
+        fieldJavadoc = false;
+        methodAPI = new MethodAPI();
+        startMethod(classAPI, methodAPI, attributes);
+      }
+      else if (elementName.equals(ELEMENT_FIELD_API) || qName.equals(ELEMENT_FIELD_API))
+      {
+        classJavadoc = false;
+        methodJavadoc = false;
+        fieldJavadoc = true;
+        fieldAPI = new FieldAPI();
+        startField(classAPI, fieldAPI, attributes);
+      }
+      else if (elementName.equals(ELEMENT_CLASS_API) || qName.equals(ELEMENT_CLASS_API))
+      {
+        classJavadoc = true;
+        methodJavadoc = false;
+        fieldJavadoc = false;
+        if (packageAPI != null)
+        {
+          classAPI = new ClassAPI();
+          classAPI.setName(attributes.getValue(ATTR_NAME));
+          String attrSuper = attributes.getValue(ATTR_SUPER);
+          if (attrSuper != null)
+            classAPI.setSuperClass(attrSuper);
+          String attrInterfaces = attributes.getValue(ATTR_INTERFACES);
+          if (attrInterfaces != null)
+          {
+            StringTokenizer st = new StringTokenizer(attrInterfaces, " ");
+            while (st.hasMoreTokens())
+            {
+              classAPI.addInterface(st.nextToken());
+            }
+          }
+          String attrAccess = attributes.getValue(ATTR_ACCESS);
+          if (attrAccess != null)
+            classAPI.setAccess(Integer.parseInt(attrAccess));
+          String attrRef = attributes.getValue(ATTR_REFERENCE);
+          if (attrRef != null)
+            classAPI.setReference(Boolean.valueOf(attrRef));
+          String attrImpl = attributes.getValue(ATTR_IMPLEMENT);
+          if (attrImpl != null)
+            classAPI.setImplement(Boolean.valueOf(attrImpl));
+          String attrSubclass = attributes.getValue(ATTR_SUBCLASS);
+          if (attrSubclass != null)
+            classAPI.setSubclass(Boolean.valueOf(attrSubclass));
+          String attrInstantiate = attributes.getValue(ATTR_INSTANTIATE);
+          if (attrInstantiate != null)
+            classAPI.setInstantiate(Boolean.valueOf(attrInstantiate));
+          packageAPI.addClassAPI(classAPI);
+        }
+      }
+      else if (elementName.equals(ELEMENT_PACKAGE_API) || qName.equals(ELEMENT_PACKAGE_API))
+      {
+        packageAPI = new PackageAPI();
+        packageAPI.setName(attributes.getValue(ATTR_NAME));
+        compAPI.addPackageAPI(packageAPI);
+      }
+      else if (equalsLocalpart(elementName, ELEMENT_COMPONENT_API) || equalsLocalpart(qName, ELEMENT_COMPONENT_API))
+      {
+        compAPI.setName(attributes.getValue(ATTR_NAME));
+        compAPI.setTimestamp(attributes.getValue(ATTR_TIMESTAMP));
+      }
+    }
+
+    private boolean equalsLocalpart(String fullname, String localpart)
+    {
+      int index = fullname.indexOf(':');
+      if (index != -1)
+        return fullname.substring(index + 1).equals(localpart);
+      else
+        return fullname.equals(localpart);
+    }
+
+    protected void startMethod(ClassAPI cAPI, MethodAPI methodAPI, Attributes attributes) throws SAXException
+    {
+      if (cAPI != null)
+      {
+        methodAPI.setName(attributes.getValue(ATTR_NAME));
+        methodAPI.setDescriptor(attributes.getValue(ATTR_DESCRIPTOR));
+        String attrAccess = attributes.getValue(ATTR_ACCESS);
+        if (attrAccess != null)
+          methodAPI.setAccess(Integer.parseInt(attrAccess));
+        String attrThrows = attributes.getValue(ATTR_THROWS);
+        if (attrThrows != null)
+          methodAPI.addThrows(toCollection(attrThrows, " "));
+        cAPI.addMethodAPI(methodAPI);
+      }
+    }
+
+    protected Collection toCollection(String value, String delimiter)
+    {
+      StringTokenizer st = new StringTokenizer(value, delimiter);
+      Collection list = new ArrayList(st.countTokens());
+      while (st.hasMoreTokens())
+        list.add(st.nextToken());
+      return list;
+    }
+
+    protected void startField(ClassAPI cAPI, FieldAPI fAPI, Attributes attributes) throws SAXException
+    {
+      if (cAPI != null)
+      {
+        fAPI.setName(attributes.getValue(ATTR_NAME));
+        fAPI.setDescriptor(attributes.getValue(ATTR_DESCRIPTOR));
+        String attrAccess = attributes.getValue(ATTR_ACCESS);
+        if (attrAccess != null)
+          fAPI.setAccess(Integer.parseInt(attrAccess));
+        cAPI.addFieldAPI(fAPI);
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentAPICache.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentAPICache.java
new file mode 100644
index 0000000..3a49d15
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentAPICache.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * 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;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.ILocationVisitor;
+import org.eclipse.wtp.releng.tools.component.internal.FileLocation;
+import org.eclipse.wtp.releng.tools.component.internal.Location;
+
+public class ComponentAPICache
+{
+  private int size;
+  private String compAPIDir;
+  private List cachedIds = new ArrayList(size);
+  private List cachedCompAPIs = new ArrayList(size);
+
+  public ComponentAPICache(String compAPIDir)
+  {
+    this(20, compAPIDir);
+  }
+
+  public ComponentAPICache(int size, String compAPIDir)
+  {
+    this.size = size;
+    this.compAPIDir = addTrailingSeperator(compAPIDir);
+  }
+  
+  private String addTrailingSeperator(String s) {
+    if (s != null && !s.endsWith("/") && !s.endsWith("\\")) { //$NON-NLS-1$ //$NON-NLS-2$
+      StringBuffer sb = new StringBuffer(s);
+      sb.append('/');
+      return sb.toString();
+    }
+    return s;
+  }
+
+  public ComponentAPI getComponentAPI(String id) throws IOException
+  {
+    int index = cachedIds.indexOf(id);
+    if (index != -1)
+    {
+      ComponentAPI compAPI = (ComponentAPI)cachedCompAPIs.get(index);
+      if (index != 0)
+      {
+        cachedIds.remove(index);
+        cachedCompAPIs.remove(index);
+        cachedIds.add(0, id);
+        cachedCompAPIs.add(0, compAPI);
+      }
+      return compAPI;
+    }
+    StringBuffer sb = new StringBuffer(compAPIDir);
+    sb.append(id);
+    sb.append("/api-info.xml");
+    File file = new File(sb.toString());
+    ComponentAPI compAPI = new ComponentAPI();
+    compAPI.setName(id);
+    compAPI.setLocation(new FileLocation(file));
+    if (file.exists())
+    {
+      compAPI.load();
+    }
+    if (cachedCompAPIs.size() == size)
+    {
+      cachedIds.remove(size - 1);
+      ((ComponentAPI)cachedCompAPIs.remove(size - 1)).save();
+    }
+    cachedIds.add(0, id);
+    cachedCompAPIs.add(0, compAPI);
+    return compAPI;
+  }
+
+  private Map pkg2Id;
+
+  public ComponentAPI getComponentAPIByClassName(String className)
+  {
+    if (pkg2Id == null)
+    {
+      pkg2Id = new HashMap();
+      ILocation dir = Location.createLocation(new File(compAPIDir));
+      LocationVisitor visitor = new LocationVisitor();
+      dir.accept(visitor);
+    }
+    int index = className.lastIndexOf('.');
+    String pkgName = (index != -1) ? className.substring(0, index) : "";
+    String localName = (index != -1) ? className.substring(index + 1) : className;
+    int innerClassIndex = localName.indexOf("$");
+    if (innerClassIndex != -1)
+    {
+      localName = localName.substring(0, innerClassIndex);
+    }
+    if (localName.endsWith("[]"))
+    {
+      localName = localName.substring(0, localName.length() - 2);
+    }
+    List ids = (List)pkg2Id.get(pkgName);
+    if (ids != null)
+    {
+      for (Iterator it = ids.iterator(); it.hasNext();)
+      {
+        try
+        {
+          ComponentAPI compAPI = getComponentAPI((String)it.next());
+          PackageAPI pkgAPI = compAPI.getPackageAPI(pkgName);
+          if (pkgAPI.getClassAPI(localName) != null)
+          {
+            return compAPI;
+          }
+        }
+        catch (IOException ioe)
+        {
+          ioe.printStackTrace();
+        }
+      }
+    }
+    return null;
+  }
+
+  private class LocationVisitor implements ILocationVisitor
+  {
+    public boolean accept(ILocation location)
+    {
+      String absPath = location.getAbsolutePath().replace('\\', '/');
+      if (absPath.endsWith("api-info.xml"))
+      {
+        String id = absPath.substring(0, absPath.length() - "/api-info.xml".length());
+        int i = id.lastIndexOf('/');
+        if (i != -1)
+        {
+          id = id.substring(i + 1);
+          try
+          {
+            ComponentAPI compAPI = new ComponentAPI();
+            compAPI.setLocation(location);
+            compAPI.load();
+            for (Iterator it = compAPI.getPackageAPIs().iterator(); it.hasNext();)
+            {
+              String pkgName = ((PackageAPI)it.next()).getName();
+              List ids = (List)pkg2Id.get(pkgName);
+              if (ids == null)
+              {
+                ids = new ArrayList();
+                pkg2Id.put(pkgName, ids);
+              }
+              ids.add(id);
+            }
+          }
+          catch (IOException ioe)
+          {
+            ioe.printStackTrace();
+          }
+        }
+      }
+      return true;
+    }
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentAPIEmitter.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentAPIEmitter.java
new file mode 100644
index 0000000..3976908
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentAPIEmitter.java
@@ -0,0 +1,447 @@
+/*******************************************************************************
+ * 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;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+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.internal.AbstractEmitter;
+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.eclipse.wtp.releng.tools.component.internal.Type;
+import org.eclipse.jdt.core.util.IExceptionAttribute;
+import org.eclipse.jdt.core.util.IFieldInfo;
+import org.eclipse.jdt.core.util.IMethodInfo;
+import org.eclipse.jdt.core.util.IModifierConstants;
+
+public class ComponentAPIEmitter extends AbstractEmitter implements IClazzVisitor
+{
+  public static final String OPTION_ECLIPSE_DIR = "eclipseDir";
+  public static final String OPTION_COMPONENT_XML_DIR = "compXMLDir";
+  public static final String OPTION_COMPONENT_API_DIR = "compAPIDir";
+  private static final String NAME_CONSTRUCTOR = "<init>";
+  private static final String NAME_STATIC_BLOCK = "<clinit>";
+  private String compAPIDir;
+  private boolean genInternalAPIs;
+  private boolean noFieldAPIs;
+  private Map compLoc2CompXML;
+  private Map pluginId2Plugin;
+  private Map fragmentId2Fragment;
+  private ComponentXML compXML;
+  private ComponentAPI compAPI;
+  private String timestamp;
+
+  public ComponentAPIEmitter(String compAPIDir)
+  {
+    this.compAPIDir = addTrailingSeperator(compAPIDir);
+    genInternalAPIs = false;
+    noFieldAPIs = false;
+    Calendar c = Calendar.getInstance();
+    StringBuffer sb = new StringBuffer(String.valueOf(c.get(Calendar.YEAR)));
+    int month = c.get(Calendar.MONTH);
+    if (month < 10)
+      sb.append("0");
+    sb.append(String.valueOf(month));
+    int date = c.get(Calendar.DATE);
+    if (date < 10)
+      sb.append("0");
+    sb.append(String.valueOf(date));
+    timestamp = sb.toString();
+  }
+
+  public void init(List eclipseDirs, List compXMLDirs)
+  {
+    compLoc2CompXML = new HashMap();
+    pluginId2Plugin = new HashMap();
+    fragmentId2Fragment = new HashMap();
+    for (Iterator it = eclipseDirs.iterator(); it.hasNext();)
+    {
+      File eclipseFile = new File(addTrailingSeperator((String)it.next()));
+      if (eclipseFile.exists())
+        harvestPlugins(eclipseFile, pluginId2Plugin, fragmentId2Fragment);
+    }
+    linkPluginsAndFragments(pluginId2Plugin, fragmentId2Fragment);
+    for (Iterator it = compXMLDirs.iterator(); it.hasNext();)
+    {
+      File compXMLFile = new File(addTrailingSeperator((String)it.next()));
+      if (compXMLFile.exists())
+        harvestComponents(compXMLFile, compLoc2CompXML);
+    }
+  }
+
+  public void init(Map compLoc2CompXML, Map pluginId2Plugin, Map fragmentId2Fragment)
+  {
+    this.compLoc2CompXML = compLoc2CompXML;
+    this.pluginId2Plugin = pluginId2Plugin;
+    this.fragmentId2Fragment = fragmentId2Fragment;
+  }
+
+  public String getTimestamp()
+  {
+    return timestamp;
+  }
+
+  public void setTimestamp(String timestamp)
+  {
+    this.timestamp = timestamp;
+  }
+
+  public boolean getNoFieldAPIs()
+  {
+    return noFieldAPIs;
+  }
+
+  public void setNoFieldAPIs(boolean noFieldAPIs)
+  {
+    this.noFieldAPIs = noFieldAPIs;
+  }
+
+  public void genComponentApiXml() throws IOException
+  {
+    for (Iterator it = compLoc2CompXML.keySet().iterator(); it.hasNext();)
+      genComponentApiXml((String)it.next());
+  }
+
+  public ComponentAPI genComponentApiXml(String compLoc) throws IOException
+  {
+    compXML = (ComponentXML)compLoc2CompXML.get(compLoc);
+    if (compXML != null)
+    {
+      compXML.load();
+      String compName = compXML.getName();
+      compAPI = newComponentAPI(compXML);
+      for (Iterator pluginsIt = compXML.getPlugins().iterator(); pluginsIt.hasNext();)
+      {
+        IPluginXML plugin = (IPluginXML)pluginId2Plugin.get(((Plugin)pluginsIt.next()).getId());
+        if (plugin != null)
+          plugin.accept(this);
+      }
+      compXML = null;
+      if (compAPIDir != null)
+        System.out.println("Writing component-api.xml for " + compName);
+      compAPI.save();
+      return compAPI;
+    }
+    return null;
+  }
+
+  public boolean visit(IClazz clazz)
+  {
+    if (compXML == null || compAPI == null)
+      return false;
+    ClassAPI classAPI = addClassAPI(compXML, clazz, compAPI);
+    if (classAPI != null)
+    {
+      boolean isPkgProtected = true;
+      List publicMethods = new ArrayList();
+      List protectedMethods = new ArrayList();
+      IMethodInfo[] methodInfos = clazz.getMethodInfo();
+      for (int i = 0; i < methodInfos.length; i++)
+      {
+        int access = methodInfos[i].getAccessFlags();
+        String methodName = new String(methodInfos[i].getName());
+        if (isPkgProtected && methodName.equals(NAME_CONSTRUCTOR))
+          isPkgProtected = !(isBit(access, IModifierConstants.ACC_PUBLIC) || isBit(access, IModifierConstants.ACC_PROTECTED));
+        if (clazz.isInterface() || ((isBit(access, IModifierConstants.ACC_PUBLIC) || isBit(access, IModifierConstants.ACC_PROTECTED)) && !methodName.equals(NAME_STATIC_BLOCK)))
+        {
+          String[] exs = new String[0];
+          IExceptionAttribute exAttr = methodInfos[i].getExceptionAttribute();
+          if (exAttr != null)
+          {
+            char[][] exChars = exAttr.getExceptionNames();
+            exs = new String[exChars.length];
+            for (int j = 0; j < exs.length; j++)
+              exs[j] = decodeClassName(new String(exChars[j]));
+          }
+          if (isBit(access, IModifierConstants.ACC_PUBLIC))
+            publicMethods.add(newMethodAPI(methodName, access, new String(methodInfos[i].getDescriptor()), exs));
+          else
+            protectedMethods.add(newMethodAPI(methodName, access, new String(methodInfos[i].getDescriptor()), exs));
+        }
+      }
+      classAPI.getMethodAPIs().addAll(publicMethods);
+      if (!isPkgProtected)
+        classAPI.getMethodAPIs().addAll(protectedMethods);
+      if (!noFieldAPIs)
+      {
+        IFieldInfo[] fieldInfos = clazz.getFieldInfo();
+        for (int i = 0; i < fieldInfos.length; i++)
+        {
+          int access = fieldInfos[i].getAccessFlags();
+          if (!isBit(access, IModifierConstants.ACC_PRIVATE))
+          {
+            if (!isPkgProtected || isBit(access, IModifierConstants.ACC_PUBLIC))
+            {
+              addFieldAPI(classAPI, newFieldAPI(new String(fieldInfos[i].getName()), access, new String(fieldInfos[i].getDescriptor())));
+            }
+          }
+        }
+      }
+    }
+    return true;
+  }
+
+  private ClassAPI addClassAPI(ComponentXML compXML, IClazz clazz, ComponentAPI compAPI)
+  {
+    String typeName = clazz.getName();
+    String superClass = clazz.getSuperClass();
+    int index = typeName.lastIndexOf('.');
+    String pkgName;
+    String localName;
+    if (index != -1)
+    {
+      pkgName = typeName.substring(0, index);
+      localName = typeName.substring(index + 1);
+    }
+    else
+    {
+      pkgName = "";
+      localName = typeName;
+    }
+    if (genInternalAPIs)
+    {
+      ClassAPI internalClassAPI = new ClassAPI();
+      internalClassAPI.setName(typeName);
+      internalClassAPI.setSuperClass(superClass);
+      addClassAPI(compAPI, true, pkgName, internalClassAPI);
+    }
+    int access = clazz.getAccessFlags();
+    if (isBit(access, IModifierConstants.ACC_PUBLIC) || isBit(access, IModifierConstants.ACC_PROTECTED))
+    {
+      boolean isInterface = clazz.isInterface();
+      Package pkg = findPackage(compXML, pkgName);
+      if (pkg != null)
+      {
+        Type type = findType(pkg, localName);
+        if (type != null)
+        {
+          boolean ref = type.isReference();
+          boolean subclass = type.isSubclass() && !isInterface;
+          boolean implement = type.isImplement() && isInterface;
+          boolean instantiate = type.isInstantiate() && !isInterface;
+          if (ref || subclass || implement || instantiate)
+          {
+            // at least one public usage
+            ClassAPI externalClassAPI = newClassAPI(typeName, superClass, access, new Boolean(ref), new Boolean(subclass), new Boolean(implement), new Boolean(instantiate));
+            addClassAPI(compAPI, false, pkgName, externalClassAPI);
+            return externalClassAPI;
+          }
+          else
+          {
+            // all usage are set to false, in another word, it is an internal API
+            return null;
+          }
+        }
+        else if (pkg.isApi())
+        {
+          // api == true means, by default, a non-listed type is an external API
+          ClassAPI externalClassAPI = newClassAPI(typeName, superClass, access, Boolean.TRUE, new Boolean(!isInterface), new Boolean(isInterface), new Boolean(!isInterface));
+          addClassAPI(compAPI, false, pkgName, externalClassAPI);
+          return externalClassAPI;
+        }
+        else
+        {
+          // api == false means, by default, a non-listed type is an internal API
+          return null;
+        }
+      }
+      else
+      {
+        // package not defined in component.xml means it is an internal API
+        return null;
+      }
+    }
+    return null;
+  }
+
+  private void addClassAPI(ComponentAPI compAPI, boolean isInternal, String pkgName, ClassAPI classAPI)
+  {
+    Collection pkgAPIs = compAPI.getPackageAPIs();
+    PackageAPI pkgAPI = null;
+    for (Iterator it = pkgAPIs.iterator(); it.hasNext();)
+    {
+      PackageAPI nextPkg = (PackageAPI)it.next();
+      if (nextPkg.getName().equals(pkgName))
+      {
+        pkgAPI = nextPkg;
+        break;
+      }
+    }
+    if (pkgAPI == null)
+    {
+      pkgAPI = newPackageAPI(pkgName);
+      pkgAPIs.add(pkgAPI);
+    }
+    pkgAPI.addClassAPI(classAPI);
+  }
+
+  private void addFieldAPI(ClassAPI classAPI, FieldAPI fieldAPI)
+  {
+    classAPI.getFieldAPIs().add(fieldAPI);
+  }
+
+  private PackageAPI newPackageAPI(String pkgName)
+  {
+    PackageAPI pkg = new PackageAPI();
+    pkg.setName(pkgName);
+    return pkg;
+  }
+
+  private ComponentAPI newComponentAPI(ComponentXML compXML)
+  {
+    String compName = compXML.getName();
+    ILocation location = null;
+    if (compAPIDir != null)
+    {
+      StringBuffer sb = new StringBuffer(compAPIDir);
+      sb.append(compName);
+      sb.append('/');
+      sb.append("component-api.xml");
+      location = new FileLocation(new File(sb.toString()));
+    }
+    return newComponentAPI(compName, location);
+  }
+
+  private ComponentAPI newComponentAPI(String compName, ILocation location)
+  {
+    ComponentAPI compAPI = new ComponentAPI();
+    compAPI.setName(compName);
+    compAPI.setTimestamp(timestamp);
+    compAPI.setLocation(location);
+    return compAPI;
+  }
+
+  private ClassAPI newClassAPI(String className, String superClass, int access, Boolean ref, Boolean subclass, Boolean implement, Boolean instantiate)
+  {
+    ClassAPI classAPI = new ClassAPI();
+    classAPI.setName(className);
+    classAPI.setSuperClass(superClass);
+    classAPI.setAccess(access);
+    classAPI.setReference(ref);
+    classAPI.setSubclass(subclass);
+    classAPI.setImplement(implement);
+    classAPI.setInstantiate(instantiate);
+    return classAPI;
+  }
+
+  private MethodAPI newMethodAPI(String methodName, int access, String descriptor, String[] throwTypes)
+  {
+    MethodAPI methodAPI = new MethodAPI();
+    methodAPI.setName(methodName);
+    methodAPI.setAccess(access);
+    methodAPI.setDescriptor(descriptor);
+    List throwList = methodAPI.getThrows();
+    for (int i = 0; i < throwTypes.length; i++)
+      throwList.add(throwTypes[i]);
+    return methodAPI;
+  }
+
+  private FieldAPI newFieldAPI(String fieldName, int access, String descriptor)
+  {
+    FieldAPI fieldAPI = new FieldAPI();
+    fieldAPI.setName(fieldName);
+    fieldAPI.setAccess(access);
+    fieldAPI.setDescriptor(descriptor);
+    return fieldAPI;
+  }
+
+  private Package findPackage(ComponentXML compXML, String pkgName)
+  {
+    if (pkgName != null && compXML != null)
+    {
+      Collection pkgs = compXML.getPackages();
+      for (Iterator it = pkgs.iterator(); it.hasNext();)
+      {
+        Package pkg = (Package)it.next();
+        if (pkgName.equals(pkg.getName()))
+          return pkg;
+      }
+    }
+    return null;
+  }
+
+  private Type findType(Package pkg, String typeName)
+  {
+    if (typeName != null)
+    {
+      // If not overwritten, inner class inherts usages from base class
+      int i = typeName.indexOf('$');
+      String baseTypeName = (i != -1) ? typeName.substring(0, i) : null;
+      Type baseType = null;
+      Collection types = pkg.getTypes();
+      for (Iterator it = types.iterator(); it.hasNext();)
+      {
+        Type type = (Type)it.next();
+        String name = type.getName();
+        if (typeName.equals(name))
+          return type;
+        if (baseTypeName != null && baseType == null && baseTypeName.equals(name))
+          baseType = type;
+      }
+      if (baseType != null)
+        return baseType;
+    }
+    return null;
+  }
+
+  private boolean isBit(int flag, int bit)
+  {
+    return ((flag & bit) == bit);
+  }
+
+  public static void main(String[] args)
+  {
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    List eclipseDir = (List)options.get(ComponentAPIEmitter.OPTION_ECLIPSE_DIR);
+    List compXMLDir = (List)options.get(ComponentAPIEmitter.OPTION_COMPONENT_XML_DIR);
+    List compAPIDir = (List)options.get(ComponentAPIEmitter.OPTION_COMPONENT_API_DIR);
+    if (eclipseDir == null || compXMLDir == null || compAPIDir == null || eclipseDir.size() < 1 || compXMLDir.size() < 1 || compAPIDir.size() < 1)
+    {
+      printUsage();
+      System.exit(-1);
+    }
+    ComponentAPIEmitter compAPIEmitter = new ComponentAPIEmitter((String)compAPIDir.get(0));
+    compAPIEmitter.init(eclipseDir, compXMLDir);
+    try
+    {
+      compAPIEmitter.genComponentApiXml();
+    }
+    catch (IOException ioe)
+    {
+      ioe.printStackTrace();
+    }
+  }
+
+  private static void printUsage()
+  {
+    System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.api.ComponentAPIEmitter -eclipseDir <eclipseDir> -compXMLDir <compDir> -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-compXMLDir\t<compXMLDir>\tdirectory containing component.xml");
+    System.out.println("\t-compAPIDir\t<compAPIDir>\toutput directory of component-api.xml");
+  }
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentUse.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentUse.java
new file mode 100644
index 0000000..3a49b27
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentUse.java
@@ -0,0 +1,276 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class ComponentUse extends ComponentAPI
+{
+  public static final String CONST_COMPONENT_USE_XML = "component-use.xml";
+  public static final String CONST_COMPONENT_USE_HTML = "component-use.html";
+
+  private static final String ELEMENT_COMPONENT_USE = "component-use";
+  private static final String ELEMENT_SOURCE = "source";
+  private static final String ELEMENT_CLASS_USE = "class-use";
+  private static final String ELEMENT_METHOD_USE = "method-use";
+  private static final String ELEMENT_FIELD_USE = "field-use";
+
+  private static final String ATTR_ACCESS = "access";
+  private static final String ATTR_LINES = "lines";
+  private static final String ATTR_NAME = "name";
+  private static final String ATTR_DESCRIPTOR = "descriptor";
+  private static final String ATTR_REFERENCE = "reference";
+  private static final String ATTR_IMPLEMENT = "implement";
+  private static final String ATTR_SUBCLASS = "subclass";
+  private static final String ATTR_INSTANTIATE = "instantiate";
+  private static final String ATTR_THROWS = "throws";
+
+  private List sources;
+
+  /**
+   * @return Returns the sources.
+   */
+  public List getSources()
+  {
+    if (sources == null)
+      sources = new ArrayList(1);
+    return sources;
+  }
+
+  public void addSource(Source source)
+  {
+    if (sources == null)
+      sources = new ArrayList(1);
+    sources.add(source);
+  }
+
+  public void load() throws IOException, FileNotFoundException
+  {
+    try
+    {
+      SAXParserFactory factory = SAXParserFactory.newInstance();
+      factory.setNamespaceAware(false);
+      factory.setValidating(false);
+      SAXParser parser = factory.newSAXParser();
+      parser.parse(new InputSource(new BufferedInputStream(location.getInputStream())), new ComponentUseHandler(this));
+    }
+    catch (ParserConfigurationException pce)
+    {
+      pce.printStackTrace();
+    }
+    catch (SAXException saxe)
+    {
+      saxe.printStackTrace();
+    }
+  }
+
+  public void saveAsHTML(ILocation html) throws TransformerConfigurationException, TransformerException, IOException
+  {
+    TransformerFactory factory = TransformerFactory.newInstance();
+    Transformer transformer = factory.newTransformer(new StreamSource(ClassLoader.getSystemResourceAsStream("org/eclipse/wtp/releng/tools/component/xsl/component-violation.xsl")));
+    transformer.transform(new StreamSource(new ByteArrayInputStream(getBytes())), new StreamResult(new FileOutputStream(new File(html.getAbsolutePath()))));
+  }
+
+  public void save() throws IOException
+  {
+    if (location != null)
+    {
+      File file = new File(location.getAbsolutePath());
+      file.getParentFile().mkdirs();
+      FileOutputStream fos = new FileOutputStream(file);
+      fos.write(getBytes());
+      fos.close();
+    }
+  }
+
+  public String toString()
+  {
+    try
+    {
+      return new String(getBytes());
+    }
+    catch (UnsupportedEncodingException e)
+    {
+      e.printStackTrace();
+    }
+    return super.toString();
+  }
+
+  private byte[] getBytes() throws UnsupportedEncodingException
+  {
+    StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    sb.append("<component-use ");
+    sb.append(toAttribute(ATTR_NAME, getName()));
+    sb.append(">");
+    for (Iterator it = getSources().iterator(); it.hasNext();)
+      saveSource(sb, (Source)it.next());
+    sb.append("</component-use>");
+    return sb.toString().getBytes("UTF-8");
+  }
+
+  private void saveSource(StringBuffer sb, Source source)
+  {
+    sb.append("<source");
+    sb.append(toAttribute(ATTR_NAME, source.getName()));
+    sb.append(">");
+    for (Iterator it = source.getClassUses().iterator(); it.hasNext();)
+      saveClassUse(sb, (ClassUse)it.next());
+    sb.append("</source>");
+  }
+
+  private void saveClassUse(StringBuffer sb, ClassUse classUse)
+  {
+    sb.append("<class-use");
+    sb.append(toAttribute(ATTR_NAME, classUse.getName()));
+    if (classUse.sizeLines() > 0)
+      sb.append(toAttribute(ATTR_LINES, classUse.getLines(), " "));
+    int access = classUse.getAccess();
+    if (access != -1)
+      sb.append(toAttribute(ATTR_ACCESS, String.valueOf(access)));
+    if (classUse.getReference() != null)
+      sb.append(toAttribute(ATTR_REFERENCE, String.valueOf(classUse.isReference())));
+    if (classUse.getImplement() != null)
+      sb.append(toAttribute(ATTR_IMPLEMENT, String.valueOf(classUse.isImplement())));
+    if (classUse.getSubclass() != null)
+      sb.append(toAttribute(ATTR_SUBCLASS, String.valueOf(classUse.isSubclass())));
+    if (classUse.getInstantiate() != null)
+      sb.append(toAttribute(ATTR_INSTANTIATE, String.valueOf(classUse.isInstantiate())));
+    sb.append(">");
+    if (classUse.sizeMethodUses() > 0)
+      for (Iterator it = classUse.getMethodUses().iterator(); it.hasNext();)
+        saveMethodUse(sb, (MethodUse)it.next());
+    if (classUse.sizeFieldUses() > 0)
+      for (Iterator it = classUse.getFieldUses().iterator(); it.hasNext();)
+        saveFieldUse(sb, (FieldUse)it.next());
+    sb.append("</class-use>");
+  }
+
+  protected void saveMethodUse(StringBuffer sb, MethodUse methodUse)
+  {
+    sb.append("<method-use");
+    sb.append(toAttribute(ATTR_NAME, methodUse.getName()));
+    sb.append(toAttribute(ATTR_DESCRIPTOR, methodUse.getDescriptor()));
+    int access = methodUse.getAccess();
+    if (access != -1)
+      sb.append(toAttribute(ATTR_ACCESS, String.valueOf(access)));
+    if (methodUse.sizeThrows() > 0)
+      sb.append(toAttribute(ATTR_THROWS, methodUse.getThrows(), " "));
+    if (methodUse.sizeLines() > 0)
+      sb.append(toAttribute(ATTR_LINES, methodUse.getLines(), " "));
+    sb.append("/>");
+  }
+
+  protected void saveFieldUse(StringBuffer sb, FieldUse fieldUse)
+  {
+    sb.append("<field-use");
+    sb.append(toAttribute(ATTR_NAME, fieldUse.getName()));
+    sb.append(toAttribute(ATTR_DESCRIPTOR, fieldUse.getDescriptor()));
+    int access = fieldUse.getAccess();
+    if (access != -1)
+      sb.append(toAttribute(ATTR_ACCESS, String.valueOf(access)));
+    if (fieldUse.sizeLines() > 0)
+      sb.append(toAttribute(ATTR_LINES, fieldUse.getLines(), " "));
+    sb.append("/>");
+  }
+
+  protected static class ComponentUseHandler extends ComponentAPIHandler
+  {
+    private ComponentUse compUse;
+    private Source source;
+    private ClassUse classUse;
+    
+    public ComponentUseHandler(ComponentUse compUse)
+    {
+      super(compUse);
+      this.compUse = compUse;
+    }
+
+    public void startElement(String uri, String elementName, String qName, Attributes attributes) throws SAXException
+    {
+      if (elementName.equals(ELEMENT_SOURCE) || qName.equals(ELEMENT_SOURCE))
+      {
+        source = new Source();
+        source.setName(attributes.getValue(ATTR_NAME));
+        compUse.addSource(source);
+      }
+      else if (elementName.equals(ELEMENT_CLASS_USE) || qName.equals(ELEMENT_CLASS_USE))
+      {
+        if (source != null)
+        {
+          classUse = new ClassUse();
+          classUse.setName(attributes.getValue(ATTR_NAME));
+          String attrLines = attributes.getValue(ATTR_LINES);
+          if (attrLines != null)
+            classUse.addLines(toCollection(attrLines, " "));
+          String attrAccess = attributes.getValue(ATTR_ACCESS);
+          if (attrAccess != null)
+            classUse.setAccess(Integer.parseInt(attrAccess));
+          String attrRef = attributes.getValue(ATTR_REFERENCE);
+          if (attrRef != null)
+            classUse.setReference(Boolean.valueOf(attrRef));
+          String attrImpl = attributes.getValue(ATTR_IMPLEMENT);
+          if (attrImpl != null)
+            classUse.setImplement(Boolean.valueOf(attrImpl));
+          String attrSubclass = attributes.getValue(ATTR_SUBCLASS);
+          if (attrSubclass != null)
+            classUse.setSubclass(Boolean.valueOf(attrSubclass));
+          String attrInstantiate = attributes.getValue(ATTR_INSTANTIATE);
+          if (attrInstantiate != null)
+            classUse.setInstantiate(Boolean.valueOf(attrInstantiate));
+          source.addClassUse(classUse);
+        }
+      }
+      else if (elementName.equals(ELEMENT_METHOD_USE) || qName.equals(ELEMENT_METHOD_USE))
+      {
+        MethodUse methodUse = new MethodUse();
+        startMethod(classUse, methodUse, attributes);
+        String attrLines = attributes.getValue(ATTR_LINES);
+        if (attrLines != null)
+          methodUse.addLines(toCollection(attrLines, " "));
+      }
+      else if (elementName.equals(ELEMENT_FIELD_USE) || qName.equals(ELEMENT_FIELD_USE))
+      {
+        FieldUse fieldUse = new FieldUse();
+        startField(classUse, fieldUse, attributes);
+        String attrLines = attributes.getValue(ATTR_LINES);
+        if (attrLines != null)
+          fieldUse.addLines(toCollection(attrLines, " "));
+      }
+      else if (elementName.equals(ELEMENT_COMPONENT_USE) || qName.equals(ELEMENT_COMPONENT_USE))
+      {
+        compUse.setName(attributes.getValue(ATTR_NAME));
+      }
+    }
+  }
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentUseEmitter.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentUseEmitter.java
new file mode 100644
index 0000000..2b42f4d
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentUseEmitter.java
@@ -0,0 +1,510 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+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.ComponentUse;
+import org.eclipse.wtp.releng.tools.component.internal.AbstractEmitter;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentXML;
+import org.eclipse.wtp.releng.tools.component.internal.FieldRef;
+import org.eclipse.wtp.releng.tools.component.internal.FileLocation;
+import org.eclipse.wtp.releng.tools.component.internal.MethodRef;
+import org.eclipse.wtp.releng.tools.component.internal.Plugin;
+
+public class ComponentUseEmitter extends AbstractEmitter implements IClazzVisitor
+{
+  public static final String OPTION_ECLIPSE_DIR = "eclipseDir";
+  public static final String OPTION_COMPONENT_XML_DIR = "compXMLDir";
+  public static final String OPTION_COMPONENT_USE_DIR = "compUseDir";
+  public static final String OPTION_INCLUDE = "include";
+  public static final String OPTION_EXCLUDE = "exclude";
+  public static final String OPTION_CLASS_REF_ONLY = "classRefOnly";
+  public static final String OPTION_DEBUG = "debug";
+  private String compUseDir;
+  private Map pluginId2Plugin;
+  private Map fragmentId2Fragment;
+  private Map compLoc2CompXML;
+  private List classUseIncludes;
+  private List classUseIncludesMatch;
+  private List classUseExcludes;
+  private List classUseExcludesMatch;
+  private boolean classRefOnly;
+  private boolean debug;
+  private ComponentUse compUse;
+
+  public ComponentUseEmitter(String compUseDir)
+  {
+    this.compUseDir = addTrailingSeperator(compUseDir);
+    classRefOnly = false;
+    debug = false;
+  }
+
+  public void init(List eclipseDirs, List compXMLDirs)
+  {
+    compLoc2CompXML = new HashMap();
+    pluginId2Plugin = new HashMap();
+    fragmentId2Fragment = new HashMap();
+    for (Iterator it = eclipseDirs.iterator(); it.hasNext();)
+    {
+      File eclipseFile = new File(addTrailingSeperator((String)it.next()));
+      if (eclipseFile.exists())
+        harvestPlugins(eclipseFile, pluginId2Plugin, fragmentId2Fragment);
+    }
+    linkPluginsAndFragments(pluginId2Plugin, fragmentId2Fragment);
+    for (Iterator it = compXMLDirs.iterator(); it.hasNext();)
+    {
+      File compXMLFile = new File(addTrailingSeperator((String)it.next()));
+      if (compXMLFile.exists())
+        harvestComponents(compXMLFile, compLoc2CompXML);
+    }
+  }
+
+  public void init(Map compLoc2CompXML, Map pluginId2Plugin, Map fragmentId2Fragment)
+  {
+    this.compLoc2CompXML = compLoc2CompXML;
+    this.pluginId2Plugin = pluginId2Plugin;
+    this.fragmentId2Fragment = fragmentId2Fragment;
+  }
+
+  /**
+   * @return Returns the classRefOnly.
+   */
+  public boolean isClassRefOnly()
+  {
+    return classRefOnly;
+  }
+
+  /**
+   * @param classRefOnly
+   *          The classRefOnly to set.
+   */
+  public void setClassRefOnly(boolean classRefOnly)
+  {
+    this.classRefOnly = classRefOnly;
+  }
+
+  /**
+   * @return Returns the debug.
+   */
+  public boolean isDebug()
+  {
+    return debug;
+  }
+
+  /**
+   * @param debug
+   *          The debug to set.
+   */
+  public void setDebug(boolean debug)
+  {
+    this.debug = debug;
+  }
+
+  public List getClassUseIncludes()
+  {
+    return classUseIncludes;
+  }
+
+  public void setClassUseIncludes(List includes)
+  {
+    this.classUseIncludes = includes;
+  }
+
+  public List getClassUseIncludesMatch()
+  {
+    return classUseIncludesMatch;
+  }
+
+  public void setClassUseIncludesMatch(List includesMatch)
+  {
+    this.classUseIncludesMatch = includesMatch;
+  }
+
+  public List getClassUseExcludes()
+  {
+    return classUseExcludes;
+  }
+
+  public void setClassUseExcludes(List excludes)
+  {
+    this.classUseExcludes = excludes;
+  }
+
+  public List getClassUseExcludesMatch()
+  {
+    return classUseExcludesMatch;
+  }
+
+  public void setClassUseExcludesMatch(List excludesMatch)
+  {
+    this.classUseExcludesMatch = excludesMatch;
+  }
+
+  public void genComponentUseXML() throws IOException
+  {
+    for (Iterator it = compLoc2CompXML.keySet().iterator(); it.hasNext();)
+      genComponentUseXML((String)it.next());
+  }
+
+  public ComponentUse genComponentUseXML(String compLoc) throws IOException
+  {
+    ComponentXML compXML = (ComponentXML)compLoc2CompXML.get(compLoc);
+    if (compXML != null)
+    {
+      compXML.load();
+      String compName = compXML.getName();
+      compUse = newComponentUse(compXML);
+      for (Iterator pluginsIt = compXML.getPlugins().iterator(); pluginsIt.hasNext();)
+      {
+        IPluginXML pluginXML = (IPluginXML)pluginId2Plugin.get(((Plugin)pluginsIt.next()).getId());
+        if (pluginXML != null)
+          pluginXML.accept(this);
+      }
+      compXML = null;
+      if (compUseDir != null)
+        System.out.println("Writing component-use.xml for " + compName);
+      compUse.save();
+      return compUse;
+    }
+    return null;
+  }
+
+  public ComponentUse genAll() throws IOException
+  {
+    compUse = new ComponentUse();
+    for (Iterator it = pluginId2Plugin.values().iterator(); it.hasNext();)
+      ((IPluginXML)it.next()).accept(this);
+    return compUse;
+  }
+
+  public Source genUse(IClazz clazz)
+  {
+    return newSource(clazz);
+  }
+
+  public boolean visit(IClazz clazz)
+  {
+    if (compUse == null)
+      return false;
+    Source source = newSource(clazz);
+    addSource(compUse, source);
+    return true;
+  }
+
+  private Source newSource(IClazz clazz)
+  {
+    String className = clazz.getName();
+    Source source = newSource(clazz.getName());
+    if (!classRefOnly)
+    {
+      // method references
+      List methodRefs = clazz.getMethodRefs(combineFilters(classUseIncludes, classUseIncludesMatch), combineFilters(classUseExcludes, classUseExcludesMatch), debug);
+      for (Iterator it = methodRefs.iterator(); it.hasNext();)
+      {
+        MethodRef methodRef = (MethodRef)it.next();
+        String refClassName = methodRef.getClassName();
+        String methodName = methodRef.getMethodName();
+		ClassUse classUse;
+        if (isConstructor(methodName))
+        {
+          // use: instantiate
+          classUse = addUniqueClassUse(source, refClassName, null, null, null, Boolean.TRUE, methodRef.getLines());
+        }
+        else
+        {
+          classUse = addUniqueClassUse(source, refClassName, Boolean.TRUE, null, null, null, null);
+        }
+		MethodUse methodUse = newMethodUse(methodName, methodRef.getMethodDescriptor(), methodRef.getLines());
+        classUse.getMethodUses().add(methodUse);
+      }
+      clazz.resetMethodRefs();
+      methodRefs = null;
+      // field references
+      List fieldRefs = clazz.getFieldRefs(combineFilters(classUseIncludes, classUseIncludesMatch), combineFilters(classUseExcludes, classUseExcludesMatch), debug);
+      for (Iterator it = fieldRefs.iterator(); it.hasNext();)
+      {
+        FieldRef fieldRef = (FieldRef)it.next();
+        String refClassName = fieldRef.getClassName();
+        ClassUse classUse = addUniqueClassUse(source, refClassName, Boolean.TRUE, null, null, null, null);
+        FieldAPI fieldUse = newFieldUse(fieldRef.getFieldName(), fieldRef.getFieldDescriptor(), fieldRef.getLines());
+        classUse.getFieldAPIs().add(fieldUse);
+      }
+      clazz.resetFieldRefs();
+      fieldRefs = null;
+      // use: subclass
+      if (!clazz.isInterface())
+      {
+        String superClass = clazz.getSuperClass();
+        if (superClass != null && isReportClassUse(className, superClass))
+          addUniqueClassUse(source, superClass, null, Boolean.TRUE, null, null, null);
+      }
+      // use: implement
+      String[] interfaces = clazz.getInterfaces();
+      for (int i = 0; i < interfaces.length; i++)
+        if (isReportClassUse(className, interfaces[i]))
+          addUniqueClassUse(source, interfaces[i], null, null, Boolean.TRUE, null, null);
+    }
+    // use: reference
+    Set refClasses = clazz.getReferencedTypes();
+    for (Iterator refClassesIt = refClasses.iterator(); refClassesIt.hasNext();)
+    {
+      String refClassName = (String)refClassesIt.next();
+      if (isReportClassUse(className, refClassName))
+        addUniqueClassUse(source, refClassName, Boolean.TRUE, null, null, null, null);
+    }
+    return source;
+  }
+
+  private List combineFilters(List filtersStart, List filtersMatch)
+  {
+    List filters = new ArrayList();
+    if (filtersStart != null)
+      filters.addAll(filtersStart);
+    if (filtersMatch != null)
+      for (Iterator it = filtersMatch.iterator(); it.hasNext();)
+        filters.add(new StringBuffer("*").append((String)it.next()).append("*").toString());
+    if (filters.size() > 0)
+      return filters;
+    else
+      return null;
+  }
+
+  private boolean isReportClassUse(String sourceClassName, String classUseName)
+  {
+    if (sourceClassName != null && sourceClassName.equals(classUseName))
+      return false;
+    if (classUseExcludes != null)
+      for (Iterator it = classUseExcludes.iterator(); it.hasNext();)
+        if (classUseName.startsWith((String)it.next()))
+          return false;
+    if (classUseExcludesMatch != null)
+      for (Iterator it = classUseExcludesMatch.iterator(); it.hasNext();)
+        if (classUseName.indexOf((String)it.next()) != -1)
+          return false;
+    if ((classUseIncludes != null && classUseIncludes.size() > 0) || (classUseIncludesMatch != null && classUseIncludesMatch.size() > 0))
+    {
+      if (classUseIncludes != null)
+        for (Iterator it = classUseIncludes.iterator(); it.hasNext();)
+          if (classUseName.startsWith((String)it.next()))
+            return true;
+      if (classUseIncludesMatch != null)
+        for (Iterator it = classUseIncludesMatch.iterator(); it.hasNext();)
+          if (classUseName.indexOf((String)it.next()) != -1)
+            return true;
+      return false;
+    }
+    return true;
+  }
+
+  private boolean isConstructor(String methodName)
+  {
+    return methodName.equals("<init>");
+  }
+
+  private void addSource(ComponentUse compUse, Source source)
+  {
+    if (source.getClassUses().size() > 0)
+      compUse.getSources().add(source);
+  }
+
+  private ClassUse addUniqueClassUse(Source source, String className, Boolean ref, Boolean subclass, Boolean implement, Boolean instantiate, List lines)
+  {
+    for (Iterator it = source.getClassUses().iterator(); it.hasNext();)
+    {
+      ClassUse classUse = (ClassUse)it.next();
+      if (!classUse.getName().equals(className))
+        continue;
+      if (ref != null && (classUse.getReference() == null || (ref.booleanValue() != classUse.isReference())))
+        continue;
+      if (subclass != null && (classUse.getSubclass() == null || (subclass.booleanValue() != classUse.isSubclass())))
+        continue;
+      if (implement != null && (classUse.getImplement() == null || (implement.booleanValue() != classUse.isImplement())))
+        continue;
+      if (instantiate != null && (classUse.getInstantiate() == null || (instantiate.booleanValue() != classUse.isInstantiate())))
+        continue;
+      if (lines != null)
+        classUse.getLines().addAll(lines);
+      return classUse;
+    }
+    ClassUse classUse = newClassUse(className, ref, subclass, implement, instantiate, lines);
+    source.addClassUse(classUse);
+    return classUse;
+  }
+
+  private ClassUse newClassUse(String className, Boolean ref, Boolean subclass, Boolean implement, Boolean instantiate, List lines)
+  {
+    ClassUse classUse = new ClassUse();
+    classUse.setName(className);
+    classUse.setReference(ref);
+    classUse.setSubclass(subclass);
+    classUse.setImplement(implement);
+    classUse.setInstantiate(instantiate);
+    if (lines != null)
+      classUse.getLines().addAll(lines);
+    return classUse;
+  }
+
+  private MethodUse newMethodUse(String methodName, String descriptor, List lines)
+  {
+    MethodUse methodUse = new MethodUse();
+    methodUse.setName(methodName);
+    methodUse.setDescriptor(descriptor);
+    if (lines != null)
+      methodUse.getLines().addAll(lines);
+    return methodUse;
+  }
+
+  private FieldUse newFieldUse(String fieldName, String descriptor, List lines)
+  {
+    FieldUse fieldUse = new FieldUse();
+    fieldUse.setName(fieldName);
+    fieldUse.setDescriptor(descriptor);
+    if (lines != null)
+      fieldUse.getLines().addAll(lines);
+    return fieldUse;
+  }
+
+  private ComponentUse newComponentUse(ComponentXML compXML)
+  {
+    String compName = compXML.getName();
+    ILocation location = null;
+    if (compUseDir != null)
+    {
+      StringBuffer sb = new StringBuffer(compUseDir);
+      sb.append(compName);
+      sb.append('/');
+      sb.append(ComponentUse.CONST_COMPONENT_USE_XML);
+      location = new FileLocation(new File(sb.toString()));
+    }
+    return newComponentUse(compName, location);
+  }
+
+  private ComponentUse newComponentUse(String name, ILocation location)
+  {
+    ComponentUse compUse = new ComponentUse();
+    compUse.setName(name);
+    compUse.setLocation(location);
+    return compUse;
+  }
+
+  private Source newSource(String className)
+  {
+    Source source = new Source();
+    source.setName(className);
+    return source;
+  }
+
+  public static void main(String[] args)
+  {
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    List eclipseDir = (List)options.get(ComponentUseEmitter.OPTION_ECLIPSE_DIR);
+    List compXMLDir = (List)options.get(ComponentUseEmitter.OPTION_COMPONENT_XML_DIR);
+    List compUseDir = (List)options.get(ComponentUseEmitter.OPTION_COMPONENT_USE_DIR);
+    List includes = (List)options.get(ComponentUseEmitter.OPTION_INCLUDE);
+    List excludes = (List)options.get(ComponentUseEmitter.OPTION_EXCLUDE);
+    List classRefOnly = (List)options.get(ComponentUseEmitter.OPTION_CLASS_REF_ONLY);
+    List debug = (List)options.get(ComponentUseEmitter.OPTION_DEBUG);
+    if (eclipseDir == null || compXMLDir == null || compUseDir == null || eclipseDir.size() < 1 || compXMLDir.size() < 1 || compUseDir.size() < 1)
+    {
+      printUsage();
+      System.exit(-1);
+    }
+    List includesStart = null;
+    List includesMatch = null;
+    if (includes != null)
+    {
+      for (Iterator it = includes.iterator(); it.hasNext();)
+      {
+        String s = (String)it.next();
+        if (s.charAt(0) == '*' && s.charAt(s.length() - 1) == '*')
+        {
+          if (includesMatch == null)
+            includesMatch = new ArrayList(1);
+          includesMatch.add(s.substring(1, s.length() - 1));
+        }
+        else
+        {
+          if (includesStart == null)
+            includesStart = new ArrayList(1);
+          includesStart.add(s);
+        }
+      }
+    }
+    List excludesStart = null;
+    List excludesMatch = null;
+    if (excludes != null)
+    {
+      for (Iterator it = excludes.iterator(); it.hasNext();)
+      {
+        String s = (String)it.next();
+        if (s.charAt(0) == '*' && s.charAt(s.length() - 1) == '*')
+        {
+          if (excludesMatch == null)
+            excludesMatch = new ArrayList(1);
+          excludesMatch.add(s.substring(1, s.length() - 1));
+        }
+        else
+        {
+          if (excludesStart == null)
+            excludesStart = new ArrayList(1);
+          excludesStart.add(s);
+        }
+      }
+    }
+    ComponentUseEmitter compUseEmitter = new ComponentUseEmitter((String)compUseDir.get(0));
+    compUseEmitter.setClassUseIncludes(includesStart);
+    compUseEmitter.setClassUseIncludesMatch(includesMatch);
+    compUseEmitter.setClassUseExcludes(excludesStart);
+    compUseEmitter.setClassUseExcludesMatch(excludesMatch);
+    compUseEmitter.setClassRefOnly(classRefOnly != null);
+    compUseEmitter.setDebug(debug != null);
+    compUseEmitter.init(eclipseDir, compXMLDir);
+    try
+    {
+      compUseEmitter.genComponentUseXML();
+    }
+    catch (IOException ioe)
+    {
+      ioe.printStackTrace();
+    }
+  }
+
+  private static void printUsage()
+  {
+    System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.use.ComponentUseEmitter -eclipseDir <eclipseDir> -compXMLDir <compDir> [-options]");
+    System.out.println("");
+    System.out.println("\t-eclipseDir\t<eclipseDir>\tspace seperated list of directories containing Eclipse plugins");
+    System.out.println("\t-compXMLDir\t<compXMLDir>\tdirectory containing component.xml");
+    System.out.println("\t-compUseDir\t<compUseDir>\toutput directory of component-use.xml");
+    System.out.println("");
+    System.out.println("where options include:");
+    System.out.println("");
+    System.out.println("\t-include\t<include>\tspace seperated packages to include");
+    System.out.println("\t-exclude\t<exclude>\tspace seperated packages to exclude");
+    System.out.println("\t-classRefOnly\t\t\ttreat all violations as class reference");
+    System.out.println("\t-debug\t\t\t\tgenerate debug information (ex. line numbers)");
+  }
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentXMLVisitor.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentXMLVisitor.java
new file mode 100644
index 0000000..c9e1f69
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/ComponentXMLVisitor.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.ILocationVisitor;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentXML;
+
+public class ComponentXMLVisitor implements ILocationVisitor
+{
+  private Map compXMLs;
+
+  public ComponentXMLVisitor()
+  {
+    this.compXMLs = new HashMap();
+  }
+
+  public Collection getCompXMLs()
+  {
+    return new ArrayList(compXMLs.values());
+  }
+
+  public boolean accept(ILocation location)
+  {
+    String locationName = location.getName();
+    if (locationName.endsWith("component.xml"))
+    {
+      try
+      {
+        ComponentXML compXML = new ComponentXML();
+        compXML.setLocation(location);
+        compXML.load();
+        String name = compXML.getName();
+        if (!compXMLs.containsKey(name))
+          compXMLs.put(name, compXML);
+      }
+      catch (Throwable e)
+      {
+      }
+    }
+    return true;
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/FieldAPI.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/FieldAPI.java
new file mode 100644
index 0000000..60c3832
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/FieldAPI.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * 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;
+
+import org.eclipse.wtp.releng.tools.component.internal.ComponentObject;
+
+public class FieldAPI extends ComponentObject
+{
+  private String name;
+  private int access;
+  private String descriptor;
+  private JavadocCoverage javadocCoverage;
+
+  public FieldAPI()
+  {
+    access = -1;
+  }
+
+  /**
+   * @return Returns the access.
+   */
+  public int getAccess()
+  {
+    return access;
+  }
+
+  /**
+   * @param access The access to set.
+   */
+  public void setAccess(int access)
+  {
+    this.access = access;
+  }
+
+  /**
+   * @return Returns the descriptor.
+   */
+  public String getDescriptor()
+  {
+    return descriptor;
+  }
+
+  /**
+   * @param descriptor The descriptor to set.
+   */
+  public void setDescriptor(String descriptor)
+  {
+    this.descriptor = descriptor;
+  }
+
+  /**
+   * @return Returns the name.
+   */
+  public String getName()
+  {
+    return name;
+  }
+
+  /**
+   * @param name The name to set.
+   */
+  public void setName(String name)
+  {
+    this.name = name;
+  }
+
+  public JavadocCoverage getJavadocCoverage()
+  {
+    if (javadocCoverage == null)
+      javadocCoverage = new JavadocCoverage();
+    return javadocCoverage;
+  }
+
+  public void setJavadocCoverage(JavadocCoverage javadocCoverage)
+  {
+    this.javadocCoverage = javadocCoverage;
+  }
+
+  public boolean isSetJavadocCoverage()
+  {
+    return javadocCoverage != null;
+  }
+
+  public String toString()
+  {
+    StringBuffer sb = new StringBuffer();
+    sb.append("<field-api");
+    sb.append(toAttribute("name", getName()));
+    sb.append(toAttribute("descriptor", getDescriptor()));
+    int access = getAccess();
+    if (access != -1)
+      sb.append(toAttribute("access", String.valueOf(access)));
+    sb.append(">");
+    if (javadocCoverage != null)
+      sb.append(javadocCoverage.toString());
+    sb.append("</field-api>");
+    return sb.toString();
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/FieldUse.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/FieldUse.java
new file mode 100644
index 0000000..fd3e45a
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/FieldUse.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class FieldUse extends FieldAPI
+{
+  private List lines;
+
+  /**
+   * @return Returns the line.
+   */
+  public List getLines()
+  {
+    if (lines == null)
+      return new ArrayList(0);
+    else
+      return new ArrayList(lines);
+  }
+
+  public void addLine(int line)
+  {
+    if (lines == null)
+      lines = new ArrayList(1);
+    lines.add(String.valueOf(line));
+  }
+
+  public void addLines(Collection l)
+  {
+    if (lines == null)
+      lines = new ArrayList(l);
+    else
+      lines.addAll(l);
+  }
+
+  public int sizeLines()
+  {
+    return lines != null ? lines.size() : 0;
+  }
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/JavadocCoverage.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/JavadocCoverage.java
new file mode 100644
index 0000000..7a8683b
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/JavadocCoverage.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wtp.releng.tools.component.internal.ComponentObject;
+
+public class JavadocCoverage extends ComponentObject
+{
+  private Boolean hasDoc;
+  private Boolean hasSince;
+  private Boolean hasReturn;
+  private List missingParams;
+  private List missingThrows;
+
+  public boolean hasDoc()
+  {
+    if (hasDoc == null)
+      return true;
+    else
+      return hasDoc.booleanValue();
+  }
+
+  public Boolean getHasDoc()
+  {
+    return hasDoc;
+  }
+
+  public void setHasDoc(Boolean hasDoc)
+  {
+    this.hasDoc = hasDoc;
+  }
+
+  public boolean hasSince()
+  {
+    if (hasSince == null)
+      return true;
+    else
+      return hasSince.booleanValue();
+  }
+
+  public Boolean getHasSince()
+  {
+    return hasSince;
+  }
+
+  public void setHasSince(Boolean hasSince)
+  {
+    this.hasSince = hasSince;
+  }
+
+  public boolean hasReturn()
+  {
+    if (hasReturn == null)
+      return true;
+    else
+      return hasReturn.booleanValue();
+  }
+
+  public Boolean getHasReturn()
+  {
+    return hasReturn;
+  }
+
+  public void setHasReturn(Boolean hasReturn)
+  {
+    this.hasReturn = hasReturn;
+  }
+
+  public void addMissingParam(String param)
+  {
+    if (missingParams == null)
+      missingParams = new ArrayList();
+    missingParams.add(param);
+  }
+
+  public List getMissingParams()
+  {
+    List copy = new ArrayList();
+    if (missingParams != null)
+      copy.addAll(missingParams);
+    return copy;
+  }
+
+  public void addMissingThrow(String missingThrow)
+  {
+    if (missingThrows == null)
+      missingThrows = new ArrayList();
+    missingThrows.add(missingThrow);
+  }
+
+  public List getMissingThrows()
+  {
+    List copy = new ArrayList();
+    if (missingThrows != null)
+      copy.addAll(missingThrows);
+    return copy;
+  }
+
+  public String toString()
+  {
+    StringBuffer sb = new StringBuffer();
+    sb.append("<javadoc-coverage");
+    if (getHasDoc() != null)
+      sb.append(toAttribute("doc", String.valueOf(hasDoc())));
+    if (getHasSince() != null)
+      sb.append(toAttribute("since", String.valueOf(hasSince())));
+    if (getHasReturn() != null)
+      sb.append(toAttribute("return", String.valueOf(hasReturn())));
+    sb.append(">");
+    for (Iterator it = getMissingParams().iterator(); it.hasNext();)
+    {
+      sb.append("<param");
+      sb.append(toAttribute("name", (String)it.next()));
+      sb.append("/>");
+    }
+    for (Iterator it = getMissingThrows().iterator(); it.hasNext();)
+    {
+      sb.append("<throw");
+      sb.append(toAttribute("name", (String)it.next()));
+      sb.append("/>");
+    }
+    sb.append("</javadoc-coverage>");
+    return sb.toString();
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/MethodAPI.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/MethodAPI.java
new file mode 100644
index 0000000..c5be030
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/MethodAPI.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentObject;
+
+public class MethodAPI extends ComponentObject
+{
+  private String name;
+  private int access;
+  private String descriptor;
+  private List throwTypes;
+  private TestCoverage testCoverage;
+  private JavadocCoverage javadocCoverage;
+
+  public MethodAPI()
+  {
+    access = -1;
+  }
+
+  /**
+   * @return Returns the access.
+   */
+  public int getAccess()
+  {
+    return access;
+  }
+
+  /**
+   * @param access The access to set.
+   */
+  public void setAccess(int access)
+  {
+    this.access = access;
+  }
+
+  /**
+   * @return Returns the descriptor.
+   */
+  public String getDescriptor()
+  {
+    return descriptor;
+  }
+
+  /**
+   * @param descriptor The descriptor to set.
+   */
+  public void setDescriptor(String descriptor)
+  {
+    this.descriptor = descriptor;
+  }
+
+  /**
+   * @return Returns the name.
+   */
+  public String getName()
+  {
+    StringBuffer sb = new StringBuffer(name);
+    int index = name.indexOf('<');
+    while (index != -1)
+    {
+      sb.deleteCharAt(index);
+      sb.insert(index, new char[] {'&', 'l', 't', ';'}, 0, 4);
+      index = sb.toString().indexOf('<');
+    }
+    return sb.toString();
+  }
+
+  /**
+   * @param name The name to set.
+   */
+  public void setName(String name)
+  {
+    StringBuffer sb = new StringBuffer(name);
+    int index = name.indexOf("&lt;");
+    while (index != -1)
+    {
+      sb.delete(index, index + 4);
+      sb.insert(index, '<');
+      index = sb.toString().indexOf("&lt;");
+    }
+    this.name = sb.toString();
+  }
+
+  /**
+   * @return Returns the throwTypes.
+   */
+  public List getThrows()
+  {
+    if (throwTypes == null)
+      throwTypes = new ArrayList(1);
+    return throwTypes;
+  }
+
+  public void addThrows(Collection throwTypes)
+  {
+    if (throwTypes == null)
+      throwTypes = new ArrayList(throwTypes);
+    else
+      throwTypes.addAll(throwTypes);
+  }
+
+  public int sizeThrows()
+  {
+    return throwTypes == null ? 0 : throwTypes.size();
+  }
+
+  public List getInputs()
+  {
+    String[] encodedInputs = Signature.getParameterTypes(getDescriptor());
+    List decodedInputs = new ArrayList(encodedInputs.length);
+    for (int i = 0; i < encodedInputs.length; i++)
+      decodedInputs.add(decodeDescriptor(encodedInputs[i]));
+    return decodedInputs;
+  }
+
+  public String getReturn()
+  {
+    return decodeDescriptor(Signature.getReturnType(getDescriptor()));
+  }
+
+  private String decodeDescriptor(String descriptor)
+  {
+    return decodeClassName(Signature.toString(descriptor));
+  }
+
+  private String decodeClassName(String className)
+  {
+    return className.replace('/', '.');
+  }
+
+  public TestCoverage getTestCoverage()
+  {
+    if (testCoverage == null)
+      testCoverage = new TestCoverage();
+    return testCoverage;
+  }
+
+  public void setTestCoverage(TestCoverage testCoverage)
+  {
+    this.testCoverage = testCoverage;
+  }
+
+  public int countTestcases()
+  {
+    return testCoverage != null ? testCoverage.getTests().size() : 0;
+  }
+
+  public JavadocCoverage getJavadocCoverage()
+  {
+    if (javadocCoverage == null)
+      javadocCoverage = new JavadocCoverage();
+    return javadocCoverage;
+  }
+
+  public void setJavadocCoverage(JavadocCoverage javadocCoverage)
+  {
+    this.javadocCoverage = javadocCoverage;
+  }
+
+  public boolean isSetJavadocCoverage()
+  {
+    return javadocCoverage != null;
+  }
+
+  public String toString()
+  {
+    StringBuffer sb = new StringBuffer();
+    sb.append("<method-api");
+    sb.append(toAttribute("name", getName()));
+    sb.append(toAttribute("descriptor", getDescriptor()));
+    int access = getAccess();
+    if (access != -1)
+      sb.append(toAttribute("access", String.valueOf(access)));
+    if (sizeThrows() > 0)
+      sb.append(toAttribute("throws", getThrows(), " "));
+    sb.append(">");
+    if (testCoverage != null)
+      sb.append(testCoverage.toString());
+    if (javadocCoverage != null)
+      sb.append(javadocCoverage.toString());
+    sb.append("</method-api>");
+    return sb.toString();
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/MethodUse.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/MethodUse.java
new file mode 100644
index 0000000..e8d091d
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/MethodUse.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class MethodUse extends MethodAPI
+{
+  private List lines;
+
+  /**
+   * @return Returns the line.
+   */
+  public Collection getLines()
+  {
+    if (lines == null)
+      return new ArrayList(0);
+    else
+      return new ArrayList(lines);
+  }
+
+  public void addLine(int line)
+  {
+    if (lines == null)
+      lines = new ArrayList(1);
+    lines.add(String.valueOf(line));
+  }
+
+  public void addLines(Collection l)
+  {
+    if (lines == null)
+      lines = new ArrayList(l);
+    else
+      lines.addAll(l);
+  }
+
+  public int sizeLines()
+  {
+    return lines != null ? lines.size() : 0;
+  }
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/PackageAPI.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/PackageAPI.java
new file mode 100644
index 0000000..2f5f1d0
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/PackageAPI.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.wtp.releng.tools.component.internal.ComponentObject;
+
+public class PackageAPI extends ComponentObject
+{
+  private String name;
+  private Map classAPIs;
+
+  /**
+   * @return Returns the name.
+   */
+  public String getName()
+  {
+    return name;
+  }
+
+  /**
+   * @param name The name to set.
+   */
+  public void setName(String name)
+  {
+    this.name = name;
+  }
+
+  /**
+   * @return Returns the classAPIs.
+   */
+  public Collection getClassAPIs()
+  {
+    if (classAPIs == null)
+      classAPIs = new HashMap(1);
+    return classAPIs.values();
+  }
+
+  public ClassAPI getClassAPI(String name)
+  {
+    if (classAPIs == null)
+      return null;
+    else
+      return (ClassAPI)classAPIs.get(name);
+  }
+
+  public void addClassAPI(ClassAPI classAPI)
+  {
+    if (classAPIs == null)
+      classAPIs = new HashMap(1);
+    classAPIs.put(classAPI.getName(), classAPI);
+  }
+
+  public void removeClassAPI(ClassAPI classAPI)
+  {
+    if (classAPIs != null)
+      classAPIs.remove(classAPI.getName());
+  }
+
+  public int sizeClassAPI()
+  {
+    if (classAPIs != null)
+      return classAPIs.size();
+    else
+      return 0;
+  }
+
+  public String toString()
+  {
+    StringBuffer sb = new StringBuffer();
+    sb.append("<package-api");
+    sb.append(toAttribute("name", getName()));
+    sb.append(">");
+    for (Iterator it = getClassAPIs().iterator(); it.hasNext();)
+      sb.append(((ClassAPI)it.next()).toString());
+    sb.append("</package-api>");
+    return sb.toString();
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/Source.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/Source.java
new file mode 100644
index 0000000..bdefe6b
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/Source.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Source
+{
+  private String name;
+  private Map classUses;
+
+  /**
+   * @return Returns the name.
+   */
+  public String getName()
+  {
+    return name;
+  }
+
+  /**
+   * @param name The name to set.
+   */
+  public void setName(String name)
+  {
+    this.name = name;
+  }
+
+  /**
+   * @return Returns the classUses.
+   */
+  public Collection getClassUses()
+  {
+    if (classUses == null)
+      classUses = new HashMap(1);
+    return classUses.values();
+  }
+
+  public ClassUse getClassUse(String name)
+  {
+    if (classUses == null)
+      return null;
+    else
+      return (ClassUse)classUses.get(name);
+  }
+
+  public void addClassUse(ClassUse classUse)
+  {
+    if (classUses == null)
+      classUses = new HashMap(1);
+    classUses.put(classUse.getName(), classUse);
+  }
+
+  public Object removeClassUse(ClassUse classUse)
+  {
+    if (classUses == null)
+      return null;
+    else
+      return classUses.remove(classUse.getName());
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/TestCoverage.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/TestCoverage.java
new file mode 100644
index 0000000..16ec365
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/TestCoverage.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wtp.releng.tools.component.internal.ComponentObject;
+
+public class TestCoverage extends ComponentObject
+{
+  private List tests;
+
+  public List getTests()
+  {
+    List copy = new ArrayList();
+    if (tests != null)
+      copy.addAll(tests);
+    return copy;
+  }
+
+  public void addTest(String test)
+  {
+    if (tests == null)
+      tests = new ArrayList();
+    tests.add(test);
+  }
+
+  public void addTests(List tests)
+  {
+    if (this.tests == null)
+      this.tests = new ArrayList(tests.size());
+    this.tests.addAll(tests);
+  }
+
+  public String toString()
+  {
+    StringBuffer sb = new StringBuffer();
+    sb.append("<test-coverage>");
+    for (Iterator it = getTests().iterator(); it.hasNext();)
+    {
+      sb.append("<test");
+      sb.append(toAttribute("name", it.next().toString()));
+      sb.append("/>");
+    }
+    sb.append("</test-coverage>");
+    return sb.toString();
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/compatibility/APICompatibility.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/compatibility/APICompatibility.java
new file mode 100644
index 0000000..d6164b9
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/compatibility/APICompatibility.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * 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.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.api.PackageAPI;
+
+public class APICompatibility
+{
+  public static final String CONST_API_COMPATIBILITY_XML = "api-compatibility.xml";
+
+  protected ILocation location;
+  protected String name;
+  private List newAPIs;
+  private List removedAPIs;
+
+  public APICompatibility()
+  {
+    newAPIs = new ArrayList();
+    removedAPIs = new ArrayList(0);
+  }
+
+  /**
+   * @return Returns the location.
+   */
+  public ILocation getLocation()
+  {
+    return location;
+  }
+
+  /**
+   * @param location The location to set.
+   */
+  public void setLocation(ILocation location)
+  {
+    this.location = location;
+  }
+
+  /**
+   * @return Returns the name.
+   */
+  public String getName()
+  {
+    return name;
+  }
+
+  /**
+   * @param name The name to set.
+   */
+  public void setName(String name)
+  {
+    this.name = name;
+  }
+
+  public void addNewAPI(PackageAPI pkgAPI)
+  {
+    newAPIs.add(pkgAPI);
+  }
+
+  public List getNewAPIs()
+  {
+    return new ArrayList(newAPIs);
+  }
+
+  public void addRemovedAPI(PackageAPI pkgAPI)
+  {
+    removedAPIs.add(pkgAPI);
+  }
+
+  public List getRemovedAPIs()
+  {
+    return new ArrayList(removedAPIs);
+  }
+
+  public void saveAsHTML(ILocation html, String xsl) throws TransformerConfigurationException, TransformerException, IOException
+  {
+    TransformerFactory factory = TransformerFactory.newInstance();
+    Transformer transformer = factory.newTransformer(new StreamSource(ClassLoader.getSystemResourceAsStream(xsl)));
+    transformer.transform(new StreamSource(new ByteArrayInputStream(getBytes())), new StreamResult(new FileOutputStream(new File(html.getAbsolutePath()))));
+  }
+
+  public void save() throws IOException
+  {
+    if (location != null)
+    {
+      File file = new File(location.getAbsolutePath());
+      file.getParentFile().mkdirs();
+      FileOutputStream fos = new FileOutputStream(file);
+      fos.write(getBytes());
+      fos.close();
+    }
+  }
+
+  private byte[] getBytes() throws UnsupportedEncodingException
+  {
+    StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    sb.append("<api-compatibility ");
+    saveAttribute(sb, "name", getName());
+    sb.append(">");
+    sb.append("<new-apis>");
+    for (Iterator it = getNewAPIs().iterator(); it.hasNext();)
+      sb.append(((PackageAPI)it.next()).toString());
+    sb.append("</new-apis>");
+    sb.append("<removed-apis>");
+    for (Iterator it = getRemovedAPIs().iterator(); it.hasNext();)
+      sb.append(((PackageAPI)it.next()).toString());
+    sb.append("</removed-apis>");
+    sb.append("</api-compatibility>");
+    return sb.toString().getBytes("UTF-8");
+  }
+
+  protected void saveAttribute(StringBuffer sb, String key, String value)
+  {
+    if (key != null && value != null)
+    {
+      sb.append(" ");
+      sb.append(key);
+      sb.append("=\"");
+      sb.append(value);
+      sb.append("\"");
+    }
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/compatibility/APICompatibilityEmitter.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/compatibility/APICompatibilityEmitter.java
new file mode 100644
index 0000000..2c7fb84
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/compatibility/APICompatibilityEmitter.java
@@ -0,0 +1,533 @@
+/*******************************************************************************
+ * 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)));
+        }
+      }
+    }
+  }
+}
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/compatibility/APICompatibilityScanner.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/compatibility/APICompatibilityScanner.java
new file mode 100644
index 0000000..b9f0797
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/compatibility/APICompatibilityScanner.java
@@ -0,0 +1,373 @@
+/*******************************************************************************
+ * 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.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.wtp.releng.tools.component.CommandOptionParser;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.ILocationVisitor;
+import org.eclipse.wtp.releng.tools.component.api.API2ComponentAPI;
+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.images.ImagesUtil;
+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.xsl.XSLUtil;
+
+public class APICompatibilityScanner
+{
+  private String outputDir;
+  private boolean html;
+  private String xsl;
+
+  public String getOutputDir()
+  {
+    return outputDir;
+  }
+
+  public void setOutputDir(String outputDir)
+  {
+    this.outputDir = addTrailingSeperator(outputDir);
+  }
+
+  public boolean isHtml()
+  {
+    return html;
+  }
+
+  public void setHtml(boolean html)
+  {
+    this.html = html;
+  }
+
+  public String getXsl()
+  {
+    return xsl;
+  }
+
+  public void setXsl(String xsl)
+  {
+    this.xsl = xsl;
+  }
+
+  private List apiCompXMLs = new ArrayList();
+
+  public void execute()
+  {
+    String currOutputDir = outputDir + "1/";
+    final String refOutputDir = outputDir + "2/";
+
+    // Iterate through api-info.xml for the current build
+    ILocation outputLoc = Location.createLocation(new File(currOutputDir));
+    outputLoc.accept(new ILocationVisitor()
+    {
+      public boolean accept(ILocation location)
+      {
+        if (location.getName().endsWith("api-info.xml"))
+        {
+          try
+          {
+            ComponentAPI currCompAPI = new ComponentAPI();
+            currCompAPI.setLocation(location);
+            currCompAPI.load();
+            String compName = currCompAPI.getName();
+            apiCompXMLs.add(compName);
+            StringBuffer sb = new StringBuffer();
+            sb.append(refOutputDir);
+            sb.append(compName);
+            sb.append("/api-info.xml");
+            ComponentAPI refCompAPI = new ComponentAPI();
+            File f = new File(sb.toString());
+            if (f.exists())
+            {
+              refCompAPI.setLocation(new FileLocation(f));
+              refCompAPI.load();
+            }
+            else
+            {
+              refCompAPI.setName(compName);
+            }
+            genAPICompatibilityXML(currCompAPI, refCompAPI);
+          }
+          catch (IOException ioe)
+          {
+            ioe.printStackTrace();
+          }
+        }
+        return true;
+      }
+    });
+
+    // Iterate through api-info.xml for the reference build
+    outputLoc = Location.createLocation(new File(refOutputDir));
+    outputLoc.accept(new ILocationVisitor()
+    {
+      public boolean accept(ILocation location)
+      {
+        if (location.getName().endsWith("api-info.xml"))
+        {
+          try
+          {
+            ComponentAPI refCompAPI = new ComponentAPI();
+            refCompAPI.setLocation(location);
+            refCompAPI.load();
+            String compName = refCompAPI.getName();
+            if (!apiCompXMLs.contains(compName))
+            {
+              ComponentAPI currCompAPI = new ComponentAPI();
+              currCompAPI.setName(compName);
+              genAPICompatibilityXML(currCompAPI, refCompAPI);
+            }
+          }
+          catch (IOException ioe)
+          {
+            ioe.printStackTrace();
+          }
+        }
+        return true;
+      }
+    });
+
+    // Generate HTML
+    if (isHtml())
+    {
+      ImagesUtil.copyAll(outputDir);
+      genHTML();
+    }
+  }
+
+  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);
+          break;
+        }
+      }
+    }
+    StringBuffer location = new StringBuffer();
+    location.append(outputDir);
+    location.append(compName);
+    location.append("/api-comp.xml");
+    apiCompatibility.setLocation(new FileLocation(new File(location.toString())));
+    apiCompatibility.save();
+    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);
+          if (refClassAPI.sizeMethodAPIs() == 0 && refClassAPI.sizeFieldAPIs() == 0)
+            refPkgAPI.removeClassAPI(refClassAPI);
+          if (currClassAPI.sizeMethodAPIs() == 0 && currClassAPI.sizeFieldAPIs() == 0)
+            currPkgAPI.removeClassAPI(currClassAPI);
+          break;
+        }
+      }
+    }
+    if (currPkgAPI.sizeClassAPI() > 0)
+      apiCompatibility.addNewAPI(currPkgAPI);
+    if (refPkgAPI.sizeClassAPI() > 0)
+      apiCompatibility.addRemovedAPI(refPkgAPI);
+  }
+
+  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()))
+        {
+          currClassAPI.removeMethodAPI(currMethodAPI);
+          refClassAPI.removeMethodAPI(refMethodAPI);
+          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()))
+        {
+          currClassAPI.removeFieldAPI(currFieldAPI);
+          refClassAPI.removeFieldAPI(refFieldAPI);
+          break;
+        }
+      }
+    }
+  }
+
+  private void genHTML()
+  {
+    final StringBuffer summary = new StringBuffer();
+    summary.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    summary.append("<root>");
+    ILocation outputLoc = Location.createLocation(new File(outputDir));
+    outputLoc.accept(new ILocationVisitor()
+    {
+      public boolean accept(ILocation location)
+      {
+        if (location.getName().endsWith("api-comp.xml"))
+        {
+          try
+          {
+            XSLUtil.transform
+            (
+              xsl != null && xsl.length() > 0 ? Location.createLocation(new File(xsl)).getInputStream() : ClassLoader.getSystemResourceAsStream("org/eclipse/wtp/releng/tools/component/xsl/api-comp.xsl"),
+              location.getInputStream(),
+              new FileOutputStream(((FileLocation)location.createSibling("api-comp.html")).getFile())
+            );
+            summary.append("<api-comp file=\"");
+            summary.append(location.getAbsolutePath().substring(outputDir.length()));
+            summary.append("\"/>");
+          }
+          catch (Throwable e)
+          {
+            e.printStackTrace();
+          }
+        }
+        return true;
+      }
+    });
+    summary.append("</root>");
+    try
+    {
+      XSLUtil.transform
+      (
+        ClassLoader.getSystemResourceAsStream("org/eclipse/wtp/releng/tools/component/xsl/api-comp-summary.xsl"),
+        new ByteArrayInputStream(summary.toString().getBytes()),
+        new FileOutputStream(new File(outputDir + "/api-comp-summary.html")),
+        outputDir
+      );
+    }
+    catch (Throwable e)
+    {
+      e.printStackTrace();
+    }
+  }
+
+  protected static String addTrailingSeperator(String s)
+  {
+    if (s != null && !s.endsWith("/") && !s.endsWith("\\"))
+    {
+      StringBuffer sb = new StringBuffer(s);
+      sb.append('/');
+      return sb.toString();
+    }
+    else
+    {
+      return s;
+    }
+  }
+
+  public static void main(String[] args)
+  {
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    Collection api = (Collection)options.get("api");
+    Collection src = (Collection)options.get("src");
+    Collection refapi = (Collection)options.get("refapi");
+    Collection refsrc = (Collection)options.get("refsrc");
+    Collection outputDir = (Collection)options.get("outputDir");
+    Collection includes = (Collection)options.get("includes");
+    Collection excludes = (Collection)options.get("excludes");
+    Collection html = (Collection)options.get("html");
+    Collection xsl = (Collection)options.get("xsl");
+    if (src == null || api == null || outputDir == null || src.isEmpty() || api.isEmpty() || outputDir.isEmpty())
+    {
+      printUsage();
+      System.exit(-1);
+    }
+    String od = addTrailingSeperator((String)outputDir.iterator().next());
+    String currOutputDir = od + "1/";
+    String refOutputDir = od + "2/";
+    API2ComponentAPI api2CompAPI = new API2ComponentAPI();
+    api2CompAPI.setApi(api);
+    api2CompAPI.setSrc(src);
+    api2CompAPI.setOutputDir(currOutputDir);
+    api2CompAPI.setIncludes(includes);
+    api2CompAPI.setExcludes(excludes);
+    api2CompAPI.execute();
+    api2CompAPI = new API2ComponentAPI();
+    api2CompAPI.setApi(refapi);
+    api2CompAPI.setSrc(refsrc);
+    api2CompAPI.setOutputDir(refOutputDir);
+    api2CompAPI.setIncludes(includes);
+    api2CompAPI.setExcludes(excludes);
+    api2CompAPI.execute();
+    APICompatibilityScanner scanner = new APICompatibilityScanner();
+    scanner.setOutputDir((String)outputDir.iterator().next());
+    scanner.setHtml(html != null);
+    scanner.setXsl(xsl != null && !xsl.isEmpty() ? (String)xsl.iterator().next() : null);
+    scanner.execute();
+  }
+
+  private static void printUsage()
+  {
+    System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.api.compatibility.APICompatibilityScanner -api <api> -src <src> -refapi <refapi> -refsrc <refsrc> -outputDir <outputDir> [-options]");
+    System.out.println("");
+    System.out.println("\t-api\t\t<api>\t\tlocation of your component.xml");
+    System.out.println("\t-src\t\t<src>\t\tlocation of your Eclipse-based product");
+    System.out.println("\t-refapi\t\t<refapi>\t\tlocation of your reference component.xml");
+    System.out.println("\t-refsrc\t\t<refsrc>\t\tlocation of your reference Eclipse-based product");
+    System.out.println("\t-outputDir\t<outputDir>\toutput directory");
+    System.out.println("");
+    System.out.println("where options include:");
+    System.out.println("");
+    System.out.println("\t-includes\t<includes>\tspace seperated packages to include");
+    System.out.println("\t-excludes\t<excludes>\tspace seperated packages to exclude");
+    System.out.println("\t-html\t\t\t\tgenerate HTML results");
+    System.out.println("\t-xsl\t<xsl>\t\tuse your own stylesheet. You must specify the -html option");
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/compatibility/APICompatibilitySummary.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/compatibility/APICompatibilitySummary.java
new file mode 100644
index 0000000..2014832
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/compatibility/APICompatibilitySummary.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * 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.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import org.eclipse.wtp.releng.tools.component.IFileLocation;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentEntry;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentSummary;
+
+public class APICompatibilitySummary extends ComponentSummary
+{
+  private static final String ROOT_TAG_NAME = "api-compatibility-summary";
+
+  public void add(APICompatibility apiCompatibility)
+  {
+    APICompatibilityEntry entry = new APICompatibilityEntry();
+    entry.setCompName(apiCompatibility.getName());
+    entry.setNewAPICount(apiCompatibility.getNewAPIs().size());
+    entry.setRemovedAPICount(apiCompatibility.getRemovedAPIs().size());
+    String ref = apiCompatibility.getLocation().getAbsolutePath();
+    entry.setRef(ref);
+    add(entry);
+  }
+
+  public void saveAsHTML(ILocation html) throws TransformerConfigurationException, TransformerException, IOException
+  {
+    String user_dir = "user.dir";
+    String currUserDir = System.getProperty(user_dir);
+    System.setProperty(user_dir, ((IFileLocation)html).getFile().getParentFile().getAbsolutePath());
+    TransformerFactory factory = TransformerFactory.newInstance();
+    Transformer transformer = factory.newTransformer(new StreamSource(ClassLoader.getSystemResourceAsStream("org/eclipse/wtp/releng/tools/component/xsl/api-compatibility-summary.xsl")));
+    transformer.transform(new StreamSource(new ByteArrayInputStream(getBytes(html, ROOT_TAG_NAME))), new StreamResult(new FileOutputStream(new File(html.getAbsolutePath()))));
+    System.setProperty(user_dir, currUserDir);
+  }
+
+  public void save(ILocation location) throws IOException
+  {
+    save(location, ROOT_TAG_NAME);
+  }
+
+  private class APICompatibilityEntry extends ComponentEntry
+  {
+    private int newAPICount;
+    private int removedAPICount;
+
+    public APICompatibilityEntry()
+    {
+      newAPICount = 0;
+      removedAPICount = 0;
+    }
+
+    public String toString()
+    {
+      StringBuffer sb = new StringBuffer();
+      sb.append("<api-compatibility ");
+      sb.append(toAttribute("name", getCompName()));
+      sb.append(toAttribute("new-api-count", String.valueOf(newAPICount)));
+      sb.append(toAttribute("removed-api-count", String.valueOf(removedAPICount)));
+      sb.append(toAttribute("ref", getRef()));
+      sb.append("/>");
+      return sb.toString();
+    }
+
+    /**
+     * @return Returns the newAPICount.
+     */
+    public int getNewAPICount()
+    {
+      return newAPICount;
+    }
+
+    /**
+     * @param newAPICount The newAPICount to set.
+     */
+    public void setNewAPICount(int newAPICount)
+    {
+      this.newAPICount = newAPICount;
+    }
+
+    /**
+     * @return Returns the removedAPICount.
+     */
+    public int getRemovedAPICount()
+    {
+      return removedAPICount;
+    }
+
+    /**
+     * @param removedAPICount The removedAPICount to set.
+     */
+    public void setRemovedAPICount(int removedAPICount)
+    {
+      this.removedAPICount = removedAPICount;
+    }
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIProgressEmitter.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIProgressEmitter.java
new file mode 100644
index 0000000..ea6f8f9
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIProgressEmitter.java
@@ -0,0 +1,621 @@
+/*******************************************************************************
+ * 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.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.wtp.releng.tools.component.CommandOptionParser;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.internal.AbstractEmitter;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentXML;
+import org.eclipse.wtp.releng.tools.component.internal.Description;
+import org.eclipse.wtp.releng.tools.component.internal.FileLocation;
+import org.eclipse.wtp.releng.tools.component.internal.Plugin;
+import org.xml.sax.SAXException;
+
+public class APIProgressEmitter extends AbstractEmitter
+{
+  public static final String OPTION_COMPONENT_INDEX = "compIndex";
+  public static final String OPTION_REF_COMP_INDEX_DIR = "refCompIndexDir";
+  public static final String OPTION_ECLIPSE_DIR = "eclipseDir";
+  public static final String OPTION_COMPONENT_XML = "compXMLDir";
+  public static final String OPTION_OUTPUT_DIR = "outputDir";
+  private static final String NAME_INDEX_COMP_SUMMARY = "index-comp-summary.xml";
+
+  private String compIndex;
+  private List refCompIndexDirs;
+  private List eclipseDirs;
+  private List compXMLDirs;
+  private String outputDir;
+
+  public APIProgressEmitter(String compIndex, List refCompIndexDirs, List eclipseDirs, List compXMLDirs, String outputDir)
+  {
+    this.compIndex = compIndex;
+    this.refCompIndexDirs = refCompIndexDirs;
+    this.eclipseDirs = eclipseDirs;
+    this.compXMLDirs = compXMLDirs;
+    this.outputDir = addTrailingSeperator(outputDir);
+  }
+
+  public void genAPIProgress() throws ParserConfigurationException, SAXException, IOException, TransformerConfigurationException, TransformerException
+  {
+    Map loc2RefCompIndex = new HashMap();
+    if (refCompIndexDirs != null)
+    {
+      for (Iterator it = refCompIndexDirs.iterator(); it.hasNext();)
+      {
+        File refCompIndexFile = new File(addTrailingSeperator((String)it.next()));
+        if (refCompIndexFile.exists())
+          harvestCompIndexes(refCompIndexFile, loc2RefCompIndex);
+      }
+    }
+    Map pluginId2Plugin = new HashMap();
+    Map fragmentId2Fragment = new HashMap();
+    for (Iterator it = eclipseDirs.iterator(); it.hasNext();)
+    {
+      File eclipseFile = new File(addTrailingSeperator((String)it.next()));
+      if (eclipseFile.exists())
+        harvestPlugins(eclipseFile, pluginId2Plugin, fragmentId2Fragment);
+    }
+    Map compLoc2CompXML = new HashMap();
+    for (Iterator it = compXMLDirs.iterator(); it.hasNext();)
+    {
+      File compXMLFile = new File(addTrailingSeperator((String)it.next()));
+      if (compXMLFile.exists())
+        harvestComponents(compXMLFile, compLoc2CompXML);
+    }
+    APIProgressSummary summary = new APIProgressSummary();
+    summary.load(new FileLocation(new File(compIndex)));
+    List pluginsDeclared = new ArrayList();
+    List missingPlugins = new ArrayList();
+    List dupPlugins = new ArrayList();
+    for (Iterator it = compLoc2CompXML.values().iterator(); it.hasNext();)
+    {
+      ComponentXML compXML = (ComponentXML)it.next();
+      compXML.load();
+      APIProgressEntry entry = (APIProgressEntry)summary.getEntry(compXML.getName());
+      if (entry != null)
+      {
+        Description desc = compXML.getDescription();
+        if (desc != null)
+        {
+          entry.setOverviewDoc(desc.getUrl());
+        }
+      }
+      Collection plugins = compXML.getPlugins();
+      for (Iterator pluginIt = plugins.iterator(); pluginIt.hasNext();)
+      {
+        Plugin plugin = (Plugin)pluginIt.next();
+        String pluginId = plugin.getId();
+        if (pluginsDeclared.contains(pluginId))
+        {
+          dupPlugins.add(pluginId);
+        }
+        else if (plugin.isFragment())
+        {
+          if (!fragmentId2Fragment.containsKey(pluginId))
+          {
+            missingPlugins.add(pluginId);
+          }
+        }
+        else
+        {
+          if (!pluginId2Plugin.containsKey(pluginId))
+          {
+            missingPlugins.add(pluginId);
+          }
+        }
+        pluginsDeclared.add(pluginId);
+      }
+    }
+    summary.addMissingPlugins(missingPlugins);
+    summary.addDupPlugins(dupPlugins);
+    List pluginsWithoutComp = new ArrayList();
+    for (Iterator it = pluginId2Plugin.keySet().iterator(); it.hasNext();)
+    {
+      String pluginId = (String)it.next();
+      if (!hasPlugin(pluginId, false, compLoc2CompXML))
+      {
+        pluginsWithoutComp.add(pluginId);
+      }
+    }
+    for (Iterator it = fragmentId2Fragment.keySet().iterator(); it.hasNext();)
+    {
+      String fragmentId = (String)it.next();
+      if (!hasPlugin(fragmentId, true, compLoc2CompXML))
+      {
+        pluginsWithoutComp.add(fragmentId);
+      }
+    }
+    summary.addPluginsWithoutComp(pluginsWithoutComp);
+    List loaders = new ArrayList();
+    for (Iterator it = summary.getEntries().iterator(); it.hasNext();)
+    {
+      APIProgressEntry entry = (APIProgressEntry)it.next();
+      if (entry.getOverviewDoc() == null)
+      {
+        OverviewDocLoader loader = new OverviewDocLoader(entry);
+        loader.start();
+        loaders.add(loader);
+      }
+    }
+    for (Iterator it = loaders.iterator(); it.hasNext();)
+    {
+      ((OverviewDocLoader)it.next()).waitFor();
+    }
+    copyImages();
+    for (Iterator it = summary.getEntries().iterator(); it.hasNext();)
+      genAPIProgress(compIndex, (APIProgressEntry)it.next(), summary.getTimestamp(), loc2RefCompIndex, outputDir);
+    genAPIProgress(compIndex, summary.getTimestamp(), loc2RefCompIndex, outputDir);
+    xslt(summary.toString(), "org/eclipse/wtp/releng/tools/component/xsl/api-progress.xsl", outputDir + "api-progress.html");
+  }
+
+  private void genAPIProgress(String baseLocation, APIProgressEntry entry, String timestamp, Map loc2RefCompIndex, String outputDir)
+  {
+    StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    String compName = entry.getCompName();
+    sb.append("<component name=\"");
+    sb.append(compName);
+    sb.append("\">");
+    List sortedTimestamps = new ArrayList();
+    List sortedSummaries = new ArrayList();
+    for (Iterator it = loc2RefCompIndex.keySet().iterator(); it.hasNext();)
+    {
+      ILocation location = (ILocation)it.next();
+      String absPath = location.getAbsolutePath();
+      APIProgressSummary summary = (APIProgressSummary)loc2RefCompIndex.get(location);
+      String summaryTimestamp = summary.getTimestamp();
+      int insertIndex = sortedTimestamps.size();
+      try
+      {
+        Integer thisTimestamp = Integer.valueOf(summaryTimestamp);
+        while (insertIndex > 0)
+        {
+          Integer i = (Integer)sortedTimestamps.get(insertIndex - 1);
+          if (thisTimestamp.intValue() > i.intValue())
+            break;
+          else
+            insertIndex--;
+        }
+        sortedTimestamps.add(insertIndex, thisTimestamp);
+      }
+      catch (NumberFormatException e)
+      {
+        e.printStackTrace();
+      }
+      sortedSummaries.add(insertIndex, toString(absPath, summaryTimestamp));
+    }
+    for (Iterator it = sortedSummaries.iterator(); it.hasNext();)
+      sb.append((String)it.next());
+    sb.append(toString(baseLocation, timestamp));
+    sb.append("</component>");
+    try
+    {
+      StringBuffer output = new StringBuffer(outputDir);
+      output.append("svg/");
+      output.append(compName);
+      output.append(".svg");
+      xslt(sb.toString(), "org/eclipse/wtp/releng/tools/component/xsl/api-progress-svg.xsl", output.toString());
+    }
+    catch (Throwable t)
+    {
+      t.printStackTrace();
+    }
+  }
+
+  private void genAPIProgress(String baseLocation, String timestamp, Map loc2RefCompIndex, String outputDir)
+  {
+    StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    sb.append("<total>");
+    List sortedTimestamps = new ArrayList();
+    List sortedTotals = new ArrayList();
+    for (Iterator it = loc2RefCompIndex.keySet().iterator(); it.hasNext();)
+    {
+      ILocation location = (ILocation)it.next();
+      String absPath = location.getAbsolutePath();
+      APIProgressSummary summary = (APIProgressSummary)loc2RefCompIndex.get(location);
+      String summaryTimestamp = summary.getTimestamp();
+      int insertIndex = sortedTimestamps.size();
+      try
+      {
+        Integer thisTimestamp = Integer.valueOf(summaryTimestamp);
+        while (insertIndex > 0)
+        {
+          Integer i = (Integer)sortedTimestamps.get(insertIndex - 1);
+          if (thisTimestamp.intValue() > i.intValue())
+            break;
+          else
+            insertIndex--;
+        }
+        sortedTimestamps.add(insertIndex, thisTimestamp);
+      }
+      catch (NumberFormatException e)
+      {
+        e.printStackTrace();
+      }
+      sortedTotals.add(insertIndex, toStringTotal(absPath, summaryTimestamp));
+    }
+    for (Iterator it = sortedTotals.iterator(); it.hasNext();)
+      sb.append((String)it.next());
+    sb.append(toStringTotal(baseLocation, timestamp));
+    sb.append("</total>");
+    try
+    {
+      StringBuffer output = new StringBuffer(outputDir);
+      output.append("svg/total.svg");
+      xslt(sb.toString(), "org/eclipse/wtp/releng/tools/component/xsl/api-progress-svg-total.xsl", output.toString());
+    }
+    catch (Throwable t)
+    {
+      t.printStackTrace();
+    }
+  }
+
+  private void xslt(String content, String xsl, String output) throws SAXException, ParserConfigurationException, TransformerConfigurationException, TransformerException, FileNotFoundException
+  {
+    File outputFile = new File(output);
+    outputFile.getParentFile().mkdirs();
+    xslt(new ByteArrayInputStream(content.getBytes()), xsl, new FileOutputStream(outputFile));
+  }
+
+  private void xslt(InputStream is, String xsl, OutputStream os) throws SAXException, ParserConfigurationException, TransformerConfigurationException, TransformerException, FileNotFoundException
+  {
+    String user_dir = "user.dir";
+    String currUserDir = System.getProperty(user_dir);
+    System.setProperty(user_dir, (new File(compIndex)).getParentFile().getAbsolutePath());
+    TransformerFactory factory = TransformerFactory.newInstance();
+    Transformer transformer = factory.newTransformer(new StreamSource(ClassLoader.getSystemResourceAsStream(xsl)));
+    transformer.transform(new StreamSource(is), new StreamResult(os));
+    System.setProperty(user_dir, currUserDir);
+  }
+
+  private String toString(String baseLocation, String timestamp)
+  {
+    baseLocation = toAbsolutePath(baseLocation);
+    StringBuffer sb = new StringBuffer("<timestamp id=\"");
+    sb.append(timestamp);
+    sb.append("\">");
+    sb.append("<testcoverage ref=\"");
+    sb.append(baseLocation + "index-api-tc.xml");
+    sb.append("\"/>");
+    sb.append("<javadoccoverage ref=\"");
+    sb.append(baseLocation + "index-api-javadoc.xml");
+    sb.append("\"/>");
+    sb.append("</timestamp>");
+    return sb.toString();
+  }
+
+  private String toStringTotal(String baseLocation, String timestamp)
+  {
+    baseLocation = toAbsolutePath(baseLocation);
+    StringBuffer sb = new StringBuffer();
+    try
+    {
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      xslt(new FileInputStream(baseLocation + "index-api-tc.xml"), "org/eclipse/wtp/releng/tools/component/xsl/component-api-util.xsl", baos);
+      Properties p = new Properties();
+      p.load(new ByteArrayInputStream(baos.toByteArray()));
+      String apiCount = p.getProperty("api-count");
+      String testCoverageCount = p.getProperty("test-coverage-count");
+
+      baos = new ByteArrayOutputStream();
+      xslt(new FileInputStream(baseLocation + "index-api-javadoc.xml"), "org/eclipse/wtp/releng/tools/component/xsl/component-api-util.xsl", baos);
+      p = new Properties();
+      p.load(new ByteArrayInputStream(baos.toByteArray()));
+      String methodApiCount = p.getProperty("method-api-count");
+      String classJavadocCount = p.getProperty("class-javadoc-count");
+      String methodJavadocCount = p.getProperty("method-javadoc-count");
+
+      sb.append("<timestamp id=\"");
+      sb.append(timestamp);
+      sb.append("\"");
+      sb.append(" api-count=\"");
+      sb.append(apiCount);
+      sb.append("\"");
+      sb.append(" test-coverage-count=\"");
+      sb.append(testCoverageCount);
+      sb.append("\"");
+      sb.append(" method-api-count=\"");
+      sb.append(methodApiCount);
+      sb.append("\"");
+      sb.append(" class-javadoc-count=\"");
+      sb.append(classJavadocCount);
+      sb.append("\"");
+      sb.append(" method-javadoc-count=\"");
+      sb.append(methodJavadocCount);
+      sb.append("\"");
+      sb.append("/>");
+    }
+    catch (Throwable t)
+    {
+      t.printStackTrace();
+    }
+    return sb.toString();
+  }
+
+  private String toAbsolutePath(String s)
+  {
+    s = s.replace('\\', '/');
+    int i = s.lastIndexOf('/');
+    if (i != -1)
+      s = s.substring(0, i);
+    s = addTrailingSeperator(s);
+    return s;
+  }
+
+  private void harvestCompIndexes(File file, Map loc2RefCompIndex)
+  {
+    if (file.isDirectory())
+    {
+      File[] files = file.listFiles();
+      for (int i = 0; i < files.length; i++)
+        harvestCompIndexes(files[i], loc2RefCompIndex);
+    }
+    else if (NAME_INDEX_COMP_SUMMARY.equalsIgnoreCase(file.getName()))
+    {
+      APIProgressSummary summary = new APIProgressSummary();
+      try
+      {
+        ILocation location = new FileLocation(file);
+        summary.load(location);
+        loc2RefCompIndex.put(location, summary);
+      }
+      catch (IOException e)
+      {
+        e.printStackTrace();
+      }
+      catch (SAXException e)
+      {
+        e.printStackTrace();
+      }
+      catch (ParserConfigurationException e)
+      {
+        e.printStackTrace();
+      }
+    }
+  }
+
+  private boolean hasPlugin(String pluginId, boolean isFragment, Map compLoc2CompXML)
+  {
+    for (Iterator compXMLIt = compLoc2CompXML.values().iterator(); compXMLIt.hasNext();)
+    {
+      ComponentXML compXML = (ComponentXML)compXMLIt.next();
+      Collection plugins = compXML.getPlugins();
+      for (Iterator pluginIt = plugins.iterator(); pluginIt.hasNext();)
+      {
+        Plugin plugin = (Plugin)pluginIt.next();
+        if (pluginId.equals(plugin.getId()) && isFragment == plugin.isFragment())
+        {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  private void copyImages()
+  {
+    try
+    {
+      copyImage("org/eclipse/wtp/releng/tools/component/images/green.gif", new File(outputDir + "green.gif"));
+    }
+    catch (IOException e)
+    {
+      e.printStackTrace();
+    }
+    try
+    {
+      copyImage("org/eclipse/wtp/releng/tools/component/images/grey.gif", new File(outputDir + "grey.gif"));
+    }
+    catch (IOException e)
+    {
+      e.printStackTrace();
+    }
+    try
+    {
+      copyImage("org/eclipse/wtp/releng/tools/component/images/Idea.jpg", new File(outputDir + "Idea.jpg"));
+    }
+    catch (IOException e)
+    {
+      e.printStackTrace();
+    }
+    try
+    {
+      copyImage("org/eclipse/wtp/releng/tools/component/images/orange.gif", new File(outputDir + "orange.gif"));
+    }
+    catch (IOException e)
+    {
+      e.printStackTrace();
+    }
+    try
+    {
+      copyImage("org/eclipse/wtp/releng/tools/component/images/red.gif", new File(outputDir + "red.gif"));
+    }
+    catch (IOException e)
+    {
+      e.printStackTrace();
+    }
+    try
+    {
+      copyImage("org/eclipse/wtp/releng/tools/component/images/space.gif", new File(outputDir + "space.gif"));
+    }
+    catch (IOException e)
+    {
+      e.printStackTrace();
+    }
+    try
+    {
+      copyImage("org/eclipse/wtp/releng/tools/component/images/yellow.gif", new File(outputDir + "yellow.gif"));
+    }
+    catch (IOException e)
+    {
+      e.printStackTrace();
+    }
+    try
+    {
+      copyImage("org/eclipse/wtp/releng/tools/component/images/twistopened.gif", new File(outputDir + "twistopened.gif"));
+    }
+    catch (IOException e)
+    {
+      e.printStackTrace();
+    }
+    try
+    {
+      copyImage("org/eclipse/wtp/releng/tools/component/images/twistclosed.gif", new File(outputDir + "twistclosed.gif"));
+    }
+    catch (IOException e)
+    {
+      e.printStackTrace();
+    }
+    try
+    {
+      copyImage("org/eclipse/wtp/releng/tools/component/images/viewsvg.gif", new File(outputDir + "viewsvg.gif"));
+    }
+    catch (IOException e)
+    {
+      e.printStackTrace();
+    }
+  }
+
+  public static void main(String[] args)
+  {
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    List compIndex = (List)options.get(APIProgressEmitter.OPTION_COMPONENT_INDEX);
+    List eclipseDirs = (List)options.get(APIProgressEmitter.OPTION_ECLIPSE_DIR);
+    List compXMLDirs = (List)options.get(APIProgressEmitter.OPTION_COMPONENT_XML);
+    List outputDir = (List)options.get(APIProgressEmitter.OPTION_OUTPUT_DIR);
+    List refCompIndexDirs = (List)options.get(APIProgressEmitter.OPTION_REF_COMP_INDEX_DIR);
+    if (compIndex == null || eclipseDirs == null || compXMLDirs == null || outputDir == null || compIndex.size() < 1 || eclipseDirs.size() < 1 || compXMLDirs.size() < 1 || outputDir.size() < 1)
+    {
+      printUsage();
+      System.exit(-1);
+    }
+    APIProgressEmitter emitter = new APIProgressEmitter((String)compIndex.get(0), refCompIndexDirs, eclipseDirs, compXMLDirs, (String)outputDir.get(0));
+    try
+    {
+      emitter.genAPIProgress();
+    }
+    catch (ParserConfigurationException pce)
+    {
+      pce.printStackTrace();
+    }
+    catch (SAXException saxe)
+    {
+      saxe.printStackTrace();
+    }
+    catch (IOException ioe)
+    {
+      ioe.printStackTrace();
+    }
+    catch (TransformerConfigurationException tce)
+    {
+      tce.printStackTrace();
+    }
+    catch (TransformerException te)
+    {
+      te.printStackTrace();
+    }
+  }
+
+  private static void printUsage()
+  {
+    System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.api.progress.APIProgressEmitter -compIndex <compIndex> -eclipseDir <eclipseDir> -compXMLDir <compXMLDir> -outputDir <outputDir>");
+    System.out.println("");
+    System.out.println("\t-compIndex\t<compIndex>\tlocation of index-comp-summary.xml");
+    System.out.println("\t-eclipseDir\t<eclipseDir>\tspace seperated list of directories containing Eclipse plugins");
+    System.out.println("\t-compXMLDir\t<compXMLDir>\tspace seperated lits of directories containing component.xml files");
+    System.out.println("\t-outputDir\t<compXMLDir>\toutput directory of the API progress report");
+  }
+
+  private class OverviewDocLoader extends Thread
+  {
+    private APIProgressEntry entry;
+    private boolean done;
+
+    public OverviewDocLoader(APIProgressEntry entry)
+    {
+      this.entry = entry;
+      this.done = false;
+    }
+
+    public void run()
+    {
+      try
+      {
+        String compName = entry.getCompName();
+        String subproject = null;
+        String component = null;
+        if (compName.startsWith("org.eclipse."))
+        {
+          compName = compName.substring(12);
+          int index = compName.indexOf('.');
+          if (index != -1)
+          {
+            subproject = compName.substring(0, index);
+            component = compName.substring(index + 1);
+          }
+        }
+        if (subproject != null && component != null)
+        {
+          StringBuffer url = new StringBuffer("http://eclipse.org/webtools/");
+          url.append(subproject);
+          url.append("/components/");
+          url.append(component);
+          url.append("/overview.html");
+          URL overviewDoc = new URL(url.toString());
+          InputStream is = overviewDoc.openStream();
+          is.close();
+          entry.setOverviewDoc(url.toString());
+        }
+      }
+      catch (Throwable t)
+      {
+      }
+      finally
+      {
+        done = true;
+      }
+    }
+
+    public void waitFor()
+    {
+      long start = Calendar.getInstance().getTimeInMillis();
+      while (!done && (Calendar.getInstance().getTimeInMillis() - start) < 60000)
+        Thread.yield();
+    }
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIProgressEntry.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIProgressEntry.java
new file mode 100644
index 0000000..4e5f225
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIProgressEntry.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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 org.eclipse.wtp.releng.tools.component.internal.ComponentEntry;
+
+public class APIProgressEntry extends ComponentEntry
+{
+  private String overviewDoc;
+
+  public String getOverviewDoc()
+  {
+    return overviewDoc;
+  }
+
+  public void setOverviewDoc(String overviewDoc)
+  {
+    this.overviewDoc = overviewDoc;
+  }
+
+  public String toString()
+  {
+    StringBuffer sb = new StringBuffer();
+    sb.append("<component ");
+    sb.append(toAttribute("name", getCompName()));
+    sb.append(toAttribute("ref", getRef()));
+    if (overviewDoc != null)
+      sb.append(toAttribute("overviewDoc", overviewDoc));
+    sb.append("/>");
+    return sb.toString();
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIProgressScanner.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIProgressScanner.java
new file mode 100644
index 0000000..49a0fec
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIProgressScanner.java
@@ -0,0 +1,492 @@
+/*******************************************************************************
+ * 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.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+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 javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wtp.releng.tools.component.CommandOptionParser;
+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.api.ComponentAPI;
+import org.eclipse.wtp.releng.tools.component.api.ComponentXMLVisitor;
+import org.eclipse.wtp.releng.tools.component.api.violation.PluginVisitor;
+import org.eclipse.wtp.releng.tools.component.images.ImagesUtil;
+import org.eclipse.wtp.releng.tools.component.internal.AbstractEmitter;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentXML;
+import org.eclipse.wtp.releng.tools.component.internal.Location;
+import org.eclipse.wtp.releng.tools.component.internal.Plugin;
+import org.eclipse.wtp.releng.tools.component.xsl.XSLUtil;
+
+public class APIProgressScanner extends AbstractEmitter
+{
+  private Collection api;
+  private Collection src;
+  private String timestamp;
+  private String progressDir;
+  private String outputDir;
+  private Collection includes;
+  private Collection excludes;
+
+  public String getTimestamp()
+  {
+    return timestamp;
+  }
+
+  public void setTimestamp(String timestamp)
+  {
+    this.timestamp = timestamp;
+  }
+
+  public String getProgressDir()
+  {
+    return progressDir;
+  }
+
+  public void setProgressDir(String progressDir)
+  {
+    this.progressDir = addTrailingSeperator(progressDir);
+  }
+
+  public Collection getApi()
+  {
+    return api;
+  }
+
+  public void setApi(Collection api)
+  {
+    this.api = api;
+  }
+
+  public String getOutputDir()
+  {
+    return outputDir;
+  }
+
+  public void setOutputDir(String outputDir)
+  {
+    this.outputDir = addTrailingSeperator(outputDir);
+  }
+
+  public Collection getSrc()
+  {
+    return src;
+  }
+
+  public void setSrc(Collection src)
+  {
+    this.src = src;
+  }
+
+  public Collection getIncludes()
+  {
+    return includes;
+  }
+
+  public void setIncludes(Collection includes)
+  {
+    this.includes = includes;
+  }
+
+  public Collection getExcludes()
+  {
+    return excludes;
+  }
+
+  public void setExcludes(Collection excludes)
+  {
+    this.excludes = excludes;
+  }
+
+  public void execute()
+  {
+    genAPIInfoSummary();
+    if (timestamp != null && progressDir != null)
+      genSVG();
+  }
+
+  private void genAPIInfoSummary()
+  {
+    final StringBuffer apiProgress = new StringBuffer();
+    apiProgress.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    apiProgress.append("<root>");
+    if (src != null && api != null)
+      apiProgress.append(validatePlugins());
+    ILocation loc = Location.createLocation(new File(outputDir));
+    loc.accept(
+    new ILocationVisitor()
+    {
+      public boolean accept(ILocation location)
+      {
+        if (location.getName().endsWith("api-info.xml"))
+        {
+          apiProgress.append("<api-info file=\"./");
+          apiProgress.append(location.getAbsolutePath().substring(outputDir.length()));
+          try
+          {
+            ComponentAPI compAPI = new ComponentAPI();
+            compAPI.setLocation(location);
+            compAPI.load();
+            String id = compAPI.getName();
+            if (id != null)
+            {
+              String compName = (String)pluginId2CompName.get(id);
+              if (compName != null)
+              {
+                OverviewDocLoader loader = new OverviewDocLoader(compName);
+                String url = loader.getOverviewDocURL();
+                if (url != null)
+                {
+                  apiProgress.append("\" overviewDoc=\"");
+                  apiProgress.append(url);
+                }
+              }
+            }
+          }
+          catch (Throwable t)
+          {
+          }
+          apiProgress.append("\"/>");
+        }
+        return true;
+      }
+    });
+    apiProgress.append("</root>");
+    try
+    {
+      ImagesUtil.copyAll(outputDir);
+      XSLUtil.transform
+      (
+        ClassLoader.getSystemResourceAsStream("org/eclipse/wtp/releng/tools/component/xsl/api-progress.xsl"),
+        new ByteArrayInputStream(apiProgress.toString().getBytes()),
+        new FileOutputStream(new File(outputDir + "api-progress.html")),
+        outputDir
+      );
+      XSLUtil.transform
+      (
+        ClassLoader.getSystemResourceAsStream("org/eclipse/wtp/releng/tools/component/xsl/api-progress-summary.xsl"),
+        new ByteArrayInputStream(apiProgress.toString().getBytes()),
+        new FileOutputStream(new File(outputDir + "api-info-summary.xml")),
+        outputDir
+      );
+    }
+    catch (Throwable e)
+    {
+      try
+      {
+        XSLUtil.transform
+        (
+          Platform.getBundle("org.eclipse.wtp.releng.tools.component.core").getResource("org/eclipse/wtp/releng/tools/component/xsl/api-progress.xsl").openStream(),
+          new ByteArrayInputStream(apiProgress.toString().getBytes()),
+          new FileOutputStream(new File(outputDir + "api-progress.html")),
+          outputDir
+        );
+        XSLUtil.transform
+        (
+          Platform.getBundle("org.eclipse.wtp.releng.tools.component.core").getResource("org/eclipse/wtp/releng/tools/component/xsl/api-progress-summary.xsl").openStream(),
+          new ByteArrayInputStream(apiProgress.toString().getBytes()),
+          new FileOutputStream(new File(outputDir + "api-info-summary.xml")),
+          outputDir
+        );
+      }
+      catch (Throwable e2)
+      {
+        e2.printStackTrace();
+      }
+    }
+  }
+
+  private Map pluginId2CompName = new HashMap();
+
+  private String validatePlugins()
+  {
+    StringBuffer sb = new StringBuffer();
+    List pluginsWithoutComp = new ArrayList();
+    List pluginsNotFoundInSrc = new ArrayList();
+    List pluginsInMoreThan1Comp = new ArrayList();
+    List pluginIds = new ArrayList();
+
+    // Collection component.xml files
+    for (Iterator i = api.iterator(); i.hasNext();)
+    {
+      ILocation apiLocation = Location.createLocation(new File((String)i.next()));
+      ComponentXMLVisitor compXMLVisitor = new ComponentXMLVisitor();
+      apiLocation.accept(compXMLVisitor);
+      for (Iterator it = compXMLVisitor.getCompXMLs().iterator(); it.hasNext();)
+      {
+        ComponentXML compXML = (ComponentXML)it.next();
+        String compName = compXML.getName();
+        for (Iterator it2 = compXML.getPlugins().iterator(); it2.hasNext();)
+        {
+          String id = ((Plugin)it2.next()).getId();
+          pluginId2CompName.put(id, compName);
+          if (pluginIds.contains(id))
+            pluginsInMoreThan1Comp.add(id);
+          else
+            pluginIds.add(id);
+        }
+      }
+    }
+
+    // Visit Src
+    for (Iterator it = src.iterator(); it.hasNext();)
+    {
+      ILocation srcLocation = Location.createLocation(new File((String)it.next()));
+      PluginVisitor v = new PluginVisitor();
+      srcLocation.accept(v);
+      for (Iterator it2 = v.getPluginIds().iterator(); it2.hasNext();)
+      {
+        String id = (String)it2.next();
+        if (!pluginIds.remove(id))
+        {
+          if (include(id))
+          {
+            pluginsWithoutComp.add(id);
+          }
+        }
+      }
+    }
+    for (Iterator it = pluginIds.iterator(); it.hasNext();)
+      pluginsNotFoundInSrc.add((String)it.next());
+
+    // Print results
+    for (Iterator it = pluginsWithoutComp.iterator(); it.hasNext();)
+    {
+      sb.append("<plugin-without-comp id=\"");
+      sb.append((String)it.next());
+      sb.append("\"/>");
+    }
+    for (Iterator it = pluginsNotFoundInSrc.iterator(); it.hasNext();)
+    {
+      sb.append("<missing-plugin id=\"");
+      sb.append((String)it.next());
+      sb.append("\"/>");
+    }
+    for (Iterator it = pluginsInMoreThan1Comp.iterator(); it.hasNext();)
+    {
+      sb.append("<dup-plugin id=\"");
+      sb.append((String)it.next());
+      sb.append("\"/>");
+    }
+    return sb.toString();
+  }
+
+  private void genSVG()
+  {
+    File src = new File(outputDir + "api-info-summary.xml");
+    File dest = new File(progressDir + timestamp + "/api-info-summary.xml");
+    try
+    {
+      copy(src, dest);
+    }
+    catch (IOException ioe)
+    {
+      ioe.printStackTrace();
+    }
+    final StringBuffer content = new StringBuffer();
+    content.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    content.append("<root name=\"#name\">");
+    ILocation progress = Location.createLocation(new File(progressDir));
+    ILocationChildrenIterator it = progress.childIterator();
+    ILocation child = it.next();
+    while (child != null)
+    {
+      content.append("<summary timestamp=\"");
+      content.append(child.getName());
+      content.append("\"/>");
+      child = it.next();
+    }
+    content.append("</root>");
+    ILocation loc = Location.createLocation(new File(outputDir));
+    loc.accept(
+    new ILocationVisitor()
+    {
+      public boolean accept(ILocation location)
+      {
+        if (location.getName().endsWith("api-info.xml"))
+        {
+          try
+          {
+            ComponentAPI compAPI = new ComponentAPI();
+            compAPI.setLocation(location);
+            compAPI.load();
+            String compName = compAPI.getName();
+            StringBuffer sb = new StringBuffer();
+            sb.append(outputDir);
+            sb.append("svg/");
+            new File(sb.toString()).mkdirs();
+            genSVG(content.toString(), compName, sb.toString());
+          }
+          catch (Throwable t)
+          {
+            t.printStackTrace();
+          }
+        }
+        return true;
+      }
+    });
+    try
+    {
+      genSVG(content.toString(), "total", outputDir + "svg/");
+    }
+    catch (Throwable t)
+    {
+      t.printStackTrace();
+    }
+  }
+
+  private void genSVG(String content, String name, String outDir) throws IOException, TransformerConfigurationException, TransformerException
+  {
+    XSLUtil.transform
+    (
+      ClassLoader.getSystemResourceAsStream("org/eclipse/wtp/releng/tools/component/xsl/api-progress-svg.xsl"),
+      new ByteArrayInputStream(content.replaceAll("#name", name).getBytes()),
+      new FileOutputStream(outDir + name + ".svg"),
+      progressDir
+    );
+  }
+
+  private void copy(File src, File dest) throws IOException
+  {
+    dest.getParentFile().mkdirs();
+    FileOutputStream fos = new FileOutputStream(dest);
+    FileInputStream fis = new FileInputStream(src);
+    byte[] b = new byte[2048];
+    int read = fis.read(b);
+    while (read != -1)
+    {
+      fos.write(b, 0, read);
+      read = fis.read(b);
+    }
+    fis.close();
+    fos.close();
+  }
+
+  private boolean include(String name)
+  {
+    name = name.replace('/', '.');
+    name = name.replace('\\', '.');
+    if (excludes != null && !excludes.isEmpty())
+      for (Iterator it = excludes.iterator(); it.hasNext();)
+        if (name.matches((String)it.next()))
+          return false;
+    if (includes != null && !includes.isEmpty())
+    {
+      for (Iterator it = includes.iterator(); it.hasNext();)
+        if (name.matches((String)it.next()))
+          return true;
+      return false;
+    }
+    return true;
+  }
+
+  public static void main(String[] args)
+  {
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    List api = (List)options.get("api");
+    List src = (List)options.get("src");
+    List timestamp = (List)options.get("timestamp");
+    List progressDir = (List)options.get("progressDir");
+    List outputDir = (List)options.get("outputDir");
+    Collection includes = (Collection)options.get("includes");
+    Collection excludes = (Collection)options.get("excludes");
+    if (outputDir == null || outputDir.size() < 1)
+    {
+      printUsage();
+      System.exit(-1);
+    }
+    APIProgressScanner scanner = new APIProgressScanner();
+    if (api != null && api.size() > 0)
+      scanner.setApi(api);
+    if (src != null && src.size() > 0)
+      scanner.setSrc(src);
+    if (timestamp != null && timestamp.size() > 0)
+      scanner.setTimestamp((String)timestamp.iterator().next());
+    if (progressDir != null && progressDir.size() > 0)
+      scanner.setProgressDir((String)progressDir.iterator().next());
+    scanner.setOutputDir((String)outputDir.iterator().next());
+    scanner.setIncludes(includes);
+    scanner.setExcludes(excludes);
+    scanner.execute();
+  }
+
+  private static void printUsage()
+  {
+    System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.api.progress.APIProgressScanner -compIndex <compIndex> -eclipseDir <eclipseDir> -compXMLDir <compXMLDir> -outputDir <outputDir>");
+    System.out.println("");
+    System.out.println("\t-outputDir\t<outputDir>\toutput directory of component.xml files");
+    System.out.println("");
+    System.out.println("where options include:");
+    System.out.println("");
+    System.out.println("\t-api\t\t<api>\t\tlocation of your component.xml");
+    System.out.println("\t-src\t\t<src>\t\tlocation of a Eclipse-based product");
+    System.out.println("\t-timestamp\t<timestamp>\ttimestamp");
+    System.out.println("\t-progressDir\t<progressDir>\tdirectory containing API progress documents");
+    System.out.println("\t-includes\t<includes>\tspace seperated plug-ins to include");
+    System.out.println("\t-excludes\t<excludes>\tspace seperated plug-ins to exclude");
+  }
+
+  private class OverviewDocLoader
+  {
+    private String componentName;
+
+    public OverviewDocLoader(String componentName)
+    {
+      this.componentName = componentName;
+    }
+
+    public String getOverviewDocURL()
+    {
+      InputStream is = null;
+      try
+      {
+        StringBuffer url = new StringBuffer("http://www.eclipse.org/webtools/components/");
+        url.append(componentName);
+        url.append("/");
+        URL overviewDoc = new URL(url.toString());
+        is = overviewDoc.openStream();
+        return url.toString();
+      }
+      catch (Throwable t)
+      {
+      }
+      finally
+      {
+        try
+        {
+          if (is != null)
+            is.close();
+        }
+        catch (Throwable t)
+        {
+          t.printStackTrace();
+        }
+      }
+      return null;
+    }
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIProgressSummary.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIProgressSummary.java
new file mode 100644
index 0000000..2a6290a
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIProgressSummary.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * 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.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.eclipse.wtp.releng.tools.component.ILocation;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentSummary;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class APIProgressSummary extends ComponentSummary
+{
+  private List pluginsWithoutComp;
+  private List missingPlugins;
+  private List dupPlugins;
+
+  public APIProgressSummary()
+  {
+    super();
+  }
+
+  public void addPluginsWithoutComp(List pluginIds)
+  {
+    if (pluginsWithoutComp == null)
+      pluginsWithoutComp = new ArrayList();
+    pluginsWithoutComp.addAll(pluginIds);
+  }
+
+  public void addMissingPlugins(List pluginIds)
+  {
+    if (missingPlugins == null)
+      missingPlugins = new ArrayList();
+    missingPlugins.addAll(pluginIds);
+  }
+
+  public void addDupPlugins(List pluginIds)
+  {
+    if (dupPlugins == null)
+      dupPlugins = new ArrayList();
+    dupPlugins.addAll(pluginIds);
+  }
+
+  public void load(ILocation location) throws ParserConfigurationException, SAXException, IOException
+  {
+    SAXParserFactory factory = SAXParserFactory.newInstance();
+    factory.setNamespaceAware(false);
+    factory.setValidating(false);
+    SAXParser parser = factory.newSAXParser();
+    parser.parse(new InputSource(new BufferedInputStream(location.getInputStream())), new APIProgressSummaryHandler(this));
+  }
+
+  public String toString(String rootTagName)
+  {
+    StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    sb.append("<");
+    sb.append(rootTagName);
+    sb.append(">");
+    for (Iterator it = getEntries().iterator(); it.hasNext();)
+      sb.append(it.next().toString());
+    if (pluginsWithoutComp != null)
+      for (Iterator it = pluginsWithoutComp.iterator(); it.hasNext();)
+        sb.append("<plugin-without-comp").append(toAttribute("id", it.next().toString())).append("/>");
+    if (missingPlugins != null)
+      for (Iterator it = missingPlugins.iterator(); it.hasNext();)
+        sb.append("<missing-plugin").append(toAttribute("id", it.next().toString())).append("/>");
+    if (dupPlugins != null)
+      for (Iterator it = dupPlugins.iterator(); it.hasNext();)
+        sb.append("<dup-plugin").append(toAttribute("id", it.next().toString())).append("/>");
+    sb.append("</");
+    sb.append(rootTagName);
+    sb.append(">");
+    return sb.toString();
+  }
+
+  private String toAttribute(String key, String value)
+  {
+    StringBuffer sb = new StringBuffer();
+    if (key != null && value != null)
+    {
+      sb.append(" ");
+      sb.append(key);
+      sb.append("=\"");
+      sb.append(value);
+      sb.append("\"");
+    }
+    return sb.toString();
+  }
+
+  private class APIProgressSummaryHandler extends DefaultHandler
+  {
+    private APIProgressSummary summary;
+    
+    public APIProgressSummaryHandler(APIProgressSummary summary)
+    {
+      this.summary = summary;
+    }
+
+    public void startElement(String uri, String elementName, String qName, Attributes attributes) throws SAXException
+    {
+      final String COMPONENT = "component";
+      final String COMPONENT_SUMMARY = "component-summary";
+      if (COMPONENT.equals(elementName) || COMPONENT.equals(qName))
+      {
+        String name = attributes.getValue("name");
+        String ref = attributes.getValue("ref");
+        if (name != null && ref != null)
+        {
+          APIProgressEntry entry = new APIProgressEntry();
+          entry.setCompName(name);
+          entry.setRef(ref);
+          summary.add(entry);
+        }
+      }
+      else if (COMPONENT_SUMMARY.equals(elementName) || COMPONENT_SUMMARY.equals(qName))
+      {
+        String timestamp = attributes.getValue("timestamp");
+        summary.setTimestamp(timestamp);
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APITestCoverageEmitter.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APITestCoverageEmitter.java
new file mode 100644
index 0000000..ba89d57
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APITestCoverageEmitter.java
@@ -0,0 +1,599 @@
+/*******************************************************************************
+ * 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());
+            }
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APITestCoverageSummary.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APITestCoverageSummary.java
new file mode 100644
index 0000000..4c52e2a
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APITestCoverageSummary.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * 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.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+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.MethodAPI;
+import org.eclipse.wtp.releng.tools.component.api.PackageAPI;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentEntry;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentSummary;
+
+public class APITestCoverageSummary extends ComponentSummary
+{
+  private static final String ROOT_TAG_NAME = "component-api-tc-summary";
+  private String refFileName;
+
+  public APITestCoverageSummary(String refFileName)
+  {
+    this.refFileName = refFileName;
+  }
+
+  public void add(ComponentAPI compAPI)
+  {
+    APITestCoverageEntry entry = new APITestCoverageEntry();
+    int apiCount = 0;
+    int testCoverageCount = 0;
+    entry.setCompName(compAPI.getName());
+    for (Iterator it = compAPI.getPackageAPIs().iterator(); it.hasNext();)
+    {
+      PackageAPI pkgAPI = (PackageAPI)it.next();
+      for (Iterator classAPIsIt = pkgAPI.getClassAPIs().iterator(); classAPIsIt.hasNext();)
+      {
+        ClassAPI classAPI = (ClassAPI)classAPIsIt.next();
+        Collection methodAPIs = classAPI.getMethodAPIs();
+        apiCount += methodAPIs.size();
+        for (Iterator methodAPIsIt = methodAPIs.iterator(); methodAPIsIt.hasNext();)
+        {
+          MethodAPI methodAPI = (MethodAPI)methodAPIsIt.next();
+          if (methodAPI.countTestcases() > 0)
+            testCoverageCount++;
+        }
+      }
+    }
+    entry.setApiCount(apiCount);
+    entry.setTestCoverageCount(testCoverageCount);
+    String ref = compAPI.getLocation().getAbsolutePath();
+    int i = ref.lastIndexOf('/');
+    if (i != -1)
+      ref = ref.substring(0, i + 1);
+    entry.setRef(ref + refFileName);
+    add(entry);
+  }
+
+  public void saveAsHTML(String xsl, ILocation html) throws TransformerConfigurationException, TransformerException, IOException
+  {
+    saveAsHTML(html, xsl, ROOT_TAG_NAME);
+  }
+
+  public void save(ILocation location) throws IOException
+  {
+    save(location, ROOT_TAG_NAME);
+  }
+
+  private class APITestCoverageEntry extends ComponentEntry
+  {
+    private int apiCount;
+    private int testCoverageCount;
+
+    public APITestCoverageEntry()
+    {
+      apiCount = 0;
+      testCoverageCount = 0;
+    }
+
+    public String toString()
+    {
+      StringBuffer sb = new StringBuffer();
+      sb.append("<component-api-tc ");
+      sb.append(toAttribute("name", getCompName()));
+      sb.append(toAttribute("api-count", String.valueOf(apiCount)));
+      sb.append(toAttribute("test-coverage-count", String.valueOf(testCoverageCount)));
+      sb.append(toAttribute("missing-coverage-count", String.valueOf(apiCount - testCoverageCount)));
+      sb.append(toAttribute("ref", getRef()));
+      sb.append("/>");
+      return sb.toString();
+    }
+
+    /**
+     * @return Returns the apiCount.
+     */
+    public int getApiCount()
+    {
+      return apiCount;
+    }
+
+    /**
+     * @param apiCount The apiCount to set.
+     */
+    public void setApiCount(int apiCount)
+    {
+      this.apiCount = apiCount;
+    }
+
+    /**
+     * @return Returns the testCoverageCount.
+     */
+    public int getTestCoverageCount()
+    {
+      return testCoverageCount;
+    }
+
+    /**
+     * @param testCoverageCount The testCoverageCount to set.
+     */
+    public void setTestCoverageCount(int testCoverageCount)
+    {
+      this.testCoverageCount = testCoverageCount;
+    }
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIUseCoverageEmitter.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIUseCoverageEmitter.java
new file mode 100644
index 0000000..3d43150
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/APIUseCoverageEmitter.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.wtp.releng.tools.component.CommandOptionParser;
+
+public class APIUseCoverageEmitter extends APITestCoverageEmitter
+{
+  public APIUseCoverageEmitter(String compAPIDir)
+  {
+    super(compAPIDir);
+  }
+
+  protected String getComponentSummaryXML()
+  {
+    return "index-comp-uc-summary.xml";
+  }
+
+  protected String getSummaryXML()
+  {
+    return "index-api-uc.xml";
+  }
+
+  protected String getSummaryHTML()
+  {
+    return "index-api-uc.html";
+  }
+
+  protected String getSummaryXSL()
+  {
+    return "org/eclipse/wtp/releng/tools/component/xsl/component-api-uc-summary.xsl";
+  }
+
+  protected String getCoverageXML()
+  {
+    return "component-api-uc.xml";
+  }
+
+  protected String getCoverageHTML()
+  {
+    return "component-api-uc.html";
+  }
+
+  public static void main(String[] args)
+  {
+    CommandOptionParser optionParser = new CommandOptionParser(args);
+    Map options = optionParser.getOptions();
+    List eclipseDir = (List)options.get(APIUseCoverageEmitter.OPTION_ECLIPSE_DIR);
+    List testDir = (List)options.get(APIUseCoverageEmitter.OPTION_TEST_DIR);
+    List compXMLDir = (List)options.get(APIUseCoverageEmitter.OPTION_COMPONENT_XML_DIR);
+    List compAPIDir = (List)options.get(APIUseCoverageEmitter.OPTION_COMPONENT_API_DIR);
+    List genHTML = (List)options.get(APIUseCoverageEmitter.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);
+    }
+    APIUseCoverageEmitter apiUseCoverageEmitter = new APIUseCoverageEmitter((String)compAPIDir.get(0));
+    apiUseCoverageEmitter.setGenHTML(genHTML != null);
+    apiUseCoverageEmitter.init(eclipseDir, testDir, compXMLDir);
+    try
+    {
+      apiUseCoverageEmitter.genAPITestCoverageXML();
+    }
+    catch (IOException ioe)
+    {
+      ioe.printStackTrace();
+    }
+  }
+
+  private static void printUsage()
+  {
+    System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.api.usecoverage.APIUseCoverageEmitter -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-genHTML\tgenerate test coverage report in HTML");
+  }
+}
\ No newline at end of file
diff --git a/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/JavadocCoverageSummary.java b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/JavadocCoverageSummary.java
new file mode 100644
index 0000000..642a66a
--- /dev/null
+++ b/releng.wtptools/api/org.eclipse.wtp.releng.tools.component.core/src/org/eclipse/wtp/releng/tools/component/api/progress/JavadocCoverageSummary.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import org.eclipse.core.runtime.Platform;
+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.ComponentEntry;
+import org.eclipse.wtp.releng.tools.component.internal.ComponentSummary;
+
+public class JavadocCoverageSummary extends ComponentSummary
+{
+  private static final String ROOT_TAG_NAME = "component-api-javadoc-summary";
+
+  public void add(ComponentAPI compAPI)
+  {
+    JavadocCoverageEntry entry = new JavadocCoverageEntry();
+    int classCount = 0;
+    int methodCount = 0;
+    int fieldCount = 0;
+    int classIncompleteJavadoc = 0;
+    int methodIncompleteJavadoc = 0;
+    int fieldIncompleteJavadoc = 0;
+    entry.setCompName(compAPI.getName());
+    for (Iterator it = compAPI.getPackageAPIs().iterator(); it.hasNext();)
+    {
+      for (Iterator classIt = ((PackageAPI)it.next()).getClassAPIs().iterator(); classIt.hasNext();)
+      {
+        ClassAPI classAPI = (ClassAPI)classIt.next();
+        classCount++;
+        if (classAPI.isSetJavadocCoverage())
+          classIncompleteJavadoc++;
+        for (Iterator methodIt = classAPI.getMethodAPIs().iterator(); methodIt.hasNext();)
+        {
+          MethodAPI methodAPI = (MethodAPI)methodIt.next();
+          methodCount++;
+          if (methodAPI.isSetJavadocCoverage())
+            methodIncompleteJavadoc++;
+        }
+        for (Iterator fieldIt = classAPI.getFieldAPIs().iterator(); fieldIt.hasNext();)
+        {
+          FieldAPI fieldAPI = (FieldAPI)fieldIt.next();