Merge changes I6062ddfa,If91c0ea5,Idd92e1be,I224e0fb7,Iab290548, ...
[aaa.git] / aaa-filterchain / src / main / java / org / opendaylight / aaa / filterchain / filters / AAAFilterChain.java
1 /*
2  * Copyright (c) 2016 - 2017 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.aaa.filterchain.filters;
10
11 import java.io.IOException;
12 import java.util.Iterator;
13 import java.util.List;
14 import javax.servlet.Filter;
15 import javax.servlet.FilterChain;
16 import javax.servlet.ServletException;
17 import javax.servlet.ServletRequest;
18 import javax.servlet.ServletResponse;
19
20 /**
21  * Recreates the <code>javax.servlet.Filter</code> chain of responsibility
22  * Pattern to allow for programmatic injection of Filters. Essentially, the
23  * links of the injected chain are traversed, and if the Requests makes it
24  * through all of the injected Filters, then the original, existing chain is
25  * maintained.
26  *
27  * <p>
28  * This revision of code assumes that the url-pattern for injected filters is
29  * exactly the same as the one specified for <code>CustomFilterAdapter</code>.
30  */
31 public final class AAAFilterChain implements FilterChain {
32
33     // Must be stored locally to be used within
34     // javax.servlet.FilterChain.doFilter(
35     // ServletRequest, ServletResponse) due to rigid API contract.
36     private volatile Iterator<Filter> injectedFilterChainIterator;
37     private volatile FilterChain existingFilterChain;
38
39     private AAAFilterChain() {
40     }
41
42     public static AAAFilterChain createAAAFilterChain() {
43         return new AAAFilterChain();
44     }
45
46     @Override
47     public void doFilter(final ServletRequest request, final ServletResponse response)
48             throws IOException, ServletException {
49
50         // Recursive call using the next available link in the chain iterator If
51         // a "next" link does
52         // not exist and we have traversed the chain thus far, that means the
53         // Request has successfully
54         // traversed the injected filter chain links and we can invoke filtering
55         // on the existing chain.
56         if (injectedFilterChainIterator != null && injectedFilterChainIterator.hasNext()) {
57             injectedFilterChainIterator.next().doFilter(request, response, this);
58         } else if (existingFilterChain != null) {
59             existingFilterChain.doFilter(request, response);
60         }
61     }
62
63     /**
64      * A wrapper method used to inject a new Filter chain. Essentially, this
65      * just adds links to the existing chain.
66      *
67      * @param request
68      *            Wrapped parameter passed directly to
69      *            <code>doFilter(ServletRequest, ServletResponse)</code>
70      * @param response
71      *            Wrapped parameter passed directly to
72      *            <code>doFilter(ServletRequest, ServletResponse)</code>
73      * @param newExistingFilterChain
74      *            The chain provided from Jersey as defined in the Servlet's
75      *            <code>web.xml</code>
76      * @param injectedFilterChain
77      *            The programmatically injected chain, which may be empty
78      * @throws IOException
79      *             Wrapped exception handling from
80      *             <code>doFilter(ServletRequest, ServletResponse)</code>
81      * @throws ServletException
82      *             Wrapped exception handling from
83      *             <code>doFilter(ServletRequest, ServletResponse)</code>
84      */
85     public void doFilter(final ServletRequest request, final ServletResponse response,
86             final FilterChain newExistingFilterChain, final List<Filter> injectedFilterChain)
87             throws IOException, ServletException {
88
89         this.existingFilterChain = newExistingFilterChain;
90         this.injectedFilterChainIterator = injectedFilterChain.iterator();
91         doFilter(request, response);
92     }
93 }