1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.struts.taglib;
22
23 import org.apache.commons.beanutils.PropertyUtils;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.struts.Globals;
27 import org.apache.struts.action.ActionErrors;
28 import org.apache.struts.action.ActionMessage;
29 import org.apache.struts.action.ActionMessages;
30 import org.apache.struts.action.ActionServlet;
31 import org.apache.struts.config.ForwardConfig;
32 import org.apache.struts.config.ModuleConfig;
33 import org.apache.struts.taglib.html.Constants;
34 import org.apache.struts.util.MessageResources;
35 import org.apache.struts.util.ModuleUtils;
36 import org.apache.struts.util.RequestUtils;
37 import org.apache.struts.util.ResponseUtils;
38
39 import javax.servlet.http.HttpServletRequest;
40 import javax.servlet.http.HttpServletResponse;
41 import javax.servlet.http.HttpSession;
42 import javax.servlet.jsp.JspException;
43 import javax.servlet.jsp.JspWriter;
44 import javax.servlet.jsp.PageContext;
45 import javax.servlet.jsp.tagext.BodyContent;
46
47 import java.io.IOException;
48
49 import java.lang.reflect.InvocationTargetException;
50
51 import java.net.MalformedURLException;
52
53 import java.util.HashMap;
54 import java.util.Iterator;
55 import java.util.Locale;
56 import java.util.Map;
57
58
59
60
61
62
63
64 public class TagUtils {
65
66
67
68
69 private static TagUtils instance = new TagUtils();
70
71
72
73
74 private static final Log log = LogFactory.getLog(TagUtils.class);
75
76
77
78
79
80 private static final MessageResources messages =
81 MessageResources.getMessageResources(
82 "org.apache.struts.taglib.LocalStrings");
83
84
85
86
87
88 private static final Map scopes = new HashMap();
89
90
91
92
93
94 static {
95 scopes.put("page", new Integer(PageContext.PAGE_SCOPE));
96 scopes.put("request", new Integer(PageContext.REQUEST_SCOPE));
97 scopes.put("session", new Integer(PageContext.SESSION_SCOPE));
98 scopes.put("application", new Integer(PageContext.APPLICATION_SCOPE));
99 }
100
101
102
103
104 protected TagUtils() {
105 super();
106 }
107
108
109
110
111 public static TagUtils getInstance() {
112 return instance;
113 }
114
115
116
117
118
119
120
121 public static void setInstance(TagUtils instance){
122 TagUtils.instance = instance;
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 public Map computeParameters(PageContext pageContext, String paramId,
152 String paramName, String paramProperty, String paramScope, String name,
153 String property, String scope, boolean transaction)
154 throws JspException {
155
156 if ((paramId == null) && (name == null) && !transaction) {
157 return (null);
158 }
159
160
161 Map map = null;
162
163 try {
164 if (name != null) {
165 map = (Map) getInstance().lookup(pageContext, name, property,
166 scope);
167 }
168
169
170
171
172
173
174 } catch (JspException e) {
175 saveException(pageContext, e);
176 throw e;
177 }
178
179
180 Map results = null;
181
182 if (map != null) {
183 results = new HashMap(map);
184 } else {
185 results = new HashMap();
186 }
187
188
189 if ((paramId != null) && (paramName != null)) {
190 Object paramValue = null;
191
192 try {
193 paramValue =
194 TagUtils.getInstance().lookup(pageContext, paramName,
195 paramProperty, paramScope);
196 } catch (JspException e) {
197 saveException(pageContext, e);
198 throw e;
199 }
200
201 if (paramValue != null) {
202 String paramString = null;
203
204 if (paramValue instanceof String) {
205 paramString = (String) paramValue;
206 } else {
207 paramString = paramValue.toString();
208 }
209
210 Object mapValue = results.get(paramId);
211
212 if (mapValue == null) {
213 results.put(paramId, paramString);
214 } else if (mapValue instanceof String[]) {
215 String[] oldValues = (String[]) mapValue;
216 String[] newValues = new String[oldValues.length + 1];
217
218 System.arraycopy(oldValues, 0, newValues, 0,
219 oldValues.length);
220 newValues[oldValues.length] = paramString;
221 results.put(paramId, newValues);
222 } else {
223 String[] newValues = new String[2];
224
225 newValues[0] = mapValue.toString();
226 newValues[1] = paramString;
227 results.put(paramId, newValues);
228 }
229 }
230 }
231
232
233 if (transaction) {
234 HttpSession session = pageContext.getSession();
235 String token = null;
236
237 if (session != null) {
238 token =
239 (String) session.getAttribute(Globals.TRANSACTION_TOKEN_KEY);
240 }
241
242 if (token != null) {
243 results.put(Constants.TOKEN_KEY, token);
244 }
245 }
246
247
248 return (results);
249 }
250
251 public String computeURL(PageContext pageContext, String forward,
252 String href, String page, String action, String module, Map params,
253 String anchor, boolean redirect)
254 throws MalformedURLException {
255 return this.computeURLWithCharEncoding(pageContext, forward, href,
256 page, action, module, params, anchor, redirect, false);
257 }
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281 public String computeURLWithCharEncoding(PageContext pageContext,
282 String forward, String href, String page, String action, String module,
283 Map params, String anchor, boolean redirect, boolean useLocalEncoding)
284 throws MalformedURLException {
285 return computeURLWithCharEncoding(pageContext, forward, href, page,
286 action, module, params, anchor, redirect, true, useLocalEncoding);
287 }
288
289 public String computeURL(PageContext pageContext, String forward,
290 String href, String page, String action, String module, Map params,
291 String anchor, boolean redirect, boolean encodeSeparator)
292 throws MalformedURLException {
293 return computeURLWithCharEncoding(pageContext, forward, href, page,
294 action, module, params, anchor, redirect, encodeSeparator, false);
295 }
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327 public String computeURLWithCharEncoding(PageContext pageContext,
328 String forward, String href, String page, String action, String module,
329 Map params, String anchor, boolean redirect, boolean encodeSeparator,
330 boolean useLocalEncoding)
331 throws MalformedURLException {
332 String charEncoding = "UTF-8";
333
334 if (useLocalEncoding) {
335 charEncoding = pageContext.getResponse().getCharacterEncoding();
336 }
337
338
339
340 int n = 0;
341
342 if (forward != null) {
343 n++;
344 }
345
346 if (href != null) {
347 n++;
348 }
349
350 if (page != null) {
351 n++;
352 }
353
354 if (action != null) {
355 n++;
356 }
357
358 if (n != 1) {
359 throw new MalformedURLException(messages.getMessage(
360 "computeURL.specifier"));
361 }
362
363
364 ModuleConfig moduleConfig = getModuleConfig(module, pageContext);
365
366
367 StringBuffer url = new StringBuffer();
368 HttpServletRequest request =
369 (HttpServletRequest) pageContext.getRequest();
370
371 if (forward != null) {
372 ForwardConfig forwardConfig =
373 moduleConfig.findForwardConfig(forward);
374
375 if (forwardConfig == null) {
376 throw new MalformedURLException(messages.getMessage(
377 "computeURL.forward", forward));
378 }
379
380
381
382
383
384
385 if (forwardConfig.getPath().startsWith("/")) {
386 url.append(request.getContextPath());
387 url.append(RequestUtils.forwardURL(request, forwardConfig,
388 moduleConfig));
389 } else {
390 url.append(forwardConfig.getPath());
391 }
392 } else if (href != null) {
393 url.append(href);
394 } else if (action != null) {
395 ActionServlet servlet = (ActionServlet) pageContext.getServletContext().getAttribute(Globals.ACTION_SERVLET_KEY);
396 String actionIdPath = RequestUtils.actionIdURL(action, moduleConfig, servlet);
397 if (actionIdPath != null) {
398 action = actionIdPath;
399 url.append(request.getContextPath());
400 url.append(actionIdPath);
401 } else {
402 url.append(instance.getActionMappingURL(action, module,
403 pageContext, false));
404 }
405 } else
406 {
407 url.append(request.getContextPath());
408 url.append(this.pageURL(request, page, moduleConfig));
409 }
410
411
412 if (anchor != null) {
413 String temp = url.toString();
414 int hash = temp.indexOf('#');
415
416 if (hash >= 0) {
417 url.setLength(hash);
418 }
419
420 url.append('#');
421 url.append(this.encodeURL(anchor, charEncoding));
422 }
423
424
425 if ((params != null) && (params.size() > 0)) {
426
427 String temp = url.toString();
428 int hash = temp.indexOf('#');
429
430 if (hash >= 0) {
431 anchor = temp.substring(hash + 1);
432 url.setLength(hash);
433 temp = url.toString();
434 } else {
435 anchor = null;
436 }
437
438
439 String separator = null;
440
441 if (redirect) {
442 separator = "&";
443 } else if (encodeSeparator) {
444 separator = "&";
445 } else {
446 separator = "&";
447 }
448
449
450 boolean question = temp.indexOf('?') >= 0;
451 Iterator keys = params.keySet().iterator();
452
453 while (keys.hasNext()) {
454 String key = (String) keys.next();
455 Object value = params.get(key);
456
457 if (value == null) {
458 if (!question) {
459 url.append('?');
460 question = true;
461 } else {
462 url.append(separator);
463 }
464
465 url.append(this.encodeURL(key, charEncoding));
466 url.append('=');
467 } else if (value instanceof String) {
468 if (!question) {
469 url.append('?');
470 question = true;
471 } else {
472 url.append(separator);
473 }
474
475 url.append(this.encodeURL(key, charEncoding));
476 url.append('=');
477 url.append(this.encodeURL((String) value, charEncoding));
478 } else if (value instanceof String[]) {
479 String[] values = (String[]) value;
480
481 for (int i = 0; i < values.length; i++) {
482 if (!question) {
483 url.append('?');
484 question = true;
485 } else {
486 url.append(separator);
487 }
488
489 url.append(this.encodeURL(key, charEncoding));
490 url.append('=');
491 url.append(this.encodeURL(values[i], charEncoding));
492 }
493 } else
494 {
495 if (!question) {
496 url.append('?');
497 question = true;
498 } else {
499 url.append(separator);
500 }
501
502 url.append(this.encodeURL(key, charEncoding));
503 url.append('=');
504 url.append(this.encodeURL(value.toString(), charEncoding));
505 }
506 }
507
508
509 if (anchor != null) {
510 url.append('#');
511 url.append(this.encodeURL(anchor, charEncoding));
512 }
513 }
514
515
516
517 if ((href == null) && (pageContext.getSession() != null)) {
518 HttpServletResponse response =
519 (HttpServletResponse) pageContext.getResponse();
520
521 if (redirect) {
522 return (response.encodeRedirectURL(url.toString()));
523 }
524
525 return (response.encodeURL(url.toString()));
526 }
527
528 return (url.toString());
529 }
530
531
532
533
534
535
536
537 public String encodeURL(String url) {
538 return encodeURL(url, "UTF-8");
539 }
540
541
542
543
544
545
546
547
548
549
550
551 public String encodeURL(String url, String enc) {
552 return ResponseUtils.encodeURL(url, enc);
553 }
554
555
556
557
558
559
560
561
562 public String filter(String value) {
563 return ResponseUtils.filter(value);
564 }
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581 public String getActionMappingName(String action) {
582 String value = action;
583 int question = action.indexOf("?");
584
585 if (question >= 0) {
586 value = value.substring(0, question);
587 }
588
589 int pound = value.indexOf("#");
590
591 if (pound >= 0) {
592 value = value.substring(0, pound);
593 }
594
595 int slash = value.lastIndexOf("/");
596 int period = value.lastIndexOf(".");
597
598 if ((period >= 0) && (period > slash)) {
599 value = value.substring(0, period);
600 }
601
602 return value.startsWith("/") ? value : ("/" + value);
603 }
604
605
606
607
608 public String getActionMappingURL(String action, PageContext pageContext) {
609 return getActionMappingURL(action, null, pageContext, false);
610 }
611
612
613
614
615 public String getActionMappingURL(String action, String module,
616 PageContext pageContext, boolean contextRelative) {
617 HttpServletRequest request =
618 (HttpServletRequest) pageContext.getRequest();
619
620 String contextPath = request.getContextPath();
621 StringBuffer value = new StringBuffer();
622
623
624
625
626 if (contextPath.length() > 1) {
627 value.append(contextPath);
628 }
629
630 ModuleConfig moduleConfig = getModuleConfig(module, pageContext);
631
632 if ((moduleConfig != null) && (!contextRelative)) {
633 value.append(moduleConfig.getPrefix());
634 }
635
636
637 String servletMapping =
638 (String) pageContext.getAttribute(Globals.SERVLET_KEY,
639 PageContext.APPLICATION_SCOPE);
640
641 if (servletMapping != null) {
642 String queryString = null;
643 int question = action.indexOf("?");
644
645 if (question >= 0) {
646 queryString = action.substring(question);
647 }
648
649 String actionMapping = getActionMappingName(action);
650
651 if (servletMapping.startsWith("*.")) {
652 value.append(actionMapping);
653 value.append(servletMapping.substring(1));
654 } else if (servletMapping.endsWith("/*")) {
655 value.append(servletMapping.substring(0,
656 servletMapping.length() - 2));
657 value.append(actionMapping);
658 } else if (servletMapping.equals("/")) {
659 value.append(actionMapping);
660 }
661
662 if (queryString != null) {
663 value.append(queryString);
664 }
665 }
666
667
668 else {
669 if (!action.startsWith("/")) {
670 value.append("/");
671 }
672
673 value.append(action);
674 }
675
676 return value.toString();
677 }
678
679
680
681
682
683
684
685
686
687
688 public ActionMessages getActionMessages(PageContext pageContext,
689 String paramName) throws JspException {
690 ActionMessages am = new ActionMessages();
691
692 Object value = pageContext.findAttribute(paramName);
693
694 if (value != null) {
695 try {
696 if (value instanceof String) {
697 am.add(ActionMessages.GLOBAL_MESSAGE,
698 new ActionMessage((String) value));
699 } else if (value instanceof String[]) {
700 String[] keys = (String[]) value;
701
702 for (int i = 0; i < keys.length; i++) {
703 am.add(ActionMessages.GLOBAL_MESSAGE,
704 new ActionMessage(keys[i]));
705 }
706 } else if (value instanceof ActionErrors) {
707 ActionMessages m = (ActionMessages) value;
708
709 am.add(m);
710 } else if (value instanceof ActionMessages) {
711 am = (ActionMessages) value;
712 } else {
713 throw new JspException(messages.getMessage(
714 "actionMessages.errors", value.getClass().getName()));
715 }
716 } catch (JspException e) {
717 throw e;
718 } catch (Exception e) {
719 log.warn("Unable to retieve ActionMessage for paramName : "
720 + paramName, e);
721 }
722 }
723
724 return am;
725 }
726
727
728
729
730
731
732
733
734 public ModuleConfig getModuleConfig(PageContext pageContext) {
735 return getModuleConfig(null, pageContext);
736 }
737
738
739
740
741
742
743
744
745
746
747 public ModuleConfig getModuleConfig(String module, PageContext pageContext) {
748 ModuleConfig config =
749 ModuleUtils.getInstance().getModuleConfig(module,
750 (HttpServletRequest) pageContext.getRequest(),
751 pageContext.getServletContext());
752
753
754 if (config == null) {
755 throw new NullPointerException("Module '" + module + "' not found.");
756 }
757
758 return config;
759 }
760
761
762
763
764
765
766
767
768
769
770 public int getScope(String scopeName)
771 throws JspException {
772 Integer scope = (Integer) scopes.get(scopeName.toLowerCase());
773
774 if (scope == null) {
775 throw new JspException(messages.getMessage("lookup.scope", scope));
776 }
777
778 return scope.intValue();
779 }
780
781
782
783
784
785
786
787
788
789
790
791 public Locale getUserLocale(PageContext pageContext, String locale) {
792 return RequestUtils.getUserLocale((HttpServletRequest) pageContext
793 .getRequest(), locale);
794 }
795
796
797
798
799 public boolean isXhtml(PageContext pageContext) {
800 String xhtml =
801 (String) pageContext.getAttribute(Globals.XHTML_KEY,
802 PageContext.PAGE_SCOPE);
803
804 return "true".equalsIgnoreCase(xhtml);
805 }
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821 public Object lookup(PageContext pageContext, String name, String scopeName)
822 throws JspException {
823 if (scopeName == null) {
824 return pageContext.findAttribute(name);
825 }
826
827 try {
828 return pageContext.getAttribute(name, instance.getScope(scopeName));
829 } catch (JspException e) {
830 saveException(pageContext, e);
831 throw e;
832 }
833 }
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855 public Object lookup(PageContext pageContext, String name, String property,
856 String scope) throws JspException {
857
858 Object bean = lookup(pageContext, name, scope);
859
860 if (bean == null) {
861 JspException e = null;
862
863 if (scope == null) {
864 e = new JspException(messages.getMessage("lookup.bean.any", name));
865 } else {
866 e = new JspException(messages.getMessage("lookup.bean", name,
867 scope));
868 }
869
870 saveException(pageContext, e);
871 throw e;
872 }
873
874 if (property == null) {
875 return bean;
876 }
877
878
879 try {
880 return PropertyUtils.getProperty(bean, property);
881 } catch (IllegalAccessException e) {
882 saveException(pageContext, e);
883 throw new JspException(messages.getMessage("lookup.access",
884 property, name));
885 } catch (IllegalArgumentException e) {
886 saveException(pageContext, e);
887 throw new JspException(messages.getMessage("lookup.argument",
888 property, name));
889 } catch (InvocationTargetException e) {
890 Throwable t = e.getTargetException();
891
892 if (t == null) {
893 t = e;
894 }
895
896 saveException(pageContext, t);
897 throw new JspException(messages.getMessage("lookup.target",
898 property, name));
899 } catch (NoSuchMethodException e) {
900 saveException(pageContext, e);
901
902 String beanName = name;
903
904
905
906
907 if (Constants.BEAN_KEY.equals(name)) {
908 Object obj = pageContext.findAttribute(Constants.BEAN_KEY);
909
910 if (obj != null) {
911 beanName = obj.getClass().getName();
912 }
913 }
914
915 throw new JspException(messages.getMessage("lookup.method",
916 property, beanName));
917 }
918 }
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933 public String message(PageContext pageContext, String bundle,
934 String locale, String key)
935 throws JspException {
936 return message(pageContext, bundle, locale, key, null);
937 }
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953 public String message(PageContext pageContext, String bundle,
954 String locale, String key, Object[] args)
955 throws JspException {
956 MessageResources resources =
957 retrieveMessageResources(pageContext, bundle, false);
958
959 Locale userLocale = getUserLocale(pageContext, locale);
960 String message = null;
961
962 if (args == null) {
963 message = resources.getMessage(userLocale, key);
964 } else {
965 message = resources.getMessage(userLocale, key, args);
966 }
967
968 if ((message == null) && log.isDebugEnabled()) {
969
970 log.debug(resources.getMessage("message.resources", key, bundle,
971 locale));
972 }
973
974 return message;
975 }
976
977
978
979
980
981
982
983
984
985
986
987
988
989 public String pageURL(HttpServletRequest request, String page,
990 ModuleConfig moduleConfig) {
991 StringBuffer sb = new StringBuffer();
992 String pagePattern =
993 moduleConfig.getControllerConfig().getPagePattern();
994
995 if (pagePattern == null) {
996 sb.append(moduleConfig.getPrefix());
997 sb.append(page);
998 } else {
999 boolean dollar = false;
1000
1001 for (int i = 0; i < pagePattern.length(); i++) {
1002 char ch = pagePattern.charAt(i);
1003
1004 if (dollar) {
1005 switch (ch) {
1006 case 'M':
1007 sb.append(moduleConfig.getPrefix());
1008
1009 break;
1010
1011 case 'P':
1012 sb.append(page);
1013
1014 break;
1015
1016 case '$':
1017 sb.append('$');
1018
1019 break;
1020
1021 default:
1022 ;
1023 }
1024
1025 dollar = false;
1026
1027 continue;
1028 } else if (ch == '$') {
1029 dollar = true;
1030 } else {
1031 sb.append(ch);
1032 }
1033 }
1034 }
1035
1036 return sb.toString();
1037 }
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052 public boolean present(PageContext pageContext, String bundle,
1053 String locale, String key)
1054 throws JspException {
1055 MessageResources resources =
1056 retrieveMessageResources(pageContext, bundle, true);
1057
1058 Locale userLocale = getUserLocale(pageContext, locale);
1059
1060 return resources.isPresent(userLocale, key);
1061 }
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076 public MessageResources retrieveMessageResources(PageContext pageContext,
1077 String bundle, boolean checkPageScope)
1078 throws JspException {
1079 MessageResources resources = null;
1080
1081 if (bundle == null) {
1082 bundle = Globals.MESSAGES_KEY;
1083 }
1084
1085 if (checkPageScope) {
1086 resources =
1087 (MessageResources) pageContext.getAttribute(bundle,
1088 PageContext.PAGE_SCOPE);
1089 }
1090
1091 if (resources == null) {
1092 resources =
1093 (MessageResources) pageContext.getAttribute(bundle,
1094 PageContext.REQUEST_SCOPE);
1095 }
1096
1097 if (resources == null) {
1098 ModuleConfig moduleConfig = getModuleConfig(pageContext);
1099
1100 resources =
1101 (MessageResources) pageContext.getAttribute(bundle
1102 + moduleConfig.getPrefix(), PageContext.APPLICATION_SCOPE);
1103 }
1104
1105 if (resources == null) {
1106 resources =
1107 (MessageResources) pageContext.getAttribute(bundle,
1108 PageContext.APPLICATION_SCOPE);
1109 }
1110
1111 if (resources == null) {
1112 JspException e =
1113 new JspException(messages.getMessage("message.bundle", bundle));
1114
1115 saveException(pageContext, e);
1116 throw e;
1117 }
1118
1119 return resources;
1120 }
1121
1122
1123
1124
1125
1126
1127
1128 public void saveException(PageContext pageContext, Throwable exception) {
1129 pageContext.setAttribute(Globals.EXCEPTION_KEY, exception,
1130 PageContext.REQUEST_SCOPE);
1131 }
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144 public void write(PageContext pageContext, String text)
1145 throws JspException {
1146 JspWriter writer = pageContext.getOut();
1147
1148 try {
1149 writer.print(text);
1150 } catch (IOException e) {
1151 saveException(pageContext, e);
1152 throw new JspException(messages.getMessage("write.io", e.toString()));
1153 }
1154 }
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164 public void writePrevious(PageContext pageContext, String text)
1165 throws JspException {
1166 JspWriter writer = pageContext.getOut();
1167
1168 if (writer instanceof BodyContent) {
1169 writer = ((BodyContent) writer).getEnclosingWriter();
1170 }
1171
1172 try {
1173 writer.print(text);
1174 } catch (IOException e) {
1175 saveException(pageContext, e);
1176 throw new JspException(messages.getMessage("write.io", e.toString()));
1177 }
1178 }
1179 }