blob: 2765e457d2edcfc2df3aa353123b4a53363fea14 [file] [log] [blame]
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.felix.atomos.launch;
import java.io.File;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;
import org.apache.felix.atomos.impl.runtime.base.AtomosRuntimeBase;
import org.apache.felix.atomos.runtime.AtomosLayer;
import org.apache.felix.atomos.runtime.AtomosRuntime;
import org.osgi.framework.BundleException;
import org.osgi.framework.connect.ConnectFrameworkFactory;
import org.osgi.framework.launch.Framework;
/**
* The Atomos launcher contains convenience methods for creating and launching
* an OSGi {@link Framework} instance with the Atomos runtime.
*/
@org.osgi.annotation.bundle.Header(name = "Main-Class", value = org.apache.felix.atomos.launch.AtomosLauncher.ATOMOS_LAUNCHER)
public class AtomosLauncher
{
// package private constant use to specify the main class
static final String ATOMOS_LAUNCHER = "org.apache.felix.atomos.launch.AtomosLauncher";
/**
* A main method that can be used by executable jars to initialize and start an
* Atomos Runtime with an available OSGi {@link Framework} implementation.
* Each string in the arguments array may contain a key=value
* pair that will be used for the framework configuration.
*
* @param args the args will be converted into a {@code Map<String, String>} to
* use as configuration parameters for the OSGi Framework.
* @throws BundleException when an error occurs
* @see AtomosLauncher#launch(Map)
*/
public static void main(String[] args) throws BundleException
{
launch(getConfiguration(args));
}
/**
* A configuration option used by {@link #launch(Map)} which can be used to
* configuration a modules folder to load additional Atomos contents from.
*/
public static final String ATOMOS_MODULES_DIR = "atomos.modules";
/**
* Convenience method that creates an AtomosRuntime in order to load the Atomos
* contents discovered in the environment. If additional layers are supported by the
* environment (see {@link AtomosLayer#isAddLayerSupported()} then additional modules
* may be loaded into a child layer by looking for a
* modules folder. The path to the modules folder can be configured by using the
* {@link #ATOMOS_MODULES_DIR atomos.modules} launch option.
* If the {@link #ATOMOS_MODULES_DIR atomos.modules}
* option is not specified in the frameworkConfig then the default will try to
* determine the location on disk of the Atomos runtime module and look for a
* folder called "modules". If the location of the Atomos Runtime module
* cannot be determined then no additional modules folder will be searched.
*
* @param frameworkConfig the framework configuration
* @return a new framework instance which has been started with the Atomos runtime.
* @throws BundleException if an error occurred creating and starting the framework
* @see AtomosLauncher#newFramework(Map, AtomosRuntime)
*/
public static Framework launch(Map<String, String> frameworkConfig)
throws BundleException
{
frameworkConfig = new HashMap<>(frameworkConfig);
// default to reporting resolution issues from launcher
frameworkConfig.putIfAbsent(AtomosRuntimeBase.ATOMOS_REPORT_RESOLUTION_PROP,
"true");
AtomosRuntime atomosRuntime = AtomosRuntime.newAtomosRuntime(frameworkConfig);
if (atomosRuntime.getBootLayer().isAddLayerSupported())
{
String modulesDirPath = frameworkConfig.get(ATOMOS_MODULES_DIR);
Path modulesPath = modulesDirPath == null ? null
: new File(modulesDirPath).toPath();
atomosRuntime.getBootLayer().addModules("modules", modulesPath);
}
Framework framework = newFramework(frameworkConfig, atomosRuntime);
framework.start();
return framework;
}
/**
* Converts a string array into a {@code Map<String,String>}
*
* @param args the arguments where each element has key=string value, the key
* cannot contain an '=' (equals) character.
* @return a map of the configuration specified by the args
*/
public static Map<String, String> getConfiguration(String[] args)
{
Map<String, String> config = new HashMap<>();
if (args != null)
{
for (String arg : args)
{
int equals = arg.indexOf('=');
if (equals != -1)
{
String key = arg.substring(0, equals);
String value = arg.substring(equals + 1);
config.put(key, value);
}
}
}
return config;
}
/**
* Creates a new {@link Framework} instance that uses the specified Atomos runtime,
* or creates a new Atomos runtime to use if a runtime is not specified. The
* {@link ServiceLoader} is used to load an implementation of a {@link ConnectFrameworkFactory}
* which is used to create a new {@link Framework} instance with the specified Atomos runtime.
* The supplied framework configuration is used to create the new {@code Framework} instance.
* Additional configuration options maybe configured automatically in order to correctly configure
* the system packages for the {@code Framework} instance.
* @param frameworkConfig The framework configuration options, or {@code null} if the defaults should be used
* @param atomosRuntime The Atomos runtime, or {@code null} will create a new Atomos runtime
* @return The new uninitialized Framework instance which uses the Atomos runtime
*/
public static Framework newFramework(Map<String, String> frameworkConfig,
AtomosRuntime atomosRuntime)
{
if (atomosRuntime == null)
{
atomosRuntime = AtomosRuntime.newAtomosRuntime();
}
frameworkConfig = frameworkConfig == null ? new HashMap<>()
: new HashMap<>(frameworkConfig);
((AtomosRuntimeBase) atomosRuntime).populateConfig(frameworkConfig);
// Always allow the console to work
frameworkConfig.putIfAbsent("osgi.console", "");
return ((AtomosRuntimeBase) atomosRuntime).findFrameworkFactory().newFramework(
frameworkConfig, atomosRuntime.getModuleConnector());
}
}