Karaf OSGi runtime provides an excellent shell console functionality called Felix GoGo that can be extended easily using Blueprint XML :<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
<command name="process/run">
<action class="com.soluvas.process.shell.ProcessRunCommand">
<argument ref="processContainer"/>
<argument ref="ksession"/>
<argument ref="dependencyLookup"/>
</action>
</command>
<command name="process/ls">
<action class="com.soluvas.process.shell.ProcessLsCommand">
<argument ref="processContainer"/>
</action>
</command>
<command name="process/class">
<action class="com.soluvas.process.shell.MakeClassCommand">
<argument ref="blueprintBundleContext"/>
</action>
</command>
</command-bundle> A Karaf Shell Blueprint command element is equivalent to:
Using the bytecode tooling library Javassist, it's possible (and almost quite practical) to create GoGo commands dynamically at runtime :ClassPool pool = new ClassPool();
pool.appendClassPath(new LoaderClassPath(getClass().getClassLoader()));CtClass helloClass = pool.makeClass("cc.HelloCommand");
helloClass.setSuperclass(pool.get("org.apache.karaf.shell.console.OsgiCommandSupport"));
helloClass.addInterface(pool.get("org.apache.karaf.shell.console.CompletableFunction"));
helloClass.addInterface(pool.get("org.apache.felix.service.command.Function")); ClassFile cf = helloClass.getClassFile();
AnnotationsAttribute attr = new AnnotationsAttribute(cf.getConstPool(), AnnotationsAttribute.visibleTag);
Annotation annotation = new Annotation("org.apache.felix.gogo.commands.Command", cf.getConstPool());
annotation.addMemberValue("scope", new StringMemberValue("test", cf.getConstPool()));
annotation.addMemberValue("name", new StringMemberValue("hello", cf.getConstPool()));
annotation.addMemberValue("description", new StringMemberValue("Hello!", cf.getConstPool()));
attr.addAnnotation(annotation);
cf.addAttribute(attr); CtMethod doExecuteMethod = CtMethod.make("protected Object doExecute() throws Exception { System.out.println(\"OMG!\"); return \"Hello!\"; }", helloClass);
helloClass.addMethod(doExecuteMethod);System.out.println("Class: " + helloClass);
Class clazz = helloClass.toClass(getClass().getClassLoader(), getClass().getProtectionDomain());
System.out.println("Created " + clazz);
final Object obj = clazz.newInstance();BlueprintCommand cmd = new BlueprintCommand() {
@Override
public Action createNewAction() {
return (Action)obj;
}
};
Hashtable<String, String> props = new Hashtable<String, String>();
props.put(CommandProcessor.COMMAND_SCOPE, "test");
props.put(CommandProcessor.COMMAND_FUNCTION, "hello");
bundleContext.registerService(new String[] { CompletableFunction.class.getName(),
Function.class.getName() }, cmd, props); return null;
<command name="process/run">
<action class="com.soluvas.process.shell.ProcessRunCommand">
<argument ref="processContainer"/>
<argument ref="ksession"/>
<argument ref="dependencyLookup"/>
</action>
</command>
<command name="process/ls">
<action class="com.soluvas.process.shell.ProcessLsCommand">
<argument ref="processContainer"/>
</action>
</command>
<command name="process/class">
<action class="com.soluvas.process.shell.MakeClassCommand">
<argument ref="blueprintBundleContext"/>
</action>
</command>
</command-bundle> A Karaf Shell Blueprint command element is equivalent to:
<bean id="processLsCommand" scope="prototype"
class="com.soluvas.process.shell.ProcessLsCommand">
<argument ref="processContainer"/>
</bean>
<service auto-export="interfaces">
<service-properties>
<entry key="osgi.command.scope" value="test"/>
<entry key="osgi.command.function" value="ls"/>
</service-properties>
<bean class="org.apache.karaf.shell.console.commands.BlueprintCommand">
<property name="blueprintContainer" ref="blueprintContainer"/>
<property name="blueprintConverter" ref="blueprintConverter"/>
<property name="actionId"><idref component-id="processLsCommand"/></property>
</bean>
</service>
Using the bytecode tooling library Javassist, it's possible (and almost quite practical) to create GoGo commands dynamically at runtime :ClassPool pool = new ClassPool();
pool.appendClassPath(new LoaderClassPath(getClass().getClassLoader()));CtClass helloClass = pool.makeClass("cc.HelloCommand");
helloClass.setSuperclass(pool.get("org.apache.karaf.shell.console.OsgiCommandSupport"));
helloClass.addInterface(pool.get("org.apache.karaf.shell.console.CompletableFunction"));
helloClass.addInterface(pool.get("org.apache.felix.service.command.Function")); ClassFile cf = helloClass.getClassFile();
AnnotationsAttribute attr = new AnnotationsAttribute(cf.getConstPool(), AnnotationsAttribute.visibleTag);
Annotation annotation = new Annotation("org.apache.felix.gogo.commands.Command", cf.getConstPool());
annotation.addMemberValue("scope", new StringMemberValue("test", cf.getConstPool()));
annotation.addMemberValue("name", new StringMemberValue("hello", cf.getConstPool()));
annotation.addMemberValue("description", new StringMemberValue("Hello!", cf.getConstPool()));
attr.addAnnotation(annotation);
cf.addAttribute(attr); CtMethod doExecuteMethod = CtMethod.make("protected Object doExecute() throws Exception { System.out.println(\"OMG!\"); return \"Hello!\"; }", helloClass);
helloClass.addMethod(doExecuteMethod);System.out.println("Class: " + helloClass);
Class clazz = helloClass.toClass(getClass().getClassLoader(), getClass().getProtectionDomain());
System.out.println("Created " + clazz);
final Object obj = clazz.newInstance();BlueprintCommand cmd = new BlueprintCommand() {
@Override
public Action createNewAction() {
return (Action)obj;
}
};
Hashtable<String, String> props = new Hashtable<String, String>();
props.put(CommandProcessor.COMMAND_SCOPE, "test");
props.put(CommandProcessor.COMMAND_FUNCTION, "hello");
bundleContext.registerService(new String[] { CompletableFunction.class.getName(),
Function.class.getName() }, cmd, props); return null;
No comments:
Post a Comment