Gradle Equinox Plugin – Part 3: How to create an empty Equinox container

updated_logo_for_gradle

In this part, I’ll implement a code which creates an empty Equinox container.
As first step must be defined a task which creates the container and a script which starts it. For the definition of the task can be used the Project object provided by the Gradle framework. It represents the project which applies the plugin, The apply method of the plugin class which implements org.gradle.api.Plugin passes the object as parameter.  In my case that is the EquinoxPlugin class:

class EquinoxPlugin implements Plugin {
    @Override
    void apply(Project project) {
		TaskContainer tasks = project.tasks
	
        tasks.create 'buildEquinoxConfig', {
            
        }
    }
}

To create an Equinox container will be needed an Equinox kernel jar and some configuration properties. To get the kernel, first must be defined a configuration and dependency to it. The Gradle Project ConfigurationContainer can be used to define the required Equinox dependency:

void apply(Project project) {
	ConfigurationContainer configurations = project.configurations
	DependencyHandler dependencies = project.dependencies
	TaskContainer tasks = project.tasks

	project.repositories {
		mavenCentral() // Using the Maven Central repository to download the Equinox kernel
	}

	configurations.create 'equinoxKernel'
	dependencies.add 'equinoxKernel', [group:'org.eclipse', name: 'osgi', version: '3.10.0-v20140606-1445', configuration: 'runtime']

	tasks.create 'buildEquinoxConfig', {
		
	}
}

When the plugin is being executed, Equinox will be downloaded at the file system. As next step must be created a configuration which will start the container. To achieve that a configuration file called config.ini is required in dedicated directory which will be used by Equinox during the  runtime.

To get the location of the Equinox kernel, will be used the already defined configuration called equionxKernel. It has only one dependency which is the actual container and this allows the usage of the singleFile getter applicable when the configuration contains only one dependency:

tasks.create 'buildEquinoxConfig', {
	doLast {
		def equinoxBuildDir = new File("$project.buildDir/equinox") // The location of the container
		Path equinoxKernelFile =
				configurations.equinoxKernel.incoming.files.singleFile.toPath() // Equinox Kernel file
	}
}

The code above gets the path to the actual Equinox jar file at the file system from the user gradle home directory.

Now we know where the kernel file is located and it can be used to configure the startup script and the configuration config.ini file.

The format of the config.ini file is standard Java key-value properties. This allows the usage of the java.util.Properties API:

tasks.create 'buildEquinoxConfig', {
	doLast {
		def equinoxBuildDir = new File("$project.buildDir/equinox")
		Path equinoxKernelFile =
				configurations.equinoxKernel.incoming.files.singleFile.toPath() // Equinox Kernel file

		Properties configurationProperties = new Properties()
		// Groovy style definition of map entries
		configurationProperties['osgi.install.area'] = equinoxBuildDir.toPath().toAbsolutePath().toUri().toString()
		configurationProperties['osgi.framework'] = "file:${equinoxBuildDir.toPath().relativize(equinoxKernelFile)}".toString()
		configurationProperties['osgi.noShutdown'] = 'true'
		configurationProperties['eclipse.consoleLog'] = 'true'
		configurationProperties['eclipse.ignoreApp'] = 'true'

		def equinoxConfigurationDir = new File("$equinoxBuildDir/configuration")
		equinoxConfigurationDir.mkdirs()
		def equinoxConfigurationFile = new File(equinoxConfigurationDir, 'config.ini')
		equinoxConfigurationFile.withOutputStream {
			configurationProperties.store it, null/*No comments*/
		}
	}
}
    The code above creates the config.ini file and writes the required configuration properties used by Equinox

  • osgi.install.area – the install location of the platform. This setting indicates the location of the basic Eclipse plug-ins. Currently the only bundle will be kernerl.
  • osgi.framework – the URL location of the OSGi framework.
  • osgi.noShutdown – if “true”, the OSGi Framework will not be shut down after the Eclipse application has ended.
  • eclipse.consoleLog – if “true”, any log output is also sent to Java’s System.out
  • eclipse.ignoreApp – if set to “true” then the main launching thread will not start the default application and will proceed in shutting down the platform and exiting.

The last thing that should be implemented is a startup script. To do that, I created a bat file which starts the Equinox jar:

@echo off
java -jar "{{OSGI_FILE}}" -console -configuration "{{CONFIG_FILE}}"

equinox-bat-file

As you can see it has placeholders which will be replaced later.

To create the actual startup script, I created a separate Gradle Copy task which copies it in the build directory and replaces the placeholders:

tasks.create 'copyEquinoxRunScripts', Copy.class, {
	from new File (EquinoxPlugin.classLoader.getResource('bin/equinox.bat').file)
	into "$project.buildDir/equinox/bin"
	filter {
		it.replace('{{OSGI_FILE}}', project.configurations.equinoxKernel.incoming.files.singleFile.path)
	}
	filter {
		it.replace('{{CONFIG_FILE}}', "$project.buildDir/equinox/configuration")
	}
}

Important thing is the -configuration options which MUST point a location containing a config.ini file. Have in mind that this configuration directory will be used by Equinox to store additional data.

Now let’s execute the defined tasks by the test written to apply the plugin (EquinoxPluginTest). Will be needed a little touch, just to define the required execution tasks:

when:
def result = GradleRunner.create()
		.withProjectDir(testBuildDir)
		.withArguments('copyEquinoxRunScripts', 'buildEquinoxConfig', '-i', '-s')
		.withPluginClasspath(pluginClasspath)
		.build()

then:
printTestOutput result
// Removed the obsolete check whether the output contains a specific string.

Execution command line:

>gradlew clean test -i

The result:

equinox-bat-file-result

And the Equinox startup bat file execution result (Ignore the error, it occurs, because the OSGi console bundle is missing.):

equinox-console

I think that this is enough for this part. As next actions, some bundles will be installed in the container (e.g console) and the Gradle tasks in the plugin will be rewritten as separate configurable classes.

One thought on “Gradle Equinox Plugin – Part 3: How to create an empty Equinox container

Leave a Reply

Your email address will not be published. Required fields are marked *