Skip to content
forked from akhikhl/unpuzzle

Gradle plugin for mavenizing OSGi artifacts

License

Notifications You must be signed in to change notification settings

stempler/unpuzzle

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

About this fork

This is a fork of the original unpuzzle project with a slightly different focus. This adapted version aims to provide the means to mavenize existing Eclipse RCP applications to be able to reuse the functionality in a standard Maven environment. It adds the following main features:

  • include dependencies based on Import-Package instructions in bundle manifests (see also this Github issue)
  • translate bundle dependencies to existing Maven artifacts on jcenter and other repositories where possible

The changes are probably(?) to extensive for the original author to agree integrating it into the main project, thus I'm maintaining this adapted version of unpuzzle on Sonatype Nexus / Maven Central with an alternate group name (org.standardout.unpuzzle). Right now there is only a snapshot version available:

buildscript {
  repositories {
    jcenter()
    maven {
      url 'https://oss.sonatype.org/content/repositories/snapshots/'
    }
  }

  dependencies {
    classpath 'org.standardout.unpuzzle:unpuzzle-plugin:0.0.23-SNAPSHOT'
  }
}

apply plugin: 'org.akhikhl.unpuzzle'

...

Unpuzzle logo

Build Status Maintainer Status Release Snapshot License

Unpuzzle is a set of tools for mavenizing OSGi-bundles. You can consume Unpuzzle in two forms: as a gradle plugin and as an ordinary jar-library. All versions of Unpuzzle are available at jcenter and maven-central under the group 'org.akhikhl.unpuzzle'.

Content of this document

  1. What "mavenizing" means?
  2. Gradle plugin
  3. Gradle tasks
  1. Configuration DSL
  2. uploadEclipse configuration
  3. Configuration hierarchy
  4. Support of multiple Eclipse versions
  5. Jar-library API
  6. Copyright and License

What "mavenizing" means?

When OSGi-bundle is being "mavenized", the following happens:

  • The program generates pom.xml for every OSGi-bundle (of eclipse distribution, for example). The generated pom.xml contains maven coordinates "group:artifact:version", where "group" is constant (could be "eclipse", for example), "artifact" corresponds to OSGi-bundle name, "version" corresponds to OSGi-bundle version.

  • The program compares every required-bundle of the given OSGi-bundle against other mavenized OSGi-bundles and, when match found, converts it to maven dependency.

  • The program analyzes exported and imported packages of OSGi bundles to create maven dependencies for OSGi Import-Package instructions

  • The program automatically finds language-fragments of the given OSGi-bundle and adds them as optional maven dependencies.

  • When the program has access to source OSGi-bundles (from eclipse-SDK, for example), it automatically adds them as source-jars to their master mavenized OSGi-bundles.

  • The program publishes mavenized OSGi-bundles to maven repository, either local ($HOME/.m2/repository) or remote. Of course, you are in control of which repository is used for publishing.

As the result, you get complete and consistent representation of OSGi-bundles as a set of maven artifacts with dependencies. Combined with maven or gradle, it can greatly simplify building OSGi/eclipse applications.

Gradle plugin

Add the following to "build.gradle":

apply from: 'https://raw.github.com/akhikhl/unpuzzle/master/pluginScripts/unpuzzle.plugin'

then do "gradle installEclipse" from command-line. This will download eclipse from it's distribution site and install eclipse plugins to the local maven repository: $HOME/.m2/repository, into maven group "eclipse-kepler".

Alternatively, you can download the script from https://raw.github.com/akhikhl/unpuzzle/master/pluginScripts/unpuzzle.plugin to the project directory and include it like this:

apply from: 'unpuzzle.plugin'

or feel free copying (and modifying) the declarations from this script to your "build.gradle".

Gradle tasks

downloadEclipse

downloadEclipse task downloads and unpacks distribution of the selected Eclipse version from the official site into directory $HOME/.unpuzzle.

By default Unpuzzle downloads eclipse kepler SR1, delta-pack and eclipse-SDK. You can fine-tune, which version of eclipse is downloaded and with which add-ons by providing your own configuration.

Before downloading a distribution package this task compares file size to the one returned by HTTP HEAD request. If file size did not change, no download is performed.

Hint: you can force re-download of eclipse distribution simply by deleting *.zip and *.tar.gz files in the directory $HOME/.unpuzzle/downloaded.

installEclipse

installEclipse task mavenizes all OSGi-bundles of selected Eclipse version and installs the generated maven artifacts to local maven repository ($HOME/.m2/repository).

By default all OSGi-bundles are installed into "eclipse-kepler" maven group. You can define other maven group by providing your own configuration.

installEclipse task depends on [downloadEclipse](#downloadeclipse] task.

uninstallEclipse

uninstallEclipse task uninstalls installed OSGi-bundles of the selected Eclipse version from the local maven repository ($HOME/.m2/repository).

uninstallAllEclipseVersions

uninstallAllEclipseVersions task uninstalls installed OSGi-bundles of all Eclipse versions from the local maven repository ($HOME/.m2/repository).

uploadEclipse

uploadEclipse task mavenizes all OSGi-bundles of the downloaded eclipse distribution and installs the generated maven artifacts to remote maven repository.

You should specify [uploadEclipse configuration](#uploadEclipse-configuration] in order to make uploadEclipse work.

By default all OSGi-bundles are installed into "eclipse-kepler" maven group. You can define other maven group by providing your own configuration.

uploadEclipse task depends on [downloadEclipse](#downloadeclipse] task.

purgeEclipse

purgeEclipse task cleans everything specific to Unpuzzle plugin. Particularly, it uninstalls installed maven artifacts and deletes directory $HOME/.unpuzzle.

Package based dependencies

Dependencies for mavenized OSGi bundles are determine based on Require-Bundle and Import-Package instructions in the bundle manifests. To resolve package based dependencies an index is built over all the exported packages of the bundles available. This information is then used to find, for each Import-Package instruction, the bundles that provide the needed package.

That means that package based dependencies can only be found in the locally downloaded bundles that are part of the configured eclipse sources. Thus there may be package dependencies that cannot be satisfied. To get an overview on which packages were not found and to identify possible problems related to that, reports files are generated in the unpuzzle directory when running installEclipse or uploadEclipse:

  • unsatisfiedPackages-mandatory.json - Lists all packages that were a mandatory dependency but could not be found, for each package information is included which bundles have the dependency and which version of the package they import (Note: often this may be packages that are available in a standard JRE and can be ignored)
  • unsatisfiedPackages-optional.json - Lists all packages that were a optional dependency but could not be found, for each package information is included which bundles have the dependency and which version of the package they import

There may be multiple bundles that provide a package. All of the bundles that provide the imported package will be added as a dependency. Depending on the situation this may be desired or not. If for some reason you have different bundles representing the same library you may only want to use one of them, if you have different bundles that add different classes to a package you will probably want to include them all. There is an additional report file generated (packageExportOverlaps.json) that lists all packages that are supplied by different dependencies for you to analyse and possibly adapt the configuration if you identify any issues.

Configuration DSL

Unpuzzle works without configuration out of the box. You just apply gradle plugin, run installEclipse task and Unpuzzle does it's job with reasonable defaults.

However, there are cases when you need to fine-tune Unpuzzle. For example you might want to download/install another version of eclipse distribution.

Unpuzzle supports the following configuration DSL:

unpuzzle {

  localMavenRepositoryDir = new File(System.getProperty('user.home'), '.m2/repository')

  unpuzzleDir = new File(System.getProperty('user.home'), '.unpuzzle')

  selectedEclipseVersion = '4.3.2'

  eclipseVersion('4.3.2') {

    eclipseMavenGroup = 'eclipse-kepler'

    eclipseMirror = 'https://mirror.netcologne.de'

    eclipseArchiveMirror = 'https://archive.eclipse.org'
    
    sources {

      source "$eclipseMirror/eclipse//technology/epp/downloads/release/kepler/SR2/eclipse-jee-kepler-SR2-linux-gtk-x86_64.tar.gz"
      source "$eclipseMirror/eclipse//eclipse/downloads/drops4/R-4.3.2-201402211700/eclipse-SDK-4.3.2-linux-gtk-x86_64.tar.gz", sourcesOnly: true
      source "$eclipseMirror/eclipse//eclipse/downloads/drops4/R-4.3.2-201402211700/eclipse-4.3.2-delta-pack.zip"
      
      languagePackTemplate '${eclipseMirror}/eclipse//technology/babel/babel_language_packs/R0.11.1/kepler/BabelLanguagePack-eclipse-${language}_4.3.0.v20131123020001.zip'
      
      languagePack 'de'
      languagePack 'fr'
      languagePack 'es'
    }
  }

  artifacts {
    // a bundle can be excluded completely
    exclude('bundleToExclude')

    // or replaced by a different bundle,
    // e.g. if you have two differently named bundles with the same library
    bundle('slf4j.api') {
      replaceWith 'org.slf4j.api'
    }

    // artifacts can be adapted, for instance change artifact group, name or version
    // or prevent deployment because an existing Maven artifact should be used (e.g. from Maven Central)
    bundle('org.slf4j.api') {
      artifact {
        group = 'org.slf4j'
        name = 'slf4j-api'
        // version = stripQualifier(version)
        deploy = false
      }
    }

    // for artifacts that are not deployed (like the above example)
    // you can enable that they should be verified by trying to resolve
    // them through the Maven repositories configured in the project
    // (disabled by default)
    verifyIfNoDeploy = false

    // artifacts can also be adapted in a more general manner with a configuration
    // that is applied to all bundles (currently only one use of all { ... } is supported)
    all {
      if (name.startsWith('org.eclipse')) {
        group = 'org.eclipse'
      }
    }
  }

  uploadEclipse = [
    url: 'https://example.com/repository',
    snapshotUrl: 'https://example.com/snapshots',
    user: 'someUser',
    password: 'somePassword'
  ]
}
  • localMavenRepositoryDir - java.io.File, optional, default value is new File(System.getProperty('user.home'), '.m2/repository'). Defines which local directory is used as local maven repository for installation of eclipse artifacts.

  • unpuzzleDir - java.io.File, optional, default value is new File(System.getProperty('user.home'), '.unpuzzle'). Defines which local directory is used for caching downloaded eclipse distributions. unpuzzleDir can be safely deleted from the file system any time. Unpuzzle re-creates this directory and downloads eclipse distributions into it as needed.

  • selectedEclipseVersion - string, optional, default value is '4.3.2'. Defines which version of eclipse is to be downloaded and installed by Unpuzzle tasks.

  • eclipseVersion - function(String, Closure), multiplicity 0..n. When called, defines version-specific configuration. Unpuzzle configuration may contain multiple version-specific configurations. Only one version-specific configuration is "active" - this is defined by selectedEclipseVersion.

  • eclipseMavenGroup - string, optional, default value (for version '4.3.2') is 'eclipse-kepler-sr2'.

  • eclipseMirror - string, optional, default is 'https://mirror.netcologne.de'. Can be used for specifying common base URL.

  • eclipseArchiveMirror - string, optional, default is 'https://archive.eclipse.org'. Can be used for specifying common base URL for older packages.

  • sources - function(Closure), multiplicity 0..n.

  • source - function(Map, String), multiplicity 0..n. Essentially "source" specifies URL from which Unpuzzle should download eclipse distribution (or add-on distributions, like eclipse-SDK, delta-pack or language-packs). Additionally it acccepts the following properties:

    • sourcesOnly - optional, boolean. When specified, signifies whether the given distribution package contains only sources. Default value is false. Typical use-case: sourcesOnly=true for eclipse-SDK.
    • languagePacksOnly - optional, boolean. When specified, signifies whether the given distribution package contains only language fragments. Default value is false. Typical use-case: languagePacksOnly=true for eclipse language packs.
  • languagePackTemplate - function(String), multiplicity 0..n. Adds the specified string to the list of language-pack templates.

  • languagePack - function(String), multiplicity 0..n. Iterates all language-pack templates, for each template does:

    • substritute given language and other parameters
    • create source with the resulting url
  • uploadEclipse - optional, hashmap. See more information at uploadEclipse configuration.

Additionally the following properties are injected into version-specific configuration and can be used for calculating correct version of eclipse to download:

  • current_os - string, assigned to 'linux' or 'windows', depending on the current operating system.

  • current_arch - string assigned to 'x86_32' or 'x86_64', depending on the current processor architecture.

You can see the complete and working Unpuzzle configuration here

uploadEclipse configuration

In order to upload mavenized OSGi bundles to remote repository you need to specify three parameters: remote repository URL, user name and password. All three can be specified in one of three places, in the following priority order:

  • in "build.gradle" of the current project (project where unpuzzle gradle-plugin is being applied):
unpuzzle {
  // ...
  uploadEclipse = [
    url: 'https://example.com/repository',
    user: 'someUser',
    password: 'somePassword'
  ]
}
  • in "build.gradle" of the root project (in case of multiproject build):
ext {
  // ...
  uploadEclipse = [
    url: 'https://example.com/repository',
    user: 'someUser',
    password: 'somePassword'
  ]
}
  • in "init.gradle" script:
projectsEvaluated {
  rootProject.ext {
    uploadEclipse = [
      url: 'file:https:///home/ahi/repository',
      user: 'someUser',
      password: 'somePassword'
    ]
  }
}

It is probably not good idea to store sensitive information (like user names and passwords) within the source code of your project. Consider: if you store the source code in the version control system, everybody authorized to see the sources effectively gets he credentials to upload to your maven repository.

A healthy decision would be to use the last option - store user name and password in "init.gradle" script outside of the project. See more information about init scripts in official gradle documentation.

Configuration hierarchy

Unpuzzle configurations are hierarchical. That is: when both parent and child project are facilitated with Unpuzzle extension (i.e. when unpuzzle-plugin is included in both), child's extension inherits properties from parent's extension. Child project's extension may override or append individual properties of parent project's extension.

The following properties are overridden rather then appended:

  • localMavenRepositoryDir
  • unpuzzleDir
  • selectedEclipseVersion
  • eclipseVersion/eclipseMavenGroup
  • eclipseVersion/eclipseMirror
  • eclipseVersion/eclipseArchiveMirror
  • uploadEclipse

The following properties are appended rather then overridden:

  • eclipseVersion
  • eclipseVersion/sources
  • eclipseVersion/sources/source
  • eclipseVersion/sources/languagePackTemplate
  • eclipseVersion/sources/languagePack

Examples of hierarchical configurations are given in ConfigHierarchyTest.groovy unit-test.

Support of multiple Eclipse versions

Unpuzzle supports Eclipse versions 4.5, 4.4.2, 4.4.1, 4.4, 4.3.2, 4.3.1, 4.2.2, 4.2.1, 3.7.2, 3.7.1 out of the box. You can easily switch between Eclipse versions by simply specifying eclipse version in "build.gradle":

unpuzzle {
  selectedEclipseVersion = '3.7.1'
}

Distribution packages for these versions are predefined in internal script defaultConfig.groovy. This script is always loaded as an implicit ancestor for Unpuzzle configuration.

You are not restricted to using only the designated versions of Eclipse. Any other Eclipse versions (and any additional packages to them) could be configured in "build.gradle" using the same syntax.

Jar library API

Gradle plugin might be sufficient for the most use-cases requiring mavenizing OSGi-bundles. However, you can mavenize OSGi-bundles even without gradle plugin, just by using Unpuzzle API functions.

Good example of Unpuzzle API usage is givenhere.

Essentially, Unpuzzle API consists of four classes:

  • EclipseDownloader, implements downloading and unpacking the specified set of sources.

  • Deployer, implements deployment of single jar or directory with the specified POM to the specified repository.

  • EclipseDeployer, implements dependency resolution and deployment of multiple OSGi bundles to the specified maven group and specified Deployer.

  • EclipseSource, simple POJO class, storing information on download source.

Copyright and License

Copyright 2014-2015 (c) Andrey Hihlovskiy and contributors.

All versions, present and past, of Unpuzzle are licensed under MIT license.

About

Gradle plugin for mavenizing OSGi artifacts

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Groovy 98.9%
  • HTML 1.1%