Package org.apache.karaf.eik.felix

Source Code of org.apache.karaf.eik.felix.FelixLaunchConfiguration

/*
* 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.karaf.eik.felix;

import org.apache.karaf.eik.felix.internal.BundleEntry;
import org.apache.karaf.eik.felix.internal.FelixLaunchHelper;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.launching.ExecutionArguments;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.core.plugin.PluginRegistry;
import org.eclipse.pde.ui.launcher.AbstractPDELaunchConfiguration;
import org.eclipse.pde.ui.launcher.IPDELauncherConstants;
import org.osgi.framework.Bundle;

public class FelixLaunchConfiguration extends AbstractPDELaunchConfiguration {

    public static final String FELIX_FRAMEWORK_LAUNCHER = "org.apache.felix.main";

    public static final String FELIX_FRAMEWORK = "org.apache.felix.framework";

    public static final String FELIX_SYSTEM_PROPERTIES_KEY = "felix.system.properties";

    public static final String FELIX_CONFIG_PROPERTIES_KEY = "felix.config.properties";

    public static final String FELIX_AUTO_START_PREFIX = "felix.auto.start.";

    public static final String FELIX_AUTO_INSTALL_PREFIX = "felix.auto.install.";

    public static final String FELIX_CONFIG_PROPERTIES_FILE = "config.properties";

    public static final String FELIX_SYSTEM_PROPERTIES_FILE = "system.properties";

    public static final int DEFAULT_START_LEVEL = 4;

    public static final boolean DEFAULT_AUTOSTART = true;

    /**
     * Implementation of join using a {@link StringBuffer}
     *
     * @param items
     *            the {@link Collection} of items that will be joined together
     * @param glue
     *            the string to act as glue in the concatenation
     * @return the concatenation of the specified items
     */
    public static String join(Collection<String> items, String glue) {
        final StringBuffer buffer = new StringBuffer();
        for (String s : items) {
            if (buffer.length() > 0) {
                buffer.append(glue);
            }

            buffer.append(s);
        }

        return buffer.toString();
    }

    /**
     * Gets the path to the specified bundle in the following manner:<br>
     * <br>
     * <ol>
     * <li>If the bundle is found in the Plug-in Registry and is not a workspace
     * resource, return the path to the bundle</li>
     * <li>If the bundle is in the Plug-in Registry but is a workspace resource,
     * return the path to the path to the output location that contains the
     * package specified ({@code project/output folder})</li>
     * <li>If the bundle is not found in the Plug-in Registry then look for it
     * in the OSGi platform</li>
     * </ol>
     *
     * @param bundleName
     *            the symbolic name of the bundle
     * @param packageName
     *            the name of the package used to locate the output folder
     * @return a fully qualified path to the requested bundle or null if it does
     *         not exist
     * @throws CoreException
     */
    private static String getBundlePath(String bundleName, String packageName) throws CoreException {
        final IPluginModelBase model = PluginRegistry.findModel(bundleName);
        if (model != null) {
            final IResource resource = model.getUnderlyingResource();

            if (!isWorkspaceModel(model)) {
                return model.getInstallLocation();
            }

            final IProject project = resource.getProject();
            if (project.hasNature(JavaCore.NATURE_ID)) {
                final IJavaProject jProject = JavaCore.create(project);
                final IClasspathEntry[] entries = jProject.getRawClasspath();

                for (int i = 0; i < entries.length; i++) {
                    final int kind = entries[i].getEntryKind();
                    if (kind == IClasspathEntry.CPE_SOURCE || kind == IClasspathEntry.CPE_LIBRARY) {
                        final IPackageFragmentRoot[] roots = jProject.findPackageFragmentRoots(entries[i]);

                        for (int j = 0; j < roots.length; j++) {
                            if (roots[j].getPackageFragment(packageName).exists()) {
                                // if source folder, find the output folder
                                if (kind == IClasspathEntry.CPE_SOURCE) {
                                    IPath path = entries[i].getOutputLocation();
                                    if (path == null) {
                                        path = jProject.getOutputLocation();
                                    }

                                    path = path.removeFirstSegments(1);

                                    return project.getLocation().append(path).toOSString();
                                }
                                // else if is a library jar, then get the
                                // location of the jar itself
                                final IResource jar = roots[j].getResource();
                                if (jar != null) {
                                    return jar.getLocation().toOSString();
                                }
                            }
                        }
                    }
                }
            }
        }

        final Bundle bundle = Platform.getBundle(bundleName);
        if (bundle != null) {
            try {
                URL url = FileLocator.resolve(bundle.getEntry("/")); //$NON-NLS-1$
                url = FileLocator.toFileURL(url);
                String path = url.getFile();
                if (path.startsWith("file:")) { //$NON-NLS-1$
                    path = path.substring(5);
                }

                path = new File(path).getAbsolutePath();

                if (path.endsWith("!")) { //$NON-NLS-1$
                    path = path.substring(0, path.length() - 1);
                }

                return path;
            } catch (IOException e) {
            }
        }

        return null;
    }

    /**
     * Uses the Eclipse Variables plugin to perform string substitution on the
     * input string
     *
     * @param text
     *            the input string that potentially contains variables that need
     *            to be resolved
     * @return the fully interpolated string
     * @throws CoreException
     */
    private static String getSubstitutedString(String text) throws CoreException {
        if (text == null) {
            return ""; //$NON-NLS-1$
        }

        final IStringVariableManager mgr = VariablesPlugin.getDefault().getStringVariableManager();
        return mgr.performStringSubstitution(text);
    }

    /**
     * Determines if the {@link IPluginModelBase} is a workspace resource
     *
     * @param model
     *            the {@code IPluginModelBase} to test
     * @return true if it is a workspace resource, false otherwise
     */
    private static boolean isWorkspaceModel(IPluginModelBase model) {
        return (model.getUnderlyingResource() != null);
    }

    /**
     * Helper method to write a properties file to the specified filename
     *
     * @param filename
     *            the fully qualfied filename
     * @param props
     *            the {@link Properties} to be stored
     * @throws CoreException
     */
    private static void writeProperties(String filename, Properties props) throws CoreException {
        try {
            final OutputStream out = new FileOutputStream(new File(filename));
            props.store(out, FelixLaunchConfiguration.class.getName());
            out.close();
        } catch (IOException e) {

        }
    }

    // used to generate the dev classpath entries
    // key is bundle ID, value is a model
    protected Map<String, IPluginModelBase> fAllBundles;

    // key is a model, value is startLevel:autoStart
    private Map<IPluginModelBase, String> fModels;

    /*
     * Apache Felix requires that the launcher and the Felix Framework be on the
     * initial classpath.
     *
     * @see
     * org.eclipse.pde.ui.launcher.AbstractPDELaunchConfiguration#getClasspath
     * (org.eclipse.debug.core.ILaunchConfiguration)
     */
    @Override
    public String[] getClasspath(ILaunchConfiguration configuration) throws CoreException {
        final String felixLauncherPath = getBundlePath(FELIX_FRAMEWORK_LAUNCHER, FELIX_FRAMEWORK_LAUNCHER);
        if (felixLauncherPath == null) {

        }

        final String felixFrameworkPath = getBundlePath(FELIX_FRAMEWORK, FELIX_FRAMEWORK);
        if (felixFrameworkPath == null) {

        }

        final List<String> entries = new ArrayList<String>();
        entries.add(felixLauncherPath);
        entries.add(felixFrameworkPath);

        /*
         * Add any boostrap entries provided by the user
         */
        final String bootstrap = configuration.getAttribute(IPDELauncherConstants.BOOTSTRAP_ENTRIES, ""); //$NON-NLS-1$
        final StringTokenizer tok = new StringTokenizer(getSubstitutedString(bootstrap), ","); //$NON-NLS-1$
        while (tok.hasMoreTokens()) {
            entries.add(tok.nextToken().trim());
        }

        return entries.toArray(new String[entries.size()]);
    }

    @Override
    public String getMainClass() {
        return "org.apache.felix.main.Main"; //$NON-NLS-1$
    }

    /*
     * Gets any additional program arguments from the user and writes all Felix
     * configuration files
     *
     * @seeorg.eclipse.pde.ui.launcher.AbstractPDELaunchConfiguration#
     * getProgramArguments(org.eclipse.debug.core.ILaunchConfiguration)
     */
    @Override
    public String[] getProgramArguments(ILaunchConfiguration configuration) throws CoreException {
        String args = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, (String) null);

        args = args == null ? "" : getSubstitutedString(args); //$NON-NLS-1$

        writeConfigProperties(configuration);
        writeSystemProperties(configuration);
        writeStartupProperties(configuration);

        return new ExecutionArguments("", args).getProgramArgumentsArray(); //$NON-NLS-1$
    }

    /*
     * Adds the base VM arguments and root system properties used to load the
     * Felix configuration files.
     *
     * @see
     * org.eclipse.pde.ui.launcher.AbstractPDELaunchConfiguration#getVMArguments
     * (org.eclipse.debug.core.ILaunchConfiguration)
     */
    @Override
    public String[] getVMArguments(ILaunchConfiguration configuration) throws CoreException {
        String args = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, (String) null);
        args = args == null ? "" : getSubstitutedString(args); //$NON-NLS-1$

        final IPath configProperties = new Path(new File(getConfigDir(configuration), FELIX_CONFIG_PROPERTIES_FILE).getAbsolutePath());
        final IPath systemProperties = new Path(new File(getConfigDir(configuration), FELIX_SYSTEM_PROPERTIES_FILE).getAbsolutePath());

        final String[] vmArgs = new ExecutionArguments("", args).getVMArgumentsArray(); //$NON-NLS-1$
       
        // arraycopy works for JDK 5 & 6
        final String[] newVmArgs = new String[vmArgs.length + 2];
        System.arraycopy(vmArgs, 0, newVmArgs, 0, vmArgs.length);
       
        try {
            // TODO: Properly merge arguments in
            newVmArgs[vmArgs.length] = "-D" + FELIX_CONFIG_PROPERTIES_KEY + "=" + configProperties.toFile().toURI().toURL();
            newVmArgs[vmArgs.length + 1] = "-D" + FELIX_SYSTEM_PROPERTIES_KEY + "=" + systemProperties.toFile().toURI().toURL();
        } catch (MalformedURLException e) {

        }

        return newVmArgs;
    }

    /**
     * Writes out the configuration properties including bundle start and
     * install values
     *
     * @param configuration
     *            the launch configuration
     * @throws CoreException
     */
    private void writeConfigProperties(ILaunchConfiguration configuration) throws CoreException {
        final File f = new File(getConfigDir(configuration), FELIX_CONFIG_PROPERTIES_FILE);

        final boolean defaultAutostart = configuration.getAttribute(IPDELauncherConstants.DEFAULT_AUTO_START, DEFAULT_AUTOSTART);
        final int defaultStart = configuration.getAttribute(IPDELauncherConstants.DEFAULT_START_LEVEL, DEFAULT_START_LEVEL);

        final Properties properties = new Properties();

        properties.put("osgi.bundles.defaultStartLevel", Integer.toString(defaultStart)); //$NON-NLS-1$
        properties.put("org.osgi.framework.startlevel.beginning", Integer.toString(defaultStart)); //$NON-NLS-1$

        final Map<String, List<String>> startEntries = new HashMap<String, List<String>>();
        final Map<String, List<String>> installEntries = new HashMap<String, List<String>>();

        for (IPluginModelBase model : fModels.keySet()) {
            final String startString = fModels.get(model);

            final int colonPos = startString.indexOf(":");

            Integer startLevel;
            String s = startString.substring(0, colonPos);
            if ("default".equals(s)) {
                startLevel = defaultStart;
            } else {
                startLevel = new Integer(s);
            }

            boolean autostart;
            s = startString.substring(colonPos + 1);
            if ("default".equals(s)) {
                autostart = defaultAutostart;
            } else {
                autostart = new Boolean(s);
            }

            List<String> entries;
            if (autostart) {
                entries = startEntries.get(FELIX_AUTO_START_PREFIX + startLevel.toString());
                if (entries == null) {
                    entries = new ArrayList<String>();
                    startEntries.put(FELIX_AUTO_START_PREFIX + startLevel.toString(), entries);
                }
            } else {
                entries = startEntries.get(FELIX_AUTO_INSTALL_PREFIX + startLevel.toString());
                if (entries == null) {
                    entries = new ArrayList<String>();
                    installEntries.put(FELIX_AUTO_INSTALL_PREFIX + startLevel.toString(), entries);
                }
            }

            try {
                final File bundle = new File(model.getBundleDescription().getLocation());
                entries.add(bundle.toURI().toURL().toString());
            } catch (MalformedURLException e) {
            }
        }

        for (Map.Entry<String, List<String>> e : startEntries.entrySet()) {
            properties.put(e.getKey(), join(e.getValue(), " "));
        }

        for (Map.Entry<String, List<String>> e : installEntries.entrySet()) {
            properties.put(e.getKey(), join(e.getValue(), " "));
        }

        writeProperties(f.getAbsolutePath(), properties);
    }

    private void writeStartupProperties(ILaunchConfiguration configuration) throws CoreException {
        final File f = new File(getConfigDir(configuration), "startup.properties"); //$NON-NLS-1$

        final Properties properties = new Properties();

        writeProperties(f.getAbsolutePath(), properties);
    }

    private void writeSystemProperties(ILaunchConfiguration configuration) throws CoreException {
        final File f = new File(getConfigDir(configuration), FELIX_SYSTEM_PROPERTIES_FILE);

        final Properties properties = new Properties();

        writeProperties(f.getAbsolutePath(), properties);
    }

    /*
     * Sets up the initial map of bundles.
     *
     * @see
     * org.eclipse.pde.ui.launcher.AbstractPDELaunchConfiguration#preLaunchCheck
     * (org.eclipse.debug.core.ILaunchConfiguration,
     * org.eclipse.debug.core.ILaunch,
     * org.eclipse.core.runtime.IProgressMonitor)
     */
    @Override
    protected void preLaunchCheck(ILaunchConfiguration configuration, ILaunch launch, IProgressMonitor monitor) throws CoreException {
        final String workspace = configuration.getAttribute(IPDELauncherConstants.WORKSPACE_BUNDLES, ""); //$NON-NLS-1$
        final String target = configuration.getAttribute(IPDELauncherConstants.TARGET_BUNDLES, ""); //$NON-NLS-1$

        final List<BundleEntry> workspaceBundles = FelixLaunchHelper.getBundles(workspace);
        final List<BundleEntry> targetBundles = FelixLaunchHelper.getBundles(target);

        fModels = new HashMap<IPluginModelBase, String>();
        for(BundleEntry e : workspaceBundles) {
            final IPluginModelBase model = FelixLaunchHelper.resolveWorkspaceBundleEntry(e);
            if(model == null) {
                continue;
            }

            fModels.put(model, e.getAutostart() + ":" + e.getStartLevel()); //$NON-NLS-1$
        }

        if (configuration.getAttribute(IPDELauncherConstants.AUTOMATIC_ADD, true)) {
            automaticallyAddWorkspaceBundles(configuration);
        }

        for(BundleEntry e : targetBundles) {
            final IPluginModelBase model = FelixLaunchHelper.resolveTargetBundleEntry(e);
            if(model == null) {
                continue;
            }

            fModels.put(model, e.getAutostart() + ":" + e.getStartLevel()); //$NON-NLS-1$
        }

        fAllBundles = new HashMap<String, IPluginModelBase>(fModels.size());

        final Iterator<IPluginModelBase> iter = fModels.keySet().iterator();
        while (iter.hasNext()) {
            final IPluginModelBase model = iter.next();
            fAllBundles.put(model.getPluginBase().getId(), model);
        }

        super.preLaunchCheck(configuration, launch, monitor);
    }

    private void automaticallyAddWorkspaceBundles(ILaunchConfiguration configuration) throws CoreException {
        final Set<IPluginModelBase> deselectedPlugins = FelixLaunchHelper.getDeselectedPluginSet(configuration);

        final IPluginModelBase[] models = PluginRegistry.getWorkspaceModels();
        for (int i = 0; i < models.length; i++) {
            final String id = models[i].getPluginBase().getId();
            if (id == null) {
                continue;
            }

            if (!deselectedPlugins.contains(models[i])) {
                if (!fModels.containsKey(models[i])) {
                    fModels.put(models[i], "default:default"); //$NON-NLS-1$
                }
            }
        }
    }

}
TOP

Related Classes of org.apache.karaf.eik.felix.FelixLaunchConfiguration

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.