📄 simplesessionhandler.java
字号:
/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.axis.handlers;import org.apache.axis.AxisEngine;import org.apache.axis.AxisFault;import org.apache.axis.Constants;import org.apache.axis.Message;import org.apache.axis.MessageContext;import org.apache.axis.components.logger.LogFactory;import org.apache.axis.message.SOAPEnvelope;import org.apache.axis.message.SOAPHeaderElement;import org.apache.axis.session.SimpleSession;import org.apache.axis.utils.Messages;import org.apache.axis.utils.SessionUtils;import org.apache.commons.logging.Log;import javax.xml.namespace.QName;import javax.xml.rpc.server.ServiceLifecycle;import java.util.Enumeration;import java.util.HashSet;import java.util.Hashtable;import java.util.Iterator;import java.util.Map;import java.util.Set;/** This handler uses SOAP headers to do simple session management. * * <p>Essentially, you install it on both the request and response chains of * your service, on both the client and the server side.</p> * * <p>ON THE SERVER:</p> * <ul> * <li>The REQUEST is checked for a session ID header. If present, we * look up the correct SimpleSession. If not, we create a new session. * In either case, we install the session into the MessageContext, and * put its ID in the SESSION_ID property. * <li>The RESPONSE gets a session ID header tacked on, assuming we found a * SESSION_ID property in the MessageContext. * </ul> * <p>ON THE CLIENT:</p> * <ul> * <li>The RESPONSE messages are checked for session ID headers. If present, * we pull the ID out and insert it into an option in the AxisClient. * This works because a given Call object is associated with a single * AxisClient. However, we might want to find a way to put it into the * Call object itself, which would make a little more sense. This would * mean being able to get to the Call from the MC, i.e. adding a getCall() * API (which would only work on the client side).... * <li>When REQUESTS are generated, we look to see if an ID option is present * in the AxisClient associated with the MessageContext. If so, we * insert a session ID header with the appropriate ID. * </ul> * * <p>SimpleSessions are "reaped" periodically via a very simplistic * mechanism. Each time the handler is invoke()d we check to see if more * than <b>reapPeriodicity</b> milliseconds have elapsed since the last * reap. If so, we walk the collection of active Sessions, and for each * one, if it hasn't been "touched" (i.e. had a getProperty() or setProperty() * performed) in longer than its timeout, we remove it from the collection.</p> * * @author Glen Daniels (gdaniels@apache.org) */public class SimpleSessionHandler extends BasicHandler{ protected static Log log = LogFactory.getLog(SimpleSessionHandler.class.getName()); public static final String SESSION_ID = "SimpleSession.id"; public static final String SESSION_NS = "http://xml.apache.org/axis/session"; public static final String SESSION_LOCALPART = "sessionID"; public static final QName sessionHeaderName = new QName(SESSION_NS, SESSION_LOCALPART); private Hashtable activeSessions = new Hashtable(); // Reap timed-out sessions on the first request after this many // seconds. private long reapPeriodicity = 30; private long lastReapTime = 0; // By default, sessions time out after 1 minute of inactivity (60 sec) private int defaultSessionTimeout = 60; /** * Process a MessageContext. */ public void invoke(MessageContext context) throws AxisFault { // Should we reap timed out sessions? long curTime = System.currentTimeMillis(); boolean reap = false; // Minimize synchronicity, just check in here, do reap later. synchronized (this) { if (curTime > lastReapTime + (reapPeriodicity * 1000)) { reap = true; lastReapTime = curTime; } } if (reap) { Set entries = activeSessions.entrySet(); Set victims = new HashSet(); Object key; Iterator i; for (i = entries.iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); key = entry.getKey(); SimpleSession session = (SimpleSession) entry.getValue(); if ((curTime - session.getLastAccessTime()) > (session.getTimeout() * 1000)) { log.debug(Messages.getMessage("timeout00", key.toString())); // Don't modify the hashtable while we're iterating. victims.add(key); } } // Now go remove all the victims we found during the iteration. for (i = victims.iterator(); i.hasNext();) { key = i.next(); SimpleSession session = (SimpleSession)activeSessions.get(key); activeSessions.remove(key); // For each victim, swing through the data looking for // ServiceLifecycle objects, and calling destroy() on them. // FIXME : This cleanup should probably happen on another // thread, as it might take a little while. Enumeration keys = session.getKeys(); while (keys != null && keys.hasMoreElements()) { String keystr = (String)keys.nextElement(); Object obj = session.get(keystr); if (obj != null && obj instanceof ServiceLifecycle) { ((ServiceLifecycle)obj).destroy(); } } } } if (context.isClient()) { doClient(context); } else { doServer(context); } } /** * Client side of processing. */ public void doClient(MessageContext context) throws AxisFault { if (context.getPastPivot()) { // This is a response. Check it for the session header. Message msg = context.getResponseMessage(); if (msg == null) return; SOAPEnvelope env = msg.getSOAPEnvelope(); SOAPHeaderElement header = env.getHeaderByName(SESSION_NS, SESSION_LOCALPART); if (header == null) return; // Got one! try { Long id = (Long)header. getValueAsType(Constants.XSD_LONG); // Store it away. AxisEngine engine = context.getAxisEngine(); engine.setOption(SESSION_ID, id); // Note that we processed this header! header.setProcessed(true); } catch (Exception e) { throw AxisFault.makeFault(e); } } else { AxisEngine engine = context.getAxisEngine(); Long id = (Long)engine.getOption(SESSION_ID); if (id == null) return; // We have a session ID, so insert the header Message msg = context.getRequestMessage(); if (msg == null) throw new AxisFault(Messages.getMessage("noRequest00")); SOAPEnvelope env = msg.getSOAPEnvelope(); SOAPHeaderElement header = new SOAPHeaderElement(SESSION_NS, SESSION_LOCALPART, id); env.addHeader(header); } } /** * Server side of processing. */ public void doServer(MessageContext context) throws AxisFault { if (context.getPastPivot()) { // This is a response. Add the session header if we have an // ID. Long id = (Long)context.getProperty(SESSION_ID); if (id == null) return; Message msg = context.getResponseMessage(); if (msg == null) return; SOAPEnvelope env = msg.getSOAPEnvelope(); SOAPHeaderElement header = new SOAPHeaderElement(SESSION_NS, SESSION_LOCALPART, id); env.addHeader(header); } else { // Request. Set up the session if we find the header. Message msg = context.getRequestMessage(); if (msg == null) throw new AxisFault(Messages.getMessage("noRequest00")); SOAPEnvelope env = msg.getSOAPEnvelope(); SOAPHeaderElement header = env.getHeaderByName(SESSION_NS, SESSION_LOCALPART); Long id; if (header != null) { // Got one! try { id = (Long)header. getValueAsType(Constants.XSD_LONG); } catch (Exception e) { throw AxisFault.makeFault(e); } } else { id = getNewSession(); } SimpleSession session = (SimpleSession)activeSessions.get(id); if (session == null) { // Must have timed out, get a new one. id = getNewSession(); session = (SimpleSession)activeSessions.get(id); } // This session is still active... session.touch(); // Store it away in the MessageContext. context.setSession(session); context.setProperty(SESSION_ID, id); } } /** * Generate a new session, register it, and return its ID. * * @return the new session's ID for later lookup. */ private synchronized Long getNewSession() { Long id = SessionUtils.generateSession(); SimpleSession session = new SimpleSession(); session.setTimeout(defaultSessionTimeout); activeSessions.put(id, session); return id; } /** * Set the reaper periodicity in SECONDS * * Convenience method for testing. * * !!! TODO: Should be able to set this via options on the Handler * or perhaps the engine. */ public void setReapPeriodicity(long reapTime) { reapPeriodicity = reapTime; } /** * Set the default session timeout in SECONDS * * Again, for testing. */ public void setDefaultSessionTimeout(int defaultSessionTimeout) { this.defaultSessionTimeout = defaultSessionTimeout; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -