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.html;
22
23 import org.apache.commons.beanutils.BeanUtils;
24 import org.apache.struts.taglib.TagUtils;
25 import org.apache.struts.util.MessageResources;
26
27 import javax.servlet.jsp.JspException;
28
29 import java.lang.reflect.InvocationTargetException;
30
31 /**
32 * Custom tag that represents an HTML select element, associated with a bean
33 * property specified by our attributes. This tag must be nested inside a
34 * form tag.
35 *
36 * @version $Rev: 471754 $ $Date: 2004-10-16 12:38:42 -0400 (Sat, 16 Oct 2004)
37 * $
38 */
39 public class SelectTag extends BaseHandlerTag {
40 /**
41 * The message resources for this package.
42 */
43 protected static MessageResources messages =
44 MessageResources.getMessageResources(Constants.Package
45 + ".LocalStrings");
46
47
48
49 /**
50 * The actual values we will match against, calculated in doStartTag().
51 */
52 protected String[] match = null;
53
54 /**
55 * Should multiple selections be allowed. Any non-null value will trigger
56 * rendering this.
57 */
58 protected String multiple = null;
59
60 /**
61 * The name of the bean containing our underlying property.
62 */
63 protected String name = Constants.BEAN_KEY;
64
65 /**
66 * The property name we are associated with.
67 */
68 protected String property = null;
69
70 /**
71 * The saved body content of this tag.
72 */
73 protected String saveBody = null;
74
75 /**
76 * How many available options should be displayed when this element is
77 * rendered?
78 */
79 protected String size = null;
80
81 /**
82 * The value to compare with for marking an option selected.
83 */
84 protected String value = null;
85
86 public String getMultiple() {
87 return (this.multiple);
88 }
89
90 public void setMultiple(String multiple) {
91 this.multiple = multiple;
92 }
93
94 public String getName() {
95 return (this.name);
96 }
97
98 public void setName(String name) {
99 this.name = name;
100 }
101
102 public String getSize() {
103 return (this.size);
104 }
105
106 public void setSize(String size) {
107 this.size = size;
108 }
109
110
111
112 /**
113 * Does the specified value match one of those we are looking for?
114 *
115 * @param value Value to be compared.
116 */
117 public boolean isMatched(String value) {
118 if ((this.match == null) || (value == null)) {
119 return false;
120 }
121
122 for (int i = 0; i < this.match.length; i++) {
123 if (value.equals(this.match[i])) {
124 return true;
125 }
126 }
127
128 return false;
129 }
130
131 /**
132 * Return the property name.
133 */
134 public String getProperty() {
135 return (this.property);
136 }
137
138 /**
139 * Set the property name.
140 *
141 * @param property The new property name
142 */
143 public void setProperty(String property) {
144 this.property = property;
145 }
146
147 /**
148 * Return the comparison value.
149 */
150 public String getValue() {
151 return (this.value);
152 }
153
154 /**
155 * Set the comparison value.
156 *
157 * @param value The new comparison value
158 */
159 public void setValue(String value) {
160 this.value = value;
161 }
162
163
164
165 /**
166 * Render the beginning of this select tag. <p> Support for indexed
167 * property since Struts 1.1
168 *
169 * @throws JspException if a JSP exception has occurred
170 */
171 public int doStartTag() throws JspException {
172 TagUtils.getInstance().write(pageContext, renderSelectStartElement());
173
174
175 pageContext.setAttribute(Constants.SELECT_KEY, this);
176
177 this.calculateMatchValues();
178
179 return (EVAL_BODY_TAG);
180 }
181
182 /**
183 * Create an appropriate select start element based on our parameters.
184 *
185 * @throws JspException
186 * @since Struts 1.1
187 */
188 protected String renderSelectStartElement()
189 throws JspException {
190 StringBuffer results = new StringBuffer("<select");
191
192 prepareAttribute(results, "name", prepareName());
193 prepareAttribute(results, "accesskey", getAccesskey());
194
195 if (multiple != null) {
196 results.append(" multiple=\"multiple\"");
197 }
198
199 prepareAttribute(results, "size", getSize());
200 prepareAttribute(results, "tabindex", getTabindex());
201 results.append(prepareEventHandlers());
202 results.append(prepareStyles());
203 prepareOtherAttributes(results);
204 results.append(">");
205
206 return results.toString();
207 }
208
209 /**
210 * Calculate the match values we will actually be using.
211 *
212 * @throws JspException
213 */
214 private void calculateMatchValues()
215 throws JspException {
216 if (this.value != null) {
217 this.match = new String[1];
218 this.match[0] = this.value;
219 } else {
220 Object bean =
221 TagUtils.getInstance().lookup(pageContext, name, null);
222
223 if (bean == null) {
224 JspException e =
225 new JspException(messages.getMessage("getter.bean", name));
226
227 TagUtils.getInstance().saveException(pageContext, e);
228 throw e;
229 }
230
231 try {
232 this.match = BeanUtils.getArrayProperty(bean, property);
233
234 if (this.match == null) {
235 this.match = new String[0];
236 }
237 } catch (IllegalAccessException e) {
238 TagUtils.getInstance().saveException(pageContext, e);
239 throw new JspException(messages.getMessage("getter.access",
240 property, name));
241 } catch (InvocationTargetException e) {
242 Throwable t = e.getTargetException();
243
244 TagUtils.getInstance().saveException(pageContext, t);
245 throw new JspException(messages.getMessage("getter.result",
246 property, t.toString()));
247 } catch (NoSuchMethodException e) {
248 TagUtils.getInstance().saveException(pageContext, e);
249 throw new JspException(messages.getMessage("getter.method",
250 property, name));
251 }
252 }
253 }
254
255 /**
256 * Save any body content of this tag, which will generally be the
257 * option(s) representing the values displayed to the user.
258 *
259 * @throws JspException if a JSP exception has occurred
260 */
261 public int doAfterBody() throws JspException {
262 if (bodyContent != null) {
263 String value = bodyContent.getString();
264
265 if (value == null) {
266 value = "";
267 }
268
269 this.saveBody = value.trim();
270 }
271
272 return (SKIP_BODY);
273 }
274
275 /**
276 * Render the end of this form.
277 *
278 * @throws JspException if a JSP exception has occurred
279 */
280 public int doEndTag() throws JspException {
281
282 pageContext.removeAttribute(Constants.SELECT_KEY);
283
284
285 StringBuffer results = new StringBuffer();
286
287 if (saveBody != null) {
288 results.append(saveBody);
289 saveBody = null;
290 }
291
292 results.append("</select>");
293
294 TagUtils.getInstance().write(pageContext, results.toString());
295
296 return (EVAL_PAGE);
297 }
298
299 /**
300 * Prepare the name element
301 *
302 * @return The element name.
303 */
304 protected String prepareName()
305 throws JspException {
306 if (property == null) {
307 return null;
308 }
309
310
311 if (indexed) {
312 StringBuffer results = new StringBuffer();
313
314 prepareIndex(results, name);
315 results.append(property);
316
317 return results.toString();
318 }
319
320 return property;
321 }
322
323 /**
324 * Release any acquired resources.
325 */
326 public void release() {
327 super.release();
328 match = null;
329 multiple = null;
330 name = Constants.BEAN_KEY;
331 property = null;
332 saveBody = null;
333 size = null;
334 value = null;
335 }
336 }