001: /*
002: * $Id: ConfigHelper.java 471754 2006-11-06 14:55:09Z husted $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021: package org.apache.struts.config;
022:
023: import org.apache.struts.Globals;
024: import org.apache.struts.action.ActionForm;
025: import org.apache.struts.action.ActionFormBean;
026: import org.apache.struts.action.ActionForward;
027: import org.apache.struts.action.ActionMapping;
028: import org.apache.struts.action.ActionMessages;
029: import org.apache.struts.upload.MultipartRequestWrapper;
030: import org.apache.struts.util.MessageResources;
031: import org.apache.struts.util.RequestUtils;
032:
033: import javax.servlet.ServletContext;
034: import javax.servlet.http.HttpServletRequest;
035: import javax.servlet.http.HttpServletResponse;
036: import javax.servlet.http.HttpSession;
037:
038: /**
039: * <p> NOTE: THIS CLASS IS UNDER ACTIVE DEVELOPMENT. THE CURRENT CODE IS
040: * WRITTEN FOR CLARITY NOT EFFICIENCY. NOT EVERY API FUNCTION HAS BEEN
041: * IMPLEMENTED YET. </p><p> A helper object to expose the Struts shared
042: * resources, which are be stored in the application, session, or request
043: * contexts, as appropriate. </p><p> An instance should be created for each
044: * request processed. The methods which return resources from the request or
045: * session contexts are not thread-safe. </p><p> Provided for use by other
046: * servlets in the application so they can easily access the Struts shared
047: * resources. </p><p> The resources are stored under attributes in the
048: * application, session, or request contexts. </p><p> The ActionConfig methods
049: * simply return the resources from under the context and key used by the
050: * Struts ActionServlet when the resources are created. </p>
051: *
052: * @version $Rev: 471754 $ $Date: 2005-05-14 02:09:06 -0400 (Sat, 14 May 2005)
053: * $
054: * @since Struts 1.1
055: */
056: public class ConfigHelper implements ConfigHelperInterface {
057: // -------------------------------------------------------- Properites
058:
059: /**
060: * <p> The application associated with this instance. </p>
061: */
062: private ServletContext application = null;
063:
064: /**
065: * <p> The session associated with this instance. </p>
066: */
067: private HttpSession session = null;
068:
069: /**
070: * <p> The request associated with this instance. </p>
071: */
072: private HttpServletRequest request = null;
073:
074: /**
075: * <p> The response associated with this instance. </p>
076: */
077: private HttpServletResponse response = null;
078:
079: /**
080: * <p> The forward associated with this instance. </p>
081: */
082: private ActionForward forward = null;
083:
084: public ConfigHelper() {
085: super ();
086: }
087:
088: public ConfigHelper(ServletContext application,
089: HttpServletRequest request, HttpServletResponse response) {
090: super ();
091: this .setResources(application, request, response);
092: }
093:
094: /**
095: * <p> Set the application associated with this instance.
096: * [servlet.getServletContext()] </p>
097: */
098: public void setApplication(ServletContext application) {
099: this .application = application;
100: }
101:
102: /**
103: * <p> Set the session associated with this instance. </p>
104: */
105: public void setSession(HttpSession session) {
106: this .session = session;
107: }
108:
109: /**
110: * <p> Set the request associated with this object. Session object is also
111: * set or cleared. </p>
112: */
113: public void setRequest(HttpServletRequest request) {
114: this .request = request;
115:
116: if (this .request == null) {
117: setSession(null);
118: } else {
119: setSession(this .request.getSession());
120: }
121: }
122:
123: /**
124: * <p> Set the response associated with this isntance. Session object is
125: * also set or cleared. </p>
126: */
127: public void setResponse(HttpServletResponse response) {
128: this .response = response;
129: }
130:
131: /**
132: * Set the forward associated with this instance.
133: */
134: public void setForward(ActionForward forward) {
135: this .forward = forward;
136: }
137:
138: /**
139: * <p> Set the application and request for this object instance. The
140: * ServletContext can be set by any servlet in the application. The
141: * request should be the instant request. Most of the other methods
142: * retrieve their own objects by reference to the application, request, or
143: * session attributes. Do not call other methods without setting these
144: * first! This is also called by the convenience constructor. </p>
145: *
146: * @param application - The associated ServletContext.
147: * @param request - The associated HTTP request.
148: * @param response - The associated HTTP response.
149: */
150: public void setResources(ServletContext application,
151: HttpServletRequest request, HttpServletResponse response) {
152: setApplication(application);
153: setRequest(request);
154: setResponse(response);
155: }
156:
157: // ------------------------------------------------ Application Context
158: public ActionMessages getActionMessages() {
159: if (this .application == null) {
160: return null;
161: }
162:
163: return (ActionMessages) this .application
164: .getAttribute(Globals.MESSAGE_KEY);
165: }
166:
167: /**
168: * <p> The application resources for this application. </p>
169: */
170: public MessageResources getMessageResources() {
171: if (this .application == null) {
172: return null;
173: }
174:
175: return (MessageResources) this .application
176: .getAttribute(Globals.MESSAGES_KEY);
177: }
178:
179: /**
180: * <p> The path-mapped pattern (<code>/action/*</code>) or extension
181: * mapped pattern ((<code>*.do</code>) used to determine our Action URIs
182: * in this application. </p>
183: */
184: public String getServletMapping() {
185: if (this .application == null) {
186: return null;
187: }
188:
189: return (String) this .application
190: .getAttribute(Globals.SERVLET_KEY);
191: }
192:
193: // ---------------------------------------------------- Session Context
194:
195: /**
196: * <p> The transaction token stored in this session, if it is used. </p>
197: */
198: public String getToken() {
199: if (this .session == null) {
200: return null;
201: }
202:
203: return (String) session
204: .getAttribute(Globals.TRANSACTION_TOKEN_KEY);
205: }
206:
207: // ---------------------------------------------------- Request Context
208:
209: /**
210: * <p> The runtime JspException that may be been thrown by a Struts tag
211: * extension, or compatible presentation extension, and placed in the
212: * request. </p>
213: */
214: public Throwable getException() {
215: if (this .request == null) {
216: return null;
217: }
218:
219: return (Throwable) this .request
220: .getAttribute(Globals.EXCEPTION_KEY);
221: }
222:
223: /**
224: * <p> The multipart object for this request. </p>
225: */
226: public MultipartRequestWrapper getMultipartRequestWrapper() {
227: if (this .request == null) {
228: return null;
229: }
230:
231: return (MultipartRequestWrapper) this .request
232: .getAttribute(Globals.MULTIPART_KEY);
233: }
234:
235: /**
236: * <p> The <code>org.apache.struts.ActionMapping</code> instance for this
237: * request. </p>
238: */
239: public ActionMapping getMapping() {
240: if (this .request == null) {
241: return null;
242: }
243:
244: return (ActionMapping) this .request
245: .getAttribute(Globals.MAPPING_KEY);
246: }
247:
248: // ---------------------------------------------------- Utility Methods
249:
250: /**
251: * <p> Return true if a message string for the specified message key is
252: * present for the user's Locale. </p>
253: *
254: * @param key Message key
255: */
256: public boolean isMessage(String key) {
257: // Look up the requested MessageResources
258: MessageResources resources = getMessageResources();
259:
260: if (resources == null) {
261: return false;
262: }
263:
264: // Return the requested message presence indicator
265: return resources.isPresent(RequestUtils.getUserLocale(request,
266: null), key);
267: }
268:
269: /*
270: * <p>
271: * Retrieve and return the <code>ActionForm</code> bean associated with
272: * this mapping, creating and stashing one if necessary. If there is no
273: * form bean associated with this mapping, return <code>null</code>.
274: * </p>
275: */
276: public ActionForm getActionForm() {
277: // Is there a mapping associated with this request?
278: ActionMapping mapping = getMapping();
279:
280: if (mapping == null) {
281: return (null);
282: }
283:
284: // Is there a form bean associated with this mapping?
285: String attribute = mapping.getAttribute();
286:
287: if (attribute == null) {
288: return (null);
289: }
290:
291: // Look up the existing form bean, if any
292: ActionForm instance;
293:
294: if ("request".equals(mapping.getScope())) {
295: instance = (ActionForm) this .request
296: .getAttribute(attribute);
297: } else {
298: instance = (ActionForm) this .session
299: .getAttribute(attribute);
300: }
301:
302: return instance;
303: }
304:
305: /**
306: * <p> Return the form bean definition associated with the specified
307: * logical name, if any; otherwise return <code>null</code>. </p>
308: *
309: * @param name Logical name of the requested form bean definition
310: */
311: public ActionFormBean getFormBean(String name) {
312: return null;
313: }
314:
315: /**
316: * <p> Return the forwarding associated with the specified logical name,
317: * if any; otherwise return <code>null</code>. </p>
318: *
319: * @param name Logical name of the requested forwarding
320: */
321: public ActionForward getActionForward(String name) {
322: return null;
323: }
324:
325: /**
326: * <p> Return the mapping associated with the specified request path, if
327: * any; otherwise return <code>null</code>. </p>
328: *
329: * @param path Request path for which a mapping is requested
330: */
331: public ActionMapping getActionMapping(String path) {
332: return null;
333: }
334:
335: /**
336: * <p> Return the form action converted into an action mapping path. The
337: * value of the <code>action</code> property is manipulated as follows in
338: * computing the name of the requested mapping:</p>
339: *
340: * <ul>
341: *
342: * <li>Any filename extension is removed (on the theory that extension
343: * mapping is being used to select the controller servlet).</li>
344: *
345: * <li>If the resulting value does not start with a slash, then a slash is
346: * prepended.</li>
347: *
348: * </ul>
349: */
350: public String getActionMappingName(String action) {
351: String value = action;
352: int question = action.indexOf("?");
353:
354: if (question >= 0) {
355: value = value.substring(0, question);
356: }
357:
358: int slash = value.lastIndexOf("/");
359: int period = value.lastIndexOf(".");
360:
361: if ((period >= 0) && (period > slash)) {
362: value = value.substring(0, period);
363: }
364:
365: if (value.startsWith("/")) {
366: return (value);
367: } else {
368: return ("/" + value);
369: }
370: }
371:
372: /**
373: * <p> Return the form action converted into a server-relative URL. </p>
374: */
375: public String getActionMappingURL(String action) {
376: StringBuffer value = new StringBuffer(this .request
377: .getContextPath());
378:
379: // Use our servlet mapping, if one is specified
380: String servletMapping = getServletMapping();
381:
382: if (servletMapping != null) {
383: String queryString = null;
384: int question = action.indexOf("?");
385:
386: if (question >= 0) {
387: queryString = action.substring(question);
388: }
389:
390: String actionMapping = getActionMappingName(action);
391:
392: if (servletMapping.startsWith("*.")) {
393: value.append(actionMapping);
394: value.append(servletMapping.substring(1));
395: } else if (servletMapping.endsWith("/*")) {
396: value.append(servletMapping.substring(0, servletMapping
397: .length() - 2));
398: value.append(actionMapping);
399: }
400:
401: if (queryString != null) {
402: value.append(queryString);
403: }
404: }
405: // Otherwise, assume extension mapping is in use and extension is
406: // already included in the action property
407: else {
408: if (!action.startsWith("/")) {
409: value.append("/");
410: }
411:
412: value.append(action);
413: }
414:
415: // Return the completed value
416: return (value.toString());
417: }
418:
419: /**
420: * <p> Return the url encoded to maintain the user session, if any. </p>
421: */
422: public String getEncodeURL(String url) {
423: if ((session != null) && (response != null)) {
424: boolean redirect = false;
425:
426: if (forward != null) {
427: redirect = forward.getRedirect();
428: }
429:
430: if (redirect) {
431: return response.encodeRedirectURL(url);
432: } else {
433: return response.encodeURL(url);
434: }
435: } else {
436: return (url);
437: }
438: }
439:
440: // ------------------------------------------------ Presentation API
441:
442: /**
443: * <p> Renders the reference for a HTML <base> element </p>
444: */
445: public String getOrigRef() {
446: // HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
447: if (request == null) {
448: return null;
449: }
450:
451: StringBuffer result = RequestUtils
452: .requestToServerUriStringBuffer(request);
453:
454: return result.toString();
455: }
456:
457: /**
458: * <p> Renders the reference for a HTML <base> element. </p>
459: */
460: public String getBaseRef() {
461: if (request == null) {
462: return null;
463: }
464:
465: StringBuffer result = RequestUtils
466: .requestToServerStringBuffer(request);
467: String path;
468:
469: if (forward == null) {
470: path = request.getRequestURI();
471: } else {
472: path = request.getContextPath() + forward.getPath();
473: }
474:
475: result.append(path);
476:
477: return result.toString();
478: }
479:
480: /**
481: * <p> Return the path for the specified forward, otherwise return
482: * <code>null</code>. </p>
483: *
484: * @param name Name given to local or global forward.
485: */
486: public String getLink(String name) {
487: ActionForward forward = getActionForward(name);
488:
489: if (forward == null) {
490: return null;
491: }
492:
493: StringBuffer path = new StringBuffer(this .request
494: .getContextPath());
495:
496: path.append(forward.getPath());
497:
498: // :TODO: What about runtime parameters?
499: return getEncodeURL(path.toString());
500: }
501:
502: /**
503: * <p> Return the localized message for the specified key, otherwise
504: * return <code>null</code>. </p>
505: *
506: * @param key Message key
507: */
508: public String getMessage(String key) {
509: MessageResources resources = getMessageResources();
510:
511: if (resources == null) {
512: return null;
513: }
514:
515: return resources.getMessage(RequestUtils.getUserLocale(request,
516: null), key);
517: }
518:
519: /**
520: * <p> Look up and return a message string, based on the specified
521: * parameters. </p>
522: *
523: * @param key Message key to be looked up and returned
524: * @param args Replacement parameters for this message
525: */
526: public String getMessage(String key, Object[] args) {
527: MessageResources resources = getMessageResources();
528:
529: if (resources == null) {
530: return null;
531: }
532:
533: // Return the requested message
534: if (args == null) {
535: return resources.getMessage(RequestUtils.getUserLocale(
536: request, null), key);
537: } else {
538: return resources.getMessage(RequestUtils.getUserLocale(
539: request, null), key, args);
540: }
541: }
542:
543: /**
544: * <p> Return the URL for the specified ActionMapping, otherwise return
545: * <code>null</code>. </p>
546: *
547: * @param path Name given to local or global forward.
548: */
549: public String getAction(String path) {
550: return getEncodeURL(getActionMappingURL(path));
551: }
552:
553: // --------------------------------------------- Presentation Wrappers
554:
555: /**
556: * <p> Wrapper for getLink(String) </p>
557: *
558: * @param name Name given to local or global forward.
559: */
560: public String link(String name) {
561: return getLink(name);
562: }
563:
564: /**
565: * <p> Wrapper for getMessage(String) </p>
566: *
567: * @param key Message key
568: */
569: public String message(String key) {
570: return getMessage(key);
571: }
572:
573: /**
574: * <p> Wrapper for getMessage(String,Object[]) </p>
575: *
576: * @param key Message key to be looked up and returned
577: * @param args Replacement parameters for this message
578: */
579: public String message(String key, Object[] args) {
580: return getMessage(key, args);
581: }
582:
583: /**
584: * <p> Wrapper for getAction(String) </p>
585: *
586: * @param path Name given to local or global forward.
587: */
588: public String action(String path) {
589: return getAction(path);
590: }
591: }
|