You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2006/05/20 04:12:52 UTC
svn commit: r407939 [2/8] - in
/tomcat/sandbox/java/org/apache/coyote/servlet: ./ util/
Added: tomcat/sandbox/java/org/apache/coyote/servlet/Host.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/coyote/servlet/Host.java?rev=407939&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/coyote/servlet/Host.java (added)
+++ tomcat/sandbox/java/org/apache/coyote/servlet/Host.java Fri May 19 19:12:51 2006
@@ -0,0 +1,823 @@
+/*
+ * Copyright 1999,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.coyote.servlet;
+
+
+import java.util.HashMap;
+
+import org.apache.tomcat.util.res.StringManager;
+
+
+/**
+ * Standard implementation of the <b>Host</b> interface. Each
+ * child container must be a Context implementation to process the
+ * requests directed to a particular web application.
+ *
+ * @author Craig R. McClanahan
+ * @author Remy Maucherat
+ * @version $Revision: 303666 $ $Date: 2005-01-29 11:38:37 -0800 (Sat, 29 Jan 2005) $
+ */
+
+public class Host
+ {
+ /* Why do we implement deployer and delegate to deployer ??? */
+
+ private static org.apache.commons.logging.Log log=
+ org.apache.commons.logging.LogFactory.getLog( Host.class );
+
+ static StringManager sm = StringManager.getManager("org.apache.coyote.servlet");
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a new StandardHost component with the default basic Valve.
+ */
+ public Host() {
+
+ super();
+// pipeline.setBasic(new StandardHostValve());
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The set of aliases for this Host.
+ */
+ private String[] aliases = new String[0];
+
+
+ /**
+ * The application root for this Host.
+ */
+ private String appBase = ".";
+
+
+ /**
+ * The auto deploy flag for this Host.
+ */
+ private boolean autoDeploy = true;
+
+
+ /**
+ * The Java class name of the default context configuration class
+ * for deployed web applications.
+ */
+ private String configClass =
+ "org.apache.catalina.startup.ContextConfig";
+
+
+ /**
+ * The Java class name of the default Context implementation class for
+ * deployed web applications.
+ */
+ private String contextClass =
+ "org.apache.catalina.core.StandardContext";
+
+
+ /**
+ * The deploy on startup flag for this Host.
+ */
+ private boolean deployOnStartup = true;
+
+
+ /**
+ * deploy Context XML config files property.
+ */
+ private boolean deployXML = true;
+
+
+ /**
+ * The Java class name of the default error reporter implementation class
+ * for deployed web applications.
+ */
+ private String errorReportValveClass =
+ "org.apache.catalina.valves.ErrorReportValve";
+
+ /**
+ * The object name for the errorReportValve.
+ */
+// private ObjectName errorReportValveObjectName = null;
+
+ /**
+ * The descriptive information string for this implementation.
+ */
+ private static final String info =
+ "org.apache.catalina.core.StandardHost/1.0";
+
+
+ /**
+ * The live deploy flag for this Host.
+ */
+ private boolean liveDeploy = true;
+
+
+ /**
+ * Unpack WARs property.
+ */
+ private boolean unpackWARs = true;
+
+
+ /**
+ * Work Directory base for applications.
+ */
+ private String workDir = null;
+
+
+ /**
+ * Attribute value used to turn on/off XML validation
+ */
+ private boolean xmlValidation = false;
+
+
+ /**
+ * Attribute value used to turn on/off XML namespace awarenes.
+ */
+ private boolean xmlNamespaceAware = false;
+
+
+ private String name;
+
+ private HashMap children = new HashMap();
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * Return the application root for this Host. This can be an absolute
+ * pathname, a relative pathname, or a URL.
+ */
+ public String getAppBase() {
+
+ return (this.appBase);
+
+ }
+
+
+ /**
+ * Set the application root for this Host. This can be an absolute
+ * pathname, a relative pathname, or a URL.
+ *
+ * @param appBase The new application root
+ */
+ public void setAppBase(String appBase) {
+
+ String oldAppBase = this.appBase;
+ this.appBase = appBase;
+// support.firePropertyChange("appBase", oldAppBase, this.appBase);
+
+ }
+
+
+ /**
+ * Return the value of the auto deploy flag. If true, it indicates that
+ * this host's child webapps will be dynamically deployed.
+ */
+ public boolean getAutoDeploy() {
+
+ return (this.autoDeploy);
+
+ }
+
+
+ /**
+ * Set the auto deploy flag value for this host.
+ *
+ * @param autoDeploy The new auto deploy flag
+ */
+ public void setAutoDeploy(boolean autoDeploy) {
+
+ boolean oldAutoDeploy = this.autoDeploy;
+ this.autoDeploy = autoDeploy;
+// support.firePropertyChange("autoDeploy", oldAutoDeploy,
+// this.autoDeploy);
+
+ }
+
+
+ /**
+ * Return the Java class name of the context configuration class
+ * for new web applications.
+ */
+ public String getConfigClass() {
+
+ return (this.configClass);
+
+ }
+
+
+ /**
+ * Set the Java class name of the context configuration class
+ * for new web applications.
+ *
+ * @param configClass The new context configuration class
+ */
+ public void setConfigClass(String configClass) {
+
+ String oldConfigClass = this.configClass;
+ this.configClass = configClass;
+// support.firePropertyChange("configClass",
+// oldConfigClass, this.configClass);
+
+ }
+
+
+ /**
+ * Return the Java class name of the Context implementation class
+ * for new web applications.
+ */
+ public String getContextClass() {
+
+ return (this.contextClass);
+
+ }
+
+
+ /**
+ * Set the Java class name of the Context implementation class
+ * for new web applications.
+ *
+ * @param contextClass The new context implementation class
+ */
+ public void setContextClass(String contextClass) {
+
+ String oldContextClass = this.contextClass;
+ this.contextClass = contextClass;
+// support.firePropertyChange("contextClass",
+// oldContextClass, this.contextClass);
+
+ }
+
+
+ /**
+ * Return the value of the deploy on startup flag. If true, it indicates
+ * that this host's child webapps should be discovred and automatically
+ * deployed at startup time.
+ */
+ public boolean getDeployOnStartup() {
+
+ return (this.deployOnStartup);
+
+ }
+
+
+ /**
+ * Set the deploy on startup flag value for this host.
+ *
+ * @param deployOnStartup The new deploy on startup flag
+ */
+ public void setDeployOnStartup(boolean deployOnStartup) {
+
+ boolean oldDeployOnStartup = this.deployOnStartup;
+ this.deployOnStartup = deployOnStartup;
+// support.firePropertyChange("deployOnStartup", oldDeployOnStartup,
+// this.deployOnStartup);
+
+ }
+
+
+ /**
+ * Deploy XML Context config files flag accessor.
+ */
+ public boolean isDeployXML() {
+
+ return (deployXML);
+
+ }
+
+
+ /**
+ * Deploy XML Context config files flag mutator.
+ */
+ public void setDeployXML(boolean deployXML) {
+
+ this.deployXML = deployXML;
+
+ }
+
+
+ /**
+ * Return the value of the live deploy flag. If true, it indicates that
+ * a background thread should be started that looks for web application
+ * context files, WAR files, or unpacked directories being dropped in to
+ * the <code>appBase</code> directory, and deploys new ones as they are
+ * encountered.
+ */
+ public boolean getLiveDeploy() {
+ return (this.autoDeploy);
+ }
+
+
+ /**
+ * Set the live deploy flag value for this host.
+ *
+ * @param liveDeploy The new live deploy flag
+ */
+ public void setLiveDeploy(boolean liveDeploy) {
+ setAutoDeploy(liveDeploy);
+ }
+
+
+ /**
+ * Return the Java class name of the error report valve class
+ * for new web applications.
+ */
+ public String getErrorReportValveClass() {
+
+ return (this.errorReportValveClass);
+
+ }
+
+
+ /**
+ * Set the Java class name of the error report valve class
+ * for new web applications.
+ *
+ * @param errorReportValveClass The new error report valve class
+ */
+ public void setErrorReportValveClass(String errorReportValveClass) {
+
+ String oldErrorReportValveClassClass = this.errorReportValveClass;
+ this.errorReportValveClass = errorReportValveClass;
+// support.firePropertyChange("errorReportValveClass",
+// oldErrorReportValveClassClass,
+// this.errorReportValveClass);
+
+ }
+
+
+ /**
+ * Return the canonical, fully qualified, name of the virtual host
+ * this Container represents.
+ */
+ public String getName() {
+
+ return (name);
+
+ }
+
+
+ /**
+ * Set the canonical, fully qualified, name of the virtual host
+ * this Container represents.
+ *
+ * @param name Virtual host name
+ *
+ * @exception IllegalArgumentException if name is null
+ */
+ public void setName(String name) {
+
+ if (name == null)
+ throw new IllegalArgumentException
+ (sm.getString("standardHost.nullName"));
+
+ name = name.toLowerCase(); // Internally all names are lower case
+
+ String oldName = this.name;
+ this.name = name;
+// support.firePropertyChange("name", oldName, this.name);
+
+ }
+
+
+ /**
+ * Unpack WARs flag accessor.
+ */
+ public boolean isUnpackWARs() {
+
+ return (unpackWARs);
+
+ }
+
+
+ /**
+ * Unpack WARs flag mutator.
+ */
+ public void setUnpackWARs(boolean unpackWARs) {
+
+ this.unpackWARs = unpackWARs;
+
+ }
+
+ /**
+ * Set the validation feature of the XML parser used when
+ * parsing xml instances.
+ * @param xmlValidation true to enable xml instance validation
+ */
+ public void setXmlValidation(boolean xmlValidation){
+
+ this.xmlValidation = xmlValidation;
+
+ }
+
+ /**
+ * Get the server.xml <host> attribute's xmlValidation.
+ * @return true if validation is enabled.
+ *
+ */
+ public boolean getXmlValidation(){
+ return xmlValidation;
+ }
+
+ /**
+ * Get the server.xml <host> attribute's xmlNamespaceAware.
+ * @return true if namespace awarenes is enabled.
+ *
+ */
+ public boolean getXmlNamespaceAware(){
+ return xmlNamespaceAware;
+ }
+
+
+ /**
+ * Set the namespace aware feature of the XML parser used when
+ * parsing xml instances.
+ * @param xmlNamespaceAware true to enable namespace awareness
+ */
+ public void setXmlNamespaceAware(boolean xmlNamespaceAware){
+ this.xmlNamespaceAware=xmlNamespaceAware;
+ }
+
+ /**
+ * Host work directory base.
+ */
+ public String getWorkDir() {
+
+ return (workDir);
+ }
+
+
+ /**
+ * Host work directory base.
+ */
+ public void setWorkDir(String workDir) {
+
+ this.workDir = workDir;
+ }
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Add an alias name that should be mapped to this same Host.
+ *
+ * @param alias The alias to be added
+ */
+ public void addAlias(String alias) {
+
+ alias = alias.toLowerCase();
+
+ // Skip duplicate aliases
+ for (int i = 0; i < aliases.length; i++) {
+ if (aliases[i].equals(alias))
+ return;
+ }
+
+ // Add this alias to the list
+ String newAliases[] = new String[aliases.length + 1];
+ for (int i = 0; i < aliases.length; i++)
+ newAliases[i] = aliases[i];
+ newAliases[aliases.length] = alias;
+
+ aliases = newAliases;
+
+ // Inform interested listeners
+// fireContainerEvent(ADD_ALIAS_EVENT, alias);
+
+ }
+
+
+ /**
+ * Add a child Container, only if the proposed child is an implementation
+ * of Context.
+ *
+ * @param child Child container to be added
+ */
+ public void addChild(ServletContextImpl child) {
+
+ if (!(child instanceof ServletContextImpl))
+ throw new IllegalArgumentException
+ (sm.getString("standardHost.notContext"));
+// super.addChild(child);
+
+ children .put(child.getName(), child);
+ }
+
+
+ /**
+ * Return the set of alias names for this Host. If none are defined,
+ * a zero length array is returned.
+ */
+ public String[] findAliases() {
+
+ return (this.aliases);
+
+ }
+
+
+ /**
+ * Return descriptive information about this Container implementation and
+ * the corresponding version number, in the format
+ * <code><description>/<version></code>.
+ */
+ public String getInfo() {
+
+ return (info);
+
+ }
+
+
+ /**
+ * Return the Context that would be used to process the specified
+ * host-relative request URI, if any; otherwise return <code>null</code>.
+ *
+ * @param uri Request URI to be mapped
+ */
+ public ServletContextImpl map(String uri) {
+
+ if (log.isDebugEnabled())
+ log.debug("Mapping request URI '" + uri + "'");
+ if (uri == null)
+ return (null);
+
+ // Match on the longest possible context path prefix
+ if (log.isTraceEnabled())
+ log.trace(" Trying the longest context path prefix");
+ ServletContextImpl context = null;
+ String mapuri = uri;
+ while (true) {
+ context = (ServletContextImpl) children.get(mapuri);
+ if (context != null)
+ break;
+ int slash = mapuri.lastIndexOf('/');
+ if (slash < 0)
+ break;
+ mapuri = mapuri.substring(0, slash);
+ }
+
+ // If no Context matches, select the default Context
+ if (context == null) {
+ if (log.isTraceEnabled())
+ log.trace(" Trying the default context");
+ context = (ServletContextImpl) children.get("");
+ }
+
+ // Complain if no Context has been selected
+ if (context == null) {
+ log.error(sm.getString("standardHost.mappingError", uri));
+ return (null);
+ }
+
+ // Return the mapped Context (if any)
+ if (log.isDebugEnabled())
+ log.debug(" Mapped to context '" + context.getPath() + "'");
+ return (context);
+
+ }
+
+
+ /**
+ * Remove the specified alias name from the aliases for this Host.
+ *
+ * @param alias Alias name to be removed
+ */
+ public void removeAlias(String alias) {
+
+ alias = alias.toLowerCase();
+
+ synchronized (aliases) {
+
+ // Make sure this alias is currently present
+ int n = -1;
+ for (int i = 0; i < aliases.length; i++) {
+ if (aliases[i].equals(alias)) {
+ n = i;
+ break;
+ }
+ }
+ if (n < 0)
+ return;
+
+ // Remove the specified alias
+ int j = 0;
+ String results[] = new String[aliases.length - 1];
+ for (int i = 0; i < aliases.length; i++) {
+ if (i != n)
+ results[j++] = aliases[i];
+ }
+ aliases = results;
+
+ }
+
+ // Inform interested listeners
+// fireContainerEvent(REMOVE_ALIAS_EVENT, alias);
+
+ }
+
+
+ /**
+ * Return a String representation of this component.
+ */
+ public String toString() {
+
+ StringBuffer sb = new StringBuffer();
+// if (getParent() != null) {
+// sb.append(getParent().toString());
+// sb.append(".");
+// }
+ sb.append("StandardHost[");
+ sb.append(getName());
+ sb.append("]");
+ return (sb.toString());
+
+ }
+
+
+ /**
+ * Start this host.
+ *
+ * @exception LifecycleException if this component detects a fatal error
+ * that prevents it from being started
+ */
+ public synchronized void start() {
+// if( started ) {
+// return;
+// }
+ if( ! initialized )
+ init();
+
+ // Look for a realm - that may have been configured earlier.
+ // If the realm is added after context - it'll set itself.
+// if( realm == null ) {
+// ObjectName realmName=null;
+// try {
+// realmName=new ObjectName( domain + ":type=Realm,host=" + getName());
+// if( mserver.isRegistered(realmName ) ) {
+// mserver.invoke(realmName, "init",
+// new Object[] {},
+// new String[] {}
+// );
+// }
+// } catch( Throwable t ) {
+// log.debug("No realm for this host " + realmName);
+// }
+// }
+
+ // Set error report valve
+// if ((errorReportValveClass != null)
+// && (!errorReportValveClass.equals(""))) {
+// try {
+// boolean found = false;
+// if(errorReportValveObjectName != null) {
+// ObjectName[] names =
+// ((StandardPipeline)pipeline).getValveObjectNames();
+// for (int i=0; !found && i<names.length; i++)
+// if(errorReportValveObjectName.equals(names[i]))
+// found = true ;
+// }
+// if(!found) {
+// Valve valve = (Valve) Class.forName(errorReportValveClass)
+// .newInstance();
+// addValve(valve);
+// errorReportValveObjectName = ((ValveBase)valve).getObjectName() ;
+// }
+// } catch (Throwable t) {
+// log.error(sm.getString
+// ("standardHost.invalidErrorReportValveClass",
+// errorReportValveClass));
+// }
+// }
+ if(log.isInfoEnabled()) {
+ if (xmlValidation)
+ log.info( sm.getString("standardHost.validationEnabled"));
+ else
+ log.info( sm.getString("standardHost.validationDisabled"));
+ }
+// super.start();
+
+ }
+
+
+ // -------------------- JMX --------------------
+ /**
+ * Return the MBean Names of the Valves assoicated with this Host
+ *
+ * @exception Exception if an MBean cannot be created or registered
+ */
+// public String [] getValveNames()
+// throws Exception
+// {
+// Valve [] valves = this.getValves();
+// String [] mbeanNames = new String[valves.length];
+// for (int i = 0; i < valves.length; i++) {
+// if( valves[i] == null ) continue;
+// if( ((ValveBase)valves[i]).getObjectName() == null ) continue;
+// mbeanNames[i] = ((ValveBase)valves[i]).getObjectName().toString();
+// }
+//
+// return mbeanNames;
+//
+// }
+
+ public String[] getAliases() {
+ return aliases;
+ }
+
+ private boolean initialized=false;
+
+ public void init() {
+ if( initialized ) return;
+ initialized=true;
+
+ // already registered.
+// if( getParent() == null ) {
+// try {
+// // Register with the Engine
+// ObjectName serviceName=new ObjectName(domain +
+// ":type=Engine");
+//
+// HostConfig deployer = new HostConfig();
+// addLifecycleListener(deployer);
+// if( mserver.isRegistered( serviceName )) {
+// if(log.isDebugEnabled())
+// log.debug("Registering "+ serviceName +" with the Engine");
+// mserver.invoke( serviceName, "addChild",
+// new Object[] { this },
+// new String[] { "org.apache.catalina.Container" } );
+// }
+// } catch( Exception ex ) {
+// log.error("Host registering failed!",ex);
+// }
+// }
+
+// if( oname==null ) {
+// // not registered in JMX yet - standalone mode
+// try {
+// StandardEngine engine=(StandardEngine)parent;
+// domain=engine.getName();
+// if(log.isDebugEnabled())
+// log.debug( "Register host " + getName() + " with domain "+ domain );
+// oname=new ObjectName(domain + ":type=Host,host=" +
+// this.getName());
+// controller = oname;
+// Registry.getRegistry(null, null)
+// .registerComponent(this, oname, null);
+// } catch( Throwable t ) {
+// log.error("Host registering failed!", t );
+// }
+// }
+ }
+
+ public void destroy() throws Exception {
+ // destroy our child containers, if any
+ //Container children[] = findChildren();
+// super.destroy();
+ for (Object child: children.values()) {
+ ((ServletContextImpl)child).destroy();
+ }
+
+ }
+
+
+ public ServletContextImpl findChild(String mapuri) {
+ return (ServletContextImpl)children.get(mapuri);
+ }
+
+// public ObjectName preRegister(MBeanServer server, ObjectName oname )
+// throws Exception
+// {
+// ObjectName res=super.preRegister(server, oname);
+// String name=oname.getKeyProperty("host");
+// if( name != null )
+// setName( name );
+// return res;
+// }
+
+// public ObjectName createObjectName(String domain, ObjectName parent)
+// throws Exception
+// {
+// if( log.isDebugEnabled())
+// log.debug("Create ObjectName " + domain + " " + parent );
+// return new ObjectName( domain + ":type=Host,host=" + getName());
+// }
+
+}
Added: tomcat/sandbox/java/org/apache/coyote/servlet/HttpSessionImpl.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/coyote/servlet/HttpSessionImpl.java?rev=407939&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/coyote/servlet/HttpSessionImpl.java (added)
+++ tomcat/sandbox/java/org/apache/coyote/servlet/HttpSessionImpl.java Fri May 19 19:12:51 2006
@@ -0,0 +1,1699 @@
+/*
+ * Copyright 1999,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.coyote.servlet;
+
+
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionActivationListener;
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionBindingListener;
+import javax.servlet.http.HttpSessionContext;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+//import org.apache.catalina.Context;
+//import org.apache.catalina.Globals;
+//import org.apache.catalina.SessionEvent;
+//import org.apache.catalina.SessionListener;
+import org.apache.coyote.servlet.util.Enumerator;
+import org.apache.tomcat.util.res.StringManager;
+
+/**
+ * Standard implementation of the <b>Session</b> interface. This object is
+ * serializable, so that it can be stored in persistent storage or transferred
+ * to a different JVM for distributable session support.
+ * <p>
+ * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the
+ * internal (Session) and application level (HttpSession) view of the session.
+ * However, because the class itself is not declared public, Java logic outside
+ * of the <code>org.apache.catalina.session</code> package cannot cast an
+ * HttpSession view of this instance back to a Session view.
+ * <p>
+ * <b>IMPLEMENTATION NOTE</b>: If you add fields to this class, you must
+ * make sure that you carry them over in the read/writeObject methods so
+ * that this class is properly serialized.
+ *
+ * @author Craig R. McClanahan
+ * @author Sean Legassick
+ * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
+ * @version $Revision: 375376 $ $Date: 2006-02-06 13:22:14 -0800 (Mon, 06 Feb 2006) $
+ */
+
+public class HttpSessionImpl
+ implements HttpSession, Serializable {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new Session associated with the specified Manager.
+ *
+ * @param manager The manager with which this Session is associated
+ */
+ public HttpSessionImpl(SessionManager manager) {
+
+ super();
+ this.manager = manager;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * Type array.
+ */
+ protected static final String EMPTY_ARRAY[] = new String[0];
+
+
+ /**
+ * The dummy attribute value serialized when a NotSerializableException is
+ * encountered in <code>writeObject()</code>.
+ */
+ protected static final String NOT_SERIALIZED =
+ "___NOT_SERIALIZABLE_EXCEPTION___";
+
+
+ /**
+ * The collection of user data attributes associated with this Session.
+ */
+ protected Map attributes = new Hashtable();
+
+
+ /**
+ * The authentication type used to authenticate our cached Principal,
+ * if any. NOTE: This value is not included in the serialized
+ * version of this object.
+ */
+ protected transient String authType = null;
+
+
+ /**
+ * The <code>java.lang.Method</code> for the
+ * <code>fireContainerEvent()</code> method of the
+ * <code>org.apache.catalina.core.StandardContext</code> method,
+ * if our Context implementation is of this class. This value is
+ * computed dynamically the first time it is needed, or after
+ * a session reload (since it is declared transient).
+ */
+ protected transient Method containerEventMethod = null;
+
+
+ /**
+ * The method signature for the <code>fireContainerEvent</code> method.
+ */
+ protected static final Class containerEventTypes[] =
+ { String.class, Object.class };
+
+
+ /**
+ * The time this session was created, in milliseconds since midnight,
+ * January 1, 1970 GMT.
+ */
+ protected long creationTime = 0L;
+
+ /**
+ * The subject under which the AccessControlContext is running.
+ */
+ public static final String SUBJECT_ATTR =
+ "javax.security.auth.subject";
+
+
+ /**
+ * Set of attribute names which are not allowed to be persisted.
+ */
+ private static final String[] excludedAttributes = {
+ SUBJECT_ATTR
+ };
+
+
+ /**
+ * We are currently processing a session expiration, so bypass
+ * certain IllegalStateException tests. NOTE: This value is not
+ * included in the serialized version of this object.
+ */
+ protected transient boolean expiring = false;
+
+
+ /**
+ * The facade associated with this session. NOTE: This value is not
+ * included in the serialized version of this object.
+ */
+// protected transient StandardSessionFacade facade = null;
+
+
+ /**
+ * The session identifier of this Session.
+ */
+ protected String id = null;
+
+
+ /**
+ * Descriptive information describing this Session implementation.
+ */
+ protected static final String info = "StandardSession/1.0";
+
+
+ /**
+ * The last accessed time for this Session.
+ */
+ protected long lastAccessedTime = creationTime;
+
+
+ /**
+ * The session event listeners for this Session.
+ */
+ protected transient ArrayList listeners = new ArrayList();
+
+
+ /**
+ * The Manager with which this Session is associated.
+ */
+ protected transient SessionManager manager = null;
+
+
+ /**
+ * The maximum time interval, in seconds, between client requests before
+ * the servlet container may invalidate this session. A negative time
+ * indicates that the session should never time out.
+ */
+ protected int maxInactiveInterval = -1;
+
+
+ /**
+ * Flag indicating whether this session is new or not.
+ */
+ protected boolean isNew = false;
+
+
+ /**
+ * Flag indicating whether this session is valid or not.
+ */
+ protected boolean isValid = false;
+
+
+ /**
+ * Internal notes associated with this session by Catalina components
+ * and event listeners. <b>IMPLEMENTATION NOTE:</b> This object is
+ * <em>not</em> saved and restored across session serializations!
+ */
+ protected transient Map notes = new Hashtable();
+
+
+ /**
+ * The authenticated Principal associated with this session, if any.
+ * <b>IMPLEMENTATION NOTE:</b> This object is <i>not</i> saved and
+ * restored across session serializations!
+ */
+ protected transient Principal principal = null;
+
+
+ /**
+ * The string manager for this package.
+ */
+ protected static StringManager sm =
+ StringManager.getManager("org.apache.coyote.servlet");
+
+
+ /**
+ * The HTTP session context associated with this session.
+ */
+ protected static HttpSessionContext sessionContext = null;
+
+
+ /**
+ * The property change support for this component. NOTE: This value
+ * is not included in the serialized version of this object.
+ */
+ protected transient PropertyChangeSupport support =
+ new PropertyChangeSupport(this);
+
+
+ /**
+ * The current accessed time for this session.
+ */
+ protected long thisAccessedTime = creationTime;
+
+
+ /**
+ * The access count for this session.
+ */
+ protected transient int accessCount = 0;
+
+
+ // ----------------------------------------------------- Session Properties
+
+
+ /**
+ * Return the authentication type used to authenticate our cached
+ * Principal, if any.
+ */
+ public String getAuthType() {
+
+ return (this.authType);
+
+ }
+
+
+ /**
+ * Set the authentication type used to authenticate our cached
+ * Principal, if any.
+ *
+ * @param authType The new cached authentication type
+ */
+ public void setAuthType(String authType) {
+
+ String oldAuthType = this.authType;
+ this.authType = authType;
+ support.firePropertyChange("authType", oldAuthType, this.authType);
+
+ }
+
+
+ /**
+ * Set the creation time for this session. This method is called by the
+ * Manager when an existing Session instance is reused.
+ *
+ * @param time The new creation time
+ */
+ public void setCreationTime(long time) {
+
+ this.creationTime = time;
+ this.lastAccessedTime = time;
+ this.thisAccessedTime = time;
+
+ }
+
+
+ /**
+ * Return the session identifier for this session.
+ */
+ public String getId() {
+
+ return (this.id);
+
+ }
+
+
+ /**
+ * Return the session identifier for this session.
+ */
+ public String getIdInternal() {
+
+ return (this.id);
+
+ }
+
+
+ /**
+ * Set the session identifier for this session.
+ *
+ * @param id The new session identifier
+ */
+ public void setId(String id) {
+
+ if ((this.id != null) && (manager != null))
+ manager.remove(this);
+
+ this.id = id;
+
+ if (manager != null)
+ manager.add(this);
+ tellNew();
+ }
+
+
+ /**
+ * Inform the listeners about the new session.
+ *
+ */
+ public void tellNew() {
+
+ // Notify interested session event listeners
+// fireSessionEvent(Session.SESSION_CREATED_EVENT, null);
+
+ // Notify interested application event listeners
+ ServletContextImpl context = (ServletContextImpl) manager.getContainer();
+ Object listeners[] = context.getApplicationLifecycleListeners();
+ if (listeners != null) {
+ HttpSessionEvent event =
+ new HttpSessionEvent(getSession());
+ for (int i = 0; i < listeners.length; i++) {
+ if (!(listeners[i] instanceof HttpSessionListener))
+ continue;
+ HttpSessionListener listener =
+ (HttpSessionListener) listeners[i];
+ try {
+ fireContainerEvent(context,
+ "beforeSessionCreated",
+ listener);
+ listener.sessionCreated(event);
+ fireContainerEvent(context,
+ "afterSessionCreated",
+ listener);
+ } catch (Throwable t) {
+ try {
+ fireContainerEvent(context,
+ "afterSessionCreated",
+ listener);
+ } catch (Exception e) {
+ ;
+ }
+ manager.getContainer().getLogger().error
+ (sm.getString("standardSession.sessionEvent"), t);
+ }
+ }
+ }
+
+ }
+
+
+ /**
+ * Return descriptive information about this Session implementation and
+ * the corresponding version number, in the format
+ * <code><description>/<version></code>.
+ */
+ public String getInfo() {
+
+ return (info);
+
+ }
+
+
+ /**
+ * Return the last time the client sent a request associated with this
+ * session, as the number of milliseconds since midnight, January 1, 1970
+ * GMT. Actions that your application takes, such as getting or setting
+ * a value associated with the session, do not affect the access time.
+ */
+ public long getLastAccessedTime() {
+
+ if ( !isValid() ) {
+ throw new IllegalStateException
+ (sm.getString("standardSession.getLastAccessedTime.ise"));
+ }
+ return (this.lastAccessedTime);
+
+ }
+
+
+ /**
+ * Return the Manager within which this Session is valid.
+ */
+ public SessionManager getManager() {
+
+ return (this.manager);
+
+ }
+
+
+ /**
+ * Set the Manager within which this Session is valid.
+ *
+ * @param manager The new Manager
+ */
+ public void setManager(SessionManager manager) {
+
+ this.manager = manager;
+
+ }
+
+
+ /**
+ * Return the maximum time interval, in seconds, between client requests
+ * before the servlet container will invalidate the session. A negative
+ * time indicates that the session should never time out.
+ */
+ public int getMaxInactiveInterval() {
+
+ return (this.maxInactiveInterval);
+
+ }
+
+
+ /**
+ * Set the maximum time interval, in seconds, between client requests
+ * before the servlet container will invalidate the session. A negative
+ * time indicates that the session should never time out.
+ *
+ * @param interval The new maximum interval
+ */
+ public void setMaxInactiveInterval(int interval) {
+
+ this.maxInactiveInterval = interval;
+ if (isValid && interval == 0) {
+ expire();
+ }
+
+ }
+
+
+ /**
+ * Set the <code>isNew</code> flag for this session.
+ *
+ * @param isNew The new value for the <code>isNew</code> flag
+ */
+ public void setNew(boolean isNew) {
+
+ this.isNew = isNew;
+
+ }
+
+
+ /**
+ * Return the authenticated Principal that is associated with this Session.
+ * This provides an <code>Authenticator</code> with a means to cache a
+ * previously authenticated Principal, and avoid potentially expensive
+ * <code>Realm.authenticate()</code> calls on every request. If there
+ * is no current associated Principal, return <code>null</code>.
+ */
+ public Principal getPrincipal() {
+
+ return (this.principal);
+
+ }
+
+
+ /**
+ * Set the authenticated Principal that is associated with this Session.
+ * This provides an <code>Authenticator</code> with a means to cache a
+ * previously authenticated Principal, and avoid potentially expensive
+ * <code>Realm.authenticate()</code> calls on every request.
+ *
+ * @param principal The new Principal, or <code>null</code> if none
+ */
+ public void setPrincipal(Principal principal) {
+
+ Principal oldPrincipal = this.principal;
+ this.principal = principal;
+ support.firePropertyChange("principal", oldPrincipal, this.principal);
+
+ }
+
+
+ /**
+ * Return the <code>HttpSession</code> for which this object
+ * is the facade.
+ */
+ public HttpSession getSession() {
+
+// if (facade == null){
+// if (SecurityUtil.isPackageProtectionEnabled()){
+// final StandardSession fsession = this;
+// facade = (StandardSessionFacade)AccessController.doPrivileged(new PrivilegedAction(){
+// public Object run(){
+// return new StandardSessionFacade(fsession);
+// }
+// });
+// } else {
+// facade = new StandardSessionFacade(this);
+// }
+// }
+// return (facade);
+
+ return this;
+ }
+
+
+ /**
+ * Return the <code>isValid</code> flag for this session.
+ */
+ public boolean isValid() {
+
+ if (this.expiring) {
+ return true;
+ }
+
+ if (!this.isValid ) {
+ return false;
+ }
+
+ if (accessCount > 0) {
+ return true;
+ }
+
+ if (maxInactiveInterval >= 0) {
+ long timeNow = System.currentTimeMillis();
+ int timeIdle = (int) ((timeNow - thisAccessedTime) / 1000L);
+ if (timeIdle >= maxInactiveInterval) {
+ expire(true);
+ }
+ }
+
+ return (this.isValid);
+ }
+
+
+ /**
+ * Set the <code>isValid</code> flag for this session.
+ *
+ * @param isValid The new value for the <code>isValid</code> flag
+ */
+ public void setValid(boolean isValid) {
+
+ this.isValid = isValid;
+ }
+
+
+ // ------------------------------------------------- Session Public Methods
+
+
+ /**
+ * Update the accessed time information for this session. This method
+ * should be called by the context when a request comes in for a particular
+ * session, even if the application does not reference it.
+ */
+ public void access() {
+
+ this.lastAccessedTime = this.thisAccessedTime;
+ this.thisAccessedTime = System.currentTimeMillis();
+
+ evaluateIfValid();
+
+ accessCount++;
+
+ }
+
+
+ /**
+ * End the access.
+ */
+ public void endAccess() {
+
+ isNew = false;
+ accessCount--;
+
+ }
+
+
+// /**
+// * Add a session event listener to this component.
+// */
+// public void addSessionListener(SessionListener listener) {
+//
+// listeners.add(listener);
+//
+// }
+
+
+ /**
+ * Perform the internal processing required to invalidate this session,
+ * without triggering an exception if the session has already expired.
+ */
+ public void expire() {
+
+ expire(true);
+
+ }
+
+
+ /**
+ * Perform the internal processing required to invalidate this session,
+ * without triggering an exception if the session has already expired.
+ *
+ * @param notify Should we notify listeners about the demise of
+ * this session?
+ */
+ public void expire(boolean notify) {
+
+ // Mark this session as "being expired" if needed
+ if (expiring)
+ return;
+
+ synchronized (this) {
+
+ if (manager == null)
+ return;
+
+ expiring = true;
+
+ // Notify interested application event listeners
+ // FIXME - Assumes we call listeners in reverse order
+ ServletContextImpl context = (ServletContextImpl) manager.getContainer();
+ Object listeners[] = context.getApplicationLifecycleListeners();
+ if (notify && (listeners != null)) {
+ HttpSessionEvent event =
+ new HttpSessionEvent(getSession());
+ for (int i = 0; i < listeners.length; i++) {
+ int j = (listeners.length - 1) - i;
+ if (!(listeners[j] instanceof HttpSessionListener))
+ continue;
+ HttpSessionListener listener =
+ (HttpSessionListener) listeners[j];
+ try {
+ fireContainerEvent(context,
+ "beforeSessionDestroyed",
+ listener);
+ listener.sessionDestroyed(event);
+ fireContainerEvent(context,
+ "afterSessionDestroyed",
+ listener);
+ } catch (Throwable t) {
+ try {
+ fireContainerEvent(context,
+ "afterSessionDestroyed",
+ listener);
+ } catch (Exception e) {
+ ;
+ }
+ manager.getContainer().getLogger().error
+ (sm.getString("standardSession.sessionEvent"), t);
+ }
+ }
+ }
+ accessCount = 0;
+ setValid(false);
+
+ /*
+ * Compute how long this session has been alive, and update
+ * session manager's related properties accordingly
+ */
+ long timeNow = System.currentTimeMillis();
+ int timeAlive = (int) ((timeNow - creationTime)/1000);
+ synchronized (manager) {
+ if (timeAlive > manager.getSessionMaxAliveTime()) {
+ manager.setSessionMaxAliveTime(timeAlive);
+ }
+ int numExpired = manager.getExpiredSessions();
+ numExpired++;
+ manager.setExpiredSessions(numExpired);
+ int average = manager.getSessionAverageAliveTime();
+ average = ((average * (numExpired-1)) + timeAlive)/numExpired;
+ manager.setSessionAverageAliveTime(average);
+ }
+
+ // Remove this session from our manager's active sessions
+ manager.remove(this);
+
+ // Notify interested session event listeners
+// if (notify) {
+// fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);
+// }
+
+ // We have completed expire of this session
+ expiring = false;
+
+ // Unbind any objects associated with this session
+ String keys[] = keys();
+ for (int i = 0; i < keys.length; i++)
+ removeAttributeInternal(keys[i], notify);
+
+ }
+
+ }
+
+
+ /**
+ * Perform the internal processing required to passivate
+ * this session.
+ */
+ public void passivate() {
+
+ // Notify interested session event listeners
+// fireSessionEvent(Session.SESSION_PASSIVATED_EVENT, null);
+
+ // Notify ActivationListeners
+ HttpSessionEvent event = null;
+ String keys[] = keys();
+ for (int i = 0; i < keys.length; i++) {
+ Object attribute = attributes.get(keys[i]);
+ if (attribute instanceof HttpSessionActivationListener) {
+ if (event == null)
+ event = new HttpSessionEvent(getSession());
+ try {
+ ((HttpSessionActivationListener)attribute)
+ .sessionWillPassivate(event);
+ } catch (Throwable t) {
+ manager.getContainer().getLogger().error
+ (sm.getString("standardSession.attributeEvent"), t);
+ }
+ }
+ }
+
+ }
+
+
+ /**
+ * Perform internal processing required to activate this
+ * session.
+ */
+ public void activate() {
+
+ // Notify interested session event listeners
+// fireSessionEvent(Session.SESSION_ACTIVATED_EVENT, null);
+
+ // Notify ActivationListeners
+ HttpSessionEvent event = null;
+ String keys[] = keys();
+ for (int i = 0; i < keys.length; i++) {
+ Object attribute = attributes.get(keys[i]);
+ if (attribute instanceof HttpSessionActivationListener) {
+ if (event == null)
+ event = new HttpSessionEvent(getSession());
+ try {
+ ((HttpSessionActivationListener)attribute)
+ .sessionDidActivate(event);
+ } catch (Throwable t) {
+ manager.getContainer().getLogger().error
+ (sm.getString("standardSession.attributeEvent"), t);
+ }
+ }
+ }
+
+ }
+
+
+ /**
+ * Return the object bound with the specified name to the internal notes
+ * for this session, or <code>null</code> if no such binding exists.
+ *
+ * @param name Name of the note to be returned
+ */
+ public Object getNote(String name) {
+
+ return (notes.get(name));
+
+ }
+
+
+ /**
+ * Return an Iterator containing the String names of all notes bindings
+ * that exist for this session.
+ */
+ public Iterator getNoteNames() {
+
+ return (notes.keySet().iterator());
+
+ }
+
+
+ /**
+ * Release all object references, and initialize instance variables, in
+ * preparation for reuse of this object.
+ */
+ public void recycle() {
+
+ // Reset the instance variables associated with this Session
+ attributes.clear();
+ setAuthType(null);
+ creationTime = 0L;
+ expiring = false;
+ id = null;
+ lastAccessedTime = 0L;
+ maxInactiveInterval = -1;
+ accessCount = 0;
+ notes.clear();
+ setPrincipal(null);
+ isNew = false;
+ isValid = false;
+ manager = null;
+
+ }
+
+
+ /**
+ * Remove any object bound to the specified name in the internal notes
+ * for this session.
+ *
+ * @param name Name of the note to be removed
+ */
+ public void removeNote(String name) {
+
+ notes.remove(name);
+
+ }
+
+
+// /**
+// * Remove a session event listener from this component.
+// */
+// public void removeSessionListener(SessionListener listener) {
+//
+// listeners.remove(listener);
+//
+// }
+
+
+ /**
+ * Bind an object to a specified name in the internal notes associated
+ * with this session, replacing any existing binding for this name.
+ *
+ * @param name Name to which the object should be bound
+ * @param value Object to be bound to the specified name
+ */
+ public void setNote(String name, Object value) {
+
+ notes.put(name, value);
+
+ }
+
+
+ /**
+ * Return a string representation of this object.
+ */
+ public String toString() {
+
+ StringBuffer sb = new StringBuffer();
+ sb.append("StandardSession[");
+ sb.append(id);
+ sb.append("]");
+ return (sb.toString());
+
+ }
+
+
+ // ------------------------------------------------ Session Package Methods
+
+
+ /**
+ * Read a serialized version of the contents of this session object from
+ * the specified object input stream, without requiring that the
+ * StandardSession itself have been serialized.
+ *
+ * @param stream The object input stream to read from
+ *
+ * @exception ClassNotFoundException if an unknown class is specified
+ * @exception IOException if an input/output error occurs
+ */
+ public void readObjectData(ObjectInputStream stream)
+ throws ClassNotFoundException, IOException {
+
+ readObject(stream);
+
+ }
+
+
+ /**
+ * Write a serialized version of the contents of this session object to
+ * the specified object output stream, without requiring that the
+ * StandardSession itself have been serialized.
+ *
+ * @param stream The object output stream to write to
+ *
+ * @exception IOException if an input/output error occurs
+ */
+ public void writeObjectData(ObjectOutputStream stream)
+ throws IOException {
+
+ writeObject(stream);
+
+ }
+
+
+ // ------------------------------------------------- HttpSession Properties
+
+
+ /**
+ * Return the time when this session was created, in milliseconds since
+ * midnight, January 1, 1970 GMT.
+ *
+ * @exception IllegalStateException if this method is called on an
+ * invalidated session
+ */
+ public long getCreationTime() {
+
+ if (!isValid())
+ throw new IllegalStateException
+ (sm.getString("standardSession.getCreationTime.ise"));
+
+ return (this.creationTime);
+
+ }
+
+
+ /**
+ * Return the ServletContext to which this session belongs.
+ */
+ public ServletContext getServletContext() {
+
+ if (manager == null)
+ return (null);
+ ServletContextImpl context = (ServletContextImpl) manager.getContainer();
+ if (context == null)
+ return (null);
+ else
+ return (context.getServletContext());
+
+ }
+
+
+ /**
+ * Return the session context with which this session is associated.
+ *
+ * @deprecated As of Version 2.1, this method is deprecated and has no
+ * replacement. It will be removed in a future version of the
+ * Java Servlet API.
+ */
+ public HttpSessionContext getSessionContext() {
+
+ if (sessionContext == null)
+ sessionContext = new StandardSessionContext();
+ return (sessionContext);
+
+ }
+
+
+ // ----------------------------------------------HttpSession Public Methods
+
+
+ /**
+ * Return the object bound with the specified name in this session, or
+ * <code>null</code> if no object is bound with that name.
+ *
+ * @param name Name of the attribute to be returned
+ *
+ * @exception IllegalStateException if this method is called on an
+ * invalidated session
+ */
+ public Object getAttribute(String name) {
+
+ if (!isValid())
+ throw new IllegalStateException
+ (sm.getString("standardSession.getAttribute.ise"));
+
+ return (attributes.get(name));
+
+ }
+
+
+ /**
+ * Return an <code>Enumeration</code> of <code>String</code> objects
+ * containing the names of the objects bound to this session.
+ *
+ * @exception IllegalStateException if this method is called on an
+ * invalidated session
+ */
+ public Enumeration getAttributeNames() {
+
+ if (!isValid())
+ throw new IllegalStateException
+ (sm.getString("standardSession.getAttributeNames.ise"));
+
+ return (new Enumerator(attributes.keySet(), true));
+
+ }
+
+
+ /**
+ * Return the object bound with the specified name in this session, or
+ * <code>null</code> if no object is bound with that name.
+ *
+ * @param name Name of the value to be returned
+ *
+ * @exception IllegalStateException if this method is called on an
+ * invalidated session
+ *
+ * @deprecated As of Version 2.2, this method is replaced by
+ * <code>getAttribute()</code>
+ */
+ public Object getValue(String name) {
+
+ return (getAttribute(name));
+
+ }
+
+
+ /**
+ * Return the set of names of objects bound to this session. If there
+ * are no such objects, a zero-length array is returned.
+ *
+ * @exception IllegalStateException if this method is called on an
+ * invalidated session
+ *
+ * @deprecated As of Version 2.2, this method is replaced by
+ * <code>getAttributeNames()</code>
+ */
+ public String[] getValueNames() {
+
+ if (!isValid())
+ throw new IllegalStateException
+ (sm.getString("standardSession.getValueNames.ise"));
+
+ return (keys());
+
+ }
+
+
+ /**
+ * Invalidates this session and unbinds any objects bound to it.
+ *
+ * @exception IllegalStateException if this method is called on
+ * an invalidated session
+ */
+ public void invalidate() {
+
+ if (!isValid())
+ throw new IllegalStateException
+ (sm.getString("standardSession.invalidate.ise"));
+
+ // Cause this session to expire
+ expire();
+
+ }
+
+
+ /**
+ * Return <code>true</code> if the client does not yet know about the
+ * session, or if the client chooses not to join the session. For
+ * example, if the server used only cookie-based sessions, and the client
+ * has disabled the use of cookies, then a session would be new on each
+ * request.
+ *
+ * @exception IllegalStateException if this method is called on an
+ * invalidated session
+ */
+ public boolean isNew() {
+
+ if (!isValid())
+ throw new IllegalStateException
+ (sm.getString("standardSession.isNew.ise"));
+
+ return (this.isNew);
+
+ }
+
+
+
+ /**
+ * Bind an object to this session, using the specified name. If an object
+ * of the same name is already bound to this session, the object is
+ * replaced.
+ * <p>
+ * After this method executes, and if the object implements
+ * <code>HttpSessionBindingListener</code>, the container calls
+ * <code>valueBound()</code> on the object.
+ *
+ * @param name Name to which the object is bound, cannot be null
+ * @param value Object to be bound, cannot be null
+ *
+ * @exception IllegalStateException if this method is called on an
+ * invalidated session
+ *
+ * @deprecated As of Version 2.2, this method is replaced by
+ * <code>setAttribute()</code>
+ */
+ public void putValue(String name, Object value) {
+
+ setAttribute(name, value);
+
+ }
+
+
+ /**
+ * Remove the object bound with the specified name from this session. If
+ * the session does not have an object bound with this name, this method
+ * does nothing.
+ * <p>
+ * After this method executes, and if the object implements
+ * <code>HttpSessionBindingListener</code>, the container calls
+ * <code>valueUnbound()</code> on the object.
+ *
+ * @param name Name of the object to remove from this session.
+ *
+ * @exception IllegalStateException if this method is called on an
+ * invalidated session
+ */
+ public void removeAttribute(String name) {
+
+ removeAttribute(name, true);
+
+ }
+
+
+ /**
+ * Remove the object bound with the specified name from this session. If
+ * the session does not have an object bound with this name, this method
+ * does nothing.
+ * <p>
+ * After this method executes, and if the object implements
+ * <code>HttpSessionBindingListener</code>, the container calls
+ * <code>valueUnbound()</code> on the object.
+ *
+ * @param name Name of the object to remove from this session.
+ * @param notify Should we notify interested listeners that this
+ * attribute is being removed?
+ *
+ * @exception IllegalStateException if this method is called on an
+ * invalidated session
+ */
+ public void removeAttribute(String name, boolean notify) {
+
+ // Validate our current state
+ if (!isValid())
+ throw new IllegalStateException
+ (sm.getString("standardSession.removeAttribute.ise"));
+
+ removeAttributeInternal(name, notify);
+
+ }
+
+
+ /**
+ * Remove the object bound with the specified name from this session. If
+ * the session does not have an object bound with this name, this method
+ * does nothing.
+ * <p>
+ * After this method executes, and if the object implements
+ * <code>HttpSessionBindingListener</code>, the container calls
+ * <code>valueUnbound()</code> on the object.
+ *
+ * @param name Name of the object to remove from this session.
+ *
+ * @exception IllegalStateException if this method is called on an
+ * invalidated session
+ *
+ * @deprecated As of Version 2.2, this method is replaced by
+ * <code>removeAttribute()</code>
+ */
+ public void removeValue(String name) {
+
+ removeAttribute(name);
+
+ }
+
+
+ /**
+ * Bind an object to this session, using the specified name. If an object
+ * of the same name is already bound to this session, the object is
+ * replaced.
+ * <p>
+ * After this method executes, and if the object implements
+ * <code>HttpSessionBindingListener</code>, the container calls
+ * <code>valueBound()</code> on the object.
+ *
+ * @param name Name to which the object is bound, cannot be null
+ * @param value Object to be bound, cannot be null
+ *
+ * @exception IllegalArgumentException if an attempt is made to add a
+ * non-serializable object in an environment marked distributable.
+ * @exception IllegalStateException if this method is called on an
+ * invalidated session
+ */
+ public void setAttribute(String name, Object value) {
+
+ // Name cannot be null
+ if (name == null)
+ throw new IllegalArgumentException
+ (sm.getString("standardSession.setAttribute.namenull"));
+
+ // Null value is the same as removeAttribute()
+ if (value == null) {
+ removeAttribute(name);
+ return;
+ }
+
+ // Validate our current state
+ if (!isValid())
+ throw new IllegalStateException
+ (sm.getString("standardSession.setAttribute.ise"));
+ if ((manager != null) && manager.getDistributable() &&
+ !(value instanceof Serializable))
+ throw new IllegalArgumentException
+ (sm.getString("standardSession.setAttribute.iae"));
+
+ // Construct an event with the new value
+ HttpSessionBindingEvent event = null;
+
+ // Call the valueBound() method if necessary
+ if (value instanceof HttpSessionBindingListener) {
+ // Don't call any notification if replacing with the same value
+ Object oldValue = attributes.get(name);
+ if (value != oldValue) {
+ event = new HttpSessionBindingEvent(getSession(), name, value);
+ try {
+ ((HttpSessionBindingListener) value).valueBound(event);
+ } catch (Throwable t){
+ manager.getContainer().getLogger().error
+ (sm.getString("standardSession.bindingEvent"), t);
+ }
+ }
+ }
+
+ // Replace or add this attribute
+ Object unbound = attributes.put(name, value);
+
+ // Call the valueUnbound() method if necessary
+ if ((unbound != null) && (unbound != value) &&
+ (unbound instanceof HttpSessionBindingListener)) {
+ try {
+ ((HttpSessionBindingListener) unbound).valueUnbound
+ (new HttpSessionBindingEvent(getSession(), name));
+ } catch (Throwable t) {
+ manager.getContainer().getLogger().error
+ (sm.getString("standardSession.bindingEvent"), t);
+ }
+ }
+
+ // Notify interested application event listeners
+ ServletContextImpl context = (ServletContextImpl) manager.getContainer();
+ Object listeners[] = context.getApplicationEventListeners();
+ if (listeners == null)
+ return;
+ for (int i = 0; i < listeners.length; i++) {
+ if (!(listeners[i] instanceof HttpSessionAttributeListener))
+ continue;
+ HttpSessionAttributeListener listener =
+ (HttpSessionAttributeListener) listeners[i];
+ try {
+ if (unbound != null) {
+ fireContainerEvent(context,
+ "beforeSessionAttributeReplaced",
+ listener);
+ if (event == null) {
+ event = new HttpSessionBindingEvent
+ (getSession(), name, unbound);
+ }
+ listener.attributeReplaced(event);
+ fireContainerEvent(context,
+ "afterSessionAttributeReplaced",
+ listener);
+ } else {
+ fireContainerEvent(context,
+ "beforeSessionAttributeAdded",
+ listener);
+ if (event == null) {
+ event = new HttpSessionBindingEvent
+ (getSession(), name, value);
+ }
+ listener.attributeAdded(event);
+ fireContainerEvent(context,
+ "afterSessionAttributeAdded",
+ listener);
+ }
+ } catch (Throwable t) {
+ try {
+ if (unbound != null) {
+ fireContainerEvent(context,
+ "afterSessionAttributeReplaced",
+ listener);
+ } else {
+ fireContainerEvent(context,
+ "afterSessionAttributeAdded",
+ listener);
+ }
+ } catch (Exception e) {
+ ;
+ }
+ manager.getContainer().getLogger().error
+ (sm.getString("standardSession.attributeEvent"), t);
+ }
+ }
+
+ }
+
+
+ // ------------------------------------------ HttpSession Protected Methods
+
+
+ /**
+ * Read a serialized version of this session object from the specified
+ * object input stream.
+ * <p>
+ * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager
+ * is not restored by this method, and must be set explicitly.
+ *
+ * @param stream The input stream to read from
+ *
+ * @exception ClassNotFoundException if an unknown class is specified
+ * @exception IOException if an input/output error occurs
+ */
+ private void readObject(ObjectInputStream stream)
+ throws ClassNotFoundException, IOException {
+
+ // Deserialize the scalar instance variables (except Manager)
+ authType = null; // Transient only
+ creationTime = ((Long) stream.readObject()).longValue();
+ lastAccessedTime = ((Long) stream.readObject()).longValue();
+ maxInactiveInterval = ((Integer) stream.readObject()).intValue();
+ isNew = ((Boolean) stream.readObject()).booleanValue();
+ isValid = ((Boolean) stream.readObject()).booleanValue();
+ thisAccessedTime = ((Long) stream.readObject()).longValue();
+ principal = null; // Transient only
+ // setId((String) stream.readObject());
+ id = (String) stream.readObject();
+ if (manager.getContainer().getLogger().isDebugEnabled())
+ manager.getContainer().getLogger().debug
+ ("readObject() loading session " + id);
+
+ // Deserialize the attribute count and attribute values
+ if (attributes == null)
+ attributes = new Hashtable();
+ int n = ((Integer) stream.readObject()).intValue();
+ boolean isValidSave = isValid;
+ isValid = true;
+ for (int i = 0; i < n; i++) {
+ String name = (String) stream.readObject();
+ Object value = (Object) stream.readObject();
+ if ((value instanceof String) && (value.equals(NOT_SERIALIZED)))
+ continue;
+ if (manager.getContainer().getLogger().isDebugEnabled())
+ manager.getContainer().getLogger().debug(" loading attribute '" + name +
+ "' with value '" + value + "'");
+ attributes.put(name, value);
+ }
+ isValid = isValidSave;
+
+ if (listeners == null) {
+ listeners = new ArrayList();
+ }
+
+ if (notes == null) {
+ notes = new Hashtable();
+ }
+ }
+
+
+ /**
+ * Write a serialized version of this session object to the specified
+ * object output stream.
+ * <p>
+ * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored
+ * in the serialized representation of this Session. After calling
+ * <code>readObject()</code>, you must set the associated Manager
+ * explicitly.
+ * <p>
+ * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable
+ * will be unbound from the session, with appropriate actions if it
+ * implements HttpSessionBindingListener. If you do not want any such
+ * attributes, be sure the <code>distributable</code> property of the
+ * associated Manager is set to <code>true</code>.
+ *
+ * @param stream The output stream to write to
+ *
+ * @exception IOException if an input/output error occurs
+ */
+ private void writeObject(ObjectOutputStream stream) throws IOException {
+
+ // Write the scalar instance variables (except Manager)
+ stream.writeObject(new Long(creationTime));
+ stream.writeObject(new Long(lastAccessedTime));
+ stream.writeObject(new Integer(maxInactiveInterval));
+ stream.writeObject(new Boolean(isNew));
+ stream.writeObject(new Boolean(isValid));
+ stream.writeObject(new Long(thisAccessedTime));
+ stream.writeObject(id);
+ if (manager.getContainer().getLogger().isDebugEnabled())
+ manager.getContainer().getLogger().debug
+ ("writeObject() storing session " + id);
+
+ // Accumulate the names of serializable and non-serializable attributes
+ String keys[] = keys();
+ ArrayList saveNames = new ArrayList();
+ ArrayList saveValues = new ArrayList();
+ for (int i = 0; i < keys.length; i++) {
+ Object value = attributes.get(keys[i]);
+ if (value == null)
+ continue;
+ else if ( (value instanceof Serializable)
+ && (!exclude(keys[i]) )) {
+ saveNames.add(keys[i]);
+ saveValues.add(value);
+ } else {
+ removeAttributeInternal(keys[i], true);
+ }
+ }
+
+ // Serialize the attribute count and the Serializable attributes
+ int n = saveNames.size();
+ stream.writeObject(new Integer(n));
+ for (int i = 0; i < n; i++) {
+ stream.writeObject((String) saveNames.get(i));
+ try {
+ stream.writeObject(saveValues.get(i));
+ if (manager.getContainer().getLogger().isDebugEnabled())
+ manager.getContainer().getLogger().debug
+ (" storing attribute '" + saveNames.get(i) +
+ "' with value '" + saveValues.get(i) + "'");
+ } catch (NotSerializableException e) {
+ manager.getContainer().getLogger().warn
+ (sm.getString("standardSession.notSerializable",
+ saveNames.get(i), id), e);
+ stream.writeObject(NOT_SERIALIZED);
+ if (manager.getContainer().getLogger().isDebugEnabled())
+ manager.getContainer().getLogger().debug
+ (" storing attribute '" + saveNames.get(i) +
+ "' with value NOT_SERIALIZED");
+ }
+ }
+
+ }
+
+
+ /**
+ * Exclude attribute that cannot be serialized.
+ * @param name the attribute's name
+ */
+ protected boolean exclude(String name){
+
+ for (int i = 0; i < excludedAttributes.length; i++) {
+ if (name.equalsIgnoreCase(excludedAttributes[i]))
+ return true;
+ }
+
+ return false;
+ }
+
+
+ protected void evaluateIfValid() {
+ /*
+ * If this session has expired or is in the process of expiring or
+ * will never expire, return
+ */
+ if (!this.isValid || expiring || maxInactiveInterval < 0)
+ return;
+
+ isValid();
+
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * Fire container events if the Context implementation is the
+ * <code>org.apache.catalina.core.StandardContext</code>.
+ *
+ * @param context Context for which to fire events
+ * @param type Event type
+ * @param data Event data
+ *
+ * @exception Exception occurred during event firing
+ */
+ protected void fireContainerEvent(ServletContextImpl context,
+ String type, Object data)
+ throws Exception {
+
+ if (!"org.apache.catalina.core.StandardContext".equals
+ (context.getClass().getName())) {
+ return; // Container events are not supported
+ }
+ // NOTE: Race condition is harmless, so do not synchronize
+ if (containerEventMethod == null) {
+ containerEventMethod =
+ context.getClass().getMethod("fireContainerEvent",
+ containerEventTypes);
+ }
+ Object containerEventParams[] = new Object[2];
+ containerEventParams[0] = type;
+ containerEventParams[1] = data;
+ containerEventMethod.invoke(context, containerEventParams);
+
+ }
+
+
+
+// /**
+// * Notify all session event listeners that a particular event has
+// * occurred for this Session. The default implementation performs
+// * this notification synchronously using the calling thread.
+// *
+// * @param type Event type
+// * @param data Event data
+// */
+// public void fireSessionEvent(String type, Object data) {
+// if (listeners.size() < 1)
+// return;
+// SessionEvent event = new SessionEvent(this, type, data);
+// SessionListener list[] = new SessionListener[0];
+// synchronized (listeners) {
+// list = (SessionListener[]) listeners.toArray(list);
+// }
+//
+// for (int i = 0; i < list.length; i++){
+// ((SessionListener) list[i]).sessionEvent(event);
+// }
+//
+// }
+
+
+ /**
+ * Return the names of all currently defined session attributes
+ * as an array of Strings. If there are no defined attributes, a
+ * zero-length array is returned.
+ */
+ protected String[] keys() {
+
+ return ((String[]) attributes.keySet().toArray(EMPTY_ARRAY));
+
+ }
+
+
+ /**
+ * Remove the object bound with the specified name from this session. If
+ * the session does not have an object bound with this name, this method
+ * does nothing.
+ * <p>
+ * After this method executes, and if the object implements
+ * <code>HttpSessionBindingListener</code>, the container calls
+ * <code>valueUnbound()</code> on the object.
+ *
+ * @param name Name of the object to remove from this session.
+ * @param notify Should we notify interested listeners that this
+ * attribute is being removed?
+ */
+ protected void removeAttributeInternal(String name, boolean notify) {
+
+ // Remove this attribute from our collection
+ Object value = attributes.remove(name);
+
+ // Do we need to do valueUnbound() and attributeRemoved() notification?
+ if (!notify || (value == null)) {
+ return;
+ }
+
+ // Call the valueUnbound() method if necessary
+ HttpSessionBindingEvent event = null;
+ if (value instanceof HttpSessionBindingListener) {
+ event = new HttpSessionBindingEvent(getSession(), name, value);
+ ((HttpSessionBindingListener) value).valueUnbound(event);
+ }
+
+ // Notify interested application event listeners
+ ServletContextImpl context = (ServletContextImpl) manager.getContainer();
+ Object listeners[] = context.getApplicationEventListeners();
+ if (listeners == null)
+ return;
+ for (int i = 0; i < listeners.length; i++) {
+ if (!(listeners[i] instanceof HttpSessionAttributeListener))
+ continue;
+ HttpSessionAttributeListener listener =
+ (HttpSessionAttributeListener) listeners[i];
+ try {
+ fireContainerEvent(context,
+ "beforeSessionAttributeRemoved",
+ listener);
+ if (event == null) {
+ event = new HttpSessionBindingEvent
+ (getSession(), name, value);
+ }
+ listener.attributeRemoved(event);
+ fireContainerEvent(context,
+ "afterSessionAttributeRemoved",
+ listener);
+ } catch (Throwable t) {
+ try {
+ fireContainerEvent(context,
+ "afterSessionAttributeRemoved",
+ listener);
+ } catch (Exception e) {
+ ;
+ }
+ manager.getContainer().getLogger().error
+ (sm.getString("standardSession.attributeEvent"), t);
+ }
+ }
+
+ }
+
+
+}
+
+
+// ------------------------------------------------------------ Protected Class
+
+
+/**
+ * This class is a dummy implementation of the <code>HttpSessionContext</code>
+ * interface, to conform to the requirement that such an object be returned
+ * when <code>HttpSession.getSessionContext()</code> is called.
+ *
+ * @author Craig R. McClanahan
+ *
+ * @deprecated As of Java Servlet API 2.1 with no replacement. The
+ * interface will be removed in a future version of this API.
+ */
+
+final class StandardSessionContext implements HttpSessionContext {
+
+
+ protected HashMap dummy = new HashMap();
+
+ /**
+ * Return the session identifiers of all sessions defined
+ * within this context.
+ *
+ * @deprecated As of Java Servlet API 2.1 with no replacement.
+ * This method must return an empty <code>Enumeration</code>
+ * and will be removed in a future version of the API.
+ */
+ public Enumeration getIds() {
+
+ return (new Enumerator(dummy));
+
+ }
+
+
+ /**
+ * Return the <code>HttpSession</code> associated with the
+ * specified session identifier.
+ *
+ * @param id Session identifier for which to look up a session
+ *
+ * @deprecated As of Java Servlet API 2.1 with no replacement.
+ * This method must return null and will be removed in a
+ * future version of the API.
+ */
+ public HttpSession getSession(String id) {
+
+ return (null);
+
+ }
+
+
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org