KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > pde > internal > build > builder > ClasspathComputer2_1


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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.builder;
12
13 import java.io.IOException JavaDoc;
14 import java.net.MalformedURLException JavaDoc;
15 import java.net.URL JavaDoc;
16 import java.util.*;
17 import org.eclipse.core.internal.boot.PlatformURLHandler;
18 import org.eclipse.core.internal.runtime.PlatformURLFragmentConnection;
19 import org.eclipse.core.internal.runtime.PlatformURLPluginConnection;
20 import org.eclipse.core.runtime.*;
21 import org.eclipse.osgi.service.resolver.BundleDescription;
22 import org.eclipse.osgi.service.resolver.HostSpecification;
23 import org.eclipse.osgi.util.NLS;
24 import org.eclipse.pde.internal.build.*;
25 import org.eclipse.pde.internal.build.site.PDEState;
26
27 public class ClasspathComputer2_1 implements IClasspathComputer, IPDEBuildConstants, IXMLConstants, IBuildPropertiesConstants {
28     private ModelBuildScriptGenerator generator;
29         
30     public ClasspathComputer2_1(ModelBuildScriptGenerator modelGenerator) {
31         this.generator = modelGenerator;
32     }
33
34     /**
35      * Compute the classpath for the given jar.
36      * The path returned conforms to Parent / Self / Prerequisite
37      *
38      * @param model the plugin containing the jar compiled
39      * @param jar the jar for which the classpath is being compiled
40      * @return String the classpath
41      * @throws CoreException
42      */

43     public List getClasspath(BundleDescription model, ModelBuildScriptGenerator.CompiledEntry jar) throws CoreException {
44         List classpath = new ArrayList(20);
45         List pluginChain = new ArrayList(10);
46         Set addedPlugins=new HashSet(20);
47         String JavaDoc location = generator.getLocation(model);
48
49         //PARENT
50
addPlugin(getPlugin(PI_BOOT, null), classpath, location);
51
52         //SELF
53
addSelf(model, jar, classpath, location, pluginChain,addedPlugins);
54
55         //PREREQUISITE
56
addPrerequisites(model, classpath, location, pluginChain,addedPlugins);
57
58         return classpath;
59
60     }
61
62     /**
63      * Add the specified plugin (including its jars) and its fragments
64      * @param plugin
65      * @param classpath
66      * @param location
67      * @throws CoreException
68      */

69     private void addPlugin(BundleDescription plugin, List classpath, String JavaDoc location) throws CoreException {
70         addRuntimeLibraries(plugin, classpath, location);
71         addFragmentsLibraries(plugin, classpath, location);
72     }
73
74     /**
75      * Add the runtime libraries for the specified plugin.
76      * @param model
77      * @param classpath
78      * @param baseLocation
79      * @throws CoreException
80      */

81     private void addRuntimeLibraries(BundleDescription model, List classpath, String JavaDoc baseLocation) throws CoreException {
82         String JavaDoc[] libraries = getClasspathEntries(model);
83         String JavaDoc root = generator.getLocation(model);
84         IPath base = Utils.makeRelative(new Path(root), new Path(baseLocation));
85         Properties modelProps = getBuildPropertiesFor(model);
86         for (int i = 0; i < libraries.length; i++) {
87             addDevEntries(model, baseLocation, classpath, Utils.getArrayFromString(generator.getBuildProperties().getProperty(PROPERTY_OUTPUT_PREFIX + libraries[i])));
88             addPathAndCheck(model.getSymbolicName(), base, libraries[i], modelProps, classpath);
89         }
90     }
91
92     /**
93      * Return the plug-in model object from the plug-in registry for the given
94      * plug-in identifier and version. If the plug-in is not in the registry then
95      * throw an exception.
96      *
97      * @param id the plug-in identifier
98      * @param version the plug-in version
99      * @return BundleDescription
100      * @throws CoreException if the specified plug-in version does not exist in the registry
101      */

102     private BundleDescription getPlugin(String JavaDoc id, String JavaDoc version) throws CoreException {
103         return generator.getSite(false).getRegistry().getResolvedBundle(id, version);
104     }
105
106     /**
107      * Add all fragments of the given plugin
108      * @param plugin
109      * @param classpath
110      * @param baseLocation
111      * @throws CoreException
112      */

113     private void addFragmentsLibraries(BundleDescription plugin, List classpath, String JavaDoc baseLocation) throws CoreException {
114         // if plugin is not a plugin, it's a fragment and there is no fragment for a fragment. So we return.
115
BundleDescription[] fragments = plugin.getFragments();
116         if (fragments == null)
117             return;
118
119         for (int i = 0; i < fragments.length; i++) {
120             if (fragments[i] == generator.getModel())
121                 continue;
122             addPluginLibrariesToFragmentLocations(plugin, fragments[i], classpath, baseLocation);
123             addRuntimeLibraries(fragments[i], classpath, baseLocation);
124         }
125     }
126
127     /**
128      * There are cases where the plug-in only declares a library but the real JAR is under
129      * a fragment location. This method gets all the plugin libraries and place them in the
130      * possible fragment location.
131      *
132      * @param plugin
133      * @param fragment
134      * @param classpath
135      * @param baseLocation
136      * @throws CoreException
137      */

138     private void addPluginLibrariesToFragmentLocations(BundleDescription plugin, BundleDescription fragment, List classpath, String JavaDoc baseLocation) throws CoreException {
139         //TODO This methods causes the addition of a lot of useless entries. See bug #35544
140
//If we reintroduce the test below, we reintroduce the problem 35544
141
// if (fragment.getRuntime() != null)
142
// return;
143

144         String JavaDoc[] libraries = getClasspathEntries(plugin);
145         String JavaDoc root = generator.getLocation(fragment);
146         IPath base = Utils.makeRelative(new Path(root), new Path(baseLocation));
147         Properties modelProps = getBuildPropertiesFor(fragment);
148         for (int i = 0; i < libraries.length; i++) {
149             addPathAndCheck(fragment.getSymbolicName(), base, libraries[i], modelProps, classpath);
150         }
151     }
152
153     private Properties getBuildPropertiesFor(BundleDescription bundle) {
154         try {
155             return AbstractScriptGenerator.readProperties(generator.getLocation(bundle), PROPERTIES_FILE, IStatus.OK);
156         } catch (CoreException e) {
157             //ignore
158
}
159         return null;
160     }
161
162     // Add a path into the classpath for a given model
163
// path : The path to add
164
// classpath : The classpath in which we want to add this path
165
private void addPathAndCheck(String JavaDoc pluginId, IPath basePath, String JavaDoc libraryName, Properties modelProperties, List classpath) {
166         String JavaDoc path = basePath.append(libraryName).toString();
167         path = generator.replaceVariables(path, pluginId == null ? false : generator.getCompiledElements().contains(pluginId));
168         if (generator.getCompiledElements().contains(pluginId)) {
169             if (modelProperties == null || modelProperties.getProperty("source." + libraryName) != null) //$NON-NLS-1$
170
path = Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER) + '/' + path;
171         }
172         if (!classpath.contains(path))
173             classpath.add(path);
174     }
175
176     private void addSelf(BundleDescription model, ModelBuildScriptGenerator.CompiledEntry jar, List classpath, String JavaDoc location, List pluginChain, Set addedPlugins) throws CoreException {
177         // If model is a fragment, we need to add in the classpath the plugin to which it is related
178
HostSpecification host = model.getHost();
179         if (host != null) {
180             BundleDescription[] hosts = host.getHosts();
181             for(int i=0; i<hosts.length; i++)
182                 addPluginAndPrerequisites(hosts[i], classpath, location, pluginChain, addedPlugins);
183         }
184
185         // Add the libraries
186
Properties modelProperties = generator.getBuildProperties();
187         String JavaDoc jarOrder = (String JavaDoc) modelProperties.get(PROPERTY_JAR_ORDER);
188         if (jarOrder == null) {
189             // if no jar order was specified in build.properties, we add all the libraries but the current one
190
// based on the order specified by the plugin.xml. Both library that we compile and .jar provided are processed
191
String JavaDoc[] libraries = getClasspathEntries(model);
192             if (libraries != null) {
193                 for (int i = 0; i < libraries.length; i++) {
194                     String JavaDoc libraryName = libraries[i];
195                     if (jar.getName(false).equals(libraryName))
196                         continue;
197
198                     boolean isSource = (modelProperties.getProperty(PROPERTY_SOURCE_PREFIX + libraryName) != null);
199                     if (isSource) {
200                         addDevEntries(model, location, classpath, Utils.getArrayFromString(modelProperties.getProperty(PROPERTY_OUTPUT_PREFIX + libraryName)));
201                     }
202                     //Potential pb: here there maybe a nasty case where the libraries variable may refer to something which is part of the base
203
//but $xx$ will replace it by the $xx instead of $basexx. The solution is for the user to use the explicitly set the content
204
// of its build.property file
205
addPathAndCheck(model.getSymbolicName(), Path.EMPTY, libraryName, modelProperties, classpath);
206                 }
207             }
208         } else {
209             // otherwise we add all the predecessor jars
210
String JavaDoc[] order = Utils.getArrayFromString(jarOrder);
211             for (int i = 0; i < order.length; i++) {
212                 if (order[i].equals(jar.getName(false)))
213                     break;
214                 addDevEntries(model, location, classpath, Utils.getArrayFromString((String JavaDoc) modelProperties.get(PROPERTY_OUTPUT_PREFIX + order[i])));
215                 addPathAndCheck(model.getSymbolicName(), Path.EMPTY, order[i], modelProperties, classpath);
216             }
217             // Then we add all the "pure libraries" (the one that does not contain source)
218
String JavaDoc[] libraries = getClasspathEntries(model);
219             for (int i = 0; i < libraries.length; i++) {
220                 String JavaDoc libraryName = libraries[i];
221                 if (modelProperties.get(PROPERTY_SOURCE_PREFIX + libraryName) == null) {
222                     //Potential pb: if the pure library is something that is being compiled (which is supposetly not the case, but who knows...)
223
//the user will get $basexx instead of $ws
224
addPathAndCheck(model.getSymbolicName(), Path.EMPTY, libraryName, modelProperties, classpath);
225                 }
226             }
227         }
228
229         // add extra classpath if it exists. this code is kept for backward compatibility
230
String JavaDoc extraClasspath = (String JavaDoc) modelProperties.get(PROPERTY_JAR_EXTRA_CLASSPATH);
231         if (extraClasspath != null) {
232             String JavaDoc[] extra = Utils.getArrayFromString(extraClasspath, ";,"); //$NON-NLS-1$
233

234             for (int i = 0; i < extra.length; i++) {
235                 //Potential pb: if the path refers to something that is being compiled (which is supposetly not the case, but who knows...)
236
//the user will get $basexx instead of $ws
237
addPathAndCheck(null, new Path(computeExtraPath(extra[i], location)), "", modelProperties, classpath); //$NON-NLS-1$
238
}
239         }
240
241         // add extra classpath if it is specified for the given jar
242
String JavaDoc[] jarSpecificExtraClasspath = jar.getExtraClasspath();
243         for (int i = 0; i < jarSpecificExtraClasspath.length; i++) {
244             //Potential pb: if the path refers to something that is being compiled (which is supposetly not the case, but who knows...)
245
//the user will get $basexx instead of $ws
246
addPathAndCheck(null, new Path(computeExtraPath(jarSpecificExtraClasspath[i], location)), "", modelProperties, classpath); //$NON-NLS-1$
247
}
248     }
249
250     /**
251      * Convenience method that compute the relative classpath of extra.classpath entries
252      * @param url a url
253      * @param location location used as a base location to compute the relative path
254      * @return String the relative path
255      * @throws CoreException
256      */

257     private String JavaDoc computeExtraPath(String JavaDoc url, String JavaDoc location) throws CoreException {
258         String JavaDoc relativePath = null;
259
260         String JavaDoc[] urlfragments = Utils.getArrayFromString(url, "/"); //$NON-NLS-1$
261

262         // A valid platform url for a plugin has a leat 3 segments.
263
if (urlfragments.length > 2 && urlfragments[0].equals(PlatformURLHandler.PROTOCOL + PlatformURLHandler.PROTOCOL_SEPARATOR)) {
264             String JavaDoc modelLocation = null;
265             if (urlfragments[1].equalsIgnoreCase(PlatformURLPluginConnection.PLUGIN))
266                 modelLocation = generator.getLocation(generator.getSite(false).getRegistry().getResolvedBundle(urlfragments[2]));
267
268             if (urlfragments[1].equalsIgnoreCase(PlatformURLFragmentConnection.FRAGMENT))
269                 modelLocation = generator.getLocation(generator.getSite(false).getRegistry().getResolvedBundle(urlfragments[2]));
270
271             if (urlfragments[1].equalsIgnoreCase("resource")) { //$NON-NLS-1$
272
String JavaDoc message = NLS.bind(Messages.exception_url, generator.getPropertiesFileName() + "::" + url); //$NON-NLS-1$
273
throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_MALFORMED_URL, message, null));
274             }
275             if (modelLocation != null) {
276                 for (int i = 3; i < urlfragments.length; i++) {
277                     if (i == 3)
278                         modelLocation += urlfragments[i];
279                     else
280                         modelLocation += '/' + urlfragments[i];
281                 }
282                 return relativePath = Utils.makeRelative(new Path(modelLocation), new Path(location)).toOSString();
283             }
284         }
285
286         // Then it's just a regular URL, or just something that will be added at the end of the classpath for backward compatibility.......
287
try {
288             URL JavaDoc extraURL = new URL JavaDoc(url);
289             try {
290                 relativePath = Utils.makeRelative(new Path(Platform.resolve(extraURL).getFile()), new Path(location)).toOSString();
291             } catch (IOException JavaDoc e) {
292                 String JavaDoc message = NLS.bind(Messages.exception_url, generator.getPropertiesFileName() + "::" + url); //$NON-NLS-1$
293
throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_MALFORMED_URL, message, e));
294             }
295         } catch (MalformedURLException JavaDoc e) {
296             String JavaDoc message = NLS.bind(Messages.exception_url, PROPERTIES_FILE + "::" + url); //$NON-NLS-1$
297
throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, IPDEBuildConstants.EXCEPTION_MALFORMED_URL, message, e));
298         }
299         return relativePath;
300     }
301
302     //Add the prerequisite of a given plugin (target)
303
private void addPrerequisites(BundleDescription target, List classpath, String JavaDoc baseLocation, List pluginChain, Set addedPlugins) throws CoreException {
304
305         if (pluginChain.contains(target)) {
306             if (target == getPlugin(PI_RUNTIME, null))
307                 return;
308             String JavaDoc cycleString = ""; //$NON-NLS-1$
309
for (Iterator iter = pluginChain.iterator(); iter.hasNext();)
310                 cycleString += iter.next().toString() + ", "; //$NON-NLS-1$
311
cycleString += target.toString();
312             String JavaDoc message = NLS.bind(Messages.error_pluginCycle, cycleString);
313             throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_CLASSPATH_CYCLE, message, null));
314         }
315
316         if (addedPlugins.contains(target)){
317             return;
318         }
319         
320         // The first prerequisite is ALWAYS runtime
321
if (target != getPlugin(PI_RUNTIME, null))
322             addPluginAndPrerequisites(getPlugin(PI_RUNTIME, null), classpath, baseLocation, pluginChain,addedPlugins);
323
324         // add libraries from pre-requisite plug-ins. Don't worry about the export flag
325
// as all required plugins may be required for compilation.
326
BundleDescription[] requires = PDEState.getDependentBundles(target);
327         if (requires != null) {
328             pluginChain.add(target);
329             for (int i = 0; i < requires.length; i++) {
330                 BundleDescription plugin = getPlugin(requires[i].getSymbolicName(), requires[i].getVersion().toString());
331                 if (plugin != null)
332                     addPluginAndPrerequisites(plugin, classpath, baseLocation, pluginChain,addedPlugins);
333             }
334             pluginChain.remove(target);
335             addedPlugins.add(target);
336         }
337         
338     }
339
340     /**
341      * The pluginChain parameter is used to keep track of possible cycles. If prerequisite is already
342      * present in the chain it is not included in the classpath.
343      *
344      * @param target : the plugin for which we are going to introduce
345      * @param classpath
346      * @param baseLocation
347      * @param pluginChain
348      * @param addedPlugins
349      * @throws CoreException
350      */

351     private void addPluginAndPrerequisites(BundleDescription target, List classpath, String JavaDoc baseLocation, List pluginChain, Set addedPlugins) throws CoreException {
352         addPlugin(target, classpath, baseLocation);
353         addPrerequisites(target, classpath, baseLocation, pluginChain,addedPlugins);
354     }
355
356     /**
357      *
358      * @param model
359      * @param baseLocation
360      * @param classpath
361      */

362     private void addDevEntries(BundleDescription model, String JavaDoc baseLocation, List classpath, String JavaDoc[] jarSpecificEntries) {
363         if (generator.devEntries == null && (jarSpecificEntries == null || jarSpecificEntries.length == 0))
364             return;
365
366         String JavaDoc[] entries;
367         // if jarSpecificEntries is given, then it overrides devEntries
368
if (jarSpecificEntries != null && jarSpecificEntries.length > 0)
369             entries = jarSpecificEntries;
370         else
371             entries = generator.devEntries.getDevClassPath(model.getSymbolicName());
372
373         IPath root = Utils.makeRelative(new Path(generator.getLocation(model)), new Path(baseLocation));
374         for (int i = 0; i < entries.length; i++) {
375             addPathAndCheck(model.getSymbolicName(), root, entries[i], null, classpath);
376         }
377     }
378
379     //Return the jar name from the classpath
380
private String JavaDoc[] getClasspathEntries(BundleDescription bundle) throws CoreException {
381         return generator.getClasspathEntries(bundle);
382     }
383 }
384
Popular Tags