View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.portals.bridges.portletfilter;
18  
19  import java.io.IOException;
20  import java.util.StringTokenizer;
21  
22  import javax.portlet.ActionRequest;
23  import javax.portlet.ActionResponse;
24  import javax.portlet.Portlet;
25  import javax.portlet.PortletConfig;
26  import javax.portlet.PortletException;
27  import javax.portlet.RenderRequest;
28  import javax.portlet.RenderResponse;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  
33  /***
34   * A PortletFilterChain is an object provided to the developer giving a view 
35   * into the invocation chain of a filtered request for a resource. 
36   * PortletFilters use the PortletFilterChain to invoke the next filter in the 
37   * chain, or if the calling filter is the last filter in the chain, to invoke 
38   * the resource at the end of the chain.
39   * 
40   * @author <a href="mailto:shinsuke@yahoo.co.jp">Shinsuke Sugaya</a>
41   *
42   */
43  public class PortletFilterChain
44  {
45      private static final Log log = LogFactory.getLog(PortletFilterChain.class);
46  
47      // -------------------------------------------------------------- Constants
48  
49      public static final int INCREMENT = 10;
50  
51      public static final String PORTLET_FILTERS = "portlet-filters";
52  
53      /***
54       * PortletFilters.
55       */
56      private PortletFilterConfig[] filters = new PortletFilterConfig[0];
57  
58      /***
59       * The int which is used to maintain the current position in the filter chain.
60       */
61      private ThreadLocal renderPosition = new ThreadLocal();
62  
63      /***
64       * The int which is used to maintain the current position in the filter chain.
65       */
66      private ThreadLocal processActionPosition = new ThreadLocal();
67  
68      /***
69       * The int which gives the current number of filters in the chain.
70       */
71      private int n = 0;
72  
73      /***
74       * The portlet instance to be executed by this chain.
75       */
76      private Portlet portlet = null;
77  
78      public PortletFilterChain(PortletConfig config)
79      {
80          String portletFilters = config.getInitParameter(PORTLET_FILTERS);
81          StringTokenizer st = new StringTokenizer(portletFilters, ", ");
82          while (st.hasMoreTokens())
83          {
84              String className = st.nextToken();
85              try
86              {
87                  addPortletFilter(new PortletFilterConfig(className, config));
88              }
89              catch (PortletException e)
90              {
91                  log.warn("Invalid portlet filter: " + className, e);
92              }
93          }
94      }
95  
96      /***
97       * Causes the next filter for renderFilter in the chain to be invoked, or 
98       * if the calling filter is the last filter in the chain, causes the 
99       * resource at the end of the chain to be invoked.
100      * 
101      * @param request
102      * @param response
103      * @throws PortletException
104      * @throws IOException
105      */
106     public void renderFilter(RenderRequest request, RenderResponse response)
107             throws PortletException, IOException
108     {
109         // Call the next filter if there is one
110         int pos = ((Integer) renderPosition.get()).intValue();
111         if (pos < n)
112         {
113             PortletFilterConfig filterConfig = filters[pos++];
114             PortletFilter filter = filterConfig.getPortletFilter();
115             renderPosition.set(new Integer(pos));
116 
117             filter.renderFilter(request, response, this);
118 
119             renderPosition.set(new Integer(--pos));
120             return;
121         }
122 
123         // We fell off the end of the chain -- call the servlet instance
124         portlet.render(request, response);
125     }
126 
127     /***
128      * Causes the next filter for processActionFilter in the chain to be invoked, or 
129      * if the calling filter is the last filter in the chain, causes the 
130      * resource at the end of the chain to be invoked.
131      * 
132      * @param request
133      * @param response
134      * @throws PortletException
135      * @throws IOException
136      */
137     public void processActionFilter(ActionRequest request,
138             ActionResponse response) throws PortletException, IOException
139     {
140         // Call the next filter if there is one
141         int pos = ((Integer) processActionPosition.get()).intValue();
142         if (pos < n)
143         {
144             PortletFilterConfig filterConfig = filters[pos++];
145             PortletFilter filter = filterConfig.getPortletFilter();
146             processActionPosition.set(new Integer(pos));
147 
148             filter.processActionFilter(request, response, this);
149 
150             processActionPosition.set(new Integer(--pos));
151             return;
152         }
153 
154         // We fell off the end of the chain -- call the servlet instance
155         portlet.processAction(request, response);
156 
157     }
158 
159     /***
160      * Add a filter to the set of filters that will be executed in this chain.
161      * 
162      * @param filterConfig The PortletFilterConfig for the portlet to be executed
163      */
164     public void addPortletFilter(PortletFilterConfig filterConfig)
165     {
166         if (filterConfig != null && filterConfig.getPortletFilter() != null)
167         {
168             if (n == filters.length)
169             {
170                 PortletFilterConfig[] newFilters = new PortletFilterConfig[n
171                         + INCREMENT];
172                 System.arraycopy(filters, 0, newFilters, 0, n);
173                 filters = newFilters;
174             }
175             filters[n++] = filterConfig;
176         }
177     }
178 
179     /***
180      * Reset this filter chain
181      */
182     public void reset()
183     {
184         renderPosition.set(new Integer(0));
185         processActionPosition.set(new Integer(0));
186     }
187 
188     /***
189      * Release references to the filters and wrapper executed by this chain.
190      */
191     public void release()
192     {
193         for (int i = 0; i < n; i++)
194         {
195             filters[i].release();
196         }
197         portlet = null;
198     }
199 
200     /***
201      * Set Portlet instance.
202      * 
203      * @param portlet The portlet to set.
204      */
205     public void setPortlet(Portlet portlet)
206     {
207         this.portlet = portlet;
208     }
209 
210 }