View Javadoc

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