KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > pde > internal > build > FeatureGenerator


1 /*******************************************************************************
2  * Copyright (c) 2006, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM - Initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.pde.internal.build;
12
13 import java.io.*;
14 import java.util.*;
15 import org.eclipse.core.runtime.*;
16 import org.eclipse.osgi.service.resolver.*;
17 import org.eclipse.osgi.util.NLS;
18 import org.eclipse.pde.build.Constants;
19 import org.eclipse.pde.internal.build.site.PDEState;
20 import org.eclipse.update.core.IFeature;
21 import org.osgi.framework.Version;
22
23 public class FeatureGenerator extends AbstractScriptGenerator {
24
25     private static final String JavaDoc FEATURE_PLATFORM_LAUNCHERS = "org.eclipse.platform.launchers"; //$NON-NLS-1$
26
private static final String JavaDoc FEATURE_EXECUTABLE = "org.eclipse.equinox.executable"; //$NON-NLS-1$
27
private static final String JavaDoc BUNDLE_OSGI = "org.eclipse.osgi"; //$NON-NLS-1$
28
private static final String JavaDoc BUNDLE_LAUNCHER = "org.eclipse.equinox.launcher"; //$NON-NLS-1$
29

30     private String JavaDoc featureId = null;
31     private String JavaDoc productFile = null;
32     private String JavaDoc[] pluginList = null;
33     private String JavaDoc[] fragmentList = null;
34     private String JavaDoc[] featureList = null;
35
36     private boolean includeLaunchers = true;
37
38     private ProductFile product = null;
39
40     private boolean verify = false;
41
42     private Properties antProperties;
43
44     /*
45      * Create and return a new Set with the given contents. If the arg
46      * is null then return an empty set.
47      */

48     private static Set createSet(String JavaDoc[] contents) {
49         if (contents == null)
50             return new LinkedHashSet(0);
51         Set result = new LinkedHashSet(contents.length);
52         for (int i = 0; i < contents.length; i++)
53             if (contents[i] != null)
54                 result.add(contents[i]);
55         return result;
56     }
57
58     /* (non-Javadoc)
59      * @see org.eclipse.pde.internal.build.AbstractScriptGenerator#generate()
60      */

61     public void generate() throws CoreException {
62         AbstractScriptGenerator.setStaticAntProperties(antProperties);
63         try {
64             initialize();
65             Set plugins = createSet(pluginList);
66             Set features = createSet(featureList);
67             Set fragments = createSet(fragmentList);
68             if (product != null) {
69                 if (product.useFeatures()) {
70                     features.addAll(product.getFeatures());
71                 } else {
72                     plugins.addAll(product.getPlugins(false));
73                     fragments.addAll(product.getFragments());
74                 }
75             }
76             try {
77                 createFeature(featureId, plugins, fragments, features);
78             } catch (FileNotFoundException e) {
79                 IStatus status = new Status(IStatus.ERROR, IPDEBuildConstants.PI_PDEBUILD, EXCEPTION_PRODUCT_FORMAT, NLS.bind(Messages.error_creatingFeature, e.getLocalizedMessage()), e);
80                 throw new CoreException(status);
81             }
82         } finally {
83             AbstractScriptGenerator.setStaticAntProperties(null);
84         }
85     }
86
87     public void setProductFile(String JavaDoc productFile) {
88         this.productFile = productFile;
89     }
90
91     public void setPluginList(String JavaDoc[] pluginList) {
92         this.pluginList = pluginList;
93     }
94
95     public void setFeatureList(String JavaDoc[] featureList) {
96         this.featureList = featureList;
97     }
98
99     public void setFragmentList(String JavaDoc[] fragmentList) {
100         this.fragmentList = fragmentList;
101     }
102
103     public void setFeatureId(String JavaDoc featureId) {
104         this.featureId = featureId;
105     }
106
107     public void setIncludeLaunchers(boolean includeLaunchers) {
108         this.includeLaunchers = includeLaunchers;
109     }
110
111     private void initialize() throws CoreException {
112         //get rid of old feature that we will be overwriting, we don't want it in the state accidently.
113
File dir = new File(getWorkingDirectory(), IPDEBuildConstants.DEFAULT_FEATURE_LOCATION + '/' + featureId);
114         File xml = new File(dir, Constants.FEATURE_FILENAME_DESCRIPTOR);
115         if (xml.exists()) {
116             xml.delete();
117         }
118
119         if (productFile != null && !productFile.startsWith("${") && productFile.length() > 0) { //$NON-NLS-1$
120
String JavaDoc productPath = findFile(productFile, false);
121             File f = null;
122             if (productPath != null) {
123                 f = new File(productPath);
124             } else {
125                 // couldn't find productFile, try it as a path directly
126
f = new File(productFile);
127                 if (!f.exists() || !f.isFile()) {
128                     // doesn't exist, try it as a path relative to the working directory
129
f = new File(getWorkingDirectory(), productFile);
130                     if (!f.exists() || !f.isFile()) {
131                         f = new File(getWorkingDirectory() + "/" + DEFAULT_PLUGIN_LOCATION, productFile); //$NON-NLS-1$
132
}
133                 }
134             }
135             if (f.exists() && f.isFile()) {
136                 product = new ProductFile(f.getAbsolutePath(), null);
137             } else {
138                 IStatus error = new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PRODUCT_FILE, NLS.bind(Messages.exception_missingElement, productFile), null);
139                 throw new CoreException(error);
140             }
141         }
142     }
143
144     /*
145      * Based on the version of OSGi that we have in our state, add the appropriate plug-ins/fragments/features
146      * for the launcher.
147      */

148     private void addLauncher(PDEState state, Set plugins, Set fragments, Set features) {
149         BundleDescription bundle = state.getResolvedBundle(BUNDLE_OSGI);
150         if (bundle == null)
151             return;
152         Version version = bundle.getVersion();
153         if (version.compareTo(new Version("3.3")) < 0) { //$NON-NLS-1$
154
// we have an OSGi version that is less than 3.3 so add the old launcher
155
features.add(FEATURE_PLATFORM_LAUNCHERS);
156         } else {
157             // we have OSGi version 3.3 or greater so add the executable feature
158
// and the launcher plug-in and fragments
159
IFeature executableFeature = null;
160             try {
161                 executableFeature = getSite(false).findFeature(FEATURE_EXECUTABLE, null, false);
162             } catch (CoreException e) {
163                 // ignore
164
}
165             if (executableFeature != null) {
166                 /* the executable feature includes the launcher and fragments already */
167                 features.add(FEATURE_EXECUTABLE);
168             } else {
169                 // We don't have the executable feature, at least try and get the launcher jar and fragments
170
plugins.add(BUNDLE_LAUNCHER);
171                 List configs = getConfigInfos();
172                 // only include the fragments for the platforms we are attempting to build, since the others
173
// probably aren't around
174
for (Iterator iterator = configs.iterator(); iterator.hasNext();) {
175                     Config config = (Config) iterator.next();
176                     String JavaDoc fragment = BUNDLE_LAUNCHER + '.' + config.getWs() + '.' + config.getOs();
177                     //macosx doesn't have the arch on its fragment
178
if (config.getOs().compareToIgnoreCase("macosx") != 0) //$NON-NLS-1$
179
fragment += '.' + config.getArch();
180
181                     fragments.add(fragment);
182                 }
183             }
184         }
185     }
186
187     /**
188      * Generate a feature that includes the given plug-ins, fragments and features.
189      * Feature order matters at compile time if there is dependencies between the features' contents.
190      * Make sure to pass an ordered set if this matters.
191      * @param feature - Name of the feature to generate
192      * @param plugins - plug-ins to include
193      * @param fragments - fragments to include
194      * @param features: An ordered set of features to include
195      * @throws CoreException
196      * @throws FileNotFoundException
197      */

198     protected void createFeature(String JavaDoc feature, Set plugins, Set fragments, Set features) throws CoreException, FileNotFoundException {
199         String JavaDoc location = IPDEBuildConstants.DEFAULT_FEATURE_LOCATION + '/' + feature;
200         File directory = new File(getWorkingDirectory(), location);
201         if (!directory.exists())
202             directory.mkdirs();
203
204         PDEState state = verify ? getSite(false).getRegistry() : null;
205         BundleHelper helper = BundleHelper.getDefault();
206
207         if (verify && includeLaunchers)
208             addLauncher(state, plugins, fragments, features);
209
210         //Create feature.xml
211
File file = new File(directory, Constants.FEATURE_FILENAME_DESCRIPTOR);
212         OutputStream output = new BufferedOutputStream(new FileOutputStream(file));
213         XMLWriter writer = null;
214         try {
215             writer = new XMLWriter(output);
216         } catch (UnsupportedEncodingException e) {
217             //should not happen
218
return;
219         }
220         try {
221             Map parameters = new HashMap();
222             Dictionary environment = new Hashtable(3);
223
224             parameters.put("id", feature); //$NON-NLS-1$
225
parameters.put("version", "1.0.0"); //$NON-NLS-1$ //$NON-NLS-2$
226
writer.startTag("feature", parameters, true); //$NON-NLS-1$
227

228             boolean fragment = false;
229             List configs = getConfigInfos();
230             //we do the generic config first as a special case
231
configs.remove(Config.genericConfig());
232             Iterator configIterator = configs.iterator();
233             Iterator listIter = plugins.iterator();
234             if (!listIter.hasNext()) {
235                 // no plugins, do fragments
236
fragment = true;
237                 listIter = fragments.iterator();
238             }
239             for (Config currentConfig = Config.genericConfig(); currentConfig != null; currentConfig = (Config) configIterator.next()) {
240                 environment.put("osgi.os", currentConfig.getOs()); //$NON-NLS-1$
241
environment.put("osgi.ws", currentConfig.getWs()); //$NON-NLS-1$
242
environment.put("osgi.arch", currentConfig.getArch()); //$NON-NLS-1$
243
for (; listIter.hasNext();) {
244                     String JavaDoc name = (String JavaDoc) listIter.next();
245                     boolean unpack = true;
246                     boolean writeBundle = !verify;
247                     if (verify) {
248                         BundleDescription bundle = state.getResolvedBundle(name);
249                         if (bundle != null) {
250                             //Bundle resolved, write it out if it matches the current config
251
String JavaDoc filterSpec = bundle.getPlatformFilter();
252                             if (filterSpec == null || helper.createFilter(filterSpec).match(environment)) {
253                                 writeBundle = true;
254                                 unpack = guessUnpack(bundle, (String JavaDoc[]) state.getExtraData().get(new Long JavaDoc(bundle.getBundleId())));
255                                 if (currentConfig.equals(Config.genericConfig())) {
256                                     listIter.remove();
257                                 }
258                             }
259                         } else {
260                             //Bundle did not resolve, only ok if it was because of the platform filter
261
BundleDescription[] bundles = state.getState().getBundles(name);
262                             boolean error = true;
263                             if (bundles != null && bundles.length > 0) {
264                                 ResolverError[] errors = state.getState().getResolverErrors(bundles[0]);
265                                 for (int i = 0; i < errors.length; i++) {
266                                     if ((errors[i].getType() & ResolverError.PLATFORM_FILTER) != 0) {
267                                         //didn't match config, this is ok
268
error = false;
269                                         break;
270                                     }
271                                 }
272                             }
273                             if (error) {
274                                 //throw error
275
String JavaDoc message = NLS.bind(Messages.exception_missingPlugin, name);
276                                 throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PLUGIN_MISSING, message, null));
277                             }
278                         }
279                     }
280
281                     if (writeBundle) {
282                         parameters.clear();
283                         parameters.put("id", name); //$NON-NLS-1$
284
parameters.put("version", "0.0.0"); //$NON-NLS-1$//$NON-NLS-2$
285
parameters.put("unpack", unpack ? "true" : "false"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
286
if (!currentConfig.equals(Config.genericConfig())) {
287                             parameters.put("os", currentConfig.getOs()); //$NON-NLS-1$
288
parameters.put("ws", currentConfig.getWs()); //$NON-NLS-1$
289
parameters.put("arch", currentConfig.getArch()); //$NON-NLS-1$
290
}
291                         if (fragment)
292                             parameters.put("fragment", "true"); //$NON-NLS-1$ //$NON-NLS-2$
293
writer.printTag("plugin", parameters, true, true, true); //$NON-NLS-1$
294
}
295
296                     if (!fragment && !listIter.hasNext() && fragments.size() > 0) {
297                         //finished the list of plugins, do the fragments now
298
fragment = true;
299                         listIter = fragments.iterator();
300                     }
301                 }
302                 if (!verify || !configIterator.hasNext()) {
303                     break;
304                 } else if (plugins.size() > 0) {
305                     fragment = false;
306                     listIter = plugins.iterator();
307                 } else {
308                     listIter = fragments.iterator();
309                 }
310             }
311
312             for (Iterator iter = features.iterator(); iter.hasNext();) {
313                 String JavaDoc name = (String JavaDoc) iter.next();
314                 if (verify) {
315                     //this will throw an exception if the feature is not found.
316
getSite(false).findFeature(name, null, true);
317                 }
318                 parameters.clear();
319                 parameters.put("id", name); //$NON-NLS-1$
320
parameters.put("version", "0.0.0"); //$NON-NLS-1$//$NON-NLS-2$
321
writer.printTag("includes", parameters, true, true, true); //$NON-NLS-1$
322
}
323             writer.endTag("feature"); //$NON-NLS-1$
324
} finally {
325             writer.close();
326         }
327
328         //create build.properties
329
file = new File(directory, IPDEBuildConstants.PROPERTIES_FILE);
330         Properties prop = new Properties();
331         prop.put("pde", "marker"); //$NON-NLS-1$ //$NON-NLS-2$
332
OutputStream stream = null;
333         try {
334             stream = new BufferedOutputStream(new FileOutputStream(file));
335             prop.store(stream, "Marker File so that the file gets written"); //$NON-NLS-1$
336
stream.flush();
337         } catch (IOException e) {
338             // nothing for now
339
} finally {
340             if (stream != null) {
341                 try {
342                     stream.close();
343                 } catch (IOException e1) {
344                     // nothing
345
}
346             }
347         }
348     }
349
350     public void setVerify(boolean verify) {
351         this.verify = verify;
352         reportResolutionErrors = verify;
353     }
354
355     public boolean guessUnpack(BundleDescription bundle, String JavaDoc[] classpath) {
356         if (bundle == null)
357             return true;
358
359         // launcher fragments are a special case, they have no bundle-classpath and they must
360
//be unpacked
361
if (bundle.getHost() != null && bundle.getName().startsWith(BUNDLE_LAUNCHER))
362             return true;
363
364         if (new File(bundle.getLocation()).isFile())
365             return false;
366
367         if (classpath.length == 0)
368             return false;
369
370         for (int i = 0; i < classpath.length; i++) {
371             if (classpath[i].equals(".")) //$NON-NLS-1$
372
return false;
373         }
374         return true;
375     }
376
377     public void setImmutableAntProperties(Properties properties) {
378         antProperties = properties;
379     }
380 }
381
Popular Tags