View Javadoc

1   /*
2    * $Id: ConfigHelper.java 421119 2006-07-12 04:49:11Z wsmoak $
3    *
4    * Copyright 1999-2004 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.struts.config;
19  
20  import org.apache.struts.Globals;
21  import org.apache.struts.action.ActionForm;
22  import org.apache.struts.action.ActionFormBean;
23  import org.apache.struts.action.ActionForward;
24  import org.apache.struts.action.ActionMapping;
25  import org.apache.struts.action.ActionMessages;
26  import org.apache.struts.upload.MultipartRequestWrapper;
27  import org.apache.struts.util.MessageResources;
28  import org.apache.struts.util.RequestUtils;
29  
30  import javax.servlet.ServletContext;
31  import javax.servlet.http.HttpServletRequest;
32  import javax.servlet.http.HttpServletResponse;
33  import javax.servlet.http.HttpSession;
34  
35  /***
36   * <p> NOTE: THIS CLASS IS UNDER ACTIVE DEVELOPMENT. THE CURRENT CODE IS
37   * WRITTEN FOR CLARITY NOT EFFICIENCY. NOT EVERY API FUNCTION HAS BEEN
38   * IMPLEMENTED YET. </p><p> A helper object to expose the Struts shared
39   * resources, which are be stored in the application, session, or request
40   * contexts, as appropriate. </p><p> An instance should be created for each
41   * request processed. The  methods which return resources from the request or
42   * session contexts are not thread-safe. </p><p> Provided for use by other
43   * servlets in the application so they can easily access the Struts shared
44   * resources. </p><p> The resources are stored under attributes in the
45   * application, session, or request contexts. </p><p> The ActionConfig methods
46   * simply return the resources from under the context and key used by the
47   * Struts ActionServlet when the resources are created. </p>
48   *
49   * @version $Rev: 421119 $ $Date: 2005-05-14 02:09:06 -0400 (Sat, 14 May 2005)
50   *          $
51   * @since Struts 1.1
52   */
53  public class ConfigHelper implements ConfigHelperInterface {
54      // --------------------------------------------------------  Properites
55  
56      /***
57       * <p> The application associated with this instance. </p>
58       */
59      private ServletContext application = null;
60  
61      /***
62       * <p> The session associated with this instance. </p>
63       */
64      private HttpSession session = null;
65  
66      /***
67       * <p> The request associated with this instance. </p>
68       */
69      private HttpServletRequest request = null;
70  
71      /***
72       * <p> The response associated with this instance. </p>
73       */
74      private HttpServletResponse response = null;
75  
76      /***
77       * <p> The forward associated with this instance. </p>
78       */
79      private ActionForward forward = null;
80  
81      public ConfigHelper() {
82          super();
83      }
84  
85      public ConfigHelper(ServletContext application, HttpServletRequest request,
86          HttpServletResponse response) {
87          super();
88          this.setResources(application, request, response);
89      }
90  
91      /***
92       * <p> Set the application associated with this instance.
93       * [servlet.getServletContext()] </p>
94       */
95      public void setApplication(ServletContext application) {
96          this.application = application;
97      }
98  
99      /***
100      * <p> Set the session associated with this instance. </p>
101      */
102     public void setSession(HttpSession session) {
103         this.session = session;
104     }
105 
106     /***
107      * <p> Set the request associated with this object. Session object is also
108      * set or cleared. </p>
109      */
110     public void setRequest(HttpServletRequest request) {
111         this.request = request;
112 
113         if (this.request == null) {
114             setSession(null);
115         } else {
116             setSession(this.request.getSession());
117         }
118     }
119 
120     /***
121      * <p> Set the response associated with this isntance. Session object is
122      * also set or cleared. </p>
123      */
124     public void setResponse(HttpServletResponse response) {
125         this.response = response;
126     }
127 
128     /***
129      * Set the forward associated with this instance.
130      */
131     public void setForward(ActionForward forward) {
132         this.forward = forward;
133     }
134 
135     /***
136      * <p> Set the application and request for this object instance. The
137      * ServletContext can be set by any servlet in the application. The
138      * request should be the instant request. Most of the other methods
139      * retrieve their own objects by reference to the application, request, or
140      * session attributes. Do not call other methods without setting these
141      * first! This is also called by the convenience constructor. </p>
142      *
143      * @param application - The associated ServletContext.
144      * @param request     - The associated HTTP request.
145      * @param response    - The associated HTTP response.
146      */
147     public void setResources(ServletContext application,
148         HttpServletRequest request, HttpServletResponse response) {
149         setApplication(application);
150         setRequest(request);
151         setResponse(response);
152     }
153 
154     // ------------------------------------------------ Application Context
155     public ActionMessages getActionMessages() {
156         if (this.application == null) {
157             return null;
158         }
159 
160         return (ActionMessages) this.application.getAttribute(Globals.MESSAGE_KEY);
161     }
162 
163     /***
164      * <p> The application resources for this application. </p>
165      */
166     public MessageResources getMessageResources() {
167         if (this.application == null) {
168             return null;
169         }
170 
171         return (MessageResources) this.application.getAttribute(Globals.MESSAGES_KEY);
172     }
173 
174     /***
175      * <p> The path-mapped pattern (<code>/action/*</code>) or extension
176      * mapped pattern ((<code>*.do</code>) used to determine our Action URIs
177      * in this application. </p>
178      */
179     public String getServletMapping() {
180         if (this.application == null) {
181             return null;
182         }
183 
184         return (String) this.application.getAttribute(Globals.SERVLET_KEY);
185     }
186 
187     // ---------------------------------------------------- Session Context
188 
189     /***
190      * <p> The transaction token stored in this session, if it is used. </p>
191      */
192     public String getToken() {
193         if (this.session == null) {
194             return null;
195         }
196 
197         return (String) session.getAttribute(Globals.TRANSACTION_TOKEN_KEY);
198     }
199 
200     // ---------------------------------------------------- Request Context
201 
202     /***
203      * <p> The runtime JspException that may be been thrown by a Struts tag
204      * extension, or compatible presentation extension, and placed in the
205      * request. </p>
206      */
207     public Throwable getException() {
208         if (this.request == null) {
209             return null;
210         }
211 
212         return (Throwable) this.request.getAttribute(Globals.EXCEPTION_KEY);
213     }
214 
215     /***
216      * <p> The multipart object for this request. </p>
217      */
218     public MultipartRequestWrapper getMultipartRequestWrapper() {
219         if (this.request == null) {
220             return null;
221         }
222 
223         return (MultipartRequestWrapper) this.request.getAttribute(Globals.MULTIPART_KEY);
224     }
225 
226     /***
227      * <p> The <code>org.apache.struts.ActionMapping</code> instance for this
228      * request. </p>
229      */
230     public ActionMapping getMapping() {
231         if (this.request == null) {
232             return null;
233         }
234 
235         return (ActionMapping) this.request.getAttribute(Globals.MAPPING_KEY);
236     }
237 
238     // ---------------------------------------------------- Utility Methods
239 
240     /***
241      * <p> Return true if a message string for the specified message key is
242      * present for the user's Locale. </p>
243      *
244      * @param key Message key
245      */
246     public boolean isMessage(String key) {
247         // Look up the requested MessageResources
248         MessageResources resources = getMessageResources();
249 
250         if (resources == null) {
251             return false;
252         }
253 
254         // Return the requested message presence indicator
255         return resources.isPresent(RequestUtils.getUserLocale(request, null),
256             key);
257     }
258 
259     /*
260      * <p>
261      * Retrieve and return the <code>ActionForm</code> bean associated with
262      * this mapping, creating and stashing one if necessary.  If there is no
263      * form bean associated with this mapping, return <code>null</code>.
264      * </p>
265      */
266     public ActionForm getActionForm() {
267         // Is there a mapping associated with this request?
268         ActionMapping mapping = getMapping();
269 
270         if (mapping == null) {
271             return (null);
272         }
273 
274         // Is there a form bean associated with this mapping?
275         String attribute = mapping.getAttribute();
276 
277         if (attribute == null) {
278             return (null);
279         }
280 
281         // Look up the existing form bean, if any
282         ActionForm instance;
283 
284         if ("request".equals(mapping.getScope())) {
285             instance = (ActionForm) this.request.getAttribute(attribute);
286         } else {
287             instance = (ActionForm) this.session.getAttribute(attribute);
288         }
289 
290         return instance;
291     }
292 
293     /***
294      * <p> Return the form bean definition associated with the specified
295      * logical name, if any; otherwise return <code>null</code>. </p>
296      *
297      * @param name Logical name of the requested form bean definition
298      */
299     public ActionFormBean getFormBean(String name) {
300         return null;
301     }
302 
303     /***
304      * <p> Return the forwarding associated with the specified logical name,
305      * if any; otherwise return <code>null</code>. </p>
306      *
307      * @param name Logical name of the requested forwarding
308      */
309     public ActionForward getActionForward(String name) {
310         return null;
311     }
312 
313     /***
314      * <p> Return the mapping associated with the specified request path, if
315      * any; otherwise return <code>null</code>. </p>
316      *
317      * @param path Request path for which a mapping is requested
318      */
319     public ActionMapping getActionMapping(String path) {
320         return null;
321     }
322 
323     /***
324      * <p> Return the form action converted into an action mapping path.  The
325      * value of the <code>action</code> property is manipulated as follows in
326      * computing the name of the requested mapping:</p>
327      *
328      * <ul>
329      *
330      * <li>Any filename extension is removed (on the theory that extension
331      * mapping is being used to select the controller servlet).</li>
332      *
333      * <li>If the resulting value does not start with a slash, then a slash is
334      * prepended.</li>
335      *
336      * </ul>
337      */
338     public String getActionMappingName(String action) {
339         String value = action;
340         int question = action.indexOf("?");
341 
342         if (question >= 0) {
343             value = value.substring(0, question);
344         }
345 
346         int slash = value.lastIndexOf("/");
347         int period = value.lastIndexOf(".");
348 
349         if ((period >= 0) && (period > slash)) {
350             value = value.substring(0, period);
351         }
352 
353         if (value.startsWith("/")) {
354             return (value);
355         } else {
356             return ("/" + value);
357         }
358     }
359 
360     /***
361      * <p> Return the form action converted into a server-relative URL. </p>
362      */
363     public String getActionMappingURL(String action) {
364         StringBuffer value = new StringBuffer(this.request.getContextPath());
365 
366         // Use our servlet mapping, if one is specified
367         String servletMapping = getServletMapping();
368 
369         if (servletMapping != null) {
370             String queryString = null;
371             int question = action.indexOf("?");
372 
373             if (question >= 0) {
374                 queryString = action.substring(question);
375             }
376 
377             String actionMapping = getActionMappingName(action);
378 
379             if (servletMapping.startsWith("*.")) {
380                 value.append(actionMapping);
381                 value.append(servletMapping.substring(1));
382             } else if (servletMapping.endsWith("/*")) {
383                 value.append(servletMapping.substring(0,
384                         servletMapping.length() - 2));
385                 value.append(actionMapping);
386             }
387 
388             if (queryString != null) {
389                 value.append(queryString);
390             }
391         }
392         // Otherwise, assume extension mapping is in use and extension is
393         // already included in the action property
394         else {
395             if (!action.startsWith("/")) {
396                 value.append("/");
397             }
398 
399             value.append(action);
400         }
401 
402         // Return the completed value
403         return (value.toString());
404     }
405 
406     /***
407      * <p> Return the url encoded to maintain the user session, if any. </p>
408      */
409     public String getEncodeURL(String url) {
410         if ((session != null) && (response != null)) {
411             boolean redirect = false;
412 
413             if (forward != null) {
414                 redirect = forward.getRedirect();
415             }
416 
417             if (redirect) {
418                 return response.encodeRedirectURL(url);
419             } else {
420                 return response.encodeURL(url);
421             }
422         } else {
423             return (url);
424         }
425     }
426 
427     // ------------------------------------------------ Presentation API
428 
429     /***
430      * <p> Renders the reference for a HTML <base> element </p>
431      */
432     public String getOrigRef() {
433         // HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
434         if (request == null) {
435             return null;
436         }
437 
438         StringBuffer result =
439             RequestUtils.requestToServerUriStringBuffer(request);
440 
441         return result.toString();
442     }
443 
444     /***
445      * <p> Renders the reference for a HTML <base> element. </p>
446      */
447     public String getBaseRef() {
448         if (request == null) {
449             return null;
450         }
451 
452         StringBuffer result = RequestUtils.requestToServerStringBuffer(request);
453         String path;
454 
455         if (forward == null) {
456             path = request.getRequestURI();
457         } else {
458             path = request.getContextPath() + forward.getPath();
459         }
460 
461         result.append(path);
462 
463         return result.toString();
464     }
465 
466     /***
467      * <p> Return the path for the specified forward, otherwise return
468      * <code>null</code>. </p>
469      *
470      * @param name Name given to local or global forward.
471      */
472     public String getLink(String name) {
473         ActionForward forward = getActionForward(name);
474 
475         if (forward == null) {
476             return null;
477         }
478 
479         StringBuffer path = new StringBuffer(this.request.getContextPath());
480 
481         path.append(forward.getPath());
482 
483         // :TODO: What about runtime parameters?
484         return getEncodeURL(path.toString());
485     }
486 
487     /***
488      * <p> Return the localized message for the specified key, otherwise
489      * return <code>null</code>. </p>
490      *
491      * @param key Message key
492      */
493     public String getMessage(String key) {
494         MessageResources resources = getMessageResources();
495 
496         if (resources == null) {
497             return null;
498         }
499 
500         return resources.getMessage(RequestUtils.getUserLocale(request, null),
501             key);
502     }
503 
504     /***
505      * <p> Look up and return a message string, based on the specified
506      * parameters. </p>
507      *
508      * @param key  Message key to be looked up and returned
509      * @param args Replacement parameters for this message
510      */
511     public String getMessage(String key, Object[] args) {
512         MessageResources resources = getMessageResources();
513 
514         if (resources == null) {
515             return null;
516         }
517 
518         // Return the requested message
519         if (args == null) {
520             return resources.getMessage(RequestUtils.getUserLocale(request, null),
521                 key);
522         } else {
523             return resources.getMessage(RequestUtils.getUserLocale(request, null),
524                 key, args);
525         }
526     }
527 
528     /***
529      * <p> Return the URL for the specified ActionMapping, otherwise return
530      * <code>null</code>. </p>
531      *
532      * @param path Name given to local or global forward.
533      */
534     public String getAction(String path) {
535         return getEncodeURL(getActionMappingURL(path));
536     }
537 
538     // --------------------------------------------- Presentation Wrappers
539 
540     /***
541      * <p> Wrapper for getLink(String) </p>
542      *
543      * @param name Name given to local or global forward.
544      */
545     public String link(String name) {
546         return getLink(name);
547     }
548 
549     /***
550      * <p> Wrapper for getMessage(String) </p>
551      *
552      * @param key Message key
553      */
554     public String message(String key) {
555         return getMessage(key);
556     }
557 
558     /***
559      * <p> Wrapper for getMessage(String,Object[]) </p>
560      *
561      * @param key  Message key to be looked up and returned
562      * @param args Replacement parameters for this message
563      */
564     public String message(String key, Object[] args) {
565         return getMessage(key, args);
566     }
567 
568     /***
569      * <p> Wrapper for getAction(String) </p>
570      *
571      * @param path Name given to local or global forward.
572      */
573     public String action(String path) {
574         return getAction(path);
575     }
576 }