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

COVERAGE SUMMARY FOR SOURCE FILE [ProjectApiDescription.java]

nameclass, %method, %block, %line, %
ProjectApiDescription.java100% (3/3)86%  (24/28)65%  (834/1280)66%  (199.9/303)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ProjectApiDescription$TypeNode100% (1/1)75%  (3/4)40%  (135/340)42%  (35.1/83)
toString (): String 0%   (0/1)0%   (0/58)0%   (0/9)
refresh (): ApiDescription$ManifestNode 100% (1/1)33%  (72/219)34%  (20.1/59)
ProjectApiDescription$TypeNode (ProjectApiDescription, IType, ApiDescription$... 100% (1/1)100% (28/28)100% (7/7)
persistXML (Document, Element): void 100% (1/1)100% (35/35)100% (8/8)
     
class ProjectApiDescription$PackageNode100% (1/1)75%  (3/4)49%  (85/174)50%  (17/34)
toString (): String 0%   (0/1)0%   (0/84)0%   (0/15)
refresh (): ApiDescription$ManifestNode 100% (1/1)80%  (20/25)67%  (4/6)
ProjectApiDescription$PackageNode (ProjectApiDescription, IPackageFragment []... 100% (1/1)100% (14/14)100% (3/3)
persistXML (Document, Element): void 100% (1/1)100% (51/51)100% (10/10)
     
class ProjectApiDescription100% (1/1)90%  (18/20)80%  (614/766)79%  (147.8/186)
newNode (ApiDescription$ManifestNode, IElementDescriptor, int, int): ApiDescr... 0%   (0/1)0%   (0/9)0%   (0/1)
toString (): String 0%   (0/1)0%   (0/15)0%   (0/3)
getApiTypeContainer (IPackageFragmentRoot): IApiTypeContainer 100% (1/1)47%  (9/19)75%  (3/4)
getApiComponent (): PluginProjectApiComponent 100% (1/1)58%  (14/24)80%  (4/5)
getElementDescriptor (IJavaElement): IElementDescriptor 100% (1/1)60%  (9/15)50%  (2/4)
accept (ApiDescriptionVisitor, IProgressMonitor): void 100% (1/1)69%  (104/150)70%  (24.4/35)
refreshPackages (): void 100% (1/1)74%  (88/119)68%  (20.3/30)
createNode (ApiDescription$ManifestNode, IElementDescriptor): ApiDescription$... 100% (1/1)88%  (168/192)81%  (39/48)
getLocalPackageFragments (): IPackageFragment [] 100% (1/1)98%  (57/58)91%  (10/11)
ProjectApiDescription (IJavaProject): void 100% (1/1)100% (17/17)100% (6/6)
clean (): void 100% (1/1)100% (12/12)100% (5/5)
getJavaProject (): IJavaProject 100% (1/1)100% (3/3)100% (1/1)
getXML (): String 100% (1/1)100% (35/35)100% (8/8)
isInsertOnResolve (IElementDescriptor): boolean 100% (1/1)100% (15/15)100% (4/4)
newPackageNode (IPackageFragment [], ApiDescription$ManifestNode, IElementDes... 100% (1/1)100% (10/10)100% (1/1)
newTypeNode (IType, ApiDescription$ManifestNode, IElementDescriptor, int, int... 100% (1/1)100% (10/10)100% (1/1)
persistChildren (Document, Element, Map): void 100% (1/1)100% (17/17)100% (5/5)
projectChanged (): void 100% (1/1)100% (4/4)100% (2/2)
projectClasspathChanged (): void 100% (1/1)100% (7/7)100% (3/3)
visit (ApiDescriptionVisitor, IType): void 100% (1/1)100% (35/35)100% (9/9)

1/*******************************************************************************
2 * Copyright (c) 2008, 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;
12 
13import java.util.ArrayList;
14import java.util.HashSet;
15import java.util.Iterator;
16import java.util.List;
17import java.util.Map;
18import java.util.Set;
19import java.util.jar.JarFile;
20 
21import org.eclipse.core.resources.IFile;
22import org.eclipse.core.resources.IResource;
23import org.eclipse.core.runtime.CoreException;
24import org.eclipse.core.runtime.IProgressMonitor;
25import org.eclipse.core.runtime.IStatus;
26import org.eclipse.core.runtime.Status;
27import org.eclipse.jdt.core.IClassFile;
28import org.eclipse.jdt.core.IClasspathEntry;
29import org.eclipse.jdt.core.ICompilationUnit;
30import org.eclipse.jdt.core.IJavaElement;
31import org.eclipse.jdt.core.IJavaProject;
32import org.eclipse.jdt.core.IPackageFragment;
33import org.eclipse.jdt.core.IPackageFragmentRoot;
34import org.eclipse.jdt.core.IType;
35import org.eclipse.jdt.core.JavaModelException;
36import org.eclipse.pde.api.tools.internal.model.BundleApiComponent;
37import org.eclipse.pde.api.tools.internal.model.PluginProjectApiComponent;
38import org.eclipse.pde.api.tools.internal.provisional.ApiDescriptionVisitor;
39import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
40import org.eclipse.pde.api.tools.internal.provisional.Factory;
41import org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations;
42import org.eclipse.pde.api.tools.internal.provisional.RestrictionModifiers;
43import org.eclipse.pde.api.tools.internal.provisional.VisibilityModifiers;
44import org.eclipse.pde.api.tools.internal.provisional.descriptors.IElementDescriptor;
45import org.eclipse.pde.api.tools.internal.provisional.descriptors.IPackageDescriptor;
46import org.eclipse.pde.api.tools.internal.provisional.descriptors.IReferenceTypeDescriptor;
47import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline;
48import org.eclipse.pde.api.tools.internal.provisional.model.IApiTypeContainer;
49import org.eclipse.pde.api.tools.internal.provisional.scanner.TagScanner;
50import org.eclipse.pde.api.tools.internal.util.Util;
51import org.w3c.dom.Document;
52import org.w3c.dom.Element;
53 
54/**
55 * Implementation of an API description for a Java project.
56 * 
57 * @since 1.0
58 */
59public class ProjectApiDescription extends ApiDescription {
60        
61        /**
62         * Associated Java project
63         */
64        private IJavaProject fProject;
65        
66        /**
67         * Time stamp at which package information was created
68         */
69        public long fPackageTimeStamp = 0L;
70        
71        /** 
72         * Whether a package refresh is in progress
73         */
74        private boolean fRefreshingInProgress = false;
75        
76        /**
77         * Associated manifest file
78         */
79        public IFile fManifestFile;
80        
81        /**
82         * Whether this API description is in synch with its project. Becomes
83         * false if anything in a project changes. When true, visiting can
84         * be performed by traversing the cached nodes, rather than traversing
85         * the java model elements (effectively building the cache).
86         */
87        private boolean fInSynch = false;
88                        
89        /**
90         * A node for a package.
91         */
92        class PackageNode extends ManifestNode {
93 
94                IPackageFragment[] fFragments;
95                /**
96                 * Constructs a new node.
97                 * 
98                 * @param parent
99                 * @param element
100                 * @param visibility
101                 * @param restrictions
102                 */
103                public PackageNode(IPackageFragment fragments[], ManifestNode parent, IElementDescriptor element, int visibility, int restrictions) {
104                        super(parent, element, visibility, restrictions);
105                        fFragments = fragments;
106                }
107 
108                /* (non-Javadoc)
109                 * @see org.eclipse.pde.api.tools.internal.ApiDescription.ManifestNode#refresh()
110                 */
111                protected ManifestNode refresh() {
112                        refreshPackages();
113                        for (int i = 0; i < fFragments.length; i++) {
114                                if (!fFragments[i].exists()) {
115                                        modified();
116                                        return null;
117                                }
118                        }
119                        return this;
120                }
121                
122                /* (non-Javadoc)
123                 * @see org.eclipse.pde.api.tools.internal.ApiDescription.ManifestNode#persistXML(org.w3c.dom.Document, org.w3c.dom.Element, java.lang.String)
124                 */
125                void persistXML(Document document, Element parent) {
126                        if (hasApiVisibility(this)) {
127                                Element pkg = document.createElement(IApiXmlConstants.ELEMENT_PACKAGE);
128                                for (int i = 0; i < fFragments.length; i++) {
129                                        Element fragment = document.createElement(IApiXmlConstants.ELEMENT_PACKAGE_FRAGMENT);
130                                        fragment.setAttribute(IApiXmlConstants.ATTR_HANDLE, fFragments[i].getHandleIdentifier());
131                                        pkg.appendChild(fragment);
132                                }
133                                pkg.setAttribute(IApiXmlConstants.ATTR_VISIBILITY, Integer.toString(this.visibility));
134                                persistChildren(document, pkg, children);
135                                parent.appendChild(pkg);
136                        }
137                }
138                
139                /* (non-Javadoc)
140                 * @see org.eclipse.pde.api.tools.internal.ApiDescription.ManifestNode#toString()
141                 */
142                public String toString() {
143                        StringBuffer buffer = new StringBuffer();
144                        String name = ((IPackageDescriptor)element).getName();
145                        buffer.append("Package Node: ").append(name.equals("") ? "<default package>" : name); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
146                        buffer.append("\nVisibility: ").append(VisibilityModifiers.getVisibilityName(visibility)); //$NON-NLS-1$
147                        buffer.append("\nRestrictions: ").append(RestrictionModifiers.getRestrictionText(restrictions)); //$NON-NLS-1$
148                        if(fFragments != null) {
149                                buffer.append("\nFragments:"); //$NON-NLS-1$
150                                IPackageFragment fragment = null;
151                                for(int i = 0; i < fFragments.length; i++) {
152                                        fragment = fFragments[i];
153                                        buffer.append("\n\t").append(fragment.getElementName()); //$NON-NLS-1$
154                                        buffer.append(" ["); //$NON-NLS-1$
155                                        buffer.append(fragment.getParent().getElementName());
156                                        buffer.append("]"); //$NON-NLS-1$
157                                }
158                        }
159                        return buffer.toString();
160                }
161        }
162        
163        /**
164         * Node for a reference type.
165         */
166        class TypeNode extends ManifestNode {
167                
168                long fTimeStamp = -1L;
169                
170                private boolean fRefreshing = false;
171                
172                IType fType;
173 
174                /**
175                 * Constructs a node for a reference type.
176                 * 
177                 * @param type
178                 * @param parent
179                 * @param element
180                 * @param visibility
181                 * @param restrictions
182                 */
183                public TypeNode(IType type, ManifestNode parent, IElementDescriptor element, int visibility, int restrictions) {
184                        super(parent, element, visibility, restrictions);
185                        fType = type;
186                        if (parent instanceof TypeNode) {
187                                fTimeStamp = ((TypeNode)parent).fTimeStamp;
188                        }
189                }
190 
191                /* (non-Javadoc)
192                 * @see org.eclipse.pde.api.tools.internal.ApiDescription.ManifestNode#refresh()
193                 */
194                protected synchronized ManifestNode refresh() {
195                        if (fRefreshing) {
196                                if(DEBUG) {
197                                        StringBuffer buffer = new StringBuffer();
198                                        buffer.append("Refreshing manifest node: "); //$NON-NLS-1$
199                                        buffer.append(this);
200                                        buffer.append(" aborted because a refresh is already in progress"); //$NON-NLS-1$
201                                        System.out.println(buffer.toString());
202                                }
203                                return this;
204                        }
205                        try {
206                                fRefreshing = true;
207                                ICompilationUnit unit = fType.getCompilationUnit();
208                                if (unit != null) {
209                                        IResource resource = null;
210                                        try {
211                                                resource = unit.getUnderlyingResource();
212                                        } catch (JavaModelException e) {
213                                                if(DEBUG) {
214                                                        StringBuffer buffer = new StringBuffer();
215                                                        buffer.append("Failed to get underlying resource for compilation unit: "); //$NON-NLS-1$
216                                                        buffer.append(unit);
217                                                        System.out.println(buffer.toString());
218                                                }
219                                                // exception if the resource does not exist
220                                                if (!e.getJavaModelStatus().isDoesNotExist()) {
221                                                        ApiPlugin.log(e.getStatus());
222                                                        return this;
223                                                }
224                                        }
225                                        if (resource != null && resource.exists()) {
226                                                long stamp = resource.getModificationStamp();
227                                                if (stamp != fTimeStamp) {
228                                                        if(DEBUG) {
229                                                                StringBuffer buffer = new StringBuffer();
230                                                                buffer.append("Resource has changed for type manifest node: "); //$NON-NLS-1$
231                                                                buffer.append(this);
232                                                                buffer.append(" tag scanning the new type"); //$NON-NLS-1$
233                                                                System.out.println(buffer.toString());
234                                                        }
235                                                        modified();
236                                                        children.clear();
237                                                        restrictions = RestrictionModifiers.NO_RESTRICTIONS;
238                                                        fTimeStamp = resource.getModificationStamp();
239                                                        try {
240                                                                TagScanner.newScanner().scan(unit, ProjectApiDescription.this,
241                                                                        getApiTypeContainer((IPackageFragmentRoot) fType.getPackageFragment().getParent()), null);
242                                                        } catch (CoreException e) {
243                                                                ApiPlugin.log(e.getStatus());
244                                                        }
245                                                }
246                                        } else {
247                                                if(DEBUG) {
248                                                        StringBuffer buffer = new StringBuffer();
249                                                        buffer.append("Underlying resource for the type manifest node: "); //$NON-NLS-1$
250                                                        buffer.append(this);
251                                                        buffer.append(" does not exist or is null"); //$NON-NLS-1$
252                                                        System.out.println(buffer.toString());
253                                                }
254                                                // element has been removed
255                                                modified();
256                                                parent.children.remove(element);
257                                                return null;
258                                        }
259                                } else {
260                                        if(DEBUG) {
261                                                StringBuffer buffer = new StringBuffer();
262                                                buffer.append("Failed to look up compilation unit for "); //$NON-NLS-1$
263                                                buffer.append(fType);
264                                                buffer.append(" refreshing type manifest node: "); //$NON-NLS-1$
265                                                buffer.append(this);
266                                                System.out.println(buffer.toString());
267                                        }
268                                        // TODO: binary type
269                                }
270                        } finally {
271                                fRefreshing = false;
272                        }
273                        return this;
274                }
275                
276                /* (non-Javadoc)
277                 * @see org.eclipse.pde.api.tools.internal.ApiDescription.ManifestNode#persistXML(org.w3c.dom.Document, org.w3c.dom.Element, java.lang.String)
278                 */
279                void persistXML(Document document, Element parent) {
280                        if(hasApiVisibility(this)) {
281                                Element type = document.createElement(IApiXmlConstants.ELEMENT_TYPE);
282                                type.setAttribute(IApiXmlConstants.ATTR_HANDLE, fType.getHandleIdentifier());
283                                persistAnnotations(type);
284                                type.setAttribute(IApiXmlConstants.ATTR_MODIFICATION_STAMP, Long.toString(fTimeStamp));
285                                persistChildren(document, type, children);
286                                parent.appendChild(type);
287                        }
288                }
289                
290                /* (non-Javadoc)
291                 * @see org.eclipse.pde.api.tools.internal.ApiDescription.ManifestNode#toString()
292                 */
293                public String toString() {
294                        StringBuffer buffer = new StringBuffer();
295                        buffer.append("Type Node: ").append(fType.getFullyQualifiedName()); //$NON-NLS-1$
296                        buffer.append("\nVisibility: ").append(VisibilityModifiers.getVisibilityName(visibility)); //$NON-NLS-1$
297                        buffer.append("\nRestrictions: ").append(RestrictionModifiers.getRestrictionText(restrictions)); //$NON-NLS-1$
298                        if(parent != null) {
299                                String pname = parent.element.getElementType() == IElementDescriptor.PACKAGE ?
300                                                ((IPackageDescriptor)parent.element).getName() : ((IReferenceTypeDescriptor)parent.element).getQualifiedName();
301                                buffer.append("\nParent: ").append(pname); //$NON-NLS-1$
302                        }
303                        return buffer.toString();
304                }
305        }
306        
307        /**
308         * Constructs a new API description for the given project API component.
309         * 
310         * @param component
311         */
312        public ProjectApiDescription(IJavaProject project) {
313                super(project.getElementName());
314                fProject = project;
315        }
316 
317        /* (non-Javadoc)
318         * @see org.eclipse.pde.api.tools.internal.provisional.IApiDescription#accept(org.eclipse.pde.api.tools.internal.provisional.ApiDescriptionVisitor)
319         */
320        public synchronized void accept(ApiDescriptionVisitor visitor, IProgressMonitor monitor) {
321                boolean completeVisit = true;
322                if (fInSynch) {
323                        super.accept(visitor, monitor);
324                } else {
325                        try {
326                                IPackageFragment[] fragments = getLocalPackageFragments();
327                                IJavaElement[] children = null;
328                                IJavaElement child = null;
329                                ICompilationUnit unit = null;
330                                for (int j = 0; j < fragments.length; j++) {
331                                        if (DEBUG) {
332                                                System.out.println("\t" + fragments[j].getElementName()); //$NON-NLS-1$
333                                        }
334                                        IPackageDescriptor packageDescriptor = Factory.packageDescriptor(fragments[j].getElementName());
335                                        // visit package
336                                        ManifestNode pkgNode = findNode(packageDescriptor, false);
337                                        if (pkgNode != null) {
338                                                IApiAnnotations annotations = resolveAnnotations(pkgNode, packageDescriptor);
339                                                if (visitor.visitElement(packageDescriptor, annotations)) {
340                                                        children = fragments[j].getChildren();
341                                                        for (int k = 0; k < children.length; k++) {
342                                                                child = children[k];
343                                                                if (child instanceof ICompilationUnit) {
344                                                                        unit = (ICompilationUnit) child;
345                                                                        String cuName = unit.getElementName(); 
346                                                                        String tName = cuName.substring(0, cuName.length() - ".java".length()); //$NON-NLS-1$
347                                                                        visit(visitor, unit.getType(tName));
348                                                                } else if (child instanceof IClassFile) {
349                                                                        visit(visitor, ((IClassFile)child).getType());
350                                                                }
351                                                        }
352                                                } else {
353                                                        completeVisit = false;
354                                                }
355                                                visitor.endVisitElement(packageDescriptor, annotations);
356                                        }
357                                }
358                        } catch (JavaModelException e) {
359                                completeVisit = false;
360                                ApiPlugin.log(e.getStatus());
361                        } finally {
362                                if (completeVisit) {
363                                        fInSynch = true;
364                                }
365                        }
366                }
367        }
368        
369        /**
370         * Visits a type.
371         * 
372         * @param visitor
373         * @param owningComponent
374         * @param type
375         */
376        private void visit(ApiDescriptionVisitor visitor, IType type) {
377                IElementDescriptor element = getElementDescriptor(type);
378                ManifestNode typeNode = findNode(element, false);
379                if (typeNode != null) {
380                        IApiAnnotations annotations = resolveAnnotations(typeNode, element);
381                        if (visitor.visitElement(element, annotations)) {
382                                // children
383                                if (typeNode.children != null) {
384                                        visitChildren(visitor, typeNode.children, null);
385                                }
386                        }
387                        visitor.endVisitElement(element, annotations);
388                }
389        }
390        
391        /* (non-Javadoc)
392         * @see org.eclipse.pde.api.tools.internal.ApiDescription#isInsertOnResolve(org.eclipse.pde.api.tools.internal.provisional.descriptors.IElementDescriptor)
393         */
394        protected boolean isInsertOnResolve(IElementDescriptor elementDescriptor) {
395                switch (elementDescriptor.getElementType()) {
396                        case IElementDescriptor.METHOD:
397                        case IElementDescriptor.FIELD:
398                                return false;
399                        case IElementDescriptor.TYPE:
400                                // no need to insert member types
401                                return ((IReferenceTypeDescriptor) elementDescriptor).getEnclosingType() == null;
402                        default:
403                                return true;
404                }
405        }
406        
407        /* (non-Javadoc)
408         * @see org.eclipse.pde.api.tools.internal.ApiDescription#createNode(org.eclipse.pde.api.tools.internal.ApiDescription.ManifestNode, org.eclipse.pde.api.tools.internal.provisional.descriptors.IElementDescriptor)
409         */
410        protected ManifestNode createNode(ManifestNode parentNode, IElementDescriptor element) {
411                switch (element.getElementType()) {
412                        case IElementDescriptor.PACKAGE:
413                                try {
414                                        IPackageDescriptor pkg = (IPackageDescriptor) element;
415                                        IPackageFragmentRoot[] roots = getJavaProject().getPackageFragmentRoots();
416                                        List fragments = new ArrayList(1);
417                                        for (int i = 0; i < roots.length; i++) {
418                                                IPackageFragmentRoot root = roots[i];
419                                                IClasspathEntry entry = root.getRawClasspathEntry();
420                                                switch (entry.getEntryKind()) {
421                                                case IClasspathEntry.CPE_SOURCE:
422                                                case IClasspathEntry.CPE_LIBRARY:
423                                                        IPackageFragment fragment = root.getPackageFragment(pkg.getName());
424                                                        if (fragment.exists()) {
425                                                                fragments.add(fragment);
426                                                        }
427                                                        break;
428                                                default:
429                                                        if (!root.isArchive()
430                                                                        && root.getKind() == IPackageFragmentRoot.K_BINARY) {
431                                                                // class file folder
432                                                                fragment = root.getPackageFragment(pkg.getName());
433                                                                if (fragment.exists()) {
434                                                                        fragments.add(fragment);
435                                                                }
436                                                        }
437                                                }
438                                        }
439                                        if (fragments.isEmpty()) {
440                                                return null;
441                                        } else {
442                                                return newPackageNode((IPackageFragment[])fragments.toArray(new IPackageFragment[fragments.size()]), parentNode, element, VisibilityModifiers.PRIVATE, RestrictionModifiers.NO_RESTRICTIONS);
443                                        }
444                                        
445                                } catch (CoreException e) {
446                                        return null;
447                                }
448                        case IElementDescriptor.TYPE:
449                                IReferenceTypeDescriptor descriptor = (IReferenceTypeDescriptor) element;
450                                try {
451                                        IType type = null;
452                                        String name = descriptor.getName();
453                                        if (parentNode instanceof PackageNode) {
454                                                IPackageFragment[] fragments = ((PackageNode) parentNode).fFragments; 
455                                                for (int i = 0; i < fragments.length; i++) {
456                                                        IPackageFragment fragment = fragments[i];
457                                                        if (fragment.getKind() == IPackageFragmentRoot.K_SOURCE) {
458                                                                ICompilationUnit unit = fragment.getCompilationUnit(name + ".java"); //$NON-NLS-1$
459                                                                try {
460                                                                        IResource resource = unit.getUnderlyingResource();
461                                                                        if (resource != null) {
462                                                                                type = unit.getType(name);
463                                                                        }
464                                                                } catch (JavaModelException jme) {
465                                                                        // exception if the resource does not exist
466                                                                        if (!jme.getJavaModelStatus().isDoesNotExist()) {
467                                                                                throw jme;
468                                                                        }
469                                                                }
470                                                        } else {
471                                                                IClassFile file = fragment.getClassFile(name + ".class"); //$NON-NLS-1$
472                                                                if (file.exists()) {
473                                                                        type = file.getType();
474                                                                }
475                                                        }
476                                                }
477                                        } else if (parentNode instanceof TypeNode) {
478                                                type = ((TypeNode)parentNode).fType.getType(name);
479                                        }
480                                        if (type != null) {
481                                                return newTypeNode(type, parentNode, element, VISIBILITY_INHERITED, RestrictionModifiers.NO_RESTRICTIONS);
482                                        }
483                                } catch (CoreException e ) {
484                                        return null;
485                                }
486                                return null;
487                }
488                return super.createNode(parentNode, element);
489        }
490 
491        /** 
492         * Constructs and returns a new node for the given package fragment.
493         * 
494         * @param fragment
495         * @param parent
496         * @param descriptor
497         * @param vis
498         * @param res
499         * @return
500         */
501        public PackageNode newPackageNode(IPackageFragment[] fragments, ManifestNode parent, IElementDescriptor descriptor, int vis, int res) {
502                return new PackageNode(fragments, parent, descriptor, vis, res);
503        }
504 
505        /**
506         * Constructs and returns a new node for the given type.
507         * 
508         * @param type
509         * @param parent
510         * @param descriptor
511         * @param vis
512         * @param res
513         * @return
514         */
515        TypeNode newTypeNode(IType type, ManifestNode parent, IElementDescriptor descriptor, int vis, int res) {
516                return new TypeNode(type, parent, descriptor, vis, res);
517        }
518        
519        /**
520         * Constructs a new manifest node.
521         * 
522         * @param parent
523         * @param element
524         * @param vis
525         * @param res
526         * @return
527         */
528        ManifestNode newNode(ManifestNode parent, IElementDescriptor element, int vis, int res) {
529                return new ManifestNode(parent, element, vis, res);
530        }
531 
532        /**
533         * Refreshes package nodes if required.
534         */
535        synchronized void refreshPackages() {
536                if (fRefreshingInProgress) {
537                        if(DEBUG) {
538                                StringBuffer buffer = new StringBuffer();
539                                buffer.append("Refreshing manifest node: "); //$NON-NLS-1$
540                                buffer.append(this);
541                                buffer.append(" aborted because a refresh is already in progress"); //$NON-NLS-1$
542                                System.out.println(buffer.toString());
543                        }
544                        return;
545                }
546                // check if in synch
547                if (fManifestFile == null || (fManifestFile.getModificationStamp() != fPackageTimeStamp)) {
548                        try {
549                                modified();
550                                fRefreshingInProgress = true;
551                                // set all existing packages to PRIVATE (could clear
552                                // the map, but it would be less efficient)
553                                Iterator iterator = fPackageMap.values().iterator();
554                                while (iterator.hasNext()) {
555                                        PackageNode node = (PackageNode) iterator.next();
556                                        node.visibility = VisibilityModifiers.PRIVATE;
557                                }
558                                fManifestFile = getJavaProject().getProject().getFile(JarFile.MANIFEST_NAME);
559                                if (fManifestFile.exists()) {
560                                        try {
561                                                IPackageFragment[] fragments = getLocalPackageFragments();
562                                                Set names = new HashSet();
563                                                for (int i = 0; i < fragments.length; i++) {
564                                                        names.add(fragments[i].getElementName());
565                                                }
566                                                PluginProjectApiComponent component = getApiComponent();
567                                                BundleApiComponent.initializeApiDescription(this, component.getBundleDescription(), names);
568                                                fPackageTimeStamp = fManifestFile.getModificationStamp();
569                                        } catch (CoreException e) {
570                                                ApiPlugin.log(e.getStatus());
571                                        }
572                                }
573                        } finally {
574                                fRefreshingInProgress = false;
575                        }
576                }
577        }
578 
579        private IElementDescriptor getElementDescriptor(IJavaElement element) {
580                switch (element.getElementType()) {
581                        case IJavaElement.PACKAGE_FRAGMENT:
582                                return Factory.packageDescriptor(element.getElementName());
583                        case IJavaElement.TYPE:
584                                return Factory.typeDescriptor(((IType)element).getFullyQualifiedName('$'));
585                        default:
586                                return null;
587                }
588        }
589        
590        /**
591         * Returns the Java project associated with this component.
592         * 
593         * @return associated Java project
594         */
595        private IJavaProject getJavaProject() {
596                return fProject;
597        }
598 
599        /**
600         * Returns a class file container for the given package fragment root.
601         * 
602         * @param root package fragment root
603         * @return class file container
604         * @exception CoreException if container cannot be located
605         */
606        synchronized IApiTypeContainer getApiTypeContainer(IPackageFragmentRoot root) throws CoreException {
607                IApiTypeContainer container  = getApiComponent().getTypeContainer(root);
608                if (container == null) {
609                        throw new CoreException(new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, "Unable to resolve type conatiner for package fragment root"));  //$NON-NLS-1$
610                }
611                return container;
612        }
613        
614        /**
615         * Returns all package fragments that originate from this project.
616         * 
617         * @return all package fragments that originate from this project
618         */
619        private IPackageFragment[] getLocalPackageFragments() {
620                List local = new ArrayList();
621                try {
622                        IPackageFragmentRoot[] roots = getJavaProject().getPackageFragmentRoots();
623                        for (int i = 0; i < roots.length; i++) {
624                                IPackageFragmentRoot root = roots[i];
625                                // only care about roots originating from this project (binary or source)
626                                IResource resource = root.getCorrespondingResource();
627                                if (resource != null && resource.getProject().equals(getJavaProject().getProject())) {
628                                        IJavaElement[] children = root.getChildren();
629                                        for (int j = 0; j < children.length; j++) {
630                                                local.add(children[j]);
631                                        }
632                                }
633                        }
634                } catch (JavaModelException e) {
635                        // ignore
636                }
637                return (IPackageFragment[]) local.toArray(new IPackageFragment[local.size()]);
638        }
639        
640        /**
641         * Returns this API description as XML.
642         * 
643         * @throws CoreException
644         */
645        public synchronized String getXML() throws CoreException {
646                Document document = Util.newDocument();        
647                Element component = document.createElement(IApiXmlConstants.ELEMENT_COMPONENT);
648                component.setAttribute(IApiXmlConstants.ATTR_ID, getJavaProject().getElementName());
649                component.setAttribute(IApiXmlConstants.ATTR_MODIFICATION_STAMP, Long.toString(fPackageTimeStamp));
650                component.setAttribute(IApiXmlConstants.ATTR_VERSION, IApiXmlConstants.API_DESCRIPTION_CURRENT_VERSION);
651                document.appendChild(component);
652                persistChildren(document, component, fPackageMap);
653                return Util.serializeDocument(document);
654        }
655 
656        /**
657         * Persists the elements in the given map as XML elements, appended
658         * to the given xmlElement.
659         *  
660         * @param document XML document
661         * @param xmlElement node to append children no
662         * @param elementMap elements to persist
663         */
664        void persistChildren(Document document, Element xmlElement, Map elementMap) {
665                Iterator iterator = elementMap.values().iterator();
666                while (iterator.hasNext()) {
667                        ManifestNode node = (ManifestNode) iterator.next();
668                        node.persistXML(document, xmlElement);
669                }
670        }
671        
672        /**
673         * Cleans this API description so it will be re-populated with fresh data.
674         */
675        public synchronized void clean() {
676                fPackageMap.clear();
677                fPackageTimeStamp = -1L;
678                fInSynch = false;
679                modified();
680        }
681        
682        /**
683         * Notes that the underlying project has changed in some way and that the
684         * description cache is no longer in synch with the project.
685         */
686        public synchronized void projectChanged() {
687                fInSynch = false;
688        }
689 
690        /**
691         * Notes that the underlying project classpath has changed in some way and that the
692         * description cache is no longer in synch with the project.
693         */
694        public synchronized void projectClasspathChanged() {
695                fInSynch = false;
696                // we want to flush the packages cache to "reload" all packages using the new package fragment roots
697                fPackageTimeStamp = -1L;
698        }
699 
700        /* (non-Javadoc)
701         * @see org.eclipse.pde.api.tools.internal.ApiDescription#toString()
702         */
703        public String toString() {
704                StringBuffer buffer = new StringBuffer();
705                buffer.append("Project API description for: ").append(getJavaProject().getElementName()); //$NON-NLS-1$
706                return buffer.toString();
707        }
708        
709        /**
710         * Returns the API component associated with this API description
711         * 
712         * @return API component
713         * @exception CoreException if the API component cannot be located
714         */
715        private PluginProjectApiComponent getApiComponent() throws CoreException {
716                IApiBaseline baseline = ApiBaselineManager.getManager().getWorkspaceBaseline();
717                PluginProjectApiComponent component = (PluginProjectApiComponent) baseline.getApiComponent(getJavaProject().getProject());
718                if (component == null) {
719                        throw new CoreException(new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, "Unable to resolve project API component for API description"));  //$NON-NLS-1$
720                }
721                return component;
722        }
723}

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