diff options
author | Michael Rennie | 2012-12-20 22:45:09 +0000 |
---|---|---|
committer | Curtis Windatt | 2012-12-20 22:45:09 +0000 |
commit | 17e890b63cb6edbae2612ebbeefca79754f141fc (patch) | |
tree | 0fdc9b6c0456a497ece4688db7dbe14760de4d56 | |
parent | 3f9ffa6aaa32747e6c38963ef089ae1d9fdc10f5 (diff) | |
download | eclipse.pde.ui-17e890b63cb6edbae2612ebbeefca79754f141fc.tar.gz eclipse.pde.ui-17e890b63cb6edbae2612ebbeefca79754f141fc.tar.xz eclipse.pde.ui-17e890b63cb6edbae2612ebbeefca79754f141fc.zip |
Bug 332772 - Support problem filters for API Use Scan Task
10 files changed, 643 insertions, 511 deletions
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiFilterStore.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiFilterStore.java index 0b6bafe755..2c300a1304 100644 --- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiFilterStore.java +++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiFilterStore.java @@ -23,18 +23,17 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import org.eclipse.pde.api.tools.internal.problems.ApiProblemFactory; -import org.eclipse.pde.api.tools.internal.problems.ApiProblemFilter; -import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin; -import org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore; -import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem; -import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemFilter; -import org.eclipse.pde.api.tools.internal.util.Util; - +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; @@ -47,47 +46,21 @@ import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.core.runtime.preferences.InstanceScope; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceChangeEvent; -import org.eclipse.core.resources.IResourceChangeListener; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.core.resources.IncrementalProjectBuilder; -import org.eclipse.core.resources.ProjectScope; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.resources.WorkspaceJob; - import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.pde.api.tools.internal.problems.ApiProblemFilter; +import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin; +import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem; +import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemFilter; +import org.eclipse.pde.api.tools.internal.util.Util; +import org.w3c.dom.Document; +import org.w3c.dom.Element; /** * Base implementation of a filter store for API components * * @since 1.0.0 */ -public class ApiFilterStore implements IApiFilterStore, IResourceChangeListener { - - /** - * Constant representing the name of the .settings folder - */ - private static final String SETTINGS_FOLDER = ".settings"; //$NON-NLS-1$ - public static final String GLOBAL = "!global!"; //$NON-NLS-1$ - public static final int CURRENT_STORE_VERSION = 2; - - /** - * Represents no filters - */ - private static IApiProblemFilter[] NO_FILTERS = new IApiProblemFilter[0]; - - /** - * The mapping of filters for this store. - * <pre> - * HashMap<IResource, HashSet<IApiProblemFilter>> - * </pre> - */ - private HashMap fFilterMap = null; +public class ApiFilterStore extends FilterStore implements IResourceChangeListener { /** * Map used to collect unused {@link IApiProblemFilter}s @@ -154,8 +127,9 @@ public class ApiFilterStore implements IApiFilterStore, IResourceChangeListener } String lineDelimiter= getLineDelimiterPreference(file); String lineSeparator= System.getProperty("line.separator"); //$NON-NLS-1$ - if (lineDelimiter != null && !lineDelimiter.equals(lineSeparator)) + if (lineDelimiter != null && !lineDelimiter.equals(lineSeparator)) { xml= xml.replaceAll(lineSeparator, lineDelimiter); + } InputStream xstream = Util.getInputStreamFromString(xml); if(xstream == null) { return Status.CANCEL_STATUS; @@ -255,7 +229,8 @@ public class ApiFilterStore implements IApiFilterStore, IResourceChangeListener return; } initializeApiFilters(); - internalAddFilters(problems, null, true); + internalAddFilters(problems, null); + persistApiFilters(); } /* (non-Javadoc) @@ -265,7 +240,7 @@ public class ApiFilterStore implements IApiFilterStore, IResourceChangeListener initializeApiFilters(); Map pTypeNames = (Map) fFilterMap.get(resource); if(pTypeNames == null) { - return NO_FILTERS; + return FilterStore.NO_FILTERS; } List allFilters = new ArrayList(); for (Iterator iterator = pTypeNames.values().iterator(); iterator.hasNext(); ) { @@ -525,11 +500,10 @@ public class ApiFilterStore implements IApiFilterStore, IResourceChangeListener return Util.serializeDocument(document); } - /** - * Initializes the backing filter map for this store from the .api_filters file. Does nothing if the filter store has already been - * initialized. + /* (non-Javadoc) + * @see org.eclipse.pde.api.tools.internal.FilterStore#initializeApiFilters() */ - private synchronized void initializeApiFilters() { + protected synchronized void initializeApiFilters() { if(fFilterMap != null) { return; } @@ -545,13 +519,12 @@ public class ApiFilterStore implements IApiFilterStore, IResourceChangeListener } return; } - String xml = null; InputStream contents = null; try { IFile filterFile = (IFile)file; if (filterFile.exists()) { contents = filterFile.getContents(); - xml = new String(Util.getInputStreamAsCharArray(contents, -1, IApiCoreConstants.UTF_8)); + readFilterFile(contents); } } catch(CoreException e) { @@ -569,101 +542,15 @@ public class ApiFilterStore implements IApiFilterStore, IResourceChangeListener } } } - if(xml == null) { - return; - } - Element root = null; - try { - root = Util.parseDocument(xml); - } - catch(CoreException ce) { - ApiPlugin.log(ce); - } - if (root == null) { - return; - } - if (!root.getNodeName().equals(IApiXmlConstants.ELEMENT_COMPONENT)) { - return; - } - String component = root.getAttribute(IApiXmlConstants.ATTR_ID); - if(component.length() == 0) { - return; - } - String versionValue = root.getAttribute(IApiXmlConstants.ATTR_VERSION); - int currentVersion = Integer.parseInt(IApiXmlConstants.API_FILTER_STORE_CURRENT_VERSION); - int version = 0; - if(versionValue.length() != 0) { - try { - version = Integer.parseInt(versionValue); - } catch (NumberFormatException e) { - // ignore - } - } - if (version != currentVersion) { - // we discard all filters since there is no way to retrieve the type name - fNeedsSaving = true; - persistApiFilters(); - return; - } - NodeList resources = root.getElementsByTagName(IApiXmlConstants.ELEMENT_RESOURCE); - ArrayList newfilters = new ArrayList(); - ArrayList comments = new ArrayList(); - for(int i = 0; i < resources.getLength(); i++) { - Element element = (Element) resources.item(i); - String path = element.getAttribute(IApiXmlConstants.ATTR_PATH); - if(path.length() == 0) { - continue; - } - String typeName = element.getAttribute(IApiXmlConstants.ATTR_TYPE); - if (typeName.length() == 0) { - typeName = null; - } - IProject project = (IProject) ResourcesPlugin.getWorkspace().getRoot().findMember(component); - if(project == null) { - continue; - } - IResource resource = project.findMember(new Path(path)); - if(resource == null) { - continue; - } - NodeList filters = element.getElementsByTagName(IApiXmlConstants.ELEMENT_FILTER); - for(int j = 0; j < filters.getLength(); j++) { - element = (Element) filters.item(j); - int id = loadIntegerAttribute(element, IApiXmlConstants.ATTR_ID); - if(id <= 0) { - continue; - } - String[] messageargs = null; - NodeList elements = element.getElementsByTagName(IApiXmlConstants.ELEMENT_PROBLEM_MESSAGE_ARGUMENTS); - if (elements.getLength() != 1) continue; - Element messageArguments = (Element) elements.item(0); - NodeList arguments = messageArguments.getElementsByTagName(IApiXmlConstants.ELEMENT_PROBLEM_MESSAGE_ARGUMENT); - int length = arguments.getLength(); - messageargs = new String[length]; - for (int k = 0; k < length; k++) { - Element messageArgument = (Element) arguments.item(k); - messageargs[k] = messageArgument.getAttribute(IApiXmlConstants.ATTR_VALUE); - } - String comment = element.getAttribute(IApiXmlConstants.ATTR_COMMENT); - comments.add((comment.length() < 1 ? null : comment)); - newfilters.add(ApiProblemFactory.newApiProblem(resource.getProjectRelativePath().toPortableString(), - typeName, - messageargs, null, null, -1, -1, -1, id)); - } - } - internalAddFilters((IApiProblem[]) newfilters.toArray(new IApiProblem[newfilters.size()]), - (String[]) comments.toArray(new String[comments.size()]), - false); - newfilters.clear(); + //need to reset the flag during initialization if we are not going to persist + //the filters, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=309635 + fNeedsSaving = false; } - /** - * Internal use method that allows auto-persisting of the filter file to be turned on or off - * @param problems the problems to add the the store - * @param comments the comments associated with each problem - * @param persist if the filters should be auto-persisted after they are added + /* (non-Javadoc) + * @see org.eclipse.pde.api.tools.internal.FilterStore#internalAddFilters(org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem[], java.lang.String[]) */ - private synchronized void internalAddFilters(IApiProblem[] problems, String[] comments, boolean persist) { + protected synchronized void internalAddFilters(IApiProblem[] problems, String[] comments) { Set filters = null; for(int i = 0; i < problems.length; i++) { IApiProblem problem = problems[i]; @@ -695,14 +582,6 @@ public class ApiFilterStore implements IApiFilterStore, IResourceChangeListener } fNeedsSaving |= filters.add(filter); } - if(persist) { - persistApiFilters(); - } - else { - //need to reset the flag during initialization if we are not going to persist - //the filters, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=309635 - fNeedsSaving = false; - } } /** @@ -715,32 +594,14 @@ public class ApiFilterStore implements IApiFilterStore, IResourceChangeListener } /** - * Loads the specified integer attribute from the given xml element - * @param element - * @param name - * @return - */ - private static int loadIntegerAttribute(Element element, String name) { - String value = element.getAttribute(name); - if(value.length() == 0) { - return -1; - } - try { - int number = Integer.parseInt(value); - return number; - } - catch(NumberFormatException nfe) {} - return -1; - } - /** * @return the {@link IPath} to the filters file */ IPath getFilterFilePath(boolean includeproject) { if(includeproject) { IPath path = fProject.getPath(); - return path.append(SETTINGS_FOLDER).append(IApiCoreConstants.API_FILTERS_XML_NAME); + return path.append(FilterStore.SETTINGS_FOLDER).append(IApiCoreConstants.API_FILTERS_XML_NAME); } - return new Path(SETTINGS_FOLDER).append(IApiCoreConstants.API_FILTERS_XML_NAME); + return new Path(FilterStore.SETTINGS_FOLDER).append(IApiCoreConstants.API_FILTERS_XML_NAME); } static String getLineDelimiterPreference(IFile file) { @@ -841,11 +702,11 @@ public class ApiFilterStore implements IApiFilterStore, IResourceChangeListener } int size = unused.size(); if (size == 0) { - return NO_FILTERS; + return FilterStore.NO_FILTERS; } return (IApiProblemFilter[]) unused.toArray(new IApiProblemFilter[size]); } - return NO_FILTERS; + return FilterStore.NO_FILTERS; } /** diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/CoreMessages.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/CoreMessages.java index d6ce2b6aba..176aafd7e7 100644 --- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/CoreMessages.java +++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/CoreMessages.java @@ -23,6 +23,7 @@ public class CoreMessages extends NLS { public static String ApiBaseline_4; public static String ApiBaseline_5; public static String ApiBaseline_6; + public static String FilterStore_0; public static String ProjectComponent_could_not_locate_model; static { // initialize resource bundle diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/FilterStore.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/FilterStore.java new file mode 100644 index 0000000000..20d65e9794 --- /dev/null +++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/FilterStore.java @@ -0,0 +1,420 @@ +/******************************************************************************* + * Copyright (c) 2012 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.pde.api.tools.internal; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Path; +import org.eclipse.pde.api.tools.internal.model.BundleComponent; +import org.eclipse.pde.api.tools.internal.problems.ApiProblemFactory; +import org.eclipse.pde.api.tools.internal.problems.ApiProblemFilter; +import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin; +import org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore; +import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem; +import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemFilter; +import org.eclipse.pde.api.tools.internal.util.Util; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * A generic {@link IApiFilterStore} that does not depend on workspace resources + * to filter {@link IApiProblem}s. + * <br> + * This filter store can have filters added and removed from it, but those changes + * are not saved. + */ +public class FilterStore implements IApiFilterStore { + + public static final String GLOBAL = "!global!"; //$NON-NLS-1$ + /** + * Represents no filters + */ + public static IApiProblemFilter[] NO_FILTERS = new IApiProblemFilter[0]; + /** + * The current version of this filter store file format + */ + public static final int CURRENT_STORE_VERSION = 2; + /** + * Constant representing the name of the .settings folder + */ + static final String SETTINGS_FOLDER = ".settings"; //$NON-NLS-1$ + /** + * The mapping of filters for this store. + */ + protected HashMap fFilterMap = null; + /** + * The bundle component backing this store + */ + private BundleComponent fComponent = null; + + /** + * Constructor + */ + public FilterStore() {} + + /** + * Constructor + * @param component + */ + public FilterStore(BundleComponent component) { + fComponent = component; + initializeApiFilters(); + } + + /* (non-Javadoc) + * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#addFilters(org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemFilter[]) + */ + public void addFilters(IApiProblemFilter[] filters) { + if(filters != null && filters.length > 0) { + initializeApiFilters(); + for (int i = 0; i < filters.length; i++) { + fFilterMap.put(filters[i].getComponentId(), filters[i]); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#addFiltersFor(org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem[]) + */ + public void addFiltersFor(IApiProblem[] problems) { + if(problems != null && problems.length > 0) { + initializeApiFilters(); + internalAddFilters(problems, null); + } + } + + /* (non-Javadoc) + * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#getFilters(org.eclipse.core.resources.IResource) + */ + public IApiProblemFilter[] getFilters(IResource resource) { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#getResources() + */ + public IResource[] getResources() { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#removeFilters(org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemFilter[]) + */ + public boolean removeFilters(IApiProblemFilter[] filters) { + if(filters != null && filters.length > 0) { + initializeApiFilters(); + boolean removed = true; + for(int i = 0; i < filters.length; i++) { + removed &= (fFilterMap.remove(filters[i].getComponentId()) != null); + } + return removed; + } + return false; + } + + /** + * Loads the filters from the .api_filters file + */ + protected synchronized void initializeApiFilters() { + if(fFilterMap == null) { + fFilterMap = new HashMap(5); + ZipFile jarFile = null; + InputStream filterstream = null; + File loc = new File(fComponent.getLocation()); + String extension = new Path(loc.getName()).getFileExtension(); + try { + if (extension != null && extension.equals("jar") && loc.isFile()) { //$NON-NLS-1$ + jarFile = new ZipFile(loc, ZipFile.OPEN_READ); + ZipEntry filterfile = jarFile.getEntry(IApiCoreConstants.API_FILTERS_XML_NAME); + if (filterfile != null) { + filterstream = jarFile.getInputStream(filterfile); + } + } else { + File file = new File(loc, SETTINGS_FOLDER+File.separator+IApiCoreConstants.API_FILTERS_XML_NAME); + if (file.exists()) { + filterstream = new FileInputStream(file); + } + } + if (filterstream == null) { + return; + } + readFilterFile(filterstream); + + } catch (IOException e) { + ApiPlugin.log(e); + } finally { + fComponent.closingZipFileAndStream(filterstream, jarFile); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#isFiltered(org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem) + */ + public boolean isFiltered(IApiProblem problem) { + if (fFilterMap == null || fFilterMap.isEmpty()) { + return false; + } + String typeName = problem.getTypeName(); + if (typeName == null || typeName.length() == 0) { + typeName = GLOBAL; + } + Set filters = (Set) fFilterMap.get(typeName); + if (filters == null) { + return false; + } + for (Iterator iterator = filters.iterator(); iterator.hasNext();) { + IApiProblemFilter filter = (IApiProblemFilter) iterator.next(); + if (problemsMatch(filter.getUnderlyingProblem(), problem)) { + return true; + } + } + return false; + } + + /** + * Returns <code>true</code> if the attributes of the problems match, <code>false</code> otherwise + * + * @param filterProblem the problem from the filter store + * @param problem the problem from the builder + * @return <code>true</code> if the problems match, <code>false</code> otherwise + */ + protected boolean problemsMatch(IApiProblem filterProblem, IApiProblem problem) { + if (problem.getId() == filterProblem.getId()) { + // check arguments +// String problemPath = problem.getResourcePath(); +// String filterProblemPath = filterProblem.getResourcePath(); +// if (problemPath == null) { +// if (filterProblemPath != null) { +// return false; +// } +// } else if (filterProblemPath == null) { +// return false; +// } else if (!new Path(problemPath).equals(new Path(filterProblemPath))) { +// return false; +// } + String problemTypeName = problem.getTypeName(); + String filterProblemTypeName = filterProblem.getTypeName(); + if (problemTypeName == null) { + if (filterProblemTypeName != null) { + return false; + } + } else if (filterProblemTypeName == null) { + return false; + } else if (!problemTypeName.equals(filterProblemTypeName)) { + return false; + } + return argumentsEquals(problem.getMessageArguments(), filterProblem.getMessageArguments()); + } + return false; + } + + /** + * Returns if the arrays of message arguments are equal. + * <br> + * The arrays are considered equal iff: + * <ul> + * <li>both are <code>null</code></li> + * <li>both are the same length</li> + * <li>both have equal elements at equal positions in the array</li> + * </ul> + * @param problemMessageArguments + * @param filterProblemMessageArguments + * @return <code>true</code> if the arrays are equal, <code>false</code> otherwise + */ + private boolean argumentsEquals(String[] problemMessageArguments, String[] filterProblemMessageArguments) { + // filter problems message arguments are always simple name + // problem message arguments are fully qualified name outside the IDE + int length = problemMessageArguments.length; + if (length == filterProblemMessageArguments.length) { + for (int i = 0; i < length; i++) { + String problemMessageArgument = problemMessageArguments[i]; + String filterProblemMessageArgument = filterProblemMessageArguments[i]; + if (problemMessageArgument.equals(filterProblemMessageArgument)) { + continue; + } + int index = problemMessageArgument.lastIndexOf('.'); + int filterProblemIndex = filterProblemMessageArgument.lastIndexOf('.'); + if (index == -1) { + if (filterProblemIndex == -1) { + return false; // simple names should match + } + if (filterProblemMessageArgument.substring(filterProblemIndex + 1).equals(problemMessageArgument)) { + continue; + } else { + return false; + } + } else if (filterProblemIndex != -1) { + return false; // fully qualified name should match + } else { + if (problemMessageArgument.substring(index + 1).equals(filterProblemMessageArgument)) { + continue; + } else { + return false; + } + } + } + return true; + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore#dispose() + */ + public void dispose() { + if(fFilterMap != null) { + fFilterMap.clear(); + fFilterMap = null; + } + } + + /** + * Reads the API problem filter file and calls back to {@link #addFilters(IApiProblemFilter[])} + * to store the filters. + * <br> + * This method will not close the given input stream when done reading it. + * + * @param contents the {@link InputStream} for the contents of the filter file, <code>null</code> is not allowed. + * @throws IOException if the stream cannot be read or fails + */ + protected void readFilterFile(InputStream contents) throws IOException { + if(contents == null) { + throw new IOException(CoreMessages.FilterStore_0); + } + String xml = new String(Util.getInputStreamAsCharArray(contents, -1, IApiCoreConstants.UTF_8)); + Element root = null; + try { + root = Util.parseDocument(xml); + } + catch(CoreException ce) { + ApiPlugin.log(ce); + } + if (root == null) { + return; + } + if (!root.getNodeName().equals(IApiXmlConstants.ELEMENT_COMPONENT)) { + return; + } + String component = root.getAttribute(IApiXmlConstants.ATTR_ID); + if(component.length() == 0) { + return; + } + String versionValue = root.getAttribute(IApiXmlConstants.ATTR_VERSION); + int currentVersion = Integer.parseInt(IApiXmlConstants.API_FILTER_STORE_CURRENT_VERSION); + int version = 0; + if(versionValue.length() != 0) { + try { + version = Integer.parseInt(versionValue); + } catch (NumberFormatException e) { + // ignore + } + } + if (version != currentVersion) { + return; + } + NodeList resources = root.getElementsByTagName(IApiXmlConstants.ELEMENT_RESOURCE); + ArrayList newfilters = new ArrayList(); + ArrayList comments = new ArrayList(); + for(int i = 0; i < resources.getLength(); i++) { + Element element = (Element) resources.item(i); + String typeName = element.getAttribute(IApiXmlConstants.ATTR_TYPE); + if (typeName.length() == 0) { + // if there is no type attribute, an empty string is returned + typeName = null; + } + String path = element.getAttribute(IApiXmlConstants.ATTR_PATH); + NodeList filters = element.getElementsByTagName(IApiXmlConstants.ELEMENT_FILTER); + for(int j = 0; j < filters.getLength(); j++) { + element = (Element) filters.item(j); + int id = loadIntegerAttribute(element, IApiXmlConstants.ATTR_ID); + if(id <= 0) { + continue; + } + String[] messageargs = null; + NodeList elements = element.getElementsByTagName(IApiXmlConstants.ELEMENT_PROBLEM_MESSAGE_ARGUMENTS); + if (elements.getLength() != 1) continue; + Element messageArguments = (Element) elements.item(0); + NodeList arguments = messageArguments.getElementsByTagName(IApiXmlConstants.ELEMENT_PROBLEM_MESSAGE_ARGUMENT); + int length = arguments.getLength(); + messageargs = new String[length]; + String comment = element.getAttribute(IApiXmlConstants.ATTR_COMMENT); + comments.add((comment.length() < 1 ? null : comment)); + for (int k = 0; k < length; k++) { + Element messageArgument = (Element) arguments.item(k); + messageargs[k] = messageArgument.getAttribute(IApiXmlConstants.ATTR_VALUE); + } + newfilters.add(ApiProblemFactory.newApiProblem(path, typeName, messageargs, null, null, -1, -1, -1, id)); + } + } + internalAddFilters( + (IApiProblem[]) newfilters.toArray(new IApiProblem[newfilters.size()]), + (String[]) comments.toArray(new String[comments.size()])); + newfilters.clear(); + } + + /** + * Internal use method that allows auto-persisting of the filter file to be turned on or off + * @param problems the problems to add the the store + * @param persist if the filters should be auto-persisted after they are added + */ + protected void internalAddFilters(IApiProblem[] problems, String[] comments) { + if(problems == null) { + return; + } + for(int i = 0; i < problems.length; i++) { + IApiProblem problem = problems[i]; + IApiProblemFilter filter = new ApiProblemFilter(fComponent.getSymbolicName(), problem, comments[i]); + String typeName = problem.getTypeName(); + if (typeName == null) { + typeName = GLOBAL; + } + Set filters = (Set) fFilterMap.get(typeName); + if(filters == null) { + filters = new HashSet(); + fFilterMap.put(typeName, filters); + } + filters.add(filter); + } + } + + /** + * Loads the specified integer attribute from the given XML element + * @param element the XML element + * @param name the name of the attribute + * @return the specified value in XML or -1 + */ + protected int loadIntegerAttribute(Element element, String name) { + String value = element.getAttribute(name); + if(value.length() == 0) { + return -1; + } + try { + int number = Integer.parseInt(value); + return number; + } + catch(NumberFormatException nfe) {} + return -1; + } + +} diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/IApiXmlConstants.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/IApiXmlConstants.java index 0e7b931116..bc8bb9acbe 100644 --- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/IApiXmlConstants.java +++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/IApiXmlConstants.java @@ -25,7 +25,7 @@ public interface IApiXmlConstants { /** * Constant representing the current version for API filter store files */ - public static final String API_FILTER_STORE_CURRENT_VERSION = Integer.toString(ApiFilterStore.CURRENT_STORE_VERSION); + public static final String API_FILTER_STORE_CURRENT_VERSION = Integer.toString(FilterStore.CURRENT_STORE_VERSION); /** * Constant representing the current version for API profile files */ diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/coremessages.properties b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/coremessages.properties index 8053c0ef8a..8cd2a78e64 100644 --- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/coremessages.properties +++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/coremessages.properties @@ -15,4 +15,5 @@ ApiBaseline_2=Error occurred while binding execution environment ApiBaseline_4=Baseline has bundles requiring unavailable execution environments ApiBaseline_5={0} is unavailable ApiBaseline_6=Baseline not bound - there are no installed VMs compatible with the required execution environments +FilterStore_0=Cannot read API problem filters from a null stream ProjectComponent_could_not_locate_model=Could not locate the plugin model base for project: {0} diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/BundleComponent.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/BundleComponent.java index a1525a39d0..c47ceac4bb 100644 --- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/BundleComponent.java +++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/BundleComponent.java @@ -28,7 +28,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.jar.JarFile; -import java.util.jar.Manifest; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -55,6 +54,7 @@ import org.eclipse.pde.api.tools.internal.ApiDescription; import org.eclipse.pde.api.tools.internal.ApiDescriptionProcessor; import org.eclipse.pde.api.tools.internal.BundleVersionRange; import org.eclipse.pde.api.tools.internal.CompositeApiDescription; +import org.eclipse.pde.api.tools.internal.FilterStore; import org.eclipse.pde.api.tools.internal.IApiCoreConstants; import org.eclipse.pde.api.tools.internal.RequiredComponentDescription; import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin; @@ -529,8 +529,7 @@ public class BundleComponent extends Component { * @see org.eclipse.pde.api.tools.internal.AbstractApiComponent#createApiFilterStore() */ protected IApiFilterStore createApiFilterStore() throws CoreException { - //always return a new empty store since we do not support filtering from bundles - return null; + return new FilterStore(this); } /** @@ -814,41 +813,8 @@ public class BundleComponent extends Component { } return null; } - - /** - * Reads and returns this bunlde's manifest in a Manifest object. - * The bundle may be in a jar or in a directory at the specified location. - * - * @param bundleLocation root location of the bundle - * @return manifest or <code>null</code> if not present - * @throws IOException if unable to parse - */ - protected Manifest readManifest(File bundleLocation) throws IOException { - ZipFile jarFile = null; - InputStream manifestStream = null; - try { - String extension = new Path(bundleLocation.getName()).getFileExtension(); - if (extension != null && extension.equals("jar") && bundleLocation.isFile()) { //$NON-NLS-1$ - jarFile = new ZipFile(bundleLocation, ZipFile.OPEN_READ); - ZipEntry manifestEntry = jarFile.getEntry(JarFile.MANIFEST_NAME); - if (manifestEntry != null) { - manifestStream = jarFile.getInputStream(manifestEntry); - } - } else { - File file = new File(bundleLocation, JarFile.MANIFEST_NAME); - if (file.exists()) - manifestStream = new FileInputStream(file); - } - if (manifestStream == null) { - return null; - } - return new Manifest(manifestStream); - } finally { - closingZipFileAndStream(manifestStream, jarFile); - } - } - void closingZipFileAndStream(InputStream stream, ZipFile jarFile) { + public void closingZipFileAndStream(InputStream stream, ZipFile jarFile) { try { if (stream != null) { stream.close(); diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/UseSearchRequestor.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/UseSearchRequestor.java index 967c17a3c5..68de9d03c4 100644 --- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/UseSearchRequestor.java +++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/UseSearchRequestor.java @@ -19,6 +19,7 @@ import org.eclipse.pde.api.tools.internal.builder.Reference; import org.eclipse.pde.api.tools.internal.builder.ReferenceAnalyzer; import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin; import org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations; +import org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore; import org.eclipse.pde.api.tools.internal.provisional.VisibilityModifiers; import org.eclipse.pde.api.tools.internal.provisional.builder.IApiProblemDetector; import org.eclipse.pde.api.tools.internal.provisional.builder.IReference; @@ -29,6 +30,7 @@ import org.eclipse.pde.api.tools.internal.provisional.model.IApiMember; import org.eclipse.pde.api.tools.internal.provisional.model.IApiScope; import org.eclipse.pde.api.tools.internal.provisional.model.IApiType; import org.eclipse.pde.api.tools.internal.provisional.model.IApiTypeContainer; +import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem; import org.eclipse.pde.api.tools.internal.provisional.search.IApiSearchRequestor; /** @@ -47,6 +49,18 @@ public class UseSearchRequestor implements IApiSearchRequestor { private Set fComponentIds = null; /** + * The current {@link IApiFilterStore} from the current {@link IApiComponent} context we are visiting + */ + private IApiFilterStore currentStore = null; + + /** + * An {@link IApiFilterStore} that was set from an external source + * + * @see #setGlobalFilterStore + */ + private IApiFilterStore globalStore = null; + + /** * The mask to use while searching */ private int fSearchMask = 0; @@ -94,12 +108,14 @@ public class UseSearchRequestor implements IApiSearchRequestor { if(includesIllegalUse()) { fAnalyzer.buildProblemDetectors(component, ProblemDetectorBuilder.K_USE, null); } + currentStore = component.getFilterStore(); return true; } } catch(CoreException ce) { //do nothing, return false } + currentStore = null; return false; } @@ -195,7 +211,19 @@ public class UseSearchRequestor implements IApiSearchRequestor { Reference ref = (Reference) reference; ref.setFlags(IReference.F_ILLEGAL); try { - ref.addProblems(((AbstractProblemDetector)detectors[i]).createProblem(reference)); + IApiProblem pb = ((AbstractProblemDetector)detectors[i]).createProblem(reference); + if(!isFiltered(pb)) { + ref.addProblems(pb); + } else { + + + // TODO CWindatt - Remove tracing + System.out.println("332772 - Problem filtered"); + + + + + } } catch (CoreException e) { ApiPlugin.log(e); } @@ -205,6 +233,16 @@ public class UseSearchRequestor implements IApiSearchRequestor { return false; } + /** + * Returns if the given problem is filtered + * @param problem + * @return <code>true</code> is filtered, false otherwise + */ + boolean isFiltered(IApiProblem problem) throws CoreException { + return (currentStore != null && currentStore.isFiltered(problem)) || + (globalStore != null && globalStore.isFiltered(problem)); + } + /* (non-Javadoc) * @see org.eclipse.pde.api.tools.internal.provisional.search.IApiSearchRequestor#getReferenceKinds() */ @@ -260,4 +298,12 @@ public class UseSearchRequestor implements IApiSearchRequestor { public void setJarPatterns(String[] patterns) { jarPatterns = patterns; } + + /** + * Allows a global {@link IApiFilterStore} to be used to filter all references found during the scan + * @param store the store to set or <code>null</code> to remove the store + */ + public void setGlobalFilterStore(IApiFilterStore store) { + globalStore = store; + } } diff --git a/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/APIToolsAnalysisTask.java b/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/APIToolsAnalysisTask.java index ef4a5ab74c..7b3e81edb7 100644 --- a/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/APIToolsAnalysisTask.java +++ b/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/APIToolsAnalysisTask.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2011 IBM Corporation and others. + * Copyright (c) 2008, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,7 +14,6 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; @@ -29,18 +28,14 @@ import java.util.Properties; import java.util.Set; import org.apache.tools.ant.BuildException; -import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.Path; import org.eclipse.osgi.util.NLS; -import org.eclipse.pde.api.tools.internal.IApiCoreConstants; import org.eclipse.pde.api.tools.internal.IApiXmlConstants; import org.eclipse.pde.api.tools.internal.builder.BaseApiAnalyzer; import org.eclipse.pde.api.tools.internal.builder.BuildContext; import org.eclipse.pde.api.tools.internal.model.StubApiComponent; import org.eclipse.pde.api.tools.internal.problems.ApiProblemFactory; -import org.eclipse.pde.api.tools.internal.problems.ApiProblemFilter; import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin; import org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore; import org.eclipse.pde.api.tools.internal.provisional.IApiMarkerConstants; @@ -48,305 +43,17 @@ import org.eclipse.pde.api.tools.internal.provisional.comparator.IDelta; import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline; import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent; import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem; -import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemFilter; import org.eclipse.pde.api.tools.internal.util.FilteredElements; import org.eclipse.pde.api.tools.internal.util.Util; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.NodeList; /** * Ant task to run the API tool verification during Eclipse build. */ public class APIToolsAnalysisTask extends CommonUtilsTask { - /** - * This filter store is only used to filter problem using existing filters. - * It doesn't add or remove any filters. - */ - private static class AntFilterStore implements IApiFilterStore { - private static final String GLOBAL = "!global!"; //$NON-NLS-1$ - private static int loadIntegerAttribute(Element element, String name) { - String value = element.getAttribute(name); - if(value.length() == 0) { - return -1; - } - try { - int number = Integer.parseInt(value); - return number; - } - catch(NumberFormatException nfe) {} - return -1; - } - private boolean debug; - - private Map fFilterMap; - - public AntFilterStore(boolean debug, String filtersRoot, String componentID) { - this.initialize(filtersRoot, componentID); - } - - public void addFiltersFor(IApiProblem[] problems) { - // do nothing - } - - public void addFilters(IApiProblemFilter[] filters) { - // do nothing - } - - private boolean argumentsEquals(String[] problemMessageArguments, - String[] filterProblemMessageArguments) { - // filter problems message arguments are always simple name - // problem message arguments are fully qualified name outside the IDE - int length = problemMessageArguments.length; - if (length == filterProblemMessageArguments.length) { - for (int i = 0; i < length; i++) { - String problemMessageArgument = problemMessageArguments[i]; - String filterProblemMessageArgument = filterProblemMessageArguments[i]; - if (problemMessageArgument.equals(filterProblemMessageArgument)) { - continue; - } - int index = problemMessageArgument.lastIndexOf('.'); - int filterProblemIndex = filterProblemMessageArgument.lastIndexOf('.'); - if (index == -1) { - if (filterProblemIndex == -1) { - return false; // simple names should match - } - if (filterProblemMessageArgument.substring(filterProblemIndex + 1).equals(problemMessageArgument)) { - continue; - } else { - return false; - } - } else if (filterProblemIndex != -1) { - return false; // fully qualified name should match - } else { - if (problemMessageArgument.substring(index + 1).equals(filterProblemMessageArgument)) { - continue; - } else { - return false; - } - } - } - return true; - } - return false; - } - - public void dispose() { - // do nothing - } - - public IApiProblemFilter[] getFilters(IResource resource) { - return null; - } - - public IResource[] getResources() { - return null; - } - - /** - * Initialize the filter store using the given component id - */ - private void initialize(String filtersRoot, String componentID) { - if(fFilterMap != null) { - return; - } - if(this.debug) { - System.out.println("null filter map, creating a new one"); //$NON-NLS-1$ - } - fFilterMap = new HashMap(5); - String xml = null; - InputStream contents = null; - try { - File filterFileParent = new File(filtersRoot, componentID); - if (!filterFileParent.exists()) { - return; - } - contents = new BufferedInputStream(new FileInputStream(new File(filterFileParent, IApiCoreConstants.API_FILTERS_XML_NAME))); - xml = new String(Util.getInputStreamAsCharArray(contents, -1, IApiCoreConstants.UTF_8)); - } - catch(IOException ioe) {} - finally { - if (contents != null) { - try { - contents.close(); - } catch(IOException e) { - // ignore - } - } - } - if(xml == null) { - return; - } - Element root = null; - try { - root = Util.parseDocument(xml); - } - catch(CoreException ce) { - ApiPlugin.log(ce); - } - if (root == null) { - return; - } - if (!root.getNodeName().equals(IApiXmlConstants.ELEMENT_COMPONENT)) { - return; - } - String component = root.getAttribute(IApiXmlConstants.ATTR_ID); - if(component.length() == 0) { - return; - } - String versionValue = root.getAttribute(IApiXmlConstants.ATTR_VERSION); - int version = 0; - if(versionValue.length() != 0) { - try { - version = Integer.parseInt(versionValue); - } catch (NumberFormatException e) { - // ignore - } - } - if (version < 2) { - // we discard all filters since there is no way to retrieve the type name - return; - } - NodeList resources = root.getElementsByTagName(IApiXmlConstants.ELEMENT_RESOURCE); - ArrayList newfilters = new ArrayList(); - ArrayList comments = new ArrayList(); - for(int i = 0; i < resources.getLength(); i++) { - Element element = (Element) resources.item(i); - String typeName = element.getAttribute(IApiXmlConstants.ATTR_TYPE); - if (typeName.length() == 0) { - // if there is no type attribute, an empty string is returned - typeName = null; - } - String path = element.getAttribute(IApiXmlConstants.ATTR_PATH); - NodeList filters = element.getElementsByTagName(IApiXmlConstants.ELEMENT_FILTER); - for(int j = 0; j < filters.getLength(); j++) { - element = (Element) filters.item(j); - int id = loadIntegerAttribute(element, IApiXmlConstants.ATTR_ID); - if(id <= 0) { - continue; - } - String[] messageargs = null; - NodeList elements = element.getElementsByTagName(IApiXmlConstants.ELEMENT_PROBLEM_MESSAGE_ARGUMENTS); - if (elements.getLength() != 1) continue; - Element messageArguments = (Element) elements.item(0); - NodeList arguments = messageArguments.getElementsByTagName(IApiXmlConstants.ELEMENT_PROBLEM_MESSAGE_ARGUMENT); - int length = arguments.getLength(); - messageargs = new String[length]; - String comment = element.getAttribute(IApiXmlConstants.ATTR_COMMENT); - comments.add((comment.length() < 1 ? null : comment)); - for (int k = 0; k < length; k++) { - Element messageArgument = (Element) arguments.item(k); - messageargs[k] = messageArgument.getAttribute(IApiXmlConstants.ATTR_VALUE); - } - newfilters.add(ApiProblemFactory.newApiProblem(path, typeName, messageargs, null, null, -1, -1, -1, id)); - } - } - internalAddFilters(componentID, (IApiProblem[]) newfilters.toArray(new IApiProblem[newfilters.size()]), - (String[]) comments.toArray(new String[comments.size()])); - newfilters.clear(); - } - - /** - * Internal use method that allows auto-persisting of the filter file to be turned on or off - * @param problems the problems to add the the store - * @param persist if the filters should be auto-persisted after they are added - */ - private void internalAddFilters(String componentID, IApiProblem[] problems, String[] comments) { - if(problems == null) { - if(this.debug) { - System.out.println("null problems array not addding filters"); //$NON-NLS-1$ - } - return; - } - for(int i = 0; i < problems.length; i++) { - IApiProblem problem = problems[i]; - IApiProblemFilter filter = new ApiProblemFilter(componentID, problem, comments[i]); - String typeName = problem.getTypeName(); - if (typeName == null) { - typeName = GLOBAL; - } - Set filters = (Set) fFilterMap.get(typeName); - if(filters == null) { - filters = new HashSet(); - fFilterMap.put(typeName, filters); - } - filters.add(filter); - } - } - - public boolean isFiltered(IApiProblem problem) { - if (this.fFilterMap == null || this.fFilterMap.isEmpty()) return false; - String typeName = problem.getTypeName(); - if (typeName == null || typeName.length() == 0) { - typeName = GLOBAL; - } - Set filters = (Set) this.fFilterMap.get(typeName); - if (filters == null) { - return false; - } - for (Iterator iterator = filters.iterator(); iterator.hasNext();) { - IApiProblemFilter filter = (IApiProblemFilter) iterator.next(); - if (problem.getCategory() == IApiProblem.CATEGORY_USAGE) { - // write our own matching implementation - return matchUsageProblem(filter.getUnderlyingProblem(), problem); - } else if (matchFilters(filter.getUnderlyingProblem(), problem)) { - return true; - } - } - return false; - } - - private boolean matchFilters(IApiProblem filterProblem, IApiProblem problem) { - if (problem.getId() == filterProblem.getId() && argumentsEquals(problem.getMessageArguments(), filterProblem.getMessageArguments())) { - String typeName = problem.getTypeName(); - String filteredProblemTypeName = filterProblem.getTypeName(); - if (typeName == null) { - if (filteredProblemTypeName != null) { - return false; - } - return true; - } else if (filteredProblemTypeName == null) { - return false; - } - return typeName.equals(filteredProblemTypeName); - } - return false; - } - - private boolean matchUsageProblem(IApiProblem filterProblem, IApiProblem problem) { - if (problem.getId() == filterProblem.getId()) { - // check arguments - String problemPath = problem.getResourcePath(); - String filterProblemPath = filterProblem.getResourcePath(); - if (problemPath == null) { - if (filterProblemPath != null) { - return false; - } - } else if (filterProblemPath == null) { - return false; - } else if (!new Path(problemPath).equals(new Path(filterProblemPath))) { - return false; - } - String problemTypeName = problem.getTypeName(); - String filterProblemTypeName = filterProblem.getTypeName(); - if (problemTypeName == null) { - if (filterProblemTypeName != null) { - return false; - } - } else if (filterProblemTypeName == null) { - return false; - } else if (!problemTypeName.equals(filterProblemTypeName)) { - return false; - } - return argumentsEquals(problem.getMessageArguments(), filterProblem.getMessageArguments()); - } - return false; - } - public boolean removeFilters(IApiProblemFilter[] filters) { - return false; - } - } + private static class Summary { List apiBundleVersionProblems = new ArrayList(); List apiCompatibilityProblems = new ArrayList(); diff --git a/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/AntFilterStore.java b/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/AntFilterStore.java new file mode 100644 index 0000000000..a4c5e328ab --- /dev/null +++ b/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/AntFilterStore.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2012 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.pde.api.tools.internal.tasks; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.pde.api.tools.internal.FilterStore; +import org.eclipse.pde.api.tools.internal.IApiCoreConstants; +import org.eclipse.pde.api.tools.internal.problems.ApiProblemFilter; +import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem; +import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemFilter; + +/** + * This filter store is only used to filter problem using existing filters. + * It doesn't add or remove any filters. + */ +public class AntFilterStore extends FilterStore { + + private boolean debug; + String fComponentId = null; + String fFiltersRoot = null; + + /** + * Constructor + * @param debug + * @param filtersRoot + * @param componentID + */ + public AntFilterStore(boolean debug, String filtersRoot, String componentID) { + fComponentId = componentID; + fFiltersRoot = filtersRoot; + } + + /* (non-Javadoc) + * @see org.eclipse.pde.api.tools.internal.FilterStore#initializeApiFilters() + */ + protected synchronized void initializeApiFilters() { + if(fFilterMap != null) { + return; + } + if(this.debug) { + System.out.println("null filter map, creating a new one"); //$NON-NLS-1$ + } + fFilterMap = new HashMap(5); + InputStream contents = null; + try { + File filterFileParent = new File(fFiltersRoot, fComponentId); + if (!filterFileParent.exists()) { + return; + } + contents = new BufferedInputStream(new FileInputStream(new File(filterFileParent, IApiCoreConstants.API_FILTERS_XML_NAME))); + readFilterFile(contents); + } + catch(IOException ioe) { + } + finally { + if (contents != null) { + try { + contents.close(); + } catch(IOException e) { + // ignore + } + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.pde.api.tools.internal.FilterStore#internalAddFilters(org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem[], java.lang.String[]) + */ + protected void internalAddFilters(IApiProblem[] problems, String[] comments) { + if(problems == null) { + return; + } + for(int i = 0; i < problems.length; i++) { + IApiProblem problem = problems[i]; + IApiProblemFilter filter = new ApiProblemFilter(fComponentId, problem, comments[i]); + String typeName = problem.getTypeName(); + if (typeName == null) { + typeName = GLOBAL; + } + Set filters = (Set) fFilterMap.get(typeName); + if(filters == null) { + filters = new HashSet(); + fFilterMap.put(typeName, filters); + } + filters.add(filter); + } + } +}
\ No newline at end of file diff --git a/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/ApiUseTask.java b/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/ApiUseTask.java index aa958be7b7..92266f98a9 100644 --- a/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/ApiUseTask.java +++ b/apitools/org.eclipse.pde.api.tools/src_ant/org/eclipse/pde/api/tools/internal/tasks/ApiUseTask.java @@ -25,6 +25,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.osgi.service.resolver.ResolverError; import org.eclipse.osgi.util.NLS; import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin; +import org.eclipse.pde.api.tools.internal.provisional.IApiFilterStore; import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline; import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent; import org.eclipse.pde.api.tools.internal.provisional.model.IApiElement; @@ -97,6 +98,10 @@ public final class ApiUseTask extends CommonUtilsTask { * </pre> */ private String[] archivePatterns = null; + /** + * Absolute file paths to the filter files to use + */ + private String[] filterPaths = null; /** * List of elements excluded from the scope @@ -238,6 +243,14 @@ public final class ApiUseTask extends CommonUtilsTask { } /** + * Sets the paths of the filter files to use + * @param paths + */ + public void setFilterPaths(String paths) { + filterPaths = parsePatterns(paths); + } + + /** * @see org.eclipse.pde.api.tools.internal.tasks.UseTask#assertParameters() */ protected void assertParameters() throws BuildException { @@ -298,6 +311,7 @@ public final class ApiUseTask extends CommonUtilsTask { (IApiElement[]) scope.toArray(new IApiElement[scope.size()]), getSearchFlags()); requestor.setJarPatterns(archivePatterns); + requestor.setGlobalFilterStore(getFilterStore(ids)); // override API descriptions as required if (apiPatterns != null || internalPatterns != null) { // modify API descriptions @@ -461,6 +475,18 @@ public final class ApiUseTask extends CommonUtilsTask { } /** + * Create a global filter store from a group of filter files + * + * @return the new {@link IApiFilterStore} or <code>null</code> + */ + protected IApiFilterStore getFilterStore(Set ids) { + if(filterPaths != null && !ids.isEmpty()) { + //TODO we need to create the filter store + } + return null; + } + + /** * Cleans the report location specified by the parameter {@link CommonUtilsTask#reportLocation} */ protected void cleanReportLocation() { |