User Tools

Site Tools


headless_eclipse

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
headless_eclipse [2012/08/22 16:30]
angelino created
headless_eclipse [2017/09/06 01:54] (current)
Line 1: Line 1:
-====== ​HEADLESS ECLIPSE ​======+====== ​Headless Eclipse ​======
  
  
-===== What is it ? ===== +===== What Is It? =====
-Headless Eclipse is an instance of Eclipse launched without Graphical User Interface, by command-line.+
  
 +A "​Headless Eclipse"​ is an instance of Eclipse launched without any Graphical User Interface, on the command-line.
  
-===== What for ? ===== 
  
-You can use headless Eclipse to run a console application plugin for Eclipse. One of the purposes of such an operation, as seen with SQUANER, is to automatically delegate processing to Eclipse from a web application. Indeed, in order to create a [[padl|PADL]] model of a C++ project, SQUANER let Eclipse parse the project and give its AST.+===== What For? =====
  
 +You can use a Headless Eclipse to call a plug-in in Eclipse from some external programs. One of the purposes of such a call, as seen with SQUANER, is to automatically delegate processing to Eclipse from a Web application. Indeed, to create the [[padl|PADL]] model of a C++ project, SQUANER asks Eclipse to parse the C++ project and to return its model.
  
-===== How to use it ? ===== 
  
-First, create your plugin ​with Eclipse IDE, within the plugin development environment+===== How to Use It? ===== 
-In the plugin.xml file of your plugin ​(root lever of the project), give a specific ​id to your plugin. You should have a file like this:+ 
 +First, create your plug-in ​with the Eclipse IDE, within the Plug-in Development Environment (PDE)
 +In the plugin.xml file of your plug-in ​(root level of the project), give a specific ​ID to your plugin. You should have a file like this:
  
 ''<?​xml version="​1.0"​ encoding="​UTF-8"?>​ ''<?​xml version="​1.0"​ encoding="​UTF-8"?>​
Line 33: Line 34:
 </​plugin>''​ </​plugin>''​
  
-Then, download a second Eclipse ​which will be used to make the application ​run (it is the headless ​Eclipse)+Then, download a second Eclipse ​that will be used to run your plug-in, i.e., the Headless ​Eclipse. 
-In Eclipse IDE, export your plugin (Right-Click on your plugin project > Export > Plug-in Development > Deployable plug-ins and framents). Check all needed pluginsand export them to the //eclipse// root folder of your headless ​Eclipse (the plugins will automatically be put in the //plugins// folder).+From the first Eclipse IDE, export your plugin (right-click on your plugin project > Export > Plug-in Development > Deployable plug-ins and framents). Check all needed plugins and export them to the //eclipse// root folder of your Headless ​Eclipse (the plugins will automatically be put in the //plugins// folder).
  
-Finally, open a shell on the //eclipse// root folder of your headless ​Eclipse and use the following command:+Finally, open a shell on the //eclipse// root folder of your Headless ​Eclipse and use the following command:
  
 ''​java -cp plugins/​org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar org.eclipse.equinox.launcher.Main -application Name_of_your_plugin_project.Id_of_the_plugin''​ ''​java -cp plugins/​org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar org.eclipse.equinox.launcher.Main -application Name_of_your_plugin_project.Id_of_the_plugin''​
  
-Please note that the version of the jar archive may differ ​in the time; just check the name of the library eclipse/​plugin/​org.eclipse.equinox.launcher_* and modify the command consequently.+The version of the JAR archive may change ​in time; just check the name of the library eclipse/​plugin/​org.eclipse.equinox.launcher_* and modify the command consequently.
  
  
-===== Known exceptions ​=====+===== Caveats ​=====
  
  
-==== Application Name_of_your_plugin_project.Id_of_the_plugin could not be found in the registry ====+==== Application ​''​Name_of_your_plugin_project.Id_of_the_plugin'' ​could not be found in the registry ====
  
 If you see this error in the log file, after launching your headless application,​ in most cases it means you may have a __dependendy__ issue. Check all the manifest files of your plugin projects and localize __all__ needed resources. Let's remind than a plugin should only depend on other plugins. Not a Java project, not an external library... If you need to use a library, you can create a plugin from the library (in Eclipse IDE, right-click on the Package Exporer > New > Other > Plug-in Development > Plug-in from Existing JAR Archives). Then let your plugin depend on the freshly //​plug-ined//​ library thanks to the Manifest > //​Dependencies//​ tab > Required Plug-ins. If you see this error in the log file, after launching your headless application,​ in most cases it means you may have a __dependendy__ issue. Check all the manifest files of your plugin projects and localize __all__ needed resources. Let's remind than a plugin should only depend on other plugins. Not a Java project, not an external library... If you need to use a library, you can create a plugin from the library (in Eclipse IDE, right-click on the Package Exporer > New > Other > Plug-in Development > Plug-in from Existing JAR Archives). Then let your plugin depend on the freshly //​plug-ined//​ library thanks to the Manifest > //​Dependencies//​ tab > Required Plug-ins.
  
-==== java.lang.NoClassDefFoundError ====+==== ''​java.lang.NoClassDefFoundError'' ​==== 
  
 It happens that if you use the plugin automatic export, some archives do not contain the class definitions... One solution is to manually export a jar archive of the project with needed class definitions,​ and rename it to replace the empty archive. One anti-solution is to add the manually exported archive in the class path. It happens that if you use the plugin automatic export, some archives do not contain the class definitions... One solution is to manually export a jar archive of the project with needed class definitions,​ and rename it to replace the empty archive. One anti-solution is to add the manually exported archive in the class path.
  
-====== ​ ======+==== Questions to Answer when Programmatically Calling Eclipse ​====  
 + 
 +When calling Eclipse programmatically,​ the reason is often to call from a program some plug-in to perform some computations,​ thus benefiting from Eclipse rich set of plug-ins, and then get an object as results from these computations to be used in the rest of the program. Exchanging objects between Eclipse and the rest of the program means that Eclipse must be told to use the same classes for these objects as the rest of the program. Hence, it must be told to use the same class-loader for these classes or, really, must be instructed to by-pass its class-loading mechanism to directly as the JVM system class-loader,​ also called application class-loader,​ instance of ''​Launcher$AppClassLoader''​. 
 + 
 +The different sections of the MANIFEST.MF and build.properties files interact and impact the compiling and running of the plug-in. First, it is important to understand that plug-in relate to other plug-ins and JARs through three questions:​ 
 +- Does the current plug-in require other plug-ins / JARs to compile? 
 +- Does the current plug-in require other plug-ins / JARs to run? 
 +- Does the current plug-in require access to the classes in other plug-ins / JARs? 
 + 
 +=== Does the current plug-in require other plug-ins / JARs to compile? === 
 + 
 +If the current plug-in requires other plug-ins / JARs to compile, these plug-ins / JARs must be declared in ''​Dependencies -> Required Plug-ins''​ **OR** ''​Build -> Extra Classpath Entries''​. The difference between the two sections is important. 
 + 
 +''​Dependencies -> Require Plug-ins''​ only accepts plug-ins, not JARs. Plug-ins listed in this section becomes accessible to the current plug-ins, i.e., their classes are visible to the current plug-in according to their visibility (''​Runtime -> Exported Packages''​).  
 + 
 +''​Build -> Extra Classpath Entries''​ only accepts JARs. These JARs will be used to compile the plug-ins but are not related to its running. 
 + 
 +=== Does the current plug-in require other plug-ins / JARs to run? === 
 + 
 +If the current plug-in requires other plug-ins / JARs to run, these plug-ins / JARs must be declared in ''​Dependencies -> Required Plug-ins''​ **OR** ''​Runtime -> Classpath''​. The difference between these two sections is also important. 
 + 
 +''​Dependencies -> Required Plug-ins''​ only accepts plug-ins, not JARs. Plug-ins listed in this section become accessible to the current plug-ins, i.e., any class belonging to the package listed in their respective ''​Runtime -> Exported Packages''​ sections is accessible. They must be available in the runtime configuration (''​config.ini''​) of the Eclipse application in which the current plug-in will run, else the current plug-in will not load and the log file in the workspace ''​.metadata''​ folder will contain a ''​ClassNotDefFoundError''​. 
 + 
 +''​Runtime -> Classpath''​ only accepts JARs. These JARs will be "​embedded"​ in the current plug-in and their classes accessible to it. JARs added to this section automatically appear in the ''​Build -> Binary Build''​ section and in the ''​bin.includes''​ statement of the ''​build.properties''​ file. 
 + 
 +=== Does the current plug-in require access to the classes in other plug-ins / JARs? === 
 + 
 +If the current plug-in requires classes in other plug-ins / JARs, these plug-ins / JARs must be declared in ''​Dependencies -> Required Plug-ins''​ **OR** ''​Dependencies -> Imported Packages''​ **OR** ''​Runtime -> Classpath''​. ''​Dependencies -> Required Plug-ins''​ and ''​Runtime -> Classpath''​ have been discussed above. ''​Dependencies -> Imported Packages''​ is used to bypass the Eclipse class-loading mechanism, as explained below. 
 + 
 + 
 +==== Sharing Class Instances between a Java Application and some Eclipse Plug-in ==== 
 + 
 +When calling Eclipse programmatically,​ the reason is often to call from a program some plug-in to perform some computations,​ thus benefiting from Eclipse rich set of plug-ins, and then get an object as results from these computations to be used in the rest of the program. Exchanging objects between Eclipse and the rest of the program means that Eclipse must be told to use the same classes for these objects as the rest of the program. Hence, it must be told to use the same class-loader for these classes or, really, must be instructed to by-pass its class-loading mechanism to directly as the JVM system class-loader,​ also called application class-loader,​ instance of ''​Launcher$AppClassLoader''​. 
 + 
 +In other words: the main interest of programmatically running some Eclipse plug-in from Java application is to benefit from the Eclipse plug-ins and obtain / use some instances of some classes from them. To share these instances, the Java application and the Eclipse plug-ins must share the same classes, i.e., classes loaded using the Java application class-loader,​ else the JVM would consider that the classes are different, because loaded from different class-loaders. 
 + 
 +To instruct Eclipse to by-pass its class-loading mechanism, the plug-in must be configured so that its ''​MANIFEST.MF''​ file uses the ''​Import-Package''​ statement to declares which packages will come from "​somewhere else", not a particular plug-in. Then, Eclipse must be run with the [[http://​wiki.eclipse.org/​Equinox_Boot_Delegation#​Compatibility|osgi.compatibility.bootdelegation]] property set to ''​true''​. Finally, the configuration file ''​Config.ini''​ of the headless Eclipse workspace must include the [[https://​felix.apache.org/​site/​apache-felix-framework-configuration-properties.html#​ApacheFelixFrameworkConfigurationProperties-framework|org.osgi.framework.system.packages.extra]] statement must match one-for-one the list of imported packages in the ''​MANIFEST.MF''​ file.  
 + 
 +If there is a discrepancy between the ''​MANIFEST.MF''​ and ''​Config.ini''​ files, Eclipse will use its class-loading mechanism and the objects returned by the plug-in and expected by the program will belong to different classes, because loaded by different class-loaders. 
 + 
 +==== Access Rules ==== 
 + 
 +When using the ''​Import-Package''​ statement and if the plug-in shares some common package with another plug-in, Eclipse gets confused and claims that other plug-in cannot use classes in this package, even if it is exported by all the plug-ins involved. Therefore, it is important to have different packages, which can of defeat the purpose of having plug-in in the first place. It is true, though, that ''​Import-Package''​ statement, by instructing Eclipse to by-pass its class-loading mechanism, disturb this mechanism. 
 + 
 + 
 +==== Plug-ins Referenced in ''​config.ini''​ but Missing ​====
  
-Created ​by //​[[|angelino]] 2012/08/22 11:42//+The ''​config.ini''​ file contains, among other things, the locations of the plug-ins (actually, their JAR files or folders) required ​by an Eclipse application. If one of more plug-ins are missing, i.e., there is a discrepancy between the ''​config.ini''​ file and the folder containing the plug-ins JARs and folders, then Eclipse will throw an error and the "​configuration area" will contain a log file detailing the missing plug-ins.
headless_eclipse.1345653022.txt.gz · Last modified: 2017/09/06 01:54 (external edit)