<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Bitwise Evolution &#187; OSGi</title>
	<atom:link href="http://blog.ciscavate.org/category/osgi/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.ciscavate.org</link>
	<description>Musings of a Portland-area hacker with a bent on improving digital lifestyles.</description>
	<lastBuildDate>Thu, 07 Apr 2011 00:42:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.3</generator>
		<item>
		<title>Auto-documenting OSGi CommandProviders</title>
		<link>http://blog.ciscavate.org/2008/10/auto-documenting-osgi-commandproviders.html</link>
		<comments>http://blog.ciscavate.org/2008/10/auto-documenting-osgi-commandproviders.html#comments</comments>
		<pubDate>Mon, 20 Oct 2008 23:08:54 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
				<category><![CDATA[OSGi]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://blog.ciscavate.org/2008/10/auto-documenting-osgi-commandproviders.html</guid>
		<description><![CDATA[(Edit: If you&#8217;re reading this after OSGi R4.2, then there is almost certainly a better way to accomplish the same thing) I&#8217;ve been digging into OSGi a bit over the last week or so inorder to create some Eclipse plugins that will automatically discover eachother, and I&#8217;ve been generally impressed with the framework on the [...]]]></description>
			<content:encoded><![CDATA[<p>(<strong>Edit:</strong> If you&#8217;re reading this after OSGi R4.2, then there is almost certainly a better way to accomplish the same thing)</p>

<p>I&#8217;ve been digging into OSGi a bit over the last week or so inorder to
create some Eclipse plugins that will automatically discover
eachother, and I&#8217;ve been generally impressed with the framework on the
whole.  The documentation is a bit lacking, but there are some good
blog posts about it.  (Specifically [Neil Bartlett's introduction to
OSGi][intro].)</p>

<p>One thing that bugged me is the repetition needed when you implement
the CommandProvider interface to add commands to the OSGi console.
CommandProvider defines one method you must supply:</p>

<div class="codecolorer-container java" style="height:35px;"><div class="codecolorer" style="font-family: monospace;"><span class="kw2">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getHelp<span class="br0">&#40;</span><span class="br0">&#41;</span></div></div>

<p>OSGi then uses reflection to extract each of the methods that starts
with an underscore, and supplies those methods to the command environment as
new commands.  (The underscore is trimmed, and the name of the method becomes
the command name.)  General practice is to include the name of the
method in the return value of <code>getHelp()</code>, along with a description of
what the method does, eg:</p>

<div class="codecolorer-container java"><div class="codecolorer" style="font-family: monospace;"><span class="kw2">public</span> <span class="kw2">class</span> SampleCommandProvider <span class="kw2">implements</span> CommandProvider <span class="br0">&#123;</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw2">synchronized</span> <span class="kw4">void</span> _run<span class="br0">&#40;</span>CommandInterpreter ci<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="co1">// do stuff.</span><br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp;<span class="kw2">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getHelp<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> <span class="st0">&quot;<span class="es0">\t</span>run - execute a Runnable service&quot;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div></div>

<p>This seems like a pain to maintain, so I took a quick look at
annotations, and propose a new syntax:</p>

<div class="codecolorer-container java"><div class="codecolorer" style="font-family: monospace;"><span class="kw2">public</span> <span class="kw2">class</span> SampleCommandProvider <span class="kw2">extends</span><br />
&nbsp; &nbsp;DescriptiveCommandProvider <span class="br0">&#123;</span><br />
<br />
&nbsp; &nbsp;@CmdDescr<span class="br0">&#40;</span>description=<span class="st0">&quot;execute a Runnable service&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw2">synchronized</span> <span class="kw4">void</span> _run<span class="br0">&#40;</span>CommandInterpreter ci<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="co1">// do stuff.</span><br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div></div>

<p>Here we&#8217;ve extracted the <code>getHelp()</code> method into a new superclass, so
our SampleCommandProvider now extends an abstract class instead of
implementing an interface.  It also makes use of an Annotation, which
we need to define:</p>

<div class="codecolorer-container java"><div class="codecolorer" style="font-family: monospace;"><span class="co2">import java.lang.annotation.ElementType;</span><br />
<span class="co2">import java.lang.annotation.Retention;</span><br />
<span class="co2">import java.lang.annotation.RetentionPolicy;</span><br />
<span class="co2">import java.lang.annotation.Target;</span><br />
&nbsp; &nbsp; <br />
@Retention<span class="br0">&#40;</span>RetentionPolicy.<span class="me1">RUNTIME</span><span class="br0">&#41;</span><br />
@Target<span class="br0">&#40;</span>ElementType.<span class="me1">METHOD</span><span class="br0">&#41;</span><br />
<span class="kw2">public</span> @<span class="kw2">interface</span> CmdDescr <span class="br0">&#123;</span><br />
&nbsp; &nbsp;<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> description<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div></div>

<p>Finally, we just need to define the superclass that implements
<code>getHelp()</code>:</p>

<div class="codecolorer-container java" style="height:280px;"><div class="codecolorer" style="font-family: monospace;"><span class="co2">import java.lang.reflect.Method;</span><br />
<span class="co2">import java.util.regex.Matcher;</span><br />
<span class="co2">import java.util.regex.Pattern;</span><br />
<br />
<span class="co2">import org.eclipse.osgi.framework.console.CommandProvider;</span><br />
<br />
<span class="kw2">public</span> <span class="kw2">abstract</span> <span class="kw2">class</span> DescriptiveCommandProvider <span class="kw2">implements</span> CommandProvider <span class="br0">&#123;</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="kw2">private</span> <span class="kw2">static</span> <span class="kw2">final</span> Pattern CMD_PATTERN = Pattern.<span class="me1">compile</span><span class="br0">&#40;</span><span class="st0">&quot;^_(.*)&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="kw2">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> help = <span class="kw2">null</span>;<br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="kw2">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getHelp<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw2">null</span> == help<span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;help = buildHelp<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> help;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> buildHelp<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; StringBuilder helpBuff = <span class="kw2">new</span> StringBuilder<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AMethod+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">Method</span></a> m : <span class="kw2">this</span>.<span class="me1">getClass</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">getMethods</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>methodIsCmd<span class="br0">&#40;</span>m<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#123;</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="nu0">0</span> != helpBuff.<span class="me1">length</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;helpBuff.<span class="me1">append</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; helpBuff.<span class="me1">append</span><span class="br0">&#40;</span>getDocumentation<span class="br0">&#40;</span>m<span class="br0">&#41;</span><span class="br0">&#41;</span>;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> helpBuff.<span class="me1">toString</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">private</span> <span class="kw4">boolean</span> methodIsCmd<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AMethod+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">Method</span></a> m<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> CMD_PATTERN.<span class="me1">matcher</span><span class="br0">&#40;</span>m.<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">matches</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getDocumentation<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AMethod+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">Method</span></a> m<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; StringBuilder methodHelp = <span class="kw2">new</span> StringBuilder<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; Matcher matcher = CMD_PATTERN.<span class="me1">matcher</span><span class="br0">&#40;</span>m.<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>matcher.<span class="me1">matches</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;methodHelp.<span class="me1">append</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\t</span>&quot;</span>+matcher.<span class="me1">group</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CmdDescr description = m.<span class="me1">getAnnotation</span><span class="br0">&#40;</span>CmdDescr.<span class="kw2">class</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw2">null</span> != description<span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; methodHelp.<span class="me1">append</span><span class="br0">&#40;</span><span class="st0">&quot; - &quot;</span>+description.<span class="me1">description</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> methodHelp.<span class="me1">toString</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div></div>

<p>Note that the actual reflection on the class only happens once &#8212; all
subsequent calls to <code>getHelp()</code> use a cached copy of the documentation.</p>

<p>[intro]: http://neilbartlett.name/blog/osgi-articles/<u style=display:none></u></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ciscavate.org/2008/10/auto-documenting-osgi-commandproviders.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

