Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=46247
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Fri, 5 Dec 2008 15:57:43 +0000 (15:57 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Fri, 5 Dec 2008 15:57:43 +0000 (15:57 +0000)
svn property patches for trunk
Patch provided be sebb at a.o

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@723775 13f79535-47bb-0310-9956-ffa450edef68

38 files changed:
modules/bayeux/java/org/apache/cometd/bayeux/Bayeux.java
modules/bayeux/java/org/apache/cometd/bayeux/Channel.java
modules/bayeux/java/org/apache/cometd/bayeux/Client.java
modules/bayeux/java/org/apache/cometd/bayeux/DataFilter.java
modules/bayeux/java/org/apache/cometd/bayeux/Listener.java
modules/bayeux/java/org/apache/cometd/bayeux/Message.java
modules/bayeux/java/org/apache/cometd/bayeux/SecurityPolicy.java
modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxException.java
modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxRequest.java
modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxServlet.java
modules/bayeux/java/org/apache/tomcat/bayeux/ChannelImpl.java
modules/bayeux/java/org/apache/tomcat/bayeux/ClientImpl.java
modules/bayeux/java/org/apache/tomcat/bayeux/HttpError.java
modules/bayeux/java/org/apache/tomcat/bayeux/MessageImpl.java
modules/bayeux/java/org/apache/tomcat/bayeux/RequestBase.java
modules/bayeux/java/org/apache/tomcat/bayeux/RequestFactory.java
modules/bayeux/java/org/apache/tomcat/bayeux/TomcatBayeux.java
modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaConnectRequest.java
modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaDisconnectRequest.java
modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaHandshakeRequest.java
modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaSubscribeRequest.java
modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaUnsubscribeRequest.java
modules/bayeux/java/org/apache/tomcat/bayeux/request/PublishRequest.java
modules/bayeux/test/org/apache/cometd/bayeux/samples/BayeuxStockTicker.java
modules/bayeux/test/org/apache/cometd/bayeux/samples/EchoChatClient.java
modules/bayeux/webapps/cometd/WEB-INF/web.xml
modules/bayeux/webapps/cometd/examples/simplechat/ticker.html
modules/bayeux/webapps/cometd/index.html
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java
res/META-INF/LICENSE
res/META-INF/NOTICE
res/procrun/amd64/tomcat6.exe [changed mode: 0755->0644]
res/procrun/amd64/tomcat6w.exe [changed mode: 0755->0644]
res/procrun/ia64/tomcat6.exe [changed mode: 0755->0644]
res/procrun/ia64/tomcat6w.exe [changed mode: 0755->0644]
res/procrun/tomcat6.exe [changed mode: 0755->0644]
res/procrun/tomcat6w.exe [changed mode: 0755->0644]

index 5385d32..3ca4fe7 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.cometd.bayeux;\r
-\r
-import java.util.List;\r
-\r
-/** Bayeux Interface.<br/>\r
- * This interface represents the server side API for the Bayeux messaging protocol.\r
- * Bayeux is a simple subscribe/publish/receive methodology, not far from JMS, but much simplified.<br/>\r
- * It is used both by the actual implementation and by server side clients.<br/>\r
- * Server side clients use this to create, retrieve and subscribe to channels.\r
- * Server side clients are represented, just like remote clients, through the Client interface.\r
- * <br/>\r
- * The Bayeux implementations is intended to be thread safe and multiple threads may simultaneously call Bayeux methods.\r
- * <br/>\r
- * The Bayeux object, is the starting point for any cometd application relying on the Bayeux object.\r
- * Dependent on the container, the Bayeux object will be stored in the <code>javax.servlet.ServletContext</code> object\r
- * as an attribute under the name <code>Bayeux.DOJOX_COMETD_BAYEUX</code><br/>\r
- * To retrieve this object, one would simply call<br/>\r
- * <code>Bayeux bx = (Bayeux)getServletContext().getAttribute(Bayeux.DOJOX_COMETD_BAYEUX);\r
- * <br/><br/>\r
- * The Bayeux protocol is pretty straight forward and includes a bunch of messaging that is not needed to be known to clients,\r
- * both server side and remote clients.\r
- * This object gets initialized by a container dependent servlet, and the servlet then handles all Bayeux communication from the client.\r
- * Remote messsages are delivered to channels, and to server side clients using the <code>Listener</code> interface.<br/>\r
- * <br/>\r
- * A <code>Bayeux session</code> is active as long as the webapp hosting the Bayeux object is active.<br/>\r
- * When the webapplication shuts down, the Bayeux object will unsubscribe all clients and remove all the active channels.\r
- * \r
- * @author Greg Wilkins\r
- * @author Filip Hanik\r
- */\r
-public interface Bayeux {\r
-    \r
-    /**Meta definitions for channels*/\r
-    public static final String META="/meta";\r
-    /**Meta definitions for channels*/\r
-    public static final String META_SLASH="/meta/";\r
-    /**Meta definitions for channels - connect message*/\r
-    public static final String META_CONNECT="/meta/connect";\r
-    /**Meta definitions for channels - client messsage*/\r
-    public static final String META_CLIENT="/meta/client";\r
-    /**Meta definitions for channels - disconnect messsage*/\r
-    public static final String META_DISCONNECT="/meta/disconnect";\r
-    /**Meta definitions for channels - handshake messsage*/\r
-    public static final String META_HANDSHAKE="/meta/handshake";\r
-    /**Meta definitions for channels - ping messsage*/\r
-    public static final String META_PING="/meta/ping";\r
-    /**Meta definitions for channels - reconnect messsage\r
-     * @deprecated\r
-     */\r
-    public static final String META_RECONNECT="/meta/reconnect";\r
-    /**Meta definitions for channels - status messsage*/\r
-    public static final String META_STATUS="/meta/status";\r
-    /**Meta definitions for channels - subscribe messsage*/\r
-    public static final String META_SUBSCRIBE="/meta/subscribe";\r
-    /**Meta definitions for channels - unsubscribe messsage*/\r
-    public static final String META_UNSUBSCRIBE="/meta/unsubscribe";\r
-    /*Field names inside Bayeux messages*/\r
-    /**Field names inside Bayeux messages - clientId field*/\r
-    public static final String CLIENT_FIELD="clientId";\r
-    /**Field names inside Bayeux messages - data field*/\r
-    public static final String DATA_FIELD="data";\r
-    /**Field names inside Bayeux messages - channel field*/\r
-    public static final String CHANNEL_FIELD="channel";\r
-    /**Field names inside Bayeux messages - id field*/\r
-    public static final String ID_FIELD="id";\r
-    /**Field names inside Bayeux messages - error field*/\r
-    public static final String ERROR_FIELD="error";\r
-    /**Field names inside Bayeux messages - timestamp field*/\r
-    public static final String TIMESTAMP_FIELD="timestamp";\r
-    /**Field names inside Bayeux messages - transport field*/\r
-    public static final String TRANSPORT_FIELD="transport";\r
-    /**Field names inside Bayeux messages - advice field*/\r
-    public static final String ADVICE_FIELD="advice";\r
-    /**Field names inside Bayeux messages - successful field*/\r
-    public static final String SUCCESSFUL_FIELD="successful";\r
-    /**Field names inside Bayeux messages - subscription field*/\r
-    public static final String SUBSCRIPTION_FIELD="subscription";\r
-    /**Field names inside Bayeux messages - ext field*/\r
-    public static final String EXT_FIELD="ext";\r
-    /**Field names inside Bayeux messages - connectionType field*/\r
-    public static final String CONNECTION_TYPE_FIELD="connectionType";\r
-    /**Field names inside Bayeux messages - version field*/\r
-    public static final String VERSION_FIELD="version";\r
-    /**Field names inside Bayeux messages - minimumVersion field*/\r
-    public static final String MIN_VERSION_FIELD="minimumVersion";\r
-    /**Field names inside Bayeux messages - supportedConnectionTypes field*/\r
-    public static final String SUPP_CONNECTION_TYPE_FIELD="supportedConnectionTypes";\r
-    /**Field names inside Bayeux messages - json-comment-filtered field*/\r
-    public static final String JSON_COMMENT_FILTERED_FIELD="json-comment-filtered";\r
-    /**Field names inside Bayeux messages - reconnect field*/\r
-    public static final String RECONNECT_FIELD = "reconnect";\r
-    /**Field names inside Bayeux messages - interval field*/\r
-    public static final String INTERVAL_FIELD = "interval";\r
-    /**Field values inside Bayeux messages - retry response*/\r
-    public static final String RETRY_RESPONSE = "retry";\r
-    /**Field values inside Bayeux messages - handshake response*/\r
-    public static final String HANDSHAKE_RESPONSE = "handshake";\r
-    /**Field values inside Bayeux messages - none response*/\r
-    public static final String NONE_RESPONSE = "none";\r
-    /**Service channel names-starts with*/\r
-    public static final String SERVICE="/service";\r
-    /**Service channel names-trailing slash*/\r
-    public static final String SERVICE_SLASH="/service/";\r
-    /*Transport types*/\r
-    /**Transport types - long polling*/\r
-    public static final String TRANSPORT_LONG_POLL="long-polling";\r
-    /**Transport types - callback polling*/\r
-    public static final String TRANSPORT_CALLBACK_POLL="callback-polling";\r
-    /**Transport types - iframe*/\r
-    public static final String TRANSPORT_IFRAME="iframe";\r
-    /**Transport types - flash*/\r
-    public static final String TRANSPORT_FLASH="flash";\r
-    /** ServletContext attribute name used to obtain the Bayeux object */\r
-    public static final String DOJOX_COMETD_BAYEUX="dojox.cometd.bayeux";\r
-    /*http field names*/\r
-    /**http helpers - text/json content type*/\r
-    public static final String JSON_CONTENT_TYPE="text/json";\r
-    /**http helpers - parameter name for json message*/\r
-    public static final String MESSAGE_PARAMETER="message";\r
-    /**http helpers - name of the jsonp parameter*/\r
-    public static final String JSONP_PARAMETER="jsonp";\r
-    /**http helpers - default name of the jsonp callback function*/\r
-    public static final String JSONP_DEFAULT_NAME="jsonpcallback";\r
-\r
-    /*--Client----------------------------------------------------------- */\r
-    /**\r
-     * Creates a new server side client. This method is to be invoked\r
-     * by server side objects only. You cannot create a remote client by using this method.\r
-     * A client represents an entity that can subscribe to channels and publish and receive messages\r
-     * through these channels\r
-     * @param idprefix String - the prefix string for the id generated, can be null\r
-     * @param listener Listener - a callback object to be called when messages are to be delivered to the new client\r
-     * @return Client - returns an implementation of the client interface.\r
-     */\r
-    public Client newClient(String idprefix, Listener listener);\r
-\r
-    /**\r
-     * retrieve a client based on an ID. Will return null if the client doesn't exist.\r
-     * @param clientid String\r
-     * @return Client-null if the client doesn't exist.returns the client if it does.\r
-     */\r
-    public Client getClient(String clientid);\r
-    \r
-    /**\r
-     * Returns a non modifiable list of all the clients that are currently active\r
-     * in this Bayeux session\r
-     * @return List<Client> - a list containing all clients. The List can not be modified.\r
-     */\r
-    public List<Client> getClients();\r
-    \r
-    /**\r
-     * Returns true if a client with the given id exists.<br/>\r
-     * Same as executing <code>getClient(id)!=null</code>.\r
-     * @param clientId String\r
-     * @return boolean - true if the client exists\r
-     */\r
-    public boolean hasClient(String clientId);\r
-    \r
-    /**\r
-     * Removes the client all together.\r
-     * This will unsubscribe the client to any channels it may be subscribed to\r
-     * and remove it from the list.\r
-     * @param client Client\r
-     * @return Client - returns the client that was removed, or null if no client was removed.\r
-     */\r
-    public Client remove(Client client);\r
-\r
-    \r
-    /*--Channel---------------------------------------------------------- */\r
-    /**\r
-     * Returns the channel for a given channel id.\r
-     * If the channel doesn't exist, and the <code>create</code> parameter is set to true,\r
-     * the channel will be created and added to the list of active channels.<br/>\r
-     * if <code>create</code> is set to false, and the channel doesn't exist, null will be returned.\r
-     * @param channelId String - the id of the channel to be retrieved or created\r
-     * @param create boolean - true if the Bayeux impl should create the channel\r
-     * @return Channel - null if <code>create</code> is set to false and the channel doesn't exist, \r
-     * otherwise it returns a channel object.\r
-     */\r
-    public Channel getChannel(String channelId, boolean create);\r
-    \r
-    /**\r
-     * Returns a list of currently active channels in this Bayeux session.\r
-     * @return List<Channel>\r
-     */\r
-    public List<Channel> getChannels();\r
-\r
-    /**\r
-     * Removes a channel from the Bayeux object.\r
-     * This will also unsubscribe all the clients currently subscribed to the\r
-     * the channel.\r
-     * @param channel Channel - the channel to be removed\r
-     * @return Channel - returns the channel that was removed, or null if no channel was removed.\r
-     */\r
-    public Channel remove(Channel channel);\r
-\r
-    /**\r
-     * returns true if a channel with the given channelId exists.\r
-     * <br/>Same as executing <code>Bayeux.getChannel(channelId,false)!=null</code>\r
-     * @param channelId String\r
-     * @return boolean - true if the channel exists.\r
-     */\r
-    public boolean hasChannel(String channelId);\r
-\r
-    /* --Message---------------------------------------------------------- */\r
-    /**\r
-     * Creates a new message to be sent by a server side client.\r
-     * @return Message - returns a new Message object, that has a unique id.\r
-     */\r
-    public Message newMessage(Client from);\r
-\r
-\r
-    /*--Security policy----------------------------------------------------------- */\r
-    /**\r
-     * Returns the security policy associated with this Bayeux session\r
-     * @return SecurityPolicy\r
-     */\r
-    public SecurityPolicy getSecurityPolicy();\r
-   \r
-    /**\r
-     * Sets the security policy to be used in this Bayeux session\r
-     * @param securityPolicy SecurityPolicy\r
-     */\r
-    public void setSecurityPolicy(SecurityPolicy securityPolicy);\r
-\r
+/*
+ * 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
index 34af328..468b5e1 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.cometd.bayeux;\r
-\r
-import java.util.List;\r
-\r
-/** \r
- * A Bayeux Channel represents a channel used to receive messages from and to publish messages to.\r
- * In order to publish messages to or receive messages from, one must subscribe to the channel.\r
- * This is easily done by invoking the <code>subscribe</code> method.\r
- * A channel is created by calling the <code>Bayeux.getChannel(channelId,true)</code> method.\r
- * A channel can be created either server side by invoking the getChannel, or client side\r
- * by using the /meta/subscribe message without a wildcard.\r
- * @author Greg Wilkins\r
- * @author Filip Hanik\r
- */\r
-public interface Channel\r
-{\r
-    /**\r
-     * Returns the id for this channel. The id is unique within bayeux session.\r
-     * @return String - will never be null.\r
-     */\r
-    public String getId();\r
-\r
-    /** \r
-     * Publishes a message to all the subscribers of this channel.\r
-     * The <code>from</code> is contained within the message, by calling\r
-     * <code>msg.getClient()</code>\r
-     * @param data - the message to be published, can not be null.\r
-     */\r
-    public void publish(Message msg);\r
-    \r
-    /** \r
-     * Publishes more than one message to all the subscribers of this channel.\r
-     * The <code>from</code> is contained within the message, by calling\r
-     * <code>msg[x].getClient()</code>\r
-     * @param data - the message to be published, can not be null.\r
-     */\r
-    public void publish(Message[] msgs);\r
-\r
-    /** \r
-     * Non persistent channels are removed when the last subscription is\r
-     * removed. Persistent channels survive periods without any subscribers.\r
-     * @return true if the Channel will persist without any subscription.\r
-     */\r
-    public boolean isPersistent();\r
-    \r
-    /**\r
-     * @param persistent true if the Channel will persist without any subscription.\r
-     * @see isPersistent\r
-     */\r
-    public void setPersistent(boolean persistent);\r
-    \r
-    /** \r
-     * Subscribes a client to a channel.\r
-     * @param subscriber - the client to be subscribed. If the client\r
-     * already is subscribed, this call will not create a duplicate subscription.\r
-     */\r
-    public void subscribe(Client subscriber);\r
-\r
-    /** \r
-     * Unsubscribes a client from a channel\r
-     * @param subscriber - the client to be subscribed.\r
-     * @return - returns the client that was unsubscribed, or null if the client wasn't subscribed.\r
-     */\r
-    public Client unsubscribe(Client subscriber);\r
-\r
-    /**\r
-     * returns a non modifiable list of all the subscribers to this \r
-     * channel.\r
-     * @return a list of subscribers\r
-     */\r
-    public List<Client> getSubscribers();\r
-    \r
-    /**\r
-     * Adds a data filter to this channel. All messages received by this channel \r
-     * will run through this filter.\r
-     * @param filter Filter\r
-     */\r
-    public void addFilter(DataFilter filter);\r
-    \r
-    /**\r
-     * Removes a filter from this channel.\r
-     * returns the filter that was removed, or null if the filter wasn't in the channel.\r
-     * @param filter Filter\r
-     * @return Filter - null if no filter was removed otherwise it returns the filter that was removed.\r
-     */\r
-    public DataFilter removeFilter(DataFilter filter);\r
+/*
+ * 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
index 3d6a8d8..32e8773 100644 (file)
@@ -1,91 +1,91 @@
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-package org.apache.cometd.bayeux;\r
-\r
-\r
-\r
-/** A Bayeux Client.\r
- * <p>\r
- * A client may subscribe to channels and publish messages to channels.\r
- * Client instances should not be directly created by uses, but should \r
- * be obtained via the {@link Bayeux#getClient(String)} or {@link Bayeux#newClient(String, Listener)}\r
- * methods.\r
- * </p>\r
- * <p>\r
- * Three types of client may be represented by this interface:<nl>\r
- * <li>The server representation of a remote client connected via HTTP, \r
- *     automatically created by the Bayeux server when a connect message comes in</li>\r
- * <li>A server side client, created by the application using the {@link Bayeux#newClient(String, Listener)} method</li>\r
- * <li>A java client connected to a remote Bayeux server - not implemented</li>\r
- * </nl>\r
- * @author Greg Wilkins\r
- * @author Filip Hanik\r
- */\r
-public interface Client\r
-{\r
-    /**\r
-     * Returns a unique id for this client. The id is unique within this Bayeux session.\r
-     * @return String - will not be null\r
-     */\r
-    public String getId();\r
-\r
-    /**\r
-     * Returns true if this client is holding messages to be delivered to the remote client.\r
-     * This method always returns false for local clients, since messages are delivered instantly using the \r
-     * Listener(callback) object\r
-     * @return boolean\r
-     */\r
-    public boolean hasMessages();\r
-\r
-    /** \r
-     * Deliver a message to this client only\r
-     * Deliver a message directly to the client. The message is not \r
-     * filtered or published to a channel.\r
-     * @param message\r
-     */\r
-    public void deliver(Message message);\r
-\r
-    /** \r
-     * Deliver a batch of messages to this client only\r
-     * Deliver a batch messages directly to the client. The messages are not \r
-     * filtered or published to a channel.\r
-     * @param message\r
-     */\r
-    public void deliver(Message[] message);\r
-\r
-    /**\r
-     * @return True if the client is local. False if this client is either a remote HTTP client or\r
-     * a java client to a remote server. \r
-     */\r
-    public boolean isLocal();\r
-    \r
-    /**\r
-     * Starts a batch, no messages will be delivered until endBatch is called.\r
-     * Batches can be nested, and messages will only be delivered after\r
-     * the last endBatch has been called.\r
-     */\r
-    public void startBatch();\r
-    \r
-    /**\r
-     * Ends a batch. since batches can be nested, messages will only be delivered\r
-     * after the endBatch has been called as many times as startBatch has.\r
-     */\r
-    public void endBatch();\r
-    \r
-    \r
+/*
+ * 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
index d632aec..abc964e 100644 (file)
@@ -1,38 +1,38 @@
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.cometd.bayeux;\r
-\r
-/** \r
- * Data Filter<br/>\r
- * Data filters are used to transform data as it is sent to a Channel.\r
- * Messages are filtered as the message is published to a channel, invoking the \r
- * {@link Channel#publish(Message)} method.<br/>\r
- * This method gets invoked in two different scenarios, the first being when a message is received from\r
- * a remote client, and the Bayeux implementation invokes the publish method directly.\r
- * The second scenario is when a local client invokes {@link Channel#publish(Message)} directly in the local JVM.\r
- * @author Greg Wilkins\r
- * @author Filip Hanik\r
- *\r
- */\r
-public interface DataFilter\r
-{\r
-    /**\r
-     * Runs a message through the filter. Filtering can only modify an existing object, it can not replace it.\r
-     * @param data Message - the message to be filtered, may not be null\r
-     */\r
-    public void filter(Message data);\r
-}\r
+/*
+ * 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);
+}
index cce2018..9cd86d0 100644 (file)
@@ -1,45 +1,45 @@
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.cometd.bayeux;\r
-\r
-/** \r
- * Cometd Listener interface.<br/>\r
- * For local clients, in order to receive messages, they pass in a callback object\r
- * when the local client is created using the {@link Bayeux#newClient(String,Listener)} method.\r
- * This callback object, implementing the Listener interface, is used to deliver messages to local, in JVM, clients.\r
- * @author Greg Wilkins\r
- * @author Filip Hanik\r
- *\r
- */\r
-public interface Listener\r
-{\r
-    /**\r
-     * This method is called when the client is removed (explicitly or from a timeout)\r
-     * @param timeout - true if the client was removed from a timeout\r
-     * false if it was removed explicitly.\r
-     */\r
-    public void removed(boolean timeout);\r
-    \r
-    /**\r
-     * Invoked when a message is delivered to the client.\r
-     * The message contains the message itself, as well as what channel this message came through\r
-     * and who the sender is. If someone invoked {@link Client#deliver(Message)} then the channel reference will\r
-     * be null.\r
-     * @param msg \r
-     */\r
-    public void deliver(Message[] msg);\r
-}\r
+/*
+ * 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);
+}
index 26ba640..12b525b 100644 (file)
@@ -1,68 +1,68 @@
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.cometd.bayeux;\r
-\r
-import java.util.Map;\r
-\r
-/** \r
- * A Bayeux Message<br/>\r
- * A Bayeux message is a Map of String/Object key value pairs representing the data in the message.\r
- * The message contains information about the channel it was published through and who the sender was\r
- * \r
- * @author Greg Wilkins\r
- * @author Filip Hanik\r
- */\r
-public interface Message extends Map<String,Object>\r
-{\r
-    /**\r
-     * Returns a reference to the client that sent this message\r
-     * @return Client - may be null\r
-     */\r
-    public Client getClient();\r
-    /**\r
-     * Returns a reference to the channel that this message was published throuhg\r
-     * @return Channel - may be null\r
-     */\r
-    public Channel getChannel();\r
-    /**\r
-     * Returns the unique id of this message\r
-     * @return String\r
-     */\r
-    public String getId();\r
-    \r
-    /**\r
-     * Sets the time to live in milliseconds. If the message hasn't been delivered \r
-     * when the time passed after the creation time is longer than the TTL the message will\r
-     * expire and removed from any delivery queues.\r
-     * @param ttl long\r
-     */\r
-    public void setTTL(long ttl);\r
-    \r
-    /**\r
-     * Returns the time to live (in milliseconds) for this message\r
-     * @return long\r
-     */\r
-    public long getTTL();\r
-    \r
-    /**\r
-     * returns the timestamp in milliseconds(System.currentTimeMillis()) of when this message was created.\r
-     * @return long\r
-     */\r
-    public long getCreationTime();\r
-}\r
-\r
-\r
+/*
+ * 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();
+}
+
+
index 930f605..55e7158 100644 (file)
@@ -1,28 +1,28 @@
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.cometd.bayeux;\r
-\r
-/**\r
- * @author Greg Wilkins\r
- */\r
-public interface SecurityPolicy\r
-{\r
-    boolean canHandshake(Message message);\r
-    boolean canCreate(Client client,String channel,Message message);\r
-    boolean canSubscribe(Client client,String channel,Message messsage);\r
-    boolean canPublish(Client client,String channel,Message messsage);\r
-}\r
+/*
+ * 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);
+}
index d201c5e..6d96bb3 100644 (file)
@@ -1,39 +1,39 @@
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux;\r
-/**\r
- * \r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class BayeuxException extends Exception {\r
-    public BayeuxException() {\r
-        super();\r
-    }\r
-\r
-    public BayeuxException(String message) {\r
-        super(message);\r
-    }\r
-\r
-    public BayeuxException(String message, Throwable cause) {\r
-        super(message, cause);\r
-    }\r
-\r
-    public BayeuxException(Throwable cause) {\r
-        super(cause);\r
-    }\r
+/*
+ * 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
index 6e93c99..6dd9b33 100644 (file)
@@ -1,54 +1,54 @@
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux;\r
-\r
-import org.apache.tomcat.bayeux.HttpError;\r
-\r
-/**\r
- * An interface that defines methods for managing Bayeux request meta \r
- * messages.\r
- *\r
- * @author Guy A. Molinari\r
- * @author Filip Hanik\r
- * @version 0.9\r
- */\r
-public interface BayeuxRequest {\r
-\r
-    public static final String LAST_REQ_ATTR = "org.apache.cometd.bayeux.last_request";\r
-    public static final String CURRENT_REQ_ATTR = "org.apache.cometd.bayeux.current_request";\r
-    public static final String JSON_MSG_ARRAY = "org.apache.cometd.bayeux.json_msg_array";\r
-\r
-    /**\r
-     * Validates a specific request. \r
-     * This method must be called prior to process()\r
-     * as a request can do pre processing in the validate method.\r
-     * <br/>\r
-     * Should the validation fail, an error object is returned \r
-     * containing an error message, and potentially a stack trace\r
-     * if an exception was generated\r
-     * @return HttpError - null if no error was detected, an HttpError object containing information about the error.\r
-     */\r
-    public HttpError validate();\r
-    \r
-    /**\r
-     * processes a remote client Bayeux message\r
-     * @param prevops - the operation requested by the previous request, in case of chained requests.\r
-     * @return int - returns the interest operation for a CometEvent. Currently not used\r
-     * @throws BayeuxException - if an error was detected, and the appropriate error response couldn't be delivered to the client. \r
-     */\r
-    public int process(int prevops) throws BayeuxException;\r
-}\r
+/*
+ * 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;
+}
index 837086d..dfb81b3 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- *\r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux;\r
-\r
-import java.io.IOException;\r
-import javax.servlet.ServletConfig;\r
-import javax.servlet.ServletContext;\r
-import javax.servlet.ServletException;\r
-import javax.servlet.ServletRequest;\r
-import javax.servlet.ServletResponse;\r
-import javax.servlet.http.HttpServletResponse;\r
-\r
-import org.apache.catalina.CometEvent;\r
-import org.apache.catalina.CometProcessor;\r
-import org.apache.juli.logging.Log;\r
-import org.apache.juli.logging.LogFactory;\r
-import org.json.JSONArray;\r
-import org.json.JSONException;\r
-import org.json.JSONObject;\r
-import org.apache.cometd.bayeux.Bayeux;\r
-\r
-/**\r
- * \r
- * @author Filip Hanik\r
- * @author Guy Molinari\r
- * @version 1.0\r
- */\r
-public class BayeuxServlet implements CometProcessor {\r
-\r
-    /**\r
-     * Attribute to hold the TomcatBayeux object in the servlet context\r
-     */\r
-    public static final String TOMCAT_BAYEUX_ATTR = Bayeux.DOJOX_COMETD_BAYEUX;\r
-    \r
-    /**\r
-     * Logger object\r
-     */\r
-    protected static Log log = LogFactory.getLog(BayeuxServlet.class);\r
-\r
-    /**\r
-     * Servlet config - for future use\r
-     */\r
-    protected ServletConfig servletConfig;\r
-    \r
-    /**\r
-     * Reference to the global TomcatBayeux object\r
-     */\r
-    protected TomcatBayeux tb;\r
-    \r
-    /**\r
-     * Upon servlet destruction, the servlet will clean up the \r
-     * TomcatBayeux object and terminate any outstanding events.\r
-     */\r
-    public void destroy() {\r
-        servletConfig = null;\r
-        //to do, close all outstanding comet events\r
-        //tb.destroy();\r
-        tb = null;//TO DO, close everything down\r
-        \r
-    }\r
-    \r
-    /**\r
-     * Returns the preconfigured connection timeout.\r
-     * If no timeout has been configured as a servlet init parameter named <code>timeout</code>\r
-     * then the default of 2min will be used.\r
-     * @return int - the timeout for a connection in milliseconds\r
-     */\r
-    protected int getTimeout() {\r
-        String timeoutS = servletConfig.getInitParameter("timeout");\r
-        int timeout = 120*1000; //2 min\r
-        try {\r
-            timeout = Integer.parseInt(timeoutS);\r
-        }catch (NumberFormatException nfe) {\r
-            //ignore, we have a default value\r
-        }\r
-        return timeout;\r
-    }\r
-    \r
-    protected int getReconnectInterval() {\r
-        String rs = servletConfig.getInitParameter("reconnectInterval");\r
-        int rct = 1000; //1 seconds\r
-        try {\r
-            rct = Integer.parseInt(rs);\r
-        }catch (NumberFormatException nfe) {\r
-            //ignore, we have a default value\r
-        }\r
-        return rct;\r
-    }\r
-\r
-\r
-    public void event(CometEvent cometEvent) throws IOException, ServletException {\r
-        CometEvent.EventType type = cometEvent.getEventType();\r
-        if (log.isDebugEnabled()) {\r
-            log.debug("["+Thread.currentThread().getName()+"] Received Comet Event type="+type+" subtype:"+cometEvent.getEventSubType());\r
-        }\r
-        synchronized (cometEvent) {\r
-            if (type==CometEvent.EventType.BEGIN) {\r
-                //begin event, set the timeout\r
-                cometEvent.setTimeout(getTimeout());\r
-                //checkBayeux(cometEvent); - READ event should always come\r
-            } else if (type==CometEvent.EventType.READ) {\r
-                checkBayeux(cometEvent);\r
-            } else if (type==CometEvent.EventType.ERROR) {\r
-                tb.remove(cometEvent);\r
-                cometEvent.close();\r
-            } else if (type==CometEvent.EventType.END) {\r
-                tb.remove(cometEvent);\r
-                cometEvent.close();\r
-            }//end if\r
-            \r
-        }//synchronized\r
-    }//event\r
-\r
-    /**\r
-     * \r
-     * @param cometEvent CometEvent\r
-     * @return boolean - true if we comet event stays open\r
-     * @throws IOException\r
-     * @throws UnsupportedOperationException\r
-     */\r
-    protected void checkBayeux(CometEvent cometEvent) throws IOException, UnsupportedOperationException {\r
-        //we actually have data.\r
-        //data can be text/json or \r
-        if (Bayeux.JSON_CONTENT_TYPE.equals(cometEvent.getHttpServletRequest().getContentType())) {\r
-            //read and decode the bytes according to content length\r
-            log.warn("["+Thread.currentThread().getName()+"] JSON encoding not supported, will throw an exception and abort the request.");\r
-            int contentlength = cometEvent.getHttpServletRequest().getContentLength();\r
-            throw new UnsupportedOperationException("Decoding "+Bayeux.JSON_CONTENT_TYPE+" not yet implemented.");\r
-        } else { //GET method or application/x-www-form-urlencoded\r
-            String message = cometEvent.getHttpServletRequest().getParameter(Bayeux.MESSAGE_PARAMETER);\r
-            if (log.isTraceEnabled()) {\r
-                log.trace("["+Thread.currentThread().getName()+"] Received JSON message:"+message);\r
-            }\r
-            try {\r
-                int action = handleBayeux(message, cometEvent);\r
-                if (log.isDebugEnabled()) {\r
-                    log.debug("["+Thread.currentThread().getName()+"] Bayeux handling complete, action result="+action);\r
-                }\r
-                if (action<=0) {\r
-                    cometEvent.close();\r
-                }\r
-            }catch (Exception x) {\r
-                x.printStackTrace();\r
-                tb.remove(cometEvent);\r
-                log.error(x);\r
-                cometEvent.close();\r
-            }\r
-        }\r
-    }\r
-    \r
-    protected int handleBayeux(String message, CometEvent event) throws IOException, ServletException {\r
-        int result = 0;\r
-        if (message==null || message.length()==0) return result;\r
-        try {\r
-            BayeuxRequest request = null;\r
-            //a message can be an array of messages\r
-            JSONArray jsArray = new JSONArray(message);\r
-            for (int i = 0; i < jsArray.length(); i++) {\r
-                JSONObject msg = jsArray.getJSONObject(i);\r
-                \r
-                if (log.isDebugEnabled()) {\r
-                    log.debug("["+Thread.currentThread().getName()+"] Processing bayeux message:"+msg);\r
-                }\r
-                request = RequestFactory.getRequest(tb,event,msg);\r
-                if (log.isDebugEnabled()) {\r
-                    log.debug("["+Thread.currentThread().getName()+"] Processing bayeux message using request:"+request);\r
-                }\r
-                result = request.process(result);\r
-                if (log.isDebugEnabled()) {\r
-                    log.debug("["+Thread.currentThread().getName()+"] Processing bayeux message result:"+result);\r
-                }\r
-            }\r
-            if (result>0 && request!=null) {\r
-                event.getHttpServletRequest().setAttribute(BayeuxRequest.LAST_REQ_ATTR, request);\r
-                ClientImpl ci = (ClientImpl)tb.getClient(((RequestBase)request).getClientId());\r
-                ci.addCometEvent(event);\r
-                if (log.isDebugEnabled()) {\r
-                    log.debug("["+Thread.currentThread().getName()+"] Done bayeux message added to request attribute");\r
-                }\r
-            } else if (result == 0 && request!=null) {\r
-                RequestBase.deliver(event,(ClientImpl)tb.getClient(((RequestBase)request).getClientId()));\r
-                if (log.isDebugEnabled()) {\r
-                    log.debug("["+Thread.currentThread().getName()+"] Done bayeux message, delivered to client");\r
-                }\r
-            }\r
-            \r
-        }catch (JSONException x) {\r
-            log.error(x);//to do impl error handling\r
-            result = -1;\r
-        }catch (BayeuxException x) {\r
-            log.error(x); //to do impl error handling\r
-            result = -1;\r
-        }\r
-        return result;\r
-    }\r
-\r
-    public ServletConfig getServletConfig() {\r
-        return servletConfig;\r
-    }\r
-\r
-    public String getServletInfo() {\r
-        return "Tomcat/BayeuxServlet/1.0";\r
-    }\r
-\r
-    public void init(ServletConfig servletConfig) throws ServletException {\r
-        \r
-        this.servletConfig = servletConfig;\r
-        ServletContext ctx = servletConfig.getServletContext();\r
-        if (ctx.getAttribute(TOMCAT_BAYEUX_ATTR)==null)\r
-            ctx.setAttribute(TOMCAT_BAYEUX_ATTR,new TomcatBayeux());\r
-        this.tb = (TomcatBayeux)ctx.getAttribute(TOMCAT_BAYEUX_ATTR);\r
-        tb.setReconnectInterval(getReconnectInterval());\r
-    }\r
-\r
-    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {\r
-        if (servletResponse instanceof HttpServletResponse) {\r
-            ( (HttpServletResponse) servletResponse).sendError(500, "Misconfigured Tomcat server, must be configured to support Comet operations.");\r
-        } else {\r
-            throw new ServletException("Misconfigured Tomcat server, must be configured to support Comet operations for the Bayeux protocol.");\r
-        }\r
-    }\r
-}\r
+/*
+ * 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 = 1000; //1 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.");
+        }
+    }
+}
index e1e08a8..353fe77 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux;\r
-\r
-import java.util.LinkedList;\r
-\r
-import org.apache.cometd.bayeux.Channel;\r
-import org.apache.cometd.bayeux.Client;\r
-import org.apache.cometd.bayeux.DataFilter;\r
-import java.util.Collections;\r
-import java.util.List;\r
-import org.apache.cometd.bayeux.Message;\r
-import java.util.Iterator;\r
-import org.apache.juli.logging.Log;\r
-import org.apache.juli.logging.LogFactory;\r
-/**\r
- * \r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class ChannelImpl implements Channel {\r
-    \r
-    protected static Log log = LogFactory.getLog(ChannelImpl.class);\r
-    \r
-    /**\r
-     * The unique id of this channel\r
-     */\r
-    protected String id = null;\r
-    \r
-    /**\r
-     * A list of the current subscribers\r
-     */\r
-    protected LinkedList<Client> subscribers = new LinkedList<Client>();\r
-    \r
-    /**\r
-     * A list of the current filters\r
-     */\r
-    protected LinkedList<DataFilter> filters = new LinkedList<DataFilter>();\r
-    \r
-    /**\r
-     * Is this channel persistent, default value is true\r
-     */\r
-    protected boolean persistent = true; \r
-    \r
-    /**\r
-     * Creates a new channel\r
-     * @param id String - the id of the channel, can not be null\r
-     */\r
-    protected ChannelImpl(String id) {\r
-        assert id != null;\r
-        this.id = id;\r
-    }\r
-\r
-    /**\r
-     * returns the id of this channel\r
-     * @return String\r
-     */\r
-    public String getId() {\r
-        return id;\r
-    }\r
-    \r
-    /**\r
-     * Returns true if this channel matches the pattern to its id.\r
-     * The channel pattern can be a complete name like <code>/service/mychannel</code>\r
-     * or it can be a wild card pattern like <code>/service/app2/**</code>\r
-     * @param pattern String according to the Bayeux specification section 2.2.1 Channel Globbing, can not be null.\r
-     * @return boolean true if the id of this channel matches the pattern\r
-     */\r
-    public boolean matches(String pattern) {\r
-        if (pattern == null)\r
-            throw new NullPointerException("Channel pattern must not be null.");\r
-        if (getId().equals(pattern))\r
-            return true;\r
-        int wildcardPos = pattern.indexOf("/*");\r
-        if (wildcardPos == -1)\r
-            return false;\r
-        boolean multiSegment = pattern.indexOf("**") != -1;\r
-        String leadSubstring = pattern.substring(0, wildcardPos);\r
-        if (leadSubstring == null)\r
-            return false;\r
-        if (multiSegment) \r
-            return getId().startsWith(leadSubstring);\r
-        else {\r
-            if (getId().length() <= wildcardPos + 2)\r
-                return false;\r
-            return !(getId().substring(wildcardPos + 2).contains("/"));\r
-        }\r
-    }\r
-\r
-\r
-\r
-    /**\r
-     * @return returns a non modifiable list of the subscribers for this channel.\r
-     */\r
-    public List<Client> getSubscribers() {\r
-        return Collections.unmodifiableList(subscribers);\r
-    }\r
-\r
-    /**\r
-     * @return true if the Channel will persist without any subscription.\r
-     */\r
-    public boolean isPersistent() {\r
-        return persistent;\r
-    }\r
-    \r
-    public void publish(Message msg) {\r
-        publish(new Message[] {msg});\r
-    }\r
-\r
-    public void publish(Message[] msgs) {\r
-        if (msgs==null) return;\r
-        MessageImpl[] imsgs = new MessageImpl[msgs.length];\r
-        for (int i=0; msgs!=null && i<msgs.length; i++) {\r
-            Message data = msgs[i];\r
-\r
-            if (!(data instanceof MessageImpl)) \r
-                throw new IllegalArgumentException("Invalid message class, you can only publish messages "+\r
-                                                   "created through the Bayeux.newMessage() method");\r
-            if (log.isDebugEnabled()) {\r
-                log.debug("Publishing message:"+data+" to channel:"+this);\r
-            }\r
-            //clone it so that we can set this channel as a reference\r
-            MessageImpl msg = (MessageImpl)((MessageImpl)data).clone();\r
-            //this is the channel it was delivered through\r
-            msg.setChannel(this);\r
-            //pass through filters\r
-            for (Iterator<DataFilter> it = filters.iterator(); it.hasNext(); ) {\r
-                it.next().filter(msg);\r
-            }\r
-            imsgs[i] = msg;\r
-        }\r
-        //deliver it to the clients\r
-        for (Iterator<Client> it = subscribers.iterator(); it.hasNext(); ) {\r
-            ClientImpl c = (ClientImpl)it.next();\r
-            c.deliverInternal(this,imsgs);\r
-        }\r
-        \r
-    }\r
-\r
-    public void setPersistent(boolean persistent) {\r
-        this.persistent = persistent;\r
-    }\r
-\r
-    public void subscribe(Client subscriber) {\r
-        if (!subscribers.contains((subscriber))) { \r
-            subscribers.addLast(subscriber);\r
-            ((ClientImpl)subscriber).subscribed(this);\r
-        }\r
-    }\r
-\r
-    public Client unsubscribe(Client subscriber) {\r
-        if (subscribers.remove(subscriber)) {\r
-            ((ClientImpl)subscriber).unsubscribed(this);\r
-            return subscriber;\r
-        } else\r
-            return null;\r
-    }\r
-    \r
-    public void addFilter(DataFilter filter) {\r
-        if (!filters.contains(filter)) \r
-            filters.addLast(filter);\r
-    }\r
-\r
-    public DataFilter removeFilter(DataFilter filter) {\r
-        if ( filters.remove(filter) ) return filter;\r
-        else return null;\r
-    }\r
-    \r
-    public String toString() {\r
-        StringBuffer buf = new StringBuffer(super.toString());\r
-        buf.append("; channelId=").append(getId());\r
-        return buf.toString();\r
-    }\r
-\r
+/*
+ * 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
index 894f9ef..bf355cb 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux;\r
-\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Queue;\r
-import java.util.concurrent.ConcurrentLinkedQueue;\r
-\r
-import org.apache.catalina.CometEvent;\r
-import org.json.JSONObject;\r
-import org.apache.cometd.bayeux.Bayeux;\r
-import org.apache.cometd.bayeux.Client;\r
-import org.apache.cometd.bayeux.Listener;\r
-import org.apache.cometd.bayeux.Message;\r
-import org.apache.juli.logging.Log;\r
-import org.apache.juli.logging.LogFactory;\r
-import java.util.concurrent.atomic.AtomicInteger;\r
-import java.util.HashMap;\r
-import java.util.ArrayList;\r
-\r
-public class ClientImpl implements Client {\r
-    \r
-    public static final int SUPPORT_CALLBACK_POLL = 0x1;\r
-    public static final int SUPPORT_LONG_POLL = 0x2; \r
-\r
-    public static final String COMET_EVENT_ATTR = "org.apache.cometd.bayeux.client";\r
-    \r
-    protected static Log log = LogFactory.getLog(ClientImpl.class);\r
-\r
-    protected static LinkedList<Message> EMPTY_LIST = new LinkedList<Message>();\r
-    /**\r
-     * queued message for remote clients.\r
-     */\r
-    protected LinkedList<Message> messages = null;\r
-    \r
-    /**\r
-     * \r
-     */\r
-    protected Queue<CometEvent> events = new LinkedList<CometEvent>();\r
-    \r
-    /**\r
-     * Unique id representing this client\r
-     */\r
-    protected String id;\r
-    \r
-    /**\r
-     * supported connection types, defaults to long-polling\r
-     */\r
-    protected int supportedConnTypes = SUPPORT_LONG_POLL | SUPPORT_CALLBACK_POLL;\r
-    \r
-    /**\r
-     * The desired connection type\r
-     */\r
-    protected int desirectConnType = SUPPORT_LONG_POLL;\r
-    \r
-    /**\r
-     * Does this client use json-comment-filtered messages\r
-     */\r
-    protected boolean useJsonFiltered = false;\r
-    \r
-    /**\r
-     * Same JVM clients, get local=true\r
-     */\r
-    protected boolean local;\r
-    \r
-    /**\r
-     * The callback object for local clients\r
-     */\r
-    protected Listener listener;\r
-    \r
-    protected AtomicInteger nrofsubscriptions = new AtomicInteger(0);\r
-    \r
-    protected ClientImpl(String id, boolean local) {\r
-        this.id = id;\r
-        this.local = local;\r
-        if (!local) messages = new LinkedList<Message>();\r
-    }\r
-    \r
-    protected ClientImpl(String id, CometEvent event) {\r
-        this(id,false);\r
-        events = new ConcurrentLinkedQueue<CometEvent>();\r
-        addCometEvent(event);\r
-    }\r
-\r
-    public synchronized void deliver(Message message) {\r
-        deliverInternal(null,new MessageImpl[] {(MessageImpl)message});\r
-    }\r
-    \r
-    public synchronized void deliver(Message[] message) {\r
-        deliverInternal(null,message);\r
-    }\r
-\r
-    protected synchronized void deliverInternal(ChannelImpl channel, MessageImpl message) {\r
-        deliverInternal(channel,new MessageImpl[] {message});\r
-    }\r
-\r
-    protected synchronized void deliverInternal(ChannelImpl channel, Message[] msgs) {\r
-        if (isLocal()) {\r
-            //local clients must have a listener\r
-            ArrayList<Message> list = new ArrayList<Message>();\r
-            for (int i=0; msgs!=null && i<msgs.length; i++) {\r
-                //dont deliver to ourselves\r
-                if (this!=msgs[i].getClient()) list.add(msgs[i]);\r
-            }\r
-            if (getListener() != null && list.size()>0) {\r
-                getListener().deliver(list.toArray(new Message[0]));\r
-            }\r
-        } else {\r
-            for (int i=0; msgs!=null && i<msgs.length; i++) {\r
-                MessageImpl message = (MessageImpl)msgs[i];\r
-                if (this==message.getClient()) { \r
-                    //dont deliver to ourself\r
-                    continue;\r
-                }\r
-                //we are not implementing forever responses, if the client is connected\r
-                //then we will fire off the message\r
-                //first we check to see if we have any existing connections we can piggy back on\r
-                CometEvent event = events.poll();\r
-                boolean delivered = false;\r
-                //TODO TODO - check on thread safety, for writing and for getting last request.\r
-                if (event!=null) {\r
-                    synchronized (event) {\r
-                        RequestBase rq = (RequestBase)event.getHttpServletRequest().getAttribute(RequestBase.LAST_REQ_ATTR);\r
-                        if (rq!=null) {\r
-                            Map map = new HashMap();\r
-                            try {\r
-                                map.put(Bayeux.CHANNEL_FIELD,message.getChannel().getId());\r
-                                map.put(Bayeux.DATA_FIELD,message);\r
-                                JSONObject json = new JSONObject(map);\r
-                                if (log.isDebugEnabled()) {\r
-                                    log.debug("Message instantly delivered to remote client["+this+"] message:"+json);\r
-                                }\r
-                                rq.addToDeliveryQueue(this, json);\r
-                                //deliver the batch\r
-                                if (i==(msgs.length-1)) {\r
-                                    rq.deliver(event, this);\r
-                                    event.close(); //todo, figure out a better way, this means only one message gets delivered\r
-                                    removeCometEvent(event); //and delivered instantly\r
-                                }\r
-                                delivered = true;\r
-                            } catch (Exception x) {\r
-                                log.error(x);\r
-                            }\r
-                        }\r
-                    }\r
-                } \r
-                if (!delivered) {\r
-                    if (log.isDebugEnabled()) {\r
-                        log.debug("Message added to queue for remote client["+this+"] message:"+message);\r
-                    }\r
-                    //queue the message for the next round\r
-                    messages.add(message);\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    public String getId() {\r
-        return this.id;\r
-    }\r
-\r
-    protected Listener getListener() {\r
-        return listener;\r
-    }\r
-\r
-    public boolean hasMessages() {\r
-        if (isLocal()) return false;\r
-        else {\r
-            return messages.size() > 0;\r
-        }\r
-    }\r
-\r
-    public boolean isLocal() {\r
-        return local;\r
-    }\r
-\r
-    public int getSupportedConnTypes() {\r
-        return supportedConnTypes;\r
-    }\r
-\r
-    public int getDesirectConnType() {\r
-        return desirectConnType;\r
-    }\r
-\r
-    public boolean useJsonFiltered() {\r
-        return useJsonFiltered;\r
-    }\r
-\r
-    public void setListener(Listener listener) {\r
-        this.listener = listener;\r
-    }\r
-\r
-    public void setSupportedConnTypes(int supportedConnTypes) {\r
-        this.supportedConnTypes = supportedConnTypes;\r
-    }\r
-\r
-    public void setUseJsonFiltered(boolean useJsonFiltered) {\r
-        this.useJsonFiltered = useJsonFiltered;\r
-    }\r
-\r
-    public void setDesirectConnType(int desirectConnType) {\r
-        this.desirectConnType = desirectConnType;\r
-    }\r
-\r
-    public boolean supportsCallbackPoll() {\r
-        return (supportedConnTypes & SUPPORT_CALLBACK_POLL) == SUPPORT_CALLBACK_POLL;\r
-    }\r
-\r
-    public boolean supportsLongPoll() {\r
-        return (supportedConnTypes & SUPPORT_LONG_POLL) == SUPPORT_LONG_POLL;\r
-    }\r
-\r
-    public synchronized List<Message> takeMessages() {\r
-        if (isLocal()) return null;\r
-        if (messages.size()==0) return EMPTY_LIST;\r
-        List result = new LinkedList(messages);\r
-        messages.clear();\r
-        return result;\r
-    }\r
-    \r
-    public String toString() {\r
-        StringBuffer buf = new StringBuffer(super.toString());\r
-        buf.append(" id=").append(getId());\r
-        return buf.toString();\r
-    }\r
-    \r
-    public boolean isSubscribed() {\r
-        return nrofsubscriptions.get()>0;\r
-    }\r
-    \r
-    protected synchronized boolean addCometEvent(CometEvent event) {\r
-        boolean result = false;\r
-        if (!events.contains(event)) {\r
-            events.add(event);\r
-            result = true;\r
-        }\r
-        event.getHttpServletRequest().setAttribute(COMET_EVENT_ATTR,this);\r
-        return result;\r
-    }\r
-    \r
-    protected synchronized boolean removeCometEvent(CometEvent event) {\r
-        boolean result = events.remove(event);\r
-        event.getHttpServletRequest().removeAttribute(COMET_EVENT_ATTR);\r
-        return result;\r
-    }\r
-    \r
-    \r
-    protected void subscribed(ChannelImpl ch) {\r
-        nrofsubscriptions.addAndGet(1);\r
-    }\r
-    \r
-    protected void unsubscribed(ChannelImpl ch) {\r
-        nrofsubscriptions.addAndGet(-1);\r
-    }\r
-    \r
-    public void startBatch(){\r
-        //noop until improved\r
-    }\r
-    public void endBatch() {\r
-        //noop until improved\r
-    }\r
-        \r
-}\r
+/*
+ * 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++) {
+                //dont deliver to ourselves
+                if (this!=msgs[i].getClient()) list.add(msgs[i]);
+            }
+            if (getListener() != null && list.size()>0) {
+                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
+    }
+        
+}
index 55ff2c7..b688658 100644 (file)
@@ -1,43 +1,43 @@
-package org.apache.tomcat.bayeux;\r
-\r
-public class HttpError {\r
-    private int code;\r
-    private String status;\r
-    private Throwable cause;\r
-    public HttpError(int code, String status, Throwable cause) {\r
-        this.code = code;\r
-        this.status = status;\r
-        this.cause = cause;\r
-    }\r
-\r
-    public void setCode(int code) {\r
-        this.code = code;\r
-    }\r
-\r
-    public void setStatus(String status) {\r
-        this.status = status;\r
-    }\r
-\r
-    public void setCause(Throwable exception) {\r
-        this.cause = exception;\r
-    }\r
-\r
-    public int getCode() {\r
-        return code;\r
-    }\r
-\r
-    public String getStatus() {\r
-        return status;\r
-    }\r
-\r
-    public Throwable getCause() {\r
-        return cause;\r
-    }\r
-\r
-    public String toString() {\r
-        if (cause != null)\r
-            return code + ":" + status + " - [" + cause + "]";\r
-        else\r
-            return code + ":" + status;\r
-    }\r
-}\r
+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;
+    }
+}
index 53d5342..8a3a24f 100644 (file)
@@ -1,80 +1,80 @@
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux;\r
-\r
-import java.util.HashMap;\r
-\r
-import org.apache.cometd.bayeux.Channel;\r
-import org.apache.cometd.bayeux.Client;\r
-import org.apache.cometd.bayeux.Message;\r
-\r
-public class MessageImpl extends HashMap<String,Object> implements Message {\r
-    \r
-    protected Channel channel;\r
-    protected Client client;\r
-    protected String id;\r
-    private long TTL = 1000*60*5; //5min is the default TTL for a message\r
-    protected long creationTime = System.currentTimeMillis();\r
-\r
-    public Object clone() {\r
-        MessageImpl copy = new MessageImpl(id);\r
-        copy.putAll(this);\r
-        copy.channel = channel;\r
-        copy.client = client;\r
-        copy.id = id;\r
-        copy.creationTime = creationTime;\r
-        copy.TTL = TTL;\r
-        return copy;\r
-    }\r
-\r
-    protected MessageImpl(String id) {\r
-        assert id != null;\r
-        this.id = id;\r
-    }\r
-\r
-    public Channel getChannel() {\r
-        return channel;\r
-    }\r
-\r
-    public Client getClient() {\r
-        return client;\r
-    }\r
-\r
-    public long getCreationTime() {\r
-        return creationTime;\r
-    }\r
-\r
-    public long getTTL() {\r
-        return TTL;\r
-    }\r
-\r
-    public String getId() {\r
-        return id;\r
-    }\r
-\r
-    protected void setChannel(Channel channel) {\r
-        this.channel = channel;\r
-    }\r
-\r
-    protected void setClient(Client client) {\r
-        this.client = client;\r
-    }\r
-\r
-    public void setTTL(long TTL) {\r
-        this.TTL = TTL;\r
-    }\r
+/*
+ * 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
index e3c4000..9f6036e 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- *\r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux;\r
-\r
-import java.io.IOException;\r
-import java.io.PrintWriter;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.LinkedHashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.TimeZone;\r
-import java.util.Date;\r
-import java.text.SimpleDateFormat;\r
-import javax.servlet.ServletException;\r
-\r
-import org.apache.catalina.CometEvent;\r
-import org.apache.tomcat.bayeux.HttpError;\r
-\r
-import org.apache.juli.logging.Log;\r
-import org.apache.juli.logging.LogFactory;\r
-import org.json.JSONArray;\r
-import org.json.JSONException;\r
-import org.json.JSONObject;\r
-import org.apache.cometd.bayeux.Bayeux;\r
-import org.apache.cometd.bayeux.Message;\r
-\r
-/**\r
- * Common functionality and member variables for all Bayeux requests.\r
- *\r
- * @author Guy A. Molinari\r
- * @author Filip Hanik\r
- * @version 0.9\r
- *\r
- */\r
-public abstract class RequestBase implements BayeuxRequest {\r
-    \r
-    protected static final SimpleDateFormat timestampFmt =\r
-        new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");\r
-    static {\r
-        timestampFmt.setTimeZone(TimeZone.getTimeZone("GMT"));\r
-    }\r
-    //message properties, combined for all messages\r
-    protected TomcatBayeux tomcatBayeux;\r
-    protected String channel;\r
-    protected String id;\r
-    protected String clientId;\r
-    protected String version = null;\r
-    protected String[] suppConnTypes = null;\r
-    protected int suppConnTypesFlag = 0;\r
-    protected int desiredConnTypeFlag = 0;\r
-    protected String minVersion = null;\r
-    protected String subscription = null;\r
-    protected String data = null;\r
-    protected String conType = null;\r
-    protected LinkedHashMap<String, Object> ext = new LinkedHashMap<String, Object> ();\r
-\r
-    \r
-    protected CometEvent event;\r
-    \r
-    protected HashMap<String, Object> response = null;\r
-    \r
-    protected static Log log = LogFactory.getLog(RequestBase.class);\r
-    \r
-    protected int reconnectInterval = 1000;\r
-    \r
-    protected RequestBase(TomcatBayeux tb, CometEvent event, JSONObject jsReq) throws JSONException {\r
-        this.tomcatBayeux = tb;\r
-        this.event = event;\r
-        channel = jsReq.optString(Bayeux.CHANNEL_FIELD);\r
-        id = jsReq.optString(Bayeux.ID_FIELD);\r
-        clientId = jsReq.optString(Bayeux.CLIENT_FIELD);\r
-        version = jsReq.optString(Bayeux.VERSION_FIELD);\r
-        minVersion = jsReq.optString(Bayeux.MIN_VERSION_FIELD);\r
-        conType = jsReq.optString(Bayeux.CONNECTION_TYPE_FIELD);\r
-        subscription = jsReq.optString(Bayeux.SUBSCRIPTION_FIELD);\r
-        data = jsReq.optString(Bayeux.DATA_FIELD);\r
-        reconnectInterval = tb.getReconnectInterval();\r
-        if (jsReq.has(Bayeux.EXT_FIELD)) {\r
-            JSONObject jext = jsReq.getJSONObject(Bayeux.EXT_FIELD);\r
-            for (Iterator<String> i = jext.keys(); i.hasNext(); ) {\r
-                String key = i.next();\r
-                ext.put(key, jext.get(key));\r
-            }//for\r
-        }//end if\r
-        \r
-        if (jsReq.has(Bayeux.SUPP_CONNECTION_TYPE_FIELD)) {\r
-            JSONArray types = jsReq.getJSONArray(Bayeux.SUPP_CONNECTION_TYPE_FIELD);\r
-            suppConnTypes = new String[types.length()];\r
-            for (int i = 0; i < types.length(); i++) {\r
-                suppConnTypes[i] = types.getString(i);\r
-                if (Bayeux.TRANSPORT_CALLBACK_POLL.equals(suppConnTypes[i]))\r
-                    suppConnTypesFlag = suppConnTypesFlag|ClientImpl.SUPPORT_CALLBACK_POLL;\r
-                else if (Bayeux.TRANSPORT_LONG_POLL.equals(suppConnTypes[i]))\r
-                    suppConnTypesFlag = suppConnTypesFlag|ClientImpl.SUPPORT_LONG_POLL;\r
-            }//for\r
-        }//end if\r
-\r
-        if (conType!=null) {\r
-            if (Bayeux.TRANSPORT_CALLBACK_POLL.equals(conType))\r
-                desiredConnTypeFlag = ClientImpl.SUPPORT_CALLBACK_POLL;\r
-            else if (Bayeux.TRANSPORT_LONG_POLL.equals(conType))\r
-                desiredConnTypeFlag = ClientImpl.SUPPORT_LONG_POLL;\r
-        }//end if\r
-        \r
-        //due to the fact that the javascript doesn't send up a required field\r
-        //we have to fake it\r
-        suppConnTypesFlag = ClientImpl.SUPPORT_CALLBACK_POLL | ClientImpl.SUPPORT_LONG_POLL;\r
-\r
-    }\r
-\r
-    public HttpError validate() {\r
-        HttpError result = null;\r
-//        if (clientId == null) {\r
-//            result = new HttpError(401,"No Client ID.", null);\r
-//        }\r
-        return result;\r
-    }\r
-\r
-    public TomcatBayeux getTomcatBayeux() {\r
-        return tomcatBayeux;\r
-    }\r
-\r
-    public String getChannel() {\r
-        return channel;\r
-    }\r
-\r
-    public String getId() {\r
-        return id;\r
-    }\r
-\r
-    public String getClientId() {\r
-        return clientId;\r
-    }\r
-\r
-    public LinkedHashMap getExt() {\r
-        return ext;\r
-    }\r
-\r
-    public CometEvent getEvent() {\r
-        return event;\r
-    }\r
-    \r
-    protected static void deliver(CometEvent event, ClientImpl to) throws IOException, ServletException, BayeuxException {\r
-        JSONArray jarray = getJSONArray(event,true);\r
-        if ( jarray == null ) throw new BayeuxException("No message to send!");\r
-        String jsonstring = jarray.toString();\r
-        if (log.isDebugEnabled()) {\r
-            log.debug("["+Thread.currentThread().getName()+"] Delivering message to[" + to + "] message:" + jsonstring);\r
-        }\r
-\r
-        if (to!=null) {\r
-            if (to.useJsonFiltered()) {\r
-                if (!event.getHttpServletResponse().isCommitted()) event.getHttpServletResponse().setContentType("text/json-comment-filtered");\r
-            }else {    \r
-                if (!event.getHttpServletResponse().isCommitted()) event.getHttpServletResponse().setContentType("text/json");\r
-            }\r
-        }\r
-\r
-        PrintWriter out = event.getHttpServletResponse().getWriter();\r
-        if (to==null) {\r
-            //do nothing\r
-        }else if ( (to.getDesirectConnType() == 0 && to.supportsLongPoll()) || to.getDesirectConnType() == ClientImpl.SUPPORT_LONG_POLL) {\r
-            if (to.useJsonFiltered())\r
-                out.print("/*");\r
-        } else if ( (to.getDesirectConnType() == 0 && to.supportsCallbackPoll()) || to.getDesirectConnType() == ClientImpl.SUPPORT_CALLBACK_POLL) {\r
-            String jsonp = event.getHttpServletRequest().getParameter(Bayeux.JSONP_PARAMETER);\r
-            if (jsonp == null)\r
-                jsonp = Bayeux.JSONP_DEFAULT_NAME;\r
-            out.print(jsonp);\r
-            out.print('(');\r
-        } else {\r
-            throw new BayeuxException("Client doesn't support any appropriate connection type.");\r
-        }\r
-        out.print(jsonstring);\r
-        if ( to == null ) {\r
-            //do nothing\r
-        } else if ( (to.getDesirectConnType() == 0 && to.supportsLongPoll()) || to.getDesirectConnType() == ClientImpl.SUPPORT_LONG_POLL) {\r
-            if (to.useJsonFiltered())\r
-                out.print("*/");\r
-        } else if ( (to.getDesirectConnType() == 0 && to.supportsCallbackPoll()) || to.getDesirectConnType() == ClientImpl.SUPPORT_CALLBACK_POLL) {\r
-            out.print(");");\r
-        } \r
-        out.flush();\r
-        event.getHttpServletResponse().flushBuffer();\r
-\r
-        \r
-    }\r
-\r
-    protected static JSONArray getJSONArray(CometEvent event, boolean nullok) {\r
-        synchronized(event) {\r
-            JSONArray jarray = (JSONArray) event.getHttpServletRequest().getAttribute(JSON_MSG_ARRAY);\r
-            if (jarray == null && (!nullok)) {\r
-                jarray = new JSONArray();\r
-                event.getHttpServletRequest().setAttribute(JSON_MSG_ARRAY, jarray);\r
-            }\r
-            return jarray;\r
-        }\r
-    }\r
-\r
-    protected JSONArray getJSONArray() {\r
-        return getJSONArray(event,false);\r
-    }\r
-\r
-    protected void addToDeliveryQueue(ClientImpl to, JSONObject msg) throws IOException, ServletException, BayeuxException {\r
-        synchronized (event) {\r
-            getJSONArray().put(msg);\r
-        }\r
-    }\r
-    \r
-    protected void flushMessages(ClientImpl client) throws BayeuxException {\r
-        List<Message> msgs = client.takeMessages();\r
-        synchronized (event) {\r
-            try {\r
-                for (Iterator<Message> it = msgs.iterator(); it.hasNext(); ){\r
-                    MessageImpl msg = (MessageImpl)it.next();\r
-                    Map map = new HashMap();\r
-                    map.put(Bayeux.CHANNEL_FIELD,msg.getChannel().getId());\r
-                    if (msg.getClient()!=null) map.put(Bayeux.CLIENT_FIELD,msg.getClient().getId());\r
-                    map.put(Bayeux.DATA_FIELD,msg);\r
-                    JSONObject obj = new JSONObject(map);\r
-                    addToDeliveryQueue(client, obj);\r
-                }\r
-            } catch (ServletException x) {\r
-                throw new BayeuxException(x);\r
-            } catch (IOException x) {\r
-                throw new BayeuxException(x);\r
-            }\r
-        }\r
-    }\r
-    \r
-    public int process(int prevops) throws BayeuxException {\r
-        event.getHttpServletRequest().setAttribute(CURRENT_REQ_ATTR,this);\r
-        return prevops;\r
-    }\r
-    \r
-    public int getReconnectInterval() {\r
-        return reconnectInterval;\r
-    }\r
-\r
-    public String getTimeStamp() {\r
-        return timestampFmt.format(new Date(System.currentTimeMillis()));\r
-    }\r
-\r
-}\r
+/*
+ * 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 = 1000;
+    
+    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);
+        }
+
+        if (to!=null) {
+            if (to.useJsonFiltered()) {
+                if (!event.getHttpServletResponse().isCommitted()) event.getHttpServletResponse().setContentType("text/json-comment-filtered");
+            }else {    
+                if (!event.getHttpServletResponse().isCommitted()) event.getHttpServletResponse().setContentType("text/json");
+            }
+        }
+
+        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()));
+    }
+
+}
index f2765e6..c617180 100644 (file)
@@ -1,48 +1,48 @@
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux;\r
-\r
-import org.json.JSONObject;\r
-import org.apache.tomcat.bayeux.request.MetaHandshakeRequest;\r
-import org.apache.catalina.CometEvent;\r
-import org.json.JSONException;\r
-import org.apache.tomcat.bayeux.request.MetaConnectRequest;\r
-import org.apache.tomcat.bayeux.request.MetaDisconnectRequest;\r
-import org.apache.tomcat.bayeux.request.MetaSubscribeRequest;\r
-import org.apache.tomcat.bayeux.request.MetaUnsubscribeRequest;\r
-import org.apache.tomcat.bayeux.request.PublishRequest;\r
-import org.apache.cometd.bayeux.Bayeux;\r
-\r
-public class RequestFactory {\r
-\r
-    public static BayeuxRequest getRequest(TomcatBayeux tomcatBayeux, CometEvent event, JSONObject msg) throws JSONException {\r
-        String channel = msg.optString(Bayeux.CHANNEL_FIELD);\r
-        if (Bayeux.META_HANDSHAKE.equals(channel)) {\r
-            return new MetaHandshakeRequest(tomcatBayeux,event,msg);\r
-        }else if (Bayeux.META_CONNECT.equals(channel)) {\r
-            return new MetaConnectRequest(tomcatBayeux,event,msg);\r
-        }else if (Bayeux.META_DISCONNECT.equals(channel)) {\r
-            return new MetaDisconnectRequest(tomcatBayeux,event,msg);\r
-        }else if (Bayeux.META_SUBSCRIBE.equals(channel)) {\r
-            return new MetaSubscribeRequest(tomcatBayeux,event,msg);\r
-        }else if (Bayeux.META_UNSUBSCRIBE.equals(channel)) {\r
-            return new MetaUnsubscribeRequest(tomcatBayeux,event,msg);\r
-        } else {\r
-            return new PublishRequest(tomcatBayeux,event,msg);\r
-        }\r
-    }\r
+/*
+ * 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.json.JSONObject;
+import org.apache.tomcat.bayeux.request.MetaHandshakeRequest;
+import org.apache.catalina.CometEvent;
+import org.json.JSONException;
+import org.apache.tomcat.bayeux.request.MetaConnectRequest;
+import org.apache.tomcat.bayeux.request.MetaDisconnectRequest;
+import org.apache.tomcat.bayeux.request.MetaSubscribeRequest;
+import org.apache.tomcat.bayeux.request.MetaUnsubscribeRequest;
+import org.apache.tomcat.bayeux.request.PublishRequest;
+import org.apache.cometd.bayeux.Bayeux;
+
+public class RequestFactory {
+
+    public static BayeuxRequest getRequest(TomcatBayeux tomcatBayeux, CometEvent event, JSONObject msg) throws JSONException {
+        String channel = msg.optString(Bayeux.CHANNEL_FIELD);
+        if (Bayeux.META_HANDSHAKE.equals(channel)) {
+            return new MetaHandshakeRequest(tomcatBayeux,event,msg);
+        }else if (Bayeux.META_CONNECT.equals(channel)) {
+            return new MetaConnectRequest(tomcatBayeux,event,msg);
+        }else if (Bayeux.META_DISCONNECT.equals(channel)) {
+            return new MetaDisconnectRequest(tomcatBayeux,event,msg);
+        }else if (Bayeux.META_SUBSCRIBE.equals(channel)) {
+            return new MetaSubscribeRequest(tomcatBayeux,event,msg);
+        }else if (Bayeux.META_UNSUBSCRIBE.equals(channel)) {
+            return new MetaUnsubscribeRequest(tomcatBayeux,event,msg);
+        } else {
+            return new PublishRequest(tomcatBayeux,event,msg);
+        }
+    }
 }
\ No newline at end of file
index efe2264..e7d33c0 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux;\r
-\r
-import java.util.HashMap;\r
-import java.util.LinkedHashMap;\r
-import java.util.List;\r
-\r
-import org.apache.catalina.CometEvent;\r
-import org.apache.catalina.tribes.util.Arrays;\r
-import org.apache.catalina.tribes.util.UUIDGenerator;\r
-import org.apache.cometd.bayeux.Bayeux;\r
-import org.apache.cometd.bayeux.Channel;\r
-import org.apache.cometd.bayeux.Client;\r
-import org.apache.cometd.bayeux.Listener;\r
-import org.apache.cometd.bayeux.Message;\r
-import org.apache.cometd.bayeux.SecurityPolicy;\r
-/**\r
- * \r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class TomcatBayeux implements Bayeux {\r
-    \r
-\r
-    protected int reconnectInterval = 5000;\r
-    /**\r
-     * a list of all active clients\r
-     */\r
-    protected HashMap<String,Client> clients = new HashMap<String,Client>();\r
-    \r
-    /**\r
-     * a list of all active channels\r
-     */\r
-    protected LinkedHashMap<String, Channel> channels = new LinkedHashMap<String,Channel>();\r
-    \r
-    /**\r
-     * security policy to be used.\r
-     */\r
-    protected SecurityPolicy securityPolicy = null;\r
-    /**\r
-     * default client to use when we need to send an error message but don't have a client valid reference\r
-     */\r
-    protected static ClientImpl errorClient = new ClientImpl("error-no-client",false);\r
-    \r
-    /**\r
-     * returns the default error client\r
-     * @return ClientImpl\r
-     */\r
-    public static ClientImpl getErrorClient() {\r
-        return errorClient;\r
-    }\r
-    \r
-    protected TomcatBayeux() {\r
-    }\r
-    \r
-    /**\r
-     * should be invoked when the servlet is destroyed or when the context shuts down\r
-     */\r
-    public void destroy() {\r
-        throw new UnsupportedOperationException("TomcatBayeux.destroy() not yet implemented");\r
-    }\r
-\r
-    public Channel getChannel(String channelId, boolean create) {\r
-        Channel result = channels.get(channelId);\r
-        if (result==null && create) {\r
-            result = new ChannelImpl(channelId);\r
-            channels.put(channelId,result);\r
-        }\r
-        return result;\r
-    }\r
-    \r
-    public Channel remove(Channel channel) {\r
-        return channels.remove(channel.getId());\r
-    }\r
-    \r
-    public Client remove(Client client) {\r
-        if (client==null) return null;\r
-        for (Channel ch : getChannels()) {\r
-            ch.unsubscribe(client);\r
-        }\r
-        return clients.remove(client.getId());\r
-    }\r
-\r
-    public Client getClient(String clientId) {\r
-        return clients.get(clientId);\r
-    }\r
-    \r
-    public boolean hasClient(String clientId) {\r
-        return clients.containsKey(clientId);\r
-    }\r
-    \r
-    public List<Client> getClients() {\r
-        return java.util.Arrays.asList(clients.entrySet().toArray(new Client[0]));\r
-    }\r
-\r
-    public SecurityPolicy getSecurityPolicy() {\r
-        return securityPolicy;\r
-    }\r
-\r
-    public int getReconnectInterval() { \r
-        return reconnectInterval;\r
-    }\r
-\r
-    public boolean hasChannel(String channel) {\r
-        return channels.containsKey(channel);\r
-    }\r
-\r
-    public Client newClient(String idprefix, Listener listener, boolean local, CometEvent event) {\r
-        String id = createUUID(idprefix);\r
-        ClientImpl client = new ClientImpl(id, local);\r
-        client.setListener(listener);\r
-        clients.put(id, client);\r
-        return client;\r
-    }\r
-\r
-    public Client newClient(String idprefix, Listener listener) {\r
-        assert listener!=null;\r
-        //if this method gets called, someone is using the API inside\r
-        //the JVM, this is a local client\r
-        return newClient(idprefix,listener,true, null);\r
-    }\r
-    \r
-    protected ClientImpl getClientImpl(CometEvent event) {\r
-        return (ClientImpl)event.getHttpServletRequest().getAttribute(ClientImpl.COMET_EVENT_ATTR);\r
-    }\r
-    \r
-    protected void remove(CometEvent event) {\r
-        ClientImpl client = getClientImpl(event);\r
-        if (client!=null) {\r
-            client.removeCometEvent(event);\r
-        }\r
-    }\r
-\r
-    public String createUUID(String idprefix) {\r
-        if (idprefix==null) idprefix="";\r
-        return idprefix + Arrays.toString(UUIDGenerator.randomUUID(false));\r
-    }\r
-    \r
-    public List<Channel> getChannels() {\r
-        return java.util.Arrays.asList(channels.entrySet().toArray(new Channel[0]));\r
-    }\r
-\r
-    protected Message newMessage() {\r
-        String id = createUUID("msg-");\r
-        return new MessageImpl(id);\r
-    }\r
-\r
-    public Message newMessage(Client from) {\r
-        MessageImpl msg = (MessageImpl)newMessage();\r
-        msg.setClient(from);\r
-        return msg;\r
-    }\r
-    public void setSecurityPolicy(SecurityPolicy securityPolicy) {\r
-        this.securityPolicy = securityPolicy;\r
-    }\r
-\r
-    public void setReconnectInterval(int reconnectTimeout) {\r
-        this.reconnectInterval = reconnectTimeout;\r
-    }\r
-\r
-}\r
+/*
+ * 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 java.util.LinkedHashMap;
+import java.util.List;
+
+import org.apache.catalina.CometEvent;
+import org.apache.catalina.tribes.util.Arrays;
+import org.apache.catalina.tribes.util.UUIDGenerator;
+import org.apache.cometd.bayeux.Bayeux;
+import org.apache.cometd.bayeux.Channel;
+import org.apache.cometd.bayeux.Client;
+import org.apache.cometd.bayeux.Listener;
+import org.apache.cometd.bayeux.Message;
+import org.apache.cometd.bayeux.SecurityPolicy;
+/**
+ * 
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class TomcatBayeux implements Bayeux {
+    
+
+    protected int reconnectInterval = 5000;
+    /**
+     * a list of all active clients
+     */
+    protected HashMap<String,Client> clients = new HashMap<String,Client>();
+    
+    /**
+     * a list of all active channels
+     */
+    protected LinkedHashMap<String, Channel> channels = new LinkedHashMap<String,Channel>();
+    
+    /**
+     * security policy to be used.
+     */
+    protected SecurityPolicy securityPolicy = null;
+    /**
+     * default client to use when we need to send an error message but don't have a client valid reference
+     */
+    protected static ClientImpl errorClient = new ClientImpl("error-no-client",false);
+    
+    /**
+     * returns the default error client
+     * @return ClientImpl
+     */
+    public static ClientImpl getErrorClient() {
+        return errorClient;
+    }
+    
+    protected TomcatBayeux() {
+    }
+    
+    /**
+     * should be invoked when the servlet is destroyed or when the context shuts down
+     */
+    public void destroy() {
+        throw new UnsupportedOperationException("TomcatBayeux.destroy() not yet implemented");
+    }
+
+    public Channel getChannel(String channelId, boolean create) {
+        Channel result = channels.get(channelId);
+        if (result==null && create) {
+            result = new ChannelImpl(channelId);
+            channels.put(channelId,result);
+        }
+        return result;
+    }
+    
+    public Channel remove(Channel channel) {
+        return channels.remove(channel.getId());
+    }
+    
+    public Client remove(Client client) {
+        if (client==null) return null;
+        for (Channel ch : getChannels()) {
+            ch.unsubscribe(client);
+        }
+        return clients.remove(client.getId());
+    }
+
+    public Client getClient(String clientId) {
+        return clients.get(clientId);
+    }
+    
+    public boolean hasClient(String clientId) {
+        return clients.containsKey(clientId);
+    }
+    
+    public List<Client> getClients() {
+        return java.util.Arrays.asList(clients.entrySet().toArray(new Client[0]));
+    }
+
+    public SecurityPolicy getSecurityPolicy() {
+        return securityPolicy;
+    }
+
+    public int getReconnectInterval() { 
+        return reconnectInterval;
+    }
+
+    public boolean hasChannel(String channel) {
+        return channels.containsKey(channel);
+    }
+
+    public Client newClient(String idprefix, Listener listener, boolean local, CometEvent event) {
+        String id = createUUID(idprefix);
+        ClientImpl client = new ClientImpl(id, local);
+        client.setListener(listener);
+        clients.put(id, client);
+        return client;
+    }
+
+    public Client newClient(String idprefix, Listener listener) {
+        assert listener!=null;
+        //if this method gets called, someone is using the API inside
+        //the JVM, this is a local client
+        return newClient(idprefix,listener,true, null);
+    }
+    
+    protected ClientImpl getClientImpl(CometEvent event) {
+        return (ClientImpl)event.getHttpServletRequest().getAttribute(ClientImpl.COMET_EVENT_ATTR);
+    }
+    
+    protected void remove(CometEvent event) {
+        ClientImpl client = getClientImpl(event);
+        if (client!=null) {
+            client.removeCometEvent(event);
+        }
+    }
+
+    public String createUUID(String idprefix) {
+        if (idprefix==null) idprefix="";
+        return idprefix + Arrays.toString(UUIDGenerator.randomUUID(false));
+    }
+    
+    public List<Channel> getChannels() {
+        return java.util.Arrays.asList(channels.entrySet().toArray(new Channel[0]));
+    }
+
+    protected Message newMessage() {
+        String id = createUUID("msg-");
+        return new MessageImpl(id);
+    }
+
+    public Message newMessage(Client from) {
+        MessageImpl msg = (MessageImpl)newMessage();
+        msg.setClient(from);
+        return msg;
+    }
+    public void setSecurityPolicy(SecurityPolicy securityPolicy) {
+        this.securityPolicy = securityPolicy;
+    }
+
+    public void setReconnectInterval(int reconnectTimeout) {
+        this.reconnectInterval = reconnectTimeout;
+    }
+
+}
index baa4e8f..2eacdbc 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux.request;\r
-\r
-import java.io.IOException;\r
-import java.util.HashMap;\r
-import javax.servlet.ServletException;\r
-\r
-import org.apache.catalina.CometEvent;\r
-import org.apache.tomcat.bayeux.HttpError;\r
-import org.apache.tomcat.bayeux.BayeuxException;\r
-import org.apache.tomcat.bayeux.BayeuxRequest;\r
-import org.apache.tomcat.bayeux.ClientImpl;\r
-import org.apache.tomcat.bayeux.TomcatBayeux;\r
-import org.json.JSONException;\r
-import org.json.JSONObject;\r
-import org.apache.cometd.bayeux.Bayeux;\r
-import org.apache.tomcat.bayeux.*;\r
-\r
-/******************************************************************************\r
- * Handshake request Bayeux message.\r
- *\r
- * @author Guy A. Molinari\r
- * @author Filip Hanik\r
- * @version 1.0\r
- *\r
- */\r
-public class MetaConnectRequest extends RequestBase implements BayeuxRequest {\r
-    protected static HashMap<String,Object> responseTemplate = new HashMap<String,Object>();\r
-\r
-    static {\r
-        responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_CONNECT);\r
-        responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE);\r
-        responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap<String, Object>());\r
-    }\r
-\r
-    public MetaConnectRequest(TomcatBayeux tb, CometEvent event, JSONObject jsReq) throws JSONException {\r
-        super(tb, event, jsReq);\r
-        if (clientId!=null && getTomcatBayeux().hasClient(clientId)) {\r
-            event.getHttpServletRequest().setAttribute("client",getTomcatBayeux().getClient(clientId));\r
-        }\r
-    }\r
-\r
-\r
-    /**\r
-     * Check client request for validity.\r
-     *\r
-     * Per section 4.2.1 of the Bayuex spec a connect request must contain:\r
-     *  1) The "/meta/connect" channel identifier.\r
-     *  2) The clientId returned by the server after handshake.\r
-     *  3) The desired connectionType (must be one of the server's supported\r
-     *     types returned by handshake response.\r
-     *  \r
-     * @return HttpError This method returns null if no errors were found\r
-     */\r
-    public HttpError validate() {\r
-        if(clientId==null|| (!getTomcatBayeux().hasClient(clientId)))\r
-            return new HttpError(400,"Client Id not valid.", null);\r
-        if (! (Bayeux.TRANSPORT_LONG_POLL.equals(conType) || Bayeux.TRANSPORT_CALLBACK_POLL.equals(conType)))\r
-            return new HttpError(400,"Unsupported connection type.",null);\r
-        return null;//no error\r
-    }\r
-\r
-    /**\r
-     * Transition to connected state, flushing pending messages if\r
-     * available.  If there are pending subscriptions and no messages to\r
-     * flush then the connection is held until there is a pending publish\r
-     * event to be delivered to this client (Section 4.2.2 of spec).\r
-     */\r
-    public int process(int prevops) throws BayeuxException {\r
-        super.process(prevops);\r
-        response = (HashMap<String, Object>)responseTemplate.clone();\r
-        ClientImpl client = (ClientImpl)getTomcatBayeux().getClient(clientId);\r
-        boolean success = false;\r
-        HttpError error = validate();\r
-        if (error == null) {\r
-            client.setDesirectConnType(desiredConnTypeFlag);\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.RECONNECT_FIELD, Bayeux.RETRY_RESPONSE);\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.INTERVAL_FIELD, getReconnectInterval());\r
-            success = true;\r
-        }else {\r
-            response.put(Bayeux.SUCCESSFUL_FIELD,Boolean.FALSE);\r
-            response.put(Bayeux.ERROR_FIELD, error.toString());\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.RECONNECT_FIELD, Bayeux.HANDSHAKE_RESPONSE);\r
-            if (client==null) client = TomcatBayeux.getErrorClient();\r
-        }\r
-        response.put(Bayeux.CLIENT_FIELD, client.getId());\r
-        response.put(Bayeux.TIMESTAMP_FIELD,getTimeStamp());\r
-        try {\r
-            JSONObject obj = new JSONObject(response);\r
-            addToDeliveryQueue(client, obj);\r
-        } catch (ServletException x) {\r
-            throw new BayeuxException(x);\r
-        } catch (IOException x) {\r
-            throw new BayeuxException(x);\r
-        }\r
-        \r
-        //return immediately if there is no subscriptions\r
-        //so that we can process the next message\r
-        int result = client.isSubscribed()?1:0; \r
-\r
-        if (success && client!=null && client.hasMessages()) {\r
-            //send out messages \r
-            flushMessages(client);\r
-            result = 0; //flush out the messages\r
-        }\r
-\r
-        return result;\r
-    }\r
-}\r
-\r
+/*
+ * 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.request;
+
+import java.io.IOException;
+import java.util.HashMap;
+import javax.servlet.ServletException;
+
+import org.apache.catalina.CometEvent;
+import org.apache.tomcat.bayeux.HttpError;
+import org.apache.tomcat.bayeux.BayeuxException;
+import org.apache.tomcat.bayeux.BayeuxRequest;
+import org.apache.tomcat.bayeux.ClientImpl;
+import org.apache.tomcat.bayeux.TomcatBayeux;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.apache.cometd.bayeux.Bayeux;
+import org.apache.tomcat.bayeux.*;
+
+/******************************************************************************
+ * Handshake request Bayeux message.
+ *
+ * @author Guy A. Molinari
+ * @author Filip Hanik
+ * @version 1.0
+ *
+ */
+public class MetaConnectRequest extends RequestBase implements BayeuxRequest {
+    protected static HashMap<String,Object> responseTemplate = new HashMap<String,Object>();
+
+    static {
+        responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_CONNECT);
+        responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE);
+        responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap<String, Object>());
+    }
+
+    public MetaConnectRequest(TomcatBayeux tb, CometEvent event, JSONObject jsReq) throws JSONException {
+        super(tb, event, jsReq);
+        if (clientId!=null && getTomcatBayeux().hasClient(clientId)) {
+            event.getHttpServletRequest().setAttribute("client",getTomcatBayeux().getClient(clientId));
+        }
+    }
+
+
+    /**
+     * Check client request for validity.
+     *
+     * Per section 4.2.1 of the Bayuex spec a connect request must contain:
+     *  1) The "/meta/connect" channel identifier.
+     *  2) The clientId returned by the server after handshake.
+     *  3) The desired connectionType (must be one of the server's supported
+     *     types returned by handshake response.
+     *  
+     * @return HttpError This method returns null if no errors were found
+     */
+    public HttpError validate() {
+        if(clientId==null|| (!getTomcatBayeux().hasClient(clientId)))
+            return new HttpError(400,"Client Id not valid.", null);
+        if (! (Bayeux.TRANSPORT_LONG_POLL.equals(conType) || Bayeux.TRANSPORT_CALLBACK_POLL.equals(conType)))
+            return new HttpError(400,"Unsupported connection type.",null);
+        return null;//no error
+    }
+
+    /**
+     * Transition to connected state, flushing pending messages if
+     * available.  If there are pending subscriptions and no messages to
+     * flush then the connection is held until there is a pending publish
+     * event to be delivered to this client (Section 4.2.2 of spec).
+     */
+    public int process(int prevops) throws BayeuxException {
+        super.process(prevops);
+        response = (HashMap<String, Object>)responseTemplate.clone();
+        ClientImpl client = (ClientImpl)getTomcatBayeux().getClient(clientId);
+        boolean success = false;
+        HttpError error = validate();
+        if (error == null) {
+            client.setDesirectConnType(desiredConnTypeFlag);
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.RECONNECT_FIELD, Bayeux.RETRY_RESPONSE);
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.INTERVAL_FIELD, getReconnectInterval());
+            success = true;
+        }else {
+            response.put(Bayeux.SUCCESSFUL_FIELD,Boolean.FALSE);
+            response.put(Bayeux.ERROR_FIELD, error.toString());
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.RECONNECT_FIELD, Bayeux.HANDSHAKE_RESPONSE);
+            if (client==null) client = TomcatBayeux.getErrorClient();
+        }
+        response.put(Bayeux.CLIENT_FIELD, client.getId());
+        response.put(Bayeux.TIMESTAMP_FIELD,getTimeStamp());
+        try {
+            JSONObject obj = new JSONObject(response);
+            addToDeliveryQueue(client, obj);
+        } catch (ServletException x) {
+            throw new BayeuxException(x);
+        } catch (IOException x) {
+            throw new BayeuxException(x);
+        }
+        
+        //return immediately if there is no subscriptions
+        //so that we can process the next message
+        int result = client.isSubscribed()?1:0; 
+
+        if (success && client!=null && client.hasMessages()) {
+            //send out messages 
+            flushMessages(client);
+            result = 0; //flush out the messages
+        }
+
+        return result;
+    }
+}
+
index be840e9..b3dde94 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux.request;\r
-\r
-import java.io.IOException;\r
-import java.util.HashMap;\r
-import javax.servlet.ServletException;\r
-\r
-import org.apache.catalina.CometEvent;\r
-import org.apache.tomcat.bayeux.HttpError;\r
-import org.apache.tomcat.bayeux.BayeuxException;\r
-import org.apache.tomcat.bayeux.BayeuxRequest;\r
-import org.apache.tomcat.bayeux.ClientImpl;\r
-import org.apache.tomcat.bayeux.TomcatBayeux;\r
-import org.json.JSONException;\r
-import org.json.JSONObject;\r
-import org.apache.cometd.bayeux.Bayeux;\r
-import org.apache.tomcat.bayeux.*;\r
-import org.apache.cometd.bayeux.Channel;\r
-\r
-/******************************************************************************\r
- * Handshake request Bayeux message.\r
- *\r
- * @author Guy A. Molinari\r
- * @author Filip Hanik\r
- * @version 1.0\r
- *\r
- */\r
-public class MetaDisconnectRequest extends RequestBase implements BayeuxRequest {\r
-\r
-    protected static HashMap<String,Object> responseTemplate = new HashMap<String,Object>();\r
-\r
-    static {\r
-        responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_DISCONNECT);\r
-        responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE);\r
-        responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap<String, Object>());\r
-    }\r
-\r
-    public MetaDisconnectRequest(TomcatBayeux tb, CometEvent event, JSONObject jsReq) throws JSONException {\r
-        super(tb, event, jsReq);\r
-    }\r
-\r
-\r
-    /**\r
-     * Check client request for validity.\r
-     *\r
-     * Per section 4.4.1 of the Bayuex spec a connect request must contain:\r
-     *  1) The "/meta/disconnect" channel identifier.\r
-     *  2) The clientId.\r
-     *  \r
-     * @return HttpError This method returns null if no errors were found\r
-     */\r
-    public HttpError validate() {\r
-        if(clientId==null|| (!this.getTomcatBayeux().hasClient(clientId)))\r
-            return new HttpError(400,"Client Id not valid.", null);\r
-//        if (! (Bayeux.TRANSPORT_LONG_POLL.equals(conType) || Bayeux.TRANSPORT_CALLBACK_POLL.equals(conType)))\r
-//            return new HttpError(400,"Unsupported connection type.",null);\r
-        return null;//no error\r
-    }\r
-\r
-    /**\r
-     * Disconnect a client session.\r
-     */\r
-    public int process(int prevops) throws BayeuxException {\r
-        super.process(prevops);\r
-        response = (HashMap<String, Object>)responseTemplate.clone();\r
-        ClientImpl client = (ClientImpl)getTomcatBayeux().getClient(clientId);\r
-        HttpError error = validate();\r
-        if (error == null) {\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("reconnect", "retry");\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("interval", getReconnectInterval());\r
-        }else {\r
-            getTomcatBayeux().remove(client);\r
-            response.put(Bayeux.SUCCESSFUL_FIELD,Boolean.FALSE);\r
-            response.put(Bayeux.ERROR_FIELD, error.toString());\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("reconnect", "none");\r
-            if (client==null) client = TomcatBayeux.getErrorClient();\r
-        }\r
-        response.put(Bayeux.CLIENT_FIELD, client.getId());\r
-        try {\r
-            JSONObject obj = new JSONObject(response);\r
-            addToDeliveryQueue(client, obj);\r
-        } catch (ServletException x) {\r
-            throw new BayeuxException(x);\r
-        } catch (IOException x) {\r
-            throw new BayeuxException(x);\r
-        }\r
-        return 0;\r
-    }\r
-}\r
-\r
+/*
+ * 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.request;
+
+import java.io.IOException;
+import java.util.HashMap;
+import javax.servlet.ServletException;
+
+import org.apache.catalina.CometEvent;
+import org.apache.tomcat.bayeux.HttpError;
+import org.apache.tomcat.bayeux.BayeuxException;
+import org.apache.tomcat.bayeux.BayeuxRequest;
+import org.apache.tomcat.bayeux.ClientImpl;
+import org.apache.tomcat.bayeux.TomcatBayeux;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.apache.cometd.bayeux.Bayeux;
+import org.apache.tomcat.bayeux.*;
+import org.apache.cometd.bayeux.Channel;
+
+/******************************************************************************
+ * Handshake request Bayeux message.
+ *
+ * @author Guy A. Molinari
+ * @author Filip Hanik
+ * @version 1.0
+ *
+ */
+public class MetaDisconnectRequest extends RequestBase implements BayeuxRequest {
+
+    protected static HashMap<String,Object> responseTemplate = new HashMap<String,Object>();
+
+    static {
+        responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_DISCONNECT);
+        responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE);
+        responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap<String, Object>());
+    }
+
+    public MetaDisconnectRequest(TomcatBayeux tb, CometEvent event, JSONObject jsReq) throws JSONException {
+        super(tb, event, jsReq);
+    }
+
+
+    /**
+     * Check client request for validity.
+     *
+     * Per section 4.4.1 of the Bayuex spec a connect request must contain:
+     *  1) The "/meta/disconnect" channel identifier.
+     *  2) The clientId.
+     *  
+     * @return HttpError This method returns null if no errors were found
+     */
+    public HttpError validate() {
+        if(clientId==null|| (!this.getTomcatBayeux().hasClient(clientId)))
+            return new HttpError(400,"Client Id not valid.", null);
+//        if (! (Bayeux.TRANSPORT_LONG_POLL.equals(conType) || Bayeux.TRANSPORT_CALLBACK_POLL.equals(conType)))
+//            return new HttpError(400,"Unsupported connection type.",null);
+        return null;//no error
+    }
+
+    /**
+     * Disconnect a client session.
+     */
+    public int process(int prevops) throws BayeuxException {
+        super.process(prevops);
+        response = (HashMap<String, Object>)responseTemplate.clone();
+        ClientImpl client = (ClientImpl)getTomcatBayeux().getClient(clientId);
+        HttpError error = validate();
+        if (error == null) {
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("reconnect", "retry");
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("interval", getReconnectInterval());
+        }else {
+            getTomcatBayeux().remove(client);
+            response.put(Bayeux.SUCCESSFUL_FIELD,Boolean.FALSE);
+            response.put(Bayeux.ERROR_FIELD, error.toString());
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("reconnect", "none");
+            if (client==null) client = TomcatBayeux.getErrorClient();
+        }
+        response.put(Bayeux.CLIENT_FIELD, client.getId());
+        try {
+            JSONObject obj = new JSONObject(response);
+            addToDeliveryQueue(client, obj);
+        } catch (ServletException x) {
+            throw new BayeuxException(x);
+        } catch (IOException x) {
+            throw new BayeuxException(x);
+        }
+        return 0;
+    }
+}
+
index bd38b9e..0883ae9 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux.request;\r
-\r
-import java.io.IOException;\r
-import java.util.HashMap;\r
-import javax.servlet.ServletException;\r
-\r
-import org.apache.catalina.CometEvent;\r
-import org.apache.tomcat.bayeux.HttpError;\r
-import org.apache.tomcat.bayeux.BayeuxException;\r
-import org.apache.tomcat.bayeux.BayeuxRequest;\r
-import org.apache.tomcat.bayeux.ClientImpl;\r
-import org.apache.tomcat.bayeux.TomcatBayeux;\r
-import org.json.JSONException;\r
-import org.json.JSONObject;\r
-import org.apache.cometd.bayeux.Bayeux;\r
-import org.apache.tomcat.bayeux.*;\r
-\r
-/******************************************************************************\r
- * Handshake request Bayeux message.\r
- *\r
- * @author Guy A. Molinari\r
- * @author Filip Hanik\r
- * @version 1.0\r
- *\r
- */\r
-public class MetaHandshakeRequest extends RequestBase implements BayeuxRequest {\r
-\r
-    protected static HashMap<String,Object> responseTemplate = new HashMap<String,Object>();\r
-    \r
-    static {\r
-        responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_HANDSHAKE);\r
-        responseTemplate.put(Bayeux.VERSION_FIELD,"1.0");\r
-        responseTemplate.put(Bayeux.SUPP_CONNECTION_TYPE_FIELD,new String[] { Bayeux.TRANSPORT_LONG_POLL, Bayeux.TRANSPORT_CALLBACK_POLL });\r
-        responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE);\r
-        responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap<String, Object>());\r
-    }\r
-\r
-    public MetaHandshakeRequest(TomcatBayeux tomcatBayeux, CometEvent event, JSONObject jsReq) throws JSONException {\r
-        super(tomcatBayeux, event, jsReq);\r
-    }\r
-    \r
-\r
-    public String getVersion() { return version; }\r
-    public String getMinimumVersion() { return minVersion; }\r
-\r
-\r
-    /**\r
-     * Check client request for validity.\r
-     *\r
-     * Per section 4.1.1 of the Bayuex spec a handshake request must contain:\r
-     *  1) The "/meta/handshake" channel identifier.\r
-     *  2) The version of the protocol supported by the client\r
-     *  3) The client's supported connection types.\r
-     *  \r
-     * @return HttpError This method returns null if no errors were found\r
-     */\r
-    public HttpError validate() {\r
-        boolean error = (version==null || version.length()==0);\r
-        if (!error) error = suppConnTypesFlag==0;\r
-        if (error) return new HttpError(400,"Invalid handshake request, supportedConnectionType field missing.",null);\r
-        else return null;\r
-    }\r
-\r
-    /**\r
-     * Generate and return a client identifier.  Return a list of\r
-     * supported connection types.  Must be a subset of or identical to\r
-     * the list of types supported by the client.  See section 4.1.2 of\r
-     * the Bayuex specification.\r
-     */\r
-    public int process(int prevops) throws BayeuxException {\r
-        super.process(prevops);\r
-        response = (HashMap<String, Object>)responseTemplate.clone();\r
-        ClientImpl client = null;\r
-        HttpError error = validate();\r
-        if (error == null) {\r
-            client = (ClientImpl) getTomcatBayeux().newClient("http-", null, false,getEvent());\r
-            clientId = client.getId();\r
-            client.setSupportedConnTypes(suppConnTypesFlag);\r
-            client.setUseJsonFiltered(getExt().get(Bayeux.JSON_COMMENT_FILTERED_FIELD) != null);\r
-            response.put(Bayeux.CLIENT_FIELD, client.getId());\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.RECONNECT_FIELD, Bayeux.RETRY_RESPONSE);\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.INTERVAL_FIELD, getReconnectInterval());\r
-        }else {\r
-            response.put(Bayeux.SUCCESSFUL_FIELD,Boolean.FALSE);\r
-            response.put(Bayeux.ERROR_FIELD, error.toString());\r
-            client = TomcatBayeux.getErrorClient();\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.RECONNECT_FIELD, Bayeux.NONE_RESPONSE);\r
-        }\r
-        try {\r
-            JSONObject obj = new JSONObject(response);\r
-            addToDeliveryQueue(client, obj);\r
-        } catch (ServletException x) {\r
-            throw new BayeuxException(x);\r
-        } catch (IOException x) {\r
-            throw new BayeuxException(x);\r
-        }\r
-        return 0;\r
-    }\r
-}\r
-\r
+/*
+ * 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.request;
+
+import java.io.IOException;
+import java.util.HashMap;
+import javax.servlet.ServletException;
+
+import org.apache.catalina.CometEvent;
+import org.apache.tomcat.bayeux.HttpError;
+import org.apache.tomcat.bayeux.BayeuxException;
+import org.apache.tomcat.bayeux.BayeuxRequest;
+import org.apache.tomcat.bayeux.ClientImpl;
+import org.apache.tomcat.bayeux.TomcatBayeux;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.apache.cometd.bayeux.Bayeux;
+import org.apache.tomcat.bayeux.*;
+
+/******************************************************************************
+ * Handshake request Bayeux message.
+ *
+ * @author Guy A. Molinari
+ * @author Filip Hanik
+ * @version 1.0
+ *
+ */
+public class MetaHandshakeRequest extends RequestBase implements BayeuxRequest {
+
+    protected static HashMap<String,Object> responseTemplate = new HashMap<String,Object>();
+    
+    static {
+        responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_HANDSHAKE);
+        responseTemplate.put(Bayeux.VERSION_FIELD,"1.0");
+        responseTemplate.put(Bayeux.SUPP_CONNECTION_TYPE_FIELD,new String[] { Bayeux.TRANSPORT_LONG_POLL, Bayeux.TRANSPORT_CALLBACK_POLL });
+        responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE);
+        responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap<String, Object>());
+    }
+
+    public MetaHandshakeRequest(TomcatBayeux tomcatBayeux, CometEvent event, JSONObject jsReq) throws JSONException {
+        super(tomcatBayeux, event, jsReq);
+    }
+    
+
+    public String getVersion() { return version; }
+    public String getMinimumVersion() { return minVersion; }
+
+
+    /**
+     * Check client request for validity.
+     *
+     * Per section 4.1.1 of the Bayuex spec a handshake request must contain:
+     *  1) The "/meta/handshake" channel identifier.
+     *  2) The version of the protocol supported by the client
+     *  3) The client's supported connection types.
+     *  
+     * @return HttpError This method returns null if no errors were found
+     */
+    public HttpError validate() {
+        boolean error = (version==null || version.length()==0);
+        if (!error) error = suppConnTypesFlag==0;
+        if (error) return new HttpError(400,"Invalid handshake request, supportedConnectionType field missing.",null);
+        else return null;
+    }
+
+    /**
+     * Generate and return a client identifier.  Return a list of
+     * supported connection types.  Must be a subset of or identical to
+     * the list of types supported by the client.  See section 4.1.2 of
+     * the Bayuex specification.
+     */
+    public int process(int prevops) throws BayeuxException {
+        super.process(prevops);
+        response = (HashMap<String, Object>)responseTemplate.clone();
+        ClientImpl client = null;
+        HttpError error = validate();
+        if (error == null) {
+            client = (ClientImpl) getTomcatBayeux().newClient("http-", null, false,getEvent());
+            clientId = client.getId();
+            client.setSupportedConnTypes(suppConnTypesFlag);
+            client.setUseJsonFiltered(getExt().get(Bayeux.JSON_COMMENT_FILTERED_FIELD) != null);
+            response.put(Bayeux.CLIENT_FIELD, client.getId());
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.RECONNECT_FIELD, Bayeux.RETRY_RESPONSE);
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.INTERVAL_FIELD, getReconnectInterval());
+        }else {
+            response.put(Bayeux.SUCCESSFUL_FIELD,Boolean.FALSE);
+            response.put(Bayeux.ERROR_FIELD, error.toString());
+            client = TomcatBayeux.getErrorClient();
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.RECONNECT_FIELD, Bayeux.NONE_RESPONSE);
+        }
+        try {
+            JSONObject obj = new JSONObject(response);
+            addToDeliveryQueue(client, obj);
+        } catch (ServletException x) {
+            throw new BayeuxException(x);
+        } catch (IOException x) {
+            throw new BayeuxException(x);
+        }
+        return 0;
+    }
+}
+
index 31994f3..b6af0b2 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux.request;\r
-\r
-import java.io.IOException;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.servlet.ServletException;\r
-\r
-import org.apache.catalina.CometEvent;\r
-import org.apache.tomcat.bayeux.HttpError;\r
-import org.apache.tomcat.bayeux.BayeuxException;\r
-import org.apache.tomcat.bayeux.BayeuxRequest;\r
-import org.apache.tomcat.bayeux.ChannelImpl;\r
-import org.apache.tomcat.bayeux.ClientImpl;\r
-import org.apache.tomcat.bayeux.TomcatBayeux;\r
-import org.json.JSONException;\r
-import org.json.JSONObject;\r
-import org.apache.cometd.bayeux.Channel;\r
-import org.apache.cometd.bayeux.Bayeux;\r
-import org.apache.tomcat.bayeux.*;\r
-\r
-/******************************************************************************\r
- * Handshake request Bayeux message.\r
- *\r
- * @author Guy A. Molinari\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class MetaSubscribeRequest extends RequestBase implements BayeuxRequest {\r
-\r
-    protected static HashMap<String,Object> responseTemplate = new HashMap<String,Object>();\r
-\r
-    static {\r
-        responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_SUBSCRIBE);\r
-        responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE);\r
-        responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap<String, Object>());\r
-    }\r
-\r
-    public MetaSubscribeRequest(TomcatBayeux tb, CometEvent event, JSONObject jsReq) throws JSONException {\r
-        super(tb, event, jsReq);\r
-    }\r
-\r
-\r
-    /**\r
-     * Check client request for validity.\r
-     *\r
-     * Per section 4.5.1 of the Bayuex spec a connect request must contain:\r
-     *  1) The "/meta/subscribe" channel identifier.\r
-     *  2) The clientId.\r
-     *  3) The subscription.  This is the name of the channel of interest,\r
-     *     or a pattern.\r
-     *  \r
-     * @return HttpError This method returns null if no errors were found\r
-     */\r
-    public HttpError validate() {\r
-        if(clientId==null|| (!this.getTomcatBayeux().hasClient(clientId)))\r
-            return new HttpError(400,"Client Id not valid.", null);\r
-        if (subscription==null||subscription.length()==0)\r
-            return new HttpError(400,"Subscription missing.",null);\r
-        return null;//no error\r
-    }\r
-\r
-    /**\r
-     * Register interest for one or more channels.  Per section 2.2.1 of the\r
-     * Bayeux spec, a pattern may be specified.  Assign client to matching\r
-     * channels and inverse client to channel reference.\r
-     */\r
-    public int process(int prevops) throws BayeuxException {\r
-        super.process(prevops);\r
-        response = (HashMap<String, Object>)this.responseTemplate.clone();\r
-        ClientImpl client = (ClientImpl)getTomcatBayeux().getClient(clientId);\r
-        HttpError error = validate();\r
-        if (error == null) {\r
-            boolean wildcard = subscription.indexOf('*')!=-1;\r
-            boolean subscribed = false;\r
-            if (wildcard) {\r
-                List<Channel> channels = getTomcatBayeux().getChannels();\r
-                Iterator<Channel> it = channels.iterator();\r
-                while (it.hasNext()) {\r
-                    ChannelImpl ch = (ChannelImpl)it.next();\r
-                    if (ch.matches(subscription)) {\r
-                        ch.subscribe(client);\r
-                        subscribed = true;\r
-                    }\r
-                }\r
-            }else {\r
-                ChannelImpl ch = (ChannelImpl)getTomcatBayeux().getChannel(subscription,true);\r
-                ch.subscribe(client);\r
-                subscribed = true;\r
-            }\r
-            response.put(Bayeux.SUCCESSFUL_FIELD, Boolean.valueOf(subscribed));\r
-            response.put(Bayeux.SUBSCRIPTION_FIELD,subscription);\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("reconnect", "retry");\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("interval", getReconnectInterval());\r
-        }else {\r
-            response.put(Bayeux.SUCCESSFUL_FIELD,Boolean.FALSE);\r
-            response.put(Bayeux.ERROR_FIELD, error.toString());\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("reconnect", "handshake");\r
-            if (client==null) client = TomcatBayeux.getErrorClient();\r
-        }\r
-        response.put(Bayeux.CLIENT_FIELD, client.getId());\r
-        response.put(Bayeux.TIMESTAMP_FIELD,getTimeStamp());\r
-        try {\r
-            JSONObject obj = new JSONObject(response);\r
-            addToDeliveryQueue(client, obj);\r
-        } catch (ServletException x) {\r
-            throw new BayeuxException(x);\r
-        } catch (IOException x) {\r
-            throw new BayeuxException(x);\r
-        }\r
-        return 0;\r
-    }\r
-}\r
-\r
+/*
+ * 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.request;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.servlet.ServletException;
+
+import org.apache.catalina.CometEvent;
+import org.apache.tomcat.bayeux.HttpError;
+import org.apache.tomcat.bayeux.BayeuxException;
+import org.apache.tomcat.bayeux.BayeuxRequest;
+import org.apache.tomcat.bayeux.ChannelImpl;
+import org.apache.tomcat.bayeux.ClientImpl;
+import org.apache.tomcat.bayeux.TomcatBayeux;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.apache.cometd.bayeux.Channel;
+import org.apache.cometd.bayeux.Bayeux;
+import org.apache.tomcat.bayeux.*;
+
+/******************************************************************************
+ * Handshake request Bayeux message.
+ *
+ * @author Guy A. Molinari
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class MetaSubscribeRequest extends RequestBase implements BayeuxRequest {
+
+    protected static HashMap<String,Object> responseTemplate = new HashMap<String,Object>();
+
+    static {
+        responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_SUBSCRIBE);
+        responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE);
+        responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap<String, Object>());
+    }
+
+    public MetaSubscribeRequest(TomcatBayeux tb, CometEvent event, JSONObject jsReq) throws JSONException {
+        super(tb, event, jsReq);
+    }
+
+
+    /**
+     * Check client request for validity.
+     *
+     * Per section 4.5.1 of the Bayuex spec a connect request must contain:
+     *  1) The "/meta/subscribe" channel identifier.
+     *  2) The clientId.
+     *  3) The subscription.  This is the name of the channel of interest,
+     *     or a pattern.
+     *  
+     * @return HttpError This method returns null if no errors were found
+     */
+    public HttpError validate() {
+        if(clientId==null|| (!this.getTomcatBayeux().hasClient(clientId)))
+            return new HttpError(400,"Client Id not valid.", null);
+        if (subscription==null||subscription.length()==0)
+            return new HttpError(400,"Subscription missing.",null);
+        return null;//no error
+    }
+
+    /**
+     * Register interest for one or more channels.  Per section 2.2.1 of the
+     * Bayeux spec, a pattern may be specified.  Assign client to matching
+     * channels and inverse client to channel reference.
+     */
+    public int process(int prevops) throws BayeuxException {
+        super.process(prevops);
+        response = (HashMap<String, Object>)this.responseTemplate.clone();
+        ClientImpl client = (ClientImpl)getTomcatBayeux().getClient(clientId);
+        HttpError error = validate();
+        if (error == null) {
+            boolean wildcard = subscription.indexOf('*')!=-1;
+            boolean subscribed = false;
+            if (wildcard) {
+                List<Channel> channels = getTomcatBayeux().getChannels();
+                Iterator<Channel> it = channels.iterator();
+                while (it.hasNext()) {
+                    ChannelImpl ch = (ChannelImpl)it.next();
+                    if (ch.matches(subscription)) {
+                        ch.subscribe(client);
+                        subscribed = true;
+                    }
+                }
+            }else {
+                ChannelImpl ch = (ChannelImpl)getTomcatBayeux().getChannel(subscription,true);
+                ch.subscribe(client);
+                subscribed = true;
+            }
+            response.put(Bayeux.SUCCESSFUL_FIELD, Boolean.valueOf(subscribed));
+            response.put(Bayeux.SUBSCRIPTION_FIELD,subscription);
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("reconnect", "retry");
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("interval", getReconnectInterval());
+        }else {
+            response.put(Bayeux.SUCCESSFUL_FIELD,Boolean.FALSE);
+            response.put(Bayeux.ERROR_FIELD, error.toString());
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("reconnect", "handshake");
+            if (client==null) client = TomcatBayeux.getErrorClient();
+        }
+        response.put(Bayeux.CLIENT_FIELD, client.getId());
+        response.put(Bayeux.TIMESTAMP_FIELD,getTimeStamp());
+        try {
+            JSONObject obj = new JSONObject(response);
+            addToDeliveryQueue(client, obj);
+        } catch (ServletException x) {
+            throw new BayeuxException(x);
+        } catch (IOException x) {
+            throw new BayeuxException(x);
+        }
+        return 0;
+    }
+}
+
index 69a57cd..e8b3e16 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux.request;\r
-\r
-import java.io.IOException;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.servlet.ServletException;\r
-\r
-import org.apache.catalina.CometEvent;\r
-import org.apache.tomcat.bayeux.HttpError;\r
-import org.apache.tomcat.bayeux.BayeuxException;\r
-import org.apache.tomcat.bayeux.BayeuxRequest;\r
-import org.apache.tomcat.bayeux.ChannelImpl;\r
-import org.apache.tomcat.bayeux.ClientImpl;\r
-import org.apache.tomcat.bayeux.TomcatBayeux;\r
-import org.json.JSONException;\r
-import org.json.JSONObject;\r
-import org.apache.cometd.bayeux.Channel;\r
-import org.apache.cometd.bayeux.Bayeux;\r
-import org.apache.tomcat.bayeux.*;\r
-\r
-/******************************************************************************\r
- * Handshake request Bayeux message.\r
- *\r
- * @author Guy A. Molinari\r
- * @author Filip Hanik\r
- * @version 1.0\r
- *\r
- */\r
-public class MetaUnsubscribeRequest extends RequestBase implements BayeuxRequest {\r
-\r
-    protected static HashMap<String,Object> responseTemplate = new HashMap<String,Object>();\r
-\r
-    static {\r
-        responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_UNSUBSCRIBE);\r
-        responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE);\r
-        responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap<String, Object>());\r
-    }\r
-\r
-    public MetaUnsubscribeRequest(TomcatBayeux tb, CometEvent event, JSONObject jsReq) throws JSONException {\r
-        super(tb, event, jsReq);\r
-    }\r
-\r
-\r
-    /**\r
-     * Check client request for validity.\r
-     *\r
-     * Per section 4.6.1 of the Bayuex spec a connect request must contain:\r
-     *  1) The "/meta/unsubscribe" channel identifier.\r
-     *  2) The clientId.\r
-     *  3) The subscription.  This is the name of the channel of interest,\r
-     *     or a pattern.\r
-     *  \r
-     * @return HttpError This method returns null if no errors were found\r
-     */\r
-    public HttpError validate() {\r
-        if(clientId==null|| (!this.getTomcatBayeux().hasClient(clientId)))\r
-            return new HttpError(400,"Client Id not valid.", null);\r
-        if (subscription==null||subscription.length()==0)\r
-            return new HttpError(400,"Subscription missing.",null);\r
-        return null;//no error\r
-    }\r
-\r
-    /**\r
-     * De-register interest for one or more channels.  Per section 2.2.1 of the\r
-     * Bayeux spec, a pattern may be specified.  Sever relationships.\r
-     */\r
-    public int process(int prevops) throws BayeuxException {\r
-        super.process(prevops);\r
-        response = (HashMap<String, Object>)responseTemplate.clone();\r
-        ClientImpl client = (ClientImpl)getTomcatBayeux().getClient(clientId);\r
-        HttpError error = validate();\r
-        if (error == null) {\r
-            boolean wildcard = subscription.indexOf('*')!=-1;\r
-            boolean unsubscribed = false;\r
-            if (wildcard) {\r
-                List<Channel> channels = getTomcatBayeux().getChannels();\r
-                Iterator<Channel> it = channels.iterator();\r
-                while (it.hasNext()) {\r
-                    ChannelImpl ch = (ChannelImpl)it.next();\r
-                    if (ch.matches(subscription)) {\r
-                        ch.unsubscribe(client);\r
-                        unsubscribed = true;\r
-                    }\r
-                }\r
-            }else {\r
-                ChannelImpl ch = (ChannelImpl)getTomcatBayeux().getChannel(subscription,true);\r
-                ch.unsubscribe(client);\r
-                unsubscribed = true;\r
-            }\r
-            response.put(Bayeux.SUCCESSFUL_FIELD, Boolean.valueOf(unsubscribed));\r
-            response.put(Bayeux.SUBSCRIPTION_FIELD,subscription);\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("reconnect", "retry");\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("interval", getReconnectInterval());\r
-        }else {\r
-            response.put(Bayeux.SUCCESSFUL_FIELD,Boolean.FALSE);\r
-            response.put(Bayeux.ERROR_FIELD, error.toString());\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("reconnect", "handshake");\r
-            if (client==null) client = TomcatBayeux.getErrorClient();\r
-        }\r
-        response.put(Bayeux.CLIENT_FIELD, client.getId());\r
-        response.put(Bayeux.TIMESTAMP_FIELD,getTimeStamp());\r
-        try {\r
-            JSONObject obj = new JSONObject(response);\r
-            addToDeliveryQueue(client, obj);\r
-        } catch (ServletException x) {\r
-            throw new BayeuxException(x);\r
-        } catch (IOException x) {\r
-            throw new BayeuxException(x);\r
-        }\r
-        return 0;\r
-    }\r
-}\r
-\r
+/*
+ * 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.request;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.servlet.ServletException;
+
+import org.apache.catalina.CometEvent;
+import org.apache.tomcat.bayeux.HttpError;
+import org.apache.tomcat.bayeux.BayeuxException;
+import org.apache.tomcat.bayeux.BayeuxRequest;
+import org.apache.tomcat.bayeux.ChannelImpl;
+import org.apache.tomcat.bayeux.ClientImpl;
+import org.apache.tomcat.bayeux.TomcatBayeux;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.apache.cometd.bayeux.Channel;
+import org.apache.cometd.bayeux.Bayeux;
+import org.apache.tomcat.bayeux.*;
+
+/******************************************************************************
+ * Handshake request Bayeux message.
+ *
+ * @author Guy A. Molinari
+ * @author Filip Hanik
+ * @version 1.0
+ *
+ */
+public class MetaUnsubscribeRequest extends RequestBase implements BayeuxRequest {
+
+    protected static HashMap<String,Object> responseTemplate = new HashMap<String,Object>();
+
+    static {
+        responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_UNSUBSCRIBE);
+        responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE);
+        responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap<String, Object>());
+    }
+
+    public MetaUnsubscribeRequest(TomcatBayeux tb, CometEvent event, JSONObject jsReq) throws JSONException {
+        super(tb, event, jsReq);
+    }
+
+
+    /**
+     * Check client request for validity.
+     *
+     * Per section 4.6.1 of the Bayuex spec a connect request must contain:
+     *  1) The "/meta/unsubscribe" channel identifier.
+     *  2) The clientId.
+     *  3) The subscription.  This is the name of the channel of interest,
+     *     or a pattern.
+     *  
+     * @return HttpError This method returns null if no errors were found
+     */
+    public HttpError validate() {
+        if(clientId==null|| (!this.getTomcatBayeux().hasClient(clientId)))
+            return new HttpError(400,"Client Id not valid.", null);
+        if (subscription==null||subscription.length()==0)
+            return new HttpError(400,"Subscription missing.",null);
+        return null;//no error
+    }
+
+    /**
+     * De-register interest for one or more channels.  Per section 2.2.1 of the
+     * Bayeux spec, a pattern may be specified.  Sever relationships.
+     */
+    public int process(int prevops) throws BayeuxException {
+        super.process(prevops);
+        response = (HashMap<String, Object>)responseTemplate.clone();
+        ClientImpl client = (ClientImpl)getTomcatBayeux().getClient(clientId);
+        HttpError error = validate();
+        if (error == null) {
+            boolean wildcard = subscription.indexOf('*')!=-1;
+            boolean unsubscribed = false;
+            if (wildcard) {
+                List<Channel> channels = getTomcatBayeux().getChannels();
+                Iterator<Channel> it = channels.iterator();
+                while (it.hasNext()) {
+                    ChannelImpl ch = (ChannelImpl)it.next();
+                    if (ch.matches(subscription)) {
+                        ch.unsubscribe(client);
+                        unsubscribed = true;
+                    }
+                }
+            }else {
+                ChannelImpl ch = (ChannelImpl)getTomcatBayeux().getChannel(subscription,true);
+                ch.unsubscribe(client);
+                unsubscribed = true;
+            }
+            response.put(Bayeux.SUCCESSFUL_FIELD, Boolean.valueOf(unsubscribed));
+            response.put(Bayeux.SUBSCRIPTION_FIELD,subscription);
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("reconnect", "retry");
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("interval", getReconnectInterval());
+        }else {
+            response.put(Bayeux.SUCCESSFUL_FIELD,Boolean.FALSE);
+            response.put(Bayeux.ERROR_FIELD, error.toString());
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put("reconnect", "handshake");
+            if (client==null) client = TomcatBayeux.getErrorClient();
+        }
+        response.put(Bayeux.CLIENT_FIELD, client.getId());
+        response.put(Bayeux.TIMESTAMP_FIELD,getTimeStamp());
+        try {
+            JSONObject obj = new JSONObject(response);
+            addToDeliveryQueue(client, obj);
+        } catch (ServletException x) {
+            throw new BayeuxException(x);
+        } catch (IOException x) {
+            throw new BayeuxException(x);
+        }
+        return 0;
+    }
+}
+
index fcf956c..017d181 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.bayeux.request;\r
-\r
-import java.io.IOException;\r
-import java.util.HashMap;\r
-import javax.servlet.ServletException;\r
-\r
-import org.apache.catalina.CometEvent;\r
-import org.apache.tomcat.bayeux.HttpError;\r
-import org.apache.tomcat.bayeux.BayeuxException;\r
-import org.apache.tomcat.bayeux.BayeuxRequest;\r
-import org.apache.tomcat.bayeux.ChannelImpl;\r
-import org.apache.tomcat.bayeux.ClientImpl;\r
-import org.apache.tomcat.bayeux.MessageImpl;\r
-import org.apache.tomcat.bayeux.TomcatBayeux;\r
-import org.json.JSONException;\r
-import org.json.JSONObject;\r
-import org.apache.cometd.bayeux.Bayeux;\r
-import java.util.List;\r
-import org.apache.cometd.bayeux.Message;\r
-import java.util.Iterator;\r
-import org.apache.tomcat.bayeux.*;\r
-\r
-/******************************************************************************\r
- * Handshake request Bayeux message.\r
- *\r
- * @author Guy A. Molinari\r
- * @author Filip Hanik\r
- * @version 1.0\r
- *\r
- */\r
-public class PublishRequest extends RequestBase implements BayeuxRequest {\r
-\r
-    JSONObject msgData = null;\r
-\r
-    protected static HashMap<String,Object> responseTemplate = new HashMap<String,Object>();\r
-\r
-    static {\r
-        responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE);\r
-        responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap<String, Object>());\r
-    }\r
-\r
-    public PublishRequest(TomcatBayeux tb, CometEvent event, JSONObject jsReq) throws JSONException {\r
-        super(tb, event, jsReq);\r
-    }\r
-\r
-\r
-    /**\r
-     * Check client request for validity.\r
-     *\r
-     * Per section 5.1.1 of the Bayuex spec a connect request must contain:\r
-     *  1) The channel identifier of the channel for publication.\r
-     *  2) The data to send.\r
-     *  \r
-     * @return HttpError This method returns null if no errors were found\r
-     */\r
-    public HttpError validate() {\r
-        if(channel==null|| (!this.getTomcatBayeux().hasChannel(channel)))\r
-            return new HttpError(400,"Channel Id not valid.", null);\r
-        if(data==null || data.length()==0)\r
-            return new HttpError(400,"Message data missing.", null);\r
-        try {\r
-            this.msgData = new JSONObject(data);\r
-        }catch (JSONException x) {\r
-            return new HttpError(400,"Invalid JSON object in data attribute.",x);\r
-        }\r
-        if(clientId==null|| (!this.getTomcatBayeux().hasClient(clientId)))\r
-            return new HttpError(400,"Client Id not valid.", null);\r
-        return null;//no error\r
-    }\r
-\r
-    /**\r
-     *  Send the event message to all registered subscribers.\r
-     */\r
-    public int process(int prevops) throws BayeuxException {\r
-        super.process(prevops);\r
-        response = (HashMap<String, Object>)responseTemplate.clone();\r
-        ClientImpl client = clientId!=null?(ClientImpl)getTomcatBayeux().getClient(clientId):\r
-                                           (ClientImpl)event.getHttpServletRequest().getAttribute("client");\r
-        boolean success = false;\r
-        HttpError error = validate();\r
-        if (error == null) {\r
-            ChannelImpl chimpl = (ChannelImpl)getTomcatBayeux().getChannel(channel,false);\r
-            MessageImpl mimpl = (MessageImpl)getTomcatBayeux().newMessage(client);\r
-            \r
-            try {\r
-                String[] keys = JSONObject.getNames(msgData);\r
-                for (int i = 0; i < keys.length; i++) {\r
-                    mimpl.put(keys[i], msgData.get(keys[i]));\r
-                }\r
-                success = true;\r
-                ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.RECONNECT_FIELD, Bayeux.RETRY_RESPONSE);\r
-                ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.INTERVAL_FIELD, getReconnectInterval());\r
-            }catch (JSONException x) {\r
-                if (log.isErrorEnabled()) log.error("Unable to parse:"+msgData,x);\r
-                throw new BayeuxException(x);\r
-            }\r
-            chimpl.publish(mimpl);\r
-        }\r
-        if(!success) {\r
-            response.put(Bayeux.SUCCESSFUL_FIELD,Boolean.FALSE);\r
-            response.put(Bayeux.ERROR_FIELD, error.toString());\r
-            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.RECONNECT_FIELD, Bayeux.HANDSHAKE_RESPONSE);\r
-            if (client==null) client = TomcatBayeux.getErrorClient();\r
-        }\r
-        response.put(Bayeux.CHANNEL_FIELD,channel);\r
-        response.put(Bayeux.CLIENT_FIELD, client.getId());\r
-        try {\r
-            JSONObject obj = new JSONObject(response);\r
-            addToDeliveryQueue(client, obj);\r
-        } catch (ServletException x) {\r
-            throw new BayeuxException(x);\r
-        } catch (IOException x) {\r
-            throw new BayeuxException(x);\r
-        }\r
-        \r
-        if (success && client!=null && client.hasMessages()) {\r
-            //send out messages \r
-            flushMessages(client);\r
-        }\r
-\r
-        return 0;\r
-    }\r
-}\r
-\r
+/*
+ * 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.request;
+
+import java.io.IOException;
+import java.util.HashMap;
+import javax.servlet.ServletException;
+
+import org.apache.catalina.CometEvent;
+import org.apache.tomcat.bayeux.HttpError;
+import org.apache.tomcat.bayeux.BayeuxException;
+import org.apache.tomcat.bayeux.BayeuxRequest;
+import org.apache.tomcat.bayeux.ChannelImpl;
+import org.apache.tomcat.bayeux.ClientImpl;
+import org.apache.tomcat.bayeux.MessageImpl;
+import org.apache.tomcat.bayeux.TomcatBayeux;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.apache.cometd.bayeux.Bayeux;
+import java.util.List;
+import org.apache.cometd.bayeux.Message;
+import java.util.Iterator;
+import org.apache.tomcat.bayeux.*;
+
+/******************************************************************************
+ * Handshake request Bayeux message.
+ *
+ * @author Guy A. Molinari
+ * @author Filip Hanik
+ * @version 1.0
+ *
+ */
+public class PublishRequest extends RequestBase implements BayeuxRequest {
+
+    JSONObject msgData = null;
+
+    protected static HashMap<String,Object> responseTemplate = new HashMap<String,Object>();
+
+    static {
+        responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE);
+        responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap<String, Object>());
+    }
+
+    public PublishRequest(TomcatBayeux tb, CometEvent event, JSONObject jsReq) throws JSONException {
+        super(tb, event, jsReq);
+    }
+
+
+    /**
+     * Check client request for validity.
+     *
+     * Per section 5.1.1 of the Bayuex spec a connect request must contain:
+     *  1) The channel identifier of the channel for publication.
+     *  2) The data to send.
+     *  
+     * @return HttpError This method returns null if no errors were found
+     */
+    public HttpError validate() {
+        if(channel==null|| (!this.getTomcatBayeux().hasChannel(channel)))
+            return new HttpError(400,"Channel Id not valid.", null);
+        if(data==null || data.length()==0)
+            return new HttpError(400,"Message data missing.", null);
+        try {
+            this.msgData = new JSONObject(data);
+        }catch (JSONException x) {
+            return new HttpError(400,"Invalid JSON object in data attribute.",x);
+        }
+        if(clientId==null|| (!this.getTomcatBayeux().hasClient(clientId)))
+            return new HttpError(400,"Client Id not valid.", null);
+        return null;//no error
+    }
+
+    /**
+     *  Send the event message to all registered subscribers.
+     */
+    public int process(int prevops) throws BayeuxException {
+        super.process(prevops);
+        response = (HashMap<String, Object>)responseTemplate.clone();
+        ClientImpl client = clientId!=null?(ClientImpl)getTomcatBayeux().getClient(clientId):
+                                           (ClientImpl)event.getHttpServletRequest().getAttribute("client");
+        boolean success = false;
+        HttpError error = validate();
+        if (error == null) {
+            ChannelImpl chimpl = (ChannelImpl)getTomcatBayeux().getChannel(channel,false);
+            MessageImpl mimpl = (MessageImpl)getTomcatBayeux().newMessage(client);
+            
+            try {
+                String[] keys = JSONObject.getNames(msgData);
+                for (int i = 0; i < keys.length; i++) {
+                    mimpl.put(keys[i], msgData.get(keys[i]));
+                }
+                success = true;
+                ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.RECONNECT_FIELD, Bayeux.RETRY_RESPONSE);
+                ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.INTERVAL_FIELD, getReconnectInterval());
+            }catch (JSONException x) {
+                if (log.isErrorEnabled()) log.error("Unable to parse:"+msgData,x);
+                throw new BayeuxException(x);
+            }
+            chimpl.publish(mimpl);
+        }
+        if(!success) {
+            response.put(Bayeux.SUCCESSFUL_FIELD,Boolean.FALSE);
+            response.put(Bayeux.ERROR_FIELD, error.toString());
+            ((HashMap) response.get(Bayeux.ADVICE_FIELD)).put(Bayeux.RECONNECT_FIELD, Bayeux.HANDSHAKE_RESPONSE);
+            if (client==null) client = TomcatBayeux.getErrorClient();
+        }
+        response.put(Bayeux.CHANNEL_FIELD,channel);
+        response.put(Bayeux.CLIENT_FIELD, client.getId());
+        try {
+            JSONObject obj = new JSONObject(response);
+            addToDeliveryQueue(client, obj);
+        } catch (ServletException x) {
+            throw new BayeuxException(x);
+        } catch (IOException x) {
+            throw new BayeuxException(x);
+        }
+        
+        if (success && client!=null && client.hasMessages()) {
+            //send out messages 
+            flushMessages(client);
+        }
+
+        return 0;
+    }
+}
+
index 5f61d29..f99c38e 100644 (file)
-package org.apache.cometd.bayeux.samples;\r
-\r
-import javax.servlet.ServletContextEvent;\r
-import javax.servlet.ServletContextListener;\r
-import javax.servlet.ServletContextAttributeListener;\r
-import javax.servlet.ServletContextAttributeEvent;\r
-import org.apache.cometd.bayeux.Bayeux;\r
-\r
-import java.text.DecimalFormat;\r
-import java.util.List;\r
-import java.util.Random;\r
-import java.util.concurrent.atomic.AtomicInteger;\r
-import org.apache.cometd.bayeux.Client;\r
-import org.apache.cometd.bayeux.Listener;\r
-import org.apache.cometd.bayeux.Message;\r
-import org.apache.cometd.bayeux.Channel;\r
-\r
-public class BayeuxStockTicker implements ServletContextListener,\r
-        ServletContextAttributeListener, Listener {\r
-\r
-    static AtomicInteger counter = new AtomicInteger(0);\r
-    protected int id;\r
-    protected Bayeux b;\r
-    protected Client c;\r
-    protected boolean alive = true;\r
-    protected boolean initialized = false;\r
-    protected TickerThread tt = new TickerThread();\r
-\r
-    public BayeuxStockTicker() {\r
-        id = counter.incrementAndGet();\r
-        System.out.println("new listener created with id:" + id);\r
-    }\r
-\r
-    public void contextDestroyed(ServletContextEvent servletContextEvent) {\r
-        alive = false;\r
-        tt.run = false;\r
-        tt.interrupt();\r
-    }\r
-\r
-    public void contextInitialized(ServletContextEvent servletContextEvent) {\r
-    }\r
-\r
-    public void attributeAdded(ServletContextAttributeEvent scae) {\r
-        if (scae.getName().equals(Bayeux.DOJOX_COMETD_BAYEUX)) {\r
-            if (initialized) return;\r
-            initialized = true;\r
-            System.out.println("Starting stock ticker server client!");\r
-            b = (Bayeux) scae.getValue();\r
-            c = b.newClient("stock-ticker-", this);\r
-            tt.start();\r
-        }\r
-    }\r
-\r
-    public void attributeRemoved(ServletContextAttributeEvent scae) {\r
-        if (scae.getName().equals(Bayeux.DOJOX_COMETD_BAYEUX)) {\r
-            initialized = false;\r
-            b = (Bayeux) scae.getValue();\r
-            List<Channel> chs = b.getChannels();\r
-            for (Channel ch : chs) {\r
-                ch.unsubscribe(c);\r
-            }\r
-        }\r
-    }\r
-\r
-    public void attributeReplaced(\r
-            ServletContextAttributeEvent servletContextAttributeEvent) {\r
-    }\r
-\r
-    public void removed(boolean timeout) {\r
-        System.out.println("Client removed.");\r
-    }\r
-\r
-    public void deliver(Message[] msgs) {\r
-        for (int i = 0; msgs != null && i < msgs.length; i++) {\r
-            Message msg = msgs[i];\r
-            System.out.println("[stock ticker server client ]received message:" + msg);\r
-        }\r
-    }\r
-\r
-    public class TickerThread extends Thread {\r
-        public boolean run = true;\r
-\r
-        public TickerThread() {\r
-            setName("Ticker Thread");\r
-        }\r
-\r
-        public void run() {\r
-            try {\r
-                \r
-                Stock[] stocks = new Stock[] { \r
-                        new Stock("GOOG", 435.43),\r
-                        new Stock("YHOO", 27.88), \r
-                        new Stock("SPRG", 1015.55), };\r
-                for (Stock s : stocks) {\r
-                    Channel ch = b.getChannel("/stock/"+s.getSymbol(), true);\r
-                    ch.subscribe(c);\r
-                    \r
-                }\r
-                Random r = new Random(System.currentTimeMillis());\r
-                while (run) {\r
-                    for (int j = 0; j < 1; j++) {\r
-                        int i = r.nextInt() % 3;\r
-                        if (i < 0)\r
-                            i = i * (-1);\r
-                        Stock stock = stocks[i];\r
-                        double change = r.nextDouble();\r
-                        boolean plus = r.nextBoolean();\r
-                        if (plus) {\r
-                            stock.setValue(stock.getValue() + change);\r
-                        } else {\r
-                            stock.setValue(stock.getValue() - change);\r
-                        }\r
-                        Channel ch = b.getChannel("/stock/"+stock.getSymbol(), true);\r
-                        Message m = b.newMessage(c);\r
-                        m.put("stock", stock.toString());\r
-                        m.put("symbol", stock.getSymbol());\r
-                        m.put("price", stock.getValueAsString());\r
-                        m.put("change", stock.getLastChangeAsString());\r
-                        ch.publish(m);\r
-                        System.out.println("Stock: "+stock.getSymbol()+" Price: "+stock.getValueAsString()+" Change: "+stock.getLastChangeAsString());\r
-                    }\r
-                    Thread.sleep(850);\r
-                }\r
-            } catch (InterruptedException ix) {\r
-\r
-            } catch (Exception x) {\r
-                x.printStackTrace();\r
-            }\r
-        }\r
-    }\r
-\r
-    public static class Stock {\r
-        protected static DecimalFormat df = new DecimalFormat("0.00");\r
-        protected String symbol = "";\r
-        protected double value = 0.0d;\r
-        protected double lastchange = 0.0d;\r
-        protected int cnt = 0;\r
-\r
-        public Stock(String symbol, double initvalue) {\r
-            this.symbol = symbol;\r
-            this.value = initvalue;\r
-        }\r
-\r
-        public void setCnt(int c) {\r
-            this.cnt = c;\r
-        }\r
-\r
-        public int getCnt() {\r
-            return cnt;\r
-        }\r
-\r
-        public String getSymbol() {\r
-            return symbol;\r
-        }\r
-\r
-        public double getValue() {\r
-            return value;\r
-        }\r
-\r
-        public void setValue(double value) {\r
-            double old = this.value;\r
-            this.value = value;\r
-            this.lastchange = value - old;\r
-        }\r
-\r
-        public String getValueAsString() {\r
-            return df.format(value);\r
-        }\r
-\r
-        public double getLastChange() {\r
-            return this.lastchange;\r
-        }\r
-\r
-        public void setLastChange(double lastchange) {\r
-            this.lastchange = lastchange;\r
-        }\r
-\r
-        public String getLastChangeAsString() {\r
-            return df.format(lastchange);\r
-        }\r
-\r
-        public int hashCode() {\r
-            return symbol.hashCode();\r
-        }\r
-\r
-        public boolean equals(Object other) {\r
-            if (other instanceof Stock) {\r
-                return this.symbol.equals(((Stock) other).symbol);\r
-            } else {\r
-                return false;\r
-            }\r
-        }\r
-        \r
-        public String toString(){\r
-            StringBuffer buf = new StringBuffer("STOCK#");\r
-            buf.append(getSymbol());\r
-            buf.append("#");\r
-            buf.append(getValueAsString());\r
-            buf.append("#");\r
-            buf.append(getLastChangeAsString());\r
-            buf.append("#");\r
-            buf.append(String.valueOf(getCnt()));\r
-            return buf.toString();\r
-         \r
-        }\r
-\r
-        public Object clone() {\r
-            Stock s = new Stock(this.getSymbol(), this.getValue());\r
-            s.setLastChange(this.getLastChange());\r
-            s.setCnt(this.cnt);\r
-            return s;\r
-        }\r
-    }\r
-\r
+package org.apache.cometd.bayeux.samples;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletContextAttributeListener;
+import javax.servlet.ServletContextAttributeEvent;
+import org.apache.cometd.bayeux.Bayeux;
+
+import java.text.DecimalFormat;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.cometd.bayeux.Client;
+import org.apache.cometd.bayeux.Listener;
+import org.apache.cometd.bayeux.Message;
+import org.apache.cometd.bayeux.Channel;
+
+public class BayeuxStockTicker implements ServletContextListener,
+        ServletContextAttributeListener, Listener {
+
+    static AtomicInteger counter = new AtomicInteger(0);
+    protected int id;
+    protected Bayeux b;
+    protected Client c;
+    protected boolean alive = true;
+    protected boolean initialized = false;
+    protected TickerThread tt = new TickerThread();
+
+    public BayeuxStockTicker() {
+        id = counter.incrementAndGet();
+        System.out.println("new listener created with id:" + id);
+    }
+
+    public void contextDestroyed(ServletContextEvent servletContextEvent) {
+        alive = false;
+        tt.run = false;
+        tt.interrupt();
+    }
+
+    public void contextInitialized(ServletContextEvent servletContextEvent) {
+    }
+
+    public void attributeAdded(ServletContextAttributeEvent scae) {
+        if (scae.getName().equals(Bayeux.DOJOX_COMETD_BAYEUX)) {
+            if (initialized) return;
+            initialized = true;
+            System.out.println("Starting stock ticker server client!");
+            b = (Bayeux) scae.getValue();
+            c = b.newClient("stock-ticker-", this);
+            tt.start();
+        }
+    }
+
+    public void attributeRemoved(ServletContextAttributeEvent scae) {
+        if (scae.getName().equals(Bayeux.DOJOX_COMETD_BAYEUX)) {
+            initialized = false;
+            b = (Bayeux) scae.getValue();
+            List<Channel> chs = b.getChannels();
+            for (Channel ch : chs) {
+                ch.unsubscribe(c);
+            }
+        }
+    }
+
+    public void attributeReplaced(
+            ServletContextAttributeEvent servletContextAttributeEvent) {
+    }
+
+    public void removed(boolean timeout) {
+        System.out.println("Client removed.");
+    }
+
+    public void deliver(Message[] msgs) {
+        for (int i = 0; msgs != null && i < msgs.length; i++) {
+            Message msg = msgs[i];
+            System.out.println("[stock ticker server client ]received message:" + msg);
+        }
+    }
+
+    public class TickerThread extends Thread {
+        public boolean run = true;
+
+        public TickerThread() {
+            setName("Ticker Thread");
+        }
+
+        public void run() {
+            try {
+                
+                Stock[] stocks = new Stock[] { 
+                        new Stock("GOOG", 435.43),
+                        new Stock("YHOO", 27.88), 
+                        new Stock("SPRG", 1015.55), };
+                for (Stock s : stocks) {
+                    Channel ch = b.getChannel("/stock/"+s.getSymbol(), true);
+                    ch.subscribe(c);
+                    
+                }
+                Random r = new Random(System.currentTimeMillis());
+                while (run) {
+                    for (int j = 0; j < 1; j++) {
+                        int i = r.nextInt() % 3;
+                        if (i < 0)
+                            i = i * (-1);
+                        Stock stock = stocks[i];
+                        double change = r.nextDouble();
+                        boolean plus = r.nextBoolean();
+                        if (plus) {
+                            stock.setValue(stock.getValue() + change);
+                        } else {
+                            stock.setValue(stock.getValue() - change);
+                        }
+                        Channel ch = b.getChannel("/stock/"+stock.getSymbol(), true);
+                        Message m = b.newMessage(c);
+                        m.put("stock", stock.toString());
+                        m.put("symbol", stock.getSymbol());
+                        m.put("price", stock.getValueAsString());
+                        m.put("change", stock.getLastChangeAsString());
+                        ch.publish(m);
+                        System.out.println("Stock: "+stock.getSymbol()+" Price: "+stock.getValueAsString()+" Change: "+stock.getLastChangeAsString());
+                    }
+                    Thread.sleep(850);
+                }
+            } catch (InterruptedException ix) {
+
+            } catch (Exception x) {
+                x.printStackTrace();
+            }
+        }
+    }
+
+    public static class Stock {
+        protected static DecimalFormat df = new DecimalFormat("0.00");
+        protected String symbol = "";
+        protected double value = 0.0d;
+        protected double lastchange = 0.0d;
+        protected int cnt = 0;
+
+        public Stock(String symbol, double initvalue) {
+            this.symbol = symbol;
+            this.value = initvalue;
+        }
+
+        public void setCnt(int c) {
+            this.cnt = c;
+        }
+
+        public int getCnt() {
+            return cnt;
+        }
+
+        public String getSymbol() {
+            return symbol;
+        }
+
+        public double getValue() {
+            return value;
+        }
+
+        public void setValue(double value) {
+            double old = this.value;
+            this.value = value;
+            this.lastchange = value - old;
+        }
+
+        public String getValueAsString() {
+            return df.format(value);
+        }
+
+        public double getLastChange() {
+            return this.lastchange;
+        }
+
+        public void setLastChange(double lastchange) {
+            this.lastchange = lastchange;
+        }
+
+        public String getLastChangeAsString() {
+            return df.format(lastchange);
+        }
+
+        public int hashCode() {
+            return symbol.hashCode();
+        }
+
+        public boolean equals(Object other) {
+            if (other instanceof Stock) {
+                return this.symbol.equals(((Stock) other).symbol);
+            } else {
+                return false;
+            }
+        }
+        
+        public String toString(){
+            StringBuffer buf = new StringBuffer("STOCK#");
+            buf.append(getSymbol());
+            buf.append("#");
+            buf.append(getValueAsString());
+            buf.append("#");
+            buf.append(getLastChangeAsString());
+            buf.append("#");
+            buf.append(String.valueOf(getCnt()));
+            return buf.toString();
+         
+        }
+
+        public Object clone() {
+            Stock s = new Stock(this.getSymbol(), this.getValue());
+            s.setLastChange(this.getLastChange());
+            s.setCnt(this.cnt);
+            return s;
+        }
+    }
+
 }
\ No newline at end of file
index 6f6ca8e..5fd4870 100644 (file)
-package org.apache.cometd.bayeux.samples;\r
-\r
-import javax.servlet.ServletContextEvent;\r
-import javax.servlet.ServletContextListener;\r
-import javax.servlet.ServletContextAttributeListener;\r
-import javax.servlet.ServletContextAttributeEvent;\r
-import org.apache.cometd.bayeux.Bayeux;\r
-import java.util.concurrent.atomic.AtomicInteger;\r
-import org.apache.cometd.bayeux.Client;\r
-import org.apache.cometd.bayeux.Listener;\r
-import org.apache.cometd.bayeux.Message;\r
-import org.apache.cometd.bayeux.Channel;\r
-\r
-public class EchoChatClient implements ServletContextListener, ServletContextAttributeListener, Listener {\r
-    \r
-    static AtomicInteger counter = new AtomicInteger(0);\r
-    protected int id;\r
-    protected Bayeux b;\r
-    protected Client c;\r
-    protected boolean alive = true;\r
-    protected TimestampThread tt = new TimestampThread();\r
-\r
-    public EchoChatClient() {\r
-        id = counter.incrementAndGet();\r
-        System.out.println("new listener created with id:"+id);\r
-    }\r
-\r
-    public void contextDestroyed(ServletContextEvent servletContextEvent) {\r
-        alive = false;\r
-        tt.interrupt();\r
-    }\r
-\r
-    public void contextInitialized(ServletContextEvent servletContextEvent) {\r
-    }\r
-\r
-    public void attributeAdded(ServletContextAttributeEvent scae) {\r
-        if (scae.getName().equals(Bayeux.DOJOX_COMETD_BAYEUX)) {\r
-            System.out.println("Starting echo chat client!");\r
-            b = (Bayeux)scae.getValue();\r
-            c = b.newClient("echochat-",this);\r
-            Channel ch = b.getChannel("/chat/demo",true);\r
-            ch.subscribe(c);\r
-            tt.start();\r
-        }\r
-    }\r
-\r
-    public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {\r
-    }\r
-\r
-    public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {\r
-    }\r
-\r
-    public void removed(boolean timeout) {\r
-        System.out.println("Client removed.");\r
-    }\r
-\r
-    public void deliver(Message[] msgs) {\r
-        for (int i=0; msgs!=null && i<msgs.length; i++) {\r
-            Message msg = msgs[i];\r
-            System.out.println("[echochatclient ]received message:" + msg);\r
-            Message m = b.newMessage(c);\r
-            m.putAll(msg);\r
-            //echo the same message\r
-            m.put("user", "echochatserver");\r
-            if (m.containsKey("msg")) {\r
-                //simple chat demo\r
-                String chat = (String) m.get("msg");\r
-                m.put("msg", "echochatserver|I received your message-" + chat.substring(chat.indexOf("|") + 1));\r
-            }\r
-            System.out.println("[echochatclient ]sending message:" + m);\r
-            msg.getChannel().publish(m);\r
-        }\r
-    }\r
-\r
-    public class TimestampThread extends Thread {\r
-        public TimestampThread() {\r
-            setDaemon(true);\r
-        }\r
-        \r
-        public void run() {\r
-            while (alive) {\r
-                try {\r
-                    sleep(5000);\r
-                    Channel ch = b.getChannel("/chat/demo",false);\r
-                    if (ch.getSubscribers().size()<=1) {\r
-                        continue;\r
-                    }\r
-                    Message m = b.newMessage(c);\r
-                    m.put("user","echochatserver");\r
-                    m.put("chat","Time is:"+new java.sql.Date(System.currentTimeMillis()).toLocaleString());\r
-                    m.put("join",false);\r
-                    ch.publish(m);\r
-                }catch (InterruptedException ignore) {\r
-                    Thread.currentThread().interrupted();\r
-                }catch (Exception x) {\r
-                    x.printStackTrace();\r
-                }\r
-            }\r
-        }\r
-    }\r
-}\r
+package org.apache.cometd.bayeux.samples;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletContextAttributeListener;
+import javax.servlet.ServletContextAttributeEvent;
+import org.apache.cometd.bayeux.Bayeux;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.cometd.bayeux.Client;
+import org.apache.cometd.bayeux.Listener;
+import org.apache.cometd.bayeux.Message;
+import org.apache.cometd.bayeux.Channel;
+
+public class EchoChatClient implements ServletContextListener, ServletContextAttributeListener, Listener {
+    
+    static AtomicInteger counter = new AtomicInteger(0);
+    protected int id;
+    protected Bayeux b;
+    protected Client c;
+    protected boolean alive = true;
+    protected TimestampThread tt = new TimestampThread();
+
+    public EchoChatClient() {
+        id = counter.incrementAndGet();
+        System.out.println("new listener created with id:"+id);
+    }
+
+    public void contextDestroyed(ServletContextEvent servletContextEvent) {
+        alive = false;
+        tt.interrupt();
+    }
+
+    public void contextInitialized(ServletContextEvent servletContextEvent) {
+    }
+
+    public void attributeAdded(ServletContextAttributeEvent scae) {
+        if (scae.getName().equals(Bayeux.DOJOX_COMETD_BAYEUX)) {
+            System.out.println("Starting echo chat client!");
+            b = (Bayeux)scae.getValue();
+            c = b.newClient("echochat-",this);
+            Channel ch = b.getChannel("/chat/demo",true);
+            ch.subscribe(c);
+            tt.start();
+        }
+    }
+
+    public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
+    }
+
+    public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
+    }
+
+    public void removed(boolean timeout) {
+        System.out.println("Client removed.");
+    }
+
+    public void deliver(Message[] msgs) {
+        for (int i=0; msgs!=null && i<msgs.length; i++) {
+            Message msg = msgs[i];
+            System.out.println("[echochatclient ]received message:" + msg);
+            Message m = b.newMessage(c);
+            m.putAll(msg);
+            //echo the same message
+            m.put("user", "echochatserver");
+            if (m.containsKey("msg")) {
+                //simple chat demo
+                String chat = (String) m.get("msg");
+                m.put("msg", "echochatserver|I received your message-" + chat.substring(chat.indexOf("|") + 1));
+            }
+            System.out.println("[echochatclient ]sending message:" + m);
+            msg.getChannel().publish(m);
+        }
+    }
+
+    public class TimestampThread extends Thread {
+        public TimestampThread() {
+            setDaemon(true);
+        }
+        
+        public void run() {
+            while (alive) {
+                try {
+                    sleep(5000);
+                    Channel ch = b.getChannel("/chat/demo",false);
+                    if (ch.getSubscribers().size()<=1) {
+                        continue;
+                    }
+                    Message m = b.newMessage(c);
+                    m.put("user","echochatserver");
+                    m.put("chat","Time is:"+new java.sql.Date(System.currentTimeMillis()).toLocaleString());
+                    m.put("join",false);
+                    ch.publish(m);
+                }catch (InterruptedException ignore) {
+                    Thread.currentThread().interrupted();
+                }catch (Exception x) {
+                    x.printStackTrace();
+                }
+            }
+        }
+    }
+}
index e8d2f80..7781d56 100644 (file)
@@ -1,37 +1,37 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>\r
-<web-app \r
-   xmlns="http://java.sun.com/xml/ns/javaee" \r
-   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
-   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"\r
-   version="2.5"> \r
-  <display-name>Cometd Test WebApp</display-name>\r
-  \r
-  <servlet>\r
-    <servlet-name>cometd</servlet-name>\r
-    <servlet-class>org.apache.tomcat.bayeux.BayeuxServlet</servlet-class>\r
-    <init-param>\r
-      <param-name>timeout</param-name>\r
-      <param-value>120000000</param-value>\r
-    </init-param>\r
-    <init-param>\r
-      <param-name>reconnectInterval</param-name>\r
-      <param-value>250</param-value>\r
-    </init-param>\r
-    <load-on-startup>1</load-on-startup>\r
-  </servlet>\r
-\r
-  <servlet-mapping>\r
-    <servlet-name>cometd</servlet-name>\r
-    <url-pattern>/cometd/*</url-pattern>\r
-  </servlet-mapping>\r
-  \r
-  <listener>\r
-    <listener-class>org.apache.cometd.bayeux.samples.EchoChatClient</listener-class>\r
-  </listener>\r
-  <listener>\r
-    <listener-class>org.apache.cometd.bayeux.samples.BayeuxStockTicker</listener-class>\r
-  </listener>\r
-  \r
-</web-app>\r
-\r
-\r
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app 
+   xmlns="http://java.sun.com/xml/ns/javaee" 
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+   version="2.5"> 
+  <display-name>Cometd Test WebApp</display-name>
+  
+  <servlet>
+    <servlet-name>cometd</servlet-name>
+    <servlet-class>org.apache.tomcat.bayeux.BayeuxServlet</servlet-class>
+    <init-param>
+      <param-name>timeout</param-name>
+      <param-value>120000000</param-value>
+    </init-param>
+    <init-param>
+      <param-name>reconnectInterval</param-name>
+      <param-value>250</param-value>
+    </init-param>
+    <load-on-startup>1</load-on-startup>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>cometd</servlet-name>
+    <url-pattern>/cometd/*</url-pattern>
+  </servlet-mapping>
+  
+  <listener>
+    <listener-class>org.apache.cometd.bayeux.samples.EchoChatClient</listener-class>
+  </listener>
+  <listener>
+    <listener-class>org.apache.cometd.bayeux.samples.BayeuxStockTicker</listener-class>
+  </listener>
+  
+</web-app>
+
+
index 3a88447..64ce47a 100644 (file)
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">\r
-<html>\r
-<head>\r
-<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1" >\r
-<title>Bayeux Stock Ticker</title>\r
-<script type="text/javascript" src="../../dojo/dojo.js.uncompressed.js"></script>\r
-<script type="text/javascript" src="../../dojox/cometd.js"></script>\r
-<script type="text/javascript" src="../../dojox/cometd/_base.js"></script>\r
-<script type="text/javascript">\r
-\r
-dojo.require("dojox.cometd");\r
-\r
-dojo.addOnUnload(function() {\r
-         dojox.cometd.init("/cometd/cometd");\r
-         dojox.cometd.startBatch();\r
-         dojox.cometd.unsubscribe("/stock/GOOG", this,"");\r
-         dojox.cometd.unsubscribe("/stock/YHOO", this,"");\r
-         dojox.cometd.unsubscribe("/stock/SPRG", this,"");\r
-         dojox.cometd.endBatch();\r
-       });\r
-\r
-\r
-dojo.addOnLoad(function() {\r
-  dojox.cometd.init("/cometd/cometd");\r
-  dojox.cometd.startBatch();\r
-  dojox.cometd.subscribe("/stock/GOOG", onMsgEvent);\r
-  dojox.cometd.subscribe("/stock/YHOO", onMsgEvent);\r
-  dojox.cometd.subscribe("/stock/SPRG", onMsgEvent);\r
-  dojox.cometd.endBatch();\r
-});\r
-\r
-\r
-function subscribe(box, symbol) {\r
-       if (box.checked) {\r
-               dojox.cometd.subscribe("/stock/"+symbol, onMsgEvent);\r
-               var rowCurrent = dojo.byId("row."+symbol);\r
-               rowCurrent.bgColor="white";\r
-       } else {\r
-               dojox.cometd.unsubscribe("/stock/"+symbol, onMsgEvent);\r
-               var rowCurrent = dojo.byId("row."+symbol);\r
-               rowCurrent.bgColor="gray";\r
-       }\r
-}\r
-\r
-function removeChildrenFromNode(node)\r
-{\r
-   if(node == undefined || node == null)\r
-   {\r
-      return;\r
-   }\r
-\r
-   var len = node.childNodes.length;\r
-\r
-       while (node.hasChildNodes())\r
-       {\r
-         node.removeChild(node.firstChild);\r
-       }\r
-}\r
-\r
-function onMsgEvent(event) {\r
-   // Break apart the text string into screen name and message parts.\r
-   var symbol = event.data.symbol;\r
-   var price = event.data.price;\r
-   var pricechange = event.data.change;\r
-   //alert("symbol: "+symbol+" price: "+price+" change: "+pricechange);\r
-\r
-   var pricenode = dojo.byId("price."+symbol);\r
-   var changenode = dojo.byId("change."+symbol);\r
-   removeChildrenFromNode(pricenode);\r
-   removeChildrenFromNode(changenode);\r
-   var pricelabel = document.createTextNode(price);\r
-   pricelabel.value = price;\r
-   var changelabel = document.createTextNode(pricechange);\r
-   changelabel.value = pricechange;\r
-   pricenode.appendChild(pricelabel);\r
-   changenode.appendChild(changelabel);\r
-\r
-   var table = dojo.byId("stocktable");  \r
-   var rows = table.getElementsByTagName("tr");  \r
-   for(i = 0; i < rows.length; i++){\r
-          if (rows[i].bgColor != "gray") {\r
-              rows[i].bgColor = "white"; \r
-          }\r
-   }          \r
-   //manipulate rows \r
-   var rowCurrent = dojo.byId("row."+symbol);\r
-   if (pricechange<=0) {\r
-       rowCurrent.bgColor = "red";\r
-   } else {\r
-          rowCurrent.bgColor = "cyan";\r
-   }\r
-}\r
-\r
-\r
-</script>\r
-</head>\r
-<body bgcolor="#ffffff">\r
-<h1 align="center">Bayeux Stock Ticker</h1>\r
-<h2 align="left"> &nbsp;</h2>\r
-<p>\r
-<table id="stocktable" cellspacing="0" cellpadding="3" width="100%" align="center" border="0">\r
-  <tr id="row.HEADER">\r
-    <td>SYMBOL</td>\r
-    <td>PRICE</td>\r
-    <td>LAST CHANGE</td>\r
-    <td>SUBSCRIBE</td></tr>\r
-  <tr id="row.SPRG">\r
-    <td>SPRG</td>\r
-    <td id="price.SPRG"></td>\r
-    <td id="change.SPRG"></td>\r
-    <td id="check.SPRG"><input type="checkbox" id="check.SPRG" checked onClick="subscribe(this,'SPRG')"></td>\r
-  </tr>\r
-  <tr id="row.GOOG">\r
-    <td>GOOG</td>\r
-    <td id="price.GOOG"></td>\r
-    <td id="change.GOOG"></td>\r
-    <td id="check.GOOG"><input type="checkbox" id="check.GOOG" checked  onClick="subscribe(this,'GOOG')"></td>\r
-  </tr>\r
-  <tr id="row.YHOO">\r
-    <td>YHOO</td>\r
-    <td id="price.YHOO"></td>\r
-    <td id="change.YHOO"></td>\r
-    <td id="check.YHOO"><input type="checkbox" id="check.GOOG" checked  onClick="subscribe(this,'YHOO')"></td>\r
-  </tr>\r
-</table>\r
-</p>\r
-</body>\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1" >
+<title>Bayeux Stock Ticker</title>
+<script type="text/javascript" src="../../dojo/dojo.js.uncompressed.js"></script>
+<script type="text/javascript" src="../../dojox/cometd.js"></script>
+<script type="text/javascript" src="../../dojox/cometd/_base.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.cometd");
+
+dojo.addOnUnload(function() {
+         dojox.cometd.init("/cometd/cometd");
+         dojox.cometd.startBatch();
+         dojox.cometd.unsubscribe("/stock/GOOG", this,"");
+         dojox.cometd.unsubscribe("/stock/YHOO", this,"");
+         dojox.cometd.unsubscribe("/stock/SPRG", this,"");
+         dojox.cometd.endBatch();
+       });
+
+
+dojo.addOnLoad(function() {
+  dojox.cometd.init("/cometd/cometd");
+  dojox.cometd.startBatch();
+  dojox.cometd.subscribe("/stock/GOOG", onMsgEvent);
+  dojox.cometd.subscribe("/stock/YHOO", onMsgEvent);
+  dojox.cometd.subscribe("/stock/SPRG", onMsgEvent);
+  dojox.cometd.endBatch();
+});
+
+
+function subscribe(box, symbol) {
+       if (box.checked) {
+               dojox.cometd.subscribe("/stock/"+symbol, onMsgEvent);
+               var rowCurrent = dojo.byId("row."+symbol);
+               rowCurrent.bgColor="white";
+       } else {
+               dojox.cometd.unsubscribe("/stock/"+symbol, onMsgEvent);
+               var rowCurrent = dojo.byId("row."+symbol);
+               rowCurrent.bgColor="gray";
+       }
+}
+
+function removeChildrenFromNode(node)
+{
+   if(node == undefined || node == null)
+   {
+      return;
+   }
+
+   var len = node.childNodes.length;
+
+       while (node.hasChildNodes())
+       {
+         node.removeChild(node.firstChild);
+       }
+}
+
+function onMsgEvent(event) {
+   // Break apart the text string into screen name and message parts.
+   var symbol = event.data.symbol;
+   var price = event.data.price;
+   var pricechange = event.data.change;
+   //alert("symbol: "+symbol+" price: "+price+" change: "+pricechange);
+
+   var pricenode = dojo.byId("price."+symbol);
+   var changenode = dojo.byId("change."+symbol);
+   removeChildrenFromNode(pricenode);
+   removeChildrenFromNode(changenode);
+   var pricelabel = document.createTextNode(price);
+   pricelabel.value = price;
+   var changelabel = document.createTextNode(pricechange);
+   changelabel.value = pricechange;
+   pricenode.appendChild(pricelabel);
+   changenode.appendChild(changelabel);
+
+   var table = dojo.byId("stocktable");  
+   var rows = table.getElementsByTagName("tr");  
+   for(i = 0; i < rows.length; i++){
+          if (rows[i].bgColor != "gray") {
+              rows[i].bgColor = "white"; 
+          }
+   }          
+   //manipulate rows 
+   var rowCurrent = dojo.byId("row."+symbol);
+   if (pricechange<=0) {
+       rowCurrent.bgColor = "red";
+   } else {
+          rowCurrent.bgColor = "cyan";
+   }
+}
+
+
+</script>
+</head>
+<body bgcolor="#ffffff">
+<h1 align="center">Bayeux Stock Ticker</h1>
+<h2 align="left"> &nbsp;</h2>
+<p>
+<table id="stocktable" cellspacing="0" cellpadding="3" width="100%" align="center" border="0">
+  <tr id="row.HEADER">
+    <td>SYMBOL</td>
+    <td>PRICE</td>
+    <td>LAST CHANGE</td>
+    <td>SUBSCRIBE</td></tr>
+  <tr id="row.SPRG">
+    <td>SPRG</td>
+    <td id="price.SPRG"></td>
+    <td id="change.SPRG"></td>
+    <td id="check.SPRG"><input type="checkbox" id="check.SPRG" checked onClick="subscribe(this,'SPRG')"></td>
+  </tr>
+  <tr id="row.GOOG">
+    <td>GOOG</td>
+    <td id="price.GOOG"></td>
+    <td id="change.GOOG"></td>
+    <td id="check.GOOG"><input type="checkbox" id="check.GOOG" checked  onClick="subscribe(this,'GOOG')"></td>
+  </tr>
+  <tr id="row.YHOO">
+    <td>YHOO</td>
+    <td id="price.YHOO"></td>
+    <td id="change.YHOO"></td>
+    <td id="check.YHOO"><input type="checkbox" id="check.GOOG" checked  onClick="subscribe(this,'YHOO')"></td>
+  </tr>
+</table>
+</p>
+</body>
 </html>
\ No newline at end of file
index 9a7d6d7..d278313 100644 (file)
@@ -1,7 +1,7 @@
-\r
-<h1>Cometd demo</h1>\r
-\r
-<p>\r
-Try the <a href="examples/simplechat/cometdchat.htm">Simple Chat Demo</a>.</br>\r
-Try the <a href="examples/simplechat/ticker.html">Stock Ticker Demo</a>.</br>\r
-</p>\r
+
+<h1>Cometd demo</h1>
+
+<p>
+Try the <a href="examples/simplechat/cometdchat.htm">Simple Chat Demo</a>.</br>
+Try the <a href="examples/simplechat/ticker.html">Stock Ticker Demo</a>.</br>
+</p>
index 93653ee..0daa295 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- *\r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.jdbc.pool.interceptor;\r
-\r
-import java.lang.reflect.Method;\r
-import java.sql.SQLException;\r
-\r
-import org.apache.juli.logging.Log;\r
-import org.apache.juli.logging.LogFactory;\r
-import org.apache.tomcat.jdbc.pool.ConnectionPool;\r
-import org.apache.tomcat.jdbc.pool.DataSourceFactory;\r
-import org.apache.tomcat.jdbc.pool.JdbcInterceptor;\r
-import org.apache.tomcat.jdbc.pool.PoolProperties;\r
-import org.apache.tomcat.jdbc.pool.PooledConnection;\r
-\r
-/**\r
- * Interceptor that keep track of connection state to avoid roundtrips to the database\r
- * @author fhanik\r
- *\r
- */\r
-\r
-public class ConnectionState extends JdbcInterceptor  {\r
-    protected static Log log = LogFactory.getLog(ConnectionState.class);\r
-    \r
-    protected final String[] readState = {"getAutoCommit","getTransactionIsolation","isReadOnly","getCatalog"};\r
-    protected final String[] writeState = {"setAutoCommit","setTransactionIsolation","setReadOnly","setCatalog"};\r
-\r
-    protected Boolean autoCommit = null;\r
-    protected Integer transactionIsolation = null;\r
-    protected Boolean readOnly = null;\r
-    protected String catalog = null;\r
-    \r
-    \r
-    public void reset(ConnectionPool parent, PooledConnection con) {\r
-        PoolProperties poolProperties = parent.getPoolProperties();\r
-        if (poolProperties.getDefaultReadOnly()!=null) {\r
-            try {\r
-                if (readOnly==null || readOnly.booleanValue()!=poolProperties.getDefaultReadOnly().booleanValue()) {\r
-                    con.getConnection().setReadOnly(poolProperties.getDefaultReadOnly().booleanValue());\r
-                    readOnly = poolProperties.getDefaultReadOnly();\r
-                }\r
-            }catch (SQLException x) {\r
-                readOnly = null;\r
-                log.error("Unable to reset readonly state to connection.",x);\r
-            }\r
-        }\r
-        if (poolProperties.getDefaultAutoCommit()!=null) {\r
-            try {\r
-                if (autoCommit==null || autoCommit.booleanValue()!=poolProperties.getDefaultAutoCommit().booleanValue()) {\r
-                    con.getConnection().setAutoCommit(poolProperties.getDefaultAutoCommit().booleanValue());\r
-                    autoCommit = poolProperties.getDefaultAutoCommit();\r
-                }\r
-            }catch (SQLException x) {\r
-                autoCommit = null;\r
-                log.error("Unable to reset autocommit state to connection.",x);\r
-            }\r
-        }\r
-        if (poolProperties.getDefaultCatalog()!=null) {\r
-            try {\r
-                if (catalog==null || (!catalog.equals(poolProperties.getDefaultCatalog()))) {\r
-                    con.getConnection().setCatalog(poolProperties.getDefaultCatalog());\r
-                    catalog = poolProperties.getDefaultCatalog();\r
-                }\r
-            }catch (SQLException x) {\r
-                catalog = null;\r
-                log.error("Unable to reset default catalog state to connection.",x);\r
-            }\r
-        }\r
-        if (poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION) {\r
-            try {\r
-                if (transactionIsolation==null || transactionIsolation.intValue()!=poolProperties.getDefaultTransactionIsolation()) {\r
-                    con.getConnection().setTransactionIsolation(poolProperties.getDefaultTransactionIsolation());\r
-                    transactionIsolation = poolProperties.getDefaultTransactionIsolation();\r
-                }\r
-            }catch (SQLException x) {\r
-                transactionIsolation = null;\r
-                log.error("Unable to reset transaction isolation state to connection.",x);\r
-            }\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
-        String name = method.getName();\r
-        boolean read = false;\r
-        int index = -1;\r
-        for (int i=0; (!read) && i<readState.length; i++) {\r
-            read = compare(name,readState[i]);\r
-            if (read) index = i;\r
-        }\r
-        boolean write = false;\r
-        for (int i=0; (!write) && (!read) && i<writeState.length; i++) {\r
-            write = compare(name,writeState[i]);\r
-            if (write) index = i;\r
-        }\r
-        Object result = null;\r
-        if (read) {\r
-            switch (index) {\r
-                case 0:{result = autoCommit; break;}\r
-                case 1:{result = transactionIsolation; break;}\r
-                case 2:{result = readOnly; break;}\r
-                case 3:{result = catalog; break;}\r
-                default: result = null;\r
-            }\r
-            //return cached result, if we have it\r
-            if (result!=null) return result;\r
-        }\r
-\r
-        result = super.invoke(proxy, method, args);\r
-        if (read || write) {\r
-            switch (index) {\r
-                case 0:{autoCommit = (Boolean) (read?result:args[0]); break;}\r
-                case 1:{transactionIsolation = (Integer)(read?result:args[0]); break;}\r
-                case 2:{readOnly = (Boolean)(read?result:args[0]); break;}\r
-                case 3:{catalog = (String)(read?result:args[0]); break;}\r
-            }\r
-        }\r
-        return result;\r
-    }\r
-\r
-}\r
+/*
+ * 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.jdbc.pool.interceptor;
+
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.DataSourceFactory;
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
+import org.apache.tomcat.jdbc.pool.PoolProperties;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+
+/**
+ * Interceptor that keep track of connection state to avoid roundtrips to the database
+ * @author fhanik
+ *
+ */
+
+public class ConnectionState extends JdbcInterceptor  {
+    protected static Log log = LogFactory.getLog(ConnectionState.class);
+    
+    protected final String[] readState = {"getAutoCommit","getTransactionIsolation","isReadOnly","getCatalog"};
+    protected final String[] writeState = {"setAutoCommit","setTransactionIsolation","setReadOnly","setCatalog"};
+
+    protected Boolean autoCommit = null;
+    protected Integer transactionIsolation = null;
+    protected Boolean readOnly = null;
+    protected String catalog = null;
+    
+    
+    public void reset(ConnectionPool parent, PooledConnection con) {
+        PoolProperties poolProperties = parent.getPoolProperties();
+        if (poolProperties.getDefaultReadOnly()!=null) {
+            try {
+                if (readOnly==null || readOnly.booleanValue()!=poolProperties.getDefaultReadOnly().booleanValue()) {
+                    con.getConnection().setReadOnly(poolProperties.getDefaultReadOnly().booleanValue());
+                    readOnly = poolProperties.getDefaultReadOnly();
+                }
+            }catch (SQLException x) {
+                readOnly = null;
+                log.error("Unable to reset readonly state to connection.",x);
+            }
+        }
+        if (poolProperties.getDefaultAutoCommit()!=null) {
+            try {
+                if (autoCommit==null || autoCommit.booleanValue()!=poolProperties.getDefaultAutoCommit().booleanValue()) {
+                    con.getConnection().setAutoCommit(poolProperties.getDefaultAutoCommit().booleanValue());
+                    autoCommit = poolProperties.getDefaultAutoCommit();
+                }
+            }catch (SQLException x) {
+                autoCommit = null;
+                log.error("Unable to reset autocommit state to connection.",x);
+            }
+        }
+        if (poolProperties.getDefaultCatalog()!=null) {
+            try {
+                if (catalog==null || (!catalog.equals(poolProperties.getDefaultCatalog()))) {
+                    con.getConnection().setCatalog(poolProperties.getDefaultCatalog());
+                    catalog = poolProperties.getDefaultCatalog();
+                }
+            }catch (SQLException x) {
+                catalog = null;
+                log.error("Unable to reset default catalog state to connection.",x);
+            }
+        }
+        if (poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION) {
+            try {
+                if (transactionIsolation==null || transactionIsolation.intValue()!=poolProperties.getDefaultTransactionIsolation()) {
+                    con.getConnection().setTransactionIsolation(poolProperties.getDefaultTransactionIsolation());
+                    transactionIsolation = poolProperties.getDefaultTransactionIsolation();
+                }
+            }catch (SQLException x) {
+                transactionIsolation = null;
+                log.error("Unable to reset transaction isolation state to connection.",x);
+            }
+        }
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        String name = method.getName();
+        boolean read = false;
+        int index = -1;
+        for (int i=0; (!read) && i<readState.length; i++) {
+            read = compare(name,readState[i]);
+            if (read) index = i;
+        }
+        boolean write = false;
+        for (int i=0; (!write) && (!read) && i<writeState.length; i++) {
+            write = compare(name,writeState[i]);
+            if (write) index = i;
+        }
+        Object result = null;
+        if (read) {
+            switch (index) {
+                case 0:{result = autoCommit; break;}
+                case 1:{result = transactionIsolation; break;}
+                case 2:{result = readOnly; break;}
+                case 3:{result = catalog; break;}
+                default: result = null;
+            }
+            //return cached result, if we have it
+            if (result!=null) return result;
+        }
+
+        result = super.invoke(proxy, method, args);
+        if (read || write) {
+            switch (index) {
+                case 0:{autoCommit = (Boolean) (read?result:args[0]); break;}
+                case 1:{transactionIsolation = (Integer)(read?result:args[0]); break;}
+                case 2:{readOnly = (Boolean)(read?result:args[0]); break;}
+                case 3:{catalog = (String)(read?result:args[0]); break;}
+            }
+        }
+        return result;
+    }
+
+}
index a10eb3a..91ba268 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- *\r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.jdbc.pool.interceptor;\r
-\r
-import java.lang.reflect.InvocationHandler;\r
-import java.lang.reflect.Method;\r
-import java.lang.reflect.Proxy;\r
-import java.sql.CallableStatement;\r
-import java.sql.SQLException;\r
-import java.util.HashMap;\r
-import java.util.IdentityHashMap;\r
-import java.util.LinkedHashMap;\r
-import java.util.Map.Entry;\r
-\r
-import org.apache.tomcat.jdbc.pool.ConnectionPool;\r
-import org.apache.tomcat.jdbc.pool.JdbcInterceptor;\r
-import org.apache.tomcat.jdbc.pool.PooledConnection;\r
-\r
-/**\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class SlowQueryReport extends AbstractCreateStatementInterceptor {\r
-    protected final String[] statements = {"createStatement","prepareStatement","prepareCall"};\r
-    protected final String[] executes = {"execute","executeQuery","executeUpdate","executeBatch"};\r
-\r
-    protected static IdentityHashMap<ConnectionPool,HashMap<String,QueryStats>> perPoolStats = \r
-        new IdentityHashMap<ConnectionPool,HashMap<String,QueryStats>>();\r
-    \r
-    protected HashMap<String,QueryStats> queries = null;\r
-    \r
-    protected long threshold = 100; //don't report queries less than this\r
-    protected int  maxQueries= 1000; //don't store more than this amount of queries\r
-\r
-    \r
-    \r
-    public SlowQueryReport() {\r
-        super();\r
-    }\r
-\r
-    public long getThreshold() {\r
-        return threshold;\r
-    }\r
-\r
-    public void setThreshold(long threshold) {\r
-        this.threshold = threshold;\r
-    }\r
-\r
-    @Override\r
-    public void closeInvoked() {\r
-        // TODO Auto-generated method stub\r
-        \r
-    }\r
-\r
-    @Override\r
-    public Object createStatement(Object proxy, Method method, Object[] args, Object statement) {\r
-        // TODO Auto-generated method stub\r
-        String sql = null;\r
-        if (method.getName().startsWith("prepare")) {\r
-            sql = (args.length>0 && (args[0] instanceof String))?(String)args[0]:null;\r
-        }\r
-        return new StatementProxy(statement,sql);\r
-    }\r
-\r
-    protected boolean process(final String[] names, Method method, boolean process) {\r
-        for (int i=0; (!process) && i<names.length; i++) {\r
-            process = compare(method.getName(),names[i]);\r
-        }\r
-        return process;\r
-    }\r
-\r
-    protected class QueryStats {\r
-        private final String query;\r
-        private int nrOfInvocations;\r
-        private long maxInvocationTime;\r
-        private long maxInvocationDate;\r
-        private long minInvocationTime;\r
-        private long minInvocationDate;\r
-        private long totalInvocationTime;\r
-        \r
-        public QueryStats(String query) {\r
-            this.query = query;\r
-        }\r
-        \r
-        public void add(long invocationTime) {\r
-            long now = -1;\r
-            //not thread safe, but don't sacrifice performance for this kind of stuff\r
-            maxInvocationTime = Math.max(invocationTime, maxInvocationTime);\r
-            if (maxInvocationTime == invocationTime) {\r
-                now = System.currentTimeMillis();\r
-                maxInvocationDate = now;\r
-            }\r
-            minInvocationTime = Math.min(invocationTime, minInvocationTime);\r
-            if (minInvocationTime==invocationTime) {\r
-                now = (now==-1)?System.currentTimeMillis():now;\r
-                minInvocationDate = now;\r
-            }\r
-            nrOfInvocations++;\r
-            totalInvocationTime+=invocationTime;\r
-        }\r
-        \r
-        public String getQuery() {\r
-            return query;\r
-        }\r
-\r
-        public int getNrOfInvocations() {\r
-            return nrOfInvocations;\r
-        }\r
-\r
-        public long getMaxInvocationTime() {\r
-            return maxInvocationTime;\r
-        }\r
-\r
-        public long getMaxInvocationDate() {\r
-            return maxInvocationDate;\r
-        }\r
-\r
-        public long getMinInvocationTime() {\r
-            return minInvocationTime;\r
-        }\r
-\r
-        public long getMinInvocationDate() {\r
-            return minInvocationDate;\r
-        }\r
-\r
-        public long getTotalInvocationTime() {\r
-            return totalInvocationTime;\r
-        }\r
-\r
-        public int hashCode() {\r
-            return query.hashCode();\r
-        }\r
-        \r
-        public boolean equals(Object other) {\r
-            if (other instanceof QueryStats) {\r
-                QueryStats qs = (QueryStats)other;\r
-                return SlowQueryReport.this.compare(qs.query,this.query);\r
-            } \r
-            return false;\r
-        }\r
-    }\r
-    \r
-    protected class StatementProxy implements InvocationHandler {\r
-        protected boolean closed = false;\r
-        protected Object delegate;\r
-        protected final String query;\r
-        public StatementProxy(Object parent, String query) {\r
-            this.delegate = parent;\r
-            this.query = query;\r
-        }\r
-        \r
-        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
-            final String name = method.getName();\r
-            boolean close = compare(JdbcInterceptor.CLOSE_VAL,name);\r
-            if (close && closed) return null; //allow close to be called multiple times\r
-            if (closed) throw new SQLException("Statement closed.");\r
-            boolean process = false;\r
-            process = process(executes, method, process);\r
-            long start = (process)?System.currentTimeMillis():0;\r
-            //execute the query\r
-            Object result =  method.invoke(delegate,args);\r
-            long delta = (process)?(System.currentTimeMillis()-start):0;\r
-            if (delta>threshold) {\r
-                String sql = null;//TODO\r
-                QueryStats qs = SlowQueryReport.this.queries.get(sql);\r
-                if (qs == null) {\r
-                    qs = new QueryStats(sql);\r
-                    SlowQueryReport.this.queries.put((String)sql,qs);\r
-                }\r
-                qs.add(delta);\r
-                return qs;\r
-            }\r
-            if (close) {\r
-                closed=true;\r
-                delegate = null;\r
-            }\r
-            return result;\r
-        }\r
-    }\r
-\r
-    public void reset(ConnectionPool parent, PooledConnection con) {\r
-        if (queries==null && SlowQueryReport.perPoolStats.get(parent)==null) {\r
-            queries = new LinkedHashMap<String,QueryStats>() {\r
-                @Override\r
-                protected boolean removeEldestEntry(Entry<String, QueryStats> eldest) {\r
-                    return size()>maxQueries;\r
-                }\r
-\r
-            };\r
-        }\r
-    }\r
-}\r
+/*
+ * 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.jdbc.pool.interceptor;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.CallableStatement;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
+
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+
+/**
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class SlowQueryReport extends AbstractCreateStatementInterceptor {
+    protected final String[] statements = {"createStatement","prepareStatement","prepareCall"};
+    protected final String[] executes = {"execute","executeQuery","executeUpdate","executeBatch"};
+
+    protected static IdentityHashMap<ConnectionPool,HashMap<String,QueryStats>> perPoolStats = 
+        new IdentityHashMap<ConnectionPool,HashMap<String,QueryStats>>();
+    
+    protected HashMap<String,QueryStats> queries = null;
+    
+    protected long threshold = 100; //don't report queries less than this
+    protected int  maxQueries= 1000; //don't store more than this amount of queries
+
+    
+    
+    public SlowQueryReport() {
+        super();
+    }
+
+    public long getThreshold() {
+        return threshold;
+    }
+
+    public void setThreshold(long threshold) {
+        this.threshold = threshold;
+    }
+
+    @Override
+    public void closeInvoked() {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public Object createStatement(Object proxy, Method method, Object[] args, Object statement) {
+        // TODO Auto-generated method stub
+        String sql = null;
+        if (method.getName().startsWith("prepare")) {
+            sql = (args.length>0 && (args[0] instanceof String))?(String)args[0]:null;
+        }
+        return new StatementProxy(statement,sql);
+    }
+
+    protected boolean process(final String[] names, Method method, boolean process) {
+        for (int i=0; (!process) && i<names.length; i++) {
+            process = compare(method.getName(),names[i]);
+        }
+        return process;
+    }
+
+    protected class QueryStats {
+        private final String query;
+        private int nrOfInvocations;
+        private long maxInvocationTime;
+        private long maxInvocationDate;
+        private long minInvocationTime;
+        private long minInvocationDate;
+        private long totalInvocationTime;
+        
+        public QueryStats(String query) {
+            this.query = query;
+        }
+        
+        public void add(long invocationTime) {
+            long now = -1;
+            //not thread safe, but don't sacrifice performance for this kind of stuff
+            maxInvocationTime = Math.max(invocationTime, maxInvocationTime);
+            if (maxInvocationTime == invocationTime) {
+                now = System.currentTimeMillis();
+                maxInvocationDate = now;
+            }
+            minInvocationTime = Math.min(invocationTime, minInvocationTime);
+            if (minInvocationTime==invocationTime) {
+                now = (now==-1)?System.currentTimeMillis():now;
+                minInvocationDate = now;
+            }
+            nrOfInvocations++;
+            totalInvocationTime+=invocationTime;
+        }
+        
+        public String getQuery() {
+            return query;
+        }
+
+        public int getNrOfInvocations() {
+            return nrOfInvocations;
+        }
+
+        public long getMaxInvocationTime() {
+            return maxInvocationTime;
+        }
+
+        public long getMaxInvocationDate() {
+            return maxInvocationDate;
+        }
+
+        public long getMinInvocationTime() {
+            return minInvocationTime;
+        }
+
+        public long getMinInvocationDate() {
+            return minInvocationDate;
+        }
+
+        public long getTotalInvocationTime() {
+            return totalInvocationTime;
+        }
+
+        public int hashCode() {
+            return query.hashCode();
+        }
+        
+        public boolean equals(Object other) {
+            if (other instanceof QueryStats) {
+                QueryStats qs = (QueryStats)other;
+                return SlowQueryReport.this.compare(qs.query,this.query);
+            } 
+            return false;
+        }
+    }
+    
+    protected class StatementProxy implements InvocationHandler {
+        protected boolean closed = false;
+        protected Object delegate;
+        protected final String query;
+        public StatementProxy(Object parent, String query) {
+            this.delegate = parent;
+            this.query = query;
+        }
+        
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            final String name = method.getName();
+            boolean close = compare(JdbcInterceptor.CLOSE_VAL,name);
+            if (close && closed) return null; //allow close to be called multiple times
+            if (closed) throw new SQLException("Statement closed.");
+            boolean process = false;
+            process = process(executes, method, process);
+            long start = (process)?System.currentTimeMillis():0;
+            //execute the query
+            Object result =  method.invoke(delegate,args);
+            long delta = (process)?(System.currentTimeMillis()-start):0;
+            if (delta>threshold) {
+                String sql = null;//TODO
+                QueryStats qs = SlowQueryReport.this.queries.get(sql);
+                if (qs == null) {
+                    qs = new QueryStats(sql);
+                    SlowQueryReport.this.queries.put((String)sql,qs);
+                }
+                qs.add(delta);
+                return qs;
+            }
+            if (close) {
+                closed=true;
+                delegate = null;
+            }
+            return result;
+        }
+    }
+
+    public void reset(ConnectionPool parent, PooledConnection con) {
+        if (queries==null && SlowQueryReport.perPoolStats.get(parent)==null) {
+            queries = new LinkedHashMap<String,QueryStats>() {
+                @Override
+                protected boolean removeEldestEntry(Entry<String, QueryStats> eldest) {
+                    return size()>maxQueries;
+                }
+
+            };
+        }
+    }
+}
index 75b5248..d645695 100644 (file)
-\r
-                                 Apache License\r
-                           Version 2.0, January 2004\r
-                        http://www.apache.org/licenses/\r
-\r
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\r
-\r
-   1. Definitions.\r
-\r
-      "License" shall mean the terms and conditions for use, reproduction,\r
-      and distribution as defined by Sections 1 through 9 of this document.\r
-\r
-      "Licensor" shall mean the copyright owner or entity authorized by\r
-      the copyright owner that is granting the License.\r
-\r
-      "Legal Entity" shall mean the union of the acting entity and all\r
-      other entities that control, are controlled by, or are under common\r
-      control with that entity. For the purposes of this definition,\r
-      "control" means (i) the power, direct or indirect, to cause the\r
-      direction or management of such entity, whether by contract or\r
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the\r
-      outstanding shares, or (iii) beneficial ownership of such entity.\r
-\r
-      "You" (or "Your") shall mean an individual or Legal Entity\r
-      exercising permissions granted by this License.\r
-\r
-      "Source" form shall mean the preferred form for making modifications,\r
-      including but not limited to software source code, documentation\r
-      source, and configuration files.\r
-\r
-      "Object" form shall mean any form resulting from mechanical\r
-      transformation or translation of a Source form, including but\r
-      not limited to compiled object code, generated documentation,\r
-      and conversions to other media types.\r
-\r
-      "Work" shall mean the work of authorship, whether in Source or\r
-      Object form, made available under the License, as indicated by a\r
-      copyright notice that is included in or attached to the work\r
-      (an example is provided in the Appendix below).\r
-\r
-      "Derivative Works" shall mean any work, whether in Source or Object\r
-      form, that is based on (or derived from) the Work and for which the\r
-      editorial revisions, annotations, elaborations, or other modifications\r
-      represent, as a whole, an original work of authorship. For the purposes\r
-      of this License, Derivative Works shall not include works that remain\r
-      separable from, or merely link (or bind by name) to the interfaces of,\r
-      the Work and Derivative Works thereof.\r
-\r
-      "Contribution" shall mean any work of authorship, including\r
-      the original version of the Work and any modifications or additions\r
-      to that Work or Derivative Works thereof, that is intentionally\r
-      submitted to Licensor for inclusion in the Work by the copyright owner\r
-      or by an individual or Legal Entity authorized to submit on behalf of\r
-      the copyright owner. For the purposes of this definition, "submitted"\r
-      means any form of electronic, verbal, or written communication sent\r
-      to the Licensor or its representatives, including but not limited to\r
-      communication on electronic mailing lists, source code control systems,\r
-      and issue tracking systems that are managed by, or on behalf of, the\r
-      Licensor for the purpose of discussing and improving the Work, but\r
-      excluding communication that is conspicuously marked or otherwise\r
-      designated in writing by the copyright owner as "Not a Contribution."\r
-\r
-      "Contributor" shall mean Licensor and any individual or Legal Entity\r
-      on behalf of whom a Contribution has been received by Licensor and\r
-      subsequently incorporated within the Work.\r
-\r
-   2. Grant of Copyright License. Subject to the terms and conditions of\r
-      this License, each Contributor hereby grants to You a perpetual,\r
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
-      copyright license to reproduce, prepare Derivative Works of,\r
-      publicly display, publicly perform, sublicense, and distribute the\r
-      Work and such Derivative Works in Source or Object form.\r
-\r
-   3. Grant of Patent License. Subject to the terms and conditions of\r
-      this License, each Contributor hereby grants to You a perpetual,\r
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
-      (except as stated in this section) patent license to make, have made,\r
-      use, offer to sell, sell, import, and otherwise transfer the Work,\r
-      where such license applies only to those patent claims licensable\r
-      by such Contributor that are necessarily infringed by their\r
-      Contribution(s) alone or by combination of their Contribution(s)\r
-      with the Work to which such Contribution(s) was submitted. If You\r
-      institute patent litigation against any entity (including a\r
-      cross-claim or counterclaim in a lawsuit) alleging that the Work\r
-      or a Contribution incorporated within the Work constitutes direct\r
-      or contributory patent infringement, then any patent licenses\r
-      granted to You under this License for that Work shall terminate\r
-      as of the date such litigation is filed.\r
-\r
-   4. Redistribution. You may reproduce and distribute copies of the\r
-      Work or Derivative Works thereof in any medium, with or without\r
-      modifications, and in Source or Object form, provided that You\r
-      meet the following conditions:\r
-\r
-      (a) You must give any other recipients of the Work or\r
-          Derivative Works a copy of this License; and\r
-\r
-      (b) You must cause any modified files to carry prominent notices\r
-          stating that You changed the files; and\r
-\r
-      (c) You must retain, in the Source form of any Derivative Works\r
-          that You distribute, all copyright, patent, trademark, and\r
-          attribution notices from the Source form of the Work,\r
-          excluding those notices that do not pertain to any part of\r
-          the Derivative Works; and\r
-\r
-      (d) If the Work includes a "NOTICE" text file as part of its\r
-          distribution, then any Derivative Works that You distribute must\r
-          include a readable copy of the attribution notices contained\r
-          within such NOTICE file, excluding those notices that do not\r
-          pertain to any part of the Derivative Works, in at least one\r
-          of the following places: within a NOTICE text file distributed\r
-          as part of the Derivative Works; within the Source form or\r
-          documentation, if provided along with the Derivative Works; or,\r
-          within a display generated by the Derivative Works, if and\r
-          wherever such third-party notices normally appear. The contents\r
-          of the NOTICE file are for informational purposes only and\r
-          do not modify the License. You may add Your own attribution\r
-          notices within Derivative Works that You distribute, alongside\r
-          or as an addendum to the NOTICE text from the Work, provided\r
-          that such additional attribution notices cannot be construed\r
-          as modifying the License.\r
-\r
-      You may add Your own copyright statement to Your modifications and\r
-      may provide additional or different license terms and conditions\r
-      for use, reproduction, or distribution of Your modifications, or\r
-      for any such Derivative Works as a whole, provided Your use,\r
-      reproduction, and distribution of the Work otherwise complies with\r
-      the conditions stated in this License.\r
-\r
-   5. Submission of Contributions. Unless You explicitly state otherwise,\r
-      any Contribution intentionally submitted for inclusion in the Work\r
-      by You to the Licensor shall be under the terms and conditions of\r
-      this License, without any additional terms or conditions.\r
-      Notwithstanding the above, nothing herein shall supersede or modify\r
-      the terms of any separate license agreement you may have executed\r
-      with Licensor regarding such Contributions.\r
-\r
-   6. Trademarks. This License does not grant permission to use the trade\r
-      names, trademarks, service marks, or product names of the Licensor,\r
-      except as required for reasonable and customary use in describing the\r
-      origin of the Work and reproducing the content of the NOTICE file.\r
-\r
-   7. Disclaimer of Warranty. Unless required by applicable law or\r
-      agreed to in writing, Licensor provides the Work (and each\r
-      Contributor provides its Contributions) on an "AS IS" BASIS,\r
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r
-      implied, including, without limitation, any warranties or conditions\r
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\r
-      PARTICULAR PURPOSE. You are solely responsible for determining the\r
-      appropriateness of using or redistributing the Work and assume any\r
-      risks associated with Your exercise of permissions under this License.\r
-\r
-   8. Limitation of Liability. In no event and under no legal theory,\r
-      whether in tort (including negligence), contract, or otherwise,\r
-      unless required by applicable law (such as deliberate and grossly\r
-      negligent acts) or agreed to in writing, shall any Contributor be\r
-      liable to You for damages, including any direct, indirect, special,\r
-      incidental, or consequential damages of any character arising as a\r
-      result of this License or out of the use or inability to use the\r
-      Work (including but not limited to damages for loss of goodwill,\r
-      work stoppage, computer failure or malfunction, or any and all\r
-      other commercial damages or losses), even if such Contributor\r
-      has been advised of the possibility of such damages.\r
-\r
-   9. Accepting Warranty or Additional Liability. While redistributing\r
-      the Work or Derivative Works thereof, You may choose to offer,\r
-      and charge a fee for, acceptance of support, warranty, indemnity,\r
-      or other liability obligations and/or rights consistent with this\r
-      License. However, in accepting such obligations, You may act only\r
-      on Your own behalf and on Your sole responsibility, not on behalf\r
-      of any other Contributor, and only if You agree to indemnify,\r
-      defend, and hold each Contributor harmless for any liability\r
-      incurred by, or claims asserted against, such Contributor by reason\r
-      of your accepting any such warranty or additional liability.\r
-\r
-   END OF TERMS AND CONDITIONS\r
-\r
-   APPENDIX: How to apply the Apache License to your work.\r
-\r
-      To apply the Apache License to your work, attach the following\r
-      boilerplate notice, with the fields enclosed by brackets "[]"\r
-      replaced with your own identifying information. (Don't include\r
-      the brackets!)  The text should be enclosed in the appropriate\r
-      comment syntax for the file format. We also recommend that a\r
-      file or class name and description of purpose be included on the\r
-      same "printed page" as the copyright notice for easier\r
-      identification within third-party archives.\r
-\r
-   Copyright [yyyy] [name of copyright owner]\r
-\r
-   Licensed under the Apache License, Version 2.0 (the "License");\r
-   you may not use this file except in compliance with the License.\r
-   You may obtain a copy of the License at\r
-\r
-       http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
index 4539205..3f59805 100644 (file)
@@ -1,2 +1,2 @@
-This product includes software developed by\r
-The Apache Software Foundation (http://www.apache.org/).\r
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)