blob: bfb238b9bc6cde9b9b5dfe58ac4e9c2c46428c28 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.ace.launcher;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.jar.Manifest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.felix.framework.util.FelixConstants;
import org.osgi.framework.Constants;
import org.osgi.framework.launch.Framework;
import org.osgi.framework.launch.FrameworkFactory;
/**
* A simple launcher, that launches the embedded Felix together with a management agent.
*/
public class Main {
private static class AdditionalBundlesOption extends KeyValueArgument {
private final List<String> m_additionalBundleActivators;
public AdditionalBundlesOption() {
super("bundle");
m_additionalBundleActivators = new ArrayList<String>();
}
/**
* @return the additionalBundleActivators
*/
public List<String> getAdditionalBundleActivators() {
return new ArrayList<String>(m_additionalBundleActivators);
}
@Override
public String getDescription() {
return "bundle: adds an additional bundle to be started with this management agent: bundle=my.fully.qualified.BundleActivator";
}
@Override
protected void doHandle(String value) {
if (!"".equals(value.trim()) && !m_additionalBundleActivators.contains(value)) {
m_additionalBundleActivators.add(value);
}
}
}
private interface Argument {
String getDescription();
void handle(String argument);
}
private static class FrameworkOption extends KeyValueArgument {
private Properties m_properties = new Properties();
public FrameworkOption() {
super("fwOption");
}
public String getDescription() {
return "fwOption: sets framework options for the OSGi framework to be created. This argument may be repeated";
}
public Properties getProperties() {
return m_properties;
}
@Override
protected void doHandle(String value) {
Pattern pattern = Pattern.compile("([^=]*)=(.*)");
Matcher m = pattern.matcher(value);
if (!m.matches()) {
throw new IllegalArgumentException(value + " is not a valid framework option.");
}
m_properties.put(m.group(1), m.group(2));
}
}
private static abstract class KeyValueArgument implements Argument {
protected final String m_key;
public KeyValueArgument(String key) {
m_key = key;
}
public void handle(String argument) {
Pattern pattern = Pattern.compile(m_key + "=(.*)");
Matcher m = pattern.matcher(argument);
if (m.matches()) {
doHandle(m.group(1));
}
}
protected abstract void doHandle(String value);
}
private static class SystemPropertyArgument extends KeyValueArgument {
private final String m_description;
public SystemPropertyArgument(String key, String description) {
super(key);
m_description = description;
}
@Override
public String getDescription() {
return m_key + ": " + m_description;
}
@Override
protected void doHandle(String value) {
System.setProperty(m_key, value);
}
}
private static final boolean m_quiet = Boolean.parseBoolean(System.getProperty("quiet", "false"));
/**
* MAIN ENTRY POINT
*
* @param args
* the command line arguments, never <code>null</code>.
* @throws Exception
* in case of errors.
*/
public static void main(String[] args) throws Exception {
new Main(args).run();
}
private final FrameworkOption m_fwOptionHandler;
private final AdditionalBundlesOption m_additionalBundleHandler;
/**
* Creates a new {@link Main} instance.
*
* @param args
* the command line arguments, never <code>null</code>.
*/
public Main(String[] args) {
m_additionalBundleHandler = new AdditionalBundlesOption();
m_fwOptionHandler = new FrameworkOption();
final List<Argument> arguments = new ArrayList<Argument>();
Argument agents = new SystemPropertyArgument("agents", "configures multiple management agents: agent-id,identification,discovery[;agent-id,identification,discovery]*");
Argument auth = new SystemPropertyArgument("auth", "point to the properties file containing the authentication credentials for a certain subsystem: <dir/file/url>");
Argument discovery = new SystemPropertyArgument("discovery", "sets the ACE server to connect to");
Argument identification = new SystemPropertyArgument("id(?:entification)?", "sets the target ID to use") {
@Override
protected void doHandle(String value) {
System.setProperty("identification", value);
}
};
Argument help = new Argument() {
public String getDescription() {
return "help: prints this help message";
}
public void handle(String argument) {
if ("help".equals(argument)) {
showHelp(arguments);
System.exit(0);
}
}
};
arguments.addAll(Arrays.asList(agents, auth, discovery, identification, m_additionalBundleHandler, m_fwOptionHandler, help));
for (String arg : args) {
for (Argument argument : arguments) {
argument.handle(arg);
}
}
}
public void run() throws Exception {
Map frameworkProperties = createFrameworkProperties();
FrameworkFactory factory = createFrameworkFactory();
Framework framework = factory.newFramework(frameworkProperties);
framework.start();
try {
framework.waitForStop(0);
}
finally {
System.exit(0);
}
}
/**
* @param extraSystemPackages
* @return
*/
private String getExtraSystemPackages(String[] extraSystemPackages) {
String isolateMA = System.getProperty("isolateMA", "managementagent");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < extraSystemPackages.length; i++) {
if (i > 0) {
sb.append(",");
}
sb.append(extraSystemPackages[i]);
if (isolateMA != null && !"".equals(isolateMA.trim())) {
sb.append(String.format(";%1$s=true;mandatory:=%1$s", isolateMA));
}
}
return sb.toString();
}
/**
* @return
*/
private FrameworkFactory createFrameworkFactory() {
try {
Class<?> clazz = Class.forName("org.apache.felix.framework.FrameworkFactory");
return (FrameworkFactory) clazz.newInstance();
}
catch (Exception e) {
throw new RuntimeException("Failed to create framework factory?!", e);
}
}
/**
* @return
* @throws Exception
*/
private Map createFrameworkProperties() throws Exception {
String[] extraSystemPackageArray = {
"org.osgi.service.deploymentadmin;version=\"1.0\"",
"org.osgi.service.deploymentadmin.spi;version=\"1.0\"",
"org.osgi.service.cm;version=\"1.3\"",
"org.osgi.service.event;version=\"1.2\"",
"org.osgi.service.log;version=\"1.3\"",
"org.osgi.service.metatype;version=\"1.1\"",
"org.apache.felix.dm;version=\"3.0\"",
"org.apache.felix.dm.tracker;version=\"3.0\"",
"org.apache.ace.log;version=\"0.8\"",
"org.apache.ace.deployment.service;version=\"0.8\""
};
Map frameworkProperties = new HashMap();
frameworkProperties.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, getSystemBundleActivators());
frameworkProperties.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, getExtraSystemPackages(extraSystemPackageArray));
frameworkProperties.putAll(m_fwOptionHandler.getProperties());
return frameworkProperties;
}
/**
* @return
* @throws IOException
*/
private List<String> getAdditionalBundleActivators() throws IOException {
List<String> bundleActivators = m_additionalBundleHandler.getAdditionalBundleActivators();
// The actual management agent itself...
bundleActivators.add(0, "org.apache.ace.managementagent.Activator");
// Pull in all the additional mentioned bundles on the classpath...
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Enumeration<URL> resources = cl.getResources("META-INF/MANIFEST.MF");
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
try {
Manifest mf = new Manifest(resource.openStream());
String bundleActivator = mf.getMainAttributes().getValue(Constants.BUNDLE_ACTIVATOR);
if (bundleActivator != null) {
bundleActivators.add(bundleActivator);
}
}
catch (Exception e) {
System.err.println("Failed to read resource: " + resource + "!\nPossible reason: " + e);
}
}
return bundleActivators;
}
/**
* @return
* @throws Exception
*/
private List<Object> getSystemBundleActivators() throws Exception {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
List<Object> result = new ArrayList<Object>();
List<String> bundleActivators = getAdditionalBundleActivators();
for (String bundleActivator : bundleActivators) {
try {
Object instance = cl.loadClass(bundleActivator).newInstance();
if (!m_quiet) {
System.out.println("Adding additional bundle activator: " + bundleActivator);
}
result.add(instance);
}
catch (Exception e) {
System.err.println("Failed to add bundle activator: " + bundleActivator + "!\nPossible reason: " + e);
}
}
return result;
}
private void showHelp(List<Argument> arguments) {
System.out.println("Apache ACE Launcher\n"
+ "Usage:\n"
+ " java -jar ace-launcher.jar [identification=<id>] [discovery=<ace-server>] [options...]");
System.out.println("All known options are:");
for (Argument argument : arguments) {
System.out.println(" " + argument.getDescription());
}
System.out.println("Example:\n"
+ " java -jar ace-launcher.jar identification=MyTarget discovery=http://provisioning.company.com:8080 "
+ "fwOption=org.osgi.framework.system.packages.extra=sun.misc,com.sun.management");
}
}