Sunday, July 15, 2012

Using Javassist to Create a Karaf/GoGo Shell Command Dynamically

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:

<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;

5 comments:

Laurie Sanders said...

This is a smart blog.

www.paperwritings.com said...

I like this code. NIce work. Thanks for sharing.

Anonymous said...

This article has me looking from the past and only now I found it. Improve the quality of your articles and continue to create a more interesting.guides2sports.com |

guidestofootball.com |

championoffantasy-sports27.com |

atrueinternetworld.com |

itsallabouthardwares.com |

pcsoft-tech.com |

mtdtechnology.com |

software4antivirus.com |

PClaptopsandNotebooks.com |

internettoools.com |

trick4internet.com |

tutorial4designer.com |

asharingportal.com |

info4dedicatedservers.com |

tech24aday.com |

Anonymous said...

"Really awesome work with the blog. I do like your hard work on and will wait for more post as from you as post gave me pleasure and gives some helps to do same work right here. Thanks a lot……………"www.maryland-funeral-home.com |

www.lbfdogs.com |

www.sport-only.com |

www.tutorial4designer.com |

www.pacetransportationinc.com |

Anonymous said...

Keep sharing such ideas in the future as well. This was actually what I was looking for, and I am glad to came here! Thanks for sharing the such information with us.http://www.rhinomoto.co.uk |

http://www.ebayshopdesigner.co.uk |

http://www.vegan-candles.co.uk |

http://www.oxygenediving.co.uk |

http://www.montagupe.co.uk |

http://www.ne7es.co.uk |

http://www.happymondayscomedy.co.uk |

http://www.mmmmh.co.uk |

http://www.eskyhobby.co.uk |

http://www.crystalapartment.co.uk |

Post a Comment

 
Copyright 2009 Spring vs Java EE Web Dev. Powered by Blogger Blogger Templates create by Deluxe Templates. WP by Masterplan