2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

Coverage Report - org.apache.shale.application.faces.ShaleApplicationFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
ShaleApplicationFilter
0%
0/99
0%
0/18
7.5
 
 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  
 
 18  
 package org.apache.shale.application.faces;
 19  
 
 20  
 import java.io.IOException;
 21  
 import java.lang.reflect.Method;
 22  
 import java.net.URL;
 23  
 
 24  
 import javax.servlet.Filter;
 25  
 import javax.servlet.FilterChain;
 26  
 import javax.servlet.FilterConfig;
 27  
 import javax.servlet.ServletContext;
 28  
 import javax.servlet.ServletException;
 29  
 import javax.servlet.ServletRequest;
 30  
 import javax.servlet.ServletResponse;
 31  
 import javax.servlet.http.HttpServletRequest;
 32  
 import javax.servlet.http.HttpServletResponse;
 33  
 
 34  
 import org.apache.commons.chain.Catalog;
 35  
 import org.apache.commons.chain.CatalogFactory;
 36  
 import org.apache.commons.chain.Command;
 37  
 import org.apache.commons.chain.config.ConfigParser;
 38  
 import org.apache.commons.chain.impl.CatalogBase;
 39  
 import org.apache.commons.chain.web.WebContext;
 40  
 import org.apache.commons.chain.web.servlet.ServletWebContext;
 41  
 import org.apache.commons.logging.Log;
 42  
 import org.apache.commons.logging.LogFactory;
 43  
 import org.apache.shale.util.Messages;
 44  
 
 45  
 
 46  
 /**
 47  
  * <p>{@link ShaleApplicationFilter} is a <code>Filter</code> implementation
 48  
  * that invokes the required <em>Application Controller</em> functionality on
 49  
  * every request.
 50  
  * In addition, it performs overall application startup and shutdown
 51  
  * operations on behalf of the framework.</p>
 52  
  *
 53  
  * <p>The detailed processing to be performed for each request is configured
 54  
  * by a <code>Command</code> or <code>Chain</code> defined using the "Chain of
 55  
  * Resposibility" design pattern, as implemented by the Commons Chain package.
 56  
  * There must exist a <code>Catalog</code> named <code>shale</code>, which
 57  
  * contains a <code>Command</code> named <code>standard</code>, that defines
 58  
  * the processing to be performed.</p>
 59  
  *
 60  
  * <p>At any point, one of the <code>Command</code>s being executed may choose
 61  
  * to complete the response itself (such as to perform an HTTP redirect),
 62  
  * instead of allowing processing to continue.  To indicate this choice, the
 63  
  * <code>Command</code> should follow the standard Commons Chain convention of
 64  
  * returning <code>true</code>.  If you want processing to continue, return
 65  
  * <code>false</code> instead.</p>
 66  
  *
 67  
  * <p>The default implementation of the standard command processing chain
 68  
  * performs the following tasks:</p>
 69  
  * <ul>
 70  
  * <li>Invoke a command named <code>preprocess</code> (in the <code>shale</code>
 71  
  *     catalog), if it exists.  This is where you should insert commands to be
 72  
  *     executed <strong>before</strong> {@link ShaleApplicationFilter} passes the
 73  
  *     request on to the next filter or servlet.</li>
 74  
  * <li>Execute the remainder of the filter chain for this request.</li>
 75  
  * <li>Invokes a command named <code>postprocess</code> (in the <code>shale</code>
 76  
  *     catalog), if it exists.  This is where you should insert commands to be
 77  
  *     executed <strong>after</strong> control returns from the invoked filter or
 78  
  *     servlet.  Note that it is no longer possible, at this point, to replace
 79  
  *     the response content produced by the filter or servlet -- that should
 80  
  *     be done in a preprocess step.</li>
 81  
  * </ul>
 82  
  *
 83  
  * <p><strong>NOTE</strong> - Configuration of the <code>shale</code> catalog,
 84  
  * and the commands it contains, may be performed in any manner you desire.
 85  
  * One convenient mechanism is to use the <code>ChainListener</code> class
 86  
  * that is included in the Commons Chain package.  If you do not reconfigure it
 87  
  * differently, the <code>standard</code> command (in the <code>shale</code>
 88  
  * catalog) will be configured according to the embedded resource
 89  
  * <code>org/apache/shale/faces/shale-config.xml</code> in the JAR file
 90  
  * containing the core Shale runtime environment, which executes the default
 91  
  * request processing described above.</p>
 92  
  *
 93  
  * $Id: ShaleApplicationFilter.java 464373 2006-10-16 04:21:54Z rahul $
 94  
  */
 95  
 
 96  0
 public class ShaleApplicationFilter implements Filter {
 97  
 
 98  
 
 99  
     // -------------------------------------------------------- Static Variables
 100  
 
 101  
 
 102  
     /**
 103  
      * <p>The name of the Commons Chain <code>Catalog</code> to use.</p>
 104  
      */
 105  
     public static final String CATALOG_NAME = "shale";
 106  
 
 107  
 
 108  
     /**
 109  
      * <p>The name of the <code>Command</code> to execute during
 110  
      * application shutdown.</p>
 111  
      */
 112  
     public static final String COMMAND_DESTROY = "destroy";
 113  
 
 114  
 
 115  
     /**
 116  
      * <p>The name of the <code>Command</code> to execute during
 117  
      * application startup.</p>
 118  
      */
 119  
     public static final String COMMAND_INIT = "init";
 120  
 
 121  
 
 122  
     /**
 123  
      * <p>The name of the <code>Command</code> to execute before
 124  
      * the application logic itself is invoked.</p>
 125  
      */
 126  
     public static final String COMMAND_PREPROCESS = "preprocess";
 127  
 
 128  
 
 129  
     /**
 130  
      * <p>The name of the <code>Command</code> to execute after
 131  
      * the application logic itself is invoked.</p>
 132  
      */
 133  
     public static final String COMMAND_POSTPROCESS = "postprocess";
 134  
 
 135  
 
 136  
     /**
 137  
      * <p>The request scope attribute key under which the <code>Context</code>
 138  
      * object used for this chain of command request to be stored, in addition
 139  
      * to it being passed in to the command chains.</p>
 140  
      */
 141  
     public static final String CONTEXT_ATTR =
 142  
       "org.apache.shale.CONTEXT_ATTR";
 143  
 
 144  
 
 145  
     /**
 146  
      * <p>The name of the internal resource containing our default
 147  
      * configuration of the default command.</p>
 148  
      */
 149  
     public static final String RESOURCE_NAME =
 150  
       "org/apache/shale/application/faces/shale-config.xml";
 151  
 
 152  
 
 153  
     // ------------------------------------------------------ Instance Variables
 154  
 
 155  
 
 156  
     /**
 157  
      * <p>Chain of Responsibility <code>Catalog</code> we will be using.</p>
 158  
      */
 159  0
     private Catalog catalog = null;
 160  
 
 161  
 
 162  
     /**
 163  
      * <p>The <code>ServletContext</code> instance for our web application.</p>
 164  
      */
 165  0
     private ServletContext context = null;
 166  
 
 167  
 
 168  
     /**
 169  
      * <p>The <code>Log</code> instance for this class.</p>
 170  
      */
 171  0
     private transient Log log = null;
 172  
 
 173  
 
 174  
     /**
 175  
      * <p>Message resources for this class.</p>
 176  
      */
 177  0
     private static Messages messages =
 178  
       new Messages("org.apache.shale.resources.Bundle",
 179  0
                    ShaleApplicationFilter.class.getClassLoader());
 180  
 
 181  
 
 182  
     // ---------------------------------------------------------- Filter Methods
 183  
 
 184  
 
 185  
     /**
 186  
      * <p>Perform application shutdown finalization as necessary.</p>
 187  
      */
 188  
     public void destroy() {
 189  
 
 190  0
         if (log().isInfoEnabled()) {
 191  0
             log().info(messages.getMessage("filter.finalizing"));
 192  
         }
 193  
 
 194  
         // Execute the "destroy" command in the "shale" catalog (if any)
 195  0
         Command command = catalog.getCommand(COMMAND_DESTROY);
 196  0
         if (command != null) {
 197  0
             WebContext webContext = new ServletWebContext(context, null, null);
 198  
             try {
 199  0
                 command.execute(webContext);
 200  0
             } catch (Exception e) {
 201  0
                 if (log().isErrorEnabled()) {
 202  0
                     log().error(messages.getMessage("filter.destroyException"), e);
 203  
                 }
 204  0
             }
 205  
         }
 206  
 
 207  
         // Clean up JavaServer Faces integration linkages
 208  0
         context = null;
 209  0
         catalog = null;
 210  
 
 211  
         // Clean up subordinate libraries as needed
 212  0
         CatalogFactory.clear();
 213  0
         cleanup();
 214  0
         LogFactory.release(Thread.currentThread().getContextClassLoader());
 215  
 
 216  0
     }
 217  
 
 218  
 
 219  
     /**
 220  
      * <p>Perform per-request application controler functionality.</p>
 221  
      *
 222  
      * @param request The request we are processing
 223  
      * @param response The response we are creating
 224  
      * @param chain The filter chain for this request
 225  
      *
 226  
      * @exception IOException if an input/output error occurs
 227  
      * @exception ServletException if a servlet exception is thrown
 228  
      */
 229  
     public void doFilter(ServletRequest request, ServletResponse response,
 230  
       FilterChain chain) throws IOException, ServletException {
 231  
 
 232  
       // Define local variables we will need
 233  0
       Command command = null;
 234  0
       boolean result = false;
 235  
 
 236  
       // Construct and store a new Context for this request
 237  0
       ShaleWebContext context =
 238  
         new ShaleWebContext(this.context,
 239  
           (HttpServletRequest) request,
 240  
           (HttpServletResponse) response);
 241  0
       request.setAttribute(CONTEXT_ATTR, context);
 242  
 
 243  
       // Invoke the "preprocess" command (if any is defined).  If this
 244  
       // command returns true, the response has been completed already
 245  
       // so we do NOT invoke the actual application.
 246  0
       command = catalog.getCommand(COMMAND_PREPROCESS);
 247  0
       if (command != null) {
 248  
           try {
 249  0
               result = command.execute(context);
 250  0
           } catch (IOException e) {
 251  0
               throw e;
 252  0
           } catch (ServletException e) {
 253  0
               throw e;
 254  0
           } catch (Exception e) {
 255  0
               throw new ServletException(e);
 256  0
           }
 257  0
           if (result) {
 258  
               // Clean up the stored request attribute
 259  0
               request.removeAttribute(CONTEXT_ATTR);
 260  
               // Bypass calling the remainder of the application
 261  0
               return;
 262  
           }
 263  
       }
 264  
 
 265  
       // Invoke the remainder of the processing for this request
 266  
       // (which will typically be the JSF controller servlet)
 267  0
       chain.doFilter(request, response);
 268  
 
 269  
       // Invoke the "postprocess" command (if any is defined).
 270  0
       command = catalog.getCommand(COMMAND_POSTPROCESS);
 271  0
       if (command != null) {
 272  
           try {
 273  0
               command.execute(context);
 274  0
           } catch (IOException e) {
 275  0
               throw e;
 276  0
           } catch (ServletException e) {
 277  0
               throw e;
 278  0
           } catch (Exception e) {
 279  0
               throw new ServletException(e);
 280  0
           }
 281  
       }
 282  
 
 283  
       // Clean up the stored request attribute
 284  0
       request.removeAttribute(CONTEXT_ATTR);
 285  
 
 286  0
     }
 287  
 
 288  
 
 289  
     /**
 290  
      * <p>Perform application startup intiialization as necessary.</p>
 291  
      *
 292  
      * @param config <code>FilterConfig</code> for this filter
 293  
      *
 294  
      * @exception ServletException if a servlet exception is thrown
 295  
      */
 296  
     public void init(FilterConfig config) throws ServletException {
 297  
 
 298  0
         if (log().isInfoEnabled()) {
 299  0
             log().info(messages.getMessage("filter.initializing"));
 300  
         }
 301  
 
 302  0
         context = config.getServletContext();
 303  
 
 304  
         // Look up the "shale" catalog and ensure "standard" is defined
 305  
         try {
 306  0
             catalog = getCatalog();
 307  0
         } catch (ServletException e) {
 308  0
             throw e;
 309  0
         } catch (Exception e) {
 310  0
             throw new ServletException(e);
 311  0
         }
 312  
 
 313  
         // Execute the "init" command in the "shale" catalog (if any)
 314  0
         Command command = catalog.getCommand(COMMAND_INIT);
 315  0
         if (command != null) {
 316  0
             WebContext webContext = new ServletWebContext(context, null, null);
 317  
             try {
 318  0
                 command.execute(webContext);
 319  0
             } catch (Exception e) {
 320  0
                 if (log().isErrorEnabled()) {
 321  0
                     log().error(messages.getMessage("filter.initException"), e);
 322  
                 }
 323  0
                 throw new ServletException(e);
 324  0
             }
 325  
         }
 326  
 
 327  0
     }
 328  
 
 329  
 
 330  
     // --------------------------------------------------------- Private Methods
 331  
 
 332  
 
 333  
     /**
 334  
      * <p>Clean up the Commons BeanUtils library if it has been loaded.</p>
 335  
      */
 336  
     private void cleanup() {
 337  
 
 338  
         try {
 339  0
             ClassLoader loader = Thread.currentThread().getContextClassLoader();
 340  0
             if (loader == null) {
 341  0
                 loader = ShaleApplicationFilter.class.getClassLoader();
 342  
             }
 343  0
             Class clazz = loader.loadClass("org.apache.commons.beanutils.PropertyUtils");
 344  0
             Method method = clazz.getMethod("clearDescriptors", (Class[]) null);
 345  0
             method.invoke(null, (Object[]) null);
 346  0
         } catch (Exception e) {
 347  
             ; // Swallow and ignore any exceptions
 348  0
         }
 349  
 
 350  0
     }
 351  
 
 352  
 
 353  
 
 354  
     /**
 355  
      * <p>Return the "shale" catalog with a "standard" command, configuring the
 356  
      * default version of this command if necessary.</p>
 357  
      *
 358  
      * @exception Exception if a resource parsing exception occurs
 359  
      */
 360  
     private Catalog getCatalog() throws Exception {
 361  
 
 362  
         // Look up the "shale" catalog, returning any existing instance
 363  
         // if it is fully configured
 364  0
         Catalog catalog = CatalogFactory.getInstance().getCatalog(CATALOG_NAME);
 365  0
         if ((catalog != null) &&
 366  
             (catalog.getCommand(COMMAND_INIT) != null) &&
 367  
             (catalog.getCommand(COMMAND_DESTROY) != null)) {
 368  0
             return catalog;
 369  
         }
 370  
 
 371  
         // Create a new catalog (if necessary)
 372  0
         if (catalog == null) {
 373  0
             if (log().isDebugEnabled()) {
 374  0
                 log().debug(messages.getMessage("filter.creatingCatalog",
 375  
                                                 new Object[] { CATALOG_NAME }));
 376  
             }
 377  0
             catalog = new CatalogBase();
 378  0
             CatalogFactory.getInstance().addCatalog(CATALOG_NAME, catalog);
 379  
         }
 380  
 
 381  
         // Configure this catalog based on our default resource
 382  0
         if (log().isDebugEnabled()) {
 383  0
             log().debug(messages.getMessage("filter.parsingResource",
 384  
                                             new Object[] { RESOURCE_NAME }));
 385  
         }
 386  0
         ConfigParser parser = new ConfigParser();
 387  0
         URL url = this.getClass().getClassLoader().getResource(RESOURCE_NAME);
 388  0
         if (url == null) {
 389  0
             throw new IllegalArgumentException(RESOURCE_NAME);
 390  
         }
 391  0
         parser.parse(url);
 392  
 
 393  0
         return catalog;
 394  
 
 395  
     }
 396  
 
 397  
 
 398  
     /**
 399  
      * <p>Return the <code>Log</code> instance to use, creating one if needed.</p>
 400  
      */
 401  
     private Log log() {
 402  
 
 403  0
         if (this.log == null) {
 404  0
             log = LogFactory.getLog(ShaleApplicationFilter.class);
 405  
         }
 406  0
         return log;
 407  
 
 408  
     }
 409  
 
 410  
 
 411  
 }