1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.struts.tiles.taglib;
20
21 import java.lang.reflect.InvocationTargetException;
22
23 import javax.servlet.jsp.JspException;
24 import javax.servlet.jsp.tagext.BodyTagSupport;
25
26 import org.apache.commons.beanutils.PropertyUtils;
27 import org.apache.struts.tiles.taglib.util.TagUtils;
28 import org.apache.struts.tiles.AttributeDefinition;
29 import org.apache.struts.tiles.DefinitionNameAttribute;
30 import org.apache.struts.tiles.DirectStringAttribute;
31 import org.apache.struts.tiles.PathAttribute;
32
33 /***
34 * Put an attribute in enclosing attribute container tag.
35 * Enclosing attribute container tag can be : <insert> or <definition>.
36 * Exception is thrown if no appropriate tag can be found.
37 * Put tag can have following atributes :
38 * <li>
39 * <ul>name : Name of the attribute</ul>
40 * <ul>value | content : value to put as attribute</ul>
41 * <ul>type : value type. Only valid if value is a String and is set by
42 * value="something" or by a bean.
43 * Possible type are : string (value is used as direct string),
44 * page | template (value is used as a page url to insert),
45 * definition (value is used as a definition name to insert)</ul>
46 * <ul>direct : Specify if value is to be used as a direct string or as a
47 * page url to insert. This is another way to specify the type. It only apply
48 * if value is set as a string, and type is not present.</ul>
49 * <ul>beanName : Name of a bean used for setting value. Only valid if value is not set.
50 * If property is specified, value come from bean's property. Otherwise, bean
51 * itself is used for value.</ul>
52 * <ul>beanProperty : Name of the property used for retrieving value.</ul>
53 * <ul>beanScope : Scope containing bean. </ul>
54 * <ul>role : Role to check when 'insert' will be called. If enclosing tag is
55 * <insert>, role is checked immediately. If enclosing tag is
56 * <definition>, role will be checked when this definition will be
57 * inserted.</ul>
58 * </li>
59 * Value can also come from tag body. Tag body is taken into account only if
60 * value is not set by one of the tag attributes. In this case Attribute type is
61 * "string", unless tag body define another type.
62 */
63 public class PutTag extends BodyTagSupport implements ComponentConstants {
64
65
66
67 /***
68 * Name of attribute to put in component context.
69 */
70 protected String attributeName = null;
71
72 /***
73 * Associated attribute value.
74 */
75 private Object value = null;
76
77 /***
78 * JSP Template compatibility.
79 */
80 private String direct = null;
81
82 /***
83 * Requested type for the value.
84 */
85 private String valueType = null;
86
87 /***
88 * Bean name attribute.
89 */
90 private String beanName = null;
91
92 /***
93 * Bean property attribute.
94 */
95 private String beanProperty = null;
96
97 /***
98 * Bean scope attribute.
99 */
100 private String beanScope = null;
101
102 /***
103 * Role attribute.
104 */
105 private String role = null;
106
107
108
109 /***
110 * Cached real value computed from tag attributes.
111 */
112 protected Object realValue = null;
113
114 /***
115 * The body content of this tag.
116 */
117 protected String body = null;
118
119 /***
120 * Default constructor.
121 */
122 public PutTag() {
123 super();
124 }
125
126 /***
127 * Release all allocated resources.
128 */
129 public void release() {
130
131 super.release();
132
133 attributeName = null;
134 valueType = null;
135 direct = null;
136 value = null;
137 beanName = null;
138 beanProperty = null;
139 beanScope = null;
140 role = null;
141 body = null;
142 }
143
144 /***
145 * Release internal properties.
146 */
147 protected void releaseInternal() {
148 realValue = null;
149 }
150
151 /***
152 * Set name.
153 */
154 public void setName(String value) {
155 this.attributeName = value;
156 }
157
158 /***
159 * Get name.
160 */
161 public String getName() {
162 return attributeName;
163 }
164
165 /***
166 * Set value.
167 * Method added to satisfy Tomcat (bug ?).
168 */
169 public void setValue(String value) {
170 this.value = value;
171 }
172
173 /***
174 * Get value.
175 * Method added to satisfy Tomcat (bug ?).
176 */
177 public String getValue() {
178 return (String) this.value;
179 }
180
181 /***
182 * Set value.
183 */
184 public void setValue(Object value) {
185 this.value = value;
186 }
187
188 /***
189 * Set property value as an object.
190 * Added because some web containers react badly to value as <code>Object</code>.
191 */
192 public void setObjectValue(Object value) {
193 this.value = value;
194 }
195
196 /***
197 * Set content.
198 * Method added to satisfy Tomcat (bug ?).
199 */
200 public void setContent(String value) {
201 this.value = value;
202 }
203
204 /***
205 * Get content.
206 * Method added to satisfy Tomcat (bug ?).
207 */
208 public String getContent() {
209 return (String) value;
210 }
211
212 /***
213 * Set content.
214 */
215 public void setContent(Object value) {
216 this.value = value;
217 }
218
219 /***
220 * Set direct.
221 * Method added for compatibility with JSP1.1.
222 */
223 public void setDirect(String isDirect) {
224 this.direct = isDirect;
225 }
226
227 /***
228 * Set type.
229 */
230 public void setType(String value) {
231 this.valueType = value;
232 }
233
234 /***
235 * Get type.
236 */
237 public String getType() {
238 return this.valueType;
239 }
240
241 /***
242 * Set bean name.
243 */
244 public void setBeanName(String value) {
245 this.beanName = value;
246 }
247
248 /***
249 * Get bean name.
250 */
251 public String getBeanName() {
252 return beanName;
253 }
254
255 /***
256 * Set bean property.
257 */
258 public void setBeanProperty(String value) {
259 this.beanProperty = value;
260 }
261
262 /***
263 * Get bean property.
264 */
265 public String getBeanProperty() {
266 return beanProperty;
267 }
268
269 /***
270 * Set bean scope.
271 */
272 public void setBeanScope(String value) {
273 this.beanScope = value;
274 }
275
276 /***
277 * Get bean scope.
278 */
279 public String getBeanScope() {
280 return beanScope;
281 }
282
283 /***
284 * Set role attribute.
285 * @param role The role the user must be in to store content.
286 */
287 public void setRole(String role) {
288 this.role = role;
289 }
290
291 /***
292 * Get role attribute
293 * @return The role defined in the tag or <code>null</code>.
294 */
295 public String getRole() {
296 return role;
297 }
298
299 /***
300 * Get real value according to tag attribute.
301 * Real value is the value computed after attribute processing.
302 * @return Real value.
303 * @throws JspException If something goes wrong while getting value from bean.
304 */
305 public Object getRealValue() throws JspException {
306 if (realValue == null) {
307 computeRealValue();
308 }
309
310 return realValue;
311 }
312
313 /***
314 * Compute real value according to tag attributes.
315 * @throws JspException If something goes wrong while getting value from bean.
316 */
317 protected void computeRealValue() throws JspException {
318
319 realValue = value;
320
321
322 if (value == null && beanName == null) {
323
324 if (body != null) {
325 realValue = body;
326 } else {
327 realValue = "";
328 }
329 }
330
331
332 if (realValue == null && beanName != null) {
333 getRealValueFromBean();
334 return;
335 }
336
337
338
339
340
341 if (valueType == null && direct != null) {
342 if (Boolean.valueOf(direct).booleanValue() == true) {
343 valueType = "string";
344 } else {
345 valueType = "page";
346 }
347 }
348
349 if (realValue != null
350 && valueType != null
351 && !(value instanceof AttributeDefinition)) {
352
353 String strValue = realValue.toString();
354 if (valueType.equalsIgnoreCase("string")) {
355 realValue = new DirectStringAttribute(strValue);
356
357 } else if (valueType.equalsIgnoreCase("page")) {
358 realValue = new PathAttribute(strValue);
359
360 } else if (valueType.equalsIgnoreCase("template")) {
361 realValue = new PathAttribute(strValue);
362
363 } else if (valueType.equalsIgnoreCase("instance")) {
364 realValue = new DefinitionNameAttribute(strValue);
365
366 } else if (valueType.equalsIgnoreCase("definition")) {
367 realValue = new DefinitionNameAttribute(strValue);
368
369 } else {
370 throw new JspException(
371 "Warning - Tag put : Bad type '" + valueType + "'.");
372 }
373 }
374
375 }
376
377 /***
378 * Extract real value from specified bean.
379 * @throws JspException If something goes wrong while getting value from bean.
380 */
381 protected void getRealValueFromBean() throws JspException {
382 try {
383 Object bean = TagUtils.retrieveBean(beanName, beanScope, pageContext);
384 if (bean != null && beanProperty != null) {
385 realValue = PropertyUtils.getProperty(bean, beanProperty);
386 } else {
387 realValue = bean;
388 }
389
390 } catch (NoSuchMethodException ex) {
391 throw new JspException(
392 "Error - component.PutAttributeTag : Error while retrieving value from bean '"
393 + beanName
394 + "' with property '"
395 + beanProperty
396 + "' in scope '"
397 + beanScope
398 + "'. (exception : "
399 + ex.getMessage(), ex);
400
401 } catch (InvocationTargetException ex) {
402 throw new JspException(
403 "Error - component.PutAttributeTag : Error while retrieving value from bean '"
404 + beanName
405 + "' with property '"
406 + beanProperty
407 + "' in scope '"
408 + beanScope
409 + "'. (exception : "
410 + ex.getMessage(), ex);
411
412 } catch (IllegalAccessException ex) {
413 throw new JspException(
414 "Error - component.PutAttributeTag : Error while retrieving value from bean '"
415 + beanName
416 + "' with property '"
417 + beanProperty
418 + "' in scope '"
419 + beanScope
420 + "'. (exception : "
421 + ex.getMessage(), ex);
422 }
423 }
424
425 /***
426 * Do start tag.
427 */
428 public int doStartTag() throws JspException {
429
430
431 body = null;
432
433
434 if (value == null && beanName == null) {
435 return EVAL_BODY_TAG;
436 }
437
438
439 return SKIP_BODY;
440 }
441
442 /***
443 * Save the body content of this tag (if any)
444 *
445 * @exception JspException if a JSP exception has occurred
446 */
447 public int doAfterBody() throws JspException {
448
449 if (bodyContent != null) {
450 body = bodyContent.getString();
451 }
452 return (SKIP_BODY);
453
454 }
455
456 /***
457 * Do end tag.
458 */
459 public int doEndTag() throws JspException {
460
461 callParent();
462
463
464 releaseInternal();
465
466 return EVAL_PAGE;
467 }
468
469 /***
470 * Find parent tag which must implement AttributeContainer.
471 * @throws JspException If we can't find an appropriate enclosing tag.
472 */
473 protected void callParent() throws JspException {
474
475 PutTagParent enclosingParent = findEnclosingPutTagParent();
476 enclosingParent.processNestedTag(this);
477 }
478
479 /***
480 * Find parent tag which must implement AttributeContainer.
481 * @throws JspException If we can't find an appropriate enclosing tag.
482 */
483 protected PutTagParent findEnclosingPutTagParent() throws JspException {
484 try {
485 PutTagParent parent =
486 (PutTagParent) findAncestorWithClass(this, PutTagParent.class);
487
488 if (parent == null) {
489 throw new JspException("Error - tag put : enclosing tag doesn't accept 'put' tag.");
490 }
491
492 return parent;
493
494 } catch (ClassCastException ex) {
495 throw new JspException("Error - tag put : enclosing tag doesn't accept 'put' tag.", ex);
496 }
497 }
498
499 }