<?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; eclipse</title>
	<atom:link href="http://blog.ciscavate.org/category/eclipse/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.ciscavate.org</link>
	<description>Musings of a Seattle-area hacker with a bent on improving digital lifestyles.</description>
	<lastBuildDate>Sun, 25 Jul 2010 23:21:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<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
whole.  The documentation [...]]]></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 &#8220;<em>&#8220;, and supplies those methods to the command environment as
new commands.  (The &#8220;</em>&#8221; 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>
