View Javadoc

1   /*
2    * $Header: /usr/local/cvsroot/dev/madcache/src/com/macvu/tiles/CacheTilesRequestProcessor.java,v 1.3 2004/05/06 02:18:54 macvu Exp $
3    * $Revision: 1.3 $
4    * $Date: 2004/05/06 02:18:54 $
5    *
6    * ====================================================================
7    *
8    * The Apache Software License, Version 1.1
9    *
10   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
11   * reserved.
12   *
13   * Redistribution and use in source and binary forms, with or without
14   * modification, are permitted provided that the following conditions
15   * are met:
16   *
17   * 1. Redistributions of source code must retain the above copyright
18   *    notice, this list of conditions and the following disclaimer.
19   *
20   * 2. Redistributions in binary form must reproduce the above copyright
21   *    notice, this list of conditions and the following disclaimer in
22   *    the documentation and/or other materials provided with the
23   *    distribution.
24   *
25   * 3. The end-user documentation included with the redistribution, if
26   *    any, must include the following acknowlegement:
27   *       "This product includes software developed by the
28   *        Apache Software Foundation (http://www.apache.org/)."
29   *    Alternately, this acknowlegement may appear in the software itself,
30   *    if and wherever such third-party acknowlegements normally appear.
31   *
32   * 4. The names "The Jakarta Project", "Struts", and "Apache Software
33   *    Foundation" must not be used to endorse or promote products derived
34   *    from this software without prior written permission. For written
35   *    permission, please contact apache@apache.org.
36   *
37   * 5. Products derived from this software may not be called "Apache"
38   *    nor may "Apache" appear in their names without prior written
39   *    permission of the Apache Group.
40   *
41   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52   * SUCH DAMAGE.
53   * ====================================================================
54   *
55   * This software consists of voluntary contributions made by many
56   * individuals on behalf of the Apache Software Foundation.  For more
57   * information on the Apache Software Foundation, please see
58   * <http://www.apache.org/>.
59   *
60   */
61  
62  package com.macvu.tiles;
63  
64  import com.macvu.tiles.cache.CacheObjectWrapper;
65  import com.macvu.tiles.capture.CacheHttpServletResponse;
66  import com.macvu.tiles.capture.CacheablesCaptureWrapper;
67  import org.apache.commons.logging.Log;
68  import org.apache.commons.logging.LogFactory;
69  import org.apache.struts.tiles.*;
70  
71  import javax.servlet.ServletContext;
72  import javax.servlet.ServletException;
73  import javax.servlet.http.HttpServletRequest;
74  import javax.servlet.http.HttpServletResponse;
75  import java.io.IOException;
76  
77  /***
78   * Created by IntelliJ IDEA.
79   * User: MVu
80   * Date: Mar 10, 2004
81   * Time: 2:09:10 PM
82   * <p/>
83   * Implement the Struts RequestProcessor that handle the cache TilesRequestProcessor.
84   * Need to handle the caching information.
85   * To use CacheTilesRequestProcessor add to struts-config: <controller processorClass="com.macvu.tiles.CacheTilesRequestProcessor" debug="0" contentType="text/html"/>
86   */
87  public class CacheTilesRequestProcessor extends TilesRequestProcessor {
88      /***
89       * Commons Logging instance.
90       */
91      protected static Log log = LogFactory.getLog(CacheTilesRequestProcessor.class);
92  
93      /***
94       * Process a Tile definition name.
95       * This method tries to process the parameter <code>definitionName</code> as a definition name.
96       * It returns <code>true</code> if a definition has been processed, or <code>false</code> otherwise.
97       * Parameter <code>contextRelative</code> is not used in this implementation.
98       *
99       * @param definitionName  Definition name to insert.
100      * @param contextRelative Is the definition marked contextRelative ?
101      * @param request         Current page request.
102      * @param response        Current page response.
103      * @return <code>true</code> if the method has processed uri as a definition name, <code>false</code> otherwise.
104      */
105     protected boolean processTilesDefinition(String definitionName, boolean contextRelative, HttpServletRequest request, HttpServletResponse response)
106             throws IOException, ServletException {
107         if (log.isDebugEnabled()) {
108             log.debug("doForward(" + definitionName + ")");
109         }
110         // Do we do a forward (original behavior) or an include ?
111         boolean doInclude = false;
112         // Controller associated to a definition, if any
113         Controller controller = null;
114         // Computed uri to include
115         String uri = null;
116         ComponentContext tileContext = null;
117 
118         CacheObjectWrapper cacheController = new CacheObjectWrapper();
119 
120         if (log.isDebugEnabled()) {
121             log.debug("Processing tile: " + definitionName);
122         }
123         try {
124             // Get current tile context if any.
125             // If context exist, we will do an include
126             tileContext = ComponentContext.getContext(request);
127             doInclude = (tileContext != null);
128             ComponentDefinition definition;
129 
130             // Process tiles definition names only if a definition factory exist,
131             // and definition is found.
132             if (definitionsFactory != null) { // Get definition of tiles/component corresponding to uri.
133                 definition = definitionsFactory.getDefinition(definitionName, request, getServletContext());
134                 if (definition != null) { // We have a definition.
135                     // We use it to complete missing attribute in context.
136                     // We also get uri, controller.
137                     uri = definition.getPath();
138                     controller = definition.getOrCreateController();
139                     if (tileContext == null) {
140                         tileContext = new ComponentContext(definition.getAttributes());
141                         ComponentContext.setContext(tileContext, request);
142                     } else {
143                         tileContext.addMissing(definition.getAttributes());
144                     }
145 
146                     ServletContext context = getServletContext();
147                     if (log.isDebugEnabled()) {
148                         log.debug("Tile " + definition.getName() + " is of type " + definition.getClass().getName());
149                     }
150                     if (definition instanceof CacheComponentDefinition) {
151                         if (log.isDebugEnabled()) {
152                             log.debug("definition is a Cache Component");
153                         }
154                         CacheInformation info = ((CacheComponentDefinition) definition).getCacheInformation();
155                         cacheController.initiateCacheInformation(context, info);
156 
157                         //  Capture the Cacheable Information.
158                         CacheablesCaptureWrapper cacheables = new CacheablesCaptureWrapper(context);
159                         if (cacheables.isEnableCapture()) {
160                             if (log.isDebugEnabled()) {
161                                 log.debug("Capture the component defintion");
162                             }
163                             cacheables.captureCacheablesForTile((CacheComponentDefinition) definition, request);
164                         }
165                     }
166                 } // end if
167             } // end if
168 
169             // Process definition set in Action, if any.
170             definition = DefinitionsUtil.getActionDefinition(request);
171             if (definition != null) { // We have a definition.
172                 // We use it to complete missing attribute in context.
173                 // We also overload uri and controller if set in definition.
174                 if (definition.getPath() != null) {
175                     uri = definition.getPath();
176                 }
177                 if (definition.getOrCreateController() != null) {
178                     controller = definition.getOrCreateController();
179                 }
180                 if (tileContext == null) {
181                     tileContext = new ComponentContext(definition.getAttributes());
182                     ComponentContext.setContext(tileContext, request);
183                 } else {
184                     tileContext.addMissing(definition.getAttributes());
185                 }
186             } // end if
187 
188 
189         } catch (java.lang.InstantiationException ex) {
190             if (log.isErrorEnabled()) {
191                 log.error("Can't create associated controller", ex);
192             }
193             throw new ServletException("Can't create associated controller", ex);
194         } catch (DefinitionsFactoryException ex) {
195             throw new ServletException(ex);
196         }
197 
198         // Have we found a definition ?
199         if (uri == null) {
200             return false;
201         }
202 
203         String key = null;
204 
205         if (cacheController.isCacheEnabled()) {
206             if (log.isDebugEnabled()) {
207                 log.debug("Caching is enable.  perform cache");
208             }
209             key = cacheController.getCacheKey(request);
210 
211             String cache = (String) cacheController.getCache(key);
212             if (cache == null) {
213                 CacheHttpServletResponse cacheResponse = new CacheHttpServletResponse(response);
214                 // Passing in the cacheResponse.
215                 processTileSection(controller, tileContext, request, cacheResponse, uri, doInclude);
216 
217                 cacheController.putCache(key, cacheResponse.getCache());
218             } else {
219                 response.getWriter().write(cache);
220             }
221         } else {
222             processTileSection(controller, tileContext, request, response, uri, doInclude);
223         }
224 
225         return true;
226     }
227 
228     private void processTileSection(Controller controller, ComponentContext tileContext, HttpServletRequest request, HttpServletResponse response, String uri, boolean doInclude) throws ServletException, IOException {
229         // Process the definition
230         // Execute controller associated to definition, if any.
231         if (controller != null) {
232             controller.perform(tileContext, request, response, getServletContext());
233         } // end if
234 
235         // If request comes from a previous Tile, do an include.
236         // This allows to insert an actions in a Tile.
237         if (log.isDebugEnabled()) {
238             log.debug("uri=" + uri + " doInclude=" + doInclude);
239         }
240         if (doInclude) {
241             doInclude(uri, request, response);
242         } else {
243             doForward(uri, request, response);   // original behavior
244         }
245     }
246 
247 }
248