1 /*
2  * Copyright 2002-2010 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.springframework.web.servlet.tags;
18 
19 import javax.servlet.jsp.JspException;
20 import javax.servlet.jsp.JspTagException;
21 import javax.servlet.jsp.tagext.TagSupport;
22 import javax.servlet.jsp.tagext.TryCatchFinally;
23 
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 
27 import org.springframework.web.servlet.support.JspAwareRequestContext;
28 import org.springframework.web.servlet.support.RequestContext;
29 
30 /**
31  * Superclass for all tags that require a {@link RequestContext}.
32  *
33  * <p>The <code>RequestContext</code> instance provides easy access
34  * to current state like the
35  * {@link org.springframework.web.context.WebApplicationContext},
36  * the {@link java.util.Locale}, the
37  * {@link org.springframework.ui.context.Theme}, etc.
38  *
39  * <p>Mainly intended for
40  * {@link org.springframework.web.servlet.DispatcherServlet} requests;
41  * will use fallbacks when used outside <code>DispatcherServlet</code>.
42  *
43  * @author Rod Johnson
44  * @author Juergen Hoeller
45  * @see org.springframework.web.servlet.support.RequestContext
46  * @see org.springframework.web.servlet.DispatcherServlet
47  */
48 public abstract class RequestContextAwareTag extends TagSupport implements TryCatchFinally {
49 
50 	/**
51 	 * {@link javax.servlet.jsp.PageContext} attribute for the
52 	 * page-level {@link RequestContext} instance.
53 	 */
54 	public static final String REQUEST_CONTEXT_PAGE_ATTRIBUTE =
55 			"org.springframework.web.servlet.tags.REQUEST_CONTEXT";
56 
57 
58 	/** Logger available to subclasses */
59 	protected final Log logger = LogFactory.getLog(getClass());
60 
61 
62 	private RequestContext requestContext;
63 
64 
65 	/**
66 	 * Create and expose the current RequestContext.
67 	 * Delegates to {@link #doStartTagInternal()} for actual work.
68 	 * @see #REQUEST_CONTEXT_PAGE_ATTRIBUTE
69 	 * @see org.springframework.web.servlet.support.JspAwareRequestContext
70 	 */
71 	@Override
doStartTag()72 	public final int doStartTag() throws JspException {
73 		try {
74 			this.requestContext = (RequestContext) this.pageContext.getAttribute(REQUEST_CONTEXT_PAGE_ATTRIBUTE);
75 			if (this.requestContext == null) {
76 				this.requestContext = new JspAwareRequestContext(this.pageContext);
77 				this.pageContext.setAttribute(REQUEST_CONTEXT_PAGE_ATTRIBUTE, this.requestContext);
78 			}
79 			return doStartTagInternal();
80 		}
81 		catch (JspException ex) {
82 			logger.error(ex.getMessage(), ex);
83 			throw ex;
84 		}
85 		catch (RuntimeException ex) {
86 			logger.error(ex.getMessage(), ex);
87 			throw ex;
88 		}
89 		catch (Exception ex) {
90 			logger.error(ex.getMessage(), ex);
91 			throw new JspTagException(ex.getMessage());
92 		}
93 	}
94 
95 	/**
96 	 * Return the current RequestContext.
97 	 */
getRequestContext()98 	protected final RequestContext getRequestContext() {
99 		return this.requestContext;
100 	}
101 
102 	/**
103 	 * Called by doStartTag to perform the actual work.
104 	 * @return same as TagSupport.doStartTag
105 	 * @throws Exception any exception, any checked one other than
106 	 * a JspException gets wrapped in a JspException by doStartTag
107 	 * @see javax.servlet.jsp.tagext.TagSupport#doStartTag
108 	 */
doStartTagInternal()109 	protected abstract int doStartTagInternal() throws Exception;
110 
111 
doCatch(Throwable throwable)112 	public void doCatch(Throwable throwable) throws Throwable {
113 		throw throwable;
114 	}
115 
doFinally()116 	public void doFinally() {
117 		this.requestContext = null;
118 	}
119 
120 }
121