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.portlet.handler;
018
019import javax.portlet.MimeResponse;
020import javax.portlet.PortletException;
021import javax.portlet.PortletRequest;
022import javax.portlet.PortletResponse;
023
024import org.springframework.web.portlet.context.PortletApplicationObjectSupport;
025
026/**
027 * Convenient superclass for any kind of web content generator,
028 * like {@link org.springframework.web.portlet.mvc.AbstractController}.
029 * Can also be used for custom handlers that have their own
030 * {@link org.springframework.web.portlet.HandlerAdapter}.
031 *
032 * <p>Supports portlet cache control options.
033 *
034 * @author Juergen Hoeller
035 * @author John A. Lewis
036 * @since 2.0
037 * @see #setCacheSeconds
038 * @see #setRequireSession
039 */
040public abstract class PortletContentGenerator extends PortletApplicationObjectSupport {
041
042        private boolean requireSession = false;
043
044        private int cacheSeconds = -1;
045
046
047        /**
048         * Set whether a session should be required to handle requests.
049         */
050        public final void setRequireSession(boolean requireSession) {
051                this.requireSession = requireSession;
052        }
053
054        /**
055         * Return whether a session is required to handle requests.
056         */
057        public final boolean isRequireSession() {
058                return this.requireSession;
059        }
060
061        /**
062         * Cache content for the given number of seconds. Default is -1,
063         * indicating no override of portlet content caching.
064         * <p>Only if this is set to 0 (no cache) or a positive value (cache for
065         * this many seconds) will this class override the portlet settings.
066         * <p>The cache setting can be overwritten by subclasses, before content is generated.
067         */
068        public final void setCacheSeconds(int seconds) {
069                this.cacheSeconds = seconds;
070        }
071
072        /**
073         * Return the number of seconds that content is cached.
074         */
075        public final int getCacheSeconds() {
076                return this.cacheSeconds;
077        }
078
079
080        /**
081         * Check and prepare the given request and response according to the settings
082         * of this generator. Checks for a required session, and applies the number of
083         * cache seconds configured for this generator (if it is a render request/response).
084         * @param request current portlet request
085         * @param response current portlet response
086         * @throws PortletException if the request cannot be handled because a check failed
087         */
088        protected final void check(PortletRequest request, PortletResponse response) throws PortletException {
089                if (this.requireSession) {
090                        if (request.getPortletSession(false) == null) {
091                                throw new PortletSessionRequiredException("Pre-existing session required but none found");
092                        }
093                }
094        }
095
096        /**
097         * Check and prepare the given request and response according to the settings
098         * of this generator. Checks for a required session, and applies the number of
099         * cache seconds configured for this generator (if it is a render request/response).
100         * @param request current portlet request
101         * @param response current portlet response
102         * @throws PortletException if the request cannot be handled because a check failed
103         */
104        protected final void checkAndPrepare(PortletRequest request, MimeResponse response)
105                        throws PortletException {
106
107                checkAndPrepare(request, response, this.cacheSeconds);
108        }
109
110        /**
111         * Check and prepare the given request and response according to the settings
112         * of this generator. Checks for a required session, and applies the given
113         * number of cache seconds (if it is a render request/response).
114         * @param request current portlet request
115         * @param response current portlet response
116         * @param cacheSeconds positive number of seconds into the future that the
117         * response should be cacheable for, 0 to prevent caching
118         * @throws PortletException if the request cannot be handled because a check failed
119         */
120        protected final void checkAndPrepare(PortletRequest request, MimeResponse response, int cacheSeconds)
121                        throws PortletException {
122
123                check(request, response);
124                applyCacheSeconds(response, cacheSeconds);
125        }
126
127        /**
128         * Prevent the render response from being cached.
129         */
130        protected final void preventCaching(MimeResponse response) {
131                cacheForSeconds(response, 0);
132        }
133
134        /**
135         * Set portlet response to allow caching for the given number of seconds.
136         * @param response current portlet render response
137         * @param seconds number of seconds into the future that the response
138         * should be cacheable for
139         */
140        protected final void cacheForSeconds(MimeResponse response, int seconds) {
141                response.setProperty(MimeResponse.EXPIRATION_CACHE, Integer.toString(seconds));
142        }
143
144        /**
145         * Apply the given cache seconds to the render response
146         * @param response current portlet render response
147         * @param seconds positive number of seconds into the future that the
148         * response should be cacheable for, 0 to prevent caching
149         */
150        protected final void applyCacheSeconds(MimeResponse response, int seconds) {
151                if (seconds > 0) {
152                        cacheForSeconds(response, seconds);
153                }
154                else if (seconds == 0) {
155                        preventCaching(response);
156                }
157                // Leave caching to the portlet configuration otherwise.
158        }
159
160}