问题
I have an application that runs as a collection of OSGi bundles. I start it using a very small wrapper that embeds the Felix framework. The necessity of that wrapper irks me a little, as does the fact that it depends on Felix (whereas the application itself could run just as well in, say, Equinox), so I want to get rid of it, and use the default Felix launcher.
The only thing that the wrapper really does is passing the command line arguments into the launched OSGi framework, so that a bundle there can react upon them. Note that it does not actually parse the arguments, just pushes the String[] into my application.
Is there a standard way (or at least a Felix-standard way) to access command line parameters from a bundle, so that I can do away with the custom launcher?
回答1:
If you use bnd(tools) you can use its launcher. It registers the command line arguments as a service property 'launcher.arguments'.
This works extremely well when you combine it with the bnd package command. This command takes a bnd project or a bndrun file describing the running environment (bundles, properties, framework) and turns into into a standalone main jar. So you develop and debug in bndtools and when you're happy you turn it into a single executable jar. Example:
@Component
public class MyApp {
String args;
@Activate
void activate() {
System.out.println("Args: " + args);
}
@Reference(target="(launcher.arguments=*)")
void args( Object object, Map<String,Object> map) {
args = (String) map.get("launcher.arguments");
}
}
# to turn into an executable
bnd package myapp.bnd
java -jar myapp.jar -a somearg *.file
回答2:
Late answer but perhaps someone finds it useful.
I was having quite the same issue. My application runs in OSGi but I have external interfaces that I need to comply with which implies reading the command line arguments.
The key to this is something defined in the new OSGi specification 4.2, namely Framework Launching. You can read about it in the Draft spec (found under Draft on www.osgi.org) in the Life Cycle Layer section.
It's a standard way of launching an OSGi framework (any implementation that supports OSGi 4.2) from a stand-alone java application. The nifty thing is that you don't need to know which implementation you start (Felix, Equinox, ...) as long as it is found in the CLASSPATH.
This way, the your launcher application reads command line arguments, instantiates and starts an OSGi framework and pass the arguments to your bundle (any way you want). What you get in the launcher application is a Context to the framework from which you can communicate with your bundles.
As of Equinox 3.5M6 (I think, well at least M6) this is supported. The latest version of Apache Felix does also support this.
回答3:
Probably not. I think the standard Felix launcher does some command line validation and only accepts the bundle cache dir as an argument. More than one argument and the launcher quits.
You may use system properties to pass information in the command line, and I think it works not only in felix but also in other osgi containers, but it probably makes your application not very user friendly.
回答4:
I am aware that you searched for Felix only. Then, this Equinox-only solution might not be useful. I leave it here, because someone else might stumble over this question and has Equinox running.
From any bundle and any framework, it might be difficult. If you use the org.eclipse.core.runtime.applications extension point, is should be easy. Precondition: You do NOT pass -console as Parameter.
public class Application implements IApplication {
@Override
public Object start(IApplicationContext context) throws Exception {
String[] args = (String[])context.getArguments().get("application.args");
// args.length == 0 if no arguments have been passed
}
}
Reference in plugin.xml
<plugin>
<extension
id="myApp"
point="org.eclipse.core.runtime.applications">
<application>
<run class="package.Application" />
</application>
</extension>
</plugin>
来源:https://stackoverflow.com/questions/434664/accessing-command-line-arguments-from-osgi-bundle