001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.catalina.valves;
019:
020: import java.io.IOException;
021:
022: import javax.servlet.ServletException;
023: import javax.servlet.http.HttpServletResponse;
024:
025: import org.apache.catalina.Context;
026: import org.apache.catalina.Manager;
027: import org.apache.catalina.Session;
028: import org.apache.catalina.Store;
029: import org.apache.catalina.connector.Request;
030: import org.apache.catalina.connector.Response;
031: import org.apache.catalina.core.StandardHost;
032: import org.apache.catalina.session.PersistentManager;
033: import org.apache.catalina.util.StringManager;
034:
035: /**
036: * Valve that implements the default basic behavior for the
037: * <code>StandardHost</code> container implementation.
038: * <p>
039: * <b>USAGE CONSTRAINT</b>: To work correctly it requires a PersistentManager.
040: *
041: * @author Jean-Frederic Clere
042: * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
043: */
044:
045: public class PersistentValve extends ValveBase {
046:
047: // ----------------------------------------------------- Instance Variables
048:
049: /**
050: * The descriptive information related to this implementation.
051: */
052: private static final String info = "org.apache.catalina.valves.PersistentValve/1.0";
053:
054: /**
055: * The string manager for this package.
056: */
057: private static final StringManager sm = StringManager
058: .getManager(Constants.Package);
059:
060: // ------------------------------------------------------------- Properties
061:
062: /**
063: * Return descriptive information about this Valve implementation.
064: */
065: public String getInfo() {
066:
067: return (info);
068:
069: }
070:
071: // --------------------------------------------------------- Public Methods
072:
073: /**
074: * Select the appropriate child Context to process this request,
075: * based on the specified request URI. If no matching Context can
076: * be found, return an appropriate HTTP error.
077: *
078: * @param request Request to be processed
079: * @param response Response to be produced
080: *
081: * @exception IOException if an input/output error occurred
082: * @exception ServletException if a servlet error occurred
083: */
084: public void invoke(Request request, Response response)
085: throws IOException, ServletException {
086:
087: // Select the Context to be used for this Request
088: StandardHost host = (StandardHost) getContainer();
089: Context context = request.getContext();
090: if (context == null) {
091: response.sendError(
092: HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm
093: .getString("standardHost.noContext"));
094: return;
095: }
096:
097: // Bind the context CL to the current thread
098: Thread.currentThread().setContextClassLoader(
099: context.getLoader().getClassLoader());
100:
101: // Update the session last access time for our session (if any)
102: String sessionId = request.getRequestedSessionId();
103: Manager manager = context.getManager();
104: if (sessionId != null && manager != null) {
105: if (manager instanceof PersistentManager) {
106: Store store = ((PersistentManager) manager).getStore();
107: if (store != null) {
108: Session session = null;
109: try {
110: session = store.load(sessionId);
111: } catch (Exception e) {
112: container.getLogger().error("deserializeError");
113: }
114: if (session != null) {
115: if (!session.isValid()
116: || isSessionStale(session, System
117: .currentTimeMillis())) {
118: if (container.getLogger().isDebugEnabled())
119: container
120: .getLogger()
121: .debug(
122: "session swapped in is invalid or expired");
123: session.expire();
124: store.remove(sessionId);
125: } else {
126: session.setManager(manager);
127: // session.setId(sessionId); Only if new ???
128: manager.add(session);
129: // ((StandardSession)session).activate();
130: session.access();
131: }
132: }
133: }
134: }
135: }
136: if (container.getLogger().isDebugEnabled())
137: container.getLogger().debug("sessionId: " + sessionId);
138:
139: // Ask the next valve to process the request.
140: getNext().invoke(request, response);
141:
142: // Read the sessionid after the response.
143: // HttpSession hsess = hreq.getSession(false);
144: Session hsess;
145: try {
146: hsess = request.getSessionInternal();
147: } catch (Exception ex) {
148: hsess = null;
149: }
150: String newsessionId = null;
151: if (hsess != null)
152: newsessionId = hsess.getIdInternal();
153:
154: if (container.getLogger().isDebugEnabled())
155: container.getLogger()
156: .debug("newsessionId: " + newsessionId);
157: if (newsessionId != null) {
158: /* store the session in the store and remove it from the manager */
159: if (manager instanceof PersistentManager) {
160: Session session = manager.findSession(newsessionId);
161: Store store = ((PersistentManager) manager).getStore();
162: if (store != null
163: && session != null
164: && session.isValid()
165: && !isSessionStale(session, System
166: .currentTimeMillis())) {
167: // ((StandardSession)session).passivate();
168: store.save(session);
169: ((PersistentManager) manager).removeSuper(session);
170: session.recycle();
171: } else {
172: if (container.getLogger().isDebugEnabled())
173: container
174: .getLogger()
175: .debug(
176: "newsessionId store: "
177: + store
178: + " session: "
179: + session
180: + " valid: "
181: + session.isValid()
182: + " Staled: "
183: + isSessionStale(
184: session,
185: System
186: .currentTimeMillis()));
187:
188: }
189: } else {
190: if (container.getLogger().isDebugEnabled())
191: container.getLogger().debug(
192: "newsessionId Manager: " + manager);
193: }
194: }
195: }
196:
197: /**
198: * Indicate whether the session has been idle for longer
199: * than its expiration date as of the supplied time.
200: *
201: * FIXME: Probably belongs in the Session class.
202: */
203: protected boolean isSessionStale(Session session, long timeNow) {
204:
205: int maxInactiveInterval = session.getMaxInactiveInterval();
206: if (maxInactiveInterval >= 0) {
207: int timeIdle = // Truncate, do not round up
208: (int) ((timeNow - session.getLastAccessedTime()) / 1000L);
209: if (timeIdle >= maxInactiveInterval)
210: return true;
211: }
212:
213: return false;
214:
215: }
216:
217: }
|