X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=eclipse%2Fplugins%2Forg.argeo.slc.ide.ui%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Fide%2Fui%2Flaunch%2Fosgi%2FOsgiLaunchHelper.java;h=d69ed53946467335ff0790840be7dcc2c356e088;hb=9b2422e7198df6f34282a805058dd5f497417318;hp=c7494723607fef0fdf982713cbfd8542bc638770;hpb=24f738dcddf83ec2c13fe2e7498a47a4bcd0f427;p=gpl%2Fargeo-slc.git diff --git a/eclipse/plugins/org.argeo.slc.ide.ui/src/main/java/org/argeo/slc/ide/ui/launch/osgi/OsgiLaunchHelper.java b/eclipse/plugins/org.argeo.slc.ide.ui/src/main/java/org/argeo/slc/ide/ui/launch/osgi/OsgiLaunchHelper.java index c74947236..d69ed5394 100644 --- a/eclipse/plugins/org.argeo.slc.ide.ui/src/main/java/org/argeo/slc/ide/ui/launch/osgi/OsgiLaunchHelper.java +++ b/eclipse/plugins/org.argeo.slc.ide.ui/src/main/java/org/argeo/slc/ide/ui/launch/osgi/OsgiLaunchHelper.java @@ -1,56 +1,315 @@ package org.argeo.slc.ide.ui.launch.osgi; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +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 java.util.TreeSet; import org.argeo.slc.ide.ui.SlcIdeUiPlugin; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.core.variables.IStringVariableManager; +import org.eclipse.core.variables.VariablesPlugin; +import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; import org.eclipse.jdt.launching.IVMInstall; import org.eclipse.jdt.launching.IVMInstall2; import org.eclipse.jdt.launching.IVMInstallType; import org.eclipse.jdt.launching.JavaRuntime; -import org.eclipse.pde.ui.launcher.IPDELauncherConstants; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.osgi.service.resolver.BundleDescription; +import org.eclipse.pde.core.plugin.IPluginModelBase; +import org.eclipse.pde.core.plugin.PluginRegistry; +import org.eclipse.pde.internal.build.IPDEBuildConstants; +import org.eclipse.pde.launching.IPDELauncherConstants; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; -public class OsgiLaunchHelper { - private static Boolean debug = false; +/** + * Most of the actual logic is concentrated in this class which manipulates + * {@link ILaunchConfigurationWorkingCopy}. Static method are used since the + * shortcut and launch configuration classes are already extending PDE classes. + */ +@SuppressWarnings("restriction") +public class OsgiLaunchHelper implements OsgiLauncherConstants { + private static Boolean debug = true; + private final static String DEFAULT_DATA_DIR = "data"; + private final static String DEFAULT_EXEC_DIR = "exec"; + private final static String DEFAULT_VMARGS = "-Xmx128m"; + private final static String DEFAULT_PROGRAM_ARGS = "-console"; + + /** Sets default values on this configuration. */ + public static void setDefaults(ILaunchConfigurationWorkingCopy wc, + Boolean isEclipse) { + try { + if (isEclipse) { + wc.setAttribute(IPDELauncherConstants.USE_DEFAULT, false); + wc.setAttribute(IPDELauncherConstants.USE_PRODUCT, false); + } + + wc.setAttribute(ATTR_ADD_JVM_PATHS, false); + wc.setAttribute(ATTR_ADDITIONAL_VM_ARGS, DEFAULT_VMARGS); + wc.setAttribute(ATTR_ADDITIONAL_PROGRAM_ARGS, DEFAULT_PROGRAM_ARGS); + + // Defaults + String originalVmArgs = wc.getAttribute( + IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, ""); + wc.setAttribute(ATTR_DEFAULT_VM_ARGS, originalVmArgs); + wc.setAttribute(IPDELauncherConstants.CONFIG_CLEAR_AREA, false); + } catch (CoreException e) { + Shell shell = Display.getCurrent().getActiveShell(); + ErrorDialog.openError(shell, "Error", + "Cannot execute initalize configuration", e.getStatus()); + } + } + + /** Find the working directory based on this properties file. */ + public static String findWorkingDirectory(IFile propertiesFile) { + try { + IProject project = propertiesFile.getProject(); + IPath parent = propertiesFile.getProjectRelativePath() + .removeLastSegments(1); + IFolder execFolder = project.getFolder(parent + .append(DEFAULT_EXEC_DIR)); + if (!execFolder.exists()) + execFolder.create(true, true, null); + IFolder launchFolder = project.getFolder(execFolder + .getProjectRelativePath().append( + extractName(propertiesFile))); + if (!launchFolder.exists()) + launchFolder.create(true, true, null); + return "${workspace_loc:" + + launchFolder.getFullPath().toString().substring(1) + "}"; + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Cannot create working directory", e); + } + } + + /** Extract the launch configuration name from the properties file. */ + public static String extractName(IFile propertiesFile) { + IPath path = propertiesFile.getFullPath(); + IPath pathNoExt = path.removeFileExtension(); + return pathNoExt.segment(pathNoExt.segmentCount() - 1); + + } + + /** Expects properties file to be set as mapped resources */ public static void updateLaunchConfiguration( - ILaunchConfigurationWorkingCopy configuration, - List bundlesToStart, - Map systemPropertiesToAppend, String workingDir, - String dataDir) throws CoreException { + ILaunchConfigurationWorkingCopy wc, Boolean isEclipse) { + try { + // Finds the properties file and load it + IFile propertiesFile = (IFile) wc.getMappedResources()[0]; + propertiesFile.refreshLocal(IResource.DEPTH_ONE, null); + Properties properties = readProperties(propertiesFile); + + // Extract information from the properties file + List bundlesToStart = new ArrayList(); + Map systemPropertiesToAppend = new HashMap(); + String applicationId = interpretProperties(properties, + bundlesToStart, systemPropertiesToAppend); + + if (applicationId != null) + wc.setAttribute(IPDELauncherConstants.APPLICATION, + applicationId); + else { + if (isEclipse) + throw new Exception("No application defined," + + " please set the 'eclipse.application' property" + + " in the properties file"); + } + + // Define directories + File workingDir = getWorkingDirectory(wc); + File dataDir = new File(workingDir, DEFAULT_DATA_DIR); + + // Update the launch configuration accordingly + updateLaunchConfiguration(wc, bundlesToStart, + systemPropertiesToAppend, dataDir.getAbsolutePath(), + isEclipse); + } catch (Exception e) { + e.printStackTrace(); + Shell shell = SlcIdeUiPlugin.getDefault().getWorkbench() + .getActiveWorkbenchWindow().getShell(); + // Shell shell= Display.getCurrent().getActiveShell(); + ErrorDialog.openError(shell, "Error", + "Cannot prepare launch configuration", + new Status(IStatus.ERROR, SlcIdeUiPlugin.ID, + e.getMessage(), e)); + return; + } + } + + /** + * Actually modifies the launch configuration in order to reflect the + * current state read from the properties file and the launch configuration + * UI. + */ + protected static void updateLaunchConfiguration( + ILaunchConfigurationWorkingCopy wc, List bundlesToStart, + Map systemPropertiesToAppend, String dataDir, + Boolean isEclipse) throws CoreException { // Convert bundle lists - String targetBundles = configuration.getAttribute( - IPDELauncherConstants.TARGET_BUNDLES, ""); - configuration.setAttribute(IPDELauncherConstants.TARGET_BUNDLES, + final String targetBundles; + final String wkSpaceBundles; + if (wc.getAttribute(ATTR_SYNC_BUNDLES, true)) { + StringBuffer tBuf = new StringBuffer(); + for (IPluginModelBase model : PluginRegistry.getExternalModels()) { + tBuf.append(model.getBundleDescription().getSymbolicName()); + tBuf.append(','); + } + targetBundles = tBuf.toString(); + StringBuffer wBuf = new StringBuffer(); + models: for (IPluginModelBase model : PluginRegistry + .getWorkspaceModels()) { + if (model.getBundleDescription() == null) { + System.err.println("No bundle description for " + model); + continue models; + } + wBuf.append(model.getBundleDescription().getSymbolicName()); + wBuf.append(','); + } + wkSpaceBundles = wBuf.toString(); + } else { + targetBundles = wc.getAttribute(targetBundlesAttr(isEclipse), ""); + wkSpaceBundles = wc.getAttribute(workspaceBundlesAttr(isEclipse), + ""); + } + wc.setAttribute(targetBundlesAttr(isEclipse), convertBundleList(bundlesToStart, targetBundles)); - String wkSpaceBundles = configuration.getAttribute( - IPDELauncherConstants.WORKSPACE_BUNDLES, ""); - configuration.setAttribute(IPDELauncherConstants.WORKSPACE_BUNDLES, + wc.setAttribute(workspaceBundlesAttr(isEclipse), convertBundleList(bundlesToStart, wkSpaceBundles)); // Update other default information - configuration.setAttribute(IPDELauncherConstants.DEFAULT_AUTO_START, - false); - configuration.setAttribute(IPDELauncherConstants.CONFIG_CLEAR_AREA, - true); - String defaultVmArgs = configuration.getAttribute( + wc.setAttribute(IPDELauncherConstants.DEFAULT_AUTO_START, false); + + // VM arguments (system properties) + String defaultVmArgs = wc.getAttribute( OsgiLauncherConstants.ATTR_DEFAULT_VM_ARGS, ""); StringBuffer vmArgs = new StringBuffer(defaultVmArgs); - vmArgs.append(" -Xmx256m"); + + // Data dir system property + if (dataDir != null) { + addSysProperty(vmArgs, OsgiLauncherConstants.ARGEO_OSGI_DATA_DIR, + dataDir); + if (isEclipse) { + wc.setAttribute(IPDELauncherConstants.LOCATION, dataDir); + } + } // Add locations of JVMs + if (wc.getAttribute(ATTR_ADD_JVM_PATHS, false)) + addVms(vmArgs); + + // Add other system properties + for (String key : systemPropertiesToAppend.keySet()) + addSysProperty(vmArgs, key, systemPropertiesToAppend.get(key)); + + vmArgs.append(" ").append(wc.getAttribute(ATTR_ADDITIONAL_VM_ARGS, "")); + + wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, + vmArgs.toString()); + + // Program arguments + StringBuffer progArgs = new StringBuffer(""); + if (dataDir != null) { + progArgs.append("-data "); + progArgs.append(surroundSpaces(dataDir)); + + if (wc.getAttribute(ATTR_CLEAR_DATA_DIRECTORY, false)) { + File dataDirFile = new File(dataDir); + deleteDir(dataDirFile); + dataDirFile.mkdirs(); + } + } + String additionalProgramArgs = wc.getAttribute( + OsgiLauncherConstants.ATTR_ADDITIONAL_PROGRAM_ARGS, ""); + progArgs.append(' ').append(additionalProgramArgs); + wc.setAttribute( + IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, + progArgs.toString()); + } + + /** The launch configuration attribute to use for target bundles */ + protected static String targetBundlesAttr(Boolean isEclipse) { + return isEclipse ? IPDELauncherConstants.SELECTED_TARGET_PLUGINS + : IPDELauncherConstants.TARGET_BUNDLES; + } + + /** The launch configuration attribute to use for workspace bundles */ + protected static String workspaceBundlesAttr(Boolean isEclipse) { + return isEclipse ? IPDELauncherConstants.SELECTED_WORKSPACE_PLUGINS + : IPDELauncherConstants.WORKSPACE_BUNDLES; + } + + /** + * Interprets special properties and register the others as system + * properties to append. + * + * @return the application id defined by + * {@link OsgiLauncherConstants#ECLIPSE_APPLICATION}, or null if not + * found + */ + protected static String interpretProperties(Properties properties, + List bundlesToStart, + Map systemPropertiesToAppend) { + String argeoOsgiStart = properties + .getProperty(OsgiLauncherConstants.ARGEO_OSGI_START); + if (argeoOsgiStart != null) { + StringTokenizer st = new StringTokenizer(argeoOsgiStart, ","); + while (st.hasMoreTokens()) + bundlesToStart.add(st.nextToken()); + } + + String applicationId = null; + propKeys: for (Object keyObj : properties.keySet()) { + String key = keyObj.toString(); + if (OsgiLauncherConstants.ARGEO_OSGI_START.equals(key)) + continue propKeys; + else if (OsgiLauncherConstants.ARGEO_OSGI_BUNDLES.equals(key)) + continue propKeys; + else if (OsgiLauncherConstants.ARGEO_OSGI_LOCATIONS.equals(key)) + continue propKeys; + else if (OsgiLauncherConstants.OSGI_BUNDLES.equals(key)) + continue propKeys; + else if (OsgiLauncherConstants.ECLIPSE_APPLICATION.equals(key)) + applicationId = properties.getProperty(key); + else + systemPropertiesToAppend.put(key, properties.getProperty(key)); + } + return applicationId; + } + + /** Adds a regular system property. */ + protected static void addSysProperty(StringBuffer vmArgs, String key, + String value) { + surroundSpaces(value); + String str = "-D" + key + "=" + value; + vmArgs.append(' ').append(str); + } + + /** Adds JVMS registered in the workspace as special system properties. */ + protected static void addVms(StringBuffer vmArgs) { addVmSysProperty(vmArgs, "default", JavaRuntime.getDefaultVMInstall()); IVMInstallType[] vmTypes = JavaRuntime.getVMInstallTypes(); for (IVMInstallType vmType : vmTypes) { @@ -69,88 +328,77 @@ public class OsgiLaunchHelper { while (st.hasMoreTokens()) tokens.add(st.nextToken()); if (tokens.size() >= 2) - addVmSysProperty(vmArgs, tokens.get(0) + "." - + tokens.get(1), vmInstall); + addVmSysProperty(vmArgs, + tokens.get(0) + "." + tokens.get(1), vmInstall); } } } - // Add other system properties - for (String key : systemPropertiesToAppend.keySet()) - addSysProperty(vmArgs, key, systemPropertiesToAppend.get(key)); - - if (dataDir != null) - addSysProperty(vmArgs, OsgiLauncherConstants.ARGEO_OSGI_DATA_DIR, - dataDir); - - configuration.setAttribute( - IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, vmArgs - .toString()); - - // Program arguments - String defaultProgArgs = configuration.getAttribute( - OsgiLauncherConstants.ATTR_DEFAULT_PROGRAM_ARGS, ""); - StringBuffer progArgs = new StringBuffer(defaultProgArgs); - if (dataDir != null) { - progArgs.append(" -data "); - progArgs.append(surroundSpaces(dataDir)); - } - configuration.setAttribute( - IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, - progArgs.toString()); - - // String dir = findWorkingDirectory(); - if (workingDir != null) - configuration.setAttribute( - IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, - workingDir); - } + /** Adds a special system property pointing to one of the registered JVMs. */ protected static void addVmSysProperty(StringBuffer vmArgs, String suffix, IVMInstall vmInstall) { addSysProperty(vmArgs, OsgiLauncherConstants.VMS_PROPERTY_PREFIX + "." + suffix, vmInstall.getInstallLocation().getPath()); } - protected static void addSysProperty(StringBuffer vmArgs, String key, - String value) { - String str = "-D" + key + "=" + value; - surroundSpaces(str); - vmArgs.append(" " + str); - } - + /** Surround the string with quotes if it contains spaces. */ protected static String surroundSpaces(String str) { - if (str.contains(" ")) - return "\"" + str + "\""; + if (str.indexOf(' ') >= 0) + return '\"' + str + '\"'; else return str; } + /** + * Reformat the bundle list in order to reflect which bundles have to be + * started. + */ protected static String convertBundleList(List bundlesToStart, String original) { - StringBuffer bufBundles = new StringBuffer(1024); + if (debug) + System.out.println("Original bundle list: " + original); + StringTokenizer stComa = new StringTokenizer(original, ","); - boolean first = true; + // sort by bundle symbolic name + Set bundleIds = new TreeSet(); bundles: while (stComa.hasMoreTokens()) { - if (first) - first = false; - else - bufBundles.append(','); String bundleId = stComa.nextToken(); + if (bundleId.indexOf('*') >= 0) + throw new RuntimeException( + "Bundle id " + + bundleId + + " not properly formatted, clean your workspace projects"); + int indexAt = bundleId.indexOf('@'); - boolean modified = false; if (indexAt >= 0) { bundleId = bundleId.substring(0, indexAt); } + // We can now rely on bundleId value + if (bundleId.endsWith(".source")) { if (debug) System.out.println("Skip source bundle " + bundleId); continue bundles; + } else if (bundleId + .equals(IPDEBuildConstants.BUNDLE_SIMPLE_CONFIGURATOR)) { + // skip simple configurator in order to avoid side-effects + continue bundles; } + bundleIds.add(bundleId); + } + StringBuffer bufBundles = new StringBuffer(1024); + boolean first = true; + for (String bundleId : bundleIds) { + if (first) + first = false; + else + bufBundles.append(','); + boolean modified = false; if (bundlesToStart.contains(bundleId)) { bufBundles.append(bundleId).append('@').append("default:true"); modified = true; @@ -160,12 +408,27 @@ public class OsgiLaunchHelper { if (!modified) bufBundles.append(bundleId); + } String output = bufBundles.toString(); return output; } - protected static Properties readProperties(IFile file) throws CoreException { + // UTILITIES + /** Recursively deletes a directory tree. */ + private static void deleteDir(File dir) { + File[] files = dir.listFiles(); + for (File file : files) { + if (file.isDirectory()) + deleteDir(file); + else + file.delete(); + } + dir.delete(); + } + + /** Loads a properties file. */ + private static Properties readProperties(IFile file) throws CoreException { Properties props = new Properties(); InputStream in = null; @@ -186,28 +449,100 @@ public class OsgiLaunchHelper { return props; } - protected static void interpretProperties(Properties properties, - List bundlesToStart, - Map systemPropertiesToAppend) { - String argeoOsgiStart = properties - .getProperty(OsgiLauncherConstants.ARGEO_OSGI_START); - StringTokenizer st = new StringTokenizer(argeoOsgiStart, ","); - while (st.hasMoreTokens()) - bundlesToStart.add(st.nextToken()); + // Hacked from + // org.eclipse.pde.internal.ui.launcher.LaunchArgumentsHelper.getWorkingDirectory(ILaunchConfiguration) + private static File getWorkingDirectory(ILaunchConfiguration configuration) + throws CoreException { + String working; + try { + working = configuration.getAttribute( + IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, + new File(".").getCanonicalPath()); //$NON-NLS-1$ + } catch (IOException e) { + working = "${workspace_loc}/../"; //$NON-NLS-1$ + } + File dir; + try { + dir = new File(getSubstitutedString(working)); + } catch (Exception e) { + // the directory was most probably deleted + IFile propertiesFile = (IFile) configuration.getMappedResources()[0]; + working = findWorkingDirectory(propertiesFile); + dir = new File(getSubstitutedString(working)); + } + if (!dir.exists()) + dir.mkdirs(); + return dir; + } - propKeys: for (Object keyObj : properties.keySet()) { - String key = keyObj.toString(); - if (OsgiLauncherConstants.ARGEO_OSGI_START.equals(key)) - continue propKeys; - else if (OsgiLauncherConstants.ARGEO_OSGI_BUNDLES.equals(key)) - continue propKeys; - else if (OsgiLauncherConstants.ARGEO_OSGI_LOCATIONS.equals(key)) - continue propKeys; - else if (OsgiLauncherConstants.OSGI_BUNDLES.equals(key)) - continue propKeys; - else - systemPropertiesToAppend.put(key, properties.getProperty(key)); + // Hacked from + // org.eclipse.pde.internal.ui.launcher.LaunchArgumentsHelper.getSubstitutedString(String) + private static String getSubstitutedString(String text) + throws CoreException { + if (text == null) + return ""; //$NON-NLS-1$ + IStringVariableManager mgr = VariablesPlugin.getDefault() + .getStringVariableManager(); + return mgr.performStringSubstitution(text); + } + + /** + * Not used anymore, but kept because this routine may be useful in the + * future. + */ + protected void addSelectedProjects(StringBuffer name, ISelection selection, + List bundlesToStart) { + Assert.isNotNull(selection); + + Map bundleProjects = new HashMap(); + for (IPluginModelBase modelBase : PluginRegistry.getWorkspaceModels()) { + IProject bundleProject = modelBase.getUnderlyingResource() + .getProject(); + bundleProjects.put(bundleProject.getName(), modelBase); } + IStructuredSelection sSelection = (IStructuredSelection) selection; + for (Iterator it = sSelection.iterator(); it.hasNext();) { + Object obj = it.next(); + if (obj instanceof IProject) { + IProject project = (IProject) obj; + if (bundleProjects.containsKey(project.getName())) { + IPluginModelBase modelBase = bundleProjects.get(project + .getName()); + + BundleDescription bundleDescription = null; + if (modelBase.isFragmentModel()) { + BundleDescription[] hosts = modelBase + .getBundleDescription().getHost().getHosts(); + for (BundleDescription bd : hosts) { + if (debug) + System.out.println("Host for " + + modelBase.getBundleDescription() + .getSymbolicName() + ": " + + bd.getSymbolicName()); + bundleDescription = bd; + } + } else { + bundleDescription = modelBase.getBundleDescription(); + } + + if (bundleDescription != null) { + String symbolicName = bundleDescription + .getSymbolicName(); + String bundleName = bundleDescription.getName(); + + bundlesToStart.add(symbolicName); + + if (name.length() > 0) + name.append(" "); + if (bundleName != null) + name.append(bundleName); + else + name.append(symbolicName); + } + } + } + } } + }