EMMA Coverage Report (generated Thu Nov 26 15:54:18 CST 2009)
[all classes][org.eclipse.pde.api.tools.internal.model]

COVERAGE SUMMARY FOR SOURCE FILE [ApiBaseline.java]

nameclass, %method, %block, %line, %
ApiBaseline.java100% (1/1)74%  (32/43)74%  (1080/1462)76%  (282.7/374)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ApiBaseline100% (1/1)74%  (32/43)74%  (1080/1462)76%  (282.7/374)
defaultVMInstallChanged (IVMInstall, IVMInstall): void 0%   (0/1)0%   (0/1)0%   (0/1)
getErrors (): ResolverError [] 0%   (0/1)0%   (0/52)0%   (0/11)
getExecutionEnvironmentStatus (): IStatus 0%   (0/1)0%   (0/3)0%   (0/1)
getVisibleDependentComponents (IApiComponent []): IApiComponent [] 0%   (0/1)0%   (0/68)0%   (0/10)
hashCode (): int 0%   (0/1)0%   (0/4)0%   (0/1)
rebindVM (): void 0%   (0/1)0%   (0/30)0%   (0/7)
setName (String): void 0%   (0/1)0%   (0/4)0%   (0/2)
toString (): String 0%   (0/1)0%   (0/3)0%   (0/1)
vmAdded (IVMInstall): void 0%   (0/1)0%   (0/10)0%   (0/5)
vmChanged (PropertyChangeEvent): void 0%   (0/1)0%   (0/22)0%   (0/8)
vmRemoved (IVMInstall): void 0%   (0/1)0%   (0/12)0%   (0/5)
clearPackage (String): void 100% (1/1)44%  (4/9)67%  (2/3)
getJavaProfileProperties (String): Properties 100% (1/1)58%  (53/91)60%  (13.8/23)
initialize (ExecutionEnvironmentDescription): void 100% (1/1)67%  (22/33)89%  (8/9)
resolveSystemLibrary (HashSet): void 100% (1/1)68%  (192/283)72%  (50/69)
loadBaselineInfos (): void 100% (1/1)75%  (9/12)67%  (4/6)
initialize (Properties, ExecutionEnvironmentDescription): void 100% (1/1)82%  (91/111)84%  (21.9/26)
getApiComponent (IProject): IApiComponent 100% (1/1)86%  (12/14)75%  (3/4)
addComponent (IApiComponent): void 100% (1/1)98%  (41/42)91%  (10/11)
resolvePackage (IApiComponent, String): IApiComponent [] 100% (1/1)98%  (100/102)96%  (26/27)
<static initializer> 100% (1/1)100% (4/4)100% (2/2)
ApiBaseline (String): void 100% (1/1)100% (44/44)100% (12/12)
ApiBaseline (String, File): void 100% (1/1)100% (6/6)100% (2/2)
ApiBaseline (String, File, String): void 100% (1/1)100% (39/39)100% (10/10)
addApiComponents (IApiComponent []): void 100% (1/1)100% (46/46)100% (12/12)
clearCachedElements (): void 100% (1/1)100% (5/5)100% (2/2)
clearComponentsCache (): void 100% (1/1)100% (10/10)100% (4/4)
close (): void 100% (1/1)100% (18/18)100% (5/5)
dispose (): void 100% (1/1)100% (64/64)100% (22/22)
equals (Object): boolean 100% (1/1)100% (16/16)100% (4/4)
getApiComponent (String): IApiComponent 100% (1/1)100% (13/13)100% (4/4)
getApiComponents (): IApiComponent [] 100% (1/1)100% (18/18)100% (5/5)
getApiComponents (BundleDescription []): IApiComponent [] 100% (1/1)100% (36/36)100% (7/7)
getBundleDescriptions (IApiComponent []): ArrayList 100% (1/1)100% (29/29)100% (6/6)
getDependentComponents (IApiComponent []): IApiComponent [] 100% (1/1)100% (19/19)100% (3/3)
getExecutionEnvironment (): String 100% (1/1)100% (3/3)100% (1/1)
getLocation (): String 100% (1/1)100% (3/3)100% (1/1)
getPrerequisiteComponents (IApiComponent []): IApiComponent [] 100% (1/1)100% (19/19)100% (3/3)
getState (): State 100% (1/1)100% (11/11)100% (3/3)
isSystemPackage (String): boolean 100% (1/1)100% (41/41)100% (8/8)
peekInfos (): boolean 100% (1/1)100% (7/7)100% (1/1)
resolvePackage0 (IApiComponent, String, List): void 100% (1/1)100% (101/101)100% (25/25)
setLocation (String): void 100% (1/1)100% (4/4)100% (2/2)

1/*******************************************************************************
2 * Copyright (c) 2007, 2009 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 *******************************************************************************/
11package org.eclipse.pde.api.tools.internal.model;
12 
13import java.io.File;
14import java.io.IOException;
15import java.io.InputStream;
16import java.net.URL;
17import java.net.URLConnection;
18import java.util.ArrayList;
19import java.util.Arrays;
20import java.util.Collection;
21import java.util.Dictionary;
22import java.util.HashMap;
23import java.util.HashSet;
24import java.util.Hashtable;
25import java.util.Iterator;
26import java.util.List;
27import java.util.Map;
28import java.util.Properties;
29import java.util.Set;
30import java.util.Map.Entry;
31 
32import org.eclipse.core.resources.IProject;
33import org.eclipse.core.runtime.CoreException;
34import org.eclipse.core.runtime.FileLocator;
35import org.eclipse.core.runtime.IStatus;
36import org.eclipse.core.runtime.MultiStatus;
37import org.eclipse.core.runtime.Platform;
38import org.eclipse.core.runtime.Status;
39import org.eclipse.jdt.core.JavaCore;
40import org.eclipse.jdt.launching.IVMInstall;
41import org.eclipse.jdt.launching.IVMInstall2;
42import org.eclipse.jdt.launching.IVMInstallChangedListener;
43import org.eclipse.jdt.launching.JavaRuntime;
44import org.eclipse.jdt.launching.PropertyChangeEvent;
45import org.eclipse.jdt.launching.VMStandin;
46import org.eclipse.jdt.launching.environments.ExecutionEnvironmentDescription;
47import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
48import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
49import org.eclipse.osgi.service.resolver.BundleDescription;
50import org.eclipse.osgi.service.resolver.ExportPackageDescription;
51import org.eclipse.osgi.service.resolver.HostSpecification;
52import org.eclipse.osgi.service.resolver.ResolverError;
53import org.eclipse.osgi.service.resolver.State;
54import org.eclipse.osgi.service.resolver.StateHelper;
55import org.eclipse.osgi.service.resolver.StateObjectFactory;
56import org.eclipse.pde.api.tools.internal.AnyValue;
57import org.eclipse.pde.api.tools.internal.ApiBaselineManager;
58import org.eclipse.pde.api.tools.internal.CoreMessages;
59import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
60import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline;
61import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
62import org.eclipse.pde.api.tools.internal.provisional.model.IApiElement;
63import org.eclipse.pde.api.tools.internal.util.Util;
64import org.osgi.framework.Bundle;
65import org.osgi.framework.Constants;
66 
67import com.ibm.icu.text.MessageFormat;
68 
69/**
70 * Implementation of an {@link IApiBaseline}
71 * 
72 * @since 1.0
73 */
74public class ApiBaseline extends ApiElement implements IApiBaseline, IVMInstallChangedListener {
75        
76        /**
77         * Empty array of component
78         */
79        private static final IApiComponent[] EMPTY_COMPONENTS = new IApiComponent[0];
80        
81        /**
82         * OSGi bundle state
83         */
84        private State fState;
85        
86        /**
87         * Execution environment identifier
88         */
89        private String fExecutionEnvironment;
90        
91        /**
92         * Component representing the system library
93         */
94        private IApiComponent fSystemLibraryComponent;
95        
96        /**
97         * Whether an execution environment should be automatically resolved 
98         * as API components are added.
99         */
100        private boolean fAutoResolve = false;
101        
102        /**
103         * Contains the location of the baseline if the baseline was created with a location.
104         */
105        private String fLocation;
106        /**
107         * Execution environment status
108         */
109        private IStatus fEEStatus = null;
110 
111        /**
112         * Constant to match any value for ws, os, arch.
113         */
114        private AnyValue ANY_VALUE = new AnyValue("*"); //$NON-NLS-1$
115        
116        /**
117         * Cache of resolved packages. 
118         * <p>Map of <code>PackageName -> Map(componentName -> IApiComponent[])</code></p>
119         * For each package the cache contains a map of API components that provide that package,
120         * by source component name (including the <code>null</code> component name).
121         */
122        private HashMap fComponentsProvidingPackageCache = null;
123        
124        /**
125         * Maps component id's to components.
126         * <p>Map of <code>componentId -> {@link IApiComponent}</code></p>
127         */
128        private HashMap fComponentsById = null;
129        /**
130         * Maps project name's to components.
131         * <p>Map of <code>project name -> {@link IApiComponent}</code></p>
132         */
133        private HashMap fComponentsByProjectNames = null;
134        /**
135         * Cache of system package names
136         */
137        private HashSet fSystemPackageNames = null;
138        
139        /**
140         * The VM install this baseline is bound to for system libraries or <code>null</code>.
141         * Only used in the IDE when OSGi is running.
142         */
143        private IVMInstall fVMBinding = null;
144 
145        /**
146         * Constructs a new API baseline with the given name.
147         * 
148         * @param name baseline name
149         */
150        public ApiBaseline(String name) {
151                super(null, IApiElement.BASELINE, name);
152                fAutoResolve = true;
153                fEEStatus = new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, CoreMessages.ApiBaseline_0);
154        }
155 
156        /**
157         * Constructs a new API baseline with the given attributes.
158         * 
159         * @param name baseline name
160         * @param eeDescriptoin execution environment description file
161         * @throws CoreException if unable to create a baseline with the given attributes
162         */
163        public ApiBaseline(String name, File eeDescription) throws CoreException {
164                this(name, eeDescription, null);
165        }
166 
167        /**
168         * Constructs a new API baseline with the given attributes.
169         * 
170         * @param name baseline name
171         * @param eeDescriptoin execution environment description file
172         * @param location the given baseline location
173         * @throws CoreException if unable to create a baseline with the given attributes
174         */
175        public ApiBaseline(String name, File eeDescription, String location) throws CoreException {
176                this(name);
177                if (eeDescription != null) {
178                        fAutoResolve = false;
179                        ExecutionEnvironmentDescription ee = new ExecutionEnvironmentDescription(eeDescription);
180                        String profile = ee.getProperty(ExecutionEnvironmentDescription.CLASS_LIB_LEVEL);
181                        initialize(ee);
182                        fEEStatus = new Status(IStatus.OK, ApiPlugin.PLUGIN_ID,
183                                        MessageFormat.format(CoreMessages.ApiBaseline_1, new String[]{profile}));
184                }
185                this.fLocation = location;
186        }
187 
188        /**
189         * Initializes this baseline to resolve in the execution environment
190         * associated with the given description.
191         * 
192         * @param ee execution environment description
193         * @throws CoreException if unable to initialize based on the given id
194         */
195        private void initialize(ExecutionEnvironmentDescription ee) throws CoreException {
196                Properties properties = null;
197                String environmentId = ee.getProperty(ExecutionEnvironmentDescription.CLASS_LIB_LEVEL);
198                if (ApiPlugin.isRunningInFramework()) {
199                        properties = getJavaProfileProperties(environmentId);
200                } else {
201                        properties = Util.getEEProfile(environmentId);
202                }
203                if (properties == null) {
204                        abort("Unknown execution environment: " + environmentId, null); //$NON-NLS-1$
205                } else {
206                        initialize(properties, ee);
207                }
208        }
209 
210        /**
211         * Returns the property file for the given environment or <code>null</code>.
212         * 
213         * @param ee execution environment symbolic name
214         * @return properties file or <code>null</code> if none
215         */
216        public static Properties getJavaProfileProperties(String ee) throws CoreException {
217                Bundle osgiBundle = Platform.getBundle("org.eclipse.osgi"); //$NON-NLS-1$
218                if (osgiBundle == null) 
219                        return null;
220                URL profileURL = osgiBundle.getEntry(ee.replace('/', '_') + ".profile"); //$NON-NLS-1$
221                if (profileURL != null) {
222                        InputStream is = null;
223                        try {
224                                profileURL = FileLocator.resolve(profileURL);
225                                URLConnection openConnection = profileURL.openConnection();
226                                openConnection.setUseCaches(false);
227                                is = openConnection.getInputStream();
228                                if (is != null) {
229                                        Properties profile = new Properties();
230                                        profile.load(is);
231                                        return profile;
232                                }
233                        } catch (IOException e) {
234                                ApiPlugin.log(e);
235                        } finally {
236                                try {
237                                        if (is != null) {
238                                                is.close();
239                                        }
240                                } catch (IOException e) {
241                                        ApiPlugin.log(e);
242                                }
243                        }
244                }
245                return null;
246        }                
247        
248        /**
249         * Initializes this baseline from the given properties.
250         * 
251         * @param profile OGSi profile properties
252         * @param description execution environment description
253         * @throws CoreException if unable to initialize
254         */
255        private void initialize(Properties profile, ExecutionEnvironmentDescription description) throws CoreException {
256                String value = profile.getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES);
257                Dictionary dictionary = new Hashtable();
258                String[] systemPackages = null;
259                if (value != null) {
260                        systemPackages = value.split(","); //$NON-NLS-1$
261                        dictionary.put(Constants.FRAMEWORK_SYSTEMPACKAGES, value);
262                }
263                value = profile.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
264                if (value != null) {
265                        dictionary.put(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, value);
266                }
267                fExecutionEnvironment = profile.getProperty("osgi.java.profile.name"); //$NON-NLS-1$
268                if (fExecutionEnvironment == null) {
269                        abort("Profile file missing 'osgi.java.profile.name'" , null); //$NON-NLS-1$
270                }
271                dictionary.put("osgi.os", ANY_VALUE); //$NON-NLS-1$
272                dictionary.put("osgi.arch", ANY_VALUE); //$NON-NLS-1$
273                dictionary.put("osgi.ws", ANY_VALUE); //$NON-NLS-1$
274                dictionary.put("osgi.nl", ANY_VALUE); //$NON-NLS-1$
275                getState().setPlatformProperties(dictionary);
276                // clean up previous system library
277                if (fSystemLibraryComponent != null && fComponentsById != null) {
278                        fComponentsById.remove(fSystemLibraryComponent.getId());
279                }
280                if(fSystemPackageNames != null) {
281                        fSystemPackageNames.clear();
282                        fSystemPackageNames = null;
283                }
284                clearComponentsCache();
285                // set new system library
286                fSystemLibraryComponent = new SystemLibraryApiComponent(this, description, systemPackages);
287                addComponent(fSystemLibraryComponent);
288        }
289 
290        /**
291         * Clears the package -> components cache and sets it to <code>null</code>
292         */
293        private synchronized void clearComponentsCache() {
294                if(fComponentsProvidingPackageCache != null) {
295                        fComponentsProvidingPackageCache.clear();
296                        fComponentsProvidingPackageCache = null;
297                }
298        }
299        
300        /**
301         * Adds an {@link IApiComponent} to the fComponentsById mapping
302         * @param component
303         */
304        private void addComponent(IApiComponent component) throws CoreException {
305                if(component == null) {
306                        return;
307                }
308                if(fComponentsById == null) {
309                        fComponentsById = new HashMap();
310                }
311                fComponentsById.put(component.getId(), component);
312                if (component instanceof PluginProjectApiComponent) {
313                        PluginProjectApiComponent projectApiComponent = (PluginProjectApiComponent) component;
314                        if (this.fComponentsByProjectNames == null) {
315                                this.fComponentsByProjectNames = new HashMap();
316                        }
317                        this.fComponentsByProjectNames.put(projectApiComponent.getJavaProject().getProject().getName(), component);
318                }
319        }
320        
321        /* (non-Javadoc)
322         * @see IApiBaseline#addApiComponents(org.eclipse.pde.api.tools.model.component.IApiComponent[], boolean)
323         */
324        public void addApiComponents(IApiComponent[] components) throws CoreException {
325                HashSet ees = new HashSet();
326                for (int i = 0; i < components.length; i++) {
327                        BundleApiComponent component = (BundleApiComponent) components[i];
328                        if (component.isSourceComponent()) {
329                                continue;
330                        }
331                        BundleDescription description = component.getBundleDescription();
332                        getState().addBundle(description);
333                        addComponent(component);
334                        ees.addAll(Arrays.asList(component.getExecutionEnvironments()));
335                }
336                resolveSystemLibrary(ees);
337                getState().resolve();
338        }
339 
340        /**
341         * Resolves and initializes the system library to use based on API component requirements.
342         * Only works when running in the framework. Has no effect if not running in the framework.
343         */
344        private void resolveSystemLibrary(HashSet ees) {
345                if (ApiPlugin.isRunningInFramework() && fAutoResolve) {
346                        IStatus error = null;
347                        IExecutionEnvironmentsManager manager = JavaRuntime.getExecutionEnvironmentsManager();
348                        Iterator iterator = ees.iterator();
349                        Map VMsToEEs = new HashMap();
350                        while (iterator.hasNext()) {
351                                String ee = (String) iterator.next();
352                                IExecutionEnvironment environment = manager.getEnvironment(ee);
353                                if (environment != null) {
354                                        IVMInstall[] compatibleVMs = environment.getCompatibleVMs();
355                                        for (int i = 0; i < compatibleVMs.length; i++) {
356                                                IVMInstall vm = compatibleVMs[i];
357                                                Set EEs = (Set) VMsToEEs.get(vm);
358                                                if (EEs == null) {
359                                                        EEs = new HashSet();
360                                                        VMsToEEs.put(vm, EEs);
361                                                }
362                                                EEs.add(ee);
363                                        }
364                                }
365                        }
366                        // select VM that is compatible with most required environments
367                        iterator = VMsToEEs.entrySet().iterator();
368                        IVMInstall bestFit = null;
369                        int bestCount = 0;
370                        while (iterator.hasNext()) {
371                                Entry entry = (Entry) iterator.next();
372                                Set EEs = (Set)entry.getValue();
373                                if (EEs.size() > bestCount) {
374                                        bestCount = EEs.size();
375                                        bestFit = (IVMInstall)entry.getKey();
376                                }
377                        }
378                        String systemEE = null;
379                        if (bestFit != null) {
380                                // find the EE this VM is strictly compatible with
381                                IExecutionEnvironment[] environments = manager.getExecutionEnvironments();
382                                for (int i = 0; i < environments.length; i++) {
383                                        IExecutionEnvironment environment = environments[i];
384                                        if (environment.isStrictlyCompatible(bestFit)) {
385                                                systemEE = environment.getId();
386                                                break;
387                                        }
388                                }
389                                if (systemEE == null) {
390                                        // a best fit, but not strictly compatible with any environment (e.g.
391                                        // a 1.7 VM for which there is no profile yet). This is a bit of a hack
392                                        // until an OSGi profile exists for 1.7.
393                                        if (bestFit instanceof IVMInstall2) {
394                                    String javaVersion = ((IVMInstall2)bestFit).getJavaVersion();
395                                    if (javaVersion != null) {
396                                            if (javaVersion.startsWith(JavaCore.VERSION_1_7)) {
397                                                    // set EE to 1.6 when 1.7 is detected
398                                                    systemEE = "JavaSE-1.6"; //$NON-NLS-1$
399                                            }
400                                    }
401                                        }
402                                }
403                                if (systemEE != null) {
404                                        // only update if different from current or missing VM binding
405                                        if (!systemEE.equals(getExecutionEnvironment()) || fVMBinding == null) {
406                                                try {
407                                                        File file = Util.createEEFile(bestFit, systemEE);
408                                                        JavaRuntime.addVMInstallChangedListener(this);
409                                                        fVMBinding = bestFit;
410                                                        ExecutionEnvironmentDescription ee = new ExecutionEnvironmentDescription(file);
411                                                        initialize(ee);
412                                                } catch (CoreException e) {
413                                                        error = new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, CoreMessages.ApiBaseline_2, e);
414                                                } catch (IOException e) {
415                                                        error = new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, CoreMessages.ApiBaseline_2, e);
416                                                }
417                                        }
418                                } else {
419                                        // VM is not strictly compatible with any EE
420                                        error = new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, CoreMessages.ApiBaseline_3);
421                                }
422                        } else {
423                                // no VMs match any required EE
424                                error = new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, CoreMessages.ApiBaseline_3);
425                        }
426                        if (error == null) {
427                                // build status for unbound required EE's
428                                Set missing = new HashSet(ees);
429                                Set covered = new HashSet((Set)VMsToEEs.get(bestFit));
430                                missing.removeAll(covered);
431                                if (missing.isEmpty()) {
432                                        fEEStatus = new Status(IStatus.OK, ApiPlugin.PLUGIN_ID,
433                                                        MessageFormat.format(CoreMessages.ApiBaseline_1, new String[]{systemEE}));
434                                } else {
435                                        iterator = missing.iterator();
436                                        MultiStatus multi = new MultiStatus(ApiPlugin.PLUGIN_ID, 0, CoreMessages.ApiBaseline_4, null);
437                                        while (iterator.hasNext()) {
438                                                String id = (String) iterator.next();
439                                                multi.add(new Status(IStatus.WARNING, ApiPlugin.PLUGIN_ID,
440                                                                MessageFormat.format(CoreMessages.ApiBaseline_5, new String[]{id})));
441                                        }
442                                        fEEStatus = multi;
443                                }
444                        } else {
445                                fEEStatus = error;
446                        }
447                }
448        }
449 
450        /**
451         * Returns true if the {@link IApiBaseline} has infos loaded (components) false otherwise.
452         * This is a handle only method that will not load infos.
453         * 
454         * @return true if the {@link IApiBaseline} has infos loaded (components) false otherwise.
455         */
456        public boolean peekInfos() {
457                return fComponentsById != null;
458        }
459        
460        /* (non-Javadoc)
461         * @see IApiBaseline#getApiComponents()
462         */
463        public IApiComponent[] getApiComponents() {
464                loadBaselineInfos();
465                if(fComponentsById == null) {
466                        return EMPTY_COMPONENTS;
467                }
468                Collection values = fComponentsById.values();
469                return (IApiComponent[]) values.toArray(new IApiComponent[values.size()]);
470        }
471        
472        /* (non-Javadoc)
473         * @see IApiBaseline#resolvePackage(IApiComponent, String)
474         */
475        public synchronized IApiComponent[] resolvePackage(IApiComponent sourceComponent, String packageName) throws CoreException {
476                HashMap componentsForPackage = null;
477                if(fComponentsProvidingPackageCache != null){
478                        componentsForPackage = (HashMap) fComponentsProvidingPackageCache.get(packageName);
479                }
480                else {
481                        fComponentsProvidingPackageCache = new HashMap(8);
482                }
483                IApiComponent[] cachedComponents = null;
484                if (componentsForPackage != null) {
485                        cachedComponents = (IApiComponent[]) componentsForPackage.get(sourceComponent);
486                        if (cachedComponents != null && cachedComponents.length > 0) {
487                                return cachedComponents;
488                        }
489                } else {
490                        componentsForPackage = new HashMap(8);
491                        fComponentsProvidingPackageCache.put(packageName, componentsForPackage);
492                }
493                // check system packages first
494                if (isSystemPackage(packageName)) {
495                        if (fSystemLibraryComponent != null) {
496                                cachedComponents = new IApiComponent[] { fSystemLibraryComponent };
497                        } else {
498                                return EMPTY_COMPONENTS;
499                        }
500                } else {
501                        if (sourceComponent != null) {
502                                List componentsList = new ArrayList();
503                                resolvePackage0(sourceComponent, packageName, componentsList);
504                                if (componentsList.size() != 0) {
505                                        cachedComponents = new IApiComponent[componentsList.size()];
506                                        componentsList.toArray(cachedComponents);
507                                }
508                        }
509                }
510                if (cachedComponents == null) {
511                        cachedComponents = EMPTY_COMPONENTS;
512                }
513                if(cachedComponents.length == 0) {
514                        return EMPTY_COMPONENTS;
515                }
516                componentsForPackage.put(sourceComponent, cachedComponents);
517                return cachedComponents;
518        }
519 
520        /**
521         * Resolves the listing of {@link IApiComponent}s that export the given package name. The collection 
522         * of {@link IApiComponent}s is written into the specified list <code>componentList</code> 
523         * @param component
524         * @param packageName
525         * @param componentsList
526         * @throws CoreException
527         */
528        private void resolvePackage0(IApiComponent component, String packageName, List componentsList) throws CoreException {
529                if (component instanceof BundleApiComponent) {
530                        BundleDescription bundle = ((BundleApiComponent)component).getBundleDescription();
531                        if (bundle != null) {
532                                StateHelper helper = getState().getStateHelper();
533                                ExportPackageDescription[] visiblePackages = helper.getVisiblePackages(bundle);
534                                for (int i = 0, max = visiblePackages.length; i < max; i++) {
535                                        ExportPackageDescription pkg = visiblePackages[i];
536                                        if (packageName.equals(pkg.getName())) {
537                                                BundleDescription bundleDescription = pkg.getExporter();
538                                                IApiComponent exporter = getApiComponent(bundleDescription.getSymbolicName());
539                                                if (exporter != null) {
540                                                        componentsList.add(exporter);
541                                                }
542                                        }
543                                }
544                                if (component.isFragment()) {
545                                        // a fragment can see all the packages from the host
546                                        HostSpecification host = bundle.getHost();
547                                        BundleDescription[] hosts = host.getHosts();
548                                        for (int i = 0, max = hosts.length; i < max; i++) {
549                                                BundleDescription currentHost = hosts[i];
550                                                IApiComponent apiComponent = component.getBaseline().getApiComponent(currentHost.getName());
551                                                if (apiComponent != null) {
552                                                        resolvePackage0(apiComponent, packageName, componentsList);
553                                                }
554                                        }
555                                }
556                                // check for package within the source component
557                                String[] packageNames = component.getPackageNames();
558                                int index = Arrays.binarySearch(packageNames, packageName, null);
559                                if (index >= 0) {
560                                        componentsList.add(component);
561                                }
562                        }
563                }
564        }
565        
566        /**
567         * Returns all of the visible dependent components from the current state
568         * 
569         * @param components
570         * @return the listing of visible dependent components to the given ones
571         * @throws CoreException
572         */
573        public IApiComponent[] getVisibleDependentComponents(IApiComponent[] components) throws CoreException {
574                ArrayList bundles = getBundleDescriptions(components);
575                BundleDescription[] descs = getState().getStateHelper().getDependentBundles((BundleDescription[]) bundles.toArray(new BundleDescription[bundles.size()]));
576                HashSet visible = new HashSet();
577                ExportPackageDescription[] packages = null;
578                for (int i = 0; i < descs.length; i++) {
579                        packages = getState().getStateHelper().getVisiblePackages(descs[i]);
580                        for (int j = 0; j < packages.length; j++) {
581                                if(bundles.contains(packages[j].getSupplier())) {
582                                        visible.add(descs[i]);
583                                }
584                        }
585                }
586                return getApiComponents((BundleDescription[]) visible.toArray(new BundleDescription[visible.size()]));
587        }
588        
589        /**
590         * Returns whether the specified package is supplied by the system
591         * library.
592         * 
593         * @param packageName package name
594         * @return whether the specified package is supplied by the system
595         *         library 
596         */
597        private boolean isSystemPackage(String packageName) {
598                if (packageName.startsWith("java.")) { //$NON-NLS-1$
599                        return true;
600                }
601                if (fSystemPackageNames == null) {
602                        ExportPackageDescription[] systemPackages = getState().getSystemPackages();
603                        fSystemPackageNames = new HashSet(systemPackages.length);
604                        for (int i = 0; i < systemPackages.length; i++) {
605                                fSystemPackageNames.add(systemPackages[i].getName());
606                        }
607                }
608                return fSystemPackageNames.contains(packageName);
609        }
610        
611        /**
612         * @return the OSGi state for this {@link IApiProfile}
613         * @nooverride This method is not intended to be re-implemented or extended by clients.
614         * @noreference This method is not intended to be referenced by clients.
615         */
616        public State getState() {
617                if(fState == null) {
618                        fState = StateObjectFactory.defaultFactory.createState(true);
619                }
620                return fState;
621        }
622        
623        /* (non-Javadoc)
624         * @see IApiBaseline#getApiComponent(String)
625         */
626        public IApiComponent getApiComponent(String id) {
627                loadBaselineInfos();
628                if(fComponentsById == null) {
629                        return null;
630                }
631                return (IApiComponent) fComponentsById.get(id);
632        }
633 
634        /* (non-Javadoc)
635         * @see IApiBaseline#getExecutionEnvironment()
636         */
637        public String getExecutionEnvironment() {
638                return fExecutionEnvironment;
639        }
640        
641        /**
642         * Loads the infos from the *.profile file the first time the baseline is accessed
643         */
644        private void loadBaselineInfos() {
645                if(fComponentsById != null) {
646                        return;
647                }
648                try {
649                        ApiBaselineManager.getManager().loadBaselineInfos(this);
650                }
651                catch(CoreException ce) {
652                        ApiPlugin.log(ce);
653                }
654        }
655        
656        /**
657         * Returns all errors in the state.
658         * 
659         * @return state errors
660         * @nooverride This method is not intended to be re-implemented or extended by clients.
661         * @noreference This method is not intended to be referenced by clients.
662         */
663        public ResolverError[] getErrors() {
664                List errs = null;
665                BundleDescription[] bundles = getState().getBundles();
666                for (int i = 0; i < bundles.length; i++) {
667                        ResolverError[] errors = getState().getResolverErrors(bundles[i]);
668                        for (int j = 0; j < errors.length; j++) {
669                                if (errs == null) {
670                                        errs = new ArrayList();
671                                }
672                                errs.add(errors[j]);
673                        }
674                }
675                if (errs != null) {
676                        return (ResolverError[]) errs.toArray(new ResolverError[errs.size()]);
677                }
678                return null;
679        }
680        /**
681         * @see org.eclipse.pde.api.tools.internal.model.ApiElement#setName(java.lang.String)
682         */
683        public void setName(String name) {
684                super.setName(name);
685        }
686        
687        /**
688         * @see java.lang.Object#equals(java.lang.Object)
689         */
690        public boolean equals(Object obj) {
691                if(obj instanceof IApiBaseline) {
692                        IApiBaseline baseline = (IApiBaseline) obj;
693                        return this.getName().equals(baseline.getName());
694                }
695                return super.equals(obj);
696        }
697        
698        /**
699         * @see java.lang.Object#hashCode()
700         */
701        public int hashCode() {
702                return this.getName().hashCode();
703        }
704        
705        /* (non-Javadoc)
706         * @see IApiBaseline#dispose()
707         */
708        public void dispose() {
709                if(fState == null) {
710                        //already disposed or nothing to dispose
711                        return;
712                }
713                if (ApiPlugin.isRunningInFramework()) {
714                        JavaRuntime.removeVMInstallChangedListener(this);
715                }
716                clearCachedElements();
717                IApiComponent[] components = getApiComponents();
718                for (int i = 0; i < components.length; i++) {
719                        components[i].dispose();
720                }
721                clearComponentsCache();
722                if(fComponentsById != null) {
723                        fComponentsById.clear();
724                        fComponentsById = null;
725                }
726                if(fComponentsByProjectNames != null) {
727                        fComponentsByProjectNames.clear();
728                        fComponentsByProjectNames = null;
729                }
730                if (fSystemPackageNames != null) {
731                        fSystemPackageNames.clear();
732                }
733                if(fSystemLibraryComponent != null) {
734                        fSystemLibraryComponent.dispose();
735                        fSystemLibraryComponent = null;
736                }
737                fState = null;
738        }
739 
740        /**
741         * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline#close()
742         */
743        public void close() throws CoreException {
744                clearCachedElements();
745                IApiComponent[] components = getApiComponents();
746                for (int i = 0; i < components.length; i++) {
747                        components[i].close();
748                }
749        }
750 
751        /**
752         * Clears all element infos from the cache for this baseline
753         * @since 1.1
754         */
755        void clearCachedElements() {
756                ApiModelCache.getCache().removeElementInfo(this);
757        }
758        
759        /* (non-Javadoc)
760         * @see IApiBaseline#getDependentComponents(IApiComponent[])
761         */
762        public IApiComponent[] getDependentComponents(IApiComponent[] components) throws CoreException {
763                ArrayList bundles = getBundleDescriptions(components);
764                BundleDescription[] bundleDescriptions = getState().getStateHelper().getDependentBundles((BundleDescription[]) bundles.toArray(new BundleDescription[bundles.size()]));
765                return getApiComponents(bundleDescriptions);
766        }
767 
768        /**
769         * Returns an array of API components corresponding to the given bundle descriptions.
770         * 
771         * @param bundles bundle descriptions
772         * @return corresponding API components
773         */
774        private IApiComponent[] getApiComponents(BundleDescription[] bundles) {
775                ArrayList dependents = new ArrayList(bundles.length);
776                for (int i = 0; i < bundles.length; i++) {
777                        BundleDescription bundle = bundles[i];
778                        IApiComponent component = getApiComponent(bundle.getSymbolicName());
779                        if (component != null) {
780                                dependents.add(component);
781                        }
782                }
783                return (IApiComponent[]) dependents.toArray(new IApiComponent[dependents.size()]);
784        }
785 
786        /**
787         * Returns an array of bundle descriptions corresponding to the given API components.
788         * 
789         * @param components API components
790         * @return corresponding bundle descriptions
791         */
792        private ArrayList getBundleDescriptions(IApiComponent[] components) throws CoreException {
793                ArrayList bundles = new ArrayList(components.length);
794                for (int i = 0; i < components.length; i++) {
795                        IApiComponent component = components[i];
796                        if (component instanceof BundleApiComponent) {
797                                bundles.add(((BundleApiComponent)component).getBundleDescription());
798                        }
799                }
800                return bundles;
801        }
802 
803        /* (non-Javadoc)
804         * @see org.eclipse.pde.api.tools.IApiBaseline#getPrerequisiteComponents(org.eclipse.pde.api.tools.IApiComponent[])
805         */
806        public IApiComponent[] getPrerequisiteComponents(IApiComponent[] components) throws CoreException {
807                ArrayList bundles = getBundleDescriptions(components);
808                BundleDescription[] bundlesDescriptions = getState().getStateHelper().getPrerequisites((BundleDescription[]) bundles.toArray(new BundleDescription[bundles.size()]));
809                return getApiComponents(bundlesDescriptions);
810        }
811 
812        /**
813         * Clear cached settings for the given package.
814         * 
815         * @param packageName
816         * @noreference This method is not intended to be referenced by clients.
817         * @nooverride This method is not intended to be re-implemented or extended by clients.
818         */
819        public synchronized void clearPackage(String packageName) {
820                if(fComponentsProvidingPackageCache != null) {
821                        fComponentsProvidingPackageCache.remove(packageName);
822                }
823        }
824        
825        /* (non-Javadoc)
826         * @see java.lang.Object#toString()
827         */
828        public String toString() {
829                return getName();
830        }
831 
832        /* (non-Javadoc)
833         * @see IApiBaseline#getExecutionEnvironmentStatus()
834         */
835        public IStatus getExecutionEnvironmentStatus() {
836                return fEEStatus;
837        }
838 
839        /* (non-Javadoc)
840         * @see org.eclipse.jdt.launching.IVMInstallChangedListener#defaultVMInstallChanged(org.eclipse.jdt.launching.IVMInstall, org.eclipse.jdt.launching.IVMInstall)
841         */
842        public void defaultVMInstallChanged(IVMInstall previous, IVMInstall current) {}
843 
844        /* (non-Javadoc)
845         * @see org.eclipse.jdt.launching.IVMInstallChangedListener#vmAdded(org.eclipse.jdt.launching.IVMInstall)
846         */
847        public void vmAdded(IVMInstall vm) {
848                if (!(vm instanceof VMStandin)) {
849                        // there may be a better fit for VMs/EEs
850                        try {
851                                rebindVM();
852                        } catch (CoreException e) {
853                                ApiPlugin.log(e);
854                        }
855                }
856        }
857 
858        /* (non-Javadoc)
859         * @see org.eclipse.jdt.launching.IVMInstallChangedListener#vmChanged(org.eclipse.jdt.launching.PropertyChangeEvent)
860         */
861        public void vmChanged(PropertyChangeEvent event) {
862                if (!(event.getSource() instanceof VMStandin)) {
863                        String property = event.getProperty();
864                        if (IVMInstallChangedListener.PROPERTY_INSTALL_LOCATION.equals(property) ||
865                                        IVMInstallChangedListener.PROPERTY_LIBRARY_LOCATIONS.equals(property)) {
866                                try {
867                                        rebindVM();
868                                } catch (CoreException e) {
869                                        ApiPlugin.log(e);
870                                }
871                        }
872                }
873        }
874 
875        /**
876         * Re-binds the VM this baseline is bound to.
877         */
878        private void rebindVM() throws CoreException {
879                fVMBinding = null;
880                IApiComponent[] components = getApiComponents();
881                HashSet ees = new HashSet();
882                for (int i = 0; i < components.length; i++) {
883                        ees.addAll(Arrays.asList(components[i].getExecutionEnvironments()));
884                }
885                resolveSystemLibrary(ees);
886        }
887        
888        /* (non-Javadoc)
889         * @see org.eclipse.jdt.launching.IVMInstallChangedListener#vmRemoved(org.eclipse.jdt.launching.IVMInstall)
890         */
891        public void vmRemoved(IVMInstall vm) {
892                if (vm.equals(fVMBinding)) {
893                        try {
894                                rebindVM();
895                        } catch (CoreException e) {
896                                ApiPlugin.log(e);
897                        }
898                }
899        }
900        
901        /* (non-Javadoc)
902         * @see IApiBaseline#getLocation()
903         */
904        public String getLocation() {
905                return this.fLocation;
906        }
907 
908        /* (non-Javadoc)
909         * @see IApiBaseline#setLocation(String)
910         */
911        public void setLocation(String location) {
912                this.fLocation = location;
913        }
914        public IApiComponent getApiComponent(IProject project) {
915                loadBaselineInfos();
916                if(fComponentsByProjectNames == null) {
917                        return null;
918                }
919                return (IApiComponent) fComponentsByProjectNames.get(project.getName());
920        }
921}

[all classes][org.eclipse.pde.api.tools.internal.model]
EMMA 2.0.5312 EclEmma Fix 1 (C) Vladimir Roubtsov