From: markt Date: Fri, 5 Dec 2008 15:57:43 +0000 (+0000) Subject: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=46247 X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=704ba4198fe6a2b3c4f539f9d8ace0e43c4f28ff;p=tomcat7.0 Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=46247 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 --- diff --git a/modules/bayeux/java/org/apache/cometd/bayeux/Bayeux.java b/modules/bayeux/java/org/apache/cometd/bayeux/Bayeux.java index 5385d325d..3ca4fe701 100644 --- a/modules/bayeux/java/org/apache/cometd/bayeux/Bayeux.java +++ b/modules/bayeux/java/org/apache/cometd/bayeux/Bayeux.java @@ -1,242 +1,242 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.cometd.bayeux; - -import java.util.List; - -/** Bayeux Interface.
- * 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.
- * It is used both by the actual implementation and by server side clients.
- * 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. - *
- * The Bayeux implementations is intended to be thread safe and multiple threads may simultaneously call Bayeux methods. - *
- * 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 javax.servlet.ServletContext object - * as an attribute under the name Bayeux.DOJOX_COMETD_BAYEUX
- * To retrieve this object, one would simply call
- * Bayeux bx = (Bayeux)getServletContext().getAttribute(Bayeux.DOJOX_COMETD_BAYEUX); - *

- * 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 Listener interface.
- *
- * A Bayeux session is active as long as the webapp hosting the Bayeux object is active.
- * 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 - a list containing all clients. The List can not be modified. - */ - public List getClients(); - - /** - * Returns true if a client with the given id exists.
- * Same as executing getClient(id)!=null. - * @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 create parameter is set to true, - * the channel will be created and added to the list of active channels.
- * if create 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 create 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 - */ - public List 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. - *
Same as executing Bayeux.getChannel(channelId,false)!=null - * @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); - +/* + * 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.
+ * 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.
+ * It is used both by the actual implementation and by server side clients.
+ * 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. + *
+ * The Bayeux implementations is intended to be thread safe and multiple threads may simultaneously call Bayeux methods. + *
+ * 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 javax.servlet.ServletContext object + * as an attribute under the name Bayeux.DOJOX_COMETD_BAYEUX
+ * To retrieve this object, one would simply call
+ * Bayeux bx = (Bayeux)getServletContext().getAttribute(Bayeux.DOJOX_COMETD_BAYEUX); + *

+ * 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 Listener interface.
+ *
+ * A Bayeux session is active as long as the webapp hosting the Bayeux object is active.
+ * 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 - a list containing all clients. The List can not be modified. + */ + public List getClients(); + + /** + * Returns true if a client with the given id exists.
+ * Same as executing getClient(id)!=null. + * @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 create parameter is set to true, + * the channel will be created and added to the list of active channels.
+ * if create 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 create 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 + */ + public List 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. + *
Same as executing Bayeux.getChannel(channelId,false)!=null + * @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 diff --git a/modules/bayeux/java/org/apache/cometd/bayeux/Channel.java b/modules/bayeux/java/org/apache/cometd/bayeux/Channel.java index 34af32878..468b5e181 100644 --- a/modules/bayeux/java/org/apache/cometd/bayeux/Channel.java +++ b/modules/bayeux/java/org/apache/cometd/bayeux/Channel.java @@ -1,103 +1,103 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.cometd.bayeux; - -import java.util.List; - -/** - * A Bayeux Channel represents a channel used to receive messages from and to publish messages to. - * In order to publish messages to or receive messages from, one must subscribe to the channel. - * This is easily done by invoking the subscribe method. - * A channel is created by calling the Bayeux.getChannel(channelId,true) 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 from is contained within the message, by calling - * msg.getClient() - * @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 from is contained within the message, by calling - * msg[x].getClient() - * @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 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); +/* + * 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 subscribe method. + * A channel is created by calling the Bayeux.getChannel(channelId,true) 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 from is contained within the message, by calling + * msg.getClient() + * @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 from is contained within the message, by calling + * msg[x].getClient() + * @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 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 diff --git a/modules/bayeux/java/org/apache/cometd/bayeux/Client.java b/modules/bayeux/java/org/apache/cometd/bayeux/Client.java index 3d6a8d89a..32e8773b0 100644 --- a/modules/bayeux/java/org/apache/cometd/bayeux/Client.java +++ b/modules/bayeux/java/org/apache/cometd/bayeux/Client.java @@ -1,91 +1,91 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.cometd.bayeux; - - - -/** A Bayeux Client. - *

- * 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. - *

- *

- * Three types of client may be represented by this interface: - *

  • The server representation of a remote client connected via HTTP, - * automatically created by the Bayeux server when a connect message comes in
  • - *
  • A server side client, created by the application using the {@link Bayeux#newClient(String, Listener)} method
  • - *
  • A java client connected to a remote Bayeux server - not implemented
  • - * - * @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(); - - +/* + * 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. + *

    + * 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. + *

    + *

    + * Three types of client may be represented by this interface: + *

  • The server representation of a remote client connected via HTTP, + * automatically created by the Bayeux server when a connect message comes in
  • + *
  • A server side client, created by the application using the {@link Bayeux#newClient(String, Listener)} method
  • + *
  • A java client connected to a remote Bayeux server - not implemented
  • + * + * @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 diff --git a/modules/bayeux/java/org/apache/cometd/bayeux/DataFilter.java b/modules/bayeux/java/org/apache/cometd/bayeux/DataFilter.java index d632aec3e..abc964e21 100644 --- a/modules/bayeux/java/org/apache/cometd/bayeux/DataFilter.java +++ b/modules/bayeux/java/org/apache/cometd/bayeux/DataFilter.java @@ -1,38 +1,38 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.cometd.bayeux; - -/** - * Data Filter
    - * 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.
    - * 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); -} +/* + * 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
    + * 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.
    + * 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); +} diff --git a/modules/bayeux/java/org/apache/cometd/bayeux/Listener.java b/modules/bayeux/java/org/apache/cometd/bayeux/Listener.java index cce2018fa..9cd86d014 100644 --- a/modules/bayeux/java/org/apache/cometd/bayeux/Listener.java +++ b/modules/bayeux/java/org/apache/cometd/bayeux/Listener.java @@ -1,45 +1,45 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.cometd.bayeux; - -/** - * Cometd Listener interface.
    - * 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); -} +/* + * 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.
    + * 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); +} diff --git a/modules/bayeux/java/org/apache/cometd/bayeux/Message.java b/modules/bayeux/java/org/apache/cometd/bayeux/Message.java index 26ba64084..12b525bf9 100644 --- a/modules/bayeux/java/org/apache/cometd/bayeux/Message.java +++ b/modules/bayeux/java/org/apache/cometd/bayeux/Message.java @@ -1,68 +1,68 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.cometd.bayeux; - -import java.util.Map; - -/** - * A Bayeux Message
    - * 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 -{ - /** - * 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(); -} - - +/* + * 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
    + * 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 +{ + /** + * 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(); +} + + diff --git a/modules/bayeux/java/org/apache/cometd/bayeux/SecurityPolicy.java b/modules/bayeux/java/org/apache/cometd/bayeux/SecurityPolicy.java index 930f605ea..55e71586d 100644 --- a/modules/bayeux/java/org/apache/cometd/bayeux/SecurityPolicy.java +++ b/modules/bayeux/java/org/apache/cometd/bayeux/SecurityPolicy.java @@ -1,28 +1,28 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.cometd.bayeux; - -/** - * @author Greg Wilkins - */ -public interface SecurityPolicy -{ - boolean canHandshake(Message message); - boolean canCreate(Client client,String channel,Message message); - boolean canSubscribe(Client client,String channel,Message messsage); - boolean canPublish(Client client,String channel,Message messsage); -} +/* + * 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); +} diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxException.java b/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxException.java index d201c5eba..6d96bb362 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxException.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxException.java @@ -1,39 +1,39 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tomcat.bayeux; -/** - * - * @author Filip Hanik - * @version 1.0 - */ -public class BayeuxException extends Exception { - public BayeuxException() { - super(); - } - - public BayeuxException(String message) { - super(message); - } - - public BayeuxException(String message, Throwable cause) { - super(message, cause); - } - - public BayeuxException(Throwable cause) { - super(cause); - } +/* + * 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 diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxRequest.java b/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxRequest.java index 6e93c9921..6dd9b33ff 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxRequest.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxRequest.java @@ -1,54 +1,54 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tomcat.bayeux; - -import org.apache.tomcat.bayeux.HttpError; - -/** - * An interface that defines methods for managing Bayeux request meta - * messages. - * - * @author Guy A. Molinari - * @author Filip Hanik - * @version 0.9 - */ -public interface BayeuxRequest { - - public static final String LAST_REQ_ATTR = "org.apache.cometd.bayeux.last_request"; - public static final String CURRENT_REQ_ATTR = "org.apache.cometd.bayeux.current_request"; - public static final String JSON_MSG_ARRAY = "org.apache.cometd.bayeux.json_msg_array"; - - /** - * Validates a specific request. - * This method must be called prior to process() - * as a request can do pre processing in the validate method. - *
    - * 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; -} +/* + * 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. + *
    + * 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; +} diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxServlet.java b/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxServlet.java index 837086d70..dfb81b372 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxServlet.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxServlet.java @@ -1,236 +1,236 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tomcat.bayeux; - -import java.io.IOException; -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletResponse; - -import org.apache.catalina.CometEvent; -import org.apache.catalina.CometProcessor; -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.apache.cometd.bayeux.Bayeux; - -/** - * - * @author Filip Hanik - * @author Guy Molinari - * @version 1.0 - */ -public class BayeuxServlet implements CometProcessor { - - /** - * Attribute to hold the TomcatBayeux object in the servlet context - */ - public static final String TOMCAT_BAYEUX_ATTR = Bayeux.DOJOX_COMETD_BAYEUX; - - /** - * Logger object - */ - protected static Log log = LogFactory.getLog(BayeuxServlet.class); - - /** - * Servlet config - for future use - */ - protected ServletConfig servletConfig; - - /** - * Reference to the global TomcatBayeux object - */ - protected TomcatBayeux tb; - - /** - * Upon servlet destruction, the servlet will clean up the - * TomcatBayeux object and terminate any outstanding events. - */ - public void destroy() { - servletConfig = null; - //to do, close all outstanding comet events - //tb.destroy(); - tb = null;//TO DO, close everything down - - } - - /** - * Returns the preconfigured connection timeout. - * If no timeout has been configured as a servlet init parameter named timeout - * 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."); - } - } -} +/* + * 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 timeout + * 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."); + } + } +} diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/ChannelImpl.java b/modules/bayeux/java/org/apache/tomcat/bayeux/ChannelImpl.java index e1e08a8a0..353fe77b5 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/ChannelImpl.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/ChannelImpl.java @@ -1,189 +1,189 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tomcat.bayeux; - -import java.util.LinkedList; - -import org.apache.cometd.bayeux.Channel; -import org.apache.cometd.bayeux.Client; -import org.apache.cometd.bayeux.DataFilter; -import java.util.Collections; -import java.util.List; -import org.apache.cometd.bayeux.Message; -import java.util.Iterator; -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -/** - * - * @author Filip Hanik - * @version 1.0 - */ -public class ChannelImpl implements Channel { - - protected static Log log = LogFactory.getLog(ChannelImpl.class); - - /** - * The unique id of this channel - */ - protected String id = null; - - /** - * A list of the current subscribers - */ - protected LinkedList subscribers = new LinkedList(); - - /** - * A list of the current filters - */ - protected LinkedList filters = new LinkedList(); - - /** - * 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 /service/mychannel - * or it can be a wild card pattern like /service/app2/** - * @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 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 it = filters.iterator(); it.hasNext(); ) { - it.next().filter(msg); - } - imsgs[i] = msg; - } - //deliver it to the clients - for (Iterator 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(); - } - +/* + * 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 subscribers = new LinkedList(); + + /** + * A list of the current filters + */ + protected LinkedList filters = new LinkedList(); + + /** + * 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 /service/mychannel + * or it can be a wild card pattern like /service/app2/** + * @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 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 it = filters.iterator(); it.hasNext(); ) { + it.next().filter(msg); + } + imsgs[i] = msg; + } + //deliver it to the clients + for (Iterator 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 diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/ClientImpl.java b/modules/bayeux/java/org/apache/tomcat/bayeux/ClientImpl.java index 894f9efb0..bf355cbde 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/ClientImpl.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/ClientImpl.java @@ -1,279 +1,279 @@ -/* - * 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 EMPTY_LIST = new LinkedList(); - /** - * queued message for remote clients. - */ - protected LinkedList messages = null; - - /** - * - */ - protected Queue events = new LinkedList(); - - /** - * 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(); - } - - protected ClientImpl(String id, CometEvent event) { - this(id,false); - events = new ConcurrentLinkedQueue(); - 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 list = new ArrayList(); - for (int i=0; msgs!=null && i0) { - getListener().deliver(list.toArray(new Message[0])); - } - } else { - for (int i=0; msgs!=null && i 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 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 - } - -} +/* + * 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 EMPTY_LIST = new LinkedList(); + /** + * queued message for remote clients. + */ + protected LinkedList messages = null; + + /** + * + */ + protected Queue events = new LinkedList(); + + /** + * 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(); + } + + protected ClientImpl(String id, CometEvent event) { + this(id,false); + events = new ConcurrentLinkedQueue(); + 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 list = new ArrayList(); + for (int i=0; msgs!=null && i0) { + getListener().deliver(list.toArray(new Message[0])); + } + } else { + for (int i=0; msgs!=null && i 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 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 + } + +} diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/HttpError.java b/modules/bayeux/java/org/apache/tomcat/bayeux/HttpError.java index 55ff2c75f..b68865872 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/HttpError.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/HttpError.java @@ -1,43 +1,43 @@ -package org.apache.tomcat.bayeux; - -public class HttpError { - private int code; - private String status; - private Throwable cause; - public HttpError(int code, String status, Throwable cause) { - this.code = code; - this.status = status; - this.cause = cause; - } - - public void setCode(int code) { - this.code = code; - } - - public void setStatus(String status) { - this.status = status; - } - - public void setCause(Throwable exception) { - this.cause = exception; - } - - public int getCode() { - return code; - } - - public String getStatus() { - return status; - } - - public Throwable getCause() { - return cause; - } - - public String toString() { - if (cause != null) - return code + ":" + status + " - [" + cause + "]"; - else - return code + ":" + status; - } -} +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; + } +} diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/MessageImpl.java b/modules/bayeux/java/org/apache/tomcat/bayeux/MessageImpl.java index 53d5342d2..8a3a24f98 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/MessageImpl.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/MessageImpl.java @@ -1,80 +1,80 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tomcat.bayeux; - -import java.util.HashMap; - -import org.apache.cometd.bayeux.Channel; -import org.apache.cometd.bayeux.Client; -import org.apache.cometd.bayeux.Message; - -public class MessageImpl extends HashMap 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; - } +/* + * 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 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 diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/RequestBase.java b/modules/bayeux/java/org/apache/tomcat/bayeux/RequestBase.java index e3c4000c8..9f6036eed 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/RequestBase.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/RequestBase.java @@ -1,259 +1,259 @@ -/* - * 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 ext = new LinkedHashMap (); - - - protected CometEvent event; - - protected HashMap 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 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 msgs = client.takeMessages(); - synchronized (event) { - try { - for (Iterator 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())); - } - -} +/* + * 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 ext = new LinkedHashMap (); + + + protected CometEvent event; + + protected HashMap 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 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 msgs = client.takeMessages(); + synchronized (event) { + try { + for (Iterator 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())); + } + +} diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/RequestFactory.java b/modules/bayeux/java/org/apache/tomcat/bayeux/RequestFactory.java index f2765e661..c61718032 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/RequestFactory.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/RequestFactory.java @@ -1,48 +1,48 @@ -/* - * 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); - } - } +/* + * 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 diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/TomcatBayeux.java b/modules/bayeux/java/org/apache/tomcat/bayeux/TomcatBayeux.java index efe226482..e7d33c05c 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/TomcatBayeux.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/TomcatBayeux.java @@ -1,176 +1,176 @@ -/* - * 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 clients = new HashMap(); - - /** - * a list of all active channels - */ - protected LinkedHashMap channels = new LinkedHashMap(); - - /** - * 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 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 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; - } - -} +/* + * 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 clients = new HashMap(); + + /** + * a list of all active channels + */ + protected LinkedHashMap channels = new LinkedHashMap(); + + /** + * 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 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 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; + } + +} diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaConnectRequest.java b/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaConnectRequest.java index baa4e8ffc..2eacdbc8b 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaConnectRequest.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaConnectRequest.java @@ -1,125 +1,125 @@ -/* - * 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 responseTemplate = new HashMap(); - - static { - responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_CONNECT); - responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE); - responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap()); - } - - 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)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; - } -} - +/* + * 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 responseTemplate = new HashMap(); + + static { + responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_CONNECT); + responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE); + responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap()); + } + + 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)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; + } +} + diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaDisconnectRequest.java b/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaDisconnectRequest.java index be840e9e0..b3dde9400 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaDisconnectRequest.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaDisconnectRequest.java @@ -1,105 +1,105 @@ -/* - * 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 responseTemplate = new HashMap(); - - static { - responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_DISCONNECT); - responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE); - responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap()); - } - - 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)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; - } -} - +/* + * 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 responseTemplate = new HashMap(); + + static { + responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_DISCONNECT); + responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE); + responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap()); + } + + 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)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; + } +} + diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaHandshakeRequest.java b/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaHandshakeRequest.java index bd38b9e46..0883ae9fc 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaHandshakeRequest.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaHandshakeRequest.java @@ -1,116 +1,116 @@ -/* - * 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 responseTemplate = new HashMap(); - - 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()); - } - - 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)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; - } -} - +/* + * 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 responseTemplate = new HashMap(); + + 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()); + } + + 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)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; + } +} + diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaSubscribeRequest.java b/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaSubscribeRequest.java index 31994f3bb..b6af0b2d6 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaSubscribeRequest.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaSubscribeRequest.java @@ -1,130 +1,130 @@ -/* - * 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 responseTemplate = new HashMap(); - - static { - responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_SUBSCRIBE); - responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE); - responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap()); - } - - 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)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 channels = getTomcatBayeux().getChannels(); - Iterator 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; - } -} - +/* + * 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 responseTemplate = new HashMap(); + + static { + responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_SUBSCRIBE); + responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE); + responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap()); + } + + 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)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 channels = getTomcatBayeux().getChannels(); + Iterator 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; + } +} + diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaUnsubscribeRequest.java b/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaUnsubscribeRequest.java index 69a57cd01..e8b3e163d 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaUnsubscribeRequest.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaUnsubscribeRequest.java @@ -1,130 +1,130 @@ -/* - * 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 responseTemplate = new HashMap(); - - static { - responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_UNSUBSCRIBE); - responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE); - responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap()); - } - - 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)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 channels = getTomcatBayeux().getChannels(); - Iterator 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; - } -} - +/* + * 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 responseTemplate = new HashMap(); + + static { + responseTemplate.put(Bayeux.CHANNEL_FIELD,Bayeux.META_UNSUBSCRIBE); + responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE); + responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap()); + } + + 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)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 channels = getTomcatBayeux().getChannels(); + Iterator 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; + } +} + diff --git a/modules/bayeux/java/org/apache/tomcat/bayeux/request/PublishRequest.java b/modules/bayeux/java/org/apache/tomcat/bayeux/request/PublishRequest.java index fcf956ce7..017d1812c 100644 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/request/PublishRequest.java +++ b/modules/bayeux/java/org/apache/tomcat/bayeux/request/PublishRequest.java @@ -1,140 +1,140 @@ -/* - * 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 responseTemplate = new HashMap(); - - static { - responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE); - responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap()); - } - - 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)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; - } -} - +/* + * 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 responseTemplate = new HashMap(); + + static { + responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE); + responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap()); + } + + 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)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; + } +} + diff --git a/modules/bayeux/test/org/apache/cometd/bayeux/samples/BayeuxStockTicker.java b/modules/bayeux/test/org/apache/cometd/bayeux/samples/BayeuxStockTicker.java index 5f61d293b..f99c38e25 100644 --- a/modules/bayeux/test/org/apache/cometd/bayeux/samples/BayeuxStockTicker.java +++ b/modules/bayeux/test/org/apache/cometd/bayeux/samples/BayeuxStockTicker.java @@ -1,215 +1,215 @@ -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 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; - } - } - +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 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 diff --git a/modules/bayeux/test/org/apache/cometd/bayeux/samples/EchoChatClient.java b/modules/bayeux/test/org/apache/cometd/bayeux/samples/EchoChatClient.java index 6f6ca8e17..5fd48701c 100644 --- a/modules/bayeux/test/org/apache/cometd/bayeux/samples/EchoChatClient.java +++ b/modules/bayeux/test/org/apache/cometd/bayeux/samples/EchoChatClient.java @@ -1,101 +1,101 @@ -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 - - Cometd Test WebApp - - - cometd - org.apache.tomcat.bayeux.BayeuxServlet - - timeout - 120000000 - - - reconnectInterval - 250 - - 1 - - - - cometd - /cometd/* - - - - org.apache.cometd.bayeux.samples.EchoChatClient - - - org.apache.cometd.bayeux.samples.BayeuxStockTicker - - - - - + + + Cometd Test WebApp + + + cometd + org.apache.tomcat.bayeux.BayeuxServlet + + timeout + 120000000 + + + reconnectInterval + 250 + + 1 + + + + cometd + /cometd/* + + + + org.apache.cometd.bayeux.samples.EchoChatClient + + + org.apache.cometd.bayeux.samples.BayeuxStockTicker + + + + + diff --git a/modules/bayeux/webapps/cometd/examples/simplechat/ticker.html b/modules/bayeux/webapps/cometd/examples/simplechat/ticker.html index 3a884471f..64ce47abe 100644 --- a/modules/bayeux/webapps/cometd/examples/simplechat/ticker.html +++ b/modules/bayeux/webapps/cometd/examples/simplechat/ticker.html @@ -1,128 +1,128 @@ - - - - -Bayeux Stock Ticker - - - - - - -

    Bayeux Stock Ticker

    -

     

    -

    - - - - - - - - - - - - - - - - - - - - - - - - -
    SYMBOLPRICELAST CHANGESUBSCRIBE
    SPRG
    GOOG
    YHOO
    -

    - + + + + +Bayeux Stock Ticker + + + + + + +

    Bayeux Stock Ticker

    +

     

    +

    + + + + + + + + + + + + + + + + + + + + + + + + +
    SYMBOLPRICELAST CHANGESUBSCRIBE
    SPRG
    GOOG
    YHOO
    +

    + \ No newline at end of file diff --git a/modules/bayeux/webapps/cometd/index.html b/modules/bayeux/webapps/cometd/index.html index 9a7d6d752..d2783136a 100644 --- a/modules/bayeux/webapps/cometd/index.html +++ b/modules/bayeux/webapps/cometd/index.html @@ -1,7 +1,7 @@ - -

    Cometd demo

    - -

    -Try the Simple Chat Demo.
    -Try the Stock Ticker Demo.
    -

    + +

    Cometd demo

    + +

    +Try the Simple Chat Demo.
    +Try the Stock Ticker Demo.
    +

    diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java index 93653eefb..0daa29550 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java @@ -1,135 +1,135 @@ -/* - * 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> perPoolStats = - new IdentityHashMap>(); - - protected HashMap 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) && ithreshold) { - 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() { - @Override - protected boolean removeEldestEntry(Entry eldest) { - return size()>maxQueries; - } - - }; - } - } -} +/* + * 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> perPoolStats = + new IdentityHashMap>(); + + protected HashMap 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) && ithreshold) { + 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() { + @Override + protected boolean removeEldestEntry(Entry eldest) { + return size()>maxQueries; + } + + }; + } + } +} diff --git a/res/META-INF/LICENSE b/res/META-INF/LICENSE index 75b52484e..d64569567 100644 --- a/res/META-INF/LICENSE +++ b/res/META-INF/LICENSE @@ -1,202 +1,202 @@ - - 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. + + 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. diff --git a/res/META-INF/NOTICE b/res/META-INF/NOTICE index 453920593..3f59805ce 100644 --- a/res/META-INF/NOTICE +++ b/res/META-INF/NOTICE @@ -1,2 +1,2 @@ -This product includes software developed by -The Apache Software Foundation (http://www.apache.org/). +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). diff --git a/res/procrun/amd64/tomcat6.exe b/res/procrun/amd64/tomcat6.exe old mode 100755 new mode 100644 diff --git a/res/procrun/amd64/tomcat6w.exe b/res/procrun/amd64/tomcat6w.exe old mode 100755 new mode 100644 diff --git a/res/procrun/ia64/tomcat6.exe b/res/procrun/ia64/tomcat6.exe old mode 100755 new mode 100644 diff --git a/res/procrun/ia64/tomcat6w.exe b/res/procrun/ia64/tomcat6w.exe old mode 100755 new mode 100644 diff --git a/res/procrun/tomcat6.exe b/res/procrun/tomcat6.exe old mode 100755 new mode 100644 diff --git a/res/procrun/tomcat6w.exe b/res/procrun/tomcat6w.exe old mode 100755 new mode 100644