1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts.util;
19
20 import org.apache.commons.beanutils.BeanUtils;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.struts.Globals;
24 import org.apache.struts.action.ActionForm;
25 import org.apache.struts.action.ActionMapping;
26 import org.apache.struts.action.ActionServlet;
27 import org.apache.struts.action.ActionServletWrapper;
28 import org.apache.struts.config.ActionConfig;
29 import org.apache.struts.config.FormBeanConfig;
30 import org.apache.struts.config.ForwardConfig;
31 import org.apache.struts.config.ModuleConfig;
32 import org.apache.struts.upload.MultipartRequestHandler;
33 import org.apache.struts.upload.MultipartRequestWrapper;
34
35 import javax.servlet.ServletException;
36 import javax.servlet.http.HttpServletRequest;
37 import javax.servlet.http.HttpSession;
38
39 import java.net.MalformedURLException;
40 import java.net.URL;
41
42 import java.util.Collections;
43 import java.util.Enumeration;
44 import java.util.HashMap;
45 import java.util.Hashtable;
46 import java.util.Locale;
47 import java.util.Map;
48
49 /***
50 * <p>General purpose utility methods related to processing a servlet request
51 * in the Struts controller framework.</p>
52 *
53 * @version $Rev: 421119 $ $Date: 2006-07-11 21:49:11 -0700 (Tue, 11 Jul 2006) $
54 */
55 public class RequestUtils {
56
57
58 /***
59 * <p>Commons Logging instance.</p>
60 */
61 protected static Log log = LogFactory.getLog(RequestUtils.class);
62
63
64
65 /***
66 * <p>Create and return an absolute URL for the specified context-relative
67 * path, based on the server and context information in the specified
68 * request.</p>
69 *
70 * @param request The servlet request we are processing
71 * @param path The context-relative path (must start with '/')
72 * @return absolute URL based on context-relative path
73 * @throws MalformedURLException if we cannot create an absolute URL
74 */
75 public static URL absoluteURL(HttpServletRequest request, String path)
76 throws MalformedURLException {
77 return (new URL(serverURL(request), request.getContextPath() + path));
78 }
79
80 /***
81 * <p>Return the <code>Class</code> object for the specified fully
82 * qualified class name, from this web application's class loader.</p>
83 *
84 * @param className Fully qualified class name to be loaded
85 * @return Class object
86 * @throws ClassNotFoundException if the class cannot be found
87 */
88 public static Class applicationClass(String className)
89 throws ClassNotFoundException {
90 return applicationClass(className, null);
91 }
92
93 /***
94 * <p>Return the <code>Class</code> object for the specified fully
95 * qualified class name, from this web application's class loader.</p>
96 *
97 * @param className Fully qualified class name to be loaded
98 * @param classLoader The desired classloader to use
99 * @return Class object
100 * @throws ClassNotFoundException if the class cannot be found
101 */
102 public static Class applicationClass(String className,
103 ClassLoader classLoader)
104 throws ClassNotFoundException {
105 if (classLoader == null) {
106
107 classLoader = Thread.currentThread().getContextClassLoader();
108
109 if (classLoader == null) {
110 classLoader = RequestUtils.class.getClassLoader();
111 }
112 }
113
114
115 return (classLoader.loadClass(className));
116 }
117
118 /***
119 * <p>Return a new instance of the specified fully qualified class name,
120 * after loading the class from this web application's class loader. The
121 * specified class <strong>MUST</strong> have a public zero-arguments
122 * constructor.</p>
123 *
124 * @param className Fully qualified class name to use
125 * @return new instance of class
126 * @throws ClassNotFoundException if the class cannot be found
127 * @throws IllegalAccessException if the class or its constructor is not
128 * accessible
129 * @throws InstantiationException if this class represents an abstract
130 * class, an interface, an array class, a
131 * primitive type, or void
132 * @throws InstantiationException if this class has no zero-arguments
133 * constructor
134 */
135 public static Object applicationInstance(String className)
136 throws ClassNotFoundException, IllegalAccessException,
137 InstantiationException {
138 return applicationInstance(className, null);
139 }
140
141 /***
142 * <p>Return a new instance of the specified fully qualified class name,
143 * after loading the class from this web application's class loader. The
144 * specified class <strong>MUST</strong> have a public zero-arguments
145 * constructor.</p>
146 *
147 * @param className Fully qualified class name to use
148 * @param classLoader The desired classloader to use
149 * @return new instance of class
150 * @throws ClassNotFoundException if the class cannot be found
151 * @throws IllegalAccessException if the class or its constructor is not
152 * accessible
153 * @throws InstantiationException if this class represents an abstract
154 * class, an interface, an array class, a
155 * primitive type, or void
156 * @throws InstantiationException if this class has no zero-arguments
157 * constructor
158 */
159 public static Object applicationInstance(String className,
160 ClassLoader classLoader)
161 throws ClassNotFoundException, IllegalAccessException,
162 InstantiationException {
163 return (applicationClass(className, classLoader).newInstance());
164 }
165
166 /***
167 * <p>Create (if necessary) and return an <code>ActionForm</code> instance
168 * appropriate for this request. If no <code>ActionForm</code> instance
169 * is required, return <code>null</code>.</p>
170 *
171 * @param request The servlet request we are processing
172 * @param mapping The action mapping for this request
173 * @param moduleConfig The configuration for this module
174 * @param servlet The action servlet
175 * @return ActionForm instance associated with this request
176 */
177 public static ActionForm createActionForm(HttpServletRequest request,
178 ActionMapping mapping, ModuleConfig moduleConfig, ActionServlet servlet) {
179
180 String attribute = mapping.getAttribute();
181
182 if (attribute == null) {
183 return (null);
184 }
185
186
187 String name = mapping.getName();
188 FormBeanConfig config = moduleConfig.findFormBeanConfig(name);
189
190 if (config == null) {
191 log.warn("No FormBeanConfig found under '" + name + "'");
192
193 return (null);
194 }
195
196 ActionForm instance =
197 lookupActionForm(request, attribute, mapping.getScope());
198
199
200 if ((instance != null) && config.canReuse(instance)) {
201 return (instance);
202 }
203
204 return createActionForm(config, servlet);
205 }
206
207 private static ActionForm lookupActionForm(HttpServletRequest request,
208 String attribute, String scope) {
209
210 if (log.isDebugEnabled()) {
211 log.debug(" Looking for ActionForm bean instance in scope '"
212 + scope + "' under attribute key '" + attribute + "'");
213 }
214
215 ActionForm instance = null;
216 HttpSession session = null;
217
218 if ("request".equals(scope)) {
219 instance = (ActionForm) request.getAttribute(attribute);
220 } else {
221 session = request.getSession();
222 instance = (ActionForm) session.getAttribute(attribute);
223 }
224
225 return (instance);
226 }
227
228 /***
229 * <p>Create and return an <code>ActionForm</code> instance appropriate to
230 * the information in <code>config</code>.</p>
231 *
232 * <p>Does not perform any checks to see if an existing ActionForm exists
233 * which could be reused.</p>
234 *
235 * @param config The configuration for the Form bean which is to be
236 * created.
237 * @param servlet The action servlet
238 * @return ActionForm instance associated with this request
239 */
240 public static ActionForm createActionForm(FormBeanConfig config,
241 ActionServlet servlet) {
242 if (config == null) {
243 return (null);
244 }
245
246 ActionForm instance = null;
247
248
249 try {
250 instance = config.createActionForm(servlet);
251
252 if (log.isDebugEnabled()) {
253 log.debug(" Creating new "
254 + (config.getDynamic() ? "DynaActionForm" : "ActionForm")
255 + " instance of type '" + config.getType() + "'");
256 log.trace(" --> " + instance);
257 }
258 } catch (Throwable t) {
259 log.error(servlet.getInternal().getMessage("formBean",
260 config.getType()), t);
261 }
262
263 return (instance);
264 }
265
266 /***
267 * <p>Look up and return current user locale, based on the specified
268 * parameters.</p>
269 *
270 * @param request The request used to lookup the Locale
271 * @param locale Name of the session attribute for our user's Locale. If
272 * this is <code>null</code>, the default locale key is
273 * used for the lookup.
274 * @return current user locale
275 * @since Struts 1.2
276 */
277 public static Locale getUserLocale(HttpServletRequest request, String locale) {
278 Locale userLocale = null;
279 HttpSession session = request.getSession(false);
280
281 if (locale == null) {
282 locale = Globals.LOCALE_KEY;
283 }
284
285
286 if (session != null) {
287 userLocale = (Locale) session.getAttribute(locale);
288 }
289
290 if (userLocale == null) {
291
292 userLocale = request.getLocale();
293 }
294
295 return userLocale;
296 }
297
298 /***
299 * <p>Populate the properties of the specified JavaBean from the specified
300 * HTTP request, based on matching each parameter name against the
301 * corresponding JavaBeans "property setter" methods in the bean's class.
302 * Suitable conversion is done for argument types as described under
303 * <code>convert()</code>.</p>
304 *
305 * @param bean The JavaBean whose properties are to be set
306 * @param request The HTTP request whose parameters are to be used to
307 * populate bean properties
308 * @throws ServletException if an exception is thrown while setting
309 * property values
310 */
311 public static void populate(Object bean, HttpServletRequest request)
312 throws ServletException {
313 populate(bean, null, null, request);
314 }
315
316 /***
317 * <p>Populate the properties of the specified JavaBean from the specified
318 * HTTP request, based on matching each parameter name (plus an optional
319 * prefix and/or suffix) against the corresponding JavaBeans "property
320 * setter" methods in the bean's class. Suitable conversion is done for
321 * argument types as described under <code>setProperties</code>.</p>
322 *
323 * <p>If you specify a non-null <code>prefix</code> and a non-null
324 * <code>suffix</code>, the parameter name must match
325 * <strong>both</strong> conditions for its value(s) to be used in
326 * populating bean properties. If the request's content type is
327 * "multipart/form-data" and the method is "POST", the
328 * <code>HttpServletRequest</code> object will be wrapped in a
329 * <code>MultipartRequestWrapper</code object.</p>
330 *
331 * @param bean The JavaBean whose properties are to be set
332 * @param prefix The prefix (if any) to be prepend to bean property names
333 * when looking for matching parameters
334 * @param suffix The suffix (if any) to be appended to bean property
335 * names when looking for matching parameters
336 * @param request The HTTP request whose parameters are to be used to
337 * populate bean properties
338 * @throws ServletException if an exception is thrown while setting
339 * property values
340 */
341 public static void populate(Object bean, String prefix, String suffix,
342 HttpServletRequest request)
343 throws ServletException {
344
345 HashMap properties = new HashMap();
346
347
348 Enumeration names = null;
349
350
351 Map multipartParameters = null;
352
353 String contentType = request.getContentType();
354 String method = request.getMethod();
355 boolean isMultipart = false;
356
357 if (bean instanceof ActionForm) {
358 ((ActionForm) bean).setMultipartRequestHandler(null);
359 }
360
361 MultipartRequestHandler multipartHandler = null;
362 if ((contentType != null)
363 && (contentType.startsWith("multipart/form-data"))
364 && (method.equalsIgnoreCase("POST"))) {
365
366 ActionServletWrapper servlet;
367
368 if (bean instanceof ActionForm) {
369 servlet = ((ActionForm) bean).getServletWrapper();
370 } else {
371 throw new ServletException("bean that's supposed to be "
372 + "populated from a multipart request is not of type "
373 + "\"org.apache.struts.action.ActionForm\", but type "
374 + "\"" + bean.getClass().getName() + "\"");
375 }
376
377
378 multipartHandler = getMultipartHandler(request);
379
380 if (multipartHandler != null) {
381 isMultipart = true;
382
383
384 servlet.setServletFor(multipartHandler);
385 multipartHandler.setMapping((ActionMapping) request
386 .getAttribute(Globals.MAPPING_KEY));
387
388
389 multipartHandler.handleRequest(request);
390
391
392 Boolean maxLengthExceeded =
393 (Boolean) request.getAttribute(MultipartRequestHandler.ATTRIBUTE_MAX_LENGTH_EXCEEDED);
394
395 if ((maxLengthExceeded != null)
396 && (maxLengthExceeded.booleanValue())) {
397 ((ActionForm) bean).setMultipartRequestHandler(multipartHandler);
398 return;
399 }
400
401
402 multipartParameters =
403 getAllParametersForMultipartRequest(request,
404 multipartHandler);
405 names = Collections.enumeration(multipartParameters.keySet());
406 }
407 }
408
409 if (!isMultipart) {
410 names = request.getParameterNames();
411 }
412
413 while (names.hasMoreElements()) {
414 String name = (String) names.nextElement();
415 String stripped = name;
416
417 if (prefix != null) {
418 if (!stripped.startsWith(prefix)) {
419 continue;
420 }
421
422 stripped = stripped.substring(prefix.length());
423 }
424
425 if (suffix != null) {
426 if (!stripped.endsWith(suffix)) {
427 continue;
428 }
429
430 stripped =
431 stripped.substring(0, stripped.length() - suffix.length());
432 }
433
434 Object parameterValue = null;
435
436 if (isMultipart) {
437 parameterValue = multipartParameters.get(name);
438 } else {
439 parameterValue = request.getParameterValues(name);
440 }
441
442
443
444 if (!(stripped.startsWith("org.apache.struts."))) {
445 properties.put(stripped, parameterValue);
446 }
447 }
448
449
450 try {
451 BeanUtils.populate(bean, properties);
452 } catch (Exception e) {
453 throw new ServletException("BeanUtils.populate", e);
454 } finally {
455 if (multipartHandler != null) {
456
457
458
459
460 ((ActionForm) bean).setMultipartRequestHandler(multipartHandler);
461 }
462 }
463 }
464
465 /***
466 * <p>Try to locate a multipart request handler for this request. First,
467 * look for a mapping-specific handler stored for us under an attribute.
468 * If one is not present, use the global multipart handler, if there is
469 * one.</p>
470 *
471 * @param request The HTTP request for which the multipart handler should
472 * be found.
473 * @return the multipart handler to use, or null if none is found.
474 * @throws ServletException if any exception is thrown while attempting to
475 * locate the multipart handler.
476 */
477 private static MultipartRequestHandler getMultipartHandler(
478 HttpServletRequest request)
479 throws ServletException {
480 MultipartRequestHandler multipartHandler = null;
481 String multipartClass =
482 (String) request.getAttribute(Globals.MULTIPART_KEY);
483
484 request.removeAttribute(Globals.MULTIPART_KEY);
485
486
487 if (multipartClass != null) {
488 try {
489 multipartHandler =
490 (MultipartRequestHandler) applicationInstance(multipartClass);
491 } catch (ClassNotFoundException cnfe) {
492 log.error("MultipartRequestHandler class \"" + multipartClass
493 + "\" in mapping class not found, "
494 + "defaulting to global multipart class");
495 } catch (InstantiationException ie) {
496 log.error("InstantiationException when instantiating "
497 + "MultipartRequestHandler \"" + multipartClass + "\", "
498 + "defaulting to global multipart class, exception: "
499 + ie.getMessage());
500 } catch (IllegalAccessException iae) {
501 log.error("IllegalAccessException when instantiating "
502 + "MultipartRequestHandler \"" + multipartClass + "\", "
503 + "defaulting to global multipart class, exception: "
504 + iae.getMessage());
505 }
506
507 if (multipartHandler != null) {
508 return multipartHandler;
509 }
510 }
511
512 ModuleConfig moduleConfig =
513 ModuleUtils.getInstance().getModuleConfig(request);
514
515 multipartClass = moduleConfig.getControllerConfig().getMultipartClass();
516
517
518 if (multipartClass != null) {
519 try {
520 multipartHandler =
521 (MultipartRequestHandler) applicationInstance(multipartClass);
522 } catch (ClassNotFoundException cnfe) {
523 throw new ServletException("Cannot find multipart class \""
524 + multipartClass + "\"" + ", exception: "
525 + cnfe.getMessage());
526 } catch (InstantiationException ie) {
527 throw new ServletException(
528 "InstantiationException when instantiating "
529 + "multipart class \"" + multipartClass + "\", exception: "
530 + ie.getMessage());
531 } catch (IllegalAccessException iae) {
532 throw new ServletException(
533 "IllegalAccessException when instantiating "
534 + "multipart class \"" + multipartClass + "\", exception: "
535 + iae.getMessage());
536 }
537
538 if (multipartHandler != null) {
539 return multipartHandler;
540 }
541 }
542
543 return multipartHandler;
544 }
545
546 /***
547 * <p>Create a <code>Map</code> containing all of the parameters supplied
548 * for a multipart request, keyed by parameter name. In addition to text
549 * and file elements from the multipart body, query string parameters are
550 * included as well.</p>
551 *
552 * @param request The (wrapped) HTTP request whose parameters are
553 * to be added to the map.
554 * @param multipartHandler The multipart handler used to parse the
555 * request.
556 * @return the map containing all parameters for this multipart request.
557 */
558 private static Map getAllParametersForMultipartRequest(
559 HttpServletRequest request, MultipartRequestHandler multipartHandler) {
560 Map parameters = new HashMap();
561 Hashtable elements = multipartHandler.getAllElements();
562 Enumeration e = elements.keys();
563
564 while (e.hasMoreElements()) {
565 String key = (String) e.nextElement();
566
567 parameters.put(key, elements.get(key));
568 }
569
570 if (request instanceof MultipartRequestWrapper) {
571 request =
572 (HttpServletRequest) ((MultipartRequestWrapper) request)
573 .getRequest();
574 e = request.getParameterNames();
575
576 while (e.hasMoreElements()) {
577 String key = (String) e.nextElement();
578
579 parameters.put(key, request.getParameterValues(key));
580 }
581 } else {
582 log.debug("Gathering multipart parameters for unwrapped request");
583 }
584
585 return parameters;
586 }
587
588 /***
589 * <p>Compute the printable representation of a URL, leaving off the
590 * scheme/host/port part if no host is specified. This will typically be
591 * the case for URLs that were originally created from relative or
592 * context-relative URIs.</p>
593 *
594 * @param url URL to render in a printable representation
595 * @return printable representation of a URL
596 */
597 public static String printableURL(URL url) {
598 if (url.getHost() != null) {
599 return (url.toString());
600 }
601
602 String file = url.getFile();
603 String ref = url.getRef();
604
605 if (ref == null) {
606 return (file);
607 } else {
608 StringBuffer sb = new StringBuffer(file);
609
610 sb.append('#');
611 sb.append(ref);
612
613 return (sb.toString());
614 }
615 }
616
617 /***
618 * <p>Return the context-relative URL that corresponds to the specified
619 * {@link ActionConfig}, relative to the module associated with the
620 * current modules's {@link ModuleConfig}.</p>
621 *
622 * @param request The servlet request we are processing
623 * @param action ActionConfig to be evaluated
624 * @param pattern URL pattern used to map the controller servlet
625 * @return context-relative URL relative to the module
626 * @since Struts 1.1
627 */
628 public static String actionURL(HttpServletRequest request,
629 ActionConfig action, String pattern) {
630 StringBuffer sb = new StringBuffer();
631
632 if (pattern.endsWith("/*")) {
633 sb.append(pattern.substring(0, pattern.length() - 2));
634 sb.append(action.getPath());
635 } else if (pattern.startsWith("*.")) {
636 ModuleConfig appConfig =
637 ModuleUtils.getInstance().getModuleConfig(request);
638
639 sb.append(appConfig.getPrefix());
640 sb.append(action.getPath());
641 sb.append(pattern.substring(1));
642 } else {
643 throw new IllegalArgumentException(pattern);
644 }
645
646 return sb.toString();
647 }
648
649 /***
650 * <p>Return the context-relative URL that corresponds to the specified
651 * <code>ForwardConfig</code>. The URL is calculated based on the
652 * properties of the {@link ForwardConfig} instance as follows:</p>
653 *
654 * <ul>
655 *
656 *
657 * <li>If the <code>contextRelative</code> property is set, it is assumed
658 * that the <code>path</code> property contains a path that is already
659 * context-relative:
660 *
661 * <ul>
662 *
663 * <li>If the <code>path</code> property value starts with a slash, it is
664 * returned unmodified.</li> <li>If the <code>path</code> property value
665 * does not start with a slash, a slash is prepended.</li>
666 *
667 * </ul></li>
668 *
669 * <li>Acquire the <code>forwardPattern</code> property from the
670 * <code>ControllerConfig</code> for the application module used to
671 * process this request. If no pattern was configured, default to a
672 * pattern of <code>$M$P</code>, which is compatible with the hard-coded
673 * mapping behavior in Struts 1.0.</li>
674 *
675 * <li>Process the acquired <code>forwardPattern</code>, performing the
676 * following substitutions:
677 *
678 * <ul>
679 *
680 * <li><strong>$M</strong> - Replaced by the module prefix for the
681 * application module processing this request.</li>
682 *
683 * <li><strong>$P</strong> - Replaced by the <code>path</code> property of
684 * the specified {@link ForwardConfig}, prepended with a slash if it does
685 * not start with one.</li>
686 *
687 * <li><strong>$$</strong> - Replaced by a single dollar sign
688 * character.</li>
689 *
690 * <li><strong>$x</strong> (where "x" is any charater not listed above) -
691 * Silently omit these two characters from the result value. (This has
692 * the side effect of causing all other $+letter combinations to be
693 * reserved.)</li>
694 *
695 * </ul></li>
696 *
697 * </ul>
698 *
699 * @param request The servlet request we are processing
700 * @param forward ForwardConfig to be evaluated
701 * @return context-relative URL
702 * @since Struts 1.1
703 */
704 public static String forwardURL(HttpServletRequest request,
705 ForwardConfig forward) {
706 return forwardURL(request, forward, null);
707 }
708
709 /***
710 * <p>Return the context-relative URL that corresponds to the specified
711 * <code>ForwardConfig</code>. The URL is calculated based on the
712 * properties of the {@link ForwardConfig} instance as follows:</p>
713 *
714 * <ul>
715 *
716 * <li>If the <code>contextRelative</code> property is set, it is assumed
717 * that the <code>path</code> property contains a path that is already
718 * context-relative: <ul>
719 *
720 * <li>If the <code>path</code> property value starts with a slash, it is
721 * returned unmodified.</li> <li>If the <code>path</code> property value
722 * does not start with a slash, a slash is prepended.</li>
723 *
724 * </ul></li>
725 *
726 * <li>Acquire the <code>forwardPattern</code> property from the
727 * <code>ControllerConfig</code> for the application module used to
728 * process this request. If no pattern was configured, default to a
729 * pattern of <code>$M$P</code>, which is compatible with the hard-coded
730 * mapping behavior in Struts 1.0.</li>
731 *
732 * <li>Process the acquired <code>forwardPattern</code>, performing the
733 * following substitutions: <ul> <li><strong>$M</strong> - Replaced by the
734 * module prefix for the application module processing this request.</li>
735 *
736 * <li><strong>$P</strong> - Replaced by the <code>path</code> property of
737 * the specified {@link ForwardConfig}, prepended with a slash if it does
738 * not start with one.</li>
739 *
740 * <li><strong>$$</strong> - Replaced by a single dollar sign
741 * character.</li>
742 *
743 * <li><strong>$x</strong> (where "x" is any charater not listed above) -
744 * Silently omit these two characters from the result value. (This has
745 * the side effect of causing all other $+letter combinations to be
746 * reserved.)</li>
747 *
748 * </ul></li></ul>
749 *
750 * @param request The servlet request we are processing
751 * @param forward ForwardConfig to be evaluated
752 * @param moduleConfig Base forward on this module config.
753 * @return context-relative URL
754 * @since Struts 1.2
755 */
756 public static String forwardURL(HttpServletRequest request,
757 ForwardConfig forward, ModuleConfig moduleConfig) {
758
759 if (moduleConfig == null) {
760 moduleConfig = ModuleUtils.getInstance().getModuleConfig(request);
761 }
762
763 String path = forward.getPath();
764
765
766 String prefix = moduleConfig.getPrefix();
767
768
769 if (forward.getModule() != null) {
770 prefix = forward.getModule();
771
772 if ("/".equals(prefix)) {
773 prefix = "";
774 }
775 }
776
777 StringBuffer sb = new StringBuffer();
778
779
780 String forwardPattern =
781 moduleConfig.getControllerConfig().getForwardPattern();
782
783 if (forwardPattern == null) {
784
785 sb.append(prefix);
786
787
788 if (!path.startsWith("/")) {
789 sb.append("/");
790 }
791
792 sb.append(path);
793 } else {
794 boolean dollar = false;
795
796 for (int i = 0; i < forwardPattern.length(); i++) {
797 char ch = forwardPattern.charAt(i);
798
799 if (dollar) {
800 switch (ch) {
801 case 'M':
802 sb.append(prefix);
803
804 break;
805
806 case 'P':
807
808
809 if (!path.startsWith("/")) {
810 sb.append("/");
811 }
812
813 sb.append(path);
814
815 break;
816
817 case '$':
818 sb.append('$');
819
820 break;
821
822 default:
823 ;
824 }
825
826 dollar = false;
827
828 continue;
829 } else if (ch == '$') {
830 dollar = true;
831 } else {
832 sb.append(ch);
833 }
834 }
835 }
836
837 return (sb.toString());
838 }
839
840 /***
841 * <p>Return the URL representing the current request. This is equivalent
842 * to <code>HttpServletRequest.getRequestURL</code> in Servlet 2.3.</p>
843 *
844 * @param request The servlet request we are processing
845 * @return URL representing the current request
846 * @throws MalformedURLException if a URL cannot be created
847 */
848 public static URL requestURL(HttpServletRequest request)
849 throws MalformedURLException {
850 StringBuffer url = requestToServerUriStringBuffer(request);
851
852 return (new URL(url.toString()));
853 }
854
855 /***
856 * <p>Return the URL representing the scheme, server, and port number of
857 * the current request. Server-relative URLs can be created by simply
858 * appending the server-relative path (starting with '/') to this.</p>
859 *
860 * @param request The servlet request we are processing
861 * @return URL representing the scheme, server, and port number of the
862 * current request
863 * @throws MalformedURLException if a URL cannot be created
864 */
865 public static URL serverURL(HttpServletRequest request)
866 throws MalformedURLException {
867 StringBuffer url = requestToServerStringBuffer(request);
868
869 return (new URL(url.toString()));
870 }
871
872 /***
873 * <p>Return the string representing the scheme, server, and port number
874 * of the current request. Server-relative URLs can be created by simply
875 * appending the server-relative path (starting with '/') to this.</p>
876 *
877 * @param request The servlet request we are processing
878 * @return URL representing the scheme, server, and port number of the
879 * current request
880 * @since Struts 1.2.0
881 */
882 public static StringBuffer requestToServerUriStringBuffer(
883 HttpServletRequest request) {
884 StringBuffer serverUri =
885 createServerUriStringBuffer(request.getScheme(),
886 request.getServerName(), request.getServerPort(),
887 request.getRequestURI());
888
889 return serverUri;
890 }
891
892 /***
893 * <p>Return <code>StringBuffer</code> representing the scheme, server,
894 * and port number of the current request. Server-relative URLs can be
895 * created by simply appending the server-relative path (starting with
896 * '/') to this.</p>
897 *
898 * @param request The servlet request we are processing
899 * @return URL representing the scheme, server, and port number of the
900 * current request
901 * @since Struts 1.2.0
902 */
903 public static StringBuffer requestToServerStringBuffer(
904 HttpServletRequest request) {
905 return createServerStringBuffer(request.getScheme(),
906 request.getServerName(), request.getServerPort());
907 }
908
909 /***
910 * <p>Return <code>StringBuffer</code> representing the scheme, server,
911 * and port number of the current request.</p>
912 *
913 * @param scheme The scheme name to use
914 * @param server The server name to use
915 * @param port The port value to use
916 * @return StringBuffer in the form scheme: server: port
917 * @since Struts 1.2.0
918 */
919 public static StringBuffer createServerStringBuffer(String scheme,
920 String server, int port) {
921 StringBuffer url = new StringBuffer();
922
923 if (port < 0) {
924 port = 80;
925 }
926
927 url.append(scheme);
928 url.append("://");
929 url.append(server);
930
931 if ((scheme.equals("http") && (port != 80))
932 || (scheme.equals("https") && (port != 443))) {
933 url.append(':');
934 url.append(port);
935 }
936
937 return url;
938 }
939
940 /***
941 * <p>Return <code>StringBuffer</code> representing the scheme, server,
942 * and port number of the current request.</p>
943 *
944 * @param scheme The scheme name to use
945 * @param server The server name to use
946 * @param port The port value to use
947 * @param uri The uri value to use
948 * @return StringBuffer in the form scheme: server: port
949 * @since Struts 1.2.0
950 */
951 public static StringBuffer createServerUriStringBuffer(String scheme,
952 String server, int port, String uri) {
953 StringBuffer serverUri = createServerStringBuffer(scheme, server, port);
954
955 serverUri.append(uri);
956
957 return serverUri;
958 }
959 }