<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
  <meta name="LastChangedDate" content="$LastChangedDate$" />
  <meta name="Revision" content="$Revision$" />
  <meta name="HeadURL" content="$HeadURL$" />
  <link rel="stylesheet" href="../../book.css" charset="ISO-8859-1" type="text/css" />
  <title>Instrumenting OSGi Bundles Through Equinox Adaptor Hooks</title>
</head>

<body>

<h1>Instrumenting OSGi Bundles Through Equinox Adaptor Hooks</h1>

<p>
  <i><b>Since Eclipse 3.2 the Equinox OSGi implementation offers so called
  adaptor hooks. This paper explains how code coverage can easily be added to
  the Equinox OSGi runtime via on-the-fly code instrumentation employing these
  hooks. A working example based on EMMA is provided that allows measuring code
  coverage of any Eclipse application.</b></i>
</p>
<p style="text-align:right;margin-bottom:15pt">
  Marc R. Hoffmann, Mountainminds GmbH &amp; Co. KG, April 2007
</p>


<p>
  The plug-in based architecture of Eclipse is the foundation of modular design
  and extensibility. <a href="http://www.eclemma.org/">EclEmma</a> for example
  inserts additional menu items to the workbench or adds the new launch mode
  <i>Coverage</i> to the existing debug infrastructure. The component model
  underneath making this possible is based on the
  <a href="http://www.osgi.org/">OSGi</a> standard which manages the lifecycle
  and contracts between all the <i>bundles</i> forming an application. 
  <a href="http://www.osgi.org/osgi_technology/download_specs.asp?section=2#Release4">OSGi Release 4</a>
  introduced so called <i>extension bundles</i> which can be configured to
  become a part of the OSGi runtime itself and contribute implementation
  specific functionality.
</p>

<p>
  <img src="frameworkext.png" width="342" height="160" alt="Framework Extension" />
</p>

<p>  
  Eclipse comes with its own OSGi implementation called
  <a href="http://www.eclipse.org/equinox/">Equinox</a>, which itself offers
  several hooks that can be used by extension bundles to modify the behaviour of
  the OSGi platform. At <a href="http://www.eclipsecon.org/2007/">EclipseCon 2007</a>
  in Santa Clara I became aware of so called <i>adaptor hooks</i> offered by
  Equinox. A impressive <a href="http://www.eclipsecon.org/2007/index.php?page=sub/&amp;id=3762">demonstration</a>
  showed how these hooks can be used to dynamically apply aspect-oriented
  techniques: Little flashing planets for each plug-in graphically visualized
  the plug-ins currently executing code. So why shouldn't the same mechanism
  allow imposing code coverage analysis on any Eclipse application?
</p>


<h2>Hooking into Equinox</h2>

<p>
  Framework adaptor hooks are available since Eclipse 3.2 and specified as
  call-back interfaces in the <code>org.eclipse.osgi.baseadaptor.hooks</code> 
  package of the <code>org.eclipse.osgi</code> plug-in. By providing 
  implementations of these hook interfaces one can inject the OSGi runtime with
  new or additional behaviour in respect of framework lifecycle, bundle storage
  or class loading. Unfortunately there is no JavaDoc for this package included
  with the online help. To explore the interfaces simply import the
  <code>org.eclipse.osgi</code> into your Eclipse workspace. Enabling your hooks
  requires the following steps:
</p>

<ul>
  <li>Implement a <code>org.eclipse.osgi.baseadaptor.HookConfigurator</code>
      that registers your adaptor hook implementations with the hook registry 
      in its <code>addHooks()</code> method.</li>
  <li>Place a file <code>hookconfigurators.properties</code> at the root of
      your extension bundle containing a property definition 
      <code>hook.configurators</code> that points to your
      <code>HookConfigurator</code> implementation class.</li>
  <li>To make your bundle a framework extension it must be enlisted in the
      system property <code>osgi.framework.extensions</code> when launching
      Eclipse. This can be achieved by specifying a
      <code>-D</code> JVM parameter or by adding an
      entry to the <code>./configuration/config.ini</code> file.</li>
</ul>

<p>
  Note that Equinox requires extension bundles to be placed in the same
  directory as the <code>org.eclipse.osgi</code> plug-in.
</p>


<h2>Code Coverage via Class File Instrumentation</h2>

<p>
  There are different possible techniques to determine code coverage during a
  program run. The one used by several coverage tools like
  <a href="http://emma.sourceforge.net/">EMMA</a> is <i>byte code
  instrumentation</i>: In this approach probes are added to the original Java
  class files. These extra instructions record which parts of the program are
  executed. While the instrumentation process must be performed before the
  class files are loaded by the JVM, the instrumented code typically needs a
  extra runtime library where the coverage information is collected and
  written e.g. to a local file when the program terminates.
</p>

<p>
  <img src="instrumentation.png" width="418" height="212" alt="Instrumentation" />
</p>

<p>
  The instrumentation process can either be performed on the class
  files before the program is launched or during the class loading process.
  The latter requires hooking into the class loading mechanism of the
  application &ndash; which is easily possible for OSGi applications using 
  Equinox adaptor hooks .
</p>


<h2>Byte Code Instrumentation Hook</h2>

<p>
  To hide the complexity of the sparely documented EMMA API we abstract a code
  coverage analyser with a simple interface that may also work for any other
  code coverage technologies. For implementation details you may study the
  <a href="http://eclemma.svn.sourceforge.net/viewvc/eclemma/research/com.mountainminds.eclemma.osgihook/src/com/mountainminds/eclemma/osgihook/EMMAAnalyzer.java?view=markup">EMMAAnalyzer</a>
  implementation.
</p>

<pre class="code">
public interface ICoverageAnalyzer {
	
  /**
   * Called when the OSGi framework is started. Can be used for initialization
   * tasks.
   */
  public void start();
	
  /**
   * Called when the OSGi framework shuts down. Here we can e.g. write a
   * coverage report.
   */
  public void stop();
	
  /**
   * For each class definition loaded from a bundle this method is called.
   * The method may return a instrumented version of the class or null, if the
   * class should not be modified.
   * 
   * @param bundleid   symbolic name of the bundle
   * @param classname  full qualified VM class name
   * @param bytes      original class file bytes
   * @return  instrumented class file bytes or null
   */
  public byte[] instrument(String bundleid, String classname, byte[] bytes);

}
</pre>

<p>
  There are two adapter hook interfaces that we can implement to drive the
  coverage analyzer: With the <code>AdaptorHook</code> we get involved with the
  framework lifecycle (start/stop), the <code>ClassLoadingHook</code> allows us
  to modify raw class files before the classes get defined.
</p>

<pre class="code">
public class InstrumentationHook implements AdaptorHook, ClassLoadingHook {

  private final ICoverageAnalyzer analyzer;

  public InstrumentationHook(ICoverageAnalyzer analyzer) {
    this.analyzer = analyzer;
  }

  public void frameworkStart(BundleContext context) throws BundleException {
    analyzer.start();
  }
  
  public void frameworkStop(BundleContext context) throws BundleException {
    analyzer.stop();
  }
  
  public byte[] processClass(String name, byte[] classbytes,
      ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
    return analyzer.instrument(manager.getBaseData().getSymbolicName(), name, classbytes);
  }

  // ... stubs for remaining interface methods
  
}
</pre>


<h2>Providing Additional Runtime Classes to Instrumented Bundles</h2>

<p>
  When executing EMMA instrumented Java classes additional runtime classes
  are required, basically providing functionality for holding and saving
  collected coverage data. These few runtime classes are contained within the
  <code>emma.jar</code> library itself. Instrumenting loaded Java classes with
  EMMA adds a new runtime dependency that is neither explicitly declared in
  existing Eclipse bundles nor available within to the bundles during a standard
  Eclipse launch.
</p>

<p>
  Therefore we need to find a way to make EMMA runtime classes available to
  any bundle which classes have been instrumented for code coverage analysis.
  The OSGi R4 specification provides an interesting example of a bundle manifest
  header (chapter 3.14):
</p>

<pre>
  Fragment-Host: system.bundle; <b>extension:=bootclasspath</b>
</pre>

<p>
  I highlighted the part that suggest one can extend not just the OSGi framework
  itself (<code>extension:=framework</code>) but also the boot class path, making
  additional classes available to all plug-ins. Unfortunately it seems that this
  mechanism is not supported by the Equinox OSGi implementation. Please get in
  touch if you have any additional information about the current implementation
  status in Equinox.
</p>

<p>
  As long we have no better solution a "standard non-standard" Java VM parameter
  serves as a stopgap. The <code>-Xbootclasspath/a</code> makes the EMMA
  runtime part of the JVM boot class path and therefore available to all OSGi
  bundles:
</p>

<pre>
  -Xbootclasspath/a:/path/to/your/libs/emma.jar 
</pre>

<p>
  Note that this mechanism is currently only possible due to the way how Eclipse
  uses the boot class loader delegation, i.e. any class from the boot class path
  is automatically available to bundles without declaring that dependency. If
  future Eclipse versions switch to a more
  <a href="http://wiki.eclipse.org/index.php/Equinox_Boot_Delegation">restrictive
  class loader delegation</a> as proposed by the OSGi specification this will
  not allow injecting any classes into Eclipse bundles any more.
</p>

<h2>Running the Code Coverage Framework Extension</h2>

<p>
  The Equinox framework extension <code>com.mountainminds.eclemma.osgihook</code>
  provided with this paper measures Java code coverage for all bundles of a Equinox based OSGi system, for example a Eclipse
  RCP application. If the extension is installed code coverage data is
  automatically recorded and written out when the OSGi system terminates. In the
  current working directory a folder <code>coverage-<i>nnn</i></code> will be
  created and populated with a HTML report and a <code>*.es</code> file for
  further analysis (e.g. import into EclEmma). The framework extension can be
  used for standalone OSGi applications or for program launches from the Eclipse
  plug-in development environment (PDE).
</p>

<h3>Standalone Mode</h3>

<p>
  In case you start your application directly with <code>eclipse.exe</code>
  perform these steps to add the code coverage extension:
</p>

<ul>
  <li>Get the compiled bundle
    <code>com.mountainminds.eclemma.osgihook_1.0.0.jar</code> from the
    <a href="http://sourceforge.net/project/showfiles.php?group_id=177969&amp;package_id=230021">Sourceforge download page</a>.</li>
  <li>Place it in your <code>plugins/</code> directory. This must be the same
    directory where the <code>org.eclipse.osgi</code> bundle is located. Using
    e.g. a extension site will not work!</li>
  <li>Insert the following line into the <code>./configuration/config.ini</code>
    file of your Eclipse installation:
    <pre>osgi.framework.extensions=com.mountainminds.eclemma.osgihook</pre></li>    
  <li>Launch <code>eclipse.exe</code> with the following additional parameter
    (insert the correct location for <code>emma.jar</code>).
    <pre>-vmargs -Xbootclasspath/a:/path/to/your/libs/emma.jar</pre></li>
</ul>

<h3>PDE Mode</h3>

<p>
  If you want to study or modify the extension bundle you may directly import
  it to your PDE workspace and launch a Eclipse application in development mode.
  The extension works for any OSGi based launch type, i.e. Eclipse application
  OSGi framework and JUnit plug-in test.
</p>

<ul>
  <li>Import the latest version of the extension bundle from the SVN repository at
    <code>https://eclemma.svn.sourceforge.net/svnroot/eclemma/research/com.mountainminds.eclemma.osgihook</code>.</li>
  <li>Due to the fact that Equinox needs any framework extension co-located with
    the OSGi framework bundle you need to also import <code>org.eclipse.osgi</code>
    into your workspace (from the <i>Plug-Ins</i> view).</li>
  <li>Take a existing launch configuration or create a new one. Make sure that
    the <code>com.mountainminds.eclemma.osgihook</code> and the 
    <code>org.eclipse.osgi</code> bundle are enabled.</li>
  <li>On the <i>Arguments</i> tab insert the following definition in the
    <i>VM arguments</i> field:
    <pre>-Dosgi.framework.extensions=com.mountainminds.eclemma.osgihook
-Xbootclasspath/a:${workspace_loc}/com.mountainminds.eclemma.osgihook/emma.jar</pre></li>
</ul>


<h2>Advantages and Limitations</h2>

<p>
  The obvious advantage of the technique described here is that code coverage
  can be determined for any OSGi bundle respectively Eclipse plug-in without 
  pre-processing the bundles, i.e. physically modifying them. Using this
  technique for test runs in automated build environments makes extra build
  targets for instrumented versions of the bundles superfluous. While the
  application start-up is slightly delayed due to the required byte code
  instrumentation, there is no significant slow-down during execution.
</p>

<p>
  Java classes required are instrumented on-the-fly, classes that are not loaded
  don't need to be processed. While this looks like an advantage at first glance
  it comes with the drawback that there is also no meta information recorded for
  these classes. They don't appear on the coverage report; completely untested
  classes will not be shown. A simple workaround here would be to collect the
  complete meta data "offline" on all involved plug-ins without actually
  instrumenting them.
</p>


<h2>Outlook</h2>

<p>
  While the provided example is kept as simple as possible just to demonstrate 
  the principles, a more evolved version may add additional functionality like
  filtering the analyzed bundles. Another interesting topic for investigation
  would be how the framework extension can be used in automated build
  environments for coverage reports.
</p>

<p>
  This adaptor bundle technique would be a great benefit for EclEmma.
  <i>In-place</i> instrumentation is no longer required for Eclipse launches.
  As a consequence any plug-in (not only the ones in the workspace) could be
  analyzed. Anyhow there are some issues for investigation:  
</p>

<ul>
  <li>Due to limited resources there is a single development branch of
    EclEmma only which supports all Eclipse versions from 3.1 on. Adopting
    framework extensions would mean to drop Eclipse 3.1 support or create a
    second development branch.</li>
  <li>Equinox framework extensions must be placed in the same directory than
    the OSGi runtime. This requires adding the coverage extension to your
    Eclipse installation &ndash; a undesirable modification that may also be
    restricted by access right. Another option would be to put the extension
    along with a copy of <code>org.eclipse.osgi</code> to a third place,
    which may interfere with other installed extensions.</li>
</ul>


<h2>References</h2>

<ul>
  <li>
    Eclipse Equinox<br/>
    <a href="http://www.eclipse.org/equinox/">http://www.eclipse.org/equinox/</a>
  </li>
  <li>
    wiki.eclipse.org, Adaptor Hooks, 2006<br/>
    <a href="http://wiki.eclipse.org/index.php/Adaptor_Hooks">http://wiki.eclipse.org/index.php/Adaptor_Hooks</a>
  </li>
  <li>
    wiki.eclipse.org, Equinox Boot Delegation, 2006<br/>
    <a href="http://wiki.eclipse.org/index.php/Equinox_Boot_Delegation">http://wiki.eclipse.org/index.php/Equinox_Boot_Delegation</a>
  </li>
  <li>
    OSGi Alliance, OSGi Service Platform Release 4, 2006<br/>
    <a href="http://www.osgi.org/osgi_technology/download_specs.asp?section=2#Release4">http://www.osgi.org/osgi_technology/download_specs.asp?section=2#Release4</a>
  </li>
  <li>
    EMMA - a free Java code coverage tool, Vlad Roubtsov, 2006<br/>
    <a href="http://emma.sourceforge.net/">http://emma.sourceforge.net/</a>
  </li>
  <li>
    EclEmma - Java Code Coverage for Eclipse<br/>
    <a href="http://www.eclemma.org/">http://www.eclemma.org/</a>
  </li>
</ul>

<h2>Resources</h2>

<ul>
  <li>
    Compiled bundle <code>com.mountainminds.eclemma.osgihook</code><br/>
    <a href="http://sourceforge.net/project/showfiles.php?group_id=177969&amp;package_id=230021">http://sourceforge.net/project/showfiles.php?group_id=177969&amp;package_id=230021</a>
  </li>
  <li>
    SVN URL 
    (<a href="http://eclemma.svn.sourceforge.net/viewvc/eclemma/research/com.mountainminds.eclemma.osgihook/">browse repository</a>)<br/>
    <a href="https://eclemma.svn.sourceforge.net/svnroot/eclemma/research/com.mountainminds.eclemma.osgihook">https://eclemma.svn.sourceforge.net/svnroot/eclemma/research/com.mountainminds.eclemma.osgihook</a></li>
  <li>
    EclEmma's <i>Open Discussion</i> forum for any remarks about this paper<br/>
    <a href="http://sourceforge.net/forum/forum.php?forum_id=614869">http://sourceforge.net/forum/forum.php?forum_id=614869</a>
  </li>
</ul>

</body>
</html>