KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > blandware > atleap > webapp > struts > ContentTilesRequestProcessor


1 /*
2  * Copyright 2004 Blandware (http://www.blandware.com)
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 com.blandware.atleap.webapp.struts;
17
18 import com.blandware.atleap.common.Constants;
19 import com.blandware.atleap.common.util.ConvertUtil;
20 import com.blandware.atleap.model.core.ContentLocale;
21 import com.blandware.atleap.model.core.ContentPage;
22 import com.blandware.atleap.model.core.Layout;
23 import com.blandware.atleap.model.core.Role;
24 import com.blandware.atleap.service.core.PageManager;
25 import com.blandware.atleap.webapp.util.core.CacheUtil;
26 import com.blandware.atleap.webapp.util.core.GlobalProperties;
27 import com.blandware.atleap.webapp.util.core.LocaleUtil;
28 import com.blandware.atleap.webapp.util.core.TokenUtil;
29 import com.blandware.atleap.webapp.util.core.WebappConstants;
30 import com.blandware.atleap.webapp.util.core.WebappUtil;
31 import com.blandware.atleap.webapp.taglib.core.html.CancelTag;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.struts.Globals;
35 import org.apache.struts.util.RequestUtils;
36 import org.apache.struts.action.*;
37 import org.apache.struts.config.ActionConfig;
38 import org.apache.struts.config.ForwardConfig;
39 import org.apache.struts.config.ModuleConfig;
40 import org.apache.struts.tiles.TilesRequestProcessor;
41 import org.springframework.context.ApplicationContext;
42 import org.springframework.web.context.support.WebApplicationContextUtils;
43
44 import javax.servlet.ServletException JavaDoc;
45 import javax.servlet.http.HttpServletRequest JavaDoc;
46 import javax.servlet.http.HttpServletResponse JavaDoc;
47 import javax.servlet.http.HttpSession JavaDoc;
48 import java.io.IOException JavaDoc;
49 import java.util.ArrayList JavaDoc;
50 import java.util.Date JavaDoc;
51 import java.util.Iterator JavaDoc;
52 import java.util.List JavaDoc;
53 import java.util.Locale JavaDoc;
54 import java.util.StringTokenizer JavaDoc;
55
56 /**
57  * <p><strong>RequestProcessor</strong> contains the processing logic that
58  * the Struts controller servlet performs as it receives each servlet request
59  * from the container.</p>
60  * <p>This processor subclasses the TilesRequestProcessor in order to intercept calls to forward
61  * or include or direct requests from browser. When such calls are done, this processor checks if the specified URI
62  * is content page uri from database. If true, the definition is retrieved from layout of the page and included. If
63  * false, the original URI is included or a forward is performed.</p>
64  * <p>For every request processed uri is stored into request attribute under PROCESSED_URI key.</p>
65  * <p>For request based on Tiles definition processed uri is stored into request attribute under DEFINITION_NAME key.</p>
66  * <p>When processing request, if current mapping contains forward named
67  * 'unsatisfiable' then security token will be checked; if token passed through
68  * request doesn't match token stored in session, then forward to
69  * 'unsatisfiable' page will be done. Else, security token will be reset
70  * (removed from session).
71  * </p>
72  * <p>Forward named 'unsatisfiableNoReset' is similar to 'unsatisfiable' with
73  * one exception: security token is not reset when this forward exists in
74  * current mapping.
75  * </p>
76  * <p>
77  * If both above-mentioned forwards present, latter will be ignored.
78  * </p>
79  * <p><a HREF="ContentTilesRequestProcessor.java.htm"><i>View Source</i></a></p>
80  * <p/>
81  *
82  * @author Andrey Grebnev <a HREF="mailto:andrey.grebnev@blandware.com">&lt;andrey.grebnev@blandware.com&gt;</a>
83  * @version $Revision: 1.33 $ $Date: 2005/11/21 12:44:54 $
84  */

85 public class ContentTilesRequestProcessor extends TilesRequestProcessor {
86
87     /**
88      * Constant name used to store processed definition name in request
89      */

90     public static final String JavaDoc DEFINITION_NAME = "com.blandware.atleap.webapp.struts.DEFINITION_NAME";
91
92     /**
93      * Constant name used to store processed uri in request
94      */

95     public static final String JavaDoc PROCESSED_URI = "com.blandware.atleap.webapp.struts.PROCESSED_URI";
96
97     /**
98      * Constant name used to store full processed url with query string in request
99      */

100     public static final String JavaDoc PROCESSED_URL = "com.blandware.atleap.webapp.struts.PROCESSED_URL";
101
102     /**
103      * Constant name used to store marker if the current processed page is content page or not
104      */

105     public static final String JavaDoc IS_NOCACHE = "com.blandware.atleap.webapp.struts.IS_NOCACHE";
106
107
108     /**
109      * Commons Logging instance.
110      */

111     protected transient final Log log = LogFactory.getLog(ContentTilesRequestProcessor.class);
112
113
114     /**
115      * Initialize this request processor instance.
116      *
117      * @param servlet The ActionServlet we are associated with.
118      * @param moduleConfig The ModuleConfig we are associated with.
119      * @throws javax.servlet.ServletException If an error occurs during initialization.
120      */

121     public void init(ActionServlet servlet, ModuleConfig moduleConfig) throws ServletException JavaDoc {
122         super.init(servlet, moduleConfig);
123         if ( log.isDebugEnabled() ) {
124             log.debug("Definitions factory class name: " + definitionsFactory.getClass().getName());
125         }
126     }
127
128     /**
129      * <p>Process an <code>HttpServletRequest</code> and create the
130      * corresponding <code>HttpServletResponse</code> or dispatch
131      * to another resource.</p>
132      *
133      * @param request The servlet request we are processing
134      * @param response The servlet response we are creating
135      * @throws IOException if an input/output error occurs
136      * @throws ServletException if a processing exception occurs
137      */

138     public void process(HttpServletRequest JavaDoc request,
139                         HttpServletResponse JavaDoc response)
140             throws IOException JavaDoc, ServletException JavaDoc {
141
142         // Wrap multipart requests with a special wrapper
143
request = processMultipart(request);
144
145         // Identify the path component we will use to select a mapping
146
String JavaDoc path = processPath(request, response);
147         if ( path == null ) {
148             return;
149         }
150
151         if ( log.isDebugEnabled() ) {
152             log.debug("Processing a '" + request.getMethod() +
153                     "' for path '" + path + "'");
154         }
155
156         // Select a Locale for the current user if requested
157
processLocale(request, response);
158
159         // Set the content type and no-caching headers if requested
160
processContent(request, response);
161         processNoCache(request, response);
162
163         // General purpose preprocessing hook
164
if ( !processPreprocess(request, response) ) {
165             return;
166         }
167
168         this.processCachedMessages(request, response);
169
170         // Identify the mapping for this request
171
ActionMapping mapping = processMapping(request, response, path);
172         if ( mapping == null ) {
173             return;
174         }
175
176         // Check for any role required to perform this action
177
if ( !processRoles(request, response, mapping) ) {
178             return;
179         }
180
181         // Note, that check for token is performed after form bean has been created and populated,
182
// but before it has been validated.
183
// It is done in order to prevent appearance of unsatisfiable page when Cancel button is pressed
184
// and session has already been invalidated
185

186         // Process any ActionForm bean related to this request
187
ActionForm form = processActionForm(request, response, mapping);
188         processPopulate(request, response, form, mapping);
189
190         // Check for token in session
191
if ( (request.getAttribute(Globals.CANCEL_KEY) == null) ) {
192             if ( !checkToken(request, response, mapping) ) {
193                 return;
194             }
195         }
196
197         // Validate form bean
198
if ( !processValidate(request, response, form, mapping) ) {
199             return;
200         } else {
201             resetToken(request, mapping);
202         }
203
204         // Process a forward or include specified by this mapping
205
if ( !processForward(request, response, mapping) ) {
206             return;
207         }
208
209         if ( !processInclude(request, response, mapping) ) {
210             return;
211         }
212
213         // Create or acquire the Action instance to process this request
214
Action action = processActionCreate(request, response, mapping);
215         if ( action == null ) {
216             return;
217         }
218
219         // Call the Action instance itself
220
ActionForward forward =
221                 processActionPerform(request, response,
222                         action, form, mapping);
223
224         // Process the returned ActionForward instance
225
processForwardConfig(request, response, forward);
226
227     }
228
229     /**
230      * Check for token in session if <code>unsatisfiable</code> mapping exists in local forwards
231      *
232      * @param request request
233      * @param response response
234      * @param mapping action mapping
235      * @return Return <code>true</code> if we should continue processing, or <code>false</code> if we have already forwarded control back.
236      */

237     protected boolean checkToken(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response, ActionMapping mapping)
238             throws IOException JavaDoc, ServletException JavaDoc {
239         ActionForward forward = mapping.findForward("unsatisfiable");
240         if (forward == null) {
241             forward = mapping.findForward("unsatisfiableNoReset");
242         }
243         if ( forward != null ) {
244             if ( !TokenUtil.getInstance().isTokenValid(request, false) ) {
245                 request.setAttribute("beginPage", forward.getPath());
246                 processForwardConfig(request, response, mapping.findForward("unsatisfiablePage"));
247                 return false;
248             }
249         }
250         return true;
251     }
252
253     /**
254      * Resets token if 'unsatisfiable' forward exists in current mapping
255      *
256      * @param request request
257      * @param mapping action mapping
258      */

259     protected void resetToken(HttpServletRequest JavaDoc request, ActionMapping mapping) {
260         ActionForward forward = mapping.findForward("unsatisfiable");
261         if ( forward != null ) {
262             TokenUtil.getInstance().resetToken(request);
263         }
264     }
265
266     /**
267      * Processes a Content page.
268      * This method tries to process the parameter <code>uri</code> as a content page uri.
269      * It returns <code>true</code> if a uri has been processed, or <code>false</code> otherwise.
270      *
271      * @param uri Uri that is suspected to be a content page uri
272      * @param contextRelative Is this page marked contextRelative ?
273      * @param request The request we are processing
274      * @param response The response we are creating
275      * @return <code>true</code> if the method has processed uri as a content page uri, <code>false</code> otherwise.
276      */

277     protected boolean processContentPage(String JavaDoc uri, boolean contextRelative, HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response)
278             throws IOException JavaDoc {
279         if ( log.isDebugEnabled() ) {
280             log.debug("processContentPage("
281                     + uri + ", "
282                     + contextRelative + ")");
283         }
284
285         //generate module relative uri
286
if ( contextRelative ) {
287             String JavaDoc prefix = moduleConfig.getPrefix();
288             log.debug("Strip module prefix '" + prefix + "' ");
289             if ( !uri.startsWith(prefix) ) {
290                 log.error(getInternal().getMessage("processPath",
291                         request.getRequestURI()));
292                 try {
293                     response.sendError(HttpServletResponse.SC_BAD_REQUEST,
294                             getInternal().getMessage
295                                     ("processPath", request.getRequestURI()));
296                 } catch ( IOException JavaDoc ex ) {
297                     //do nothing
298
}
299                 return true;
300             }
301             uri = uri.substring(prefix.length());
302         }
303
304
305         String JavaDoc cpDefinition = null;
306         List JavaDoc roleNames = new ArrayList JavaDoc();
307         long lastModified = -1;
308         Long JavaDoc cacheMaxAge = null;
309
310         //try to get from cache
311
CacheUtil cacheUtil = CacheUtil.getInstance(request);
312         CacheUtil.ContentPageData cpd = cacheUtil.getContentPageFromCache(uri);
313
314         if ( cpd != null ) {
315             cpDefinition = cpd.getCpDefinition();
316             roleNames = ConvertUtil.convertStringToList(cpd.getRoles(), ",", true);
317             lastModified = cpd.getLastModified();
318             cacheMaxAge = cpd.getCacheMaxAge();
319
320             if ( log.isDebugEnabled() ) {
321                 log.debug("Retrieving content page from Cache with for uri=" + uri + " with cpDefinition=" + cpDefinition + " and roles=" + roleNames.toString());
322             }
323
324         } else {
325             // getting from DB
326
ContentPage contentPage = null;
327             try {
328                 ApplicationContext applicationCtx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
329                 PageManager pageManager = (PageManager) applicationCtx.getBean(Constants.PAGE_MANAGER_BEAN);
330                 contentPage = pageManager.findContentPageByUri(uri);
331             } catch ( Exception JavaDoc ex ) {
332                 if ( log.isErrorEnabled() ) {
333                     log.error("Cannot perfom function because layout could not be found. Cause: " + ex.getLocalizedMessage());
334                 }
335             }
336
337             //if page is found
338
if ( contentPage != null ) {
339                 if ( contentPage.getActive().booleanValue() ) {
340                     Layout layout = contentPage.getLayout();
341                     cpDefinition = layout.getCpDefinition();
342                     lastModified = new Date JavaDoc().getTime();
343                     cacheMaxAge = contentPage.getCacheMaxAge();
344                     if ( cpDefinition != null ) {
345                         //getting names of roles
346
List JavaDoc roles = contentPage.getRoles();
347                         for ( int i = 0; i < roles.size(); i++ ) {
348                             Role role = (Role) roles.get(i);
349                             roleNames.add(role.getName());
350                         }
351
352                         //put into cache
353
String JavaDoc roleNamesString = null;
354                         if ( roleNames.size() > 0 ) {
355                             roleNamesString = ConvertUtil.convertListToString(roleNames, ",");
356                         }
357                         cpd = new CacheUtil.ContentPageData(cpDefinition, roleNamesString, cacheMaxAge);
358                         cacheUtil.putContentPageInCache(cpd, uri);
359
360                         if ( log.isDebugEnabled() ) {
361                             log.debug("Definition '" + cpDefinition + "' for layout of content page was found in database");
362                         }
363                     }
364                 } else {
365                     // the page is not active -- it's not ready for publication yet
366
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
367                     return true;
368                 }
369             }
370
371         }
372
373         //if page was not found
374
if ( cpDefinition == null ) {
375             return false;
376         }
377
378         //client caching logic
379
int maxAge = -1;
380         if ( cacheMaxAge != null ) {
381             maxAge = cacheMaxAge.intValue();
382         } else {
383             maxAge = ((Integer JavaDoc) GlobalProperties.getInstance(servlet.getServletContext()).getInteger(WebappConstants.CACHE_CONTENTPAGE_MAXAGE_PROPERTY, -1)).intValue();
384         }
385         if ( maxAge < 0 ) {
386             response.setHeader("Cache-Control", "no-cache,no-store,max-age=0");
387             response.setHeader("Pragma", "no-cache");
388             request.setAttribute(IS_NOCACHE, "true");
389         } else {
390             String JavaDoc cacheType = "public";
391             if ( roleNames.size() != 0 ) {
392                 cacheType = "private";
393             }
394
395             String JavaDoc editMode = "false";
396             if ( Boolean.TRUE.equals(request.getSession().getAttribute(WebappConstants.SITE_EDIT_MODE_ENABLED_KEY)) ) {
397                 editMode = "true";
398                 maxAge = 0;
399             }
400
401             response.setHeader("Cache-Control", cacheType + ",max-age=" + maxAge);
402             response.setHeader("Pragma", "");
403
404             //check for entity tag
405
if ( request.getMethod().equals("GET") && lastModified != -1 ) {
406
407                 //ETag generation
408
String JavaDoc locale = ((Locale) request.getSession(true).getAttribute(Globals.LOCALE_KEY)).getLanguage();
409                 String JavaDoc username = request.getRemoteUser();
410
411
412                 StringBuffer JavaDoc eTagBuffer = new StringBuffer JavaDoc("W/\"").append(locale).append("-").append(username).append("-").append(editMode).append("-").append(lastModified).append("\"");
413                 String JavaDoc eTag = eTagBuffer.toString();
414                 response.setHeader("ETag", eTag);
415
416                 boolean conditionSatisfied = false;
417                 String JavaDoc headerValue = request.getHeader("If-None-Match");
418                 if ( headerValue != null ) {
419                     if ( !headerValue.equals("*") ) {
420                         StringTokenizer JavaDoc commaTokenizer =
421                                 new StringTokenizer JavaDoc(headerValue, ",");
422                         while ( !conditionSatisfied && commaTokenizer.hasMoreTokens() ) {
423                             String JavaDoc currentToken = commaTokenizer.nextToken();
424                             if ( currentToken.trim().equals(eTag) ) {
425                                 conditionSatisfied = true;
426                             }
427                         }
428                     } else {
429                         conditionSatisfied = true;
430                     }
431                     if ( conditionSatisfied ) {
432                         response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
433                         return true;
434                     }
435                 }
436             }
437         }
438
439         //check roles
440
boolean granted = false;
441         if ( roleNames != null && roleNames.size() > 0 ) {
442             for ( int i = 0; i < roleNames.size(); i++ ) {
443                 String JavaDoc roleName = (String JavaDoc) roleNames.get(i);
444                 if ( request.isUserInRole(roleName) ) {
445                     if ( log.isDebugEnabled() ) {
446                         log.debug(" User '" + request.getRemoteUser() +
447                                 "' has role '" + roleName + "', granting access");
448                     }
449                     granted = true;
450                     break;
451                 }
452             }
453         } else {
454             granted = true;
455             if ( log.isDebugEnabled() ) {
456                 log.debug("Anonymous user granting access");
457             }
458         }
459
460         if ( !granted ) {
461             // The current user is not authorized for this action
462
if ( log.isDebugEnabled() ) {
463                 log.debug(" User '" + request.getRemoteUser() +
464                         "' does not have any required role, denying access");
465             }
466             response.sendError(HttpServletResponse.SC_FORBIDDEN,
467                     getInternal().getMessage("notAuthorized", uri));
468             return true;
469         }
470
471         //store into request uri
472
request.setAttribute(PROCESSED_URI, uri);
473         request.setAttribute(PROCESSED_URL, getFullUrl(request));
474
475         try {
476             if ( processTilesDefinition(cpDefinition, contextRelative, request, response) ) {
477                 return true;
478             } else {
479                 if ( log.isWarnEnabled() ) {
480                     log.warn("Cannot process Tiles definition specified in database");
481                 }
482             }
483         } catch ( Exception JavaDoc ex ) {
484             if ( log.isErrorEnabled() ) {
485                 log.error("Cannot process Tiles definition " + ex.getLocalizedMessage());
486             }
487         }
488
489         return false;
490     }
491
492     /**
493      * <p>Set the no-cache headers for all responses, if requested.
494      * <strong>NOTE</strong> - This header will be overridden
495      * automatically if a <code>RequestDispatcher.forward</code> call is
496      * ultimately invoked.</p>
497      *
498      * @param request The servlet request we are processing
499      * @param response The servlet response we are creating
500      */

501     protected void processNoCache(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) {
502         //we override this method to enable caching manually afterwards in this class
503
}
504
505     /**
506      * Returns full reqested URL with query string
507      *
508      * @param request the request for which full URL is obtained
509      * @return full URL
510      */

511     protected String JavaDoc getFullUrl(HttpServletRequest JavaDoc request) {
512         StringBuffer JavaDoc requestUrl = request.getRequestURL();
513         if ( requestUrl == null ) {
514             return null;
515         }
516         String JavaDoc queryString = request.getQueryString();
517         if ( queryString != null && queryString.length() > 0 ) {
518             requestUrl = requestUrl.append('?').append(queryString);
519         }
520         return requestUrl.toString();
521     }
522
523     /**
524      * Overloaded method from RequestProcessor
525      * Selects the mapping used to process the selection path for this request.
526      * If no mapping can be identified, tries to process as content page
527      * if content page was not found creates an error response and returns
528      * <code>null</code>.
529      *
530      * @param request The servlet request we are processing
531      * @param response The servlet response we are creating
532      * @param path The portion of the request URI for selecting a mapping
533      * @throws java.io.IOException if an input/output error occurs
534      */

535     protected ActionMapping processMapping(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response, String JavaDoc path)
536             throws IOException JavaDoc {
537         // Is there a directly defined mapping for this path?
538
ActionMapping mapping = (ActionMapping)
539                 moduleConfig.findActionConfig(path);
540         if ( mapping != null ) {
541             //no-cache actions
542
response.setHeader("Cache-Control", "no-cache,no-store,max-age=0");
543             response.setHeader("Pragma", "no-cache");
544             request.setAttribute(IS_NOCACHE, "true");
545
546             request.setAttribute(Globals.MAPPING_KEY, mapping);
547
548             //store into request uri
549
request.setAttribute(PROCESSED_URI, path);
550             request.setAttribute(PROCESSED_URL, getFullUrl(request));
551
552             return (mapping);
553         }
554
555         //Try to process content page
556
if ( processContentPage(path, false, request, response) ) {
557             return null;
558         }
559
560         //no-cache actions
561
response.setHeader("Cache-Control", "no-cache,no-store,max-age=0");
562         response.setHeader("Pragma", "no-cache");
563         request.setAttribute(IS_NOCACHE, "true");
564
565         // Locate the mapping for unknown paths (if any)
566
ActionConfig configs[] = moduleConfig.findActionConfigs();
567         for ( int i = 0; i < configs.length; i++ ) {
568             if ( configs[i].getUnknown() ) {
569                 mapping = (ActionMapping) configs[i];
570                 request.setAttribute(Globals.MAPPING_KEY, mapping);
571                 return (mapping);
572             }
573         }
574
575         // No mapping can be found to process this request
576
String JavaDoc msg = getInternal().getMessage("processInvalid", path);
577         log.error(msg);
578         response.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
579
580         return null;
581     }
582
583     /**
584      * <p>Automatically selects a <code>Locale</code> for the current user, if requested.
585      * <strong>NOTE</strong> - configuring Locale selection will trigger
586      * the creation of a new <code>HttpSession</code> if necessary.</p>
587      *
588      * @param request The HTTP servlet request we are proceeding
589      * @param response The HTTP servlet response we are creating
590      */

591     protected void processLocale(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) {
592
593         String JavaDoc localeIdentifier = null;
594         HttpSession JavaDoc session = request.getSession();
595
596         // check the presence of 'language' parameter in request
597
localeIdentifier = request.getParameter("language");
598
599         // can we automatically change locale?
600
boolean canChangeLocale = moduleConfig.getControllerConfig().getLocale();
601         if ( (localeIdentifier == null || localeIdentifier.trim().length() == 0) && !canChangeLocale ) {
602             return;
603         }
604
605         // 'language' parameter in request has the top priority
606
// if it is not specified, check session and request
607
if ( localeIdentifier == null || localeIdentifier.trim().length() == 0 ) {
608             Locale locale = (Locale) session.getAttribute(Globals.LOCALE_KEY);
609             if ( locale == null ) {
610                 // Use the Locale returned by the servlet container (if any)
611
locale = request.getLocale();
612             }
613             if ( locale != null ) {
614                 localeIdentifier = locale.getLanguage();
615             }
616         }
617
618         LocaleUtil localeUtil = LocaleUtil.getInstance(servlet.getServletContext());
619         if ( localeIdentifier != null && localeIdentifier.trim().length() > 0 ) {
620             List JavaDoc availableLocales = localeUtil.getAvailableLocales();
621             ContentLocale contentLocale = null;
622             boolean localeFound = false;
623             boolean localeIsActive = false;
624             for ( Iterator JavaDoc i = availableLocales.iterator(); i.hasNext() && !localeFound; ) {
625                 contentLocale = (ContentLocale) i.next();
626                 localeFound = contentLocale.getIdentifier().equalsIgnoreCase(localeIdentifier);
627                 localeIsActive = contentLocale.getActive().booleanValue();
628             }
629             if ( !localeFound || !localeIsActive ) {
630                 contentLocale = localeUtil.getDefaultLocale();
631                 if ( contentLocale != null ) {
632                     localeIdentifier = contentLocale.getIdentifier();
633                 }
634             }
635         } else {
636             ContentLocale contentLocale = localeUtil.getDefaultLocale();
637             if ( contentLocale != null ) {
638                 localeIdentifier = contentLocale.getIdentifier();
639             }
640         }
641
642         if ( log.isDebugEnabled() ) {
643             log.debug(" Setting user locale '" + localeIdentifier + "'");
644         }
645
646         response.setHeader("Content-Language", localeIdentifier);
647
648         session.setAttribute(Globals.LOCALE_KEY, new Locale(localeIdentifier));
649     }
650
651     /**
652      * Processes a Tile definition name. This overloaded method sets up definition name into request attribute
653      *
654      * @param definitionName Definition name to insert.
655      * @param contextRelative Is the definition marked contextRelative ?
656      * @param request Current page request.
657      * @param response Current page response.
658      * @return <code>true</code> if the method has processed uri as a definition name, <code>false</code> otherwise.
659      */

660     protected boolean processTilesDefinition(String JavaDoc definitionName, boolean contextRelative, HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) throws IOException JavaDoc, ServletException JavaDoc {
661         request.setAttribute(DEFINITION_NAME, definitionName);
662         boolean result = super.processTilesDefinition(definitionName, contextRelative, request, response);
663         if ( !result ) {
664             request.removeAttribute(DEFINITION_NAME);
665         }
666         return result;
667     }
668
669     /**
670      * Overloaded method from Struts' TilesRequestProcessor.
671      * Forwards or redirects to the specified destination by the specified
672      * mechanism.
673      * This method catches the Struts' actionForward call. It checks if the
674      * actionForward is done on a Tiles definition name. If true, processes the
675      * definition and inserts it. If false, behaves as original parent's method.
676      *
677      * @param request The servlet request we are processing.
678      * @param response The servlet response we are creating.
679      * @param forward The ActionForward controlling where we go next.
680      * @throws IOException if an input/output error occurs.
681      * @throws ServletException if a servlet exception occurs.
682      */

683     protected void processForwardConfig(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response, ForwardConfig forward) throws IOException JavaDoc, ServletException JavaDoc {
684         // Required by struts contract
685
if ( forward == null ) {
686             return;
687         }
688
689         boolean contextRelative = forward.getModule() == null || forward.getModule().trim().length() == 0;
690
691         if ( log.isDebugEnabled() ) {
692             log.debug("processForwardConfig(" + forward.getPath() + ", " + contextRelative + ")");
693         }
694
695         // Try to process the definition.
696
if ( processTilesDefinition(forward.getPath(), contextRelative, request, response) ) {
697             if ( log.isDebugEnabled() ) {
698                 log.debug(" '" + forward.getPath() + "' - processed as definition");
699             }
700             return;
701         }
702
703         if ( log.isDebugEnabled() ) {
704             log.debug(" '" + forward.getPath() + "' - processed as uri");
705         }
706
707         // forward doesn't contain a definition, process as in Struts' RequestProcessor
708

709         // if we forward must be redirected to, add context path, otherwise do not
710
int urlType = forward.getRedirect() ? WebappConstants.URL_TYPE_DOMAIN_RELATIVE : WebappConstants.URL_TYPE_CONTEXT_RELATIVE;
711         String JavaDoc uri = WebappUtil.getActionForwardURL(forward, null, request, urlType, forward.getRedirect());
712
713         if ( forward.getRedirect() ) {
714             response.sendRedirect(response.encodeRedirectURL(uri));
715         } else {
716             doForward(uri, request, response);
717         }
718
719
720     }
721
722     /**
723      * <p>Populate the properties of the specified <code>ActionForm</code> instance from
724      * the request parameters included with this request. In addition,
725      * request attribute <code>Globals.CANCEL_KEY</code> will be set if
726      * the request was submitted with a button created by a regular
727      * <code>CancelTag</code>; request attribute <code>WebappConstants.BACK_KEY</code>
728      * will be set if the request was submitted with a button created by
729      * 'back' type <code>CancelTag</code>.</p>
730      *
731      * @param request The servlet request we are processing
732      * @param response The servlet response we are creating
733      * @param form The ActionForm instance we are populating
734      * @param mapping The ActionMapping we are using
735      *
736      * @exception ServletException if thrown by RequestUtils.populate()
737      */

738     protected void processPopulate(HttpServletRequest JavaDoc request,
739                                    HttpServletResponse JavaDoc response,
740                                    ActionForm form,
741                                    ActionMapping mapping)
742         throws ServletException JavaDoc {
743
744         super.processPopulate(request, response, form, mapping);
745
746         // Set attribute for 'back' button: whether it was pressed or not
747
if (request.getParameter(CancelTag.BACK_PROPERTY) != null) {
748             request.setAttribute(WebappConstants.BACK_KEY, Boolean.TRUE);
749         }
750
751     }
752
753     /**
754      * <p>If this request was not cancelled, was not accuired after pressing
755      * 'back' button, and the request's
756      * {@link ActionMapping} has not disabled validation, call the
757      * <code>validate</code> method of the specified {@link ActionForm},
758      * and forward to the input path if there were any errors.
759      * Return <code>true</code> if we should continue processing,
760      * or <code>false</code> if we have already forwarded control back
761      * to the input form.</p>
762      *
763      * @param request The servlet request we are processing
764      * @param response The servlet response we are creating
765      * @param form The ActionForm instance we are populating
766      * @param mapping The ActionMapping we are using
767      *
768      * @exception IOException if an input/output error occurs
769      * @exception ServletException if a servlet exception occurs
770      */

771     protected boolean processValidate(HttpServletRequest JavaDoc request,
772                                       HttpServletResponse JavaDoc response,
773                                       ActionForm form,
774                                       ActionMapping mapping)
775         throws IOException JavaDoc, ServletException JavaDoc {
776                                               // Was this request 'backed'?
777
if (request.getAttribute(WebappConstants.BACK_KEY) != null) {
778             if (log.isDebugEnabled()) {
779                 log.debug(" Got here after pressing 'back', skipping validation");
780             }
781             return (true);
782         }
783
784         return super.processValidate(request, response, form, mapping);
785     }
786
787 }
788
Popular Tags