Java tutorial
/* * Copyright 2007 Alin Dreghiciu. * * 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.ops4j.pax.runner.platform.felix.internal; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.ops4j.lang.NullArgumentException; import org.ops4j.pax.runner.platform.*; import org.ops4j.util.collections.PropertiesWriter; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.util.*; /** * Platform builder for felix platform. */ public abstract class FelixPlatformBuilder implements PlatformBuilder { /** * Logger. */ protected final Log LOGGER = LogFactory.getLog(this.getClass()); /** * Provider name to be used in registration. */ private static final String PROVIDER_NAME = "felix"; /** * Name of the main class from Felix. */ private static final String MAIN_CLASS_NAME = "org.apache.felix.main.Main"; /** * The directory name where the configuration will be stored. */ protected static final String CONFIG_DIRECTORY = "felix"; /** * Configuration file name. */ private static final String CONFIG_INI = "config.ini"; /** * Caching directory. */ protected static final String CACHE_DIRECTORY = "cache"; /** * Profile name to be used when console should be started. */ private static final String CONSOLE_PROFILE = "tui"; /** * Separator for properties (bundles) */ private static final String SEPARATOR = " "; /** * Current bundle context. */ private final BundleContext m_bundleContext; /** * Supported version. */ private final String m_version; /** * Create a new felix platform builder. * * @param bundleContext a bundle context * @param version supported version */ public FelixPlatformBuilder(final BundleContext bundleContext, final String version) { NullArgumentException.validateNotNull(bundleContext, "Bundle context"); NullArgumentException.validateNotNull(version, "Version"); m_bundleContext = bundleContext; m_version = version; } /** * Creates a config.ini file under the working directory/felix directory. * * @see org.ops4j.pax.runner.platform.PlatformBuilder * #prepare(org.ops4j.pax.runner.platform.PlatformContext) */ public void prepare(final PlatformContext context) throws PlatformException { NullArgumentException.validateNotNull(context, "Platform context"); final List<BundleReference> bundles = context.getBundles(); OutputStream os = null; try { final File workingDirectory = context.getWorkingDirectory(); // make sure the configuration directory exists final File configDirectory = new File(workingDirectory, CONFIG_DIRECTORY); configDirectory.mkdirs(); // create the configuration file final File configFile = new File(configDirectory, CONFIG_INI); configFile.createNewFile(); LOGGER.debug("Create felix configuration ini file [" + configFile + "]"); final Configuration configuration = context.getConfiguration(); os = new FileOutputStream(configFile); final PropertiesWriter writer = new PropertiesWriter(os, SEPARATOR); writeHeader(writer); writer.append("#############################"); writer.append(" Felix settings"); writer.append("#############################"); // framework start level { final Integer startLevel = configuration.getStartLevel(); if (startLevel != null) { writer.append(getFrameworkStartLevelPropertyName(), startLevel.toString()); } } // bundle start level { final Integer bundleStartLevel = configuration.getBundleStartLevel(); if (bundleStartLevel != null) { writer.append("felix.startlevel.bundle", bundleStartLevel.toString()); } } this.appendFrameworkStorage(context, writer); // execution environments { writer.append(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, context.getExecutionEnvironment()); } // boot delegation packages { final String bootDelegation = context.getConfiguration().getBootDelegation(); if (bootDelegation != null) { writer.append(Constants.FRAMEWORK_BOOTDELEGATION, bootDelegation); } } // system packages { writer.append(Constants.FRAMEWORK_SYSTEMPACKAGES, context.getSystemPackages()); } if (bundles != null && bundles.size() > 0) { writer.append(); writer.append("#############################"); writer.append(" Client bundles to install"); writer.append("#############################"); appendBundles(writer, bundles, context, configuration.getBundleStartLevel()); } writer.append(); writer.append("#############################"); writer.append(" System properties"); writer.append("#############################"); appendProperties(writer, context.getProperties()); writer.write(); } catch (IOException e) { throw new PlatformException("Could not create felix configuration file", e); } finally { if (os != null) { try { os.close(); } catch (IOException e) { //noinspection ThrowFromFinallyBlock throw new PlatformException("Could not create felix configuration file", e); } } } } /** * Writes framework storage settings to configuration file * * @param context the platform context * @param writer a property writer */ protected abstract void appendFrameworkStorage(final PlatformContext context, final PropertiesWriter writer); /** * Writes properties to configuration file. * * @param writer a property writer * @param properties properties to be written; can be null */ private void appendProperties(final PropertiesWriter writer, final Properties properties) { if (properties != null) { final Enumeration<?> enumeration = properties.propertyNames(); while (enumeration.hasMoreElements()) { final String key = (String) enumeration.nextElement(); writer.append(key, properties.getProperty(key)); } } } /** * Writes bundles to configuration file. * * @param writer a property writer * @param bundles bundles to write * @param context platform context * @param defaultStartlevel default start level for bundles. used if no start level is set on bundles. * * @throws java.net.MalformedURLException re-thrown from getting the file url * @throws org.ops4j.pax.runner.platform.PlatformException * if one of the bundles does not have a file */ private void appendBundles(final PropertiesWriter writer, final List<BundleReference> bundles, final PlatformContext context, final Integer defaultStartlevel) throws MalformedURLException, PlatformException { for (BundleReference reference : bundles) { URL url = reference.getURL(); if (url == null) { throw new PlatformException("The file from bundle to install cannot be null"); } final StringBuilder propertyName = new StringBuilder().append("felix.auto"); final Boolean shouldStart = reference.shouldStart(); if (shouldStart != null && shouldStart) { propertyName.append(".").append("start"); } else { propertyName.append(".").append("install"); } Integer startLevel = reference.getStartLevel(); if (startLevel == null) { startLevel = defaultStartlevel; } if (startLevel != null) { propertyName.append(".").append(startLevel); } // PAXRUNNER-41 // url of the file must be quoted otherwise will be considered as two separated files by Felix writer.append(propertyName.toString(), "\"" + context.getFilePathStrategy().normalizeAsUrl(url) + "\""); } } /** * Writes OPS4j header. * * @param writer a property writer */ private void writeHeader(final PropertiesWriter writer) { writer.append("###############################################"); writer.append(" ______ ________ __ __ #"); writer.append(" / __ / / __ / / / / / #"); writer.append(" / ___/ / __ / _\\ \\ _/ #"); writer.append(" / / / / / / / _\\ \\ #"); writer.append(" /__/ /__/ /__/ /_/ /_/ #"); writer.append(" #"); writer.append(" Pax Runner from OPS4J - http://www.ops4j.org #"); writer.append("###############################################"); writer.append(); } /** * @see org.ops4j.pax.runner.platform.PlatformBuilder#getMainClassName() */ public String getMainClassName() { return MAIN_CLASS_NAME; } /** * @see org.ops4j.pax.runner.platform.PlatformBuilder * #getArguments(org.ops4j.pax.runner.platform.PlatformContext) */ public String[] getArguments(final PlatformContext context) { // there are no arguments to pass to Main for felix return null; } /** * @see org.ops4j.pax.runner.platform.PlatformBuilder * #getVMOptions(org.ops4j.pax.runner.platform.PlatformContext) */ public String[] getVMOptions(final PlatformContext context) { NullArgumentException.validateNotNull(context, "Platform context"); final Collection<String> vmOptions = new ArrayList<String>(); final File workingDirectory = context.getWorkingDirectory(); vmOptions.add("-Dfelix.config.properties=" + context.getFilePathStrategy() .normalizeAsUrl(new File(new File(workingDirectory, CONFIG_DIRECTORY), CONFIG_INI))); // TODO http://team.ops4j.org/browse/PAXSCANNER-23?focusedCommentId=18236&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-18236 final Properties frameworkProperties = context.getProperties(); if (frameworkProperties != null) { final Enumeration<?> enumeration = frameworkProperties.propertyNames(); while (enumeration.hasMoreElements()) { final String key = (String) enumeration.nextElement(); String property = frameworkProperties.getProperty(key); String quotedProperty = property.replace("\"", "\\\""); if (property.length() < quotedProperty.length() || property.indexOf(' ') >= 0) { property = '"' + quotedProperty + '"'; } StringBuilder vmOption = new StringBuilder(2 + key.length() + 1 + property.length()); vmOption.append("-D"); vmOption.append(key); if (property.length() > 0) { vmOption.append('='); vmOption.append(property); } vmOptions.add(vmOption.toString()); } } return vmOptions.toArray(new String[vmOptions.size()]); } /** * {@inheritDoc} */ public InputStream getDefinition(final Configuration configuration) throws IOException { final String definitionFile = "META-INF/platform-felix/definition-" + m_version + ".xml"; final URL url = m_bundleContext.getBundle().getResource(definitionFile); if (url == null) { throw new FileNotFoundException(definitionFile + " could not be found"); } return url.openStream(); } /** * If the console option is set then it will return the tui profile otherwise will return null. * * @see org.ops4j.pax.runner.platform.PlatformBuilder * #getRequiredProfile(org.ops4j.pax.runner.platform.PlatformContext) */ public String getRequiredProfile(final PlatformContext context) { final String profile = context.getConfiguration().getFrameworkProfile(); if (profile != null && !"runner".equals(profile)) { return profile; } final Boolean console = context.getConfiguration().startConsole(); if (console == null || !console) { return null; } else { return CONSOLE_PROFILE; } } /** * @see Object#toString() */ public String toString() { return "Felix " + m_version; } /** * @see org.ops4j.pax.runner.platform.PlatformBuilder#getProviderName() */ public String getProviderName() { return PROVIDER_NAME; } /** * @see org.ops4j.pax.runner.platform.PlatformBuilder#getProviderVersion() */ public String getProviderVersion() { return m_version; } /** * Return the name of property specifying the framework start level. * * @return property name */ protected abstract String getFrameworkStartLevelPropertyName(); }