| /* |
| * 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.ui.workbench.internal; |
| |
| import org.apache.karaf.eik.core.IKarafConstants; |
| import org.apache.karaf.eik.core.KarafCorePluginUtils; |
| import org.apache.karaf.eik.core.KarafPlatformModel; |
| import org.apache.karaf.eik.core.KarafWorkingPlatformModel; |
| import org.apache.karaf.eik.core.PropertyUtils; |
| import org.apache.karaf.eik.core.configuration.FeaturesSection; |
| import org.apache.karaf.eik.core.configuration.ManagementSection; |
| import org.apache.karaf.eik.core.equinox.BundleEntry; |
| import org.apache.karaf.eik.core.model.GenericKarafPlatformModel; |
| import org.apache.karaf.eik.core.shell.KarafSshConnectionUrl; |
| import org.apache.karaf.eik.core.shell.KarafSshShellConnection; |
| import org.apache.karaf.eik.ui.IKarafProject; |
| import org.apache.karaf.eik.ui.KarafLaunchConfigurationConstants; |
| import org.apache.karaf.eik.ui.KarafUIPluginActivator; |
| import org.apache.karaf.eik.ui.console.KarafRemoteConsole; |
| import org.apache.karaf.eik.ui.workbench.KarafWorkbenchService; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.ILaunch; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; |
| import org.eclipse.debug.core.ILaunchListener; |
| import org.eclipse.debug.core.model.IProcess; |
| import org.eclipse.debug.ui.IDebugUIConstants; |
| import org.eclipse.debug.ui.console.ConsoleColorProvider; |
| import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; |
| import org.eclipse.jdt.launching.SocketUtil; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.ui.console.ConsolePlugin; |
| import org.eclipse.ui.console.IConsole; |
| import org.eclipse.ui.console.IConsoleManager; |
| |
| public class GenericKarafWorkbenchService implements KarafWorkbenchService { |
| |
| private final class KarafConsoleLaunchListener implements ILaunchListener { |
| |
| /** |
| * Returns the console for the given {@link IProcess}, or {@code null} |
| * if none. |
| * |
| * @param process |
| * the {@code IProcess} whose console is to be found |
| * @return the console for the given process, or {@code null} if none |
| */ |
| public IConsole findConsole(final IProcess process) { |
| final IConsoleManager manager = ConsolePlugin.getDefault().getConsoleManager(); |
| |
| for (final IConsole console : manager.getConsoles()) { |
| if (console instanceof KarafRemoteConsole) { |
| final KarafRemoteConsole karafConsole = (KarafRemoteConsole) console; |
| if (karafConsole.getProcess().equals(process)) { |
| return karafConsole; |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Returns the {@link IDocument} for the {@link IProcess}, or |
| * {@code null} if none is available. |
| * |
| * @param process |
| * the {@code IProcess} whose document is to be retrieved |
| * @return the {@code IDocument} for the specified {@code IProcess} or |
| * {@code null} if one could not be found |
| */ |
| public IDocument getConsoleDocument(final IProcess process) { |
| final KarafRemoteConsole console = (KarafRemoteConsole) findConsole(process); |
| return console != null ? console.getDocument() : null; |
| } |
| |
| @Override |
| public void launchAdded(final ILaunch launch) { |
| launchChanged(launch); |
| } |
| |
| @Override |
| public void launchChanged(final ILaunch launch) { |
| if (!isKarafLaunch(launch)) { |
| return; |
| } |
| |
| for (final IProcess process : launch.getProcesses()) { |
| if (getConsoleDocument(process) != null) { |
| continue; |
| } |
| |
| if (process.getStreamsProxy() == null) { |
| continue; |
| } |
| |
| final String encoding = launch.getAttribute(DebugPlugin.ATTR_CONSOLE_ENCODING); |
| |
| final KarafPlatformModel karafPlatform = |
| (KarafPlatformModel) launch.getLaunchConfiguration().getAdapter(KarafPlatformModel.class); |
| |
| final KarafSshConnectionUrl sshConnectionUrl = |
| (KarafSshConnectionUrl) karafPlatform.getAdapter(KarafSshConnectionUrl.class); |
| |
| final KarafSshShellConnection.Credentials credentials; |
| |
| try { |
| final String username = |
| launch.getLaunchConfiguration().getAttribute(KarafLaunchConfigurationConstants.KARAF_REMOTE_CONSOLE_USERNAME, "karaf"); |
| final String password = |
| launch.getLaunchConfiguration().getAttribute(KarafLaunchConfigurationConstants.KARAF_REMOTE_CONSOLE_PASSWORD, "karaf"); |
| |
| credentials = new KarafSshShellConnection.Credentials(username, password); |
| } catch (final CoreException e) { |
| throw new AssertionError(e); |
| } |
| |
| final KarafRemoteConsole remoteConsole = new KarafRemoteConsole( |
| process, |
| sshConnectionUrl, |
| credentials, |
| new ConsoleColorProvider(), |
| launch.getLaunchConfiguration().getName(), |
| encoding); |
| |
| remoteConsole.setAttribute(IDebugUIConstants.ATTR_CONSOLE_PROCESS, process); |
| |
| ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { remoteConsole }); |
| } |
| } |
| |
| @Override |
| public void launchRemoved(final ILaunch launch) { |
| if (!isKarafLaunch(launch)) { |
| return; |
| } |
| |
| for (final IProcess process : launch.getProcesses()) { |
| final IConsole console = findConsole(process); |
| |
| if (console != null) { |
| final IConsoleManager manager = ConsolePlugin.getDefault().getConsoleManager(); |
| manager.removeConsoles(new IConsole[] { console }); |
| } |
| } |
| } |
| |
| /** |
| * Determines whether or not the {@link ILaunch} is from an EIK launch |
| * |
| * @param launch |
| * the {@code ILaunch} to evaluate |
| * @return true if the {@code ILaunch} is an EIK launch |
| */ |
| private boolean isKarafLaunch(final ILaunch launch) { |
| try { |
| final ILaunchConfiguration configuration = launch.getLaunchConfiguration(); |
| if (!configuration.getAttributes().containsKey(KarafLaunchConfigurationConstants.KARAF_LAUNCH_START_REMOTE_CONSOLE)) { |
| return false; |
| } |
| |
| return true; |
| } catch (final CoreException e) { |
| return false; |
| } |
| } |
| } |
| |
| public GenericKarafWorkbenchService() { |
| DebugPlugin.getDefault().getLaunchManager().addLaunchListener(new KarafConsoleLaunchListener()); |
| } |
| |
| @Override |
| public List<BundleEntry> getAdditionalBundles(final KarafWorkingPlatformModel platformModel, final ILaunchConfiguration configuration) { |
| if (!platformModel.getParentKarafModel().getClass().equals(GenericKarafPlatformModel.class)) { |
| return Collections.emptyList(); |
| } |
| |
| final String[] bundles = { |
| "org.apache.karaf.eik.app", |
| "org.eclipse.core.contenttype", |
| "org.eclipse.core.jobs", |
| "org.eclipse.core.runtime", |
| "org.eclipse.core.runtime.compatibility.auth", |
| "org.eclipse.equinox.app", |
| "org.eclipse.equinox.common", |
| "org.eclipse.equinox.registry", |
| "org.eclipse.equinox.preferences", |
| "org.eclipse.osgi.util" |
| }; |
| |
| final List<BundleEntry> bundleEntries = new ArrayList<BundleEntry>(); |
| |
| for (final String b : bundles) { |
| |
| // If the bundle is already present in the platform, don't add it |
| if (platformModel.getState().getBundle(b, null) != null) { |
| continue; |
| } |
| |
| final String bundleLocation = |
| KarafCorePluginUtils.getBundleLocation(b); |
| |
| if (bundleLocation != null) { |
| final BundleEntry entry = |
| new BundleEntry.Builder(bundleLocation).startLevel("1").autostart("start").build(); //$NON-NLS-1$ $NON-NLS-2$ |
| |
| bundleEntries.add(entry); |
| } |
| } |
| |
| return bundleEntries; |
| } |
| |
| @Override |
| public Map<String, String> getAdditionalEquinoxConfiguration(final KarafWorkingPlatformModel platformModel, final ILaunchConfiguration configuration) { |
| if (!platformModel.getParentKarafModel().getClass().equals(GenericKarafPlatformModel.class)) { |
| return Collections.emptyMap(); |
| } |
| |
| final Map<String, String> equinoxProperties = new HashMap<String, String>(); |
| |
| final Properties currentConfig; |
| try { |
| currentConfig = |
| KarafCorePluginUtils.loadProperties( |
| platformModel.getParentKarafModel().getConfigurationDirectory().toFile(), |
| IKarafConstants.KARAF_DEFAULT_CONFIG_PROPERTIES_FILE, |
| true); |
| |
| final Properties systemProperties = createLaunchSystemProperties(platformModel, configuration); |
| currentConfig.putAll(systemProperties); |
| |
| PropertyUtils.interpolateVariables(currentConfig, currentConfig); |
| |
| for (final Map.Entry<Object, Object> e : currentConfig.entrySet()) { |
| equinoxProperties.put((String)e.getKey(), (String)e.getValue()); |
| } |
| } catch(final CoreException e) { |
| KarafUIPluginActivator.getLogger().error("Unable to load configuration file: " + platformModel.getParentKarafModel().getConfigurationDirectory(), e); |
| } |
| |
| addEclipseObrFile(platformModel, equinoxProperties); |
| |
| equinoxProperties.put( |
| IKarafConstants.KARAF_BASE_PROP, |
| platformModel.getParentKarafModel().getRootDirectory().toOSString()); |
| |
| equinoxProperties.put( |
| IKarafConstants.KARAF_HOME_PROP, |
| platformModel.getParentKarafModel().getRootDirectory().toOSString()); |
| |
| /* |
| * Adds the $TARGET_HOME/<system plugins> directory to the default |
| * bundle.locations search space |
| */ |
| equinoxProperties.put( |
| IKarafConstants.KARAF_BUNDLE_LOCATIONS_PROP, |
| platformModel.getPluginRootDirectory().toOSString()); |
| |
| return equinoxProperties; |
| } |
| |
| @Override |
| public List<String> getVMArguments( |
| final KarafWorkingPlatformModel platformModel, |
| final ILaunchConfiguration configuration) |
| throws CoreException |
| { |
| if (!platformModel.getParentKarafModel().getClass().equals(GenericKarafPlatformModel.class)) { |
| return Collections.emptyList(); |
| } |
| |
| final Properties systemProperties = createLaunchSystemProperties(platformModel, configuration); |
| |
| final List<String> arguments = new ArrayList<String>(); |
| for (final Map.Entry<Object, Object> e : systemProperties.entrySet()) { |
| arguments.add( |
| KarafCorePluginUtils.constructSystemProperty( |
| (String) e.getKey(), |
| (String) e.getValue())); |
| } |
| |
| return arguments; |
| } |
| |
| @Override |
| public void initialize(final KarafWorkingPlatformModel platformModel, final ILaunchConfigurationWorkingCopy configuration) { |
| if (!platformModel.getParentKarafModel().getClass().equals(GenericKarafPlatformModel.class)) { |
| return; |
| } |
| |
| configuration.setAttribute( |
| IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, |
| platformModel.getParentKarafModel().getRootDirectory().toString()); |
| |
| final StringBuffer vmArgs = new StringBuffer(); |
| if (vmArgs.indexOf("-Declipse.application") == -1) { //$NON-NLS-1$ |
| if (vmArgs.length() > 0) { |
| vmArgs.append(" "); //$NON-NLS-1$ |
| } |
| vmArgs.append(" -Declipse.application=org.apache.karaf.eik.app.KarafMain"); //$NON-NLS-1$ |
| } |
| |
| try { |
| final String currentVMArguments = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, ""); |
| |
| if (currentVMArguments.trim().length() > 0) { |
| vmArgs.append(" ").append(currentVMArguments); |
| } |
| |
| configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, vmArgs.toString()); |
| } catch (final CoreException e) { |
| KarafUIPluginActivator.getLogger().error("Unable to set default VM arguments", e); |
| } |
| } |
| |
| @Override |
| public void launch( |
| final KarafWorkingPlatformModel platformModel, |
| final ILaunchConfiguration configuration, |
| final String mode, |
| final ILaunch launch, |
| final IProgressMonitor monitor) throws CoreException |
| { |
| if (!platformModel.getParentKarafModel().getClass().equals(GenericKarafPlatformModel.class)) { |
| return; |
| } |
| |
| configureKarafFeatures(platformModel, configuration); |
| configureJMXConnector(platformModel); |
| } |
| |
| private void addEclipseObrFile( |
| final KarafWorkingPlatformModel platformModel, |
| final Map<String, String> equinoxProperties) { |
| final IKarafProject karafProject = (IKarafProject) platformModel.getAdapter(IKarafProject.class); |
| // TODO: This should be factored out somehow |
| final IFile file = karafProject.getFile("platform/eclipse.obr.xml"); |
| final IPath path = file.getRawLocation(); |
| |
| final String obr = equinoxProperties.get(IKarafConstants.KARAF_OBR_REPOSITORY_PROP); |
| if (obr.indexOf("eclipse.obr.xml") == -1) { |
| final String obrUrls; |
| if (obr.trim().length() > 1) { |
| obrUrls = obr + "," + "file://" + path.toFile().getAbsolutePath(); |
| } else { |
| obrUrls = "file://" + path.toFile().getAbsolutePath(); |
| } |
| equinoxProperties.put( |
| IKarafConstants.KARAF_OBR_REPOSITORY_PROP, |
| obrUrls); |
| } |
| } |
| |
| private void configureJMXConnector( |
| final KarafWorkingPlatformModel platformModel) throws CoreException { |
| /* |
| * Ensure that the RMI registry port for the JMX connector is unique |
| */ |
| final int jmxRegistryPort = SocketUtil.findFreePort(); |
| |
| if (jmxRegistryPort == -1) { |
| throw new CoreException(new Status( |
| IStatus.ERROR, |
| KarafUIPluginActivator.PLUGIN_ID, |
| "Could not find suitable TCP/IP port for JMX RMI Registry")); |
| } |
| |
| final ManagementSection managementSection = |
| (ManagementSection) platformModel.getAdapter(ManagementSection.class); |
| |
| managementSection.load(); |
| managementSection.setPort(jmxRegistryPort); |
| managementSection.save(); |
| } |
| |
| private void configureKarafFeatures( |
| final KarafWorkingPlatformModel platformModel, final ILaunchConfiguration configuration) throws CoreException { |
| |
| if (!configuration.getAttribute(KarafLaunchConfigurationConstants.KARAF_LAUNCH_FEATURES_MANAGEMENT, true)) { |
| return; |
| } |
| |
| final FeaturesSection featuresSection = |
| (FeaturesSection) platformModel.getAdapter(FeaturesSection.class); |
| |
| featuresSection.load(); |
| |
| final String bootFeaturesString = |
| configuration.getAttribute(KarafLaunchConfigurationConstants.KARAF_LAUNCH_BOOT_FEATURES, ""); //$NON-NLS-1$ |
| final String[] bootFeaturesArray = bootFeaturesString.split(","); |
| |
| final List<String> features = new ArrayList<String>(); |
| Collections.addAll(features, bootFeaturesArray); |
| |
| featuresSection.setBootFeatureNames(features); |
| featuresSection.save(); |
| } |
| |
| private Properties createLaunchSystemProperties( |
| final KarafWorkingPlatformModel platformModel, |
| final ILaunchConfiguration configuration) throws CoreException { |
| final Properties systemProperties = loadSystemProperties(platformModel); |
| |
| systemProperties.put( |
| IKarafConstants.KARAF_BASE_PROP, |
| platformModel.getParentKarafModel().getRootDirectory().toString()); |
| |
| systemProperties.put( |
| IKarafConstants.KARAF_HOME_PROP, |
| platformModel.getParentKarafModel().getRootDirectory().toString()); |
| |
| systemProperties.put( |
| "java.util.logging.config.file", //$NON-NLS-1$ |
| platformModel.getParentKarafModel().getConfigurationDirectory().append("java.util.logging.properties").toString()); //$NON-NLS-1$ |
| |
| systemProperties.put( |
| IKarafConstants.KARAF_DATA_PROP, |
| platformModel.getParentKarafModel().getRootDirectory().append("data").toString()); //$NON-NLS-1$ |
| |
| systemProperties.put( |
| IKarafConstants.KARAF_INSTANCES_PROP, |
| platformModel.getParentKarafModel().getRootDirectory().append("instances").toString()); //$NON-NLS-1$ |
| |
| final Boolean startLocalConsole = |
| configuration.getAttribute( |
| KarafLaunchConfigurationConstants.KARAF_LAUNCH_START_LOCAL_CONSOLE, |
| true); |
| systemProperties.put( |
| "karaf.startLocalConsole", //$NON-NLS-1$ |
| startLocalConsole.toString()); |
| |
| final Boolean startRemoteConsole = |
| configuration.getAttribute( |
| KarafLaunchConfigurationConstants.KARAF_LAUNCH_START_REMOTE_CONSOLE, |
| false); |
| systemProperties.put( |
| "karaf.startRemoteShell", //$NON-NLS-1$ |
| startRemoteConsole.toString()); |
| |
| PropertyUtils.interpolateVariables(systemProperties, systemProperties); |
| return systemProperties; |
| } |
| |
| private Properties loadSystemProperties(final KarafWorkingPlatformModel platformModel) { |
| |
| try { |
| final Properties properties = |
| KarafCorePluginUtils.loadProperties( |
| platformModel.getParentKarafModel().getConfigurationDirectory().toFile(), |
| IKarafConstants.KARAF_DEFAULT_SYSTEM_PROPERTIES_FILE, |
| true); |
| |
| return properties; |
| } catch(final CoreException e) { |
| KarafUIPluginActivator.getLogger().error("Unable to load configuration file: " + platformModel.getConfigurationDirectory(), e); |
| } |
| |
| return new Properties(); |
| } |
| |
| } |