Chameleon Core

Chameleon Core is a basic infrastructure to assemble and run OSGi applications. It provides a common runtime with a logging backend, a configuration agent, a basic provisioning solution and a flexible component model. Based on that, it is possible to create sophisticated OSGi-based runtimes.

Chameleon Core and Chameleon (instance)

The Chameleon core is the common runtime. It a framework embedding an OSGi framework and providing some core features:

  • Apache Felix iPOJO
  • Configuration Admin
  • A static and dynamic provisioning solution
  • A log backend
When starting, the core deploys 'core' bundles as well as bundles placed in:
  • a runtime directory : containing technical services and configuration files. It's a static folder (no update)
  • an application directory : containing application bundles and configuration files. It's a static folder (no update)
  • a deploy directory : containing bundles and configuration files. It's a dynamic folder. To changes are tracked and reflected to the framework.
Thanks to such features, it's easy to create custom runtime (named chameleon instance (or color)), by just copying bundles to the appropriate directories. As an example, let's imagine an OSGi web server. You just need to copy an HTTP Service, an embedded database and any other required bundles in the runtime directory. Then, copy the kernel of your application in the application directory. You can also copy the (dynamic) extensions of your application in the deploy directory.

Structure of a Chameleon instance

The structure of a Chameleon instance is pretty simple:

root
|- core -> contains chameleon core bundles
|- runtime -> contains the technical services and configuration
|- application -> contains the application bundles and configuration
|- deploy -> contains a dynamic set of bundles and configuration
|- log -> contains the default chameleon log file
|chameleon.properties -> chameleon configuration
|system.properties -> system properties

Obviously you can configure the location of the core, runtime, application, deploy, log from the command line and from the chameleon properties. The location of the chameleon properties can also be configured from the command line.

Only the core directory is necessary. The other directories are optional.

Launching a Chameleon instance

Chameleon Core provides a standard way to launch a Chameleon. From the root of your chameleon, just execute the following command:

java -jar core/core-0.4.0.jar

Note: Change the 0.4.0 by the exact version. Note: Scripts are also provided

Chameleon supports several parameters:

ArgumentDefault
--corecoreDefines the core directory (--core=mycore)
--runtimeruntimeDefines the runtime directory (--runtime=myruntime)
--appapplicationDefines the application directory (--app=myapp)
--deploydeployDefines the deploy directory (--deploy=mydeploy)
--debugNo debugEnables the debug mode. It will provide a shell (Felix Shell)
-- configchameleon.propertiesSet the configuration file location
--systemsystem.propertiesLoads the content of this property file as system properties

For example, the following command launches a Chameleon using my??? directories and enabling the debug mode:

java -jar core/core-0.4.0.jar
   --core=mycore
   --app=myapp 
   --runtime=myruntime
   --deploy=mydeploy
   --debug

Configuring a Chameleon instance

Chameleon instances can also be configured from a configuration file. The --config= argument allows setting the location of this file. Supported properties are:

PropertyDefault
chameleon.log.dirlogset the directory in which the log will be stored
chameleon.log.levelinfoset the chameleon log level
chameleon.log.enabledtrueset to false to disable the log backend
chameleon.runtimeruntimeset the runtime directory
chameleon.applicationapplicationset the application directory
chameleon.corecoreset the core directory
chameleon.deploydeployset the deploy directory

Log framework and back-end

Chameleon Core provides logging features:

  • applications deployed in a chameleon can use the SLF4J logging API. Messages will be logged on the chameleon log file
  • if applications use an OSGi log service, log entries will also be stored on the chameleon log file
Chameleon does not provide an OSGi log service as the implementation choice depends on the application (Apache Felix Log, OPS4J Pax Logging...). But, you can choose your favorite implementation and deploy it.

By default, the log backend is logback, and log messages are stored in the 'log' folder (in an HTML file). However, you can override the log backend configuration by just adding a logback.xml file in your classpath. (See the logback web site for further information: http://logback.qos.ch/).

LogBack was chosen for its configuration features, but can be replaced. The Chameleon Core code does not depend on LogBack, so you can just use any SLF4J backend. Moreover, you can use any other log viewer such as Chainsaw or Lilith.

Exploded bundles

Chameleon uses the reference protocol to install bundles. This avoids the need to copy the bundles in the OSGi framework cache. Moreover, Chameleon supports exploded bundles for runtime and application. If you place an exploded bundle inside its own folder, it will be installed as the other bundles. This avoids having the framework unzip the jar.

Customize a Chameleon with MAVEN

Maven can be used to create Chameleon instances. To achieve that task, you just configure a Maven project creating the chameleon structure. Chameleon core provides a distribution package containing the scripts and the core bundles.

So, just declare a dependency on this distribution:

<dependency>
        <groupId>org.ow2.chameleon</groupId>
        <artifactId>core</artifactId>
        <classifier>distribution</classifier>
        <type>zip</type>
        <version>${chameleon.version}</version>
</dependency>

And then unzip this artifact to your destination folder with the maven-dependency-plugin:

<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-dependency-plugin</artifactId>
   <version>2.1</version>
   <executions>
       <execution>
           <id>copy-core</id>
           <phase>process-resources</phase>
           <goals>
               <goal>unpack-dependencies</goal>
           </goals>
           <configuration>
               <includes>**/*.jar</includes>
               <outputDirectory>${project.build.directory}/mychameleon</outputDirectory>
               <overWriteReleases>false</overWriteReleases>
               <overWriteSnapshots>true</overWriteSnapshots>
               <includeArtifactIds>core</includeArtifactIds>
               <includeClassifiers>distribution</includeClassifiers>
           </configuration>
       </execution>
    </executions>
</plugin>

To add other bundles, you can still use the maven-dependency-plugin to copy them to the appropriate directory (runtime or application):

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <extensions>true</extensions>
        <executions>
          <execution>
            <id>copy-runtime</id>
            <phase>compile</phase>
            <goals>
              <goal>copy</goal>
            </goals>
            <configuration>
              <artifactItems>
                <artifactItem>
                  <groupId>org.apache.felix</groupId>
                  <artifactId>org.apache.felix.log</artifactId>
                  <version>1.0.0</version>
                  <overWrite>false</overWrite>
                  <outputDirectory>${project.build.directory}/mychameleon/${runtime.dir}</outputDirectory>
                </artifactItem>
                <artifactItem>
                  <groupId>org.ops4j.pax.web</groupId>
                  <artifactId>pax-web-jsp</artifactId>
                  <version>0.7.0</version>
                  <overWrite>false</overWrite>
                  <outputDirectory>${project.build.directory}/mychameleon/${runtime.dir}</outputDirectory>
                </artifactItem>
                <artifactItem>
                  <groupId>org.ops4j.pax.web</groupId>
                  <artifactId>pax-web-jetty-bundle</artifactId>
                  <version>0.7.0</version>
                  <overWrite>false</overWrite>
                  <outputDirectory>${project.build.directory}/mychameleon/${runtime.dir}</outputDirectory>
                </artifactItem>
              </artifactItems>
            </configuration>
          </execution>
        </executions>
</plugin>

Once configured, you can build your chameleon with:

mvn clean package

All bundles will be copied to the correct directory. The 'core' will be also created (from the parent configuration). You can go further and zip your chameleon configuration thanks to the maven-assembly-plugin.

Using Equinox (or any other OSGi R4.2 implementation)

By default, Chameleon uses Felix and Chameleon distributions come with Felix, but it is simple to use any other OSGi R4.2 implementation. This section explains how to use Equinox.

  1. Download Equinox from http://www.eclipse.org/downloads/download.php
  2. Copy the downloaded file in the core directory of your chameleon
  3. Launch your chameleon with
java -cp core/core-0.2.6.jar:core/logback-classic-0.9.21.jar:core/org.osgi.compendium-1.4.2.jar:core/logback-core-0.9.9.jar:core/org.eclipse.osgi_3.5.1.R35x_v20090827.jar:core/slf4j-api-1.6.1.jar org.ow2.chameleon.core.Main

Note: Change the equinox jar name.

All chameleon features are available, like log backend, provisioning …