1 package org
.argeo
.slc
.ide
.ui
.launch
.osgi
;
4 import java
.io
.IOException
;
5 import java
.io
.InputStream
;
6 import java
.util
.ArrayList
;
7 import java
.util
.HashMap
;
8 import java
.util
.Iterator
;
11 import java
.util
.Properties
;
13 import java
.util
.StringTokenizer
;
14 import java
.util
.TreeSet
;
16 import org
.argeo
.slc
.ide
.ui
.SlcIdeUiPlugin
;
17 import org
.eclipse
.core
.resources
.IFile
;
18 import org
.eclipse
.core
.resources
.IFolder
;
19 import org
.eclipse
.core
.resources
.IProject
;
20 import org
.eclipse
.core
.resources
.IResource
;
21 import org
.eclipse
.core
.runtime
.Assert
;
22 import org
.eclipse
.core
.runtime
.CoreException
;
23 import org
.eclipse
.core
.runtime
.IPath
;
24 import org
.eclipse
.core
.runtime
.IStatus
;
25 import org
.eclipse
.core
.runtime
.Status
;
26 import org
.eclipse
.core
.variables
.IStringVariableManager
;
27 import org
.eclipse
.core
.variables
.VariablesPlugin
;
28 import org
.eclipse
.debug
.core
.ILaunchConfiguration
;
29 import org
.eclipse
.debug
.core
.ILaunchConfigurationWorkingCopy
;
30 import org
.eclipse
.jdt
.launching
.IJavaLaunchConfigurationConstants
;
31 import org
.eclipse
.jdt
.launching
.IVMInstall
;
32 import org
.eclipse
.jdt
.launching
.IVMInstall2
;
33 import org
.eclipse
.jdt
.launching
.IVMInstallType
;
34 import org
.eclipse
.jdt
.launching
.JavaRuntime
;
35 import org
.eclipse
.jface
.dialogs
.ErrorDialog
;
36 import org
.eclipse
.jface
.viewers
.ISelection
;
37 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
38 import org
.eclipse
.osgi
.service
.resolver
.BundleDescription
;
39 import org
.eclipse
.pde
.core
.plugin
.IPluginModelBase
;
40 import org
.eclipse
.pde
.core
.plugin
.PluginRegistry
;
41 import org
.eclipse
.pde
.internal
.build
.IPDEBuildConstants
;
42 import org
.eclipse
.pde
.launching
.IPDELauncherConstants
;
43 import org
.eclipse
.swt
.widgets
.Display
;
44 import org
.eclipse
.swt
.widgets
.Shell
;
47 * Most of the actual logic is concentrated in this class which manipulates
48 * {@link ILaunchConfigurationWorkingCopy}. Static method are used since the
49 * shortcut and launch configuration classes are already extending PDE classes.
51 @SuppressWarnings("restriction")
52 public class OsgiLaunchHelper
implements OsgiLauncherConstants
{
53 private static Boolean debug
= true;
55 private final static String DEFAULT_DATA_DIR
= "data";
56 private final static String DEFAULT_EXEC_DIR
= "exec";
57 private final static String DEFAULT_VMARGS
= "-Xmx256m";
58 private final static String DEFAULT_PROGRAM_ARGS
= "-console";
60 /** Sets default values on this configuration. */
61 public static void setDefaults(ILaunchConfigurationWorkingCopy wc
,
65 wc
.setAttribute(IPDELauncherConstants
.USE_DEFAULT
, false);
66 wc
.setAttribute(IPDELauncherConstants
.USE_PRODUCT
, false);
69 wc
.setAttribute(ATTR_ADD_JVM_PATHS
, false);
70 wc
.setAttribute(ATTR_ADDITIONAL_VM_ARGS
, DEFAULT_VMARGS
);
71 wc
.setAttribute(ATTR_ADDITIONAL_PROGRAM_ARGS
, DEFAULT_PROGRAM_ARGS
);
74 String originalVmArgs
= wc
.getAttribute(
75 IJavaLaunchConfigurationConstants
.ATTR_VM_ARGUMENTS
, "");
76 wc
.setAttribute(ATTR_DEFAULT_VM_ARGS
, originalVmArgs
);
77 wc
.setAttribute(IPDELauncherConstants
.CONFIG_CLEAR_AREA
, true);
78 } catch (CoreException e
) {
79 Shell shell
= Display
.getCurrent().getActiveShell();
80 ErrorDialog
.openError(shell
, "Error",
81 "Cannot execute initalize configuration", e
.getStatus());
85 /** Find the working directory based on this properties file. */
86 public static String
findWorkingDirectory(IFile propertiesFile
) {
88 IProject project
= propertiesFile
.getProject();
89 IPath parent
= propertiesFile
.getProjectRelativePath()
90 .removeLastSegments(1);
91 IFolder execFolder
= project
.getFolder(parent
92 .append(DEFAULT_EXEC_DIR
));
93 if (!execFolder
.exists())
94 execFolder
.create(true, true, null);
95 IFolder launchFolder
= project
.getFolder(execFolder
96 .getProjectRelativePath().append(
97 extractName(propertiesFile
)));
98 if (!launchFolder
.exists())
99 launchFolder
.create(true, true, null);
100 return "${workspace_loc:"
101 + launchFolder
.getFullPath().toString().substring(1) + "}";
102 } catch (Exception e
) {
104 throw new RuntimeException("Cannot create working directory", e
);
108 /** Extract the launch configuration name from the properties file. */
109 public static String
extractName(IFile propertiesFile
) {
110 IPath path
= propertiesFile
.getFullPath();
111 IPath pathNoExt
= path
.removeFileExtension();
112 return pathNoExt
.segment(pathNoExt
.segmentCount() - 1);
116 /** Expects properties file to be set as mapped resources */
117 public static void updateLaunchConfiguration(
118 ILaunchConfigurationWorkingCopy wc
, Boolean isEclipse
) {
120 // Finds the properties file and load it
121 IFile propertiesFile
= (IFile
) wc
.getMappedResources()[0];
122 propertiesFile
.refreshLocal(IResource
.DEPTH_ONE
, null);
123 Properties properties
= readProperties(propertiesFile
);
125 // Extract information from the properties file
126 List
<String
> bundlesToStart
= new ArrayList
<String
>();
127 Map
<String
, String
> systemPropertiesToAppend
= new HashMap
<String
, String
>();
128 String applicationId
= interpretProperties(properties
,
129 bundlesToStart
, systemPropertiesToAppend
);
131 if (applicationId
!= null)
132 wc
.setAttribute(IPDELauncherConstants
.APPLICATION
,
136 throw new Exception("No application defined,"
137 + " please set the 'eclipse.application' property"
138 + " in the properties file");
141 // Define directories
142 File workingDir
= getWorkingDirectory(wc
);
143 File dataDir
= new File(workingDir
, DEFAULT_DATA_DIR
);
145 // Update the launch configuration accordingly
146 updateLaunchConfiguration(wc
, bundlesToStart
,
147 systemPropertiesToAppend
, dataDir
.getAbsolutePath(),
149 } catch (Exception e
) {
151 Shell shell
= SlcIdeUiPlugin
.getDefault().getWorkbench()
152 .getActiveWorkbenchWindow().getShell();
153 // Shell shell= Display.getCurrent().getActiveShell();
154 ErrorDialog
.openError(shell
, "Error",
155 "Cannot prepare launch configuration",
156 new Status(IStatus
.ERROR
, SlcIdeUiPlugin
.ID
,
163 * Actually modifies the launch configuration in order to reflect the
164 * current state read from the properties file and the launch configuration
167 protected static void updateLaunchConfiguration(
168 ILaunchConfigurationWorkingCopy wc
, List
<String
> bundlesToStart
,
169 Map
<String
, String
> systemPropertiesToAppend
, String dataDir
,
170 Boolean isEclipse
) throws CoreException
{
171 // Convert bundle lists
172 final String targetBundles
;
173 final String wkSpaceBundles
;
174 if (wc
.getAttribute(ATTR_SYNC_BUNDLES
, true)) {
175 StringBuffer tBuf
= new StringBuffer();
176 for (IPluginModelBase model
: PluginRegistry
.getExternalModels()) {
177 tBuf
.append(model
.getBundleDescription().getSymbolicName());
180 targetBundles
= tBuf
.toString();
181 StringBuffer wBuf
= new StringBuffer();
182 models
: for (IPluginModelBase model
: PluginRegistry
183 .getWorkspaceModels()) {
184 if (model
.getBundleDescription() == null) {
185 System
.err
.println("No bundle description for " + model
);
188 wBuf
.append(model
.getBundleDescription().getSymbolicName());
191 wkSpaceBundles
= wBuf
.toString();
193 targetBundles
= wc
.getAttribute(targetBundlesAttr(isEclipse
), "");
194 wkSpaceBundles
= wc
.getAttribute(workspaceBundlesAttr(isEclipse
),
197 wc
.setAttribute(targetBundlesAttr(isEclipse
),
198 convertBundleList(bundlesToStart
, targetBundles
));
200 wc
.setAttribute(workspaceBundlesAttr(isEclipse
),
201 convertBundleList(bundlesToStart
, wkSpaceBundles
));
203 // Update other default information
204 wc
.setAttribute(IPDELauncherConstants
.DEFAULT_AUTO_START
, false);
206 // VM arguments (system properties)
207 String defaultVmArgs
= wc
.getAttribute(
208 OsgiLauncherConstants
.ATTR_DEFAULT_VM_ARGS
, "");
209 StringBuffer vmArgs
= new StringBuffer(defaultVmArgs
);
211 // Data dir system property
212 if (dataDir
!= null) {
213 addSysProperty(vmArgs
, OsgiLauncherConstants
.ARGEO_OSGI_DATA_DIR
,
216 wc
.setAttribute(IPDELauncherConstants
.LOCATION
, dataDir
);
220 // Add locations of JVMs
221 if (wc
.getAttribute(ATTR_ADD_JVM_PATHS
, false))
224 // Add other system properties
225 for (String key
: systemPropertiesToAppend
.keySet())
226 addSysProperty(vmArgs
, key
, systemPropertiesToAppend
.get(key
));
228 vmArgs
.append(" ").append(wc
.getAttribute(ATTR_ADDITIONAL_VM_ARGS
, ""));
230 wc
.setAttribute(IJavaLaunchConfigurationConstants
.ATTR_VM_ARGUMENTS
,
234 StringBuffer progArgs
= new StringBuffer("");
235 if (dataDir
!= null) {
236 progArgs
.append("-data ");
237 progArgs
.append(surroundSpaces(dataDir
));
239 if (wc
.getAttribute(ATTR_CLEAR_DATA_DIRECTORY
, false)) {
240 File dataDirFile
= new File(dataDir
);
241 deleteDir(dataDirFile
);
242 dataDirFile
.mkdirs();
245 String additionalProgramArgs
= wc
.getAttribute(
246 OsgiLauncherConstants
.ATTR_ADDITIONAL_PROGRAM_ARGS
, "");
247 progArgs
.append(' ').append(additionalProgramArgs
);
249 IJavaLaunchConfigurationConstants
.ATTR_PROGRAM_ARGUMENTS
,
250 progArgs
.toString());
253 /** The launch configuration attribute to use for target bundles */
254 protected static String
targetBundlesAttr(Boolean isEclipse
) {
255 return isEclipse ? IPDELauncherConstants
.SELECTED_TARGET_PLUGINS
256 : IPDELauncherConstants
.TARGET_BUNDLES
;
259 /** The launch configuration attribute to use for workspace bundles */
260 protected static String
workspaceBundlesAttr(Boolean isEclipse
) {
261 return isEclipse ? IPDELauncherConstants
.SELECTED_WORKSPACE_PLUGINS
262 : IPDELauncherConstants
.WORKSPACE_BUNDLES
;
266 * Interprets special properties and register the others as system
267 * properties to append.
269 * @return the application id defined by
270 * {@link OsgiLauncherConstants#ECLIPSE_APPLICATION}, or null if not
273 protected static String
interpretProperties(Properties properties
,
274 List
<String
> bundlesToStart
,
275 Map
<String
, String
> systemPropertiesToAppend
) {
276 String argeoOsgiStart
= properties
277 .getProperty(OsgiLauncherConstants
.ARGEO_OSGI_START
);
278 if (argeoOsgiStart
!= null) {
279 StringTokenizer st
= new StringTokenizer(argeoOsgiStart
, ",");
280 while (st
.hasMoreTokens())
281 bundlesToStart
.add(st
.nextToken());
284 String applicationId
= null;
285 propKeys
: for (Object keyObj
: properties
.keySet()) {
286 String key
= keyObj
.toString();
287 if (OsgiLauncherConstants
.ARGEO_OSGI_START
.equals(key
))
289 else if (OsgiLauncherConstants
.ARGEO_OSGI_BUNDLES
.equals(key
))
291 else if (OsgiLauncherConstants
.ARGEO_OSGI_LOCATIONS
.equals(key
))
293 else if (OsgiLauncherConstants
.OSGI_BUNDLES
.equals(key
))
295 else if (OsgiLauncherConstants
.ECLIPSE_APPLICATION
.equals(key
))
296 applicationId
= properties
.getProperty(key
);
298 systemPropertiesToAppend
.put(key
, properties
.getProperty(key
));
300 return applicationId
;
303 /** Adds a regular system property. */
304 protected static void addSysProperty(StringBuffer vmArgs
, String key
,
306 surroundSpaces(value
);
307 String str
= "-D" + key
+ "=" + value
;
308 vmArgs
.append(' ').append(str
);
311 /** Adds JVMS registered in the workspace as special system properties. */
312 protected static void addVms(StringBuffer vmArgs
) {
313 addVmSysProperty(vmArgs
, "default", JavaRuntime
.getDefaultVMInstall());
314 IVMInstallType
[] vmTypes
= JavaRuntime
.getVMInstallTypes();
315 for (IVMInstallType vmType
: vmTypes
) {
316 for (IVMInstall vmInstall
: vmType
.getVMInstalls()) {
317 // printVm("", vmInstall);
318 // properties based on name
319 addVmSysProperty(vmArgs
, vmInstall
.getName(), vmInstall
);
320 if (vmInstall
instanceof IVMInstall2
) {
321 // properties based on version
322 IVMInstall2 vmInstall2
= (IVMInstall2
) vmInstall
;
323 String version
= vmInstall2
.getJavaVersion();
324 addVmSysProperty(vmArgs
, version
, vmInstall
);
326 List
<String
> tokens
= new ArrayList
<String
>();
327 StringTokenizer st
= new StringTokenizer(version
, ".");
328 while (st
.hasMoreTokens())
329 tokens
.add(st
.nextToken());
330 if (tokens
.size() >= 2)
331 addVmSysProperty(vmArgs
,
332 tokens
.get(0) + "." + tokens
.get(1), vmInstall
);
339 /** Adds a special system property pointing to one of the registered JVMs. */
340 protected static void addVmSysProperty(StringBuffer vmArgs
, String suffix
,
341 IVMInstall vmInstall
) {
342 addSysProperty(vmArgs
, OsgiLauncherConstants
.VMS_PROPERTY_PREFIX
+ "."
343 + suffix
, vmInstall
.getInstallLocation().getPath());
346 /** Surround the string with quotes if it contains spaces. */
347 protected static String
surroundSpaces(String str
) {
348 if (str
.indexOf(' ') >= 0)
349 return '\"' + str
+ '\"';
355 * Reformat the bundle list in order to reflect which bundles have to be
358 protected static String
convertBundleList(List
<String
> bundlesToStart
,
360 debug("Original bundle list: " + original
);
362 StringTokenizer stComa
= new StringTokenizer(original
, ",");
363 // sort by bundle symbolic name
364 Set
<String
> bundleIds
= new TreeSet
<String
>();
365 bundles
: while (stComa
.hasMoreTokens()) {
367 String bundleId
= stComa
.nextToken();
368 if (bundleId
.indexOf('*') >= 0)
369 throw new RuntimeException(
372 + " not properly formatted, clean your workspace projects");
374 int indexAt
= bundleId
.indexOf('@');
376 bundleId
= bundleId
.substring(0, indexAt
);
379 // We can now rely on bundleId value
381 if (bundleId
.endsWith(".source")) {
382 debug("Skip source bundle " + bundleId
);
385 .equals(IPDEBuildConstants
.BUNDLE_SIMPLE_CONFIGURATOR
)) {
386 // skip simple configurator in order to avoid side-effects
389 bundleIds
.add(bundleId
);
392 StringBuffer bufBundles
= new StringBuffer(1024);
393 boolean first
= true;
394 for (String bundleId
: bundleIds
) {
398 bufBundles
.append(',');
399 boolean modified
= false;
400 if (bundlesToStart
.contains(bundleId
)) {
401 bufBundles
.append(bundleId
).append('@').append("default:true");
403 debug("Will start " + bundleId
);
407 bufBundles
.append(bundleId
);
410 String output
= bufBundles
.toString();
415 /** Recursively deletes a directory tree. */
416 private static void deleteDir(File dir
) {
417 File
[] files
= dir
.listFiles();
418 for (File file
: files
) {
419 if (file
.isDirectory())
427 /** Loads a properties file. */
428 private static Properties
readProperties(IFile file
) throws CoreException
{
429 Properties props
= new Properties();
431 InputStream in
= null;
433 in
= file
.getContents();
435 } catch (Exception e
) {
436 throw new CoreException(new Status(IStatus
.ERROR
,
437 SlcIdeUiPlugin
.ID
, "Cannot read properties file", e
));
442 } catch (IOException e
) {
450 // org.eclipse.pde.internal.ui.launcher.LaunchArgumentsHelper.getWorkingDirectory(ILaunchConfiguration)
451 private static File
getWorkingDirectory(ILaunchConfiguration configuration
)
452 throws CoreException
{
455 working
= configuration
.getAttribute(
456 IJavaLaunchConfigurationConstants
.ATTR_WORKING_DIRECTORY
,
457 new File(".").getCanonicalPath()); //$NON-NLS-1$
458 } catch (IOException e
) {
459 working
= "${workspace_loc}/../"; //$NON-NLS-1$
463 dir
= new File(getSubstitutedString(working
));
464 } catch (Exception e
) {
465 // the directory was most probably deleted
466 IFile propertiesFile
= (IFile
) configuration
.getMappedResources()[0];
467 working
= findWorkingDirectory(propertiesFile
);
468 dir
= new File(getSubstitutedString(working
));
476 // org.eclipse.pde.internal.ui.launcher.LaunchArgumentsHelper.getSubstitutedString(String)
477 private static String
getSubstitutedString(String text
)
478 throws CoreException
{
480 return ""; //$NON-NLS-1$
481 IStringVariableManager mgr
= VariablesPlugin
.getDefault()
482 .getStringVariableManager();
483 return mgr
.performStringSubstitution(text
);
487 * Not used anymore, but kept because this routine may be useful in the
490 protected void addSelectedProjects(StringBuffer name
, ISelection selection
,
491 List
<String
> bundlesToStart
) {
492 Assert
.isNotNull(selection
);
494 Map
<String
, IPluginModelBase
> bundleProjects
= new HashMap
<String
, IPluginModelBase
>();
495 for (IPluginModelBase modelBase
: PluginRegistry
.getWorkspaceModels()) {
496 IProject bundleProject
= modelBase
.getUnderlyingResource()
498 bundleProjects
.put(bundleProject
.getName(), modelBase
);
501 IStructuredSelection sSelection
= (IStructuredSelection
) selection
;
502 for (Iterator
<?
> it
= sSelection
.iterator(); it
.hasNext();) {
503 Object obj
= it
.next();
504 if (obj
instanceof IProject
) {
505 IProject project
= (IProject
) obj
;
506 if (bundleProjects
.containsKey(project
.getName())) {
507 IPluginModelBase modelBase
= bundleProjects
.get(project
510 BundleDescription bundleDescription
= null;
511 if (modelBase
.isFragmentModel()) {
512 BundleDescription
[] hosts
= modelBase
513 .getBundleDescription().getHost().getHosts();
514 for (BundleDescription bd
: hosts
) {
516 System
.out
.println("Host for "
517 + modelBase
.getBundleDescription()
518 .getSymbolicName() + ": "
519 + bd
.getSymbolicName());
520 bundleDescription
= bd
;
523 bundleDescription
= modelBase
.getBundleDescription();
526 if (bundleDescription
!= null) {
527 String symbolicName
= bundleDescription
529 String bundleName
= bundleDescription
.getName();
531 bundlesToStart
.add(symbolicName
);
533 if (name
.length() > 0)
535 if (bundleName
!= null)
536 name
.append(bundleName
);
538 name
.append(symbolicName
);
545 static void debug(Object obj
) {
547 System
.out
.println(obj
);