Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/opencms/flex/cache/CmsFlexRequest.java


1   /*
2    * File   : $Source: /usr/local/cvs/opencms/src/com/opencms/flex/cache/Attic/CmsFlexRequest.java,v $
3    * Date   : $Date: 2003/05/13 13:18:20 $
4    * Version: $Revision: 1.12.2.1 $
5    *
6    * This library is part of OpenCms -
7    * the Open Source Content Mananagement System
8    *
9    * Copyright (C) 2002 - 2003 Alkacon Software (http://www.alkacon.com)
10   *
11   * This library is free software; you can redistribute it and/or
12   * modify it under the terms of the GNU Lesser General Public
13   * License as published by the Free Software Foundation; either
14   * version 2.1 of the License, or (at your option) any later version.
15   *
16   * This library is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19   * Lesser General Public License for more details.
20   *
21   * For further information about Alkacon Software, please see the
22   * company website: http://www.alkacon.com
23   *
24   * For further information about OpenCms, please see the
25   * project website: http://www.opencms.org
26   * 
27   * You should have received a copy of the GNU Lesser General Public
28   * License along with this library; if not, write to the Free Software
29   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30   */
31  
32  package com.opencms.flex.cache;
33  
34  import com.opencms.core.A_OpenCms;
35  import com.opencms.file.CmsObject;
36  import com.opencms.flex.CmsEvent;
37  import com.opencms.flex.I_CmsEventListener;
38  
39  import java.util.Arrays;
40  import java.util.Collections;
41  import java.util.Enumeration;
42  import java.util.HashMap;
43  import java.util.Iterator;
44  import java.util.List;
45  import java.util.Map;
46  import java.util.Set;
47  
48  import javax.servlet.http.HttpServletRequest;
49  import javax.servlet.http.HttpServletRequestWrapper;
50  
51  /**
52   * Wrapper class for a HttpServletRequest.<p>
53   *
54   * This class wrapps the standard HttpServletRequest so that it's output can be delivered to
55   * the CmsFlexCache.
56   *
57   * @author Alexander Kandzior (a.kandzior@alkacon.com)
58   * @version $Revision: 1.12.2.1 $
59   */
60  public class CmsFlexRequest extends HttpServletRequestWrapper {
61      
62      /** The wrapped HttpServletRequest */    
63      private HttpServletRequest m_req = null;
64          
65      /** The requested resource (target resource) */    
66      private String m_resource = null;
67      
68      /** The CmsFlexCacheKey for this request */
69      private CmsFlexCacheKey m_key = null;
70      
71      /** The CmsFlexController for this request */
72      private CmsFlexController m_controller = null;
73      
74      /** Flag to decide if this request can be cached or not */
75      private boolean m_canCache = false;
76      
77      /** Flag to check if this request is in the online project or not */
78      private boolean m_isOnline = false;
79      
80      /** Flag to force a JSP recompile */
81      private boolean m_doRecompile = false; 
82      
83      /** Stores the request URI after it was once calculated */
84      private String m_requestUri = null;
85      
86      /** Stores the request URI after it was once calculated */
87      private StringBuffer m_requestUrl = null;
88          
89      /** Set of all include calls (to prevent an endless inclusion loop) */
90      private Set m_includeCalls;    
91      
92      /** Map of parameters from the original request */
93      private Map m_parameters = null;
94      
95      /** Attribute name used for checking if _flex request parameters have already been processed */
96      public static String ATTRIBUTE_PROCESSED = "__com.opencms.flex.cache.CmsFlexRequest";
97      
98      /** Debug flag */
99      private static final boolean DEBUG = false;
100             
101     /**
102      * Creates a new CmsFlexRequest wrapper which is most likley the "Top"
103      * request wrapper, i.e. the wrapper that is constructed around the
104      * first "real" (not wrapped) request.<p>
105      *
106      * @param req the request to wrap
107      * @param controller the controller to use
108      */    
109     public CmsFlexRequest(HttpServletRequest req, CmsFlexController controller) {
110         super(req);
111         m_req = req;
112         m_controller = controller;
113         m_resource = m_controller.getCmsFile().getAbsolutePath();
114         CmsObject cms = m_controller.getCmsObject();
115         m_includeCalls = Collections.synchronizedSet(new java.util.HashSet(23));
116         m_parameters = req.getParameterMap();
117         try {
118             m_isOnline = cms.getRequestContext().currentProject().isOnlineProject();
119         } catch (Exception e) {}        
120         String[] paras = req.getParameterValues("_flex");
121         boolean nocachepara = false;
122         boolean dorecompile = false;
123         boolean isAdmin = false;
124         if (paras != null) {
125             try {
126                 isAdmin = cms.getRequestContext().isAdmin();
127             } catch (Exception e) {}
128             if (isAdmin) {                        
129                 List l = Arrays.asList(paras);
130                 String context = (String)req.getAttribute(ATTRIBUTE_PROCESSED);
131                 boolean firstCall = (context == null);
132                 if (firstCall) req.setAttribute(ATTRIBUTE_PROCESSED, "true");
133                 nocachepara = l.contains("nocache");            
134                 dorecompile = l.contains("recompile");
135                 boolean p_on = l.contains("online");
136                 boolean p_off = l.contains("offline");                
137                 if (l.contains("purge") && firstCall) {
138                     A_OpenCms.fireCmsEvent(new CmsEvent(cms, I_CmsEventListener.EVENT_FLEX_PURGE_JSP_REPOSITORY, new java.util.HashMap(0)));
139                     A_OpenCms.fireCmsEvent(new CmsEvent(cms, I_CmsEventListener.EVENT_FLEX_CACHE_CLEAR, Collections.singletonMap("action", new Integer(CmsFlexCache.C_CLEAR_ENTRIES))));
140                     dorecompile = false;
141                 } else if ((l.contains("clearcache") || dorecompile) && firstCall) {
142                     if (! (p_on || p_off)) {
143                         A_OpenCms.fireCmsEvent(new CmsEvent(cms, I_CmsEventListener.EVENT_FLEX_CACHE_CLEAR, Collections.singletonMap("action", new Integer(CmsFlexCache.C_CLEAR_ALL))));
144                     } else {
145                         if (p_on) A_OpenCms.fireCmsEvent(new CmsEvent(cms, I_CmsEventListener.EVENT_FLEX_CACHE_CLEAR, Collections.singletonMap("action", new Integer(CmsFlexCache.C_CLEAR_ONLINE_ALL))));
146                         if (p_off) A_OpenCms.fireCmsEvent(new CmsEvent(cms, I_CmsEventListener.EVENT_FLEX_CACHE_CLEAR, Collections.singletonMap("action", new Integer(CmsFlexCache.C_CLEAR_OFFLINE_ALL))));
147                     }                    
148                 } else if (l.contains("clearvariations") && firstCall) {
149                     if (! (p_on || p_off)) {
150                         A_OpenCms.fireCmsEvent(new CmsEvent(cms, I_CmsEventListener.EVENT_FLEX_CACHE_CLEAR, Collections.singletonMap("action", new Integer(CmsFlexCache.C_CLEAR_ENTRIES))));
151                     } else {
152                         if (p_on) A_OpenCms.fireCmsEvent(new CmsEvent(cms, I_CmsEventListener.EVENT_FLEX_CACHE_CLEAR, Collections.singletonMap("action", new Integer(CmsFlexCache.C_CLEAR_ONLINE_ENTRIES))));
153                         if (p_off)  A_OpenCms.fireCmsEvent(new CmsEvent(cms, I_CmsEventListener.EVENT_FLEX_CACHE_CLEAR, Collections.singletonMap("action", new Integer(CmsFlexCache.C_CLEAR_OFFLINE_ENTRIES))));              
154                     }
155                 }
156             }
157         }  
158         m_canCache = (((m_isOnline || m_controller.getCmsCache().cacheOffline()) && ! nocachepara) || dorecompile);
159         m_doRecompile = dorecompile;
160         if (DEBUG) System.err.println("[FlexRequest] Constructing new Flex request for resource: " + m_resource);
161     }
162         
163     /** 
164      * Constructs a new wrapper layer around a (already wrapped) CmsFlexRequest.<p>
165      *
166      * @param req the request to be wrapped
167      * @param controller the controller to use
168      * @param resource the target resource that has been requested
169      */    
170     CmsFlexRequest(HttpServletRequest req, CmsFlexController controller, String resource) {
171         super(req);
172         m_req = req;
173         m_controller = controller;
174         m_resource = toAbsolute(resource);
175         // must reset request URI/URL buffer here because m_resource has changed
176         m_requestUri = null; 
177         m_requestUrl = null;
178         m_isOnline = m_controller.getCurrentRequest().isOnline();
179         m_canCache = m_controller.getCurrentRequest().isCacheable();
180         m_doRecompile = m_controller.getCurrentRequest().isDoRecompile();
181         m_includeCalls = m_controller.getCurrentRequest().getCmsIncludeCalls();        
182         m_parameters = req.getParameterMap();
183         if (DEBUG) System.err.println("[FlexRequest] Re-using Flex request for resource: " + m_resource);
184     }
185     
186     /** 
187      * Returns the name of the resource currently processed.<p>
188      * 
189      * This might be the name of an included resource,
190      * not neccesarily the name the resource requested by the user.
191      * 
192      * @return the name of the resource currently processed
193      * @see #getCmsRequestedResource()
194      */    
195     public String getElementUri() {
196         return m_resource;
197     }    
198     
199     /** 
200      * Replacement for the standard servlet API getRequestDispatcher() method.<p>
201      * 
202      * This variation is used if an external file (probably JSP) is dispached to.
203      * This external file must have a "mirror" version, i.e. a file in the OpenCms VFS
204      * that represents the external file.<p>
205      *
206      * @param cms_target the OpenCms file that is a "mirror" version of the external file
207      * @param ext_target the external file (outside the OpenCms VFS)
208      * @return the constructed CmsFlexRequestDispatcher
209      */     
210     public CmsFlexRequestDispatcher getRequestDispatcherToExternal(String vfs_target, String ext_target) {
211         return new CmsFlexRequestDispatcher(m_controller.getTopRequest().getRequestDispatcher(ext_target), toAbsolute(vfs_target), ext_target);
212     }
213 
214     /** 
215      * Overloads the standard servlet API getRequestDispatcher() method,
216      * which is the main purpose of this wrapper implementation.<p>
217      *
218      * @param target the target for the request dispatcher
219      * @return the constructed RequestDispatcher
220      */    
221     public javax.servlet.RequestDispatcher getRequestDispatcher(String target) {
222         return (javax.servlet.RequestDispatcher) new CmsFlexRequestDispatcher (m_controller.getTopRequest().getRequestDispatcher(toAbsolute(target)), toAbsolute(target), null);
223     }
224 
225     /** 
226      * Wraps the request URI, overloading the standard API.<p>
227      * 
228      * This ensures that any wrapped request will use the "faked"
229      * target parameters. Remember that for the real request,
230      * a mixture of PathInfo and other request information is used to
231      * idenify the target.<p>
232      *
233      * @return a faked URI that will point to the wrapped target in the VFS 
234      * @see javax.servlet.http.HttpServletRequest#getRequestURI()
235      */      
236     public String getRequestURI() {
237         if (m_requestUri != null) return m_requestUri;
238         StringBuffer buf = new StringBuffer(128);
239         buf.append(getContextPath());
240         buf.append(getServletPath());
241         buf.append(getElementUri());
242         m_requestUri = buf.toString();
243         return m_requestUri;
244     } 
245     
246     /** 
247      * Wraps the request URL, overloading the standard API,
248      * the wrapped URL will always point to the currently included VFS resource.<p>
249      *
250      * @return a faked URL that will point to the included target in the VFS
251      * @see javax.servlet.http.HttpServletRequest#getRequestURL()
252      */   
253     public StringBuffer getRequestURL() {
254         if (m_requestUrl != null) return m_requestUrl;
255         StringBuffer buf = new StringBuffer(128);
256         buf.append(getScheme());
257         buf.append("://");
258         buf.append(getServerName());
259         buf.append(":");
260         buf.append(getServerPort());
261         buf.append(getRequestURI());  
262         m_requestUrl = buf;      
263         return m_requestUrl;
264     }
265         
266     /** 
267      * Convert (if necessary) and return the absolute URI that represents the
268      * resource referenced by this possibly relative URI for this request.<p>
269      * 
270      * Adjust for resources in the OpenCms VFS by cutting of servlet context
271      * and servlet name.
272      * If this URI is already absolute, return it unchanged.
273      * Return URI also unchanged if it is not well-formed.<p>
274      *
275      * @param location URI to be (possibly) converted and then returned
276      * @return the location converted to an absolut location
277      */
278     public String toAbsolute(String location) {
279 
280         if (DEBUG) System.err.println(getClass().getName() + " location=" + location);        
281         if (location == null) return null;
282         if (location.startsWith("/")) return location;
283 
284         // Construct a new absolute URL if possible (cribbed from Tomcat)
285         java.net.URL url = null;
286         try {
287             url = new java.net.URL(location);
288         } catch (java.net.MalformedURLException e1) {
289             String requrl = getRequestURL().toString();
290             try {
291                 url = new java.net.URL(new java.net.URL(requrl), location);
292             } catch (java.net.MalformedURLException e2) {
293                 // Some other method will deal with that sooner or later
294                 return location;
295             }
296         }
297         
298         // Now check if this is a opencms resource and if so remove the context / servlet path
299         String uri = url.getPath();
300         String context = getContextPath() + getServletPath();
301         if (uri.startsWith(context)) {
302             uri = uri.substring(context.length());
303         }
304         if (url.getQuery() != null) uri += "?" + url.getQuery();                    
305         
306         if (DEBUG) System.err.println(getClass().getName() + " result=" + uri);                
307         return uri;
308     }     
309             
310     /**
311      * Return the value of the specified request parameter, if any; otherwise,
312      * return <code>null</code>.<p>
313      * 
314      * If there is more than one value defined,
315      * return only the first one.<p>
316      *
317      * @param name the name of the desired request parameter
318      * @see javax.servlet.ServletRequest#getParameter(java.lang.String)
319      */
320     public String getParameter(String name) {
321 
322         String values[] = (String[]) m_parameters.get(name);
323         if (values != null)
324             return (values[0]);
325         else
326             return (null);
327     }
328 
329 
330     /**
331      * Returns a <code>Map</code> of the parameters of this request.<p>
332      * 
333      * Request parameters are extra information sent with the request.
334      * For HTTP servlets, parameters are contained in the query string
335      * or posted form data.<p>
336      *
337      * @return a <code>Map</code> containing parameter names as keys
338      *  and parameter values as map values
339      * @see javax.servlet.ServletRequest#getParameterMap()
340      */
341     public Map getParameterMap() {
342         return (this.m_parameters);
343     }
344 
345     /**
346      * Return the names of all defined request parameters for this request.<p>
347      * 
348      * @return the names of all defined request parameters for this request
349      * @see javax.servlet.ServletRequest#getParameterNames()
350      */
351     public Enumeration getParameterNames() {
352         java.util.Vector v = new java.util.Vector();
353         v.addAll(m_parameters.keySet());
354         return (v.elements());
355     }
356 
357     /**
358      * Returns the defined values for the specified request parameter, if any;
359      * otherwise, return <code>null</code>.
360      *
361      * @param name Name of the desired request parameter
362      * @return the defined values for the specified request parameter, if any;
363      *          <code>null</code> otherwise
364      * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String)
365      */
366     public String[] getParameterValues(String name) {
367 
368         String values[] = (String[]) m_parameters.get(name);
369         if (values != null)
370             return (values);
371         else
372             return (null);
373     }
374     
375     /**
376      * Adds the specified Map to the paramters of the request.<p>
377      * 
378      * Added parametes will not overwrite existing parameters in the 
379      * request. Remember that the value for a parameter name in
380      * a HttpRequest is a String array. If a parameter name already
381      * exists in the HttpRequest, the values will be added to the existing
382      * value array. Multiple occurences of the same value for one 
383      * paramter are also possible.<p>
384      * 
385      * @param map the map to add
386      * @return the merged map of parameters
387      */
388   public Map addParameterMap(Map map) {
389     if (map == null)
390       return m_parameters;
391     if ((m_parameters == null) || (m_parameters.size() == 0)) {
392             m_parameters = Collections.unmodifiableMap(map);
393     } else {
394             HashMap parameters = new HashMap();
395             parameters.putAll(m_parameters);
396             
397             Iterator it = map.keySet().iterator();
398             while (it.hasNext()) {
399                 String key = (String) it.next();
400                 // Check if the parameter name (key) exists
401                 if (parameters.containsKey(key)) {
402                                 
403                     String[] oldValues = (String[]) parameters.get(key);
404                     String[] newValues = (String[]) map.get(key);     
405                                
406                     String[] mergeValues = new String[oldValues.length + newValues.length];
407                     System.arraycopy(newValues, 0, mergeValues, 0, newValues.length);
408                     System.arraycopy(oldValues, 0, mergeValues, newValues.length, oldValues.length);
409                     
410                     parameters.put(key, mergeValues);
411                 } else {
412                     // No: Add new value array
413                     parameters.put(key, map.get(key));
414                 }                                     
415       }
416             m_parameters = Collections.unmodifiableMap(parameters);
417     }
418 
419     return m_parameters;
420   }
421     
422     /**
423      * Sets the specified Map as paramter map of the request.<p>
424      * 
425      * The map set should be immutable. 
426      * This will completly replace the parameter map. 
427      * Use this in combination with getParameterMap() and
428      * addParameterMap() in case you want to set the old status
429      * of the parameter map after you have modified it for
430      * a specific operation.<p>
431      * 
432      * @param map the map to set
433      */    
434     public void setParameterMap(Map map) {
435         m_parameters = map;
436     }
437     
438     /** 
439      * Returns the CmsFlexCacheKey for this request,
440      * the key will be calculated if neccessary.<p>
441      * 
442      * @return the CmsFlexCacheKey for this request
443      */
444     CmsFlexCacheKey getCmsCacheKey() {
445         // The key for this request is only calculated if actually requested
446         if (m_key == null) {
447             m_key = new CmsFlexCacheKey(this, m_resource, m_isOnline);
448         }
449         return m_key;
450     }
451 
452     /** 
453      * Indicates that this request belongs to an online project.<p>
454      * 
455      * This is required to distinguish between online and offline
456      * resources in the cache. Since the resources have the same name,
457      * a suffix [online] or [offline] is added to distinguish the strings
458      * when building cache keys.
459      * Any resource from a request that isOnline() will be saved with
460      * the [online] suffix and vice versa.<p>
461      *
462      * The suffixes are used so that we have a simple String name
463      * for the resources in the cache. This makes it easy to
464      * use a standard HashMap for storage of the resources.<p>
465      *
466      * @return true if an online resource was requested, false otherwise
467      */
468     public boolean isOnline() {
469         return m_isOnline;
470     }
471     
472     /** 
473      * This is needed to decide if this request can be cached or not.<p>
474      * 
475      * Using the request to decide if caching is used or not
476      * makes it possible to set caching to false e.g. on a per-user
477      * or per-project basis.<p>
478      *
479      * @return true if the request is cacheable, false otherwise
480      */
481     boolean isCacheable() {
482         return m_canCache;
483     }
484     
485     /** 
486      * Checks if JSPs should always be recompiled.<p>
487      * 
488      * This is useful in case directive based includes are used
489      * with &lt;%@ include file="..." %&gt; on a JSP.
490      * Note that this also forces the request not to be cached.<p>
491      *
492      * @return true if JSPs should be recompiled, false otherwise
493      */
494     public boolean isDoRecompile() {
495         return m_doRecompile;
496     }
497     
498     /**
499      * Adds another include call to this wrapper.<p>
500      * 
501      * The set of include calls is maintained to dectect 
502      * an endless inclusion loop.<p>
503      * 
504      * @param target the target name (absolute OpenCms URI) to add
505      */
506     void addInlucdeCall(String target) {
507         m_includeCalls.add(target);
508     }
509     
510     /**
511      * Removes an include call from this wrapper.<p>
512      * 
513      * The set of include calls is maintained to dectect 
514      * an endless inclusion loop.<p>
515      * 
516      * @param target the target name (absolute OpenCms URI) to remove
517      */
518     void removeIncludeCall(String target) {
519         m_includeCalls.remove(target);
520     }
521     
522     /**
523      * Checks if a given target is already included in a top-layer of this
524      * wrapped request.<p>
525      * 
526      * The set of include calls is maintained to dectect 
527      * an endless inclusion loop.<p>
528      * 
529      * @param target the target name (absolute OpenCms URI) to check for
530      * @return true if the target is already included, false otherwise
531      */
532     boolean containsIncludeCall(String target) {
533         return m_includeCalls.contains(target);
534     }
535         
536     /**
537      * Returns the Set of include calls which will be passed to the next wrapping layer.<p>
538      * 
539      * The set of include calls is maintained to dectect 
540      * an endless inclusion loop.<p>
541      * 
542      * @return the Set of include calls
543      */
544     protected Set getCmsIncludeCalls() {
545         return m_includeCalls;
546     }    
547 }