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

COVERAGE SUMMARY FOR SOURCE FILE [ApiAnalysisBuilder.java]

nameclass, %method, %block, %line, %
ApiAnalysisBuilder.java100% (1/1)80%  (20/25)67%  (1064/1598)71%  (250.8/352)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ApiAnalysisBuilder100% (1/1)80%  (20/25)67%  (1064/1598)71%  (250.8/352)
clean (IProgressMonitor): void 0%   (0/1)0%   (0/63)0%   (0/14)
cleanupApiDescription (IProject): void 0%   (0/1)0%   (0/12)0%   (0/3)
getProjectOutputPaths (IProject): HashSet 0%   (0/1)0%   (0/6)0%   (0/1)
setDebug (boolean): void 0%   (0/1)0%   (0/9)0%   (0/2)
toString (): String 0%   (0/1)0%   (0/6)0%   (0/1)
build (int, Map, IProgressMonitor): IProject [] 100% (1/1)44%  (232/528)54%  (45.2/84)
isOptional (IClasspathEntry): boolean 100% (1/1)45%  (14/31)49%  (2.9/6)
cleanupUnsupportedTagMarkers (IResource): void 100% (1/1)56%  (9/16)50%  (3/6)
getDeltas (IProject []): IResourceDelta [] 100% (1/1)62%  (48/77)80%  (12/15)
cleanUnusedFilterMarkers (IResource): void 100% (1/1)75%  (12/16)60%  (3/5)
cleanupUsageMarkers (IResource): void 100% (1/1)75%  (12/16)60%  (3/5)
getCurrentModel (): IPluginModelBase 100% (1/1)76%  (44/58)86%  (12/14)
worthDoingFullBuild (IProject []): boolean 100% (1/1)76%  (29/38)70%  (7/10)
resolveResource (IApiProblem): IResource 100% (1/1)77%  (20/26)67%  (6/9)
createMarkers (): void 100% (1/1)80%  (63/79)78%  (14/18)
getProblemTypeFromCategory (int, int): String 100% (1/1)85%  (22/26)83%  (10/12)
cleanupCompatibilityMarkers (IResource): void 100% (1/1)90%  (36/40)80%  (8/10)
buildAll (IApiBaseline, IApiBaseline, IProgressMonitor): void 100% (1/1)91%  (75/82)85%  (17.9/21)
getRequiredProjects (boolean): IProject [] 100% (1/1)92%  (215/233)89%  (48.7/55)
createMarkerForProblem (int, String, IApiProblem): void 100% (1/1)98%  (136/139)92%  (33/36)
<static initializer> 100% (1/1)100% (20/20)100% (6/6)
ApiAnalysisBuilder (): void 100% (1/1)100% (22/22)100% (6/6)
cleanupMarkers (IResource): void 100% (1/1)100% (13/13)100% (5/5)
createArgAttribute (String []): String 100% (1/1)100% (31/31)100% (6/6)
getAnalyzer (): IApiAnalyzer 100% (1/1)100% (11/11)100% (3/3)

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.builder;
12 
13import java.util.ArrayList;
14import java.util.Date;
15import java.util.HashMap;
16import java.util.HashSet;
17import java.util.Map;
18import java.util.Set;
19import java.util.jar.JarFile;
20 
21import org.eclipse.core.resources.IMarker;
22import org.eclipse.core.resources.IProject;
23import org.eclipse.core.resources.IResource;
24import org.eclipse.core.resources.IResourceDelta;
25import org.eclipse.core.resources.IWorkspaceRoot;
26import org.eclipse.core.resources.IncrementalProjectBuilder;
27import org.eclipse.core.resources.ResourcesPlugin;
28import org.eclipse.core.runtime.CoreException;
29import org.eclipse.core.runtime.IPath;
30import org.eclipse.core.runtime.IProgressMonitor;
31import org.eclipse.core.runtime.IStatus;
32import org.eclipse.core.runtime.OperationCanceledException;
33import org.eclipse.core.runtime.Path;
34import org.eclipse.core.runtime.SubMonitor;
35import org.eclipse.jdt.core.IClasspathAttribute;
36import org.eclipse.jdt.core.IClasspathEntry;
37import org.eclipse.jdt.core.IJavaProject;
38import org.eclipse.jdt.core.IPackageFragmentRoot;
39import org.eclipse.jdt.core.JavaCore;
40import org.eclipse.jdt.core.JavaModelException;
41import org.eclipse.jdt.internal.core.JavaModelManager;
42import org.eclipse.jdt.internal.core.builder.State;
43import org.eclipse.osgi.service.resolver.BundleDescription;
44import org.eclipse.osgi.util.NLS;
45import org.eclipse.pde.api.tools.internal.ApiDescriptionManager;
46import org.eclipse.pde.api.tools.internal.IApiCoreConstants;
47import org.eclipse.pde.api.tools.internal.problems.ApiProblemFactory;
48import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
49import org.eclipse.pde.api.tools.internal.provisional.IApiMarkerConstants;
50import org.eclipse.pde.api.tools.internal.provisional.builder.IApiAnalyzer;
51import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline;
52import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
53import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem;
54import org.eclipse.pde.api.tools.internal.util.Util;
55import org.eclipse.pde.core.plugin.IPluginModelBase;
56import org.eclipse.pde.core.plugin.PluginRegistry;
57 
58import com.ibm.icu.text.MessageFormat;
59 
60/**
61 * Builder for creating API tooling resource markers
62 * @since 1.0.0
63 */
64public class ApiAnalysisBuilder extends IncrementalProjectBuilder {
65        /**
66         * Constant used for controlling tracing in the API tool builder
67         */
68        static boolean DEBUG = Util.DEBUG;
69        
70        /**
71         * Project relative path to the .settings folder
72         * @since 1.0.1
73         */
74        static final IPath SETTINGS_PATH = new Path(".settings"); //$NON-NLS-1$
75        
76        /**
77         * Project relative path to the manifest file.
78         */
79        static final IPath MANIFEST_PATH = new Path(JarFile.MANIFEST_NAME);
80        
81        /**
82         * Project relative path to the .api_filters file
83         */
84        static final IPath FILTER_PATH = SETTINGS_PATH.append(IApiCoreConstants.API_FILTERS_XML_NAME);
85        
86        /**
87         * Empty listing of projects to be returned by the builder if there is nothing to do
88         */
89        static final IProject[] NO_PROJECTS = new IProject[0];
90 
91        /**
92         * Constant representing the name of the 'source' attribute on API tooling markers.
93         * Value is <code>Api Tooling</code>
94         */
95        static final String SOURCE = "Api Tooling"; //$NON-NLS-1$
96        
97        /**
98         * Method used for initializing tracing in the API tool builder
99         */
100        public static void setDebug(boolean debugValue) {
101                DEBUG = debugValue || Util.DEBUG;
102        }
103        
104        /**
105         * The current project for which this builder was defined
106         */
107        private IProject currentproject = null;
108        
109        /**
110         * The API analyzer for this builder
111         */
112        private IApiAnalyzer analyzer = null;
113        
114        /**
115         * Maps prerequisite projects to their output location(s)
116         */
117        HashMap output_locs = new HashMap();
118        
119        /**
120         * Maps pre-requisite projects to their source locations
121         */
122        HashMap src_locs = new HashMap();
123        
124        /**
125         * Current build state
126         */
127        private BuildState buildstate = null;
128        
129        /**
130         * Cleans up markers associated with API tooling on the given resource.
131         * 
132         * @param resource
133         */
134        void cleanupMarkers(IResource resource) {
135                cleanUnusedFilterMarkers(resource);
136                cleanupUsageMarkers(resource);
137                cleanupCompatibilityMarkers(resource);
138                cleanupUnsupportedTagMarkers(resource);
139        }
140        
141        /**
142         * Cleans up unsupported Javadoc tag markers on the specified resource
143         * @param resource
144         */
145        void cleanupUnsupportedTagMarkers(IResource resource) {
146                try {
147                        if(DEBUG) {
148                                System.out.println("cleaning unsupported tag problems"); //$NON-NLS-1$
149                        }
150                        resource.deleteMarkers(IApiMarkerConstants.UNSUPPORTED_TAG_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
151                } catch (CoreException e) {
152                        ApiPlugin.log(e.getStatus());
153                }
154        }
155        
156        /**
157         * Cleans up only API compatibility markers on the given {@link IResource}
158         * @param resource the given resource
159         */
160        void cleanupCompatibilityMarkers(IResource resource) {
161                try {
162                        if (resource != null && resource.isAccessible()) {
163                                resource.deleteMarkers(IApiMarkerConstants.COMPATIBILITY_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
164                                resource.deleteMarkers(IApiMarkerConstants.SINCE_TAGS_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
165                                if (resource.getType() == IResource.PROJECT) {
166                                        // on full builds
167                                        resource.deleteMarkers(IApiMarkerConstants.VERSION_NUMBERING_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
168                                        resource.deleteMarkers(IApiMarkerConstants.DEFAULT_API_BASELINE_PROBLEM_MARKER, true, IResource.DEPTH_ZERO);
169                                        resource.deleteMarkers(IApiMarkerConstants.API_COMPONENT_RESOLUTION_PROBLEM_MARKER, true, IResource.DEPTH_ZERO);
170                                }
171                        }
172                } catch(CoreException e) {
173                        ApiPlugin.log(e.getStatus());
174                }
175        }
176        
177        /**
178         * cleans up only API usage markers from the given {@link IResource}
179         * @param resource
180         */
181        void cleanupUsageMarkers(IResource resource) {
182                try {
183                        if (resource != null && resource.isAccessible()) {
184                                resource.deleteMarkers(IApiMarkerConstants.API_USAGE_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
185                        }
186                } catch(CoreException e) {
187                        ApiPlugin.log(e.getStatus());
188                }
189        }
190        
191        /**
192         * Cleans up the unused API filter problems from the given resource
193         * @param resource
194         */
195        void cleanUnusedFilterMarkers(IResource resource) {
196                try {
197                        if(resource != null && resource.isAccessible()) {
198                                resource.deleteMarkers(IApiMarkerConstants.UNUSED_FILTER_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
199                        }
200                }
201                catch(CoreException ce) {
202                        ApiPlugin.log(ce.getStatus());
203                }
204        }
205        
206        /* (non-Javadoc)
207         * @see org.eclipse.core.resources.IncrementalProjectBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
208         */
209        protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException {
210                this.currentproject = getProject();
211                if (!this.currentproject.isAccessible() || !this.currentproject.hasNature(ApiPlugin.NATURE_ID) || hasBeenBuilt(this.currentproject)) {
212                        return NO_PROJECTS;
213                }
214                if (DEBUG) {
215                        System.out.println("\nApiAnalysis builder - Starting build of " + this.currentproject.getName() + " @ " + new Date(System.currentTimeMillis())); //$NON-NLS-1$ //$NON-NLS-2$
216                }
217                SubMonitor localMonitor = SubMonitor.convert(monitor, BuilderMessages.api_analysis_builder, 8);
218                IApiBaseline wbaseline = ApiPlugin.getDefault().getApiBaselineManager().getWorkspaceBaseline();
219                if (wbaseline == null) {
220                        if (DEBUG) {
221                                System.err.println("Could not retrieve a workspace profile");  //$NON-NLS-1$
222                        }
223                        return NO_PROJECTS;
224                }
225                final IProject[] projects = getRequiredProjects(true);
226                IApiBaseline baseline = ApiPlugin.getDefault().getApiBaselineManager().getDefaultApiBaseline();
227                try {
228                        switch(kind) {
229                                case FULL_BUILD : {
230                                        if (DEBUG) {
231                                                System.out.println("Performing full build as requested by user"); //$NON-NLS-1$
232                                        }
233                                        buildAll(baseline, wbaseline, localMonitor.newChild(1));
234                                        break;
235                                }
236                                case AUTO_BUILD :
237                                case INCREMENTAL_BUILD : {
238                                        this.buildstate = BuildState.getLastBuiltState(currentproject);
239                                        if (this.buildstate == null) {
240                                                buildAll(baseline, wbaseline, localMonitor.newChild(1));
241                                                break;
242                                        }
243                                        else if(worthDoingFullBuild(projects)) {
244                                                buildAll(baseline, wbaseline, localMonitor.newChild(1));
245                                                break;
246                                        }
247                                        else {
248                                                IResourceDelta[] deltas = getDeltas(projects);
249                                                if(deltas.length < 1) {
250                                                        buildAll(baseline, wbaseline, localMonitor.newChild(1));
251                                                }
252                                                else {        
253                                                        IResourceDelta manifest = null;
254                                                        IResourceDelta filters = null;
255                                                        boolean filterbuild = false;
256                                                        for (int i = 0; i < deltas.length; i++) {
257                                                                manifest = deltas[i].findMember(MANIFEST_PATH);
258                                                                if(manifest != null) {
259                                                                        break;
260                                                                }
261                                                                filters = deltas[i].findMember(FILTER_PATH);
262                                                                if(filters != null){
263                                                                        switch(filters.getKind()) {
264                                                                                case IResourceDelta.ADDED:
265                                                                                case IResourceDelta.REMOVED: {
266                                                                                        filterbuild = true;
267                                                                                        break;
268                                                                                }
269                                                                                case IResourceDelta.CHANGED: {
270                                                                                        filterbuild = (filters.getFlags() & IResourceDelta.REPLACED) > 0;
271                                                                                        break;
272                                                                                }
273                                                                        }
274                                                                        if(filterbuild) {
275                                                                                break;
276                                                                        }
277                                                                }
278                                                        }
279                                                        if (manifest != null || filterbuild) {
280                                                                if (DEBUG) {
281                                                                        System.out.println("Performing full build since MANIFEST.MF or .api_filters was modified"); //$NON-NLS-1$
282                                                                 }
283                                                                buildAll(baseline, wbaseline, localMonitor.newChild(1));
284                                                        }
285                                                        else {
286                                                                State state = (State)JavaModelManager.getJavaModelManager().getLastBuiltState(this.currentproject, localMonitor.newChild(1));
287                                                                if(state == null) {
288                                                                        buildAll(baseline, wbaseline, localMonitor.newChild(1));
289                                                                        break;
290                                                                }
291                                                                BuildState.setLastBuiltState(this.currentproject, null);
292                                                                IncrementalApiBuilder builder = new IncrementalApiBuilder(this);
293                                                                builder.build(baseline, wbaseline, deltas, state, this.buildstate, localMonitor.newChild(1));
294                                                        }
295                                                }
296                                        }
297                                }        
298                        }
299                        Util.updateMonitor(localMonitor, 0);
300                
301                }
302                catch (OperationCanceledException oce) {
303                        //do nothing, just end and clean up
304                }
305                catch(CoreException e) {
306                        IStatus status = e.getStatus();
307                        if (status == null || status.getCode() != ApiPlugin.REPORT_BASELINE_IS_DISPOSED) {
308                                throw e;
309                        }
310                        ApiPlugin.log(e);
311                } finally {
312                        Util.updateMonitor(localMonitor, 0);
313                        if(this.analyzer != null) {
314                                this.analyzer.dispose();
315                                this.analyzer = null;
316                        }
317                        if(projects.length < 1) {
318                                //if this build cycle indicates that more projects need to be built do not close 
319                                //the baselines yet, they might be re-read by another build cycle
320                                if(baseline != null) {
321                                        baseline.close();
322                                }
323                        }
324                        Util.updateMonitor(localMonitor, 0);
325                        if (this.buildstate != null) {
326                                for(int i = 0, max = projects.length; i < max; i++) {
327                                        IProject project = projects[i];
328                                        if (Util.isApiProject(project)) {
329                                                this.buildstate.addApiToolingDependentProject(project.getName());
330                                        }
331                                }
332                                BuildState.saveBuiltState(this.currentproject, this.buildstate);
333                                this.buildstate = null;
334                                Util.updateMonitor(monitor, 0);
335                        }
336                        if(localMonitor != null) {
337                                localMonitor.done();
338                        }
339                }
340                if (DEBUG) {
341                        System.out.println("Finished build of " + this.currentproject.getName() + " @ " + new Date(System.currentTimeMillis())); //$NON-NLS-1$ //$NON-NLS-2$
342                }
343                return projects;
344        }
345        
346        /**
347         * if its worth doing a full build considering the given set if projects
348         * @param projects projects to check the build state for
349         * @return true if a full build should take place, false otherwise
350         */
351        boolean worthDoingFullBuild(IProject[] projects) {
352                Set apiToolingDependentProjects = this.buildstate.getApiToolingDependentProjects();
353                for (int i = 0, max = projects.length; i < max; i++) {
354                        IProject currentProject = projects[i];
355                        if (Util.isApiProject(currentProject)) {
356                                if (apiToolingDependentProjects.contains(currentProject.getName())) {
357                                        continue;
358                                }
359                                return true;
360                        } else if (apiToolingDependentProjects.contains(currentProject.getName())) {
361                                return true;
362                        }
363                }
364                return false;
365        }
366        
367        /**
368         * Performs a full build for the project
369         * @param baseline the default baseline 
370         * @param wbaseline the workspace baseline
371         * @param monitor
372         */
373        void buildAll(IApiBaseline baseline, IApiBaseline wbaseline, IProgressMonitor monitor) throws CoreException {
374                SubMonitor localMonitor = SubMonitor.convert(monitor, BuilderMessages.api_analysis_on_0, 4);
375                try {
376                        BuildState.setLastBuiltState(this.currentproject, null);
377                        this.buildstate = new BuildState();
378                        localMonitor.subTask(NLS.bind(BuilderMessages.ApiAnalysisBuilder_initializing_analyzer, currentproject.getName()));
379                        cleanupMarkers(this.currentproject);
380                        IPluginModelBase currentModel = getCurrentModel();
381                        if (currentModel != null) {
382                                localMonitor.subTask(BuilderMessages.building_workspace_profile);
383                                Util.updateMonitor(localMonitor, 1);
384                                String id = currentModel.getBundleDescription().getSymbolicName();
385                                // Compatibility checks
386                                IApiComponent apiComponent = wbaseline.getApiComponent(id);
387                                if(apiComponent != null) {
388                                        getAnalyzer().analyzeComponent(this.buildstate, null, null, baseline, apiComponent, new BuildContext(), localMonitor.newChild(1));
389                                        Util.updateMonitor(localMonitor, 1);
390                                        createMarkers();
391                                        Util.updateMonitor(localMonitor, 1);
392                                }
393                        }
394                }
395                finally {
396                        if(localMonitor != null) {
397                                localMonitor.done();
398                        }
399                }
400        }
401        
402        /**
403         * Creates new markers are for the listing of problems added to this reporter.
404         * If no problems have been added to this reporter, or we are not running in the framework,
405         * no work is done.
406         */
407        protected void createMarkers() {
408                try {
409                        IResource manifest = Util.getManifestFile(this.currentproject);
410                        if(manifest != null)  {
411                                manifest.deleteMarkers(IApiMarkerConstants.VERSION_NUMBERING_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
412                        }
413                        this.currentproject.deleteMarkers(IApiMarkerConstants.DEFAULT_API_BASELINE_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
414                        this.currentproject.deleteMarkers(IApiMarkerConstants.API_COMPONENT_RESOLUTION_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
415                } catch (CoreException e) {
416                        ApiPlugin.log(e);
417                }
418                IApiProblem[] problems = getAnalyzer().getProblems();
419                String type = null;
420                for(int i = 0; i < problems.length; i++) {
421                        int category = problems[i].getCategory();
422                        type = getProblemTypeFromCategory(category, problems[i].getKind());
423                        if(type == null) {
424                                continue;
425                        }
426                        if(DEBUG) {
427                                System.out.println("creating marker for: "+problems[i].toString()); //$NON-NLS-1$
428                        }
429                        createMarkerForProblem(category, type, problems[i]);
430                }
431        }
432        
433        /**
434         * Returns the {@link IApiMarkerConstants} problem type given the 
435         * problem category
436         * @param category the problem category - see {@link IApiProblem} for problem categories
437         * @param kind the kind of the problem - see {@link IApiProblem} for problem kinds
438         * @return the problem type or <code>null</code>
439         */
440        String getProblemTypeFromCategory(int category, int kind) {
441                switch(category) {
442                        case IApiProblem.CATEGORY_API_COMPONENT_RESOLUTION : {
443                                return IApiMarkerConstants.API_COMPONENT_RESOLUTION_PROBLEM_MARKER;
444                        }
445                        case IApiProblem.CATEGORY_API_BASELINE: {
446                                return IApiMarkerConstants.DEFAULT_API_BASELINE_PROBLEM_MARKER;
447                        }
448                        case IApiProblem.CATEGORY_COMPATIBILITY: {
449                                return IApiMarkerConstants.COMPATIBILITY_PROBLEM_MARKER;
450                        }
451                        case IApiProblem.CATEGORY_SINCETAGS: {
452                                return IApiMarkerConstants.SINCE_TAGS_PROBLEM_MARKER;
453                        }
454                        case IApiProblem.CATEGORY_USAGE: {
455                                if(kind == IApiProblem.UNSUPPORTED_TAG_USE) {
456                                        return IApiMarkerConstants.UNSUPPORTED_TAG_PROBLEM_MARKER;
457                                }
458                                if(kind == IApiProblem.UNUSED_PROBLEM_FILTERS) {
459                                        return IApiMarkerConstants.UNUSED_FILTER_PROBLEM_MARKER;
460                                }
461                                return IApiMarkerConstants.API_USAGE_PROBLEM_MARKER;
462                        }
463                        case IApiProblem.CATEGORY_VERSION: {
464                                return IApiMarkerConstants.VERSION_NUMBERING_PROBLEM_MARKER;
465                        }
466                }
467                return null;
468        }
469 
470        /**
471         * Creates an {@link IMarker} on the resource specified
472         * in the problem (via its path) with the given problem
473         * attributes
474         * @param category the category of the problem - see {@link IApiProblem} for categories
475         * @param type the marker type to create - see {@link IApiMarkerConstants} for types
476         * @param problem the problem to create a marker from
477         */
478        void createMarkerForProblem(int category, String type, IApiProblem problem) {
479                IResource resource = resolveResource(problem);
480                if(resource == null) {
481                        return;
482                }
483                try {
484                        IMarker marker = resource.createMarker(type);
485                        int line = problem.getLineNumber();
486                        switch(category) {
487                                case IApiProblem.CATEGORY_VERSION :
488                                case IApiProblem.CATEGORY_API_BASELINE :
489                                case IApiProblem.CATEGORY_API_COMPONENT_RESOLUTION : {
490                                        break;
491                                }
492                                default : {
493                                        line++;
494                                }
495                        }
496                        marker.setAttributes(
497                                        new String[] {
498                                                        IMarker.MESSAGE,
499                                                        IMarker.SEVERITY,
500                                                        IMarker.LINE_NUMBER,
501                                                        IMarker.CHAR_START,
502                                                        IMarker.CHAR_END,
503                                                        IMarker.SOURCE_ID,
504                                                        IApiMarkerConstants.MARKER_ATTR_PROBLEM_ID},
505                                        new Object[] {
506                                                        problem.getMessage(),
507                                                        new Integer(ApiPlugin.getDefault().getSeverityLevel(ApiProblemFactory.getProblemSeverityId(problem), this.currentproject)),
508                                                        new Integer(line),
509                                                        new Integer(problem.getCharStart()),
510                                                        new Integer(problem.getCharEnd()),
511                                                        ApiAnalysisBuilder.SOURCE,
512                                                        new Integer(problem.getId())
513                                        }
514                                );
515                        //add message arguments, if any
516                        String[] args = problem.getMessageArguments();
517                        if(args.length > 0) {
518                                marker.setAttribute(IApiMarkerConstants.MARKER_ATTR_MESSAGE_ARGUMENTS, createArgAttribute(args));
519                        }
520                        String typeName = problem.getTypeName();
521                        if (typeName != null) {
522                                marker.setAttribute(IApiMarkerConstants.MARKER_ATTR_PROBLEM_TYPE_NAME, typeName);
523                        }
524                        //add all other extra arguments, if any
525                        if(problem.getExtraMarkerAttributeIds().length > 0) {
526                                marker.setAttributes(problem.getExtraMarkerAttributeIds(), problem.getExtraMarkerAttributeValues());
527                        }
528                } catch (CoreException e) {
529                        //ignore and continue
530                        return;
531                }
532        }
533        
534        /**
535         * Resolves the resource from the path in the problem, returns <code>null</code> in 
536         * the following cases: 
537         * <ul>
538         * <li>The resource is not found in the parent project (findMember() returns null)</li>
539         * <li>The resource is not accessible (isAccessible() returns false</li>
540         * </ul>
541         * @param problem the problem to get the resource for
542         * @return the resource or <code>null</code>
543         */
544        IResource resolveResource(IApiProblem problem) {
545                String resourcePath = problem.getResourcePath();
546                if (resourcePath == null) {
547                        return null;
548                }
549                IResource resource = currentproject.findMember(new Path(resourcePath));
550                if(resource == null) {
551                        return null;
552                }
553                if(!resource.isAccessible()) {
554                        return null;
555                }
556                return resource;
557        }
558        
559        /**
560         * Creates a single string attribute from an array of strings. Uses the '#' char as 
561         * a delimiter
562         * @param args
563         * @return a single string attribute from an array or arguments
564         */
565        String createArgAttribute(String[] args) {
566                StringBuffer buff = new StringBuffer();
567                for(int i = 0; i < args.length; i++) {
568                        buff.append(args[i]);
569                        if(i < args.length-1) {
570                                buff.append("#"); //$NON-NLS-1$
571                        }
572                }
573                return buff.toString();
574        }
575        
576        /* (non-Javadoc)
577         * @see org.eclipse.core.resources.IncrementalProjectBuilder#clean(org.eclipse.core.runtime.IProgressMonitor)
578         */
579        protected void clean(IProgressMonitor monitor) throws CoreException {
580                this.currentproject = getProject();
581                SubMonitor localmonitor = SubMonitor.convert(monitor, MessageFormat.format(BuilderMessages.CleaningAPIDescription, new String[] {this.currentproject.getName()}), 2);
582                try {
583                        // clean up all existing markers
584                        cleanupUsageMarkers(this.currentproject);
585                        cleanupCompatibilityMarkers(this.currentproject);
586                        cleanupUnsupportedTagMarkers(this.currentproject);
587                        this.currentproject.deleteMarkers(IApiMarkerConstants.UNUSED_FILTER_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
588                        Util.updateMonitor(localmonitor, 1);
589                        //clean up the .api_settings
590                        cleanupApiDescription(this.currentproject);
591                        Util.updateMonitor(localmonitor, 1);
592                }
593                finally {
594                        BuildState.setLastBuiltState(this.currentproject, null);
595                        localmonitor.done();
596                }
597        }
598 
599        /**
600         * Cleans the .api_settings file for the given project
601         * @param project
602         */
603        void cleanupApiDescription(IProject project) {
604                if(project != null && project.exists()) {
605                        ApiDescriptionManager.getDefault().clean(JavaCore.create(project), true, false);
606                }
607        }
608        
609        /**
610         * @return the current {@link IPluginModelBase} based on the current project for this builder
611         */
612        IPluginModelBase getCurrentModel() {
613                IPluginModelBase[] workspaceModels = PluginRegistry.getWorkspaceModels();
614                IPath location = this.currentproject.getLocation();
615                IPluginModelBase currentModel = null;
616                BundleDescription desc = null;
617                loop: for (int i = 0, max = workspaceModels.length; i < max; i++) {
618                        desc = workspaceModels[i].getBundleDescription();
619                        if(desc != null) {
620                                Path path = new Path(desc.getLocation());
621                                if (path.equals(location)) {
622                                        currentModel = workspaceModels[i];
623                                        break loop;
624                                }
625                        }
626                        else if(DEBUG) {
627                                System.out.println("Tried to look up bundle description for: " + workspaceModels[i].toString()); //$NON-NLS-1$
628                        }
629                }
630                return currentModel;
631        }
632 
633        /**
634         * Returns a listing of deltas for this project and for dependent projects
635         * @param projects
636         * @return
637         */
638        IResourceDelta[] getDeltas(IProject[] projects) {
639                if(DEBUG) {
640                        System.out.println("Searching for deltas for build of project: "+this.currentproject.getName()); //$NON-NLS-1$
641                }
642                ArrayList deltas = new ArrayList();
643                IResourceDelta delta = getDelta(this.currentproject);
644                if(delta != null) {
645                        if (DEBUG) {
646                                System.out.println("Found a delta: " + delta); //$NON-NLS-1$
647                        }
648                        deltas.add(delta);
649                }
650                for(int i = 0; i < projects.length; i++) {
651                        delta = getDelta(projects[i]);
652                        if(delta != null) {
653                                if (DEBUG) {
654                                        System.out.println("Found a delta: " + delta); //$NON-NLS-1$
655                                }
656                                deltas.add(delta);
657                        }
658                }
659                return (IResourceDelta[]) deltas.toArray(new IResourceDelta[deltas.size()]);
660        }
661 
662        /**
663         * Returns the API analyzer to use with this instance of the builder
664         * @return the API analyzer to use
665         */
666        protected synchronized IApiAnalyzer getAnalyzer() {
667                if(this.analyzer == null) {
668                        this.analyzer = new BaseApiAnalyzer();
669                }
670                return this.analyzer;
671        }
672        
673        /**
674         * Returns the complete listing of required projects from the classpath of the backing project
675         * @param includeBinaryPrerequisites
676         * @return the list of projects required 
677         * @throws CoreException
678         */
679        IProject[] getRequiredProjects(boolean includebinaries) throws CoreException {
680                IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
681                if (this.currentproject == null || workspaceRoot == null) { 
682                        return new IProject[0];
683                }
684                ArrayList projects = new ArrayList();
685                try {
686                        IJavaProject javaProject = JavaCore.create(this.currentproject);
687                        HashSet blocations = new HashSet();
688                        blocations.add(javaProject.getOutputLocation());
689                        this.output_locs.put(this.currentproject, blocations);
690                        HashSet slocations = new HashSet();
691                        IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
692                        for (int i = 0; i < roots.length; i++) {
693                                if(roots[i].isArchive()) {
694                                        continue;
695                                }
696                                slocations.add(roots[i].getPath());
697                        }
698                        this.src_locs.put(this.currentproject, slocations);
699                        IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
700                        for (int i = 0, l = entries.length; i < l; i++) {
701                                IClasspathEntry entry = entries[i];
702                                IPath path = entry.getPath();
703                                IProject p = null;
704                                switch (entry.getEntryKind()) {
705                                        case IClasspathEntry.CPE_PROJECT : {
706                                                p = workspaceRoot.getProject(path.lastSegment()); // missing projects are considered too
707                                                if (isOptional(entry) && !p.hasNature(ApiPlugin.NATURE_ID)) {// except if entry is optional 
708                                                        p = null;
709                                                }
710                                                break;
711                                        }
712                                        case IClasspathEntry.CPE_LIBRARY : {
713                                                if (includebinaries && path.segmentCount() > 1) {
714                                                        // some binary resources on the class path can come from projects that are not included in the project references
715                                                        IResource resource = workspaceRoot.findMember(path.segment(0));
716                                                        if (resource instanceof IProject) {
717                                                                p = (IProject) resource;
718                                                        }
719                                                }
720                                                break;
721                                        }
722                                        case IClasspathEntry.CPE_SOURCE: {
723                                                IPath entrypath = entry.getOutputLocation();
724                                                if(entrypath != null) {
725                                                        blocations.add(entrypath);
726                                                }
727                                        }
728                                }
729                                if (p != null && !projects.contains(p)) {
730                                        projects.add(p);
731                                        //try to derive all of the output locations for each of the projects
732                                        javaProject = JavaCore.create(p);
733                                        HashSet bins = new HashSet();
734                                        HashSet srcs = new HashSet();
735                                        if(javaProject.exists()) {
736                                                bins.add(javaProject.getOutputLocation());
737                                                IClasspathEntry[] source = javaProject.getRawClasspath();
738                                                IPath entrypath = null;
739                                                for(int j = 0; j < source.length; j++) {
740                                                        if(source[j].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
741                                                                srcs.add(source[j].getPath());
742                                                                entrypath = source[j].getOutputLocation();
743                                                                if(entrypath != null) {
744                                                                        bins.add(entrypath);
745                                                                }
746                                                        }
747                                                }
748                                                this.output_locs.put(p, bins);
749                                                this.src_locs.put(p, srcs);
750                                        }
751                                }
752                        }
753                } 
754                catch(JavaModelException e) {
755                        return new IProject[0];
756                }
757                IProject[] result = new IProject[projects.size()];
758                projects.toArray(result);
759                return result;
760        }
761        
762        /**
763         * Returns the output paths of the given project or <code>null</code> if none have been computed
764         * @param project
765         * @return the output paths for the given project or <code>null</code>
766         */
767        HashSet getProjectOutputPaths(IProject project) {
768                return (HashSet) this.output_locs.get(project);
769        }
770        
771        /**
772         * Returns is the given classpath entry is optional or not
773         * @param entry
774         * @return true if the specified {@link IClasspathEntry} is optional, false otherwise
775         */
776        boolean isOptional(IClasspathEntry entry) {
777                IClasspathAttribute[] attribs = entry.getExtraAttributes();
778                for (int i = 0, length = attribs.length; i < length; i++) {
779                        IClasspathAttribute attribute = attribs[i];
780                        if (IClasspathAttribute.OPTIONAL.equals(attribute.getName()) && "true".equals(attribute.getValue())) //$NON-NLS-1$
781                                return true;
782                }
783                return false;
784        }
785        
786        /* (non-Javadoc)
787         * @see java.lang.Object#toString()
788         */
789        public String toString() {
790                return NLS.bind(BuilderMessages.ApiAnalysisBuilder_builder_for_project, this.currentproject.getName());
791        }
792}

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