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 2014-2015 ForgeRock AS.
015 */
016
017package org.forgerock.openig.audit.decoration;
018
019import static org.forgerock.util.Reject.*;
020
021import java.util.Set;
022import java.util.TreeSet;
023
024import org.forgerock.http.Filter;
025import org.forgerock.http.Handler;
026import org.forgerock.json.JsonValue;
027import org.forgerock.openig.decoration.Context;
028import org.forgerock.openig.decoration.helper.AbstractHandlerAndFilterDecorator;
029import org.forgerock.openig.heap.HeapException;
030
031/**
032 * The audit decorator can decorate both {@link Handler} and {@link Filter} instances.
033 * It triggers notifications ({@link org.forgerock.openig.audit.AuditEvent}) to an
034 * {@link org.forgerock.openig.audit.AuditSystem} sink.
035 * <p>
036 * Each {@link org.forgerock.openig.audit.AuditEvent} includes a source marker that will indicate that the event comes
037 * from the decorated component.
038 * <p>
039 * Each notification includes a set of <i>tags</i> that helps the notification receiver to filter the
040 * events with simple matching rules. Here is the list of built-in tags:
041 * <ul>
042 *     <li>{@link org.forgerock.openig.audit.Tag#request}: The event happens before the delegate
043 *     {@link Filter}/{@link Handler} is called</li>
044 *     <li>{@link org.forgerock.openig.audit.Tag#response}: The event happens after the delegate
045 *     {@link Filter}/{@link Handler} was called</li>
046 *     <li>{@link org.forgerock.openig.audit.Tag#completed}: The event happens when the request has been completely
047 *     handled <b>successfully</b>
048 *     by the processing unit (always complements a {@link org.forgerock.openig.audit.Tag#response} tag)</li>
049 *     <li>{@link org.forgerock.openig.audit.Tag#exception}: The event happens when the request has been handled
050 *     with <b>errors</b>
051 *     by the processing unit (always complements a {@link org.forgerock.openig.audit.Tag#response} tag).
052 *     Notice that this does not indicate that
053 *     the source heap object is the origin of the failure (it may or may not have thrown the exception itself).</li>
054 * </ul>
055 * <p>
056 * The user can add extra tags to the list of tags that decorates the notification, in order to help
057 * notification qualification:
058 * <pre>
059 *     {@code
060 *         "audit": "route-#1"  // add a single tag to the decorated component
061 *         "audit": [ "super-tag", "route-#2" ] // add all of theses tags
062 *         "audit": boolean, object, ... // any other format will be ignored
063 *     }
064 * </pre>
065 * <p>
066 * Notice that the attribute name in the decorated object <b>has to be</b> the same as the decorator
067 * heap object name ({@code audit} in our example).
068 * <p>
069 * A default {@literal audit} decorator is automatically created when OpenIG starts.
070 *
071 * @see Tag
072 */
073@Deprecated
074public class AuditDecorator extends AbstractHandlerAndFilterDecorator {
075
076    private final org.forgerock.openig.audit.AuditSystem auditSystem;
077
078    /**
079     * Builds a new AuditDecorator that will send events to the provided AuditSystem.
080     *
081     * @param auditSystem
082     *         AuditSystem reference (cannot be {@code null})
083     */
084    public AuditDecorator(final org.forgerock.openig.audit.AuditSystem auditSystem) {
085        this.auditSystem = checkNotNull(auditSystem);
086    }
087
088    @Override
089    protected Filter decorateFilter(final Filter delegate, final JsonValue decoratorConfig, final Context context)
090            throws HeapException {
091        return new AuditFilter(auditSystem, source(context), delegate, getAdditionalTags(decoratorConfig));
092    }
093
094    @Override
095    protected Handler decorateHandler(final Handler delegate, final JsonValue decoratorConfig, final Context context)
096            throws HeapException {
097        return new AuditHandler(auditSystem, source(context), delegate, getAdditionalTags(decoratorConfig));
098    }
099
100    private static org.forgerock.openig.audit.AuditSource source(final Context context) {
101        return new org.forgerock.openig.audit.AuditSource(context.getName());
102    }
103
104    private static Set<String> getAdditionalTags(final JsonValue config) {
105        Set<String> tags = new TreeSet<>();
106        if (config.isString()) {
107            tags.add(config.asString());
108        } else if (config.isList()) {
109            tags.addAll(config.asSet(String.class));
110        }
111        // otherwise, returns an empty set
112        return tags;
113    }
114}