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 }