001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2015-2016 ForgeRock AS.
015 */
016package org.forgerock.audit.filter;
017
018import java.util.Arrays;
019import java.util.LinkedHashMap;
020import java.util.LinkedList;
021import java.util.List;
022import java.util.Map;
023
024import org.forgerock.audit.AuditException;
025import org.forgerock.json.JsonPointer;
026import org.forgerock.util.Reject;
027import org.forgerock.util.Utils;
028import org.slf4j.Logger;
029import org.slf4j.LoggerFactory;
030
031/** Utility methods for creating audit event filters. */
032public final class Filters {
033    private static final Logger logger = LoggerFactory.getLogger(Filters.class);
034
035    /** The filter types. */
036    protected enum FilterNames {
037        /** Value event filter type. */
038        VALUE,
039        /** Field event filter type. */
040        FIELD
041    }
042
043    /**
044     * Create a new filter for values and fields.
045     *
046     * @param auditTopics The topics to filter.
047     * @param policy The policy to apply.
048     * @return The new filter.
049     */
050    public static ValueOrFieldFilter newValueOrFieldFilter(final List<String> auditTopics, final FilterPolicy policy) {
051        return new ValueOrFieldFilter(exclusionListPerTopic(auditTopics, policy));
052    }
053
054    /**
055     * Create a new filter for of the type specified.
056     *
057     * @param name The name of the filter type.
058     * @param auditTopics The topics to filter.
059     * @param policy The policy to apply.
060     * @return The filter.
061     * @throws AuditException If the type is unknown, or cannot be created.
062     */
063    public static ValueOrFieldFilter newFilter(final String name, final List<String> auditTopics,
064            final FilterPolicy policy) throws AuditException {
065        Reject.ifNull(name);
066        FilterNames filterName = Utils.asEnum(name, FilterNames.class);
067        switch (filterName) {
068        case VALUE:
069        case FIELD:
070            return newValueOrFieldFilter(auditTopics, policy);
071        default:
072            final String error = String.format("Unknown filter policy name: %s", name);
073            logger.error(error);
074            throw new AuditException(error);
075        }
076    }
077
078    private static Map<String, List<JsonPointer>> exclusionListPerTopic(final List<String> auditTopicsList,
079            final FilterPolicy policy) {
080        final Map<String, List<JsonPointer>> topicMap = initializeTopicMap(auditTopicsList);
081        for (final String value : policy.getExcludeIf()) {
082            addToTopicMap(value, topicMap);
083        }
084        return topicMap;
085    }
086
087    private static void addToTopicMap(final String value, final Map<String, List<JsonPointer>> topicMap) {
088        final JsonPointer pointer = new JsonPointer(value);
089        final String topic = pointer.get(0);
090        final JsonPointer exclusionPointer =
091                new JsonPointer(Arrays.copyOfRange(pointer.toArray(), 1, pointer.size()));
092        final List<JsonPointer> topicPolicies = topicMap.get(topic);
093        if (topicPolicies != null) {
094            topicPolicies.add(exclusionPointer);
095        } else {
096            logger.error(String.format("Attempting to create a policy for an audit topic not registered: %s", value));
097        }
098    }
099
100    private static Map<String, List<JsonPointer>> initializeTopicMap(final List<String> auditTopicsList) {
101        Map<String, List<JsonPointer>> topicMap = new LinkedHashMap<>(auditTopicsList.size());
102        for (final String auditTopic : auditTopicsList) {
103            topicMap.put(auditTopic, new LinkedList<JsonPointer>());
104        }
105        return topicMap;
106    }
107
108    private Filters() {
109        // utility class
110    }
111
112}