tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fha...@apache.org
Subject svn commit: r691359 [1/8] - in /tomcat/trunk: ./ java/org/apache/cometd/ java/org/apache/cometd/bayeux/ java/org/apache/tomcat/bayeux/ java/org/apache/tomcat/bayeux/request/ test/org/apache/cometd/ test/org/apache/cometd/bayeux/ test/org/apache/cometd/...
Date Tue, 02 Sep 2008 20:00:38 GMT
Author: fhanik
Date: Tue Sep  2 13:00:36 2008
New Revision: 691359

URL: http://svn.apache.org/viewvc?rev=691359&view=rev
Log:
Added in Bayeux implementation, as per 
https://issues.apache.org/bugzilla/show_bug.cgi?id=45413
to build, 
ant download
ant
ant -f extras.xml bayeux


Added:
    tomcat/trunk/COPYRIGHT
    tomcat/trunk/java/org/apache/cometd/
    tomcat/trunk/java/org/apache/cometd/bayeux/
    tomcat/trunk/java/org/apache/cometd/bayeux/Bayeux.java
    tomcat/trunk/java/org/apache/cometd/bayeux/Channel.java
    tomcat/trunk/java/org/apache/cometd/bayeux/Client.java
    tomcat/trunk/java/org/apache/cometd/bayeux/DataFilter.java
    tomcat/trunk/java/org/apache/cometd/bayeux/Listener.java
    tomcat/trunk/java/org/apache/cometd/bayeux/Message.java
    tomcat/trunk/java/org/apache/cometd/bayeux/SecurityPolicy.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/
    tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxException.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxRequest.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxServlet.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/ChannelImpl.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/ClientImpl.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/HttpError.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/MessageImpl.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/RequestBase.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/RequestFactory.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/TomcatBayeux.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/request/
    tomcat/trunk/java/org/apache/tomcat/bayeux/request/MetaConnectRequest.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/request/MetaDisconnectRequest.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/request/MetaHandshakeRequest.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/request/MetaSubscribeRequest.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/request/MetaUnsubscribeRequest.java
    tomcat/trunk/java/org/apache/tomcat/bayeux/request/PublishRequest.java
    tomcat/trunk/test/org/apache/cometd/
    tomcat/trunk/test/org/apache/cometd/bayeux/
    tomcat/trunk/test/org/apache/cometd/bayeux/samples/
    tomcat/trunk/test/org/apache/cometd/bayeux/samples/EchoChatClient.java
    tomcat/trunk/webapps/cometd/
    tomcat/trunk/webapps/cometd/WEB-INF/
    tomcat/trunk/webapps/cometd/WEB-INF/filters.json
    tomcat/trunk/webapps/cometd/WEB-INF/web.xml
    tomcat/trunk/webapps/cometd/examples/
    tomcat/trunk/webapps/cometd/examples/chat/
    tomcat/trunk/webapps/cometd/examples/chat/chat.css
    tomcat/trunk/webapps/cometd/examples/chat/chat.js
    tomcat/trunk/webapps/cometd/examples/chat/index.html
    tomcat/trunk/webapps/cometd/examples/dojo/
    tomcat/trunk/webapps/cometd/examples/dojo/dojo/
    tomcat/trunk/webapps/cometd/examples/dojo/dojo/dojo.js
    tomcat/trunk/webapps/cometd/examples/dojo/dojo/dojo.js.uncompressed.js
    tomcat/trunk/webapps/cometd/examples/dojo/dojo/dojo.xd.js
    tomcat/trunk/webapps/cometd/examples/dojo/dojo/dojo.xd.js.uncompressed.js
    tomcat/trunk/webapps/cometd/examples/dojo/dojox/
    tomcat/trunk/webapps/cometd/examples/dojo/dojox/cometd/
    tomcat/trunk/webapps/cometd/examples/dojo/dojox/cometd.js
    tomcat/trunk/webapps/cometd/examples/dojo/dojox/cometd.js.uncompressed.js
    tomcat/trunk/webapps/cometd/examples/dojo/dojox/cometd.xd.js
    tomcat/trunk/webapps/cometd/examples/dojo/dojox/cometd.xd.js.uncompressed.js
    tomcat/trunk/webapps/cometd/examples/dojo/dojox/cometd/session.js
    tomcat/trunk/webapps/cometd/examples/dojo/dojox/cometd/timestamp.js
    tomcat/trunk/webapps/cometd/examples/dojo/dojox/cometd/timesync.js
    tomcat/trunk/webapps/cometd/examples/echo/
    tomcat/trunk/webapps/cometd/examples/echo/index.html
    tomcat/trunk/webapps/cometd/examples/simplechat/
    tomcat/trunk/webapps/cometd/examples/simplechat/cometdchat.htm
    tomcat/trunk/webapps/cometd/examples/tictactoe/
    tomcat/trunk/webapps/cometd/examples/tictactoe/resources/
    tomcat/trunk/webapps/cometd/examples/tictactoe/resources/0.gif   (with props)
    tomcat/trunk/webapps/cometd/examples/tictactoe/resources/1.gif   (with props)
    tomcat/trunk/webapps/cometd/examples/tictactoe/resources/10.gif   (with props)
    tomcat/trunk/webapps/cometd/examples/tictactoe/resources/blank.gif   (with props)
    tomcat/trunk/webapps/cometd/examples/tictactoe/resources/tictactoe.css
    tomcat/trunk/webapps/cometd/examples/tictactoe/ttt1.htm
    tomcat/trunk/webapps/cometd/examples/timesync/
    tomcat/trunk/webapps/cometd/examples/timesync/index.html
    tomcat/trunk/webapps/cometd/index.html
Modified:
    tomcat/trunk/.classpath
    tomcat/trunk/build.properties.default
    tomcat/trunk/build.xml
    tomcat/trunk/extras.xml
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/.classpath
URL: http://svn.apache.org/viewvc/tomcat/trunk/.classpath?rev=691359&r1=691358&r2=691359&view=diff
==============================================================================
--- tomcat/trunk/.classpath (original)
+++ tomcat/trunk/.classpath Tue Sep  2 13:00:36 2008
@@ -1,27 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--
- 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.
--->
 <classpath>
-        <classpathentry excluding="**/.svn/**|org/apache/naming/factory/webservices/" kind="src" path="java"/>
+	<classpathentry excluding="**/.svn/**|org/apache/naming/factory/webservices/" kind="src" path="java"/>
 	<classpathentry kind="src" path="test"/>
 	<classpathentry kind="src" path="webapps/examples/WEB-INF/classes"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="var" path="TOMCAT_LIBS_BASE/eclipse/plugins/org.eclipse.jdt.core_3.3.1.v_780_R33x.jar"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
 	<classpathentry kind="var" path="ANT_HOME/lib/ant.jar"/>
+	<classpathentry kind="var" path="TOMCAT_LIBS_BASE/json-20070829/json.jar"/>
 	<classpathentry kind="output" path=".settings/output"/>
 </classpath>

Added: tomcat/trunk/COPYRIGHT
URL: http://svn.apache.org/viewvc/tomcat/trunk/COPYRIGHT?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/COPYRIGHT (added)
+++ tomcat/trunk/COPYRIGHT Tue Sep  2 13:00:36 2008
@@ -0,0 +1,5 @@
+****For the bayeux implementation*********
+* Copyright 2007-2008 Guy Molinari
+* Copyright 2007-2008 Filip Hanik
+* Copyright 2007 Dojo Foundation
+* Copyright 2007 Mort Bay Consulting Pty. Ltd.

Modified: tomcat/trunk/build.properties.default
URL: http://svn.apache.org/viewvc/tomcat/trunk/build.properties.default?rev=691359&r1=691358&r2=691359&view=diff
==============================================================================
--- tomcat/trunk/build.properties.default (original)
+++ tomcat/trunk/build.properties.default Tue Sep  2 13:00:36 2008
@@ -98,3 +98,8 @@
 commons-daemon.jar=${commons-daemon.lib}/commons-daemon.jar
 commons-daemon.loc=${base-commons.loc}/daemon/binaries/commons-daemon-1.0.1.tar.gz
 commons-daemon.jsvc.tar.gz=${commons-daemon.lib}/bin/jsvc.tar.gz
+
+# ----- JSON Libraries, 
+json-lib.home=${base.path}/json-20070829
+json-lib.lib=http://repo1.maven.org/maven2/org/json/json/20070829/json-20070829.jar
+json-lib.jar=json.jar

Modified: tomcat/trunk/build.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/build.xml?rev=691359&r1=691358&r2=691359&view=diff
==============================================================================
--- tomcat/trunk/build.xml (original)
+++ tomcat/trunk/build.xml Tue Sep  2 13:00:36 2008
@@ -112,6 +112,8 @@
 <!-- Comment this in to show unchecked warnings:     <compilerarg value="-Xlint:unchecked"/> -->
       <classpath refid="tomcat.classpath" />
       <exclude name="org/apache/naming/factory/webservices/**" />
+      <exclude name="org/apache/tomcat/bayeux/**" />
+      <exclude name="org/apache/cometd/**" />
     </javac>
     <tstamp>
       <format property="TODAY" pattern="MMM d yyyy" locale="en"/>

Modified: tomcat/trunk/extras.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/extras.xml?rev=691359&r1=691358&r2=691359&view=diff
==============================================================================
--- tomcat/trunk/extras.xml (original)
+++ tomcat/trunk/extras.xml Tue Sep  2 13:00:36 2008
@@ -76,6 +76,11 @@
   <property name="tomcat-juli.jar" value="${tomcat.extras}/tomcat-juli.jar"/>
   <property name="tomcat-juli-adapters.jar" value="${tomcat.extras}/tomcat-juli-adapters.jar"/>
   <property name="catalina-ws.jar" value="${tomcat.extras}/catalina-ws.jar"/>
+
+  <property name="cometd-api.jar" value="${tomcat.extras}/cometd-api.jar"/>
+  <property name="tomcat-bayeux.jar" value="${tomcat.extras}/tomcat-bayeux.jar"/>
+  <property name="cometd.war" value="${tomcat.extras}/cometd.war"/>
+
 	
   <!-- Classpath -->
   <path id="tomcat.classpath">
@@ -220,7 +225,62 @@
 	
   </target>
 
-  <target name="extras" depends="prepare,commons-logging,webservices">
+  <target name="bayeux">
+    <mkdir dir="${tomcat.extras}"/>
+
+    <copy todir="${tomcat.extras}" file="${json-lib.home}/${json-lib.jar}"/>
+    <!-- Classpath -->
+    <path id="tomcat.bayeux.classpath">
+      <pathelement path="${tomcat.classpath}"/>
+      <pathelement path="${json-lib.home}/${json-lib.jar}"/>
+    </path>
+
+    <!-- compile org.apache.tomcat.bayeux -->
+    <!-- compile org.apache.cometd -->
+    <javac srcdir="java" destdir="${tomcat.classes}"
+           debug="${compile.debug}"
+           deprecation="${compile.deprecation}"
+           source="${compile.source}"
+           optimize="${compile.optimize}">
+      <classpath refid="tomcat.bayeux.classpath" />
+      <include name="org/apache/tomcat/bayeux/**" />
+      <include name="org/apache/cometd/**" />
+    </javac>
+    <!-- Cometd API JAR File -->
+    <jar jarfile="${cometd-api.jar}">
+      <fileset dir="${tomcat.classes}">
+        <exclude name="**/package.html" />
+        <exclude name="**/LocalStrings_*" />
+        <include name="org/apache/cometd/**" />
+      </fileset>
+    </jar>
+    <!-- Cometd API JAR File -->
+    <jar jarfile="${tomcat-bayeux.jar}">
+      <fileset dir="${tomcat.classes}">
+        <exclude name="**/package.html" />
+        <exclude name="**/LocalStrings_*" />
+        <include name="org/apache/tomcat/bayeux/**" />
+      </fileset>
+    </jar>
+
+    <zip zipfile="${cometd.war}">
+      <fileset dir="${basedir}/webapps/cometd">
+        <include name="**/**"/>
+      </fileset>
+    </zip>
+    <checksum file="${cometd-api.jar}" forceOverwrite="yes" fileext=".md5" />
+    <checksum file="${tomcat-bayeux.jar}" forceOverwrite="yes" fileext=".md5" />
+    <checksum file="${tomcat.extras}/${json-lib.jar}" forceOverwrite="yes" fileext=".md5" />
+    <echo>You've built the Tomcat Bayeux libraries, simply add the following libraries to your CATALINA_HOME/lib directory:
+          ${cometd-api.jar}
+          ${tomcat-bayeux.jar} 
+          ${tomcat.extras}/${json-lib.jar}
+To run the sample application, copy the following applications into your CATALINA_BASE/webapps directory
+          ${cometd.war}
+    </echo>
+  </target>
+
+  <target name="extras" depends="prepare,commons-logging,webservices,bayeux">
   </target>
 
   <!-- Download and dependency building -->

Added: tomcat/trunk/java/org/apache/cometd/bayeux/Bayeux.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/cometd/bayeux/Bayeux.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/cometd/bayeux/Bayeux.java (added)
+++ tomcat/trunk/java/org/apache/cometd/bayeux/Bayeux.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,242 @@
+/*
+ * 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.cometd.bayeux;
+
+import java.util.List;
+
+/** Bayeux Interface.<br/>
+ * This interface represents the server side API for the Bayeux messaging protocol.
+ * Bayeux is a simple subscribe/publish/receive methodology, not far from JMS, but much simplified.<br/>
+ * It is used both by the actual implementation and by server side clients.<br/>
+ * Server side clients use this to create, retrieve and subscribe to channels.
+ * Server side clients are represented, just like remote clients, through the Client interface.
+ * <br/>
+ * The Bayeux implementations is intended to be thread safe and multiple threads may simultaneously call Bayeux methods.
+ * <br/>
+ * The Bayeux object, is the starting point for any cometd application relying on the Bayeux object.
+ * Dependent on the container, the Bayeux object will be stored in the <code>javax.servlet.ServletContext</code> object
+ * as an attribute under the name <code>Bayeux.DOJOX_COMETD_BAYEUX</code><br/>
+ * To retrieve this object, one would simply call<br/>
+ * <code>Bayeux bx = (Bayeux)getServletContext().getAttribute(Bayeux.DOJOX_COMETD_BAYEUX);
+ * <br/><br/>
+ * The Bayeux protocol is pretty straight forward and includes a bunch of messaging that is not needed to be known to clients,
+ * both server side and remote clients.
+ * This object gets initialized by a container dependent servlet, and the servlet then handles all Bayeux communication from the client.
+ * Remote messsages are delivered to channels, and to server side clients using the <code>Listener</code> interface.<br/>
+ * <br/>
+ * A <code>Bayeux session</code> is active as long as the webapp hosting the Bayeux object is active.<br/>
+ * When the webapplication shuts down, the Bayeux object will unsubscribe all clients and remove all the active channels.
+ * 
+ * @author Greg Wilkins
+ * @author Filip Hanik
+ */
+public interface Bayeux {
+    
+    /**Meta definitions for channels*/
+    public static final String META="/meta";
+    /**Meta definitions for channels*/
+    public static final String META_SLASH="/meta/";
+    /**Meta definitions for channels - connect message*/
+    public static final String META_CONNECT="/meta/connect";
+    /**Meta definitions for channels - client messsage*/
+    public static final String META_CLIENT="/meta/client";
+    /**Meta definitions for channels - disconnect messsage*/
+    public static final String META_DISCONNECT="/meta/disconnect";
+    /**Meta definitions for channels - handshake messsage*/
+    public static final String META_HANDSHAKE="/meta/handshake";
+    /**Meta definitions for channels - ping messsage*/
+    public static final String META_PING="/meta/ping";
+    /**Meta definitions for channels - reconnect messsage
+     * @deprecated
+     */
+    public static final String META_RECONNECT="/meta/reconnect";
+    /**Meta definitions for channels - status messsage*/
+    public static final String META_STATUS="/meta/status";
+    /**Meta definitions for channels - subscribe messsage*/
+    public static final String META_SUBSCRIBE="/meta/subscribe";
+    /**Meta definitions for channels - unsubscribe messsage*/
+    public static final String META_UNSUBSCRIBE="/meta/unsubscribe";
+    /*Field names inside Bayeux messages*/
+    /**Field names inside Bayeux messages - clientId field*/
+    public static final String CLIENT_FIELD="clientId";
+    /**Field names inside Bayeux messages - data field*/
+    public static final String DATA_FIELD="data";
+    /**Field names inside Bayeux messages - channel field*/
+    public static final String CHANNEL_FIELD="channel";
+    /**Field names inside Bayeux messages - id field*/
+    public static final String ID_FIELD="id";
+    /**Field names inside Bayeux messages - error field*/
+    public static final String ERROR_FIELD="error";
+    /**Field names inside Bayeux messages - timestamp field*/
+    public static final String TIMESTAMP_FIELD="timestamp";
+    /**Field names inside Bayeux messages - transport field*/
+    public static final String TRANSPORT_FIELD="transport";
+    /**Field names inside Bayeux messages - advice field*/
+    public static final String ADVICE_FIELD="advice";
+    /**Field names inside Bayeux messages - successful field*/
+    public static final String SUCCESSFUL_FIELD="successful";
+    /**Field names inside Bayeux messages - subscription field*/
+    public static final String SUBSCRIPTION_FIELD="subscription";
+    /**Field names inside Bayeux messages - ext field*/
+    public static final String EXT_FIELD="ext";
+    /**Field names inside Bayeux messages - connectionType field*/
+    public static final String CONNECTION_TYPE_FIELD="connectionType";
+    /**Field names inside Bayeux messages - version field*/
+    public static final String VERSION_FIELD="version";
+    /**Field names inside Bayeux messages - minimumVersion field*/
+    public static final String MIN_VERSION_FIELD="minimumVersion";
+    /**Field names inside Bayeux messages - supportedConnectionTypes field*/
+    public static final String SUPP_CONNECTION_TYPE_FIELD="supportedConnectionTypes";
+    /**Field names inside Bayeux messages - json-comment-filtered field*/
+    public static final String JSON_COMMENT_FILTERED_FIELD="json-comment-filtered";
+    /**Field names inside Bayeux messages - reconnect field*/
+    public static final String RECONNECT_FIELD = "reconnect";
+    /**Field names inside Bayeux messages - interval field*/
+    public static final String INTERVAL_FIELD = "interval";
+    /**Field values inside Bayeux messages - retry response*/
+    public static final String RETRY_RESPONSE = "retry";
+    /**Field values inside Bayeux messages - handshake response*/
+    public static final String HANDSHAKE_RESPONSE = "handshake";
+    /**Field values inside Bayeux messages - none response*/
+    public static final String NONE_RESPONSE = "none";
+    /**Service channel names-starts with*/
+    public static final String SERVICE="/service";
+    /**Service channel names-trailing slash*/
+    public static final String SERVICE_SLASH="/service/";
+    /*Transport types*/
+    /**Transport types - long polling*/
+    public static final String TRANSPORT_LONG_POLL="long-polling";
+    /**Transport types - callback polling*/
+    public static final String TRANSPORT_CALLBACK_POLL="callback-polling";
+    /**Transport types - iframe*/
+    public static final String TRANSPORT_IFRAME="iframe";
+    /**Transport types - flash*/
+    public static final String TRANSPORT_FLASH="flash";
+    /** ServletContext attribute name used to obtain the Bayeux object */
+    public static final String DOJOX_COMETD_BAYEUX="dojox.cometd.bayeux";
+    /*http field names*/
+    /**http helpers - text/json content type*/
+    public static final String JSON_CONTENT_TYPE="text/json";
+    /**http helpers - parameter name for json message*/
+    public static final String MESSAGE_PARAMETER="message";
+    /**http helpers - name of the jsonp parameter*/
+    public static final String JSONP_PARAMETER="jsonp";
+    /**http helpers - default name of the jsonp callback function*/
+    public static final String JSONP_DEFAULT_NAME="jsonpcallback";
+
+    /*--Client----------------------------------------------------------- */
+    /**
+     * Creates a new server side client. This method is to be invoked
+     * by server side objects only. You cannot create a remote client by using this method.
+     * A client represents an entity that can subscribe to channels and publish and receive messages
+     * through these channels
+     * @param idprefix String - the prefix string for the id generated, can be null
+     * @param listener Listener - a callback object to be called when messages are to be delivered to the new client
+     * @return Client - returns an implementation of the client interface.
+     */
+    public Client newClient(String idprefix, Listener listener);
+
+    /**
+     * retrieve a client based on an ID. Will return null if the client doesn't exist.
+     * @param clientid String
+     * @return Client-null if the client doesn't exist.returns the client if it does.
+     */
+    public Client getClient(String clientid);
+    
+    /**
+     * Returns a non modifiable list of all the clients that are currently active
+     * in this Bayeux session
+     * @return List<Client> - a list containing all clients. The List can not be modified.
+     */
+    public List<Client> getClients();
+    
+    /**
+     * Returns true if a client with the given id exists.<br/>
+     * Same as executing <code>getClient(id)!=null</code>.
+     * @param clientId String
+     * @return boolean - true if the client exists
+     */
+    public boolean hasClient(String clientId);
+    
+    /**
+     * Removes the client all together.
+     * This will unsubscribe the client to any channels it may be subscribed to
+     * and remove it from the list.
+     * @param client Client
+     * @return Client - returns the client that was removed, or null if no client was removed.
+     */
+    public Client remove(Client client);
+
+    
+    /*--Channel---------------------------------------------------------- */
+    /**
+     * Returns the channel for a given channel id.
+     * If the channel doesn't exist, and the <code>create</code> parameter is set to true,
+     * the channel will be created and added to the list of active channels.<br/>
+     * if <code>create</code> is set to false, and the channel doesn't exist, null will be returned.
+     * @param channelId String - the id of the channel to be retrieved or created
+     * @param create boolean - true if the Bayeux impl should create the channel
+     * @return Channel - null if <code>create</code> is set to false and the channel doesn't exist, 
+     * otherwise it returns a channel object.
+     */
+    public Channel getChannel(String channelId, boolean create);
+    
+    /**
+     * Returns a list of currently active channels in this Bayeux session.
+     * @return List<Channel>
+     */
+    public List<Channel> getChannels();
+
+    /**
+     * Removes a channel from the Bayeux object.
+     * This will also unsubscribe all the clients currently subscribed to the
+     * the channel.
+     * @param channel Channel - the channel to be removed
+     * @return Channel - returns the channel that was removed, or null if no channel was removed.
+     */
+    public Channel remove(Channel channel);
+
+    /**
+     * returns true if a channel with the given channelId exists.
+     * <br/>Same as executing <code>Bayeux.getChannel(channelId,false)!=null</code>
+     * @param channelId String
+     * @return boolean - true if the channel exists.
+     */
+    public boolean hasChannel(String channelId);
+
+    /* --Message---------------------------------------------------------- */
+    /**
+     * Creates a new message to be sent by a server side client.
+     * @return Message - returns a new Message object, that has a unique id.
+     */
+    public Message newMessage(Client from);
+
+
+    /*--Security policy----------------------------------------------------------- */
+    /**
+     * Returns the security policy associated with this Bayeux session
+     * @return SecurityPolicy
+     */
+    public SecurityPolicy getSecurityPolicy();
+   
+    /**
+     * Sets the security policy to be used in this Bayeux session
+     * @param securityPolicy SecurityPolicy
+     */
+    public void setSecurityPolicy(SecurityPolicy securityPolicy);
+
+}
\ No newline at end of file

Added: tomcat/trunk/java/org/apache/cometd/bayeux/Channel.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/cometd/bayeux/Channel.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/cometd/bayeux/Channel.java (added)
+++ tomcat/trunk/java/org/apache/cometd/bayeux/Channel.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,103 @@
+/*
+ * 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.cometd.bayeux;
+
+import java.util.List;
+
+/** 
+ * A Bayeux Channel represents a channel used to receive messages from and to publish messages to.
+ * In order to publish messages to or receive messages from, one must subscribe to the channel.
+ * This is easily done by invoking the <code>subscribe</code> method.
+ * A channel is created by calling the <code>Bayeux.getChannel(channelId,true)</code> method.
+ * A channel can be created either server side by invoking the getChannel, or client side
+ * by using the /meta/subscribe message without a wildcard.
+ * @author Greg Wilkins
+ * @author Filip Hanik
+ */
+public interface Channel
+{
+    /**
+     * Returns the id for this channel. The id is unique within bayeux session.
+     * @return String - will never be null.
+     */
+    public String getId();
+
+    /** 
+     * Publishes a message to all the subscribers of this channel.
+     * The <code>from</code> is contained within the message, by calling
+     * <code>msg.getClient()</code>
+     * @param data - the message to be published, can not be null.
+     */
+    public void publish(Message msg);
+    
+    /** 
+     * Publishes more than one message to all the subscribers of this channel.
+     * The <code>from</code> is contained within the message, by calling
+     * <code>msg[x].getClient()</code>
+     * @param data - the message to be published, can not be null.
+     */
+    public void publish(Message[] msgs);
+
+    /** 
+     * Non persistent channels are removed when the last subscription is
+     * removed. Persistent channels survive periods without any subscribers.
+     * @return true if the Channel will persist without any subscription.
+     */
+    public boolean isPersistent();
+    
+    /**
+     * @param persistent true if the Channel will persist without any subscription.
+     * @see isPersistent
+     */
+    public void setPersistent(boolean persistent);
+    
+    /** 
+     * Subscribes a client to a channel.
+     * @param subscriber - the client to be subscribed. If the client
+     * already is subscribed, this call will not create a duplicate subscription.
+     */
+    public void subscribe(Client subscriber);
+
+    /** 
+     * Unsubscribes a client from a channel
+     * @param subscriber - the client to be subscribed.
+     * @return - returns the client that was unsubscribed, or null if the client wasn't subscribed.
+     */
+    public Client unsubscribe(Client subscriber);
+
+    /**
+     * returns a non modifiable list of all the subscribers to this 
+     * channel.
+     * @return a list of subscribers
+     */
+    public List<Client> getSubscribers();
+    
+    /**
+     * Adds a data filter to this channel. All messages received by this channel 
+     * will run through this filter.
+     * @param filter Filter
+     */
+    public void addFilter(DataFilter filter);
+    
+    /**
+     * Removes a filter from this channel.
+     * returns the filter that was removed, or null if the filter wasn't in the channel.
+     * @param filter Filter
+     * @return Filter - null if no filter was removed otherwise it returns the filter that was removed.
+     */
+    public DataFilter removeFilter(DataFilter filter);
+}
\ No newline at end of file

Added: tomcat/trunk/java/org/apache/cometd/bayeux/Client.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/cometd/bayeux/Client.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/cometd/bayeux/Client.java (added)
+++ tomcat/trunk/java/org/apache/cometd/bayeux/Client.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,91 @@
+/*
+ * 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.cometd.bayeux;
+
+
+
+/** A Bayeux Client.
+ * <p>
+ * A client may subscribe to channels and publish messages to channels.
+ * Client instances should not be directly created by uses, but should 
+ * be obtained via the {@link Bayeux#getClient(String)} or {@link Bayeux#newClient(String, Listener)}
+ * methods.
+ * </p>
+ * <p>
+ * Three types of client may be represented by this interface:<nl>
+ * <li>The server representation of a remote client connected via HTTP, 
+ *     automatically created by the Bayeux server when a connect message comes in</li>
+ * <li>A server side client, created by the application using the {@link Bayeux#newClient(String, Listener)} method</li>
+ * <li>A java client connected to a remote Bayeux server - not implemented</li>
+ * </nl>
+ * @author Greg Wilkins
+ * @author Filip Hanik
+ */
+public interface Client
+{
+    /**
+     * Returns a unique id for this client. The id is unique within this Bayeux session.
+     * @return String - will not be null
+     */
+    public String getId();
+
+    /**
+     * Returns true if this client is holding messages to be delivered to the remote client.
+     * This method always returns false for local clients, since messages are delivered instantly using the 
+     * Listener(callback) object
+     * @return boolean
+     */
+    public boolean hasMessages();
+
+    /** 
+     * Deliver a message to this client only
+     * Deliver a message directly to the client. The message is not 
+     * filtered or published to a channel.
+     * @param message
+     */
+    public void deliver(Message message);
+
+    /** 
+     * Deliver a batch of messages to this client only
+     * Deliver a batch messages directly to the client. The messages are not 
+     * filtered or published to a channel.
+     * @param message
+     */
+    public void deliver(Message[] message);
+
+    /**
+     * @return True if the client is local. False if this client is either a remote HTTP client or
+     * a java client to a remote server. 
+     */
+    public boolean isLocal();
+    
+    /**
+     * Starts a batch, no messages will be delivered until endBatch is called.
+     * Batches can be nested, and messages will only be delivered after
+     * the last endBatch has been called.
+     */
+    public void startBatch();
+    
+    /**
+     * Ends a batch. since batches can be nested, messages will only be delivered
+     * after the endBatch has been called as many times as startBatch has.
+     */
+    public void endBatch();
+    
+    
+}
\ No newline at end of file

Added: tomcat/trunk/java/org/apache/cometd/bayeux/DataFilter.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/cometd/bayeux/DataFilter.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/cometd/bayeux/DataFilter.java (added)
+++ tomcat/trunk/java/org/apache/cometd/bayeux/DataFilter.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,38 @@
+/*
+ * 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.cometd.bayeux;
+
+/** 
+ * Data Filter<br/>
+ * Data filters are used to transform data as it is sent to a Channel.
+ * Messages are filtered as the message is published to a channel, invoking the 
+ * {@link Channel#publish(Message)} method.<br/>
+ * This method gets invoked in two different scenarios, the first being when a message is received from
+ * a remote client, and the Bayeux implementation invokes the publish method directly.
+ * The second scenario is when a local client invokes {@link Channel#publish(Message)} directly in the local JVM.
+ * @author Greg Wilkins
+ * @author Filip Hanik
+ *
+ */
+public interface DataFilter
+{
+    /**
+     * Runs a message through the filter. Filtering can only modify an existing object, it can not replace it.
+     * @param data Message - the message to be filtered, may not be null
+     */
+    public void filter(Message data);
+}

Added: tomcat/trunk/java/org/apache/cometd/bayeux/Listener.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/cometd/bayeux/Listener.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/cometd/bayeux/Listener.java (added)
+++ tomcat/trunk/java/org/apache/cometd/bayeux/Listener.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,45 @@
+/*
+ * 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.cometd.bayeux;
+
+/** 
+ * Cometd Listener interface.<br/>
+ * For local clients, in order to receive messages, they pass in a callback object
+ * when the local client is created using the {@link Bayeux#newClient(String,Listener)} method.
+ * This callback object, implementing the Listener interface, is used to deliver messages to local, in JVM, clients.
+ * @author Greg Wilkins
+ * @author Filip Hanik
+ *
+ */
+public interface Listener
+{
+    /**
+     * This method is called when the client is removed (explicitly or from a timeout)
+     * @param timeout - true if the client was removed from a timeout
+     * false if it was removed explicitly.
+     */
+    public void removed(boolean timeout);
+    
+    /**
+     * Invoked when a message is delivered to the client.
+     * The message contains the message itself, as well as what channel this message came through
+     * and who the sender is. If someone invoked {@link Client#deliver(Message)} then the channel reference will
+     * be null.
+     * @param msg 
+     */
+    public void deliver(Message[] msg);
+}

Added: tomcat/trunk/java/org/apache/cometd/bayeux/Message.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/cometd/bayeux/Message.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/cometd/bayeux/Message.java (added)
+++ tomcat/trunk/java/org/apache/cometd/bayeux/Message.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,68 @@
+/*
+ * 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.cometd.bayeux;
+
+import java.util.Map;
+
+/** 
+ * A Bayeux Message<br/>
+ * A Bayeux message is a Map of String/Object key value pairs representing the data in the message.
+ * The message contains information about the channel it was published through and who the sender was
+ * 
+ * @author Greg Wilkins
+ * @author Filip Hanik
+ */
+public interface Message extends Map<String,Object>
+{
+    /**
+     * Returns a reference to the client that sent this message
+     * @return Client - may be null
+     */
+    public Client getClient();
+    /**
+     * Returns a reference to the channel that this message was published throuhg
+     * @return Channel - may be null
+     */
+    public Channel getChannel();
+    /**
+     * Returns the unique id of this message
+     * @return String
+     */
+    public String getId();
+    
+    /**
+     * Sets the time to live in milliseconds. If the message hasn't been delivered 
+     * when the time passed after the creation time is longer than the TTL the message will
+     * expire and removed from any delivery queues.
+     * @param ttl long
+     */
+    public void setTTL(long ttl);
+    
+    /**
+     * Returns the time to live (in milliseconds) for this message
+     * @return long
+     */
+    public long getTTL();
+    
+    /**
+     * returns the timestamp in milliseconds(System.currentTimeMillis()) of when this message was created.
+     * @return long
+     */
+    public long getCreationTime();
+}
+
+

Added: tomcat/trunk/java/org/apache/cometd/bayeux/SecurityPolicy.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/cometd/bayeux/SecurityPolicy.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/cometd/bayeux/SecurityPolicy.java (added)
+++ tomcat/trunk/java/org/apache/cometd/bayeux/SecurityPolicy.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,28 @@
+/*
+ * 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.cometd.bayeux;
+
+/**
+ * @author Greg Wilkins
+ */
+public interface SecurityPolicy
+{
+    boolean canHandshake(Message message);
+    boolean canCreate(Client client,String channel,Message message);
+    boolean canSubscribe(Client client,String channel,Message messsage);
+    boolean canPublish(Client client,String channel,Message messsage);
+}

Added: tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxException.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxException.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxException.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxException.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,39 @@
+/*
+ * 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.tomcat.bayeux;
+/**
+ * 
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class BayeuxException extends Exception {
+    public BayeuxException() {
+        super();
+    }
+
+    public BayeuxException(String message) {
+        super(message);
+    }
+
+    public BayeuxException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public BayeuxException(Throwable cause) {
+        super(cause);
+    }
+}
\ No newline at end of file

Added: tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxRequest.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxRequest.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxRequest.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxRequest.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,54 @@
+/*
+ * 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.tomcat.bayeux;
+
+import org.apache.tomcat.bayeux.HttpError;
+
+/**
+ * An interface that defines methods for managing Bayeux request meta 
+ * messages.
+ *
+ * @author Guy A. Molinari
+ * @author Filip Hanik
+ * @version 0.9
+ */
+public interface BayeuxRequest {
+
+    public static final String LAST_REQ_ATTR = "org.apache.cometd.bayeux.last_request";
+    public static final String CURRENT_REQ_ATTR = "org.apache.cometd.bayeux.current_request";
+    public static final String JSON_MSG_ARRAY = "org.apache.cometd.bayeux.json_msg_array";
+
+    /**
+     * Validates a specific request. 
+     * This method must be called prior to process()
+     * as a request can do pre processing in the validate method.
+     * <br/>
+     * Should the validation fail, an error object is returned 
+     * containing an error message, and potentially a stack trace
+     * if an exception was generated
+     * @return HttpError - null if no error was detected, an HttpError object containing information about the error.
+     */
+    public HttpError validate();
+    
+    /**
+     * processes a remote client Bayeux message
+     * @param prevops - the operation requested by the previous request, in case of chained requests.
+     * @return int - returns the interest operation for a CometEvent. Currently not used
+     * @throws BayeuxException - if an error was detected, and the appropriate error response couldn't be delivered to the client. 
+     */
+    public int process(int prevops) throws BayeuxException;
+}

Added: tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxServlet.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxServlet.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxServlet.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/bayeux/BayeuxServlet.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,236 @@
+/*
+ * 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.tomcat.bayeux;
+
+import java.io.IOException;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.catalina.CometEvent;
+import org.apache.catalina.CometProcessor;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.apache.cometd.bayeux.Bayeux;
+
+/**
+ * 
+ * @author Filip Hanik
+ * @author Guy Molinari
+ * @version 1.0
+ */
+public class BayeuxServlet implements CometProcessor {
+
+    /**
+     * Attribute to hold the TomcatBayeux object in the servlet context
+     */
+    public static final String TOMCAT_BAYEUX_ATTR = Bayeux.DOJOX_COMETD_BAYEUX;
+    
+    /**
+     * Logger object
+     */
+    protected static Log log = LogFactory.getLog(BayeuxServlet.class);
+
+    /**
+     * Servlet config - for future use
+     */
+    protected ServletConfig servletConfig;
+    
+    /**
+     * Reference to the global TomcatBayeux object
+     */
+    protected TomcatBayeux tb;
+    
+    /**
+     * Upon servlet destruction, the servlet will clean up the 
+     * TomcatBayeux object and terminate any outstanding events.
+     */
+    public void destroy() {
+        servletConfig = null;
+        //to do, close all outstanding comet events
+        //tb.destroy();
+        tb = null;//TO DO, close everything down
+        
+    }
+    
+    /**
+     * Returns the preconfigured connection timeout.
+     * If no timeout has been configured as a servlet init parameter named <code>timeout</code>
+     * then the default of 2min will be used.
+     * @return int - the timeout for a connection in milliseconds
+     */
+    protected int getTimeout() {
+        String timeoutS = servletConfig.getInitParameter("timeout");
+        int timeout = 120*1000; //2 min
+        try {
+            timeout = Integer.parseInt(timeoutS);
+        }catch (NumberFormatException nfe) {
+            //ignore, we have a default value
+        }
+        return timeout;
+    }
+    
+    protected int getReconnectInterval() {
+        String rs = servletConfig.getInitParameter("reconnectInterval");
+        int rct = 5000; //5 seconds
+        try {
+            rct = Integer.parseInt(rs);
+        }catch (NumberFormatException nfe) {
+            //ignore, we have a default value
+        }
+        return rct;
+    }
+
+
+    public void event(CometEvent cometEvent) throws IOException, ServletException {
+        CometEvent.EventType type = cometEvent.getEventType();
+        if (log.isDebugEnabled()) {
+            log.debug("["+Thread.currentThread().getName()+"] Received Comet Event type="+type+" subtype:"+cometEvent.getEventSubType());
+        }
+        synchronized (cometEvent) {
+            if (type==CometEvent.EventType.BEGIN) {
+                //begin event, set the timeout
+                cometEvent.setTimeout(getTimeout());
+                //checkBayeux(cometEvent); - READ event should always come
+            } else if (type==CometEvent.EventType.READ) {
+                checkBayeux(cometEvent);
+            } else if (type==CometEvent.EventType.ERROR) {
+                tb.remove(cometEvent);
+                cometEvent.close();
+            } else if (type==CometEvent.EventType.END) {
+                tb.remove(cometEvent);
+                cometEvent.close();
+            }//end if
+            
+        }//synchronized
+    }//event
+
+    /**
+     * 
+     * @param cometEvent CometEvent
+     * @return boolean - true if we comet event stays open
+     * @throws IOException
+     * @throws UnsupportedOperationException
+     */
+    protected void checkBayeux(CometEvent cometEvent) throws IOException, UnsupportedOperationException {
+        //we actually have data.
+        //data can be text/json or 
+        if (Bayeux.JSON_CONTENT_TYPE.equals(cometEvent.getHttpServletRequest().getContentType())) {
+            //read and decode the bytes according to content length
+            log.warn("["+Thread.currentThread().getName()+"] JSON encoding not supported, will throw an exception and abort the request.");
+            int contentlength = cometEvent.getHttpServletRequest().getContentLength();
+            throw new UnsupportedOperationException("Decoding "+Bayeux.JSON_CONTENT_TYPE+" not yet implemented.");
+        } else { //GET method or application/x-www-form-urlencoded
+            String message = cometEvent.getHttpServletRequest().getParameter(Bayeux.MESSAGE_PARAMETER);
+            if (log.isTraceEnabled()) {
+                log.trace("["+Thread.currentThread().getName()+"] Received JSON message:"+message);
+            }
+            try {
+                int action = handleBayeux(message, cometEvent);
+                if (log.isDebugEnabled()) {
+                    log.debug("["+Thread.currentThread().getName()+"] Bayeux handling complete, action result="+action);
+                }
+                if (action<=0) {
+                    cometEvent.close();
+                }
+            }catch (Exception x) {
+                x.printStackTrace();
+                tb.remove(cometEvent);
+                log.error(x);
+                cometEvent.close();
+            }
+        }
+    }
+    
+    protected int handleBayeux(String message, CometEvent event) throws IOException, ServletException {
+        int result = 0;
+        if (message==null || message.length()==0) return result;
+        try {
+            BayeuxRequest request = null;
+            //a message can be an array of messages
+            JSONArray jsArray = new JSONArray(message);
+            for (int i = 0; i < jsArray.length(); i++) {
+                JSONObject msg = jsArray.getJSONObject(i);
+                
+                if (log.isDebugEnabled()) {
+                    log.debug("["+Thread.currentThread().getName()+"] Processing bayeux message:"+msg);
+                }
+                request = RequestFactory.getRequest(tb,event,msg);
+                if (log.isDebugEnabled()) {
+                    log.debug("["+Thread.currentThread().getName()+"] Processing bayeux message using request:"+request);
+                }
+                result = request.process(result);
+                if (log.isDebugEnabled()) {
+                    log.debug("["+Thread.currentThread().getName()+"] Processing bayeux message result:"+result);
+                }
+            }
+            if (result>0 && request!=null) {
+                event.getHttpServletRequest().setAttribute(BayeuxRequest.LAST_REQ_ATTR, request);
+                ClientImpl ci = (ClientImpl)tb.getClient(((RequestBase)request).getClientId());
+                ci.addCometEvent(event);
+                if (log.isDebugEnabled()) {
+                    log.debug("["+Thread.currentThread().getName()+"] Done bayeux message added to request attribute");
+                }
+            } else if (result == 0 && request!=null) {
+                RequestBase.deliver(event,(ClientImpl)tb.getClient(((RequestBase)request).getClientId()));
+                if (log.isDebugEnabled()) {
+                    log.debug("["+Thread.currentThread().getName()+"] Done bayeux message, delivered to client");
+                }
+            }
+            
+        }catch (JSONException x) {
+            log.error(x);//to do impl error handling
+            result = -1;
+        }catch (BayeuxException x) {
+            log.error(x); //to do impl error handling
+            result = -1;
+        }
+        return result;
+    }
+
+    public ServletConfig getServletConfig() {
+        return servletConfig;
+    }
+
+    public String getServletInfo() {
+        return "Tomcat/BayeuxServlet/1.0";
+    }
+
+    public void init(ServletConfig servletConfig) throws ServletException {
+        
+        this.servletConfig = servletConfig;
+        ServletContext ctx = servletConfig.getServletContext();
+        if (ctx.getAttribute(TOMCAT_BAYEUX_ATTR)==null)
+            ctx.setAttribute(TOMCAT_BAYEUX_ATTR,new TomcatBayeux());
+        this.tb = (TomcatBayeux)ctx.getAttribute(TOMCAT_BAYEUX_ATTR);
+        tb.setReconnectInterval(getReconnectInterval());
+    }
+
+    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
+        if (servletResponse instanceof HttpServletResponse) {
+            ( (HttpServletResponse) servletResponse).sendError(500, "Misconfigured Tomcat server, must be configured to support Comet operations.");
+        } else {
+            throw new ServletException("Misconfigured Tomcat server, must be configured to support Comet operations for the Bayeux protocol.");
+        }
+    }
+}

Added: tomcat/trunk/java/org/apache/tomcat/bayeux/ChannelImpl.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/bayeux/ChannelImpl.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/bayeux/ChannelImpl.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/bayeux/ChannelImpl.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,189 @@
+/*
+ * 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.tomcat.bayeux;
+
+import java.util.LinkedList;
+
+import org.apache.cometd.bayeux.Channel;
+import org.apache.cometd.bayeux.Client;
+import org.apache.cometd.bayeux.DataFilter;
+import java.util.Collections;
+import java.util.List;
+import org.apache.cometd.bayeux.Message;
+import java.util.Iterator;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+/**
+ * 
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class ChannelImpl implements Channel {
+    
+    protected static Log log = LogFactory.getLog(ChannelImpl.class);
+    
+    /**
+     * The unique id of this channel
+     */
+    protected String id = null;
+    
+    /**
+     * A list of the current subscribers
+     */
+    protected LinkedList<Client> subscribers = new LinkedList<Client>();
+    
+    /**
+     * A list of the current filters
+     */
+    protected LinkedList<DataFilter> filters = new LinkedList<DataFilter>();
+    
+    /**
+     * Is this channel persistent, default value is true
+     */
+    protected boolean persistent = true; 
+    
+    /**
+     * Creates a new channel
+     * @param id String - the id of the channel, can not be null
+     */
+    protected ChannelImpl(String id) {
+        assert id != null;
+        this.id = id;
+    }
+
+    /**
+     * returns the id of this channel
+     * @return String
+     */
+    public String getId() {
+        return id;
+    }
+    
+    /**
+     * Returns true if this channel matches the pattern to its id.
+     * The channel pattern can be a complete name like <code>/service/mychannel</code>
+     * or it can be a wild card pattern like <code>/service/app2/**</code>
+     * @param pattern String according to the Bayeux specification section 2.2.1 Channel Globbing, can not be null.
+     * @return boolean true if the id of this channel matches the pattern
+     */
+    public boolean matches(String pattern) {
+        if (pattern == null)
+            throw new NullPointerException("Channel pattern must not be null.");
+        if (getId().equals(pattern))
+            return true;
+        int wildcardPos = pattern.indexOf("/*");
+        if (wildcardPos == -1)
+            return false;
+        boolean multiSegment = pattern.indexOf("**") != -1;
+        String leadSubstring = pattern.substring(0, wildcardPos);
+        if (leadSubstring == null)
+            return false;
+        if (multiSegment) 
+            return getId().startsWith(leadSubstring);
+        else {
+            if (getId().length() <= wildcardPos + 2)
+                return false;
+            return !(getId().substring(wildcardPos + 2).contains("/"));
+        }
+    }
+
+
+
+    /**
+     * @return returns a non modifiable list of the subscribers for this channel.
+     */
+    public List<Client> getSubscribers() {
+        return Collections.unmodifiableList(subscribers);
+    }
+
+    /**
+     * @return true if the Channel will persist without any subscription.
+     */
+    public boolean isPersistent() {
+        return persistent;
+    }
+    
+    public void publish(Message msg) {
+        publish(new Message[] {msg});
+    }
+
+    public void publish(Message[] msgs) {
+        if (msgs==null) return;
+        MessageImpl[] imsgs = new MessageImpl[msgs.length];
+        for (int i=0; msgs!=null && i<msgs.length; i++) {
+            Message data = msgs[i];
+
+            if (!(data instanceof MessageImpl)) 
+                throw new IllegalArgumentException("Invalid message class, you can only publish messages "+
+                                                   "created through the Bayeux.newMessage() method");
+            if (log.isDebugEnabled()) {
+                log.debug("Publishing message:"+data+" to channel:"+this);
+            }
+            //clone it so that we can set this channel as a reference
+            MessageImpl msg = (MessageImpl)((MessageImpl)data).clone();
+            //this is the channel it was delivered through
+            msg.setChannel(this);
+            //pass through filters
+            for (Iterator<DataFilter> it = filters.iterator(); it.hasNext(); ) {
+                it.next().filter(msg);
+            }
+            imsgs[i] = msg;
+        }
+        //deliver it to the clients
+        for (Iterator<Client> it = subscribers.iterator(); it.hasNext(); ) {
+            ClientImpl c = (ClientImpl)it.next();
+            c.deliverInternal(this,imsgs);
+        }
+        
+    }
+
+    public void setPersistent(boolean persistent) {
+        this.persistent = persistent;
+    }
+
+    public void subscribe(Client subscriber) {
+        if (!subscribers.contains((subscriber))) { 
+            subscribers.addLast(subscriber);
+            ((ClientImpl)subscriber).subscribed(this);
+        }
+    }
+
+    public Client unsubscribe(Client subscriber) {
+        if (subscribers.remove(subscriber)) {
+            ((ClientImpl)subscriber).unsubscribed(this);
+            return subscriber;
+        } else
+            return null;
+    }
+    
+    public void addFilter(DataFilter filter) {
+        if (!filters.contains(filter)) 
+            filters.addLast(filter);
+    }
+
+    public DataFilter removeFilter(DataFilter filter) {
+        if ( filters.remove(filter) ) return filter;
+        else return null;
+    }
+    
+    public String toString() {
+        StringBuffer buf = new StringBuffer(super.toString());
+        buf.append("; channelId=").append(getId());
+        return buf.toString();
+    }
+
+}
\ No newline at end of file

Added: tomcat/trunk/java/org/apache/tomcat/bayeux/ClientImpl.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/bayeux/ClientImpl.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/bayeux/ClientImpl.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/bayeux/ClientImpl.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,278 @@
+/*
+ * 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.tomcat.bayeux;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.apache.catalina.CometEvent;
+import org.json.JSONObject;
+import org.apache.cometd.bayeux.Bayeux;
+import org.apache.cometd.bayeux.Client;
+import org.apache.cometd.bayeux.Listener;
+import org.apache.cometd.bayeux.Message;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.HashMap;
+import java.util.ArrayList;
+
+public class ClientImpl implements Client {
+    
+    public static final int SUPPORT_CALLBACK_POLL = 0x1;
+    public static final int SUPPORT_LONG_POLL = 0x2; 
+
+    public static final String COMET_EVENT_ATTR = "org.apache.cometd.bayeux.client";
+    
+    protected static Log log = LogFactory.getLog(ClientImpl.class);
+
+    protected static LinkedList<Message> EMPTY_LIST = new LinkedList<Message>();
+    /**
+     * queued message for remote clients.
+     */
+    protected LinkedList<Message> messages = null;
+    
+    /**
+     * 
+     */
+    protected Queue<CometEvent> events = new LinkedList<CometEvent>();
+    
+    /**
+     * Unique id representing this client
+     */
+    protected String id;
+    
+    /**
+     * supported connection types, defaults to long-polling
+     */
+    protected int supportedConnTypes = SUPPORT_LONG_POLL | SUPPORT_CALLBACK_POLL;
+    
+    /**
+     * The desired connection type
+     */
+    protected int desirectConnType = SUPPORT_LONG_POLL;
+    
+    /**
+     * Does this client use json-comment-filtered messages
+     */
+    protected boolean useJsonFiltered = false;
+    
+    /**
+     * Same JVM clients, get local=true
+     */
+    protected boolean local;
+    
+    /**
+     * The callback object for local clients
+     */
+    protected Listener listener;
+    
+    protected AtomicInteger nrofsubscriptions = new AtomicInteger(0);
+    
+    protected ClientImpl(String id, boolean local) {
+        this.id = id;
+        this.local = local;
+        if (!local) messages = new LinkedList<Message>();
+    }
+    
+    protected ClientImpl(String id, CometEvent event) {
+        this(id,false);
+        events = new ConcurrentLinkedQueue<CometEvent>();
+        addCometEvent(event);
+    }
+
+    public synchronized void deliver(Message message) {
+        deliverInternal(null,new MessageImpl[] {(MessageImpl)message});
+    }
+    
+    public synchronized void deliver(Message[] message) {
+        deliverInternal(null,message);
+    }
+
+    protected synchronized void deliverInternal(ChannelImpl channel, MessageImpl message) {
+        deliverInternal(channel,new MessageImpl[] {message});
+    }
+
+    protected synchronized void deliverInternal(ChannelImpl channel, Message[] msgs) {
+        if (isLocal()) {
+            //local clients must have a listener
+            ArrayList<Message> list = new ArrayList<Message>();
+            for (int i=0; msgs!=null && i<msgs.length; i++) {
+                if (this!=msgs[i].getClient()) list.add(msgs[i]);
+            }
+            if (getListener() != null) {
+                getListener().deliver(list.toArray(new Message[0]));
+            }
+        } else {
+            for (int i=0; msgs!=null && i<msgs.length; i++) {
+                MessageImpl message = (MessageImpl)msgs[i];
+                if (this==message.getClient()) { 
+                    //dont deliver to ourself
+                    continue;
+                }
+                //we are not implementing forever responses, if the client is connected
+                //then we will fire off the message
+                //first we check to see if we have any existing connections we can piggy back on
+                CometEvent event = events.poll();
+                boolean delivered = false;
+                //TODO TODO - check on thread safety, for writing and for getting last request.
+                if (event!=null) {
+                    synchronized (event) {
+                        RequestBase rq = (RequestBase)event.getHttpServletRequest().getAttribute(RequestBase.LAST_REQ_ATTR);
+                        if (rq!=null) {
+                            Map map = new HashMap();
+                            try {
+                                map.put(Bayeux.CHANNEL_FIELD,message.getChannel().getId());
+                                map.put(Bayeux.DATA_FIELD,message);
+                                JSONObject json = new JSONObject(map);
+                                if (log.isDebugEnabled()) {
+                                    log.debug("Message instantly delivered to remote client["+this+"] message:"+json);
+                                }
+                                rq.addToDeliveryQueue(this, json);
+                                //deliver the batch
+                                if (i==(msgs.length-1)) {
+                                    rq.deliver(event, this);
+                                    event.close(); //todo, figure out a better way, this means only one message gets delivered
+                                    removeCometEvent(event); //and delivered instantly
+                                }
+                                delivered = true;
+                            } catch (Exception x) {
+                                log.error(x);
+                            }
+                        }
+                    }
+                } 
+                if (!delivered) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Message added to queue for remote client["+this+"] message:"+message);
+                    }
+                    //queue the message for the next round
+                    messages.add(message);
+                }
+            }
+        }
+    }
+
+    public String getId() {
+        return this.id;
+    }
+
+    protected Listener getListener() {
+        return listener;
+    }
+
+    public boolean hasMessages() {
+        if (isLocal()) return false;
+        else {
+            return messages.size() > 0;
+        }
+    }
+
+    public boolean isLocal() {
+        return local;
+    }
+
+    public int getSupportedConnTypes() {
+        return supportedConnTypes;
+    }
+
+    public int getDesirectConnType() {
+        return desirectConnType;
+    }
+
+    public boolean useJsonFiltered() {
+        return useJsonFiltered;
+    }
+
+    public void setListener(Listener listener) {
+        this.listener = listener;
+    }
+
+    public void setSupportedConnTypes(int supportedConnTypes) {
+        this.supportedConnTypes = supportedConnTypes;
+    }
+
+    public void setUseJsonFiltered(boolean useJsonFiltered) {
+        this.useJsonFiltered = useJsonFiltered;
+    }
+
+    public void setDesirectConnType(int desirectConnType) {
+        this.desirectConnType = desirectConnType;
+    }
+
+    public boolean supportsCallbackPoll() {
+        return (supportedConnTypes & SUPPORT_CALLBACK_POLL) == SUPPORT_CALLBACK_POLL;
+    }
+
+    public boolean supportsLongPoll() {
+        return (supportedConnTypes & SUPPORT_LONG_POLL) == SUPPORT_LONG_POLL;
+    }
+
+    public synchronized List<Message> takeMessages() {
+        if (isLocal()) return null;
+        if (messages.size()==0) return EMPTY_LIST;
+        List result = new LinkedList(messages);
+        messages.clear();
+        return result;
+    }
+    
+    public String toString() {
+        StringBuffer buf = new StringBuffer(super.toString());
+        buf.append(" id=").append(getId());
+        return buf.toString();
+    }
+    
+    public boolean isSubscribed() {
+        return nrofsubscriptions.get()>0;
+    }
+    
+    protected synchronized boolean addCometEvent(CometEvent event) {
+        boolean result = false;
+        if (!events.contains(event)) {
+            events.add(event);
+            result = true;
+        }
+        event.getHttpServletRequest().setAttribute(COMET_EVENT_ATTR,this);
+        return result;
+    }
+    
+    protected synchronized boolean removeCometEvent(CometEvent event) {
+        boolean result = events.remove(event);
+        event.getHttpServletRequest().removeAttribute(COMET_EVENT_ATTR);
+        return result;
+    }
+    
+    
+    protected void subscribed(ChannelImpl ch) {
+        nrofsubscriptions.addAndGet(1);
+    }
+    
+    protected void unsubscribed(ChannelImpl ch) {
+        nrofsubscriptions.addAndGet(-1);
+    }
+    
+    public void startBatch(){
+        //noop until improved
+    }
+    public void endBatch() {
+        //noop until improved
+    }
+        
+}

Added: tomcat/trunk/java/org/apache/tomcat/bayeux/HttpError.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/bayeux/HttpError.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/bayeux/HttpError.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/bayeux/HttpError.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,43 @@
+package org.apache.tomcat.bayeux;
+
+public class HttpError {
+    private int code;
+    private String status;
+    private Throwable cause;
+    public HttpError(int code, String status, Throwable cause) {
+        this.code = code;
+        this.status = status;
+        this.cause = cause;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public void setCause(Throwable exception) {
+        this.cause = exception;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public Throwable getCause() {
+        return cause;
+    }
+
+    public String toString() {
+        if (cause != null)
+            return code + ":" + status + " - [" + cause + "]";
+        else
+            return code + ":" + status;
+    }
+}

Added: tomcat/trunk/java/org/apache/tomcat/bayeux/MessageImpl.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/bayeux/MessageImpl.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/bayeux/MessageImpl.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/bayeux/MessageImpl.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,80 @@
+/*
+ * 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.tomcat.bayeux;
+
+import java.util.HashMap;
+
+import org.apache.cometd.bayeux.Channel;
+import org.apache.cometd.bayeux.Client;
+import org.apache.cometd.bayeux.Message;
+
+public class MessageImpl extends HashMap<String,Object> implements Message {
+    
+    protected Channel channel;
+    protected Client client;
+    protected String id;
+    private long TTL = 1000*60*5; //5min is the default TTL for a message
+    protected long creationTime = System.currentTimeMillis();
+
+    public Object clone() {
+        MessageImpl copy = new MessageImpl(id);
+        copy.putAll(this);
+        copy.channel = channel;
+        copy.client = client;
+        copy.id = id;
+        copy.creationTime = creationTime;
+        copy.TTL = TTL;
+        return copy;
+    }
+
+    protected MessageImpl(String id) {
+        assert id != null;
+        this.id = id;
+    }
+
+    public Channel getChannel() {
+        return channel;
+    }
+
+    public Client getClient() {
+        return client;
+    }
+
+    public long getCreationTime() {
+        return creationTime;
+    }
+
+    public long getTTL() {
+        return TTL;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    protected void setChannel(Channel channel) {
+        this.channel = channel;
+    }
+
+    protected void setClient(Client client) {
+        this.client = client;
+    }
+
+    public void setTTL(long TTL) {
+        this.TTL = TTL;
+    }
+}
\ No newline at end of file

Added: tomcat/trunk/java/org/apache/tomcat/bayeux/RequestBase.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/bayeux/RequestBase.java?rev=691359&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/bayeux/RequestBase.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/bayeux/RequestBase.java Tue Sep  2 13:00:36 2008
@@ -0,0 +1,251 @@
+/*
+ * 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.tomcat.bayeux;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.Date;
+import java.text.SimpleDateFormat;
+import javax.servlet.ServletException;
+
+import org.apache.catalina.CometEvent;
+import org.apache.tomcat.bayeux.HttpError;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.apache.cometd.bayeux.Bayeux;
+import org.apache.cometd.bayeux.Message;
+
+/**
+ * Common functionality and member variables for all Bayeux requests.
+ *
+ * @author Guy A. Molinari
+ * @author Filip Hanik
+ * @version 0.9
+ *
+ */
+public abstract class RequestBase implements BayeuxRequest {
+    
+    protected static final SimpleDateFormat timestampFmt =
+        new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+    static {
+        timestampFmt.setTimeZone(TimeZone.getTimeZone("GMT"));
+    }
+    //message properties, combined for all messages
+    protected TomcatBayeux tomcatBayeux;
+    protected String channel;
+    protected String id;
+    protected String clientId;
+    protected String version = null;
+    protected String[] suppConnTypes = null;
+    protected int suppConnTypesFlag = 0;
+    protected int desiredConnTypeFlag = 0;
+    protected String minVersion = null;
+    protected String subscription = null;
+    protected String data = null;
+    protected String conType = null;
+    protected LinkedHashMap<String, Object> ext = new LinkedHashMap<String, Object> ();
+
+    
+    protected CometEvent event;
+    
+    protected HashMap<String, Object> response = null;
+    
+    protected static Log log = LogFactory.getLog(RequestBase.class);
+    
+    protected int reconnectInterval;
+    
+    protected RequestBase(TomcatBayeux tb, CometEvent event, JSONObject jsReq) throws JSONException {
+        this.tomcatBayeux = tb;
+        this.event = event;
+        channel = jsReq.optString(Bayeux.CHANNEL_FIELD);
+        id = jsReq.optString(Bayeux.ID_FIELD);
+        clientId = jsReq.optString(Bayeux.CLIENT_FIELD);
+        version = jsReq.optString(Bayeux.VERSION_FIELD);
+        minVersion = jsReq.optString(Bayeux.MIN_VERSION_FIELD);
+        conType = jsReq.optString(Bayeux.CONNECTION_TYPE_FIELD);
+        subscription = jsReq.optString(Bayeux.SUBSCRIPTION_FIELD);
+        data = jsReq.optString(Bayeux.DATA_FIELD);
+        reconnectInterval = tb.getReconnectInterval();
+        if (jsReq.has(Bayeux.EXT_FIELD)) {
+            JSONObject jext = jsReq.getJSONObject(Bayeux.EXT_FIELD);
+            for (Iterator<String> i = jext.keys(); i.hasNext(); ) {
+                String key = i.next();
+                ext.put(key, jext.get(key));
+            }//for
+        }//end if
+        
+        if (jsReq.has(Bayeux.SUPP_CONNECTION_TYPE_FIELD)) {
+            JSONArray types = jsReq.getJSONArray(Bayeux.SUPP_CONNECTION_TYPE_FIELD);
+            suppConnTypes = new String[types.length()];
+            for (int i = 0; i < types.length(); i++) {
+                suppConnTypes[i] = types.getString(i);
+                if (Bayeux.TRANSPORT_CALLBACK_POLL.equals(suppConnTypes[i]))
+                    suppConnTypesFlag = suppConnTypesFlag|ClientImpl.SUPPORT_CALLBACK_POLL;
+                else if (Bayeux.TRANSPORT_LONG_POLL.equals(suppConnTypes[i]))
+                    suppConnTypesFlag = suppConnTypesFlag|ClientImpl.SUPPORT_LONG_POLL;
+            }//for
+        }//end if
+
+        if (conType!=null) {
+            if (Bayeux.TRANSPORT_CALLBACK_POLL.equals(conType))
+                desiredConnTypeFlag = ClientImpl.SUPPORT_CALLBACK_POLL;
+            else if (Bayeux.TRANSPORT_LONG_POLL.equals(conType))
+                desiredConnTypeFlag = ClientImpl.SUPPORT_LONG_POLL;
+        }//end if
+        
+        //due to the fact that the javascript doesn't send up a required field
+        //we have to fake it
+        suppConnTypesFlag = ClientImpl.SUPPORT_CALLBACK_POLL | ClientImpl.SUPPORT_LONG_POLL;
+
+    }
+
+    public HttpError validate() {
+        HttpError result = null;
+//        if (clientId == null) {
+//            result = new HttpError(401,"No Client ID.", null);
+//        }
+        return result;
+    }
+
+    public TomcatBayeux getTomcatBayeux() {
+        return tomcatBayeux;
+    }
+
+    public String getChannel() {
+        return channel;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public LinkedHashMap getExt() {
+        return ext;
+    }
+
+    public CometEvent getEvent() {
+        return event;
+    }
+    
+    protected static void deliver(CometEvent event, ClientImpl to) throws IOException, ServletException, BayeuxException {
+        JSONArray jarray = getJSONArray(event,true);
+        if ( jarray == null ) throw new BayeuxException("No message to send!");
+        String jsonstring = jarray.toString();
+        if (log.isDebugEnabled()) {
+            log.debug("["+Thread.currentThread().getName()+"] Delivering message to[" + to + "] message:" + jsonstring);
+        }
+
+        PrintWriter out = event.getHttpServletResponse().getWriter();
+        if (to==null) {
+            //do nothing
+        }else if ( (to.getDesirectConnType() == 0 && to.supportsLongPoll()) || to.getDesirectConnType() == ClientImpl.SUPPORT_LONG_POLL) {
+            if (to.useJsonFiltered())
+                out.print("/*");
+        } else if ( (to.getDesirectConnType() == 0 && to.supportsCallbackPoll()) || to.getDesirectConnType() == ClientImpl.SUPPORT_CALLBACK_POLL) {
+            String jsonp = event.getHttpServletRequest().getParameter(Bayeux.JSONP_PARAMETER);
+            if (jsonp == null)
+                jsonp = Bayeux.JSONP_DEFAULT_NAME;
+            out.print(jsonp);
+            out.print('(');
+        } else {
+            throw new BayeuxException("Client doesn't support any appropriate connection type.");
+        }
+        out.print(jsonstring);
+        if ( to == null ) {
+            //do nothing
+        } else if ( (to.getDesirectConnType() == 0 && to.supportsLongPoll()) || to.getDesirectConnType() == ClientImpl.SUPPORT_LONG_POLL) {
+            if (to.useJsonFiltered())
+                out.print("*/");
+        } else if ( (to.getDesirectConnType() == 0 && to.supportsCallbackPoll()) || to.getDesirectConnType() == ClientImpl.SUPPORT_CALLBACK_POLL) {
+            out.print(");");
+        } 
+        out.flush();
+        event.getHttpServletResponse().flushBuffer();
+
+        
+    }
+
+    protected static JSONArray getJSONArray(CometEvent event, boolean nullok) {
+        synchronized(event) {
+            JSONArray jarray = (JSONArray) event.getHttpServletRequest().getAttribute(JSON_MSG_ARRAY);
+            if (jarray == null && (!nullok)) {
+                jarray = new JSONArray();
+                event.getHttpServletRequest().setAttribute(JSON_MSG_ARRAY, jarray);
+            }
+            return jarray;
+        }
+    }
+
+    protected JSONArray getJSONArray() {
+        return getJSONArray(event,false);
+    }
+
+    protected void addToDeliveryQueue(ClientImpl to, JSONObject msg) throws IOException, ServletException, BayeuxException {
+        synchronized (event) {
+            getJSONArray().put(msg);
+        }
+    }
+    
+    protected void flushMessages(ClientImpl client) throws BayeuxException {
+        List<Message> msgs = client.takeMessages();
+        synchronized (event) {
+            try {
+                for (Iterator<Message> it = msgs.iterator(); it.hasNext(); ){
+                    MessageImpl msg = (MessageImpl)it.next();
+                    Map map = new HashMap();
+                    map.put(Bayeux.CHANNEL_FIELD,msg.getChannel().getId());
+                    if (msg.getClient()!=null) map.put(Bayeux.CLIENT_FIELD,msg.getClient().getId());
+                    map.put(Bayeux.DATA_FIELD,msg);
+                    JSONObject obj = new JSONObject(map);
+                    addToDeliveryQueue(client, obj);
+                }
+            } catch (ServletException x) {
+                throw new BayeuxException(x);
+            } catch (IOException x) {
+                throw new BayeuxException(x);
+            }
+        }
+    }
+    
+    public int process(int prevops) throws BayeuxException {
+        event.getHttpServletRequest().setAttribute(CURRENT_REQ_ATTR,this);
+        return prevops;
+    }
+    
+    public int getReconnectInterval() {
+        return reconnectInterval;
+    }
+
+    public String getTimeStamp() {
+        return timestampFmt.format(new Date(System.currentTimeMillis()));
+    }
+
+}



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


Mime
View raw message