You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2006/10/24 04:45:59 UTC

svn commit: r467206 [28/30] - in /tomcat: build/tc5.5.x/ connectors/trunk/ connectors/trunk/ajp/ajplib/test/ connectors/trunk/ajp/proxy/ connectors/trunk/jk/jkstatus/src/share/org/apache/jk/status/ connectors/trunk/jk/native/iis/ connectors/trunk/jk/na...

Modified: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/session/SimpleTcpReplicationManager.java
URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/session/SimpleTcpReplicationManager.java?view=diff&rev=467206&r1=467205&r2=467206
==============================================================================
--- tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/session/SimpleTcpReplicationManager.java (original)
+++ tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/session/SimpleTcpReplicationManager.java Mon Oct 23 19:45:46 2006
@@ -1,691 +1,691 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.catalina.ha.session;
-
-import java.io.IOException;
-
-import org.apache.catalina.LifecycleException;
-import org.apache.catalina.Session;
-import org.apache.catalina.ha.CatalinaCluster;
-import org.apache.catalina.ha.ClusterManager;
-import org.apache.catalina.ha.ClusterMessage;
-import org.apache.catalina.tribes.Member;
-import org.apache.catalina.realm.GenericPrincipal;
-import org.apache.catalina.session.StandardManager;
-import org.apache.catalina.tribes.io.ReplicationStream;
-import java.io.ByteArrayInputStream;
-import org.apache.catalina.Loader;
-
-/**
- * Title:        Tomcat Session Replication for Tomcat 4.0 <BR>
- * Description:  A very simple straight forward implementation of
- *               session replication of servers in a cluster.<BR>
- *               This session replication is implemented "live". By live
- *               I mean, when a session attribute is added into a session on Node A
- *               a message is broadcasted to other messages and setAttribute is called on the
- *               replicated sessions.<BR>
- *               A full description of this implementation can be found under
- *               <href="http://www.filip.net/tomcat/">Filip's Tomcat Page</a><BR>
- *
- * Copyright:    See apache license
- * Company:      www.filip.net
- * @author  <a href="mailto:mail@filip.net">Filip Hanik</a>
- * @author Bela Ban (modifications for synchronous replication)
- * @version 1.0 for TC 4.0
- * Description: The InMemoryReplicationManager is a session manager that replicated
- * session information in memory. It uses <a href="www.javagroups.com">JavaGroups</a> as
- * a communication protocol to ensure guaranteed and ordered message delivery.
- * JavaGroups also provides a very flexible protocol stack to ensure that the replication
- * can be used in any environment.
- * <BR><BR>
- * The InMemoryReplicationManager extends the StandardManager hence it allows for us
- * to inherit all the basic session management features like expiration, session listeners etc
- * <BR><BR>
- * To communicate with other nodes in the cluster, the InMemoryReplicationManager sends out 7 different type of multicast messages
- * all defined in the SessionMessage class.<BR>
- * When a session is replicated (not an attribute added/removed) the session is serialized into
- * a byte array using the StandardSession.readObjectData, StandardSession.writeObjectData methods.
- */
-public class SimpleTcpReplicationManager extends StandardManager implements ClusterManager
-{
-    public static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog( SimpleTcpReplicationManager.class );
-
-    //the channel configuration
-    protected String mChannelConfig = null;
-
-    //the group name
-    protected String mGroupName = "TomcatReplication";
-
-    //somehow start() gets called more than once
-    protected boolean mChannelStarted = false;
-
-    //log to screen
-    protected boolean mPrintToScreen = true;
-
-    protected boolean defaultMode = false;
-
-    protected boolean mManagerRunning = false;
-
-    /** Use synchronous rather than asynchronous replication. Every session modification (creation, change, removal etc)
-     * will be sent to all members. The call will then wait for max milliseconds, or forever (if timeout is 0) for
-     * all responses.
-     */
-    protected boolean synchronousReplication=true;
-
-    /** Set to true if we don't want the sessions to expire on shutdown */
-    protected boolean mExpireSessionsOnShutdown = true;
-
-    protected boolean useDirtyFlag = false;
-
-    protected String name;
-
-    protected boolean distributable = true;
-
-    protected CatalinaCluster cluster;
-
-    protected java.util.HashMap invalidatedSessions = new java.util.HashMap();
-
-    /**
-     * Flag to keep track if the state has been transferred or not
-     * Assumes false.
-     */
-    protected boolean stateTransferred = false;
-    private boolean notifyListenersOnReplication;
-    private boolean sendClusterDomainOnly = true ;
-
-    /**
-     * Constructor, just calls super()
-     *
-     */
-    public SimpleTcpReplicationManager()
-    {
-        super();
-    }
-
-    public boolean isSendClusterDomainOnly() {
-        return sendClusterDomainOnly;
-    }
-    
-    /**
-     * @param sendClusterDomainOnly The sendClusterDomainOnly to set.
-     */
-    public void setSendClusterDomainOnly(boolean sendClusterDomainOnly) {
-        this.sendClusterDomainOnly = sendClusterDomainOnly;
-    }
-  
-    /**
-     * @return Returns the defaultMode.
-     */
-    public boolean isDefaultMode() {
-        return defaultMode;
-    }
-    /**
-     * @param defaultMode The defaultMode to set.
-     */
-    public void setDefaultMode(boolean defaultMode) {
-        this.defaultMode = defaultMode;
-    }
-    
-    public boolean isManagerRunning()
-    {
-        return mManagerRunning;
-    }
-
-    public void setUseDirtyFlag(boolean usedirtyflag)
-    {
-        this.useDirtyFlag = usedirtyflag;
-    }
-
-    public void setExpireSessionsOnShutdown(boolean expireSessionsOnShutdown)
-    {
-        mExpireSessionsOnShutdown = expireSessionsOnShutdown;
-    }
-
-    public void setCluster(CatalinaCluster cluster) {
-        if(log.isDebugEnabled())
-            log.debug("Cluster associated with SimpleTcpReplicationManager");
-        this.cluster = cluster;
-    }
-
-    public boolean getExpireSessionsOnShutdown()
-    {
-        return mExpireSessionsOnShutdown;
-    }
-
-    public void setPrintToScreen(boolean printtoscreen)
-    {
-        if(log.isDebugEnabled())
-            log.debug("Setting screen debug to:"+printtoscreen);
-        mPrintToScreen = printtoscreen;
-    }
-
-    public void setSynchronousReplication(boolean flag)
-    {
-        synchronousReplication=flag;
-    }
-
-    /**
-     * Override persistence since they don't go hand in hand with replication for now.
-     */
-    public void unload() throws IOException {
-        if ( !getDistributable() ) {
-            super.unload();
-        }
-    }
-
-    /**
-     * Creates a HTTP session.
-     * Most of the code in here is copied from the StandardManager.
-     * This is not pretty, yeah I know, but it was necessary since the
-     * StandardManager had hard coded the session instantiation to the a
-     * StandardSession, when we actually want to instantiate a ReplicatedSession<BR>
-     * If the call comes from the Tomcat servlet engine, a SessionMessage goes out to the other
-     * nodes in the cluster that this session has been created.
-     * @param notify - if set to true the other nodes in the cluster will be notified.
-     *                 This flag is needed so that we can create a session before we deserialize
-     *                 a replicated one
-     *
-     * @see ReplicatedSession
-     */
-    protected Session createSession(String sessionId, boolean notify, boolean setId)
-    {
-
-        //inherited from the basic manager
-        if ((getMaxActiveSessions() >= 0) &&
-           (sessions.size() >= getMaxActiveSessions()))
-            throw new IllegalStateException(sm.getString("standardManager.createSession.ise"));
-
-
-        Session session = new ReplicatedSession(this);
-
-        // Initialize the properties of the new session and return it
-        session.setNew(true);
-        session.setValid(true);
-        session.setCreationTime(System.currentTimeMillis());
-        session.setMaxInactiveInterval(this.maxInactiveInterval);
-        if(sessionId == null)
-            sessionId = generateSessionId();
-        if ( setId ) session.setId(sessionId);
-        if ( notify && (cluster!=null) ) {
-            ((ReplicatedSession)session).setIsDirty(true);
-        }
-        return (session);
-    }//createSession
-
-    //=========================================================================
-    // OVERRIDE THESE METHODS TO IMPLEMENT THE REPLICATION
-    //=========================================================================
-
-    /**
-     * Construct and return a new session object, based on the default
-     * settings specified by this Manager's properties.  The session
-     * id will be assigned by this method, and available via the getId()
-     * method of the returned session.  If a new session cannot be created
-     * for any reason, return <code>null</code>.
-     *
-     * @exception IllegalStateException if a new session cannot be
-     *  instantiated for any reason
-     */
-    public Session createSession(String sessionId)
-    {
-        //create a session and notify the other nodes in the cluster
-        Session session =  createSession(sessionId,getDistributable(),true);
-        add(session);
-        return session;
-    }
-
-    public void sessionInvalidated(String sessionId) {
-        synchronized ( invalidatedSessions ) {
-            invalidatedSessions.put(sessionId, sessionId);
-        }
-    }
-
-    public String[] getInvalidatedSessions() {
-        synchronized ( invalidatedSessions ) {
-            String[] result = new String[invalidatedSessions.size()];
-            invalidatedSessions.values().toArray(result);
-            return result;
-        }
-
-    }
-
-    public ClusterMessage requestCompleted(String sessionId)
-    {
-        if (  !getDistributable() ) {
-            log.warn("Received requestCompleted message, although this context["+
-                     getName()+"] is not distributable. Ignoring message");
-            return null;
-        }
-        //notify javagroups
-        try
-        {
-            if ( invalidatedSessions.get(sessionId) != null ) {
-                synchronized ( invalidatedSessions ) {
-                    invalidatedSessions.remove(sessionId);
-                    SessionMessage msg = new SessionMessageImpl(name,
-                    SessionMessage.EVT_SESSION_EXPIRED,
-                    null,
-                    sessionId,
-                    sessionId);
-                return msg;
-                }
-            } else {
-                ReplicatedSession session = (ReplicatedSession) findSession(
-                    sessionId);
-                if (session != null) {
-                    //return immediately if the session is not dirty
-                    if (useDirtyFlag && (!session.isDirty())) {
-                        //but before we return doing nothing,
-                        //see if we should send
-                        //an updated last access message so that
-                        //sessions across cluster dont expire
-                        long interval = session.getMaxInactiveInterval();
-                        long lastaccdist = System.currentTimeMillis() -
-                            session.getLastAccessWasDistributed();
-                        if ( ((interval*1000) / lastaccdist)< 3 ) {
-                            SessionMessage accmsg = new SessionMessageImpl(name,
-                                SessionMessage.EVT_SESSION_ACCESSED,
-                                null,
-                                sessionId,
-                                sessionId);
-                            session.setLastAccessWasDistributed(System.currentTimeMillis());
-                            return accmsg;
-                        }
-                        return null;
-                    }
-
-                    session.setIsDirty(false);
-                    if (log.isDebugEnabled()) {
-                        try {
-                            log.debug("Sending session to cluster=" + session);
-                        }
-                        catch (Exception ignore) {}
-                    }
-                    SessionMessage msg = new SessionMessageImpl(name,
-                        SessionMessage.EVT_SESSION_CREATED,
-                        writeSession(session),
-                        session.getIdInternal(),
-                        session.getIdInternal());
-                    return msg;
-                } //end if
-            }//end if
-        }
-        catch (Exception x )
-        {
-            log.error("Unable to replicate session",x);
-        }
-        return null;
-    }
-
-    /**
-     * Serialize a session into a byte array<BR>
-     * This method simple calls the writeObjectData method on the session
-     * and returns the byte data from that call
-     * @param session - the session to be serialized
-     * @return a byte array containing the session data, null if the serialization failed
-     */
-    protected byte[] writeSession( Session session )
-    {
-        try
-        {
-            java.io.ByteArrayOutputStream session_data = new java.io.ByteArrayOutputStream();
-            java.io.ObjectOutputStream session_out = new java.io.ObjectOutputStream(session_data);
-            session_out.flush();
-            boolean hasPrincipal = session.getPrincipal() != null;
-            session_out.writeBoolean(hasPrincipal);
-            if ( hasPrincipal )
-            {
-                session_out.writeObject(SerializablePrincipal.createPrincipal((GenericPrincipal)session.getPrincipal()));
-            }//end if
-            ((ReplicatedSession)session).writeObjectData(session_out);
-            return session_data.toByteArray();
-
-        }
-        catch ( Exception x )
-        {
-            log.error("Failed to serialize the session!",x);
-        }
-        return null;
-    }
-    
-    /**
-     * Open Stream and use correct ClassLoader (Container) Switch
-     * ThreadClassLoader
-     * 
-     * @param data
-     * @return The object input stream
-     * @throws IOException
-     */
-    public ReplicationStream getReplicationStream(byte[] data) throws IOException {
-        return getReplicationStream(data,0,data.length);
-    }
-    
-    public ReplicationStream getReplicationStream(byte[] data, int offset, int length) throws IOException {
-        ByteArrayInputStream fis =null;
-        ReplicationStream ois = null;
-        Loader loader = null;
-        ClassLoader classLoader = null;
-        //fix to be able to run the DeltaManager
-        //stand alone without a container.
-        //use the Threads context class loader
-        if (container != null)
-            loader = container.getLoader();
-        if (loader != null)
-            classLoader = loader.getClassLoader();
-        else
-            classLoader = Thread.currentThread().getContextClassLoader();
-        //end fix
-        fis = new ByteArrayInputStream(data, offset, length);
-        if ( classLoader == Thread.currentThread().getContextClassLoader() ) {
-            ois = new ReplicationStream(fis, new ClassLoader[] {classLoader});
-        } else {
-            ois = new ReplicationStream(fis, new ClassLoader[] {classLoader,Thread.currentThread().getContextClassLoader()});
-        }
-        return ois;
-    }    
-
-
-    
-
-    /**
-     * Reinstantiates a serialized session from the data passed in.
-     * This will first call createSession() so that we get a fresh instance with all
-     * the managers set and all the transient fields validated.
-     * Then it calls Session.readObjectData(byte[]) to deserialize the object
-     * @param data - a byte array containing session data
-     * @return a valid Session object, null if an error occurs
-     *
-     */
-    protected Session readSession( byte[] data, String sessionId )
-    {
-        try
-        {
-            ReplicationStream session_in = getReplicationStream(data);
-
-            Session session = sessionId!=null?this.findSession(sessionId):null;
-            boolean isNew = (session==null);
-            //clear the old values from the existing session
-            if ( session!=null ) {
-                ReplicatedSession rs = (ReplicatedSession)session;
-                rs.expire(false);  //cleans up the previous values, since we are not doing removes
-                session = null;
-            }//end if
-
-            if (session==null) {
-                session = createSession(null,false, false);
-                sessions.remove(session.getIdInternal());
-            }
-            
-            
-            boolean hasPrincipal = session_in.readBoolean();
-            SerializablePrincipal p = null;
-            if ( hasPrincipal )
-                p = (SerializablePrincipal)session_in.readObject();
-            ((ReplicatedSession)session).readObjectData(session_in);
-            if ( hasPrincipal )
-                session.setPrincipal(p.getPrincipal(getContainer().getRealm()));
-            ((ReplicatedSession)session).setId(sessionId,isNew);
-            ReplicatedSession rsession = (ReplicatedSession)session; 
-            rsession.setAccessCount(1);
-            session.setManager(this);
-            session.setValid(true);
-            rsession.setLastAccessedTime(System.currentTimeMillis());
-            rsession.setThisAccessedTime(System.currentTimeMillis());
-            ((ReplicatedSession)session).setAccessCount(0);
-            session.setNew(false);
-            if(log.isTraceEnabled())
-                 log.trace("Session loaded id="+sessionId +
-                               " actualId="+session.getId()+ 
-                               " exists="+this.sessions.containsKey(sessionId)+
-                               " valid="+rsession.isValid());
-            return session;
-
-        }
-        catch ( Exception x )
-        {
-            log.error("Failed to deserialize the session!",x);
-        }
-        return null;
-    }
-
-    public String getName() {
-        return this.name;
-    }
-    /**
-     * Prepare for the beginning of active use of the public methods of this
-     * component.  This method should be called after <code>configure()</code>,
-     * and before any of the public methods of the component are utilized.<BR>
-     * Starts the cluster communication channel, this will connect with the other nodes
-     * in the cluster, and request the current session state to be transferred to this node.
-     * @exception IllegalStateException if this component has already been
-     *  started
-     * @exception LifecycleException if this component detects a fatal error
-     *  that prevents this component from being used
-     */
-    public void start() throws LifecycleException {
-        mManagerRunning = true;
-        super.start();
-        //start the javagroups channel
-        try {
-            //the channel is already running
-            if ( mChannelStarted ) return;
-            if(log.isInfoEnabled())
-                log.info("Starting clustering manager...:"+getName());
-            if ( cluster == null ) {
-                log.error("Starting... no cluster associated with this context:"+getName());
-                return;
-            }
-            cluster.addManager(getName(),this);
-
-            if (cluster.getMembers().length > 0) {
-                Member mbr = cluster.getMembers()[0];
-                SessionMessage msg =
-                    new SessionMessageImpl(this.getName(),
-                                       SessionMessage.EVT_GET_ALL_SESSIONS,
-                                       null,
-                                       "GET-ALL",
-                                       "GET-ALL-"+this.getName());
-                cluster.send(msg, mbr);
-                if(log.isWarnEnabled())
-                     log.warn("Manager["+getName()+"], requesting session state from "+mbr+
-                         ". This operation will timeout if no session state has been received within "+
-                         "60 seconds");
-                long reqStart = System.currentTimeMillis();
-                long reqNow = 0;
-                boolean isTimeout=false;
-                do {
-                    try {
-                        Thread.sleep(100);
-                    }catch ( Exception sleep) {}
-                    reqNow = System.currentTimeMillis();
-                    isTimeout=((reqNow-reqStart)>(1000*60));
-                } while ( (!isStateTransferred()) && (!isTimeout));
-                if ( isTimeout || (!isStateTransferred()) ) {
-                    log.error("Manager["+getName()+"], No session state received, timing out.");
-                }else {
-                    if(log.isInfoEnabled())
-                        log.info("Manager["+getName()+"], session state received in "+(reqNow-reqStart)+" ms.");
-                }
-            } else {
-                if(log.isInfoEnabled())
-                    log.info("Manager["+getName()+"], skipping state transfer. No members active in cluster group.");
-            }//end if
-            mChannelStarted = true;
-        }  catch ( Exception x ) {
-            log.error("Unable to start SimpleTcpReplicationManager",x);
-        }
-    }
-
-    /**
-     * Gracefully terminate the active use of the public methods of this
-     * component.  This method should be the last one called on a given
-     * instance of this component.<BR>
-     * This will disconnect the cluster communication channel and stop the listener thread.
-     * @exception IllegalStateException if this component has not been started
-     * @exception LifecycleException if this component detects a fatal error
-     *  that needs to be reported
-     */
-    public void stop() throws LifecycleException
-    {
-        mManagerRunning = false;
-        mChannelStarted = false;
-        super.stop();
-        //stop the javagroup channel
-        try
-        {
-            this.sessions.clear();
-            cluster.removeManager(getName(),this);
-//            mReplicationListener.stopListening();
-//            mReplicationTransmitter.stop();
-//            service.stop();
-//            service = null;
-        }
-        catch ( Exception x )
-        {
-            log.error("Unable to stop SimpleTcpReplicationManager",x);
-        }
-    }
-
-    public void setDistributable(boolean dist) {
-        this.distributable = dist;
-    }
-
-    public boolean getDistributable() {
-        return distributable;
-    }
-
-    /**
-     * This method is called by the received thread when a SessionMessage has
-     * been received from one of the other nodes in the cluster.
-     * @param msg - the message received
-     * @param sender - the sender of the message, this is used if we receive a
-     *                 EVT_GET_ALL_SESSION message, so that we only reply to
-     *                 the requesting node
-     */
-    protected void messageReceived( SessionMessage msg, Member sender ) {
-        try  {
-            if(log.isInfoEnabled()) {
-                log.debug("Received SessionMessage of type="+msg.getEventTypeString());
-                log.debug("Received SessionMessage sender="+sender);
-            }
-            switch ( msg.getEventType() ) {
-                case SessionMessage.EVT_GET_ALL_SESSIONS: {
-                    //get a list of all the session from this manager
-                    Object[] sessions = findSessions();
-                    java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();
-                    java.io.ObjectOutputStream oout = new java.io.ObjectOutputStream(bout);
-                    oout.writeInt(sessions.length);
-                    for (int i=0; i<sessions.length; i++){
-                        ReplicatedSession ses = (ReplicatedSession)sessions[i];
-                        oout.writeUTF(ses.getIdInternal());
-                        byte[] data = writeSession(ses);
-                        oout.writeObject(data);
-                    }//for
-                    //don't send a message if we don't have to
-                    oout.flush();
-                    oout.close();
-                    byte[] data = bout.toByteArray();
-                    SessionMessage newmsg = new SessionMessageImpl(name,
-                        SessionMessage.EVT_ALL_SESSION_DATA,
-                        data, "SESSION-STATE","SESSION-STATE-"+getName());
-                    cluster.send(newmsg, sender);
-                    break;
-                }
-                case SessionMessage.EVT_ALL_SESSION_DATA: {
-                    java.io.ByteArrayInputStream bin =
-                        new java.io.ByteArrayInputStream(msg.getSession());
-                    java.io.ObjectInputStream oin = new java.io.ObjectInputStream(bin);
-                    int size = oin.readInt();
-                    for ( int i=0; i<size; i++) {
-                        String id = oin.readUTF();
-                        byte[] data = (byte[])oin.readObject();
-                        Session session = readSession(data,id);
-                    }//for
-                    stateTransferred=true;
-                    break;
-                }
-                case SessionMessage.EVT_SESSION_CREATED: {
-                    Session session = this.readSession(msg.getSession(),msg.getSessionID());
-                    if ( log.isDebugEnabled() ) {
-                        log.debug("Received replicated session=" + session +
-                            " isValid=" + session.isValid());
-                    }
-                    break;
-                }
-                case SessionMessage.EVT_SESSION_EXPIRED: {
-                    Session session = findSession(msg.getSessionID());
-                    if ( session != null ) {
-                        session.expire();
-                        this.remove(session);
-                    }//end if
-                    break;
-                }
-                case SessionMessage.EVT_SESSION_ACCESSED :{
-                    Session session = findSession(msg.getSessionID());
-                    if ( session != null ) {
-                        session.access();
-                        session.endAccess();
-                    }
-                    break;
-                }
-                default:  {
-                    //we didn't recognize the message type, do nothing
-                    break;
-                }
-            }//switch
-        }
-        catch ( Exception x )
-        {
-            log.error("Unable to receive message through TCP channel",x);
-        }
-    }
-
-    public void messageDataReceived(ClusterMessage cmsg) {
-        try {
-            if ( cmsg instanceof SessionMessage ) {
-                SessionMessage msg = (SessionMessage)cmsg;
-                messageReceived(msg,
-                                msg.getAddress() != null ? (Member) msg.getAddress() : null);
-            }
-        } catch(Throwable ex){
-            log.error("InMemoryReplicationManager.messageDataReceived()", ex);
-        }//catch
-    }
-
-    public boolean isStateTransferred() {
-        return stateTransferred;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-    public boolean isNotifyListenersOnReplication() {
-        return notifyListenersOnReplication;
-    }
-    public void setNotifyListenersOnReplication(boolean notifyListenersOnReplication) {
-        this.notifyListenersOnReplication = notifyListenersOnReplication;
-    }
-
-
-    /* 
-     * @see org.apache.catalina.ha.ClusterManager#getCluster()
-     */
-    public CatalinaCluster getCluster() {
-        return cluster;
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.catalina.ha.session;
+
+import java.io.IOException;
+
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.Session;
+import org.apache.catalina.ha.CatalinaCluster;
+import org.apache.catalina.ha.ClusterManager;
+import org.apache.catalina.ha.ClusterMessage;
+import org.apache.catalina.tribes.Member;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.apache.catalina.session.StandardManager;
+import org.apache.catalina.tribes.io.ReplicationStream;
+import java.io.ByteArrayInputStream;
+import org.apache.catalina.Loader;
+
+/**
+ * Title:        Tomcat Session Replication for Tomcat 4.0 <BR>
+ * Description:  A very simple straight forward implementation of
+ *               session replication of servers in a cluster.<BR>
+ *               This session replication is implemented "live". By live
+ *               I mean, when a session attribute is added into a session on Node A
+ *               a message is broadcasted to other messages and setAttribute is called on the
+ *               replicated sessions.<BR>
+ *               A full description of this implementation can be found under
+ *               <href="http://www.filip.net/tomcat/">Filip's Tomcat Page</a><BR>
+ *
+ * Copyright:    See apache license
+ * Company:      www.filip.net
+ * @author  <a href="mailto:mail@filip.net">Filip Hanik</a>
+ * @author Bela Ban (modifications for synchronous replication)
+ * @version 1.0 for TC 4.0
+ * Description: The InMemoryReplicationManager is a session manager that replicated
+ * session information in memory. It uses <a href="www.javagroups.com">JavaGroups</a> as
+ * a communication protocol to ensure guaranteed and ordered message delivery.
+ * JavaGroups also provides a very flexible protocol stack to ensure that the replication
+ * can be used in any environment.
+ * <BR><BR>
+ * The InMemoryReplicationManager extends the StandardManager hence it allows for us
+ * to inherit all the basic session management features like expiration, session listeners etc
+ * <BR><BR>
+ * To communicate with other nodes in the cluster, the InMemoryReplicationManager sends out 7 different type of multicast messages
+ * all defined in the SessionMessage class.<BR>
+ * When a session is replicated (not an attribute added/removed) the session is serialized into
+ * a byte array using the StandardSession.readObjectData, StandardSession.writeObjectData methods.
+ */
+public class SimpleTcpReplicationManager extends StandardManager implements ClusterManager
+{
+    public static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog( SimpleTcpReplicationManager.class );
+
+    //the channel configuration
+    protected String mChannelConfig = null;
+
+    //the group name
+    protected String mGroupName = "TomcatReplication";
+
+    //somehow start() gets called more than once
+    protected boolean mChannelStarted = false;
+
+    //log to screen
+    protected boolean mPrintToScreen = true;
+
+    protected boolean defaultMode = false;
+
+    protected boolean mManagerRunning = false;
+
+    /** Use synchronous rather than asynchronous replication. Every session modification (creation, change, removal etc)
+     * will be sent to all members. The call will then wait for max milliseconds, or forever (if timeout is 0) for
+     * all responses.
+     */
+    protected boolean synchronousReplication=true;
+
+    /** Set to true if we don't want the sessions to expire on shutdown */
+    protected boolean mExpireSessionsOnShutdown = true;
+
+    protected boolean useDirtyFlag = false;
+
+    protected String name;
+
+    protected boolean distributable = true;
+
+    protected CatalinaCluster cluster;
+
+    protected java.util.HashMap invalidatedSessions = new java.util.HashMap();
+
+    /**
+     * Flag to keep track if the state has been transferred or not
+     * Assumes false.
+     */
+    protected boolean stateTransferred = false;
+    private boolean notifyListenersOnReplication;
+    private boolean sendClusterDomainOnly = true ;
+
+    /**
+     * Constructor, just calls super()
+     *
+     */
+    public SimpleTcpReplicationManager()
+    {
+        super();
+    }
+
+    public boolean isSendClusterDomainOnly() {
+        return sendClusterDomainOnly;
+    }
+    
+    /**
+     * @param sendClusterDomainOnly The sendClusterDomainOnly to set.
+     */
+    public void setSendClusterDomainOnly(boolean sendClusterDomainOnly) {
+        this.sendClusterDomainOnly = sendClusterDomainOnly;
+    }
+  
+    /**
+     * @return Returns the defaultMode.
+     */
+    public boolean isDefaultMode() {
+        return defaultMode;
+    }
+    /**
+     * @param defaultMode The defaultMode to set.
+     */
+    public void setDefaultMode(boolean defaultMode) {
+        this.defaultMode = defaultMode;
+    }
+    
+    public boolean isManagerRunning()
+    {
+        return mManagerRunning;
+    }
+
+    public void setUseDirtyFlag(boolean usedirtyflag)
+    {
+        this.useDirtyFlag = usedirtyflag;
+    }
+
+    public void setExpireSessionsOnShutdown(boolean expireSessionsOnShutdown)
+    {
+        mExpireSessionsOnShutdown = expireSessionsOnShutdown;
+    }
+
+    public void setCluster(CatalinaCluster cluster) {
+        if(log.isDebugEnabled())
+            log.debug("Cluster associated with SimpleTcpReplicationManager");
+        this.cluster = cluster;
+    }
+
+    public boolean getExpireSessionsOnShutdown()
+    {
+        return mExpireSessionsOnShutdown;
+    }
+
+    public void setPrintToScreen(boolean printtoscreen)
+    {
+        if(log.isDebugEnabled())
+            log.debug("Setting screen debug to:"+printtoscreen);
+        mPrintToScreen = printtoscreen;
+    }
+
+    public void setSynchronousReplication(boolean flag)
+    {
+        synchronousReplication=flag;
+    }
+
+    /**
+     * Override persistence since they don't go hand in hand with replication for now.
+     */
+    public void unload() throws IOException {
+        if ( !getDistributable() ) {
+            super.unload();
+        }
+    }
+
+    /**
+     * Creates a HTTP session.
+     * Most of the code in here is copied from the StandardManager.
+     * This is not pretty, yeah I know, but it was necessary since the
+     * StandardManager had hard coded the session instantiation to the a
+     * StandardSession, when we actually want to instantiate a ReplicatedSession<BR>
+     * If the call comes from the Tomcat servlet engine, a SessionMessage goes out to the other
+     * nodes in the cluster that this session has been created.
+     * @param notify - if set to true the other nodes in the cluster will be notified.
+     *                 This flag is needed so that we can create a session before we deserialize
+     *                 a replicated one
+     *
+     * @see ReplicatedSession
+     */
+    protected Session createSession(String sessionId, boolean notify, boolean setId)
+    {
+
+        //inherited from the basic manager
+        if ((getMaxActiveSessions() >= 0) &&
+           (sessions.size() >= getMaxActiveSessions()))
+            throw new IllegalStateException(sm.getString("standardManager.createSession.ise"));
+
+
+        Session session = new ReplicatedSession(this);
+
+        // Initialize the properties of the new session and return it
+        session.setNew(true);
+        session.setValid(true);
+        session.setCreationTime(System.currentTimeMillis());
+        session.setMaxInactiveInterval(this.maxInactiveInterval);
+        if(sessionId == null)
+            sessionId = generateSessionId();
+        if ( setId ) session.setId(sessionId);
+        if ( notify && (cluster!=null) ) {
+            ((ReplicatedSession)session).setIsDirty(true);
+        }
+        return (session);
+    }//createSession
+
+    //=========================================================================
+    // OVERRIDE THESE METHODS TO IMPLEMENT THE REPLICATION
+    //=========================================================================
+
+    /**
+     * Construct and return a new session object, based on the default
+     * settings specified by this Manager's properties.  The session
+     * id will be assigned by this method, and available via the getId()
+     * method of the returned session.  If a new session cannot be created
+     * for any reason, return <code>null</code>.
+     *
+     * @exception IllegalStateException if a new session cannot be
+     *  instantiated for any reason
+     */
+    public Session createSession(String sessionId)
+    {
+        //create a session and notify the other nodes in the cluster
+        Session session =  createSession(sessionId,getDistributable(),true);
+        add(session);
+        return session;
+    }
+
+    public void sessionInvalidated(String sessionId) {
+        synchronized ( invalidatedSessions ) {
+            invalidatedSessions.put(sessionId, sessionId);
+        }
+    }
+
+    public String[] getInvalidatedSessions() {
+        synchronized ( invalidatedSessions ) {
+            String[] result = new String[invalidatedSessions.size()];
+            invalidatedSessions.values().toArray(result);
+            return result;
+        }
+
+    }
+
+    public ClusterMessage requestCompleted(String sessionId)
+    {
+        if (  !getDistributable() ) {
+            log.warn("Received requestCompleted message, although this context["+
+                     getName()+"] is not distributable. Ignoring message");
+            return null;
+        }
+        //notify javagroups
+        try
+        {
+            if ( invalidatedSessions.get(sessionId) != null ) {
+                synchronized ( invalidatedSessions ) {
+                    invalidatedSessions.remove(sessionId);
+                    SessionMessage msg = new SessionMessageImpl(name,
+                    SessionMessage.EVT_SESSION_EXPIRED,
+                    null,
+                    sessionId,
+                    sessionId);
+                return msg;
+                }
+            } else {
+                ReplicatedSession session = (ReplicatedSession) findSession(
+                    sessionId);
+                if (session != null) {
+                    //return immediately if the session is not dirty
+                    if (useDirtyFlag && (!session.isDirty())) {
+                        //but before we return doing nothing,
+                        //see if we should send
+                        //an updated last access message so that
+                        //sessions across cluster dont expire
+                        long interval = session.getMaxInactiveInterval();
+                        long lastaccdist = System.currentTimeMillis() -
+                            session.getLastAccessWasDistributed();
+                        if ( ((interval*1000) / lastaccdist)< 3 ) {
+                            SessionMessage accmsg = new SessionMessageImpl(name,
+                                SessionMessage.EVT_SESSION_ACCESSED,
+                                null,
+                                sessionId,
+                                sessionId);
+                            session.setLastAccessWasDistributed(System.currentTimeMillis());
+                            return accmsg;
+                        }
+                        return null;
+                    }
+
+                    session.setIsDirty(false);
+                    if (log.isDebugEnabled()) {
+                        try {
+                            log.debug("Sending session to cluster=" + session);
+                        }
+                        catch (Exception ignore) {}
+                    }
+                    SessionMessage msg = new SessionMessageImpl(name,
+                        SessionMessage.EVT_SESSION_CREATED,
+                        writeSession(session),
+                        session.getIdInternal(),
+                        session.getIdInternal());
+                    return msg;
+                } //end if
+            }//end if
+        }
+        catch (Exception x )
+        {
+            log.error("Unable to replicate session",x);
+        }
+        return null;
+    }
+
+    /**
+     * Serialize a session into a byte array<BR>
+     * This method simple calls the writeObjectData method on the session
+     * and returns the byte data from that call
+     * @param session - the session to be serialized
+     * @return a byte array containing the session data, null if the serialization failed
+     */
+    protected byte[] writeSession( Session session )
+    {
+        try
+        {
+            java.io.ByteArrayOutputStream session_data = new java.io.ByteArrayOutputStream();
+            java.io.ObjectOutputStream session_out = new java.io.ObjectOutputStream(session_data);
+            session_out.flush();
+            boolean hasPrincipal = session.getPrincipal() != null;
+            session_out.writeBoolean(hasPrincipal);
+            if ( hasPrincipal )
+            {
+                session_out.writeObject(SerializablePrincipal.createPrincipal((GenericPrincipal)session.getPrincipal()));
+            }//end if
+            ((ReplicatedSession)session).writeObjectData(session_out);
+            return session_data.toByteArray();
+
+        }
+        catch ( Exception x )
+        {
+            log.error("Failed to serialize the session!",x);
+        }
+        return null;
+    }
+    
+    /**
+     * Open Stream and use correct ClassLoader (Container) Switch
+     * ThreadClassLoader
+     * 
+     * @param data
+     * @return The object input stream
+     * @throws IOException
+     */
+    public ReplicationStream getReplicationStream(byte[] data) throws IOException {
+        return getReplicationStream(data,0,data.length);
+    }
+    
+    public ReplicationStream getReplicationStream(byte[] data, int offset, int length) throws IOException {
+        ByteArrayInputStream fis =null;
+        ReplicationStream ois = null;
+        Loader loader = null;
+        ClassLoader classLoader = null;
+        //fix to be able to run the DeltaManager
+        //stand alone without a container.
+        //use the Threads context class loader
+        if (container != null)
+            loader = container.getLoader();
+        if (loader != null)
+            classLoader = loader.getClassLoader();
+        else
+            classLoader = Thread.currentThread().getContextClassLoader();
+        //end fix
+        fis = new ByteArrayInputStream(data, offset, length);
+        if ( classLoader == Thread.currentThread().getContextClassLoader() ) {
+            ois = new ReplicationStream(fis, new ClassLoader[] {classLoader});
+        } else {
+            ois = new ReplicationStream(fis, new ClassLoader[] {classLoader,Thread.currentThread().getContextClassLoader()});
+        }
+        return ois;
+    }    
+
+
+    
+
+    /**
+     * Reinstantiates a serialized session from the data passed in.
+     * This will first call createSession() so that we get a fresh instance with all
+     * the managers set and all the transient fields validated.
+     * Then it calls Session.readObjectData(byte[]) to deserialize the object
+     * @param data - a byte array containing session data
+     * @return a valid Session object, null if an error occurs
+     *
+     */
+    protected Session readSession( byte[] data, String sessionId )
+    {
+        try
+        {
+            ReplicationStream session_in = getReplicationStream(data);
+
+            Session session = sessionId!=null?this.findSession(sessionId):null;
+            boolean isNew = (session==null);
+            //clear the old values from the existing session
+            if ( session!=null ) {
+                ReplicatedSession rs = (ReplicatedSession)session;
+                rs.expire(false);  //cleans up the previous values, since we are not doing removes
+                session = null;
+            }//end if
+
+            if (session==null) {
+                session = createSession(null,false, false);
+                sessions.remove(session.getIdInternal());
+            }
+            
+            
+            boolean hasPrincipal = session_in.readBoolean();
+            SerializablePrincipal p = null;
+            if ( hasPrincipal )
+                p = (SerializablePrincipal)session_in.readObject();
+            ((ReplicatedSession)session).readObjectData(session_in);
+            if ( hasPrincipal )
+                session.setPrincipal(p.getPrincipal(getContainer().getRealm()));
+            ((ReplicatedSession)session).setId(sessionId,isNew);
+            ReplicatedSession rsession = (ReplicatedSession)session; 
+            rsession.setAccessCount(1);
+            session.setManager(this);
+            session.setValid(true);
+            rsession.setLastAccessedTime(System.currentTimeMillis());
+            rsession.setThisAccessedTime(System.currentTimeMillis());
+            ((ReplicatedSession)session).setAccessCount(0);
+            session.setNew(false);
+            if(log.isTraceEnabled())
+                 log.trace("Session loaded id="+sessionId +
+                               " actualId="+session.getId()+ 
+                               " exists="+this.sessions.containsKey(sessionId)+
+                               " valid="+rsession.isValid());
+            return session;
+
+        }
+        catch ( Exception x )
+        {
+            log.error("Failed to deserialize the session!",x);
+        }
+        return null;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+    /**
+     * Prepare for the beginning of active use of the public methods of this
+     * component.  This method should be called after <code>configure()</code>,
+     * and before any of the public methods of the component are utilized.<BR>
+     * Starts the cluster communication channel, this will connect with the other nodes
+     * in the cluster, and request the current session state to be transferred to this node.
+     * @exception IllegalStateException if this component has already been
+     *  started
+     * @exception LifecycleException if this component detects a fatal error
+     *  that prevents this component from being used
+     */
+    public void start() throws LifecycleException {
+        mManagerRunning = true;
+        super.start();
+        //start the javagroups channel
+        try {
+            //the channel is already running
+            if ( mChannelStarted ) return;
+            if(log.isInfoEnabled())
+                log.info("Starting clustering manager...:"+getName());
+            if ( cluster == null ) {
+                log.error("Starting... no cluster associated with this context:"+getName());
+                return;
+            }
+            cluster.addManager(getName(),this);
+
+            if (cluster.getMembers().length > 0) {
+                Member mbr = cluster.getMembers()[0];
+                SessionMessage msg =
+                    new SessionMessageImpl(this.getName(),
+                                       SessionMessage.EVT_GET_ALL_SESSIONS,
+                                       null,
+                                       "GET-ALL",
+                                       "GET-ALL-"+this.getName());
+                cluster.send(msg, mbr);
+                if(log.isWarnEnabled())
+                     log.warn("Manager["+getName()+"], requesting session state from "+mbr+
+                         ". This operation will timeout if no session state has been received within "+
+                         "60 seconds");
+                long reqStart = System.currentTimeMillis();
+                long reqNow = 0;
+                boolean isTimeout=false;
+                do {
+                    try {
+                        Thread.sleep(100);
+                    }catch ( Exception sleep) {}
+                    reqNow = System.currentTimeMillis();
+                    isTimeout=((reqNow-reqStart)>(1000*60));
+                } while ( (!isStateTransferred()) && (!isTimeout));
+                if ( isTimeout || (!isStateTransferred()) ) {
+                    log.error("Manager["+getName()+"], No session state received, timing out.");
+                }else {
+                    if(log.isInfoEnabled())
+                        log.info("Manager["+getName()+"], session state received in "+(reqNow-reqStart)+" ms.");
+                }
+            } else {
+                if(log.isInfoEnabled())
+                    log.info("Manager["+getName()+"], skipping state transfer. No members active in cluster group.");
+            }//end if
+            mChannelStarted = true;
+        }  catch ( Exception x ) {
+            log.error("Unable to start SimpleTcpReplicationManager",x);
+        }
+    }
+
+    /**
+     * Gracefully terminate the active use of the public methods of this
+     * component.  This method should be the last one called on a given
+     * instance of this component.<BR>
+     * This will disconnect the cluster communication channel and stop the listener thread.
+     * @exception IllegalStateException if this component has not been started
+     * @exception LifecycleException if this component detects a fatal error
+     *  that needs to be reported
+     */
+    public void stop() throws LifecycleException
+    {
+        mManagerRunning = false;
+        mChannelStarted = false;
+        super.stop();
+        //stop the javagroup channel
+        try
+        {
+            this.sessions.clear();
+            cluster.removeManager(getName(),this);
+//            mReplicationListener.stopListening();
+//            mReplicationTransmitter.stop();
+//            service.stop();
+//            service = null;
+        }
+        catch ( Exception x )
+        {
+            log.error("Unable to stop SimpleTcpReplicationManager",x);
+        }
+    }
+
+    public void setDistributable(boolean dist) {
+        this.distributable = dist;
+    }
+
+    public boolean getDistributable() {
+        return distributable;
+    }
+
+    /**
+     * This method is called by the received thread when a SessionMessage has
+     * been received from one of the other nodes in the cluster.
+     * @param msg - the message received
+     * @param sender - the sender of the message, this is used if we receive a
+     *                 EVT_GET_ALL_SESSION message, so that we only reply to
+     *                 the requesting node
+     */
+    protected void messageReceived( SessionMessage msg, Member sender ) {
+        try  {
+            if(log.isInfoEnabled()) {
+                log.debug("Received SessionMessage of type="+msg.getEventTypeString());
+                log.debug("Received SessionMessage sender="+sender);
+            }
+            switch ( msg.getEventType() ) {
+                case SessionMessage.EVT_GET_ALL_SESSIONS: {
+                    //get a list of all the session from this manager
+                    Object[] sessions = findSessions();
+                    java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();
+                    java.io.ObjectOutputStream oout = new java.io.ObjectOutputStream(bout);
+                    oout.writeInt(sessions.length);
+                    for (int i=0; i<sessions.length; i++){
+                        ReplicatedSession ses = (ReplicatedSession)sessions[i];
+                        oout.writeUTF(ses.getIdInternal());
+                        byte[] data = writeSession(ses);
+                        oout.writeObject(data);
+                    }//for
+                    //don't send a message if we don't have to
+                    oout.flush();
+                    oout.close();
+                    byte[] data = bout.toByteArray();
+                    SessionMessage newmsg = new SessionMessageImpl(name,
+                        SessionMessage.EVT_ALL_SESSION_DATA,
+                        data, "SESSION-STATE","SESSION-STATE-"+getName());
+                    cluster.send(newmsg, sender);
+                    break;
+                }
+                case SessionMessage.EVT_ALL_SESSION_DATA: {
+                    java.io.ByteArrayInputStream bin =
+                        new java.io.ByteArrayInputStream(msg.getSession());
+                    java.io.ObjectInputStream oin = new java.io.ObjectInputStream(bin);
+                    int size = oin.readInt();
+                    for ( int i=0; i<size; i++) {
+                        String id = oin.readUTF();
+                        byte[] data = (byte[])oin.readObject();
+                        Session session = readSession(data,id);
+                    }//for
+                    stateTransferred=true;
+                    break;
+                }
+                case SessionMessage.EVT_SESSION_CREATED: {
+                    Session session = this.readSession(msg.getSession(),msg.getSessionID());
+                    if ( log.isDebugEnabled() ) {
+                        log.debug("Received replicated session=" + session +
+                            " isValid=" + session.isValid());
+                    }
+                    break;
+                }
+                case SessionMessage.EVT_SESSION_EXPIRED: {
+                    Session session = findSession(msg.getSessionID());
+                    if ( session != null ) {
+                        session.expire();
+                        this.remove(session);
+                    }//end if
+                    break;
+                }
+                case SessionMessage.EVT_SESSION_ACCESSED :{
+                    Session session = findSession(msg.getSessionID());
+                    if ( session != null ) {
+                        session.access();
+                        session.endAccess();
+                    }
+                    break;
+                }
+                default:  {
+                    //we didn't recognize the message type, do nothing
+                    break;
+                }
+            }//switch
+        }
+        catch ( Exception x )
+        {
+            log.error("Unable to receive message through TCP channel",x);
+        }
+    }
+
+    public void messageDataReceived(ClusterMessage cmsg) {
+        try {
+            if ( cmsg instanceof SessionMessage ) {
+                SessionMessage msg = (SessionMessage)cmsg;
+                messageReceived(msg,
+                                msg.getAddress() != null ? (Member) msg.getAddress() : null);
+            }
+        } catch(Throwable ex){
+            log.error("InMemoryReplicationManager.messageDataReceived()", ex);
+        }//catch
+    }
+
+    public boolean isStateTransferred() {
+        return stateTransferred;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+    public boolean isNotifyListenersOnReplication() {
+        return notifyListenersOnReplication;
+    }
+    public void setNotifyListenersOnReplication(boolean notifyListenersOnReplication) {
+        this.notifyListenersOnReplication = notifyListenersOnReplication;
+    }
+
+
+    /* 
+     * @see org.apache.catalina.ha.ClusterManager#getCluster()
+     */
+    public CatalinaCluster getCluster() {
+        return cluster;
+    }
+
+}

Propchange: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/session/SimpleTcpReplicationManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/session/SimpleTcpReplicationManager.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/session/mbeans-descriptors.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/session/mbeans-descriptors.xml
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/tcp/Constants.java
URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/tcp/Constants.java?view=diff&rev=467206&r1=467205&r2=467206
==============================================================================
--- tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/tcp/Constants.java (original)
+++ tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/tcp/Constants.java Mon Oct 23 19:45:46 2006
@@ -1,33 +1,33 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.catalina.ha.tcp;
-
-/**
- * Manifest constants for the <code>org.apache.catalina.ha.tcp</code>
- * package.
- *
- * @author Peter Rossbach
- * @version $Revision: 303753 $ $Date: 2005-03-14 15:24:30 -0600 (Mon, 14 Mar 2005) $
- */
-
-public class Constants {
-
-    public static final String Package = "org.apache.catalina.ha.tcp";
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.catalina.ha.tcp;
+
+/**
+ * Manifest constants for the <code>org.apache.catalina.ha.tcp</code>
+ * package.
+ *
+ * @author Peter Rossbach
+ * @version $Revision$ $Date$
+ */
+
+public class Constants {
+
+    public static final String Package = "org.apache.catalina.ha.tcp";
+
+}

Propchange: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/tcp/Constants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/tcp/Constants.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/tcp/LocalStrings.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/ha/tcp/LocalStrings.properties
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org