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 2016 ForgeRock AS.
015 */
016
017package org.forgerock.opendj.rest2ldap.authz;
018
019import static org.forgerock.util.Reject.checkNotNull;
020
021import org.forgerock.http.Filter;
022import org.forgerock.http.Handler;
023import org.forgerock.http.protocol.Request;
024import org.forgerock.http.protocol.Response;
025import org.forgerock.http.protocol.Status;
026import org.forgerock.services.context.Context;
027import org.forgerock.util.promise.NeverThrowsException;
028import org.forgerock.util.promise.Promise;
029
030/** Encapsulate a {@link Condition} which must be fulfilled in order to apply the Filter. */
031public final class ConditionalFilters {
032
033    /** Encapsulate a {@link Filter} which will be processed only if the attached {@link Condition} is true. */
034    public interface ConditionalFilter {
035        /**
036         * Get the filter which must be processed if the {@link Condition} evaluates to true.
037         *
038         * @return The filter to process.
039         */
040        Filter getFilter();
041
042        /**
043         * Get the {@link Condition} to evaluate.
044         *
045         * @return the {@link Condition} to evaluate.
046         */
047        Condition getCondition();
048    }
049
050    /** Condition which have to be fulfilled in order to apply the {@link Filter}. */
051    public interface Condition {
052        /**
053         * Check if a {@link Filter} must be executed or not.
054         *
055         * @param context
056         *            Current {@link Context} of the request processing.
057         * @param request
058         *            the {@link Request} currently processed.
059         * @return true if the filter must be applied.
060         */
061        boolean canApplyFilter(Context context, Request request);
062    }
063
064    /** {@link Condition} which always returns true. */
065    public static final Condition ALWAYS_TRUE = new Condition() {
066        @Override
067        public boolean canApplyFilter(Context context, Request request) {
068            return true;
069        }
070    };
071
072    /** {@link Condition} which always returns false. */
073    public static final Condition ALWAYS_FALSE = new Condition() {
074        @Override
075        public boolean canApplyFilter(Context context, Request request) {
076            return false;
077        }
078    };
079
080    /** {@link ConditionalFilter} with an ALWAYS_FALSE {@link Condition}. */
081    public static final ConditionalFilter NEVER_APPLICABLE = newConditionalFilter(new Filter() {
082        @Override
083        public Promise<Response, NeverThrowsException> filter(Context context, Request request, Handler next) {
084            return Response.newResponsePromise(new Response(Status.NOT_IMPLEMENTED));
085        }
086    }, ALWAYS_FALSE);
087
088    private ConditionalFilters() {
089    }
090
091    /**
092     * Wrap a {@link Filter} into a {@link ConditionalFilter} with an ALWAYS_TRUE condition.
093     *
094     * @param filter
095     *            The {@link Filter} to wrap.
096     * @return a new {@link ConditionalFilter}
097     * @throws NullPointerException
098     *             if filter is null
099     */
100    public static ConditionalFilter asConditionalFilter(final Filter filter) {
101        return newConditionalFilter(filter, ALWAYS_TRUE);
102    }
103
104    /**
105     * Create a {@link ConditionalFilter} from a {@link Filter} and a {@link Condition}.
106     *
107     * @param filter
108     *            {@link Filter} which must be processed if the condition is true.
109     * @param condition
110     *            {@link Condition} to evaluate.
111     * @return a new {@link ConditionalFilter}
112     * @throws NullPointerException
113     *             if a parameter is null
114     */
115    public static ConditionalFilter newConditionalFilter(final Filter filter, final Condition condition) {
116        checkNotNull(filter, "filter cannot be null");
117        checkNotNull(condition, "condition cannot be null");
118        return new ConditionalFilter() {
119            @Override
120            public Filter getFilter() {
121                return filter;
122            }
123
124            @Override
125            public Condition getCondition() {
126                return condition;
127            }
128        };
129    }
130}