KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > pde > internal > core > RequiredPluginsClasspathContainer


1 /*******************************************************************************
2  * Copyright (c) 2000, 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 Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.pde.internal.core;
12
13 import java.io.File JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.HashSet JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.Map JavaDoc;
19 import java.util.Stack JavaDoc;
20 import java.util.TreeMap JavaDoc;
21
22 import org.eclipse.core.resources.IFile;
23 import org.eclipse.core.resources.IProject;
24 import org.eclipse.core.resources.IResource;
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.IPath;
27 import org.eclipse.core.runtime.Path;
28 import org.eclipse.core.runtime.Platform;
29 import org.eclipse.jdt.core.IClasspathContainer;
30 import org.eclipse.jdt.core.IClasspathEntry;
31 import org.eclipse.jdt.core.JavaCore;
32 import org.eclipse.osgi.service.resolver.BaseDescription;
33 import org.eclipse.osgi.service.resolver.BundleDescription;
34 import org.eclipse.osgi.service.resolver.BundleSpecification;
35 import org.eclipse.osgi.service.resolver.ExportPackageDescription;
36 import org.eclipse.osgi.service.resolver.HostSpecification;
37 import org.eclipse.osgi.service.resolver.ImportPackageSpecification;
38 import org.eclipse.osgi.service.resolver.StateHelper;
39 import org.eclipse.pde.core.build.IBuild;
40 import org.eclipse.pde.core.build.IBuildEntry;
41 import org.eclipse.pde.core.plugin.IPluginModelBase;
42 import org.eclipse.pde.core.plugin.PluginRegistry;
43 import org.eclipse.pde.internal.build.IBuildPropertiesConstants;
44 import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase;
45
46 public class RequiredPluginsClasspathContainer extends PDEClasspathContainer implements IClasspathContainer {
47
48     private IPluginModelBase fModel;
49     private IBuild fBuild;
50     
51     private static boolean DEBUG = false;
52     
53     private IClasspathEntry[] fEntries = null;
54     
55     static {
56         DEBUG = PDECore.getDefault().isDebugging()
57                     && "true".equals(Platform.getDebugOption("org.eclipse.pde.core/classpath")); //$NON-NLS-1$ //$NON-NLS-2$
58
}
59     
60     /**
61      * Constructor for RequiredPluginsClasspathContainer.
62      */

63     public RequiredPluginsClasspathContainer(IPluginModelBase model) {
64         this(model, null);
65     }
66     
67     public RequiredPluginsClasspathContainer(IPluginModelBase model, IBuild build) {
68         fModel = model;
69         fBuild = build;
70     }
71
72     /*
73      * (non-Javadoc)
74      * @see org.eclipse.jdt.core.IClasspathContainer#getKind()
75      */

76     public int getKind() {
77         return K_APPLICATION;
78     }
79
80     /*
81      * (non-Javadoc)
82      * @see org.eclipse.jdt.core.IClasspathContainer#getPath()
83      */

84     public IPath getPath() {
85         return PDECore.REQUIRED_PLUGINS_CONTAINER_PATH;
86     }
87     
88     /*
89      * (non-Javadoc)
90      * @see org.eclipse.jdt.core.IClasspathContainer#getDescription()
91      */

92     public String JavaDoc getDescription() {
93         return PDECoreMessages.RequiredPluginsClasspathContainer_description;
94     }
95     
96     /*
97      * (non-Javadoc)
98      * @see org.eclipse.jdt.core.IClasspathContainer#getClasspathEntries()
99      */

100     public IClasspathEntry[] getClasspathEntries() {
101         if (fModel == null) {
102             if (DEBUG) {
103                 System.out.println("********Returned an empty container"); //$NON-NLS-1$
104
System.out.println();
105             }
106             return new IClasspathEntry[0];
107         }
108         if (fEntries == null) {
109             fEntries = computePluginEntries();
110         }
111         if (DEBUG) {
112             System.out.println("Dependencies for plugin '" + fModel.getPluginBase().getId() + "':"); //$NON-NLS-1$ //$NON-NLS-2$
113
for (int i = 0; i < fEntries.length; i++) {
114                 System.out.println(fEntries[i]);
115             }
116             System.out.println();
117         }
118         return fEntries;
119     }
120
121     private IClasspathEntry[] computePluginEntries() {
122         ArrayList JavaDoc entries = new ArrayList JavaDoc();
123         try {
124             BundleDescription desc = fModel.getBundleDescription();
125             if (desc == null)
126                 return new IClasspathEntry[0];
127             
128             Map JavaDoc map = retrieveVisiblePackagesFromState(desc);
129             
130             HashSet JavaDoc added = new HashSet JavaDoc();
131             
132             // to avoid cycles, e.g. when a bundle imports a package it exports
133
added.add(desc);
134             
135             HostSpecification host = desc.getHost();
136             if (host != null) {
137                 addHostPlugin(host, added, map, entries);
138             } else if ("true".equals(System.getProperty("pde.allowCycles"))) { //$NON-NLS-1$ //$NON-NLS-2$
139
BundleDescription[] fragments = desc.getFragments();
140                 for (int i = 0; i < fragments.length; i++) {
141                     if (fragments[i].isResolved()) {
142                         addPlugin(fragments[i], false, map, entries);
143                     }
144                 }
145             }
146
147             // add dependencies
148
BundleSpecification[] required = desc.getRequiredBundles();
149             for (int i = 0; i < required.length; i++) {
150                 addDependency((BundleDescription)required[i].getSupplier(), added, map, entries);
151             }
152             
153             if (fBuild == null)
154                 fBuild = ClasspathUtilCore.getBuild(fModel);
155             if (fBuild != null)
156                 addSecondaryDependencies(desc, added, entries);
157             
158             // add Import-Package
159
// sort by symbolicName_version to get a consistent order
160
Map JavaDoc sortedMap = new TreeMap JavaDoc();
161             Iterator JavaDoc iter = map.keySet().iterator();
162             while (iter.hasNext()) {
163                 BundleDescription bundle = (BundleDescription)iter.next();
164                 sortedMap.put(bundle.toString(), bundle);
165             }
166             
167             iter = sortedMap.values().iterator();
168             while (iter.hasNext()) {
169                 BundleDescription bundle = (BundleDescription)iter.next();
170                 IPluginModelBase model = PluginRegistry.findModel(bundle);
171                 if (model != null && model.isEnabled())
172                     addDependencyViaImportPackage(model.getBundleDescription(), added, map, entries);
173             }
174
175             if (fBuild != null)
176                 addExtraClasspathEntries(added, entries);
177
178         } catch (CoreException e) {
179         }
180         return (IClasspathEntry[])entries.toArray(new IClasspathEntry[entries.size()]);
181     }
182     
183     private Map JavaDoc retrieveVisiblePackagesFromState(BundleDescription desc) {
184         Map JavaDoc visiblePackages = new HashMap JavaDoc();
185         StateHelper helper = Platform.getPlatformAdmin().getStateHelper();
186         addVisiblePackagesFromState(helper, desc, visiblePackages);
187         if (desc.getHost() != null)
188             addVisiblePackagesFromState(helper, (BundleDescription)desc.getHost().getSupplier(), visiblePackages);
189         return visiblePackages;
190     }
191
192     private void addVisiblePackagesFromState(StateHelper helper, BundleDescription desc, Map JavaDoc visiblePackages) {
193         if (desc == null)
194             return;
195         ExportPackageDescription[] exports = helper.getVisiblePackages(desc);
196         for (int i = 0; i < exports.length; i++) {
197             BundleDescription exporter = exports[i].getExporter();
198             if (exporter == null)
199                 continue;
200             ArrayList JavaDoc list = (ArrayList JavaDoc)visiblePackages.get(exporter);
201             if (list == null)
202                 list = new ArrayList JavaDoc();
203             Rule rule = getRule(helper, desc, exports[i]);
204             if (!list.contains(rule))
205                 list.add(rule);
206             visiblePackages.put(exporter, list);
207         }
208     }
209     
210     private Rule getRule(StateHelper helper, BundleDescription desc, ExportPackageDescription export) {
211         Rule rule = new Rule();
212         rule.discouraged = helper.getAccessCode(desc, export) == StateHelper.ACCESS_DISCOURAGED;
213         String JavaDoc name = export.getName();
214         rule.path = (name.equals(".")) ? new Path("*") : new Path(name.replaceAll("\\.", "/") + "/*"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
215
return rule;
216     }
217     
218     protected void addDependencyViaImportPackage(BundleDescription desc, HashSet JavaDoc added, Map JavaDoc map, ArrayList JavaDoc entries) throws CoreException {
219         if (desc == null || !added.add(desc))
220             return;
221
222         addPlugin(desc, true, map, entries);
223
224         if (hasExtensibleAPI(desc) && desc.getContainingState() != null) {
225             BundleDescription[] fragments = desc.getFragments();
226             for (int i = 0; i < fragments.length; i++) {
227                 if (fragments[i].isResolved())
228                     addDependencyViaImportPackage(fragments[i], added, map, entries);
229             }
230         }
231     }
232
233     private void addDependency(BundleDescription desc, HashSet JavaDoc added, Map JavaDoc map, ArrayList JavaDoc entries) throws CoreException {
234         addDependency(desc, added, map, entries, true);
235     }
236     
237     private void addDependency(BundleDescription desc, HashSet JavaDoc added, Map JavaDoc map, ArrayList JavaDoc entries, boolean useInclusion) throws CoreException {
238         if (desc == null || !added.add(desc))
239             return;
240
241         BundleDescription[] fragments = hasExtensibleAPI(desc) ? desc.getFragments() : new BundleDescription[0];
242
243         // add fragment patches before host
244
for (int i = 0; i < fragments.length; i++) {
245             if (fragments[i].isResolved() && ClasspathUtilCore.isPatchFragment(fragments[i])) {
246                 addDependency(fragments[i], added, map, entries, useInclusion);
247             }
248         }
249         
250         addPlugin(desc, useInclusion, map, entries);
251         
252         // add fragments that are not patches after the host
253
for (int i = 0; i < fragments.length; i++) {
254             if (fragments[i].isResolved() && !ClasspathUtilCore.isPatchFragment(fragments[i])) {
255                 addDependency(fragments[i], added, map, entries, useInclusion);
256             }
257         }
258
259         BundleSpecification[] required = desc.getRequiredBundles();
260         for (int i = 0; i < required.length; i++) {
261             if (required[i].isExported()) {
262                 addDependency((BundleDescription)required[i].getSupplier(), added, map, entries, useInclusion);
263             }
264         }
265     }
266     
267     private boolean addPlugin(BundleDescription desc, boolean useInclusions, Map JavaDoc map, ArrayList JavaDoc entries)
268             throws CoreException {
269         IPluginModelBase model = PluginRegistry.findModel(desc);
270         if (model == null || !model.isEnabled())
271             return false;
272         IResource resource = model.getUnderlyingResource();
273         Rule[] rules = useInclusions ? getInclusions(map, model) : null;
274         if (resource != null) {
275             addProjectEntry(resource.getProject(), rules, entries);
276         } else {
277             addExternalPlugin(model, rules, entries);
278         }
279         return true;
280     }
281     
282     private Rule[] getInclusions(Map JavaDoc map, IPluginModelBase model) {
283         BundleDescription desc = model.getBundleDescription();
284         if (desc == null
285                 || "false".equals(System.getProperty("pde.restriction")) //$NON-NLS-1$ //$NON-NLS-2$
286
|| !(fModel instanceof IBundlePluginModelBase)
287                 || TargetPlatformHelper.getTargetVersion() < 3.1)
288             return null;
289         
290         Rule[] rules;
291
292         if (desc.getHost() != null)
293             rules = getInclusions(map, (BundleDescription)desc.getHost().getSupplier());
294         else
295             rules = getInclusions(map, desc);
296         
297         return (rules.length == 0 && !ClasspathUtilCore.hasBundleStructure(model)) ? null : rules;
298     }
299     
300     private Rule[] getInclusions(Map JavaDoc map, BundleDescription desc) {
301         ArrayList JavaDoc list = (ArrayList JavaDoc)map.get(desc);
302         return list != null ? (Rule[])list.toArray(new Rule[list.size()]) : new Rule[0];
303     }
304
305     private void addHostPlugin(HostSpecification hostSpec, HashSet JavaDoc added, Map JavaDoc map, ArrayList JavaDoc entries) throws CoreException {
306         BaseDescription desc = hostSpec.getSupplier();
307         
308         if (desc instanceof BundleDescription) {
309             BundleDescription host = (BundleDescription)desc;
310             
311             // add host plug-in
312
if (added.add(host) && addPlugin(host, false, map, entries)) {
313                 BundleSpecification[] required = host.getRequiredBundles();
314                 for (int i = 0; i < required.length; i++) {
315                     addDependency((BundleDescription)required[i].getSupplier(), added, map, entries);
316                 }
317                 
318                 // add Import-Package
319
ImportPackageSpecification[] imports = host.getImportPackages();
320                 for (int i = 0; i < imports.length; i++) {
321                     BaseDescription supplier = imports[i].getSupplier();
322                     if (supplier instanceof ExportPackageDescription) {
323                         addDependencyViaImportPackage(((ExportPackageDescription)supplier).getExporter(), added, map, entries);
324                     }
325                 }
326             }
327         }
328     }
329     
330     private boolean hasExtensibleAPI(BundleDescription desc) {
331         IPluginModelBase model = PluginRegistry.findModel(desc);
332         return model != null ? ClasspathUtilCore.hasExtensibleAPI(model) : false;
333     }
334     
335     protected void addExtraClasspathEntries(HashSet JavaDoc added, ArrayList JavaDoc entries) throws CoreException {
336         IBuildEntry[] buildEntries = fBuild.getBuildEntries();
337         for (int i = 0; i < buildEntries.length; i++) {
338             String JavaDoc name = buildEntries[i].getName();
339             if (name.equals(IBuildPropertiesConstants.PROPERTY_JAR_EXTRA_CLASSPATH)
340                     || name.startsWith(IBuildPropertiesConstants.PROPERTY_EXTRAPATH_PREFIX)) {
341                 addExtraClasspathEntries(added, entries, buildEntries[i].getTokens());
342             }
343         }
344     }
345     
346     protected void addExtraClasspathEntries(HashSet JavaDoc added, ArrayList JavaDoc entries, String JavaDoc[] tokens) throws CoreException {
347         for (int i = 0; i < tokens.length; i++) {
348             IPath path = Path.fromPortableString(tokens[i]);
349             if (!path.isAbsolute()) {
350                 File JavaDoc file = new File JavaDoc(fModel.getInstallLocation(), path.toString());
351                 if (file.exists()) {
352                     IFile resource = PDECore.getWorkspace().getRoot().getFileForLocation(new Path(file.getAbsolutePath()));
353                     if (resource != null && resource.getProject().equals(fModel.getUnderlyingResource().getProject())) {
354                         addExtraLibrary(resource.getFullPath(), null, entries);
355                         continue;
356                     }
357                 }
358                 if (path.segmentCount() >= 3 && "..".equals(path.segment(0))) { //$NON-NLS-1$
359
path = path.removeFirstSegments(1);
360                     path = Path.fromPortableString("platform:/plugin/").append(path); //$NON-NLS-1$
361
} else {
362                     continue;
363                 }
364             }
365             
366             if (!path.toPortableString().startsWith("platform:")) { //$NON-NLS-1$
367
addExtraLibrary(path, null, entries);
368             } else {
369                 int count = path.getDevice() == null ? 4 : 3;
370                 if (path.segmentCount() >= count) {
371                     String JavaDoc pluginID = path.segment(count-2);
372                     if (added.contains(pluginID))
373                         continue;
374                     IPluginModelBase model = PluginRegistry.findModel(pluginID);
375                     if (model != null && model.isEnabled()) {
376                         path = path.setDevice(null);
377                         path = path.removeFirstSegments(count-1);
378                         if (model.getUnderlyingResource() == null) {
379                             File JavaDoc file = new File JavaDoc(model.getInstallLocation(), path.toOSString());
380                             if (file.exists()) {
381                                 addExtraLibrary(new Path(file.getAbsolutePath()), model, entries);
382                             }
383                         } else {
384                             IProject project = model.getUnderlyingResource().getProject();
385                             IFile file = project.getFile(path);
386                             if (file.exists()) {
387                                 addExtraLibrary(file.getFullPath(), model, entries);
388                             }
389                         }
390                     }
391                 }
392             }
393         }
394     }
395     
396     private void addSecondaryDependencies(BundleDescription desc, HashSet JavaDoc added, ArrayList JavaDoc entries) {
397         try {
398           IBuildEntry entry = fBuild.getEntry(IBuildEntry.SECONDARY_DEPENDENCIES);
399           if (entry != null) {
400               String JavaDoc[] tokens = entry.getTokens();
401               for (int i = 0; i < tokens.length; i++) {
402                   String JavaDoc pluginId = tokens[i];
403                   if (added.contains(pluginId))
404                       continue;
405                   // Get PluginModelBase first to resolve system.bundle entry if it exists
406
IPluginModelBase model = PluginRegistry.findModel(pluginId);
407                   if (model != null) {
408                       Map JavaDoc rules = new HashMap JavaDoc();
409                       findExportedPackages(model.getBundleDescription(), desc, rules);
410                       if (model != null) {
411                           addDependency(model.getBundleDescription(), added, rules, entries, true);
412                       }
413                   }
414               }
415           }
416         } catch (CoreException e) {
417             return;
418         }
419     }
420
421     protected final void findExportedPackages(BundleDescription desc, BundleDescription projectDesc, Map JavaDoc map) {
422         if (desc != null) {
423             Stack JavaDoc stack = new Stack JavaDoc();
424             stack.add(desc);
425             while (!stack.isEmpty()) {
426                 BundleDescription bdesc = (BundleDescription) stack.pop();
427                 ExportPackageDescription[] expkgs = bdesc.getExportPackages();
428                 ArrayList JavaDoc rules = new ArrayList JavaDoc();
429                 for (int i = 0; i < expkgs.length; i++) {
430                     Rule rule = new Rule();
431                     rule.discouraged = restrictPackage(projectDesc, expkgs[i]);
432                     rule.path = new Path(expkgs[i].getName().replaceAll("\\.", "/") + "/*"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
433
rules.add(rule);
434                 }
435                 map.put(bdesc, rules);
436             
437                 // Look at re-exported Require-Bundles for any other exported packages
438
BundleSpecification[] requiredBundles = bdesc.getRequiredBundles();
439                 for (int i = 0; i < requiredBundles.length; i++)
440                     if (requiredBundles[i].isExported()) {
441                         BaseDescription bd = requiredBundles[i].getSupplier();
442                         if (bd != null && bd instanceof BundleDescription)
443                             stack.add(bd);
444                     }
445             }
446         }
447     }
448     
449     private boolean restrictPackage(BundleDescription desc, ExportPackageDescription pkg ) {
450         String JavaDoc[] friends = (String JavaDoc[])pkg.getDirective(ICoreConstants.FRIENDS_DIRECTIVE);
451         if (friends != null) {
452             String JavaDoc symbolicName = desc.getSymbolicName();
453             for (int i = 0; i < friends.length; i++) {
454                 if (symbolicName.equals(friends[i]))
455                     return false;
456                 
457             }
458             return true;
459         }
460         return (((Boolean JavaDoc)pkg.getDirective(ICoreConstants.INTERNAL_DIRECTIVE)).booleanValue());
461     }
462     
463     private void addExtraLibrary(IPath path, IPluginModelBase model, ArrayList JavaDoc entries) throws CoreException {
464         IPath srcPath = null;
465         if (model != null) {
466             IPath shortPath = path.removeFirstSegments(path.matchingFirstSegments(new Path(model.getInstallLocation())));
467             srcPath = ClasspathUtilCore.getSourceAnnotation(model, shortPath.toString());
468         } else {
469             String JavaDoc filename = ClasspathUtilCore.getSourceZipName(path.lastSegment());
470             IPath candidate = path.removeLastSegments(1).append(filename);
471             if (PDECore.getWorkspace().getRoot().getFile(candidate).exists())
472                 srcPath = candidate;
473         }
474         IClasspathEntry clsEntry = JavaCore.newLibraryEntry(
475                 path,
476                 srcPath,
477                 null);
478         if (!entries.contains(clsEntry))
479             entries.add(clsEntry);
480     }
481 }
482
Popular Tags