package edu.umd.cs.findbugs.filter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.util.IdentityHashMap;
import java.util.Iterator;
import javax.annotation.WillClose;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.SAXBugCollectionHandler;
import edu.umd.cs.findbugs.SystemProperties;
import edu.umd.cs.findbugs.util.Util;
import edu.umd.cs.findbugs.xml.OutputStreamXMLOutput;
import edu.umd.cs.findbugs.xml.XMLOutput;
public class Filter extends OrMatcher {
private static final boolean DEBUG = SystemProperties.getBoolean("filter.debug");
private final IdentityHashMap<Matcher, Boolean> disabled = new IdentityHashMap<Matcher, Boolean>();
public Filter() {
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((disabled == null) ? 0 : disabled.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof Filter)) {
return false;
}
final Filter other = (Filter) obj;
if (disabled == null) {
if (other.disabled != null) {
return false;
}
} else if (!disabled.equals(other.disabled)) {
return false;
}
return true;
}
public boolean isEmpty() {
return super.numberChildren() == 0;
}
public void setEnabled(Matcher m, boolean value) {
if (value) {
enable(m);
} else {
disable(m);
}
}
public void disable(Matcher m) {
disabled.put(m, true);
}
public boolean isEnabled(Matcher m) {
return !disabled.containsKey(m);
}
public void enable(Matcher m) {
disabled.remove(m);
}
public static Filter parseFilter(String fileName) throws IOException {
return new Filter(fileName);
}
public Filter(String fileName) throws IOException {
try {
parse(fileName);
} catch (SAXException e) {
throw new IOException(e.getMessage());
}
}
public Filter(InputStream stream) throws IOException {
try {
parse("", stream);
} catch (SAXException e) {
throw new IOException(e.getMessage());
}
}
public boolean contains(Matcher child) {
return children.contains(child);
}
public void softAdd(Matcher child) {
super.addChild(child);
}
@Override
public void addChild(Matcher child) {
super.addChild(child);
enable(child);
}
@Override
public void removeChild(Matcher child) {
enable(child);
super.removeChild(child);
}
@Override
public void clear() {
disabled.clear();
super.clear();
}
@Override
public boolean match(BugInstance bugInstance) {
Iterator<Matcher> i = childIterator();
while (i.hasNext()) {
Matcher child = i.next();
if (isEnabled(child) && child.match(bugInstance)) {
return true;
}
}
return false;
}
private void parse(String fileName) throws IOException, SAXException {
FileInputStream fileInputStream = new FileInputStream(new File(fileName));
parse(fileName, fileInputStream);
}
private void parse(String fileName, @WillClose InputStream stream) throws IOException, SAXException {
try {
SAXBugCollectionHandler handler = new SAXBugCollectionHandler(this, new File(fileName));
XMLReader xr = XMLReaderFactory.createXMLReader();
xr.setContentHandler(handler);
xr.setErrorHandler(handler);
Reader reader = Util.getReader(stream);
xr.parse(new InputSource(reader));
} finally {
Util.closeSilently(stream);
}
}
public static void main(String[] argv) {
try {
if (argv.length != 1) {
System.err.println("Usage: " + Filter.class.getName() + " <filename>");
System.exit(1);
}
Filter filter = new Filter(argv[0]);
filter.writeAsXML(System.out);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
public void writeAsXML(@WillClose OutputStream out) throws IOException {
XMLOutput xmlOutput = new OutputStreamXMLOutput(out);
try {
xmlOutput.beginDocument();
xmlOutput.openTag("FindBugsFilter");
writeBodyAsXML(xmlOutput);
xmlOutput.closeTag("FindBugsFilter");
} finally {
xmlOutput.finish();
}
}
public void writeEnabledMatchersAsXML(@WillClose OutputStream out) throws IOException {
XMLOutput xmlOutput = new OutputStreamXMLOutput(out);
try {
xmlOutput.beginDocument();
xmlOutput.openTag("FindBugsFilter");
Iterator<Matcher> i = childIterator();
while (i.hasNext()) {
Matcher child = i.next();
if (!disabled.containsKey(child)) {
child.writeXML(xmlOutput, false);
}
}
xmlOutput.closeTag("FindBugsFilter");
} finally {
xmlOutput.finish();
}
}
public void writeBodyAsXML(XMLOutput xmlOutput) throws IOException {
Iterator<Matcher> i = childIterator();
while (i.hasNext()) {
Matcher child = i.next();
child.writeXML(xmlOutput, disabled.containsKey(child));
}
}
}