001/*
002 * Copyright 2002-2012 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.web.servlet.tags;
018
019import javax.servlet.jsp.JspException;
020import javax.servlet.jsp.JspTagException;
021import javax.servlet.jsp.tagext.TagSupport;
022import javax.servlet.jsp.tagext.TryCatchFinally;
023
024import org.apache.commons.logging.Log;
025import org.apache.commons.logging.LogFactory;
026
027import org.springframework.web.servlet.support.JspAwareRequestContext;
028import org.springframework.web.servlet.support.RequestContext;
029
030/**
031 * Superclass for all tags that require a {@link RequestContext}.
032 *
033 * <p>The {@code RequestContext} instance provides easy access
034 * to current state like the
035 * {@link org.springframework.web.context.WebApplicationContext},
036 * the {@link java.util.Locale}, the
037 * {@link org.springframework.ui.context.Theme}, etc.
038 *
039 * <p>Mainly intended for
040 * {@link org.springframework.web.servlet.DispatcherServlet} requests;
041 * will use fallbacks when used outside {@code DispatcherServlet}.
042 *
043 * @author Rod Johnson
044 * @author Juergen Hoeller
045 * @see org.springframework.web.servlet.support.RequestContext
046 * @see org.springframework.web.servlet.DispatcherServlet
047 */
048@SuppressWarnings("serial")
049public abstract class RequestContextAwareTag extends TagSupport implements TryCatchFinally {
050
051        /**
052         * {@link javax.servlet.jsp.PageContext} attribute for the
053         * page-level {@link RequestContext} instance.
054         */
055        public static final String REQUEST_CONTEXT_PAGE_ATTRIBUTE =
056                        "org.springframework.web.servlet.tags.REQUEST_CONTEXT";
057
058
059        /** Logger available to subclasses */
060        protected final Log logger = LogFactory.getLog(getClass());
061
062
063        private RequestContext requestContext;
064
065
066        /**
067         * Create and expose the current RequestContext.
068         * Delegates to {@link #doStartTagInternal()} for actual work.
069         * @see #REQUEST_CONTEXT_PAGE_ATTRIBUTE
070         * @see org.springframework.web.servlet.support.JspAwareRequestContext
071         */
072        @Override
073        public final int doStartTag() throws JspException {
074                try {
075                        this.requestContext = (RequestContext) this.pageContext.getAttribute(REQUEST_CONTEXT_PAGE_ATTRIBUTE);
076                        if (this.requestContext == null) {
077                                this.requestContext = new JspAwareRequestContext(this.pageContext);
078                                this.pageContext.setAttribute(REQUEST_CONTEXT_PAGE_ATTRIBUTE, this.requestContext);
079                        }
080                        return doStartTagInternal();
081                }
082                catch (JspException ex) {
083                        logger.error(ex.getMessage(), ex);
084                        throw ex;
085                }
086                catch (RuntimeException ex) {
087                        logger.error(ex.getMessage(), ex);
088                        throw ex;
089                }
090                catch (Exception ex) {
091                        logger.error(ex.getMessage(), ex);
092                        throw new JspTagException(ex.getMessage());
093                }
094        }
095
096        /**
097         * Return the current RequestContext.
098         */
099        protected final RequestContext getRequestContext() {
100                return this.requestContext;
101        }
102
103        /**
104         * Called by doStartTag to perform the actual work.
105         * @return same as TagSupport.doStartTag
106         * @throws Exception any exception, any checked one other than
107         * a JspException gets wrapped in a JspException by doStartTag
108         * @see javax.servlet.jsp.tagext.TagSupport#doStartTag
109         */
110        protected abstract int doStartTagInternal() throws Exception;
111
112
113        @Override
114        public void doCatch(Throwable throwable) throws Throwable {
115                throw throwable;
116        }
117
118        @Override
119        public void doFinally() {
120                this.requestContext = null;
121        }
122
123}