001: /*******************************************************************************
002: * Copyright (c) 2005, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.ui.launcher;
011:
012: import java.io.File;
013: import java.io.FileInputStream;
014: import java.io.FileOutputStream;
015: import java.io.IOException;
016: import java.util.ArrayList;
017: import java.util.HashSet;
018: import java.util.Iterator;
019: import java.util.Map;
020: import java.util.Properties;
021: import java.util.Set;
022: import java.util.StringTokenizer;
023:
024: import org.eclipse.core.runtime.CoreException;
025: import org.eclipse.core.runtime.IConfigurationElement;
026: import org.eclipse.core.runtime.IExtension;
027: import org.eclipse.core.runtime.IStatus;
028: import org.eclipse.core.runtime.Path;
029: import org.eclipse.core.runtime.Status;
030: import org.eclipse.core.variables.IStringVariableManager;
031: import org.eclipse.core.variables.VariablesPlugin;
032: import org.eclipse.debug.core.ILaunchConfiguration;
033: import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
034: import org.eclipse.osgi.service.resolver.BundleDescription;
035: import org.eclipse.pde.core.plugin.IPluginModelBase;
036: import org.eclipse.pde.core.plugin.TargetPlatform;
037: import org.eclipse.pde.internal.core.PDECore;
038: import org.eclipse.pde.internal.core.TargetPlatformHelper;
039: import org.eclipse.pde.internal.ui.PDEPlugin;
040: import org.eclipse.pde.ui.launcher.IPDELauncherConstants;
041:
042: public class LaunchConfigurationHelper {
043:
044: public static void synchronizeManifests(
045: ILaunchConfiguration config, File configDir) {
046: try {
047: String programArgs = config
048: .getAttribute(
049: IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,
050: ""); //$NON-NLS-1$
051: if (programArgs.indexOf("-clean") != -1) //$NON-NLS-1$
052: return;
053: } catch (CoreException e) {
054: }
055: File dir = new File(configDir, "org.eclipse.osgi/manifests"); //$NON-NLS-1$
056: if (dir.exists() && dir.isDirectory()) {
057: PDECore.getDefault().getJavaElementChangeListener()
058: .synchronizeManifests(dir);
059: }
060: }
061:
062: public static File getConfigurationArea(ILaunchConfiguration config) {
063: File dir = getConfigurationLocation(config);
064: if (!dir.exists())
065: dir.mkdirs();
066: return dir;
067: }
068:
069: public static File getConfigurationLocation(
070: ILaunchConfiguration config) {
071: //bug 170213 change config location if config name contains #
072: String configName = config.getName();
073: configName = configName.replace('#', 'h');
074: File dir = new File(PDECore.getDefault().getStateLocation()
075: .toOSString(), configName);
076: try {
077: if (!config
078: .getAttribute(
079: IPDELauncherConstants.CONFIG_USE_DEFAULT_AREA,
080: true)) {
081: String userPath = config.getAttribute(
082: IPDELauncherConstants.CONFIG_LOCATION,
083: (String) null);
084: if (userPath != null) {
085: userPath = getSubstitutedString(userPath);
086: dir = new File(userPath).getAbsoluteFile();
087: }
088: }
089: } catch (CoreException e) {
090: }
091: return dir;
092: }
093:
094: private static String getSubstitutedString(String text)
095: throws CoreException {
096: if (text == null)
097: return ""; //$NON-NLS-1$
098: IStringVariableManager mgr = VariablesPlugin.getDefault()
099: .getStringVariableManager();
100: return mgr.performStringSubstitution(text);
101: }
102:
103: public static Properties createConfigIniFile(
104: ILaunchConfiguration configuration, String productID,
105: Map map, File directory) throws CoreException {
106: Properties properties = null;
107: // if we are to generate a config.ini, start with the values in the target platform's config.ini - bug 141918
108: if (configuration.getAttribute(
109: IPDELauncherConstants.CONFIG_GENERATE_DEFAULT, true)) {
110: properties = TargetPlatformHelper.getConfigIniProperties();
111: // if target's config.ini does not exist, lets try to fill in default values
112: if (properties == null)
113: properties = new Properties();
114: // keep properties only if we are launching the default product (bug 175437)
115: else if (productID == null
116: || !productID.equals(properties
117: .get("eclipse.product"))) //$NON-NLS-1$
118: properties.clear();
119: // if target's config.ini has the osgi.bundles header, then parse and compute the proper osgi.bundles value
120: String bundleList = properties.getProperty("osgi.bundles"); //$NON-NLS-1$
121: if (bundleList != null)
122: properties
123: .setProperty(
124: "osgi.bundles", computeOSGiBundles(TargetPlatformHelper.stripPathInformation(bundleList), map)); //$NON-NLS-1$
125: } else {
126: String templateLoc = configuration.getAttribute(
127: IPDELauncherConstants.CONFIG_TEMPLATE_LOCATION,
128: (String) null);
129: if (templateLoc != null) {
130: properties = loadFromTemplate(getSubstitutedString(templateLoc));
131: // if template contains osgi.bundles, then only strip the path, do not compute the value
132: String osgiBundles = properties
133: .getProperty("osgi.bundles"); //$NON-NLS-1$
134: if (osgiBundles != null)
135: properties
136: .setProperty(
137: "osgi.bundles", TargetPlatformHelper.stripPathInformation(osgiBundles)); //$NON-NLS-1$
138: }
139: }
140: // whether we create a new config.ini or read from one as a template, we should add the required properties - bug 161265
141: if (properties != null)
142: addRequiredProperties(properties, productID, map);
143: else
144: properties = new Properties();
145: setBundleLocations(map, properties);
146: if (!directory.exists())
147: directory.mkdirs();
148: save(new File(directory, "config.ini"), properties); //$NON-NLS-1$
149: return properties;
150: }
151:
152: private static void addRequiredProperties(Properties properties,
153: String productID, Map map) {
154: if (!properties.containsKey("osgi.install.area")) //$NON-NLS-1$
155: properties
156: .setProperty(
157: "osgi.install.area", "file:" + TargetPlatform.getLocation()); //$NON-NLS-1$ //$NON-NLS-2$
158: if (!properties.containsKey("osgi.configuration.cascaded")) //$NON-NLS-1$
159: properties.setProperty(
160: "osgi.configuration.cascaded", "false"); //$NON-NLS-1$ //$NON-NLS-2$
161: if (!properties.containsKey("osgi.framework")) //$NON-NLS-1$
162: properties
163: .setProperty("osgi.framework", "org.eclipse.osgi"); //$NON-NLS-1$ //$NON-NLS-2$
164: if (!properties.containsKey("osgi.splashPath") && productID != null) //$NON-NLS-1$
165: addSplashLocation(properties, productID, map);
166: // if osgi.splashPath is set, try to resolve relative paths to absolute paths
167: if (properties.containsKey("osgi.splashPath")) //$NON-NLS-1$
168: resolveLocationPath(properties
169: .getProperty("osgi.splashPath"), properties, map); //$NON-NLS-1$
170: if (!properties.containsKey("osgi.bundles")) //$NON-NLS-1$
171: properties
172: .setProperty(
173: "osgi.bundles", computeOSGiBundles(TargetPlatform.getBundleList(), map)); //$NON-NLS-1$
174: if (!properties.containsKey("osgi.bundles.defaultStartLevel")) //$NON-NLS-1$
175: properties.setProperty(
176: "osgi.bundles.defaultStartLevel", "4"); //$NON-NLS-1$ //$NON-NLS-2$
177: }
178:
179: private static String computeOSGiBundles(String bundleList, Map map) {
180: StringBuffer buffer = new StringBuffer();
181: Set initialBundleSet = new HashSet();
182: StringTokenizer tokenizer = new StringTokenizer(bundleList, ","); //$NON-NLS-1$
183: while (tokenizer.hasMoreTokens()) {
184: String token = tokenizer.nextToken();
185: int index = token.indexOf('@');
186: String id = index != -1 ? token.substring(0, index) : token;
187: if (map.containsKey(id)) {
188: if (buffer.length() > 0)
189: buffer.append(',');
190: buffer.append(id);
191: if (index != -1 && index < token.length() - 1)
192: buffer.append(token.substring(index));
193: initialBundleSet.add(id);
194: }
195: }
196: // if org.eclipse.update.configurator is not included (LIKE IN BASIC RCP APPLICATION), then write out all bundles in osgi.bundles - bug 170772
197: if (!initialBundleSet
198: .contains("org.eclipse.update.configurator")) { //$NON-NLS-1$
199: initialBundleSet.add("org.eclipse.osgi"); //$NON-NLS-1$
200: Iterator iter = map.keySet().iterator();
201: while (iter.hasNext()) {
202: String id = iter.next().toString();
203: if (!initialBundleSet.contains(id)) {
204: if (buffer.length() > 0)
205: buffer.append(',');
206: buffer.append(id);
207: }
208: }
209: }
210: return buffer.toString();
211: }
212:
213: private static Properties loadFromTemplate(String templateLoc)
214: throws CoreException {
215: Properties properties = new Properties();
216: File templateFile = new File(templateLoc);
217: if (templateFile.exists() && templateFile.isFile()) {
218: FileInputStream stream = null;
219: try {
220: stream = new FileInputStream(templateFile);
221: properties.load(stream);
222: } catch (Exception e) {
223: String message = e.getMessage();
224: if (message != null)
225: throw new CoreException(new Status(IStatus.ERROR,
226: PDEPlugin.getPluginId(), IStatus.ERROR,
227: message, e));
228: } finally {
229: if (stream != null) {
230: try {
231: stream.close();
232: } catch (IOException e) {
233: }
234: }
235: }
236: }
237: return properties;
238: }
239:
240: private static void addSplashLocation(Properties properties,
241: String productID, Map map) {
242: Properties targetConfig = TargetPlatformHelper
243: .getConfigIniProperties();
244: String targetProduct = targetConfig == null ? null
245: : targetConfig.getProperty("eclipse.product"); //$NON-NLS-1$
246: String targetSplash = targetConfig == null ? null
247: : targetConfig.getProperty("osgi.splashPath"); //$NON-NLS-1$
248: if (!productID.equals(targetProduct) || targetSplash == null) {
249: ArrayList locations = new ArrayList();
250: String plugin = getContributingPlugin(productID);
251: locations.add(plugin);
252: IPluginModelBase model = (IPluginModelBase) map.get(plugin);
253: if (model != null) {
254: BundleDescription desc = model.getBundleDescription();
255: if (desc != null) {
256: BundleDescription[] fragments = desc.getFragments();
257: for (int i = 0; i < fragments.length; i++)
258: locations.add(fragments[i].getSymbolicName());
259: }
260: }
261: resolveLocationPath(locations, properties, map);
262: } else
263: resolveLocationPath(targetSplash, properties, map);
264: }
265:
266: private static void resolveLocationPath(String splashPath,
267: Properties properties, Map map) {
268: ArrayList locations = new ArrayList();
269: StringTokenizer tok = new StringTokenizer(splashPath, ","); //$NON-NLS-1$
270: while (tok.hasMoreTokens())
271: locations.add(tok.nextToken());
272: resolveLocationPath(locations, properties, map);
273: }
274:
275: private static void resolveLocationPath(ArrayList locations,
276: Properties properties, Map map) {
277: StringBuffer buffer = new StringBuffer();
278: for (int i = 0; i < locations.size(); i++) {
279: String location = (String) locations.get(i);
280: if (location.startsWith("platform:/base/plugins/")) { //$NON-NLS-1$
281: location = location.replaceFirst(
282: "platform:/base/plugins/", ""); //$NON-NLS-1$ //$NON-NLS-2$
283: }
284: String url = getBundleURL(location, map);
285: if (url == null)
286: continue;
287: if (buffer.length() > 0)
288: buffer.append(","); //$NON-NLS-1$
289: buffer.append(url);
290: }
291: if (buffer.length() > 0)
292: properties
293: .setProperty("osgi.splashPath", buffer.toString()); //$NON-NLS-1$
294: }
295:
296: public static String getBundleURL(String id, Map pluginMap) {
297: IPluginModelBase model = (IPluginModelBase) pluginMap.get(id
298: .trim());
299: return getBundleURL(model);
300: }
301:
302: public static String getBundleURL(IPluginModelBase model) {
303: if (model == null)
304: return null;
305: return "file:" + new Path(model.getInstallLocation()).removeTrailingSeparator().toString(); //$NON-NLS-1$
306: }
307:
308: private static void setBundleLocations(Map map,
309: Properties properties) {
310: String framework = properties.getProperty("osgi.framework"); //$NON-NLS-1$
311: if (framework != null) {
312: if (framework.startsWith("platform:/base/plugins/")) { //$NON-NLS-1$
313: framework.replaceFirst("platform:/base/plugins/", ""); //$NON-NLS-1$ //$NON-NLS-2$
314: }
315: String url = getBundleURL(framework, map);
316: if (url != null)
317: properties.setProperty("osgi.framework", url); //$NON-NLS-1$
318: }
319:
320: String bundles = properties.getProperty("osgi.bundles"); //$NON-NLS-1$
321: if (bundles != null) {
322: StringBuffer buffer = new StringBuffer();
323: StringTokenizer tokenizer = new StringTokenizer(bundles,
324: ","); //$NON-NLS-1$
325: while (tokenizer.hasMoreTokens()) {
326: String token = tokenizer.nextToken().trim();
327: String url = getBundleURL(token, map);
328: int index = -1;
329: if (url == null) {
330: index = token.indexOf('@');
331: if (index != -1)
332: url = getBundleURL(token.substring(0, index),
333: map);
334: if (url == null) {
335: index = token.indexOf(':');
336: if (index != -1)
337: url = getBundleURL(token
338: .substring(0, index), map);
339: }
340: }
341: if (url != null) {
342: if (buffer.length() > 0) {
343: buffer.append(","); //$NON-NLS-1$
344: }
345: buffer.append("reference:" + url); //$NON-NLS-1$
346: if (index != -1)
347: buffer.append(token.substring(index));
348: }
349: }
350: properties.setProperty("osgi.bundles", buffer.toString()); //$NON-NLS-1$
351: }
352: }
353:
354: public static void save(File file, Properties properties) {
355: try {
356: FileOutputStream stream = new FileOutputStream(file);
357: properties.store(stream, "Configuration File"); //$NON-NLS-1$
358: stream.flush();
359: stream.close();
360: } catch (IOException e) {
361: PDECore.logException(e);
362: }
363: }
364:
365: public static String getContributingPlugin(String productID) {
366: if (productID == null)
367: return null;
368: int index = productID.lastIndexOf('.');
369: return index == -1 ? productID : productID.substring(0, index);
370: }
371:
372: public static String getProductID(ILaunchConfiguration configuration)
373: throws CoreException {
374: if (configuration.getAttribute(
375: IPDELauncherConstants.USE_PRODUCT, false)) {
376: return configuration.getAttribute(
377: IPDELauncherConstants.PRODUCT, (String) null);
378: }
379:
380: // find the product associated with the application, and return its
381: // contributing plug-in
382: String appID = configuration.getAttribute(
383: IPDELauncherConstants.APPLICATION, TargetPlatform
384: .getDefaultApplication());
385: IExtension[] extensions = PDECore.getDefault()
386: .getExtensionsRegistry().findExtensions(
387: "org.eclipse.core.runtime.products"); //$NON-NLS-1$
388: for (int i = 0; i < extensions.length; i++) {
389: String id = extensions[i].getUniqueIdentifier();
390: if (id == null)
391: continue;
392: IConfigurationElement[] children = extensions[i]
393: .getConfigurationElements();
394: if (children.length != 1)
395: continue;
396: if (!"product".equals(children[0].getName())) //$NON-NLS-1$
397: continue;
398: if (appID.equals(children[0].getAttribute("application"))) //$NON-NLS-1$
399: return id;
400: }
401: return null;
402:
403: }
404:
405: }
|