I am a total beginner on this topic, but here is what I have found so far. Please correct me, advise me etc. in the comments.
A colleague has written a program based on OSGi, which is a framework for obfuscating everything “modular” software, which I think means loading code at runtime, even if it requires a different classloader, and even if it depends on other things which also need loading at runtime. I may be wrong though.
Anyway, all I want to do is run it (on windows only, for now).
OSGi is quite closely linked to the Eclipse development environment – Eclipse uses OSGi to manage its plugins, which are an infinitely complex web of incompatible interdependencies.
My colleague showed me how to set up their Eclipse environment, and how to run the program from within Eclipse using an OSGi launch configuration. I also managed to build the JAR files of the program itself.
What I wanted to do was run it outside Eclipse, on the command line (and eventually in an Ant build).
I found it almost impossible to understand anything others have written about OSGi, but somehow I muddled my way through to being able to do it.
Here’s how I managed it.
Find out the dependencies
If you have an Eclipse launch configuration that successfully runs your program inside Eclipse, you can find out all the OSGi bundles (which are JAR files containing extra config) that it needs. Go to the Run menu and click Run Configurations. Find the relevant run configuration, which will be inside the OSGi Framework tree item on the left. Click on it, and choose the Bundles tab. The tree view will show you all the bundles needed to run this program. If you check “Only show selected” you can see only the ones you need.
If you want a text version of this list, look for a file here:
WORKSPACE/.metadata/.plugins/org.eclipse.pde.core/LAUNCHERNAME/org.eclipse.simpleconfigurator/bundles.info
where WORKSPACE is the location of your Eclipse workspace, and LAUNCHERNAME is the name of the run configuration you found in the tree view in the Run Configurations page.
The bundles.info file contains a comma-separated list of bundle name (which is a reversed-url type name, like a package name – don’t confuse it with a package name though), some version information, and the path to the actual JAR file that is this bundle.
We will also need the Equinox OSGi bundles, including the SimpleConfigurator (oh, the irony). I am using these versions – yours might be different:
org.eclipse.equinox.launcher.win32.win32.x86_1.1.2.R36x_v20101222/* org.eclipse.equinox.app_1.3.1.R36x_v20100803.jar org.eclipse.equinox.common_3.6.0.v20100503.jar org.eclipse.equinox.concurrent_1.0.100.v20100503.jar org.eclipse.equinox.ds_1.2.1.R36x_v20100803.jar org.eclipse.equinox.event_1.2.0.v20100503.jar org.eclipse.equinox.frameworkadmin.equinox_1.0.200.v20100505.jar org.eclipse.equinox.frameworkadmin_2.0.0.v20100503.jar org.eclipse.equinox.http.jetty_2.0.0.v20100503.jar org.eclipse.equinox.http.registry_1.1.1.R36x_v20101103.jar org.eclipse.equinox.http.servlet_1.1.0.v20100503.jar org.eclipse.equinox.launcher_1.1.1.R36x_v20101122_1400.jar org.eclipse.equinox.p2.artifact.repository_1.1.1.R36x_v20100901.jar org.eclipse.equinox.p2.console_1.0.200.v20100601.jar org.eclipse.equinox.p2.core_2.0.3.R36x_v20110111.jar org.eclipse.equinox.p2.director.app_1.0.202.R36x_v20110608.jar org.eclipse.equinox.p2.directorywatcher_1.0.203.R36x_v20101220.jar org.eclipse.equinox.p2.director_2.0.4.R36x_v20120223.jar org.eclipse.equinox.p2.engine_2.0.1.R36x_v20110201.jar org.eclipse.equinox.p2.extensionlocation_1.2.0.v20100518.jar org.eclipse.equinox.p2.garbagecollector_1.0.100.v20100503.jar org.eclipse.equinox.p2.jarprocessor_1.0.200.v20100503a.jar org.eclipse.equinox.p2.metadata.repository_1.1.1.R36x_v20110302.jar org.eclipse.equinox.p2.metadata_2.0.1.R36x_v20101202.jar org.eclipse.equinox.p2.operations_2.0.0.v20100510.jar org.eclipse.equinox.p2.publisher_1.1.2.v20100824-2220.jar org.eclipse.equinox.p2.ql_2.0.0.v20100503a.jar org.eclipse.equinox.p2.reconciler.dropins_1.1.3.R36x_v20111213.jar org.eclipse.equinox.p2.repository.tools_2.0.1.R36x_v20100823.jar org.eclipse.equinox.p2.repository_2.0.2.R36x_v20110111-1500.jar org.eclipse.equinox.p2.touchpoint.eclipse_2.0.4.R36x_v20110908.jar org.eclipse.equinox.p2.touchpoint.natives_1.0.201.R36x_v20110111.jar org.eclipse.equinox.p2.ui.sdk.scheduler_1.0.0.v20100507-1815.jar org.eclipse.equinox.p2.ui.sdk_1.0.100.v20100513.jar org.eclipse.equinox.p2.ui_2.0.0.v20100518.jar org.eclipse.equinox.p2.updatechecker_1.1.101.R36x_v20100823.jar org.eclipse.equinox.p2.updatesite_1.0.201.R36x_v20100823.jar org.eclipse.equinox.preferences_3.3.1.R36x_v20110302.jar org.eclipse.equinox.registry_3.5.0.v20100503.jar org.eclipse.equinox.security.ui_1.0.200.v20100503.jar org.eclipse.equinox.security.win32.x86_1.0.200.v20100503.jar org.eclipse.equinox.security_1.0.200.v20100503.jar org.eclipse.equinox.simpleconfigurator.manipulator_2.0.0.v20100503.jar org.eclipse.equinox.simpleconfigurator_1.0.200.v20100503.jar org.eclipse.equinox.util_1.0.200.v20100503.jar org.eclipse.osgi.services_3.2.100.v20100503.jar org.eclipse.osgi.util_3.2.100.v20100503.jar org.eclipse.osgi_3.6.50.R36x_v20120315-1500.jar
(I have no idea whether you need all of these – sorry.)
Make a fake environment
Imagine you have a program that consists of 2 JARs itself, called my_program_main_1.0.jar and my_program_lib_1.1.jar, 2 dependency bundles called com.dep1_3.6v20091112.jar and org.dep2_1.0.jar and a directory containing a dependency bundle called org.foo.dep3_1.4.
Create a directory that will contain your program and its dependencies. Structure it like this:
main_dir/ my_program/ my_program_main_1.0.jar my_program_lib_1.1.jar osgi_install_area/ plugins/ com.dep1_3.6v20091112.jar org.dep2_1.0.jar org.foo.dep3_1.4/ ... more stuff in here ... org.eclipse.equinox.launcher.win32.win32.x86_1.1.2.R36x_v20101222/ ... more stuff in here ... org.eclipse.equinox.app_1.3.1.R36x_v20100803.jar ... lots more here ... configuration/ config.ini bundles.info
Copy your program’s JARs into the my_program directory (feel free to give it a different name!).
Copy the Equinox bundles and the other dependencies into the plugins directory. You can find them in the directory listed in the bundles.info file you found in the previous section. The Equinox bundles should be alongside the others (hopefully).
The contents of bundles.info should be something like this:
#version=1 MyProgramMain,1.0,file:../my_program/my_program_main_1.0.jar,4,true MyProgramLib,1.1,file:../my_program/my_program_lib_1.1.jar,4,true com.dep1,3.6v20091112,file:./plugins/com.dep1_3.6v20091112.jar,4,true org.dep2,1.0,file:./plugins/org.dep2_1.0.jar,4,true org.foo.dep3,1.4,file:./plugins/org.foo.dep3_1.4/,4,true org.eclipse.equinox.launcher.win32.win32.x86,1.1.2.R36x_v20101222,file:./plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.1.2.R36x_v20101222/,4,true org.eclipse.equinox.app,1.3.1.R36x_v20100803,org.eclipse.equinox.app_1.3.1.R36x_v20100803.jar,4,true ... Plus similar lines for all the equinox and OSGi bundles you need ...
Make sure that the version number after the first comma exactly matches the version number encoded in the JAR filename.
The contents of config.ini should be something like this:
osgi.bundles=reference\:file\:C\:/absolute/path/to/main_dir/osgi_install_area/plugins/org.eclipse.equinox.simpleconfigurator_1.0.200.v20100503.jar@1\:start org.eclipse.update.reconcile=false osgi.bundles.defaultStartLevel=4 osgi.install.area=file\:C\:/absolute/path/to/main_dir/osgi_install_area osgi.framework=file\:C\:/absolute/path/to/main_dir/osgi_install_area/plugins/org.eclipse.osgi_3.6.50.R36x_v20120315-1500.jar org.eclipse.equinox.simpleconfigurator.configUrl=file\:/C\:/absolute/path/to/main_dir/bundles.info osgi.configuration.cascaded=false
Note that these paths have to be absolute. I plan to write a small ant script to create the config.ini file when needed.
Run the program
Now, to run your program, it’s a simple matter of getting into the right directory:
cd "C:\absolute\path\to\main_dir"
and typing this simple command:
java -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dfile.encoding=Cp1252 -classpath "osgi_install_area\plugins\org.eclipse.equinox.launcher_1.1.1.R36x_v20101122_1400.jar" org.eclipse.equinox.launcher.Main -configuration "file:configuration/" -os win32 -ws win32 -arch x86 -nl en_GB -console ACTUAL_ARGS_TO_PROGRAM
Where ACTUAL_ARGS_TO_PROGRAM is where you type the actual command-line arguments (if any) you want to pass to your program.
Disclaimer
I have no idea what most of this means, and I’ve probably told you a lot of things that are wrong. Please, people who know about this stuff, correct me and I’ll update this post.
This worked for me, but I feel like I must be doing something wrong – can it really be this difficult?
You can run an OSGi framework with just “java -jar org.eclipse.osgi_.jar”.
The problems you have encountered seem related to the vast number of bundles you have added to the framework. You admit yourself that you don’t know what they do, so why are you bothering with them?
Hi Neil, thanks for the information. The bundles were needed by the code I was running, which I didn’t write. The main problem I was having was constructing a directory structure containing all the right stuff in order to be able to run the program, rather than the actual command line needed to run it (although that was a challenge too). I’d appreciate any tips on how to “build” something running inside Eclipse into a “executable” project (i.e. a file or set of files that can be run using the command you gave or a similar one).
Hi there, simple question (hooping you still read this old post)
Where is the point where you tell which application framwork must run? i suppose is main class in you MyProgramMain.jar ..where ACTUAL_ARGS_TO_PROGRAM goes.
Becaouse in you command line there is not reference to you MyProgramMain, in bundles.info line with MyProgramMain.jar seems similar to others line and in config.ini i don’t see anything can help.
I try to replicate but nothing invoke my main class.
Hi Teu, I don’t think OSGi uses Main classes or methods but to be honest I found it totally confusing and am very glad I never have to touch it again. Good luck, and sorry I can’t help!