001: /*
002: * Copyright 1999-2001,2004 The Apache Software Foundation.
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: * http://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:
017: package org.apache.catalina.valves;
018:
019: import java.io.IOException;
020:
021: import javax.servlet.ServletException;
022: import javax.servlet.http.HttpServletRequest;
023: import javax.servlet.http.HttpServletResponse;
024: import javax.servlet.http.HttpSession;
025:
026: import org.apache.catalina.Context;
027: import org.apache.catalina.Logger;
028: import org.apache.catalina.Manager;
029: import org.apache.catalina.Request;
030: import org.apache.catalina.Response;
031: import org.apache.catalina.Session;
032: import org.apache.catalina.Store;
033: import org.apache.catalina.ValveContext;
034: import org.apache.catalina.core.StandardHost;
035: import org.apache.catalina.session.PersistentManager;
036: import org.apache.catalina.util.StringManager;
037:
038: /**
039: * Valve that implements the default basic behavior for the
040: * <code>StandardHost</code> container implementation.
041: * <p>
042: * <b>USAGE CONSTRAINT</b>: To work correctly it requires a PersistentManager.
043: *
044: * @author Jean-Frederic Clere
045: * @version $Revision: 1.5 $ $Date: 2004/02/27 14:58:52 $
046: */
047:
048: public class PersistentValve extends ValveBase {
049:
050: // ----------------------------------------------------- Instance Variables
051:
052: /**
053: * The descriptive information related to this implementation.
054: */
055: private static final String info = "org.apache.catalina.valves.PersistentValve/1.0";
056:
057: /**
058: * The string manager for this package.
059: */
060: private static final StringManager sm = StringManager
061: .getManager(Constants.Package);
062:
063: // ------------------------------------------------------------- Properties
064:
065: /**
066: * Return descriptive information about this Valve implementation.
067: */
068: public String getInfo() {
069:
070: return (info);
071:
072: }
073:
074: // --------------------------------------------------------- Public Methods
075:
076: /**
077: * Select the appropriate child Context to process this request,
078: * based on the specified request URI. If no matching Context can
079: * be found, return an appropriate HTTP error.
080: *
081: * @param request Request to be processed
082: * @param response Response to be produced
083: * @param valveContext Valve context used to forward to the next Valve
084: *
085: * @exception IOException if an input/output error occurred
086: * @exception ServletException if a servlet error occurred
087: */
088: public void invoke(Request request, Response response,
089: ValveContext valveContext) throws IOException,
090: ServletException {
091:
092: // Select the Context to be used for this Request
093: StandardHost host = (StandardHost) getContainer();
094: Context context = request.getContext();
095: if (context == null) {
096: ((HttpServletResponse) response.getResponse()).sendError(
097: HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm
098: .getString("standardHost.noContext"));
099: return;
100: }
101:
102: // Bind the context CL to the current thread
103: Thread.currentThread().setContextClassLoader(
104: context.getLoader().getClassLoader());
105:
106: // Update the session last access time for our session (if any)
107: HttpServletRequest hreq = (HttpServletRequest) request
108: .getRequest();
109: String sessionId = hreq.getRequestedSessionId();
110: Manager manager = context.getManager();
111: if (sessionId != null && manager != null) {
112: if (manager instanceof PersistentManager) {
113: Store store = ((PersistentManager) manager).getStore();
114: if (store != null) {
115: Session session = null;
116: try {
117: session = store.load(sessionId);
118: } catch (Exception e) {
119: log("deserializeError");
120: }
121: if (session != null) {
122: if (!session.isValid()
123: || isSessionStale(session, System
124: .currentTimeMillis())) {
125: log("session swapped in is invalid or expired");
126: session.expire();
127: store.remove(sessionId);
128: } else {
129: session.setManager(manager);
130: // session.setId(sessionId); Only if new ???
131: manager.add(session);
132: // ((StandardSession)session).activate();
133: session.access();
134: }
135: }
136: }
137: }
138: }
139: log("sessionId: " + sessionId);
140:
141: // Ask the next valve to process the request.
142: valveContext.invokeNext(request, response);
143:
144: // Read the sessionid after the response.
145: // HttpSession hsess = hreq.getSession(false);
146: HttpSession hsess;
147: try {
148: hsess = hreq.getSession();
149: } catch (Exception ex) {
150: hsess = null;
151: }
152: String newsessionId = null;
153: if (hsess != null)
154: newsessionId = hsess.getId();
155:
156: log("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: log("newsessionId store: "
173: + store
174: + " session: "
175: + session
176: + " valid: "
177: + session.isValid()
178: + " Staled: "
179: + isSessionStale(session, System
180: .currentTimeMillis()));
181:
182: }
183: } else {
184: log("newsessionId Manager: " + manager);
185: }
186: }
187: }
188:
189: /**
190: * Log a message on the Logger associated with our Container (if any).
191: *
192: * @param message Message to be logged
193: */
194: protected void log(String message) {
195:
196: Logger logger = container.getLogger();
197: if (logger != null)
198: logger.log(this .toString() + ": " + message);
199: else
200: System.out.println(this .toString() + ": " + message);
201:
202: }
203:
204: /**
205: * Indicate whether the session has been idle for longer
206: * than its expiration date as of the supplied time.
207: *
208: * FIXME: Probably belongs in the Session class.
209: */
210: protected boolean isSessionStale(Session session, long timeNow) {
211:
212: int maxInactiveInterval = session.getMaxInactiveInterval();
213: if (maxInactiveInterval >= 0) {
214: int timeIdle = // Truncate, do not round up
215: (int) ((timeNow - session.getLastAccessedTime()) / 1000L);
216: if (timeIdle >= maxInactiveInterval)
217: return true;
218: }
219:
220: return false;
221:
222: }
223:
224: }
|