1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.tiles.jsp.taglib;
22
23 import java.io.IOException;
24
25 import javax.servlet.jsp.PageContext;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.tiles.Attribute;
30 import org.apache.tiles.AttributeContext;
31 import org.apache.tiles.ListAttribute;
32 import org.apache.tiles.TilesContainer;
33 import org.apache.tiles.jsp.context.JspUtil;
34
35 /***
36 * <p>
37 * Abstracts class for all tags which render (an attribute, a template, or
38 * definition).
39 * </p>
40 * <p>
41 * Properly invokes the defined preparer and invokes the abstract render method
42 * upon completion.
43 * </p>
44 * This tag takes special care to ensure that the attribute context is reset to
45 * it's original state after the execution of the tag is complete. This ensures
46 * that all all included attributes in subsequent tiles are scoped properly and
47 * do not bleed outside their intended scope.
48 *
49 * @since 2.1.1
50 * @version $Rev: 749983 $ $Date: 2009-03-04 13:41:31 +0100 (mer, 04 mar 2009) $
51 */
52 public abstract class RenderTag extends TilesBodyTag implements
53 PutAttributeTagParent, PutListAttributeTagParent {
54
55 /***
56 * The log instance for this tag.
57 */
58 private final Log log = LogFactory.getLog(RenderTag.class);
59
60 /***
61 * The role to check. If the user is in the specified role, the tag is taken
62 * into account; otherwise, the tag is ignored (skipped).
63 *
64 * @since 2.1.1
65 */
66 protected String role;
67
68 /***
69 * The view preparer to use before the rendering.
70 *
71 * @since 2.1.1
72 */
73 protected String preparer;
74
75 /***
76 * This flag, if <code>true</code>, flushes the content before rendering.
77 *
78 * @since 2.1.1
79 */
80 protected boolean flush;
81
82 /***
83 * This flag, if <code>true</code>, ignores exception thrown by preparers
84 * and those caused by problems with definitions.
85 *
86 * @since 2.1.1
87 */
88 protected boolean ignore;
89
90 /***
91 * The Tiles container that can be used inside the tag.
92 *
93 * @since 2.1.1
94 */
95 protected TilesContainer container;
96
97 /***
98 * The attribute context to use to store and read attribute values.
99 *
100 * @since 2.1.1
101 */
102 protected AttributeContext attributeContext;
103
104 /***
105 * Returns the role to check. If the user is in the specified role, the tag is
106 * taken into account; otherwise, the tag is ignored (skipped).
107 *
108 * @return The role to check.
109 * @since 2.1.1
110 */
111 public String getRole() {
112 return role;
113 }
114
115 /***
116 * Sets the role to check. If the user is in the specified role, the tag is
117 * taken into account; otherwise, the tag is ignored (skipped).
118 *
119 * @param role The role to check.
120 * @since 2.1.1
121 */
122 public void setRole(String role) {
123 this.role = role;
124 }
125
126 /***
127 * Returns the preparer name.
128 *
129 * @return The preparer name.
130 * @since 2.1.1
131 */
132 public String getPreparer() {
133 return preparer;
134 }
135
136 /***
137 * Sets the preparer name.
138 *
139 * @param preparer The preparer name.
140 * @since 2.1.1
141 */
142 public void setPreparer(String preparer) {
143 this.preparer = preparer;
144 }
145
146 /***
147 * Returns the flush flag. If <code>true</code>, current page out stream
148 * is flushed before insertion.
149 *
150 * @return The flush flag.
151 * @since 2.1.1
152 */
153 public boolean isFlush() {
154 return flush;
155 }
156
157 /***
158 * Sets the flush flag. If <code>true</code>, current page out stream
159 * is flushed before insertion.
160 *
161 * @param flush The flush flag.
162 * @since 2.1.1
163 */
164 public void setFlush(boolean flush) {
165 this.flush = flush;
166 }
167
168 /***
169 * Returns the ignore flag. If it is set to true, and the attribute
170 * specified by the name does not exist, simply return without writing
171 * anything. The default value is false, which will cause a runtime
172 * exception to be thrown.
173 *
174 * @return The ignore flag.
175 * @since 2.1.1
176 */
177 public boolean isIgnore() {
178 return ignore;
179 }
180
181 /***
182 * Sets the ignore flag. If this attribute is set to true, and the attribute
183 * specified by the name does not exist, simply return without writing
184 * anything. The default value is false, which will cause a runtime
185 * exception to be thrown.
186 *
187 * @param ignore The ignore flag.
188 * @since 2.1.1
189 */
190 public void setIgnore(boolean ignore) {
191 this.ignore = ignore;
192 }
193
194 /*** {@inheritDoc} */
195 @Override
196 protected void reset() {
197 super.reset();
198 preparer = null;
199 flush = false;
200 ignore = false;
201 container = null;
202 attributeContext = null;
203 role = null;
204 }
205
206 /*** {@inheritDoc} */
207 public int doStartTag() throws TilesJspException {
208 container = JspUtil.getCurrentContainer(pageContext);
209 if (container != null) {
210 startContext(pageContext);
211 return EVAL_BODY_BUFFERED;
212 } else {
213 throw new TilesJspException("TilesContainer not initialized");
214 }
215 }
216
217 /*** {@inheritDoc} */
218 public int doEndTag() throws TilesJspException {
219 try {
220 render();
221 if (flush) {
222 pageContext.getOut().flush();
223 }
224
225 return EVAL_PAGE;
226 } catch (IOException io) {
227 String message = "IO Error executing tag: " + io.getMessage();
228 log.error(message, io);
229 throw new TilesJspException(message, io);
230 } finally {
231 endContext(pageContext);
232 }
233 }
234
235 /***
236 * Render the specified content.
237 *
238 * @throws TilesJspException if a jsp exception occurs.
239 * @throws IOException if an io exception occurs.
240 */
241 protected abstract void render() throws TilesJspException, IOException;
242
243 /***
244 * Starts the context when entering the tag.
245 *
246 * @param context The page context to use.
247 */
248 protected void startContext(PageContext context) {
249 if (container != null) {
250 attributeContext = container.startContext(pageContext);
251 }
252 }
253
254 /***
255 * Ends the context when exiting the tag.
256 *
257 * @param context The page context to use.
258 */
259 protected void endContext(PageContext context) {
260 if (attributeContext != null && container != null) {
261 container.endContext(pageContext);
262 }
263 }
264
265 /***
266 * <p>
267 * Process nested ≶put> tag.
268 * <p/>
269 * <p>
270 * Places the value of the nested tag within the
271 * {@link org.apache.tiles.AttributeContext}.It is the responsibility
272 * of the descendent to check security. Security will be managed by
273 * called tags.
274 * </p>
275 *
276 * @param nestedTag the put tag desciendent.
277 */
278 public void processNestedTag(PutAttributeTag nestedTag) {
279 Attribute attribute = new Attribute(
280 nestedTag.getValue(), null,
281 nestedTag.getRole(), nestedTag.getType());
282
283 attributeContext.putAttribute(nestedTag.getName(), attribute, nestedTag
284 .isCascade());
285 }
286
287 /*** {@inheritDoc} */
288 public void processNestedTag(PutListAttributeTag nestedTag) {
289 ListAttribute attribute = new ListAttribute(nestedTag.getAttributes());
290 attribute.setRole(nestedTag.getRole());
291 attribute.setInherit(nestedTag.getInherit());
292
293 attributeContext.putAttribute(nestedTag.getName(), attribute, nestedTag
294 .isCascade());
295 }
296 }