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 2010-2011 ApexIdentity Inc. 015 * Portions Copyright 2011-2015 ForgeRock AS. 016 */ 017 018package org.forgerock.openig.filter; 019 020import static org.forgerock.openig.util.JsonValues.ofRequiredHeapObject; 021 022import java.util.List; 023 024import org.forgerock.http.Filter; 025import org.forgerock.http.Handler; 026import org.forgerock.http.handler.Handlers; 027import org.forgerock.http.protocol.Request; 028import org.forgerock.http.protocol.Response; 029import org.forgerock.json.JsonValue; 030import org.forgerock.openig.heap.GenericHeapObject; 031import org.forgerock.openig.heap.GenericHeaplet; 032import org.forgerock.openig.heap.HeapException; 033import org.forgerock.services.context.Context; 034import org.forgerock.util.promise.NeverThrowsException; 035import org.forgerock.util.promise.Promise; 036 037/** 038 * A chain of zero or more filters and one handler. The chain is responsible for 039 * dispatching the request to each filter in the chain, and finally the handler. 040 * <p> 041 * When a chain dispatches a request to a filter, it creates a "subchain" (a subset of this 042 * chain, which contains the remaining downstream filters and handler), and passes it as a 043 * parameter to the filter. For this reason, a filter should make no assumptions or 044 * correlations using the chain it is supplied with when invoked. 045 * <p> 046 * A filter may elect to terminate dispatching of the request to the rest of the chain by not 047 * calling {@code chain.handle(Context, Request)} and generate its own response or dispatch to a 048 * completely different handler. 049 * 050 * @see Filter 051 */ 052public class Chain extends GenericHeapObject implements Handler { 053 054 /** The CHF Chain implementation. */ 055 private final Handler delegate; 056 057 /** 058 * Builds a chain of filters that will finally dispatch to the given handler. 059 * List of Filters is empty by default. 060 * @param handler terminus of the chain 061 * @param filters list of {@link Filter}s 062 */ 063 public Chain(final Handler handler, final List<Filter> filters) { 064 delegate = Handlers.chainOf(handler, filters); 065 } 066 067 @Override 068 public Promise<Response, NeverThrowsException> handle(final Context context, final Request request) { 069 return delegate.handle(context, request); 070 } 071 072 /** Creates and initializes a filter chain in a heap environment. */ 073 public static class Heaplet extends GenericHeaplet { 074 @Override 075 public Object create() throws HeapException { 076 Handler terminus = heap.resolve(config.get("handler"), 077 Handler.class); 078 JsonValue list = config.get("filters") 079 .required() 080 .expect(List.class); 081 List<Filter> filters = list.asList(ofRequiredHeapObject(heap, Filter.class)); 082 return new Chain(terminus, filters); 083 } 084 } 085}