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 [ApiFilterStore.java]

nameclass, %method, %block, %line, %
ApiFilterStore.java100% (5/5)77%  (24/31)68%  (1214/1798)68%  (320.2/471)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ApiFilterStore$2100% (1/1)50%  (1/2)21%  (6/28)29%  (2/7)
compare (Object, Object): int 0%   (0/1)0%   (0/22)0%   (0/5)
ApiFilterStore$2 (ApiFilterStore): void 100% (1/1)100% (6/6)100% (2/2)
     
class ApiFilterStore$3100% (1/1)50%  (1/2)25%  (6/24)29%  (2/7)
compare (Object, Object): int 0%   (0/1)0%   (0/18)0%   (0/5)
ApiFilterStore$3 (ApiFilterStore): void 100% (1/1)100% (6/6)100% (2/2)
     
class ApiFilterStore$4100% (1/1)50%  (1/2)30%  (6/20)40%  (2/5)
compare (Object, Object): int 0%   (0/1)0%   (0/14)0%   (0/3)
ApiFilterStore$4 (ApiFilterStore): void 100% (1/1)100% (6/6)100% (2/2)
     
class ApiFilterStore$1100% (1/1)100% (2/2)48%  (73/153)62%  (24.3/39)
runInWorkspace (IProgressMonitor): IStatus 100% (1/1)45%  (66/146)60%  (22.3/37)
ApiFilterStore$1 (ApiFilterStore, String): void 100% (1/1)100% (7/7)100% (2/2)
     
class ApiFilterStore100% (1/1)83%  (19/23)71%  (1123/1573)71%  (296.8/420)
collectFilterFor (Set, String, Set): void 0%   (0/1)0%   (0/32)0%   (0/8)
getResources (): IResource [] 0%   (0/1)0%   (0/13)0%   (0/3)
setDebug (boolean): void 0%   (0/1)0%   (0/9)0%   (0/2)
toString (): String 0%   (0/1)0%   (0/10)0%   (0/1)
getUnusedFilters (IResource, String): IApiProblemFilter [] 100% (1/1)45%  (46/103)46%  (12/26)
recordFilterUsed (IResource, IApiProblemFilter): void 100% (1/1)50%  (12/24)57%  (4/7)
isFiltered (IApiProblem): boolean 100% (1/1)50%  (57/113)64%  (16/25)
addFiltersFor (IApiProblem []): void 100% (1/1)52%  (13/25)45%  (5/11)
resourceChanged (IResourceChangeEvent): void 100% (1/1)66%  (83/125)67%  (24.3/36)
loadIntegerAttribute (Element, String): int 100% (1/1)71%  (12/17)57%  (4/7)
removeFilters (IApiProblemFilter []): boolean 100% (1/1)74%  (105/141)75%  (26.9/36)
initializeApiFilters (): void 100% (1/1)77%  (244/318)72%  (62.4/87)
addFilters (IApiProblemFilter []): void 100% (1/1)78%  (83/107)70%  (21/30)
getStoreAsXml (): String 100% (1/1)79%  (190/239)78%  (45.3/58)
internalAddFilters (IApiProblem [], boolean): void 100% (1/1)83%  (86/104)78%  (21/27)
persistApiFilters (): void 100% (1/1)95%  (18/19)86%  (6/7)
<static initializer> 100% (1/1)100% (6/6)100% (3/3)
ApiFilterStore (IJavaProject): void 100% (1/1)100% (26/26)100% (10/10)
clearFilters (): void 100% (1/1)100% (10/10)100% (4/4)
dispose (): void 100% (1/1)100% (15/15)100% (6/6)
getFilterFilePath (boolean): IPath 100% (1/1)100% (19/19)100% (4/4)
getFilters (IResource): IApiProblemFilter [] 100% (1/1)100% (39/39)100% (9/9)
recordFilterUsage (): void 100% (1/1)100% (59/59)100% (13/13)

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.io.IOException;
14import java.io.InputStream;
15import java.util.ArrayList;
16import java.util.Collection;
17import java.util.Collections;
18import java.util.Comparator;
19import java.util.HashMap;
20import java.util.HashSet;
21import java.util.Iterator;
22import java.util.List;
23import java.util.Map;
24import java.util.Set;
25 
26import org.eclipse.core.resources.IFile;
27import org.eclipse.core.resources.IFolder;
28import org.eclipse.core.resources.IProject;
29import org.eclipse.core.resources.IResource;
30import org.eclipse.core.resources.IResourceChangeEvent;
31import org.eclipse.core.resources.IResourceChangeListener;
32import org.eclipse.core.resources.IResourceDelta;
33import org.eclipse.core.resources.IncrementalProjectBuilder;
34import org.eclipse.core.resources.ResourcesPlugin;
35import org.eclipse.core.resources.WorkspaceJob;
36import org.eclipse.core.runtime.Assert;
37import org.eclipse.core.runtime.CoreException;
38import org.eclipse.core.runtime.IPath;
39import org.eclipse.core.runtime.IProgressMonitor;
40import org.eclipse.core.runtime.IStatus;
41import org.eclipse.core.runtime.Path;
42import org.eclipse.core.runtime.Status;
43import org.eclipse.core.runtime.SubMonitor;
44import org.eclipse.core.runtime.jobs.Job;
45import org.eclipse.jdt.core.IJavaProject;
46import org.eclipse.pde.api.tools.internal.problems.ApiProblemFactory;
47import org.eclipse.pde.api.tools.internal.problems.ApiProblemFilter;
48import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
49import org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore;
50import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem;
51import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemFilter;
52import org.eclipse.pde.api.tools.internal.util.Util;
53import org.w3c.dom.Document;
54import org.w3c.dom.Element;
55import org.w3c.dom.NodeList;
56 
57/**
58 * Base implementation of a filter store for Api components
59 * 
60 * @since 1.0.0
61 */
62public class ApiFilterStore implements IApiFilterStore, IResourceChangeListener {
63        /**
64         * Constant representing the name of the .settings folder
65         */
66        private static final String SETTINGS_FOLDER = ".settings"; //$NON-NLS-1$
67        public static final String GLOBAL = "!global!"; //$NON-NLS-1$
68        public static final int CURRENT_STORE_VERSION = 2;
69        /**
70         * Constant used for controlling tracing in the plug-in workspace component
71         */
72        static boolean DEBUG = Util.DEBUG;
73        
74        /**
75         * Method used for initializing tracing in the plug-in workspace component
76         */
77        public static void setDebug(boolean debugValue) {
78                DEBUG = debugValue || Util.DEBUG;
79        }
80        /**
81         * Represents no filters
82         */
83        private static IApiProblemFilter[] NO_FILTERS = new IApiProblemFilter[0];
84        
85        /**
86         * The mapping of filters for this store.
87         * <pre>
88         * HashMap<IResource, HashSet<IApiProblemFilter>>
89         * </pre>
90         */
91        private HashMap fFilterMap = null;
92        
93        /**
94         * Map used to collect unused {@link IApiProblemFilter}s
95         */
96        private HashMap fUnusedFilters = null;
97        
98        /**
99         * The backing {@link IJavaProject}
100         */
101        IJavaProject fProject = null;
102        
103        boolean fNeedsSaving = false;
104        boolean fTriggeredChange = false;
105        
106        /**
107         * Constructor
108         * @param owningComponent the id of the component that owns this filter store
109         */
110        public ApiFilterStore(IJavaProject project) {
111                Assert.isNotNull(project);
112                fProject = project;
113                ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
114        }
115        
116        /**
117         * Saves the .api_filters file for the component
118         * @throws IOException 
119         */
120        private void persistApiFilters() {
121                if(!fNeedsSaving) {
122                        return;
123                }
124                WorkspaceJob job = new WorkspaceJob(Util.EMPTY_STRING) {
125                        public IStatus runInWorkspace(IProgressMonitor monitor)        throws CoreException {
126                                if(DEBUG) {
127                                        System.out.println("persisting api filters for plugin project component ["+fProject.getElementName()+"]"); //$NON-NLS-1$ //$NON-NLS-2$
128                                }
129                                try {
130                                        SubMonitor localmonitor = SubMonitor.convert(monitor);
131                                        IProject project = fProject.getProject();
132                                        if(!project.isAccessible()) {
133                                                if(DEBUG) {
134                                                        System.out.println("project ["+fProject.getElementName()+"] is not accessible, saving termainated"); //$NON-NLS-1$ //$NON-NLS-2$
135                                                }
136                                                return Status.CANCEL_STATUS;
137                                        }
138                                        String xml = getStoreAsXml();
139                                        IFile file = project.getFile(getFilterFilePath(false));
140                                        if(xml == null) {
141                                                // no filters - delete the file if it exists
142                                                if (file.isAccessible()) {
143                                                        IFolder folder = (IFolder) file.getParent();
144                                                        file.delete(true, localmonitor);
145                                                        if(folder.members().length == 0 && folder.isAccessible()) {
146                                                                folder.delete(true, localmonitor);
147                                                        }
148                                                        fTriggeredChange = true;
149                                                }
150                                                return Status.OK_STATUS;
151                                        }
152                                        InputStream xstream = Util.getInputStreamFromString(xml);
153                                        if(xstream == null) {
154                                                return Status.CANCEL_STATUS;
155                                        }
156                                        try {
157                                                if(!file.exists()) {
158                                                        IFolder folder = (IFolder) file.getParent();
159                                                        if(!folder.exists()) {
160                                                                folder.create(true, true, localmonitor);
161                                                        }
162                                                        file.create(xstream, true, localmonitor);
163                                                }
164                                                else {
165                                                        file.setContents(xstream, true, false, localmonitor);
166                                                }
167                                        }
168                                        finally {
169                                                xstream.close();
170                                        }
171                                        fTriggeredChange = true;
172                                        fNeedsSaving = false;
173                                }
174                                catch(CoreException ce) {
175                                        ApiPlugin.log(ce);
176                                }
177                                catch (IOException ioe) {
178                                        ApiPlugin.log(ioe);        
179                                }
180                                return Status.OK_STATUS;
181                        }
182                };
183                job.setSystem(true);
184                job.setPriority(Job.INTERACTIVE);
185                job.schedule();
186        }
187 
188        /* (non-Javadoc)
189         * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#addFilters(org.eclipse.pde.api.tools.internal.provisional.IApiProblemFilter[])
190         */
191        public synchronized void addFilters(IApiProblemFilter[] filters) {
192                if(filters == null) {
193                        if(DEBUG) {
194                                System.out.println("null filters array, not adding filters"); //$NON-NLS-1$
195                        }
196                        return;
197                }
198                initializeApiFilters();
199                for(int i = 0; i < filters.length; i++) {
200                        IApiProblem problem = filters[i].getUnderlyingProblem();
201                        String resourcePath = problem.getResourcePath();
202                        if (resourcePath == null) {
203                                continue;
204                        }
205                        IResource resource = fProject.getProject().findMember(new Path(resourcePath));
206                        if(resource == null) {
207                                continue;
208                        }
209                        Map pTypeNames = (HashMap) fFilterMap.get(resource);
210                        String typeName = problem.getTypeName();
211                        if (typeName == null) {
212                                typeName = GLOBAL;
213                        }
214                        Set pfilters = null;
215                        if(pTypeNames == null) {
216                                pTypeNames = new HashMap();
217                                pfilters = new HashSet();
218                                pTypeNames.put(typeName, pfilters);
219                                fFilterMap.put(resource, pTypeNames);
220                        } else {
221                                pfilters = (Set) pTypeNames.get(typeName);
222                                if (pfilters == null) {
223                                        pfilters = new HashSet();
224                                        pTypeNames.put(typeName, pfilters);
225                                }
226                        }
227                        fNeedsSaving |= pfilters.add(filters[i]);
228                }
229                persistApiFilters();
230        }
231        
232        /* (non-Javadoc)
233         * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#addFilters(org.eclipse.pde.api.tools.internal.provisional.IApiProblem[])
234         */
235        public synchronized void addFiltersFor(IApiProblem[] problems) {
236                if(problems == null) {
237                        if(DEBUG) {
238                                System.out.println("null problems array: not addding filters"); //$NON-NLS-1$
239                        }
240                        return;
241                }
242                if(problems.length < 1) {
243                        if(DEBUG) {
244                                System.out.println("empty problem array: not addding filters"); //$NON-NLS-1$
245                        }
246                        return;
247                }
248                initializeApiFilters();
249                internalAddFilters(problems, true);
250        }
251 
252        /* (non-Javadoc)
253         * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#getFilters(org.eclipse.core.resources.IResource)
254         */
255        public synchronized IApiProblemFilter[] getFilters(IResource resource) {
256                initializeApiFilters();
257                Map pTypeNames = (Map) fFilterMap.get(resource);
258                if(pTypeNames == null) {
259                        return NO_FILTERS;
260                }
261                List allFilters = new ArrayList();
262                for (Iterator iterator = pTypeNames.values().iterator(); iterator.hasNext(); ) {
263                        Set values = (Set) iterator.next();
264                        allFilters.addAll(values);
265                }
266                return (IApiProblemFilter[]) allFilters.toArray(new IApiProblemFilter[allFilters.size()]);
267        }
268        
269        /* (non-Javadoc)
270         * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#isFiltered(org.eclipse.pde.api.tools.internal.provisional.IApiProblem)
271         */
272        public synchronized boolean isFiltered(IApiProblem problem) {
273                initializeApiFilters();
274                String resourcePath = problem.getResourcePath();
275                if (resourcePath == null) {
276                        return false;
277                }
278                IResource resource = fProject.getProject().findMember(new Path(resourcePath));
279                if(resource == null) {
280                        if(DEBUG) {
281                                System.out.println("no resource exists: ["+resourcePath+"]"); //$NON-NLS-1$ //$NON-NLS-2$
282                        }
283                        return false;
284                }
285                IApiProblemFilter[] filters = this.getFilters(resource);
286                if(filters == null) {
287                        if(DEBUG) {
288                                System.out.println("no filters defined for ["+resourcePath+"] return not filtered"); //$NON-NLS-1$ //$NON-NLS-2$
289                        }
290                        return false;
291                }
292                IApiProblemFilter filter = null;
293                for(int i = 0, max = filters.length; i < max; i++) {
294                        filter = filters[i];
295                        if(filter.getUnderlyingProblem().equals(problem)) {
296                                if(DEBUG) {
297                                        System.out.println("recording filter used: ["+filter.toString()+"]"); //$NON-NLS-1$ //$NON-NLS-2$
298                                }
299                                recordFilterUsed(resource, filter);
300                                return true;
301                        }
302                }
303                if(DEBUG) {
304                        System.out.println("no filter defined for problem: ["+problem.toString()+"]"); //$NON-NLS-1$ //$NON-NLS-2$
305                }
306                return false;
307        }
308        
309        /* (non-Javadoc)
310         * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#dispose()
311         */
312        public void dispose() {
313                clearFilters();
314                if(fUnusedFilters != null) {
315                        fUnusedFilters.clear();
316                        fUnusedFilters = null;
317                }
318                 ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
319        }
320        
321        /* (non-Javadoc)
322         * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#getResources()
323         */
324        public synchronized IResource[] getResources() {
325                initializeApiFilters();
326                Collection resources = fFilterMap.keySet();
327                return (IResource[]) resources.toArray(new IResource[resources.size()]);
328        }
329        
330        /* (non-Javadoc)
331         * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#removeFilters(org.eclipse.pde.api.tools.internal.provisional.IApiProblemFilter[])
332         */
333        public synchronized boolean removeFilters(IApiProblemFilter[] filters) {
334                if(filters == null) {
335                        if(DEBUG) {
336                                System.out.println("null filters array, not removing"); //$NON-NLS-1$
337                        }
338                        return false;
339                }
340                if(fFilterMap == null) {
341                        if(DEBUG) {
342                                System.out.println("null filter map, not removing"); //$NON-NLS-1$
343                        }
344                        return false;
345                }
346                boolean success = true;
347                for(int i = 0; i < filters.length; i++) {
348                        IApiProblem underlyingProblem = filters[i].getUnderlyingProblem();
349                        String resourcePath = underlyingProblem.getResourcePath();
350                        if (resourcePath == null) {
351                                continue;
352                        }
353                        IResource resource = fProject.getProject().findMember(new Path(resourcePath));
354                        if(resource == null) {
355                                resource = fProject.getProject().getFile(resourcePath);
356                        }
357                        Map pTypeNames = (Map) fFilterMap.get(resource);
358                        if (pTypeNames == null) {
359                                continue;
360                        }
361                        String typeName = underlyingProblem.getTypeName();
362                        if (typeName == null) {
363                                typeName = GLOBAL;
364                        }
365                        Set pfilters = (Set) pTypeNames.get(typeName);
366                        if(pfilters != null && pfilters.remove(filters[i])) {
367                                if(DEBUG) {
368                                        System.out.println("removed filter: ["+filters[i]+"]"); //$NON-NLS-1$ //$NON-NLS-2$
369                                }
370                                fNeedsSaving |= true;
371                                success &= true;
372                                if(pfilters.isEmpty()) {
373                                        pTypeNames.remove(typeName);
374                                        if (pTypeNames.isEmpty()) {
375                                                success &= fFilterMap.remove(resource) != null;
376                                        }
377                                }
378                        } else {
379                                success &= false;
380                        }
381                }
382                persistApiFilters();
383                return success;
384        }
385        
386        /**
387         * Converts the information contained in this filter store to an xml string
388         * @return an xml string representation of this filter store
389         * @throws CoreException
390         */
391        synchronized String getStoreAsXml() throws CoreException {
392                if(fFilterMap == null) {
393                        return null;
394                }
395                if(fFilterMap.isEmpty()) {
396                        return null;
397                }
398                Document document = Util.newDocument();
399                Element root = document.createElement(IApiXmlConstants.ELEMENT_COMPONENT);
400                document.appendChild(root);
401                root.setAttribute(IApiXmlConstants.ATTR_ID, fProject.getElementName());
402                root.setAttribute(IApiXmlConstants.ATTR_VERSION, IApiXmlConstants.API_FILTER_STORE_CURRENT_VERSION);
403                Set allFiltersEntrySet = fFilterMap.entrySet();
404                List allFiltersEntries = new ArrayList(allFiltersEntrySet.size());
405                allFiltersEntries.addAll(allFiltersEntrySet);
406                Collections.sort(allFiltersEntries, new Comparator() {
407                        public int compare(Object o1, Object o2) {
408                                Map.Entry entry1 = (Map.Entry) o1;
409                                Map.Entry entry2 = (Map.Entry) o2;
410                                String path1 = ((IResource) entry1.getKey()).getProjectRelativePath().toOSString();
411                                String path2 = ((IResource) entry2.getKey()).getProjectRelativePath().toOSString();
412                                return path1.compareTo(path2);
413                        }
414                });
415                for(Iterator iter = allFiltersEntries.iterator(); iter.hasNext();) {
416                        Map.Entry allFiltersEntry = (Map.Entry) iter.next();
417                        IResource resource = (IResource) allFiltersEntry.getKey();
418                        Map pTypeNames = (Map) allFiltersEntry.getValue();
419                        if(pTypeNames == null) {
420                                continue;
421                        }
422                        Set allTypeNamesEntriesSet = pTypeNames.entrySet();
423                        List allTypeNamesEntries = new ArrayList(allTypeNamesEntriesSet.size());
424                        allTypeNamesEntries.addAll(allTypeNamesEntriesSet);
425                        Collections.sort(allTypeNamesEntries, new Comparator() {
426                                public int compare(Object o1, Object o2) {
427                                        Map.Entry entry1 = (Map.Entry) o1;
428                                        Map.Entry entry2 = (Map.Entry) o2;
429                                        String typeName1 = (String) entry1.getKey();
430                                        String typeName2 = (String) entry2.getKey();
431                                        return typeName1.compareTo(typeName2);
432                                }
433                        });
434                        for (Iterator iterator = allTypeNamesEntries.iterator(); iterator.hasNext(); ) {
435                                Map.Entry entry = (Map.Entry) iterator.next();
436                                String typeName = (String) entry.getKey();
437                                Set filters = (Set) entry.getValue();
438                                if(filters.isEmpty()) {
439                                        continue;
440                                }
441                                Element relement = document.createElement(IApiXmlConstants.ELEMENT_RESOURCE);
442                                relement.setAttribute(IApiXmlConstants.ATTR_PATH, resource.getProjectRelativePath().toPortableString());
443                                boolean typeNameIsInitialized = false;
444                                if (typeName != GLOBAL) {
445                                        relement.setAttribute(IApiXmlConstants.ATTR_TYPE, typeName);
446                                        typeNameIsInitialized = true;
447                                }
448                                root.appendChild(relement);
449                                typeName = null;
450                                List filtersList = new ArrayList(filters.size());
451                                filtersList.addAll(filters);
452                                Collections.sort(filtersList, new Comparator(){
453                                        public int compare(Object o1, Object o2) {
454                                                int problem1Id = ((IApiProblemFilter) o1).getUnderlyingProblem().getId();
455                                                int problem2Id = ((IApiProblemFilter) o2).getUnderlyingProblem().getId();
456                                                return problem1Id - problem2Id;
457                                        }
458                                });
459                                for(Iterator iterator2 = filtersList.iterator(); iterator2.hasNext(); ) {
460                                        IApiProblem problem = ((IApiProblemFilter) iterator2.next()).getUnderlyingProblem();
461                                        typeName = problem.getTypeName();
462                                        Element filterElement = document.createElement(IApiXmlConstants.ELEMENT_FILTER);
463                                        filterElement.setAttribute(IApiXmlConstants.ATTR_ID, Integer.toString(problem.getId()));
464                                        String[] messageArguments = problem.getMessageArguments();
465                                        int length = messageArguments.length;
466                                        if(length > 0) {
467                                                Element messageArgumentsElement = document.createElement(IApiXmlConstants.ELEMENT_PROBLEM_MESSAGE_ARGUMENTS);
468                                                for (int j = 0; j < length; j++) {
469                                                        Element messageArgumentElement = document.createElement(IApiXmlConstants.ELEMENT_PROBLEM_MESSAGE_ARGUMENT);
470                                                        messageArgumentElement.setAttribute(IApiXmlConstants.ATTR_VALUE, String.valueOf(messageArguments[j]));
471                                                        messageArgumentsElement.appendChild(messageArgumentElement);
472                                                }
473                                                filterElement.appendChild(messageArgumentsElement);
474                                        }
475                                        relement.appendChild(filterElement);
476                                }
477                                if (typeName != null && !typeNameIsInitialized && typeName.length() != 0) {
478                                        relement.setAttribute(IApiXmlConstants.ATTR_TYPE, typeName);
479                                }
480                        }
481                }
482                return Util.serializeDocument(document);
483        }
484 
485        /**
486         * Initializes the backing filter map for this store from the .api_filters file. Does nothing if the filter store has already been
487         * initialized.
488         */
489        private synchronized void initializeApiFilters() {
490                if(fFilterMap != null) {
491                        return;
492                }
493                if(DEBUG) {
494                        System.out.println("initializing api filter map for project ["+fProject.getElementName()+"]"); //$NON-NLS-1$ //$NON-NLS-2$
495                }
496                fFilterMap = new HashMap(5);
497                IPath filepath = getFilterFilePath(true);
498                IResource file = ResourcesPlugin.getWorkspace().getRoot().findMember(filepath, true);
499                if(file == null) {
500                        if(DEBUG) {
501                                System.out.println(".api_filter file not found during initialization for project ["+fProject.getElementName()+"]"); //$NON-NLS-1$ //$NON-NLS-2$
502                        }
503                        return;
504                }
505                String xml = null;
506                InputStream contents = null;
507                try {
508                        IFile filterFile = (IFile)file;
509                        if (filterFile.exists()) {
510                                contents = filterFile.getContents();
511                                xml = new String(Util.getInputStreamAsCharArray(contents, -1, IApiCoreConstants.UTF_8));
512                        }
513                }
514                catch(CoreException e) {
515                        ApiPlugin.log(e);
516                }
517                catch(IOException e) {
518                        ApiPlugin.log(e);
519                }
520                finally {
521                        if (contents != null) {
522                                try {
523                                        contents.close();
524                                } catch(IOException e) {
525                                        // ignore
526                                }
527                        }
528                }
529                if(xml == null) {
530                        return;
531                }
532                Element root = null;
533                try {
534                        root = Util.parseDocument(xml);
535                }
536                catch(CoreException ce) {
537                        ApiPlugin.log(ce);
538                }
539                if (root == null) {
540                        return;
541                }
542                if (!root.getNodeName().equals(IApiXmlConstants.ELEMENT_COMPONENT)) {
543                        return;
544                }
545                String component = root.getAttribute(IApiXmlConstants.ATTR_ID);
546                if(component.length() == 0) {
547                        return;
548                }
549                String versionValue = root.getAttribute(IApiXmlConstants.ATTR_VERSION);
550                int currentVersion = Integer.parseInt(IApiXmlConstants.API_FILTER_STORE_CURRENT_VERSION);
551                int version = 0;
552                if(versionValue.length() != 0) {
553                        try {
554                                version = Integer.parseInt(versionValue);
555                        } catch (NumberFormatException e) {
556                                // ignore
557                        }
558                }
559                if (version != currentVersion) {
560                        // we discard all filters since there is no way to retrieve the type name
561                        fNeedsSaving = true;
562                        persistApiFilters();
563                        return;
564                }
565                NodeList resources = root.getElementsByTagName(IApiXmlConstants.ELEMENT_RESOURCE);
566                ArrayList newfilters = new ArrayList();
567                for(int i = 0; i < resources.getLength(); i++) {
568                        Element element = (Element) resources.item(i);
569                        String path = element.getAttribute(IApiXmlConstants.ATTR_PATH);
570                        if(path.length() == 0) {
571                                continue;
572                        }
573                        String typeName = element.getAttribute(IApiXmlConstants.ATTR_TYPE);
574                        if (typeName.length() == 0) {
575                                typeName = null;
576                        }
577                        IProject project = (IProject) ResourcesPlugin.getWorkspace().getRoot().findMember(component);
578                        if(project == null) {
579                                continue;
580                        }
581                        IResource resource = project.findMember(new Path(path));
582                        if(resource == null) {
583                                continue;
584                        }
585                        NodeList filters = element.getElementsByTagName(IApiXmlConstants.ELEMENT_FILTER);
586                        for(int j = 0; j < filters.getLength(); j++) {
587                                element = (Element) filters.item(j);
588                                int id = loadIntegerAttribute(element, IApiXmlConstants.ATTR_ID);
589                                if(id <= 0) {
590                                        continue;
591                                }
592                                String[] messageargs = null;
593                                NodeList elements = element.getElementsByTagName(IApiXmlConstants.ELEMENT_PROBLEM_MESSAGE_ARGUMENTS);
594                                if (elements.getLength() != 1) continue;
595                                Element messageArguments = (Element) elements.item(0);
596                                NodeList arguments = messageArguments.getElementsByTagName(IApiXmlConstants.ELEMENT_PROBLEM_MESSAGE_ARGUMENT);
597                                int length = arguments.getLength();
598                                messageargs = new String[length];
599                                for (int k = 0; k < length; k++) {
600                                        Element messageArgument = (Element) arguments.item(k);
601                                        messageargs[k] = messageArgument.getAttribute(IApiXmlConstants.ATTR_VALUE);
602                                }
603                                newfilters.add(ApiProblemFactory.newApiProblem(resource.getProjectRelativePath().toPortableString(),
604                                                typeName,
605                                                messageargs, null, null, -1, -1, -1, id));
606                        }
607                }
608                internalAddFilters((IApiProblem[]) newfilters.toArray(new IApiProblem[newfilters.size()]), false);
609                newfilters.clear();
610        }
611        
612        /**
613         * Internal use method that allows auto-persisting of the filter file to be turned on or off
614         * @param problems the problems to add the the store
615         * @param persist if the filters should be auto-persisted after they are added
616         */
617        private synchronized void internalAddFilters(IApiProblem[] problems, boolean persist) {
618                Set filters = null;
619                for(int i = 0; i < problems.length; i++) {
620                        IApiProblem problem = problems[i];
621                        IApiProblemFilter filter = new ApiProblemFilter(fProject.getElementName(), problem);
622                        String resourcePath = problem.getResourcePath();
623                        if (resourcePath == null) {
624                                continue;
625                        }
626                        IResource resource = fProject.getProject().findMember(new Path(resourcePath));
627                        if(resource == null) {
628                                continue;
629                        }
630                        Map pTypeNames = (Map) fFilterMap.get(resource);
631                        String typeName = problem.getTypeName();
632                        if (typeName == null) {
633                                typeName = GLOBAL;
634                        }
635                        if(pTypeNames == null) {
636                                filters = new HashSet();
637                                pTypeNames = new HashMap();
638                                pTypeNames.put(typeName, filters);
639                                fFilterMap.put(resource, pTypeNames);
640                        } else {
641                                filters = (Set) pTypeNames.get(typeName);
642                                if (filters == null) {
643                                        filters = new HashSet();
644                                        pTypeNames.put(typeName, filters);
645                                }
646                        }
647                        fNeedsSaving |= filters.add(filter);
648                }
649                if(persist) {
650                        persistApiFilters();
651                }
652        }
653        /**
654         * Loads the specified integer attribute from the given xml element
655         * @param element
656         * @param name
657         * @return
658         */
659        private static int loadIntegerAttribute(Element element, String name) {
660                String value = element.getAttribute(name);
661                if(value.length() == 0) {
662                        return -1;
663                }
664                try {
665                        int number = Integer.parseInt(value);
666                        return number;
667                }
668                catch(NumberFormatException nfe) {}
669                return -1;
670        }
671        /**
672         * @return the {@link IPath} to the filters file
673         */
674        IPath getFilterFilePath(boolean includeproject) {
675                if(includeproject) {
676                        IPath path = fProject.getPath();
677                        return path.append(SETTINGS_FOLDER).append(IApiCoreConstants.API_FILTERS_XML_NAME);
678                }
679                return new Path(SETTINGS_FOLDER).append(IApiCoreConstants.API_FILTERS_XML_NAME);
680        }
681        /**
682         * Start recording filter usage for this store.
683         */
684        public synchronized void recordFilterUsage() {
685                initializeApiFilters();
686                fUnusedFilters = new HashMap();
687                IResource resource = null;
688                Map types = null;
689                Set values = null;
690                for(Iterator iter = fFilterMap.keySet().iterator(); iter.hasNext();) {
691                        resource = (IResource) iter.next();
692                        types = (Map) fFilterMap.get(resource);
693                        values = new HashSet();
694                        fUnusedFilters.put(resource, values);
695                        for(Iterator iter2 = types.keySet().iterator(); iter2.hasNext();) {
696                                values.addAll((Set) types.get(iter2.next()));
697                        }
698                }
699        }
700        
701        /**
702         * records that the following filter has been used
703         * @param resource
704         * @param filter
705         */
706        private void recordFilterUsed(IResource resource, IApiProblemFilter filter) {
707                if(fUnusedFilters != null) {
708                        Set unused = (Set) fUnusedFilters.get(resource);
709                        if(unused != null) {
710                                unused.remove(filter);
711                                if(unused.isEmpty()) {
712                                        fUnusedFilters.remove(resource);
713                                }
714                        }
715                }
716        }
717        
718        /**
719         * Returns all of the unused filters for this store at the moment in time this
720         * method is called.
721         * @return the listing of currently unused filters or an empty list, never <code>null</code>
722         */
723        public IApiProblemFilter[] getUnusedFilters(IResource resource, String typeName) {
724                if(fUnusedFilters != null) {
725                        Set unused = new HashSet();
726                        Set set = null;
727                        if(resource != null) {
728                                // add any unused filters for the resource
729                                set = (Set) fUnusedFilters.get(resource);
730                                if (set != null) {
731                                        collectFilterFor(set, typeName, unused);
732                                }
733                                if(Util.isManifest(resource.getProjectRelativePath())) {
734                                        //we need to add any filters that are cached for resources
735                                        //that no longer exist - deleted types
736                                        //deleted types are only ever passed in with the manifest associated with them
737                                        IResource res = null;
738                                        for (Iterator iter = fUnusedFilters.keySet().iterator(); iter.hasNext();) {
739                                                res = (IResource) iter.next();
740                                                if(res.exists()) {
741                                                        continue;
742                                                }
743                                                if(!res.getProject().equals(resource.getProject())) {
744                                                        continue;
745                                                }
746                                                set = (Set)fUnusedFilters.get(res);
747                                                collectFilterFor(set, typeName, unused);
748                                        }
749                                }
750                        }
751                        else {
752                                for(Iterator iter = fUnusedFilters.keySet().iterator(); iter.hasNext();) {
753                                        set = (Set) fUnusedFilters.get(iter.next());
754                                        if(set != null) {
755                                                unused.addAll(set);
756                                        }
757                                }
758                        }
759                        int size = unused.size();
760                        if (size == 0) {
761                                return NO_FILTERS;
762                        }
763                        return (IApiProblemFilter[]) unused.toArray(new IApiProblemFilter[size]);
764                }
765                return NO_FILTERS;
766        }
767        
768        private void collectFilterFor(Set filters, String typename, Set collector) {
769                for (Iterator iter = filters.iterator(); iter.hasNext();) {
770                        ApiProblemFilter filter = (ApiProblemFilter) iter.next();
771                        IApiProblem underlyingProblem = filter.getUnderlyingProblem();
772                        if (underlyingProblem != null) {
773                                String underlyingTypeName = underlyingProblem.getTypeName();
774                                if (underlyingTypeName != null && (typename == null || underlyingTypeName.equals(typename))) {
775                                        collector.add(filter);
776                                }
777                        }
778                }
779        }
780        
781        /* (non-Javadoc)
782         * @see java.lang.Object#toString()
783         */
784        public String toString() {
785                return "Api filter store for component: "+fProject.getElementName(); //$NON-NLS-1$
786        }
787 
788        /* (non-Javadoc)
789         * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
790         */
791        public void resourceChanged(IResourceChangeEvent event) {
792                if(fTriggeredChange) {
793                        //eat the event if the deletion / addition / change occurred because we persisted the file
794                        //via the persistApiFilters(..) method
795                        //see https://bugs.eclipse.org/bugs/show_bug.cgi?id=222442
796                        fTriggeredChange = false;
797                        if(DEBUG) {
798                                System.out.println("ignoring trigered change"); //$NON-NLS-1$
799                        }
800                        return;
801                }
802                if(event.getType() == IResourceChangeEvent.POST_CHANGE) {
803                        IPath path = getFilterFilePath(true);
804                        IResourceDelta leafdelta = event.getDelta().findMember(path);
805                        if(leafdelta == null) {
806                                return;
807                        }
808                        boolean needsbuild = false;
809                        if(leafdelta.getKind() == IResourceDelta.REMOVED) {
810                                if(DEBUG) {
811                                        System.out.println("processed REMOVED delta"); //$NON-NLS-1$
812                                }
813                                if(fFilterMap != null) {
814                                        fFilterMap.clear();
815                                        needsbuild = true;
816                                }
817                        }
818                        else if(leafdelta.getKind() == IResourceDelta.ADDED || 
819                                        (leafdelta.getFlags() & IResourceDelta.CONTENT) != 0 || 
820                                        (leafdelta.getFlags() & IResourceDelta.REPLACED) != 0) {
821                                if(DEBUG) {
822                                        System.out.println("processing ADDED or CONTENT or REPLACED"); //$NON-NLS-1$
823                                }
824                                IResource resource = leafdelta.getResource();
825                                if(resource != null && resource.getType() == IResource.FILE) {
826                                        if(DEBUG) {
827                                                System.out.println("processed FILE delta for ["+resource.getName()+"]"); //$NON-NLS-1$ //$NON-NLS-2$
828                                        }
829                                        IFile file = (IFile) resource;
830                                        if(file.isAccessible()) {
831                                                try {
832                                                        clearFilters();
833                                                        initializeApiFilters();
834                                                }
835                                                finally {
836                                                        needsbuild = true;
837                                                }
838                                        }
839                                }
840                        }
841                        if(needsbuild && ResourcesPlugin.getWorkspace().isAutoBuilding()) {
842                                Util.getBuildJob(new IProject[] {fProject.getProject()}, IncrementalProjectBuilder.INCREMENTAL_BUILD).schedule();
843                        }
844                }
845        }
846 
847        /**
848         * Clears out the filter map
849         */
850        private synchronized void clearFilters() {
851                if(fFilterMap != null) {
852                        fFilterMap.clear();
853                        fFilterMap = null; 
854                }
855        }
856}

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