001: /*******************************************************************************
002: * Copyright (c) 2006, 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.build;
011:
012: import java.io.*;
013: import java.util.*;
014: import org.eclipse.core.runtime.CoreException;
015: import org.eclipse.core.runtime.Platform;
016: import org.eclipse.osgi.service.resolver.BundleDescription;
017: import org.eclipse.pde.internal.build.site.PDEState;
018:
019: public class ProductGenerator extends AbstractScriptGenerator {
020: private static final String BUNDLE_EQUINOX_COMMON = "org.eclipse.equinox.common"; //$NON-NLS-1$
021: private static final String BUNDLE_OSGI = "org.eclipse.osgi"; //$NON-NLS-1$
022: private static final String BUNDLE_CORE_RUNTIME = "org.eclipse.core.runtime"; //$NON-NLS-1$
023: private static final String BUNDLE_UPDATE_CONFIGURATOR = "org.eclipse.update.configurator"; //$NON-NLS-1$
024: private static final String START_LEVEL_2 = "@2:start"; //$NON-NLS-1$
025: private static final String START_LEVEL_3 = "@3:start"; //$NON-NLS-1$
026: private static final String START = "@start"; //$NON-NLS-1$
027:
028: private String product = null;
029: private ProductFile productFile = null;
030: private String root = null;
031: private boolean refactoredRuntime = false;
032: private Properties buildProperties;
033:
034: /* (non-Javadoc)
035: * @see org.eclipse.pde.internal.build.AbstractScriptGenerator#generate()
036: */
037: public void generate() throws CoreException {
038: initialize();
039:
040: if (productFile == null)
041: return;
042:
043: //we need at least a product id
044: if (productFile.getId() == null) {
045: return;
046: }
047:
048: String custom = findFile(productFile.getConfigIniPath(), false);
049: String location = null, fileList = null;
050: for (Iterator iter = getConfigInfos().iterator(); iter
051: .hasNext();) {
052: Config config = (Config) iter.next();
053: location = DEFAULT_PRODUCT_ROOT_FILES_DIR + '/'
054: + config.toStringReplacingAny(".", ANY_STRING); //$NON-NLS-1$
055:
056: String rootLocation = root + location;
057: File rootDir = new File(rootLocation);
058: if ((!rootDir.exists() && !rootDir.mkdirs())
059: || rootDir.isFile())
060: continue; //we will fail trying to create the files, TODO log warning/error
061:
062: //add generated root files to build.properties
063: if (buildProperties != null) {
064: fileList = buildProperties.getProperty(ROOT_PREFIX
065: + config.toString("."), ""); //$NON-NLS-1$ //$NON-NLS-2$
066: fileList += (fileList.length() > 0) ? ',' + location
067: : location;
068: buildProperties.put(
069: ROOT_PREFIX + config.toString("."), fileList); //$NON-NLS-1$
070: }
071:
072: //configuration/config.ini
073: if (custom != null) {
074: copyFile(custom, rootLocation
075: + "/configuration/config.ini"); //$NON-NLS-1$
076: } else {
077: createConfigIni(config, rootLocation);
078: }
079:
080: //only the config.ini makes sense in the any config
081: if (config.getOs().equals(Config.ANY))
082: continue;
083:
084: //.eclipseproduct
085: createEclipseProductFile(rootLocation);
086:
087: //eclipse.ini
088: createLauncherIniFile(rootLocation, config.getOs());
089: }
090:
091: }
092:
093: private void initialize() throws CoreException {
094: loadProduct();
095:
096: PDEState state = getSite(false).getRegistry();
097: refactoredRuntime = state
098: .getResolvedBundle(BUNDLE_EQUINOX_COMMON) != null;
099: }
100:
101: private void loadProduct() throws CoreException {
102: if (product == null || product.startsWith("${")) { //$NON-NLS-1$
103: productFile = null;
104: return;
105: }
106: String productPath = findFile(product, false);
107: File f = null;
108: if (productPath != null) {
109: f = new File(productPath);
110: } else {
111: // couldn't find productFile, try it as a path directly
112: f = new File(product);
113: if (!f.exists() || !f.isFile()) {
114: // doesn't exist, try it as a path relative to the working directory
115: f = new File(getWorkingDirectory(), product);
116: if (!f.exists() || !f.isFile()) {
117: f = new File(getWorkingDirectory()
118: + "/" + DEFAULT_PLUGIN_LOCATION, product); //$NON-NLS-1$
119: }
120: }
121: }
122:
123: //the ProductFile uses the OS to determine which icons to return, we don't care so can use null
124: //this is better since this generator may be used for multiple OS's
125: productFile = new ProductFile(f.getAbsolutePath(), null);
126: }
127:
128: private void copyFile(String src, String dest) {
129: File source = new File(src);
130: if (!source.exists())
131: return;
132: File destination = new File(dest);
133: File destDir = destination.getParentFile();
134: if ((!destDir.exists() && !destDir.mkdirs())
135: || destDir.isFile())
136: return; //we will fail trying to create the file, TODO log warning/error
137:
138: InputStream in = null;
139: OutputStream out = null;
140: try {
141: in = new BufferedInputStream(new FileInputStream(source));
142: out = new BufferedOutputStream(new FileOutputStream(
143: destination));
144:
145: //Transfer bytes from in to out
146: byte[] buf = new byte[1024];
147: int len;
148: while ((len = in.read(buf)) > 0) {
149: out.write(buf, 0, len);
150: }
151: } catch (IOException e) {
152: //nothing
153: } finally {
154: if (in != null) {
155: try {
156: in.close();
157: } catch (IOException e) {
158: //nothing
159: }
160: }
161: if (out != null) {
162: try {
163: out.close();
164: } catch (IOException e) {
165: //nothing
166: }
167: }
168: }
169: }
170:
171: private void createConfigIni(Config config, String location)
172: throws CoreException {
173: File configDir = new File(location + "/configuration"); //$NON-NLS-1$
174: if ((!configDir.exists() && !configDir.mkdirs())
175: || configDir.isFile())
176: return; //we will fail trying to create the file, TODO log warning/error
177:
178: PDEState state = getSite(false).getRegistry();
179:
180: StringBuffer buffer = new StringBuffer();
181: buffer.append("#Product Runtime Configuration File\n"); //$NON-NLS-1$
182:
183: String splash = getSplashLocation(config);
184: if (splash != null)
185: buffer.append("osgi.splashPath=" + splash + '\n'); //$NON-NLS-1$
186:
187: String application = productFile.getApplication();
188: if (application != null)
189: buffer.append("eclipse.application=" + application + '\n'); //$NON-NLS-1$
190: buffer.append("eclipse.product=" + productFile.getId() + '\n'); //$NON-NLS-1$
191: buffer.append("osgi.bundles="); //$NON-NLS-1$
192: //When update configurator is present or when feature based product
193: if (productFile.useFeatures()
194: || productFile
195: .containsPlugin(BUNDLE_UPDATE_CONFIGURATOR)) {
196: if (refactoredRuntime) {
197: //start levels for eclipse 3.2
198: //org.eclipse.equinox.common@2:start,
199: buffer.append(BUNDLE_EQUINOX_COMMON);
200: buffer.append(START_LEVEL_2);
201: buffer.append(',');
202: //org.eclipse.update.configurator@3:start
203: buffer.append(BUNDLE_UPDATE_CONFIGURATOR);
204: buffer.append(START_LEVEL_3);
205: buffer.append(',');
206: //org.eclipse.core.runtime
207: buffer.append(BUNDLE_CORE_RUNTIME);
208: buffer.append(START);
209: buffer.append('\n');
210: } else {
211: //start level for 3.1 and 3.0
212: buffer.append(BUNDLE_CORE_RUNTIME);
213: buffer.append(START_LEVEL_2);
214: buffer.append(',');
215: buffer.append(BUNDLE_UPDATE_CONFIGURATOR);
216: buffer.append(START_LEVEL_3);
217: buffer.append('\n');
218: }
219: } else {
220: //When the plugins are all listed.
221: Dictionary environment = new Hashtable(3);
222: environment.put("osgi.os", config.getOs()); //$NON-NLS-1$
223: environment.put("osgi.ws", config.getWs()); //$NON-NLS-1$
224: environment.put("osgi.arch", config.getArch()); //$NON-NLS-1$
225:
226: List pluginList = productFile.getPlugins();
227: BundleHelper helper = BundleHelper.getDefault();
228: boolean first = true;
229: for (Iterator iter = pluginList.iterator(); iter.hasNext();) {
230: String id = (String) iter.next();
231: BundleDescription bundle = state.getResolvedBundle(id);
232: if (bundle == null) {
233: //TODO error?
234: continue;
235: }
236: String filter = bundle.getPlatformFilter();
237: if (filter == null
238: || helper.createFilter(filter).match(
239: environment)) {
240: if (BUNDLE_OSGI.equals(id))
241: continue;
242: if (first)
243: first = false;
244: else
245: buffer.append(","); //$NON-NLS-1$
246: buffer.append(id);
247: if (BUNDLE_EQUINOX_COMMON.equals(id)) {
248: buffer.append(START_LEVEL_2);
249: } else if (BUNDLE_CORE_RUNTIME.equals(id)) {
250: if (refactoredRuntime) {
251: buffer.append(START);
252: } else {
253: buffer.append(START_LEVEL_2);
254: }
255: }
256: }
257: }
258: buffer.append('\n');
259: }
260: buffer.append("osgi.bundles.defaultStartLevel=4\n"); //$NON-NLS-1$
261:
262: FileWriter writer = null;
263: try {
264: writer = new FileWriter(new File(configDir, "config.ini")); //$NON-NLS-1$
265: writer.write(buffer.toString());
266: } catch (IOException e) {
267: //nothing
268: } finally {
269: try {
270: if (writer != null)
271: writer.close();
272: } catch (IOException e) {
273: //nothing
274: }
275: }
276:
277: }
278:
279: private void createEclipseProductFile(String directory)
280: throws CoreException {
281: File dir = new File(directory);
282: if ((!dir.exists() && !dir.mkdirs()) || dir.isFile())
283: return; //we will fail trying to create the file, TODO log warning/error
284:
285: Properties properties = new Properties();
286: if (productFile.getProductName() != null)
287: properties.put("name", productFile.getProductName()); //$NON-NLS-1$
288: if (productFile.getId() != null)
289: properties.put("id", productFile.getId()); //$NON-NLS-1$
290:
291: BundleDescription bundle = getSite(false).getRegistry()
292: .getResolvedBundle(getBrandingPlugin());
293: if (bundle != null)
294: properties.put("version", bundle.getVersion().toString()); //$NON-NLS-1$
295:
296: OutputStream stream = null;
297: try {
298: File file = new File(dir, ".eclipseproduct"); //$NON-NLS-1$
299: stream = new BufferedOutputStream(
300: new FileOutputStream(file));
301: properties.store(stream, "Eclipse Product File"); //$NON-NLS-1$
302: stream.flush();
303: } catch (IOException e) {
304: //nothing
305: } finally {
306: if (stream != null) {
307: try {
308: stream.close();
309: } catch (IOException e) {
310: //nothing
311: }
312: }
313: }
314: }
315:
316: private String getBrandingPlugin() {
317: String id = productFile.getId();
318: if (id == null)
319: return null;
320: int dot = id.lastIndexOf('.');
321: return (dot != -1) ? id.substring(0, dot) : null;
322: }
323:
324: private String getSplashLocation(Config config)
325: throws CoreException {
326: String plugin = productFile.getSplashLocation();
327:
328: if (plugin == null) {
329: plugin = getBrandingPlugin();
330: }
331:
332: if (plugin == null)
333: return null;
334:
335: StringBuffer buffer = new StringBuffer(
336: "platform:/base/plugins/"); //$NON-NLS-1$
337: buffer.append(plugin);
338:
339: Dictionary environment = new Hashtable(4);
340: environment.put("osgi.os", config.getOs()); //$NON-NLS-1$
341: environment.put("osgi.ws", config.getWs()); //$NON-NLS-1$
342: environment.put("osgi.arch", config.getArch()); //$NON-NLS-1$
343:
344: PDEState state = getSite(false).getRegistry();
345: BundleHelper helper = BundleHelper.getDefault();
346: BundleDescription bundle = state.getResolvedBundle(plugin);
347: if (bundle != null) {
348: BundleDescription[] fragments = bundle.getFragments();
349: for (int i = 0; i < fragments.length; i++) {
350: String filter = fragments[i].getPlatformFilter();
351: if (filter == null
352: || helper.createFilter(filter).match(
353: environment)) {
354: String fragmentId = fragments[i].getSymbolicName();
355: if (productFile.containsPlugin(fragmentId)) {
356: buffer.append(",platform:/base/plugins/"); //$NON-NLS-1$
357: buffer.append(fragmentId);
358: }
359: }
360: }
361: }
362: return buffer.toString();
363: }
364:
365: private void createLauncherIniFile(String directory, String os) {
366: String launcher = getLauncherName();
367:
368: if (os.equals(Platform.OS_MACOSX)) {
369: directory += "/" + launcher + ".app/Contents/MacOS"; //$NON-NLS-1$//$NON-NLS-2$
370: }
371: File dir = new File(directory);
372: if ((!dir.exists() && !dir.mkdirs()) || dir.isFile())
373: return; //we will fail trying to create the file TODO log warning/error
374:
375: String programArgs = productFile.getProgramArguments(os);
376: String vmArgs = productFile.getVMArguments(os);
377:
378: if ((programArgs == null || programArgs.length() == 0)
379: && (vmArgs == null || vmArgs.length() == 0))
380: return;
381:
382: String lineDelimiter = Platform.OS_WIN32.equals(os) ? "\r\n" : "\n"; //$NON-NLS-1$ //$NON-NLS-2$
383: PrintWriter writer = null;
384: try {
385: writer = new PrintWriter(new FileWriter(new File(dir,
386: launcher + ".ini"))); //$NON-NLS-1$
387: if (programArgs != null && programArgs.length() > 0) {
388: StringReader reader = new StringReader(programArgs);
389: StreamTokenizer tokenizer = new StreamTokenizer(reader);
390: tokenizer.resetSyntax();
391: tokenizer.whitespaceChars(0, 0x20);
392: tokenizer.wordChars(0x21, 0xFF);
393: tokenizer.quoteChar('"');
394: tokenizer.quoteChar('\'');
395: while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
396: writer.print(tokenizer.sval);
397: writer.print(lineDelimiter);
398: }
399: }
400: if (vmArgs != null && vmArgs.length() > 0) {
401: writer.print("-vmargs"); //$NON-NLS-1$
402: writer.print(lineDelimiter);
403: StringReader reader = new StringReader(vmArgs);
404: StreamTokenizer tokenizer = new StreamTokenizer(reader);
405: tokenizer.resetSyntax();
406: tokenizer.whitespaceChars(0, 0x20);
407: tokenizer.wordChars(0x21, 0xFF);
408: tokenizer.quoteChar('"');
409: tokenizer.quoteChar('\'');
410: while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
411: writer.print(tokenizer.sval);
412: writer.print(lineDelimiter);
413: }
414: }
415: } catch (IOException e) {
416: //nothing
417: } finally {
418: if (writer != null) {
419: writer.close();
420: }
421: }
422: }
423:
424: private String getLauncherName() {
425: String name = productFile.getLauncherName();
426:
427: if (name != null && name.length() > 0) {
428: name = name.trim();
429: if (name.endsWith(".exe")) //$NON-NLS-1$
430: name = name.substring(0, name.length() - 4);
431: return name;
432: }
433: return "eclipse"; //$NON-NLS-1$
434: }
435:
436: public void setProduct(String product) {
437: this .product = product;
438: }
439:
440: public void setRoot(String root) {
441: this .root = root;
442: }
443:
444: public void setBuildProperties(Properties buildProperties) {
445: this.buildProperties = buildProperties;
446: }
447:
448: }
|