001////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code for adherence to a set of rules.
003// Copyright (C) 2001-2016 the original author or authors.
004//
005// This library is free software; you can redistribute it and/or
006// modify it under the terms of the GNU Lesser General Public
007// License as published by the Free Software Foundation; either
008// version 2.1 of the License, or (at your option) any later version.
009//
010// This library is distributed in the hope that it will be useful,
011// but WITHOUT ANY WARRANTY; without even the implied warranty of
012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013// Lesser General Public License for more details.
014//
015// You should have received a copy of the GNU Lesser General Public
016// License along with this library; if not, write to the Free Software
017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
018////////////////////////////////////////////////////////////////////////////////
019
020package com.puppycrawl.tools.checkstyle.filters;
021
022import java.io.IOException;
023import java.io.InputStream;
024import java.net.URI;
025import java.net.URL;
026import java.util.Objects;
027
028import com.puppycrawl.tools.checkstyle.api.AuditEvent;
029import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
030import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
031import com.puppycrawl.tools.checkstyle.api.Filter;
032import com.puppycrawl.tools.checkstyle.api.FilterSet;
033import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
034
035/**
036 * <p>
037 * This filter accepts AuditEvents according to file, check, line, and
038 * column, as specified in a suppression file.
039 * </p>
040 * @author Rick Giles
041 * @author <a href="mailto:piotr.listkiewicz@gmail.com">liscju</a>
042 */
043public class SuppressionFilter
044    extends AutomaticBean
045    implements Filter {
046    /** Filename of supression file. */
047    private String file;
048    /** Tells whether config file existence is optional. */
049    private boolean optional;
050    /** Set of individual suppresses. */
051    private FilterSet filters = new FilterSet();
052
053    /**
054     * Sets name of the supression file.
055     * @param fileName name of the suppressions file.
056     */
057    public void setFile(String fileName) {
058        file = fileName;
059    }
060
061    /**
062     * Sets whether config file existence is optional.
063     * @param optional tells if config file existence is optional.
064     */
065    public void setOptional(boolean optional) {
066        this.optional = optional;
067    }
068
069    @Override
070    public boolean accept(AuditEvent event) {
071        return filters.accept(event);
072    }
073
074    @Override
075    public boolean equals(Object obj) {
076        if (this == obj) {
077            return true;
078        }
079        if (obj == null || getClass() != obj.getClass()) {
080            return false;
081        }
082        final SuppressionFilter suppressionFilter = (SuppressionFilter) obj;
083        return Objects.equals(filters, suppressionFilter.filters);
084    }
085
086    @Override
087    public int hashCode() {
088        return Objects.hash(filters);
089    }
090
091    @Override
092    protected void finishLocalSetup() throws CheckstyleException {
093        if (file != null) {
094            if (optional) {
095                if (suppressionSourceExists(file)) {
096                    filters = SuppressionsLoader.loadSuppressions(file);
097                }
098                else {
099                    filters = new FilterSet();
100                }
101            }
102            else {
103                filters = SuppressionsLoader.loadSuppressions(file);
104            }
105        }
106    }
107
108    /**
109     * Checks if suppression source with given fileName exists.
110     * @param fileName name of the suppressions file.
111     * @return true if suppression file exists, otherwise false
112     */
113    private static boolean suppressionSourceExists(String fileName) {
114        boolean suppressionSourceExists = true;
115        InputStream sourceInput = null;
116        try {
117            final URI uriByFilename = CommonUtils.getUriByFilename(fileName);
118            final URL url = uriByFilename.toURL();
119            sourceInput = url.openStream();
120        }
121        catch (CheckstyleException | IOException ignored) {
122            suppressionSourceExists = false;
123        }
124        finally {
125            if (sourceInput != null) {
126                try {
127                    sourceInput.close();
128                }
129                catch (IOException ignored) {
130                    suppressionSourceExists = false;
131                }
132            }
133        }
134        return suppressionSourceExists;
135    }
136}