diff --git a/build.properties.default b/build.properties.default index 355a38a5975c..d503c8d3f723 100644 --- a/build.properties.default +++ b/build.properties.default @@ -29,7 +29,7 @@ version.major=7 version.minor=0 version.build=4 version.patch=0 -version.suffix=-dev +version.suffix= # ----- Build control flags ----- # Note enabling validation uses Checkstyle which is LGPL licensed diff --git a/modules/bayeux/.classpath b/modules/bayeux/.classpath deleted file mode 100644 index 889b127a83b4..000000000000 --- a/modules/bayeux/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/modules/bayeux/.project b/modules/bayeux/.project deleted file mode 100644 index 872599e020b2..000000000000 --- a/modules/bayeux/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - tomcat-bayeux - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/modules/bayeux/build.xml b/modules/bayeux/build.xml deleted file mode 100644 index d4af122215d6..000000000000 --- a/modules/bayeux/build.xml +++ /dev/null @@ -1,230 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - You've built the Tomcat Bayeux libraries, simply add the following libraries to your CATALINA_HOME/lib directory: - ${cometd-api.jar} - ${tomcat-bayeux.jar} - ${tomcat.extras}/${json-lib.jar} -To run the sample application, copy the following applications into your CATALINA_BASE/webapps directory - ${cometd.war} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/modules/bayeux/java/org/apache/cometd/bayeux/Bayeux.java b/modules/bayeux/java/org/apache/cometd/bayeux/Bayeux.java deleted file mode 100644 index 3ca4fe701ec5..000000000000 --- a/modules/bayeux/java/org/apache/cometd/bayeux/Bayeux.java +++ /dev/null @@ -1,242 +0,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.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 deleted file mode 100644 index 468b5e181811..000000000000 --- a/modules/bayeux/java/org/apache/cometd/bayeux/Channel.java +++ /dev/null @@ -1,103 +0,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.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 deleted file mode 100644 index 32e8773b09e1..000000000000 --- a/modules/bayeux/java/org/apache/cometd/bayeux/Client.java +++ /dev/null @@ -1,91 +0,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.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 deleted file mode 100644 index abc964e21edf..000000000000 --- a/modules/bayeux/java/org/apache/cometd/bayeux/DataFilter.java +++ /dev/null @@ -1,38 +0,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.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 deleted file mode 100644 index 9cd86d014f35..000000000000 --- a/modules/bayeux/java/org/apache/cometd/bayeux/Listener.java +++ /dev/null @@ -1,45 +0,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.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 deleted file mode 100644 index 12b525bf9853..000000000000 --- a/modules/bayeux/java/org/apache/cometd/bayeux/Message.java +++ /dev/null @@ -1,68 +0,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.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 deleted file mode 100644 index 55e71586d046..000000000000 --- a/modules/bayeux/java/org/apache/cometd/bayeux/SecurityPolicy.java +++ /dev/null @@ -1,28 +0,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.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 deleted file mode 100644 index 6d96bb362388..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxException.java +++ /dev/null @@ -1,39 +0,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; -/** - * - * @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 deleted file mode 100644 index 6dd9b33ff8c6..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxRequest.java +++ /dev/null @@ -1,54 +0,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; - -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 deleted file mode 100644 index d53c80aad19c..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/BayeuxServlet.java +++ /dev/null @@ -1,236 +0,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; - -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.comet.CometEvent; -import org.apache.catalina.comet.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 - */ - private static final 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 deleted file mode 100644 index 353af6c8cb65..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/ChannelImpl.java +++ /dev/null @@ -1,189 +0,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; - -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 { - - private static final 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() { - StringBuilder buf = new StringBuilder(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 deleted file mode 100644 index 4a9de3c39543..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/ClientImpl.java +++ /dev/null @@ -1,279 +0,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; - -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.comet.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"; - - private static final 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() { - StringBuilder buf = new StringBuilder(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 deleted file mode 100644 index 57d5636ea854..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/HttpError.java +++ /dev/null @@ -1,60 +0,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; - -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 deleted file mode 100644 index 8a3a24f98387..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/MessageImpl.java +++ /dev/null @@ -1,80 +0,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; - -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 deleted file mode 100644 index 0daa2cc49114..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/RequestBase.java +++ /dev/null @@ -1,259 +0,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; - -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.comet.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; - - private static final 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 deleted file mode 100644 index 203d94dc1a50..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/RequestFactory.java +++ /dev/null @@ -1,48 +0,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; - -import org.json.JSONObject; -import org.apache.tomcat.bayeux.request.MetaHandshakeRequest; -import org.apache.catalina.comet.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 deleted file mode 100644 index d6f17f72c600..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/TomcatBayeux.java +++ /dev/null @@ -1,176 +0,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; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; - -import org.apache.catalina.comet.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.values().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 deleted file mode 100644 index f2f509af0ab9..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaConnectRequest.java +++ /dev/null @@ -1,125 +0,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.comet.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 deleted file mode 100644 index 78bf7b47dc5e..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaDisconnectRequest.java +++ /dev/null @@ -1,105 +0,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.comet.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 deleted file mode 100644 index 593cfef0ffd3..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaHandshakeRequest.java +++ /dev/null @@ -1,116 +0,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.comet.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 deleted file mode 100644 index af42d097cee7..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaSubscribeRequest.java +++ /dev/null @@ -1,130 +0,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.comet.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 deleted file mode 100644 index 62e4c8f4f1a9..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/request/MetaUnsubscribeRequest.java +++ /dev/null @@ -1,130 +0,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.comet.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 deleted file mode 100644 index 0b1a03472be9..000000000000 --- a/modules/bayeux/java/org/apache/tomcat/bayeux/request/PublishRequest.java +++ /dev/null @@ -1,142 +0,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.comet.CometEvent; -import org.apache.tomcat.bayeux.HttpError; -import org.apache.tomcat.bayeux.BayeuxException; -import org.apache.tomcat.bayeux.ChannelImpl; -import org.apache.tomcat.bayeux.ClientImpl; -import org.apache.tomcat.bayeux.MessageImpl; -import org.apache.tomcat.bayeux.RequestBase; -import org.apache.tomcat.bayeux.TomcatBayeux; -import org.json.JSONException; -import org.json.JSONObject; -import org.apache.cometd.bayeux.Bayeux; -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; - -/****************************************************************************** - * Handshake request Bayeux message. - * - * @author Guy A. Molinari - * @author Filip Hanik - * @version 1.0 - * - */ -public class PublishRequest extends RequestBase { - - private static final Log log = LogFactory.getLog(PublishRequest.class); - - protected static HashMap responseTemplate = new HashMap(); - - static { - responseTemplate.put(Bayeux.SUCCESSFUL_FIELD,Boolean.TRUE); - responseTemplate.put(Bayeux.ADVICE_FIELD, new HashMap()); - } - - JSONObject msgData = null; - - 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 - */ - @Override - 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. - */ - @Override - 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 deleted file mode 100644 index fbd19fdf3f46..000000000000 --- a/modules/bayeux/test/org/apache/cometd/bayeux/samples/BayeuxStockTicker.java +++ /dev/null @@ -1,232 +0,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.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("ASF", 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("Bayeux 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(){ - StringBuilder buf = new StringBuilder("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 deleted file mode 100644 index a4b38734b028..000000000000 --- a/modules/bayeux/test/org/apache/cometd/bayeux/samples/EchoChatClient.java +++ /dev/null @@ -1,118 +0,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.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 - - - - - diff --git a/modules/bayeux/webapps/cometd/examples/simplechat/cometdchat.htm b/modules/bayeux/webapps/cometd/examples/simplechat/cometdchat.htm deleted file mode 100644 index 0f30cad1be71..000000000000 --- a/modules/bayeux/webapps/cometd/examples/simplechat/cometdchat.htm +++ /dev/null @@ -1,130 +0,0 @@ - - -
    Comet Simple Chat Application - - - - - - - - -
    - -
    -
    -Screen name:  -
    Type a screen name and click the 'Connect' button -
    - -
    -
    -
    -
    Is my screen name
    -[ENTER] sends message
    -
    - - - diff --git a/modules/bayeux/webapps/cometd/examples/simplechat/ticker.html b/modules/bayeux/webapps/cometd/examples/simplechat/ticker.html deleted file mode 100644 index 501beddae90c..000000000000 --- a/modules/bayeux/webapps/cometd/examples/simplechat/ticker.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - -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 deleted file mode 100644 index f7f722ea136b..000000000000 --- a/modules/bayeux/webapps/cometd/index.html +++ /dev/null @@ -1,22 +0,0 @@ - -

    Cometd demo

    - -

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

    diff --git a/modules/jdbc-pool/.classpath b/modules/jdbc-pool/.classpath deleted file mode 100644 index 6983e0db613f..000000000000 --- a/modules/jdbc-pool/.classpath +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/modules/jdbc-pool/.project b/modules/jdbc-pool/.project deleted file mode 100644 index 207e70742da7..000000000000 --- a/modules/jdbc-pool/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - tomcat-jdbc-pool - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/modules/jdbc-pool/LICENSE b/modules/jdbc-pool/LICENSE deleted file mode 100644 index f49a4e16e68b..000000000000 --- a/modules/jdbc-pool/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - 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. \ No newline at end of file diff --git a/modules/jdbc-pool/NOTICE b/modules/jdbc-pool/NOTICE deleted file mode 100644 index c9cf69d09f25..000000000000 --- a/modules/jdbc-pool/NOTICE +++ /dev/null @@ -1,6 +0,0 @@ -Apache Tomcat JDBC Pool -Copyright 2008-2010 The Apache Software Foundation - -This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). - diff --git a/modules/jdbc-pool/build.properties.default b/modules/jdbc-pool/build.properties.default deleted file mode 100644 index 141cd2ecf776..000000000000 --- a/modules/jdbc-pool/build.properties.default +++ /dev/null @@ -1,101 +0,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. -# ----------------------------------------------------------------------------- -# build.properties.sample -# -# This is an example "build.properties" file, used to customize building -# Tomcat JDBC Pool for your local environment. It defines the location of all external -# modules that Tomcat JDBC Pool depends on. Copy this file to "build.properties" -# in the top-level source directory, and customize it as needed. -# -# $Id: build.properties.default 786496 2009-06-19 13:11:00Z markt $ -# ----------------------------------------------------------------------------- - -# ----- Vesion Control Flags ----- -version.major=1 -version.minor=0 -version.build=9 -version.patch=0 -version.suffix= - -# ----- Default Base Path for Dependent Packages ----- -# Please note this path must be absolute, not relative, -# as it is referenced with different working directory -# contexts by the various build scripts. -base.path=${basedir}/includes - -compile.source=1.5 -compile.target=1.5 -compile.debug=true - -# ----- Settings for Junit test database. - -# Common settings -testdb.username=root -testdb.password=password - -# H2 -testdb.url=jdbc:h2:~/.h2/test;QUERY_TIMEOUT=0;DB_CLOSE_ON_EXIT=TRUE;LOCK_TIMEOUT=50000;DEFAULT_LOCK_TIMEOUT=50000 -testdb.driverClassName=org.h2.Driver -testdb.validationQuery=SELECT 1 - -# MySQL -#testdb.url=jdbc:mysql://localhost:3306/mysql?autoReconnect=true -#testdb.driverClassName=com.mysql.jdbc.Driver -#testdb.validationQuery=SELECT 1 - -# Derby -#testdb.url=jdbc:derby:derbyDB;create=true -#testdb.driverClassName=org.apache.derby.jdbc.EmbeddedDriver -#testdb.validationQuery=VALUES 1 - -# ----- JUnit Unit Test Suite, version 3.7 or later ----- -junit.home=${base.path}/junit3.8.2 -junit.lib=${junit.home} -junit.jar=${junit.lib}/junit.jar -junit.loc=http://downloads.sourceforge.net/junit/junit3.8.2.zip - -c3p0.home=${base.path}/c3p0-0.9.1.2 -c3p0.jar=${c3p0.home}/lib/c3p0-0.9.1.2.jar -c3p0.loc=http://superb-east.dl.sourceforge.net/sourceforge/c3p0/c3p0-0.9.1.2.bin.zip - -mysql.home=${base.path}/mysql-connector-java-5.1.12 -mysql.jar=${mysql.home}/mysql-connector-java-5.1.12-bin.jar -mysql.loc=http://mysql.he.net/Downloads/Connector-J/mysql-connector-java-5.1.12.zip - -dbcp.home=${base.path}/commons-dbcp-1.3 -dbcp.jar=${dbcp.home}/commons-dbcp-1.3.jar -dbcp.loc=http://archive.apache.org/dist/commons/dbcp/binaries/commons-dbcp-1.3.zip - -tomcat.version=6.0.29 -tomcat.home=${base.path}/apache-tomcat-${tomcat.version} -tomcat.dbcp.jar=${tomcat.home}/lib/tomcat-dbcp.jar -tomcat.juli.jar=${tomcat.home}/bin/tomcat-juli.jar -tomcat.loc=http://archive.apache.org/dist/tomcat/tomcat-6/v${tomcat.version}/bin/apache-tomcat-${tomcat.version}.zip - -tomcat.project.loc=http://svn.apache.org/repos/asf/tomcat/trunk/webapps/docs/project.xml -tomcat.project.dest=${base.path}/project.xml - -tomcat.xsl.loc=http://svn.apache.org/repos/asf/tomcat/trunk/webapps/docs/tomcat-docs.xsl -tomcat.xsl.dest=${base.path}/tomcat-docs.xsl - -derby.home=${base.path}/db-derby-10.5.1.1-bin -derby.loc=http://archive.apache.org/dist/db/derby/db-derby-10.5.1.1/db-derby-10.5.1.1-bin.tar.gz -derby.jar=${derby.home}/lib/derby.jar - -h2.home=${base.path}/h2 -h2.loc=http://h2database.googlecode.com/files/h2-2010-02-19.zip -h2.jar=${h2.home}/bin/h2-1.2.129.jar diff --git a/modules/jdbc-pool/build.xml b/modules/jdbc-pool/build.xml deleted file mode 100644 index 0e8255004518..000000000000 --- a/modules/jdbc-pool/build.xml +++ /dev/null @@ -1,499 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Creating test table for test purposes. - - - - - - - - - - - - - - - Performance and fairness tests. - - - - - - - - - - - - - - - - - Functional tests. - - - - - - - - - - - - - - - - - - - - - - - - - Testing:${test} - - - - - - - - - - - - - - - - - - diff --git a/modules/jdbc-pool/doc/changelog.xml b/modules/jdbc-pool/doc/changelog.xml deleted file mode 100644 index d7401a7e691e..000000000000 --- a/modules/jdbc-pool/doc/changelog.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - -]> - - - &project; - - - Filip Hanik - Changelog - - - -
    - - - 997321 Ensure threads borrowing connections do not - get stuck waiting for a new connection if a connection is released in - another thread. (markt) - 995432 Make interceptor class names, property names - and property values tolerant of whitespace by trimming the values before - use. (markt) - 995091 49831 Make sure pooled XAConnections are - closed when the connection pool shuts down. Patch provided by Daniel - Mikusa. (markt) - 995087 Code clean-up. Remove some unused code. (markt) - - 995083 Update to Tomcat 6.0.29 (for JULI). (markt) - - 992409 Code clean-up. Reduce sequences of three or more - blank lines to two blank lines. (markt) - 952811, 995095 48814 Add Validator - interface and allow users to configure a Validator class name. Patch - provided by Matt Passell. (markt) - 948073 Code clean-up. Remove unused imports. (markt) - - 943434 49224 Only try setting the username and - password if they are non-null. Patch provided by Matt Passell. (markt) - - 943032 49269 Set maxIdle to maxActive by - default to prevent warning on start when maxIdle > maxActive. Patch - provided by Matt Passell. (markt) - 940574 49241 Don't ignore the - suspectTimeout property. (fhanik) - 939320 Fix svn:keywords for property replacement. - (kkolinko) - 931550, 934651, 934677 Add a - statement cache. (fhanik) - 919076 Improve XA support. (fhanik) - 915940 48392 Add an interceptor to wrap - Statements and ResultSets to prevent access to the physical connection. - (fhanik) - 912026 Call setTransactionIsolation() before - anything else as some drivers require this to be the first call. (fhanik) - - 900017 Update Javadoc for XADataSource. (kkolinko) - - - -
    -
    - - - 720253 Document how to use interceptors - 717972 Added an interceptor that will clean up non closed statements when a connection is returned to the pool. (org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer) - 713763 Improve connection state handling - 713763 Improve connection state handling - - -
    - -
    diff --git a/modules/jdbc-pool/doc/jdbc-pool.xml b/modules/jdbc-pool/doc/jdbc-pool.xml deleted file mode 100644 index 3b2b65d2431f..000000000000 --- a/modules/jdbc-pool/doc/jdbc-pool.xml +++ /dev/null @@ -1,787 +0,0 @@ - - - -]> - - - &project; - - - Filip Hanik - The Tomcat JDBC Connection Pool - - - - - -
    - -

    The JDBC Connection Pool org.apache.tomcat.jdbc.pool - is a replacement or an alternative to the commons-dbcp - connection pool.

    - -

    So why do we need a new connection pool?

    - -

    Here are a few of the reasons: -

      -
    1. commons-dbcp is single threaded, in order to be thread safe commons-dbcp locks the entire pool, even during query validation.
    2. -
    3. commons-dbcp is slow - as the number of logical CPUs grow, the performance suffers, the above point shows that there is not support for high concurrency - Even with the enormous optimizations of the synchronized statement in Java 6, commons-dbcp still suffers in speed and concurrency.
    4. -
    5. commons-dbcp is complex, over 60 classes. tomcat-jdbc-pool, core is 8 classes, hence modifications for future requirement will require - much less changes. This is all you need to run the connection pool itself, the rest is gravy.
    6. -
    7. commons-dbcp uses static interfaces. This means you can't compile it with JDK 1.6, or if you run on JDK 1.6/1.7 you will get - NoSuchMethodException for all the methods not implemented, even if the driver supports it.
    8. -
    9. The commons-dbcp has become fairly stagnant. Sparse updates, releases, and new feature support.
    10. -
    11. It's not worth rewriting over 60 classes, when something as a connection pool can be accomplished with as a much simpler implementation.
    12. -
    13. Tomcat jdbc pool implements a fairness option not available in commons-dbcp and still performs faster than commons-dbcp
    14. -
    15. Tomcat jdbc pool implements the ability retrieve a connection asynchronously, without adding additional threads to the library itself
    16. -
    17. Tomcat jdbc pool is a Tomcat module, it depends on Tomcat JULI, a simplified logging framework used in Tomcat.
    18. -
    19. Retrieve the underlying connection using the javax.sql.PooledConnection interface.
    20. -
    21. Starvation proof. If a pool is empty, and threads are waiting for a connection, when a connection is returned, - the pool will awake the correct thread waiting. Most pools will simply starve.
    22. -
    -

    - -

    Features added over other connection pool implementations -

      -
    1. Support for highly concurrent environments and multi core/cpu systems.
    2. -
    3. Dynamic implementation of interface, will support java.sql and javax.sql interfaces for - your runtime environment (as long as your JDBC driver does the same), even when compiled with a lower version of the JDK.
    4. -
    5. Validation intervals - we don't have to validate every single time we use the connection, we can do this - when we borrow or return the connection, just not more frequent than an interval we can configure.
    6. -
    7. Run-Once query, a configurable query that will be run only once, when the connection to the database is established. - Very useful to setup session settings, that you want to exist during the entire time the connection is established.
    8. -
    9. Ability to configure custom interceptors. - This allows you to write custom interceptors to enhance the functionality. You can use interceptors to gather query stats, - cache session states, reconnect the connection upon failures, retry queries, cache query results, and so on. - Your options are endless and the interceptors are dynamic, not tied to a JDK version of a java.sql/javax.sql interface.
    10. -
    11. High performance - we will show some differences in performance later on
    12. -
    13. Extremely simple, due to the very simplified implementation, the line count and source file count are very low, compare with c3p0 - that has over 200 source files(last time we checked), Tomcat jdbc has a core of 8 files, the connection pool itself is about half - that. As bugs may occur, they will be faster to track down, and easier to fix. Complexity reduction has been a focus from inception.
    14. -
    15. Asynchronous connection retrieval - you can queue your request for a connection and receive a Future<Connection> back.
    16. -
    17. Better idle connection handling. Instead of closing connections directly, it can still pool connections and sizes the idle pool with a smarter algorithm.
    18. -
    19. You can decide at what moment connections are considered abandoned, is it when the pool is full, or directly at a timeout - by specifying a pool usage threshold. -
    20. -
    21. The abandon connection timer will reset upon a statement/query activity. Allowing a connections that is in use for a long time to not timeout. - This is achieved using the ResetAbandonedTimer -
    22. -
    23. Close connections after they have been connected for a certain time. Age based close upon return to the pool. -
    24. -
    25. Get JMX notifications and log entries when connections are suspected for being abandoned. This is similar to - the removeAbandonedTimeout but it doesn't take any action, only reports the information. - This is achieved using the suspectTimeout attribute.
    26. -
    27. Connections can be retrieved from a java.sql.Driver, javax.sql.DataSource or javax.sql.XADataSource - This is achieved using the dataSource and dataSourceJNDI attributes.
    28. -
    29. XA connection support
    30. -
    -

    - - -
    -
    -

    - Usage of the Tomcat connection pool has been made to be as simple as possible, for those of you that are familiar with commons-dbcp, the - transition will be very simple. Moving from other connection pools is also fairly straight forward. -

    - -

    The Tomcat connection pool offers a few additional features over what most other pools let you do:

    -
      -
    • initSQL - the ability to run a SQL statement exactly once, when the connection is created
    • -
    • validationInterval - in addition to running validations on connections, avoid running them too frequently.
    • -
    • jdbcInterceptors - flexible and pluggable interceptors to create any customizations around the pool, - the query execution and the result set handling. More on this in the advanced section.
    • -
    • fairQueue - Set the fair flag to true to achieve thread fairness or to use asynchronous connection retrieval
    • -
    -
    - -

    - The Tomcat Connection pool is configured as a resource described in The Tomcat JDBC documentation - With the only difference being that you have to specify the factory attribute and set the value to - org.apache.tomcat.jdbc.pool.DataSourceFactory -

    -
    - -

    - The connection pool only has another dependency, and that is on tomcat-juli.jar. - To configure the pool in a stand alone project using bean instantiation, the bean to instantiate is - org.apache.tomcat.jdbc.pool.DataSource. The same attributes (documented below) as you use to configure a connection - pool as a JNDI resource, are used to configure a data source as a bean. -

    -
    - -

    - The connection pool object exposes an MBean that can be registered. - In order for the connection pool object to create the MBean, the flag jmxEnabled has to be set to true. - This doesn't imply that the pool will be registered with an MBean server, merely that the MBean is created. - In a container like Tomcat, Tomcat itself registers the DataSource with the MBean server, the - org.apache.tomcat.jdbc.pool.DataSource object will then register the actual - connection pool MBean. - If you're running outside of a container, you can register the DataSource yourself under any object name you specify, - and it propagates the registration to the underlying pool. -

    -
    - -
    -
    -

    To provide a very simple switch to and from commons-dbcp and tomcat-jdbc-pool, - Most attributes are the same and have the same meaning.

    - - - -

    factory is required, and the value should be org.apache.tomcat.jdbc.pool.DataSourceFactory

    -
    - -

    Type should always be javax.sql.DataSource or javax.sql.XADataSource

    -

    Depending on the type a org.apache.tomcat.jdbc.pool.DataSource or a org.apache.tomcat.jdbc.pool.XADataSource will be created.

    -
    -
    -
    - - -

    These attributes are shared between commons-dbcp and tomcat-jdbc-pool, in some cases default values are different.

    - - - -

    (boolean) The default auto-commit state of connections created by this pool. If not set, default is JDBC driver default (If not set then the setAutoCommit method will not be called.)

    -
    - - -

    (boolean) The default read-only state of connections created by this pool. If not set then the setReadOnly method will not be called. (Some drivers don't support read only mode, ex: Informix)

    -
    - - -

    (String) The default TransactionIsolation state of connections created by this pool. One of the following: (see javadoc )
    - * NONE
    - * READ_COMMITTED
    - * READ_UNCOMMITTED
    - * REPEATABLE_READ
    - * SERIALIZABLE
    - If not set, the method will not be called and it defaults to the JDBC driver. -

    -
    - - -

    (String) The default catalog of connections created by this pool.

    -
    - - -

    (String) The fully qualified Java class name of the JDBC driver to be used. The driver has to be accessible - from the same classloader as tomcat-jdbc.jar -

    -
    - - -

    (String) The connection username to be passed to our JDBC driver to establish a connection. - Note, at this point, DataSource.getConnection(username,password) is not using the credentials passed into the method. -

    -
    - - -

    (String) The connection password to be passed to our JDBC driver to establish a connection. - Note, at this point, DataSource.getConnection(username,password) is not using the credentials passed into the method. -

    -
    - - -

    (int) The maximum number of active connections that can be allocated from this pool at the same time. - The default value is 100

    -
    - - -

    (int) The maximum number of connections that should be kept in the pool at all times. - Default value is maxActive:100 - Idle connections are checked periodically (if enabled) and - connections that been idle for longer than minEvictableIdleTimeMillis - will be released. (also see testWhileIdle)

    -
    - - -

    - (int) The minimum number of established connections that should be kept in the pool at all times. - The connection pool can shrink below this number if validation queries fail. - Default value is derived from initialSize:10 (also see testWhileIdle) -

    -
    - - -

    (int)The initial number of connections that are created when the pool is started. - Default value is 10

    -
    - - -

    (int) The maximum number of milliseconds that the pool will wait (when there are no available connections) - for a connection to be returned before throwing an exception. - Default value is 30000 (30 seconds)

    -
    - - -

    (boolean) The indication of whether objects will be validated before being borrowed from the pool. - If the object fails to validate, it will be dropped from the pool, and we will attempt to borrow another. - NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. - Default value is false - In order to have a more efficient validation, see validationInterval - Default value is false -

    -
    - - -

    (boolean) The indication of whether objects will be validated before being returned to the pool. - NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. - The default value is false. -

    -
    - - -

    (boolean) The indication of whether objects will be validated by the idle object evictor (if any). - If an object fails to validate, it will be dropped from the pool. - NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. - The default value is false and this property has to be set in order for the - pool cleaner/test thread is to run (also see timeBetweenEvictionRunsMillis) -

    -
    - - -

    (String) The SQL query that will be used to validate connections from this pool before returning them to the caller. - If specified, this query does not have to return any data, it just can't throw a SQLException. - The default value is null. - Example values are SELECT 1(mysql), select 1 from dual(oracle), SELECT 1(MS Sql Server) -

    -
    - - -

    (String) The name of a class which implements the - org.apache.tomcat.jdbc.pool.Validator interface and - provides a no-arg constructor (may be implicit). If specified, the - class will be used to create a Validator instance which is then used - instead of any validation query to validate connections. The default - value is null. An example value is - com.mycompany.project.SimpleValidator. -

    -
    - - -

    (int) The number of milliseconds to sleep between runs of the idle connection validation/cleaner thread. - This value should not be set under 1 second. It dictates how often we check for idle, abandoned connections, and how often - we validate idle connections. - The default value is 5000 (5 seconds).

    -
    - - -

    (int) Property not used in tomcat-jdbc-pool.

    -
    - - -

    (int) The minimum amount of time an object may sit idle in the pool before it is eligible for eviction. - The default value is 60000 (60 seconds).

    -
    - - -

    (boolean) Property not used. Access can be achieved by calling unwrap on the pooled connection. - see javax.sql.DataSource interface, or call getConnection through reflection or - or cast the object as javax.sql.PooledConnection

    -
    - - -

    (boolean) Flag to remove abandoned connections if they exceed the removeAbandonedTimout. - If set to true a connection is considered abandoned and eligible for removal if it has been in use - longer than the removeAbandonedTimeout Setting this to true can recover db connections from - applications that fail to close a connection. See also logAbandoned - The default value is false.

    -
    - - -

    (int) Timeout in seconds before an abandoned(in use) connection can be removed. - The default value is 60 (60 seconds). The value should be set to the longest running query your applications - might have.

    -
    - - -

    (boolean) Flag to log stack traces for application code which abandoned a Connection. - Logging of abandoned Connections adds overhead for every Connection borrow because a stack trace has to be generated. - The default value is false.

    -
    - - -

    (String) The connection properties that will be sent to our JDBC driver when establishing new connections. - Format of the string must be [propertyName=property;]* - NOTE - The "user" and "password" properties will be passed explicitly, so they do not need to be included here. - The default value is null.

    -
    - - -

    (boolean) Property not used. The default value is false.

    -
    - - -

    (int) Property not used. The default value is false.

    -
    - -
    - -
    - - - - - - -

    (String) A custom query to be run when a connection is first created. - The default value is null.

    -
    - - -

    (String) A semicolon separated list of classnames extending org.apache.tomcat.jdbc.pool.JdbcInterceptor class. - These interceptors will be inserted as an interceptor into the chain of operations on a java.sql.Connection object. - The default value is null.
    - Predefined interceptors:
    - org.apache.tomcat.jdbc.pool.interceptor.ConnectionState - keeps track of auto commit, read only, catalog and transaction isolation level.
    - org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer - keeps track of opened statements, and closes them when the connection is returned to the pool.
    -

    -
    - - -

    (long) avoid excess validation, only run validation at most at this frequency - time in milliseconds. - If a connection is due for validation, but has been validated previously within this interval, it will not be validated again. - The default value is 30000 (30 seconds).

    -
    - - -

    (boolean) Register the pool with JMX or not. - The default value is true.

    -
    - - -

    (boolean) Set to true if you wish that calls to getConnection should be treated - fairly in a true FIFO fashion. This uses the org.apache.tomcat.jdbc.pool.FairBlockingQueue - implementation for the list of the idle connections. The default value is true. - This flag is required when you want to use asynchronous connection retrieval.
    - Setting this flag ensures that threads receive connections in the order they arrive.
    - During performance tests, there is a very large difference in how locks - and lock waiting is implemented. When fairQueue=true> - there is a decision making process based on what operating system the system is running. - If the system is running on Linux (property os.name=Linux. - To disable this Linux specific behavior and still use the fair queue, simply add the property - org.apache.tomcat.jdbc.pool.FairBlockingQueue.ignoreOS=true to your system properties - before the connection pool classes are loaded. -

    -
    - - -

    (int) Connections that have been abandoned (timed out) wont get closed and reported up unless - the number of connections in use are above the percentage defined by abandonWhenPercentageFull. - The value should be between 0-100. - The default value is 0, which implies that connections are eligible for closure as soon - as removeAbandonedTimeout has been reached.

    -
    - - -

    (long) Time in milliseconds to keep this connection. When a connection is returned to the pool, - the pool will check to see if the now - time-when-connected > maxAge has been reached, - and if so, it closes the connection rather than returning it to the pool. - The default value is 0, which implies that connections will be left open and no age check - will be done upon returning the connection to the pool.

    -
    - - -

    (boolean) Set to true if you wish the ProxyConnection class to use String.equals and set to false - when you wish to use == when comparing method names. This property does not apply to added interceptors as those are configured individually. - The default value is true. -

    -
    - -

    (int) Timeout value in seconds. Default value is 0.
    - Similar to to the removeAbandonedTimeout value but instead of treating the connection - as abandoned, and potentially closing the connection, this simply logs the warning if - logAbandoned is set to true. If this value is equal or less than 0, no suspect - checking will be performed. Suspect checking only takes place if the timeout value is larger than 0 and - the connection was not abandoned or if abandon check is disabled. If a connection is suspect a WARN message gets - logged and a JMX notification gets sent once. -

    -
    - -

    (javax.sql.DataSource) -

    -
    - -

    (String) -

    -
    -
    -
    -
    -
    - -

    To see an example of how to use an interceptor, take a look at - org.apache.tomcat.jdbc.pool.interceptor.ConnectionState. - This simple interceptor is a cache of three attributes, transaction isolation level, auto commit and read only state, - in order for the system to avoid not needed roundtrips to the database. -

    -

    Further interceptors will be added to the core of the pool as the need arises. Contributions are always welcome!

    -

    Interceptors are of course not limited to just java.sql.Connection but can be used to wrap any - of the results from a method invokation as well. You could build query performance analyzer that provides JMX notifications when a - query is running longer than the expected time.

    -
    - -

    Configuring JDBC interceptors is done using the jdbcInterceptors property. - The property contains a list of semi colon separated class names. If the classname if not fully qualified it will be prefixed with the - org.apache.tomcat.jdbc.pool.interceptor. prefix.
    - Example:
    - - jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer" -
    - is the same as -
    - jdbcInterceptors="ConnectionState;StatementFinalizer" -

    - Interceptors can have properties as well. These would be configured within the paranthesis of the class names. - Example:
    - - jdbcInterceptors="ConnectionState;StatementFinalizer(useEquals=true)" -
    -

    -
    - -

    Abstract base class for all interceptors, can not be instantiated.

    - - -

    (boolean) Set to true if you wish the ProxyConnection class to use String.equals and set to false - when you wish to use == when comparing method names. - The default value is true. -

    -
    -
    -
    - -

    Caches the connection for the following attributes autoCommit, readOnly, - transactionIsolation and catalog. - It is a performance enhancement to avoid roundtrip to the database when getters are called or setters are called with an already set value. -

    - - -
    - -

    Keeps track of all statements created using createStatement, prepareStatement or prepareCall - and closes these statements when the connection is returned to the pool. -

    - - -
    - -

    See 48392. Interceptor to wrap statements and result sets in order to prevent access to the actual connection - using the methods ResultSet.getStatement().getConnection() and Statement.getConnection() -

    - - -
    - -

    Keeps track of query performance and issues log entries when queries exceed a time threshold of fail. - The log level used is WARN -

    - - -

    (int as String) The number of milliseconds a query has to exceed before issuing a log alert. - The default value is 1000 milliseconds. -

    -
    - -

    (int as String) The maximum number of queries to keep track of in order to preserve memory space - The default value is 1000. -

    -
    -
    -
    - -

    Extends the SlowQueryReport and in addition to log entries it issues JMX notification - for monitoring tools to react to. Inherits all the attributes from its parent class. - This class uses Tomcat's JMX engine so it wont work outside of the Tomcat container. - By default, JMX notifications are sent through the ConnectionPool mbean if it is enabled. - The SlowQueryReportJmx can also register an MBean if notifyPool=false -

    - - -

    (boolean as String) Set to false if you want JMX notifications to go to the SlowQueryReportJmx MBean - The default value is true. -

    -
    -
    -
    - -

    - The abandoned timer starts when a connection is checked out from the pool. - This means if you have a 30second timeout and run 10x10second queries using the connection - it will be marked abandoned and potentially reclaimed depending on the abandonWhenPercentageFull - attribute. - Using this interceptor it will reset the checkout timer every time you perform an operation on the connection or execute a - query successfully. -

    - - -
    -
    - -
    -

    Other examples of Tomcat configuration for JDBC usage can be found in the Tomcat documentation.

    - -

    Here is a simple example of how to create and use a data source.

    - - import java.sql.Connection; - import java.sql.ResultSet; - import java.sql.Statement; - - import org.apache.tomcat.jdbc.pool.DataSource; - import org.apache.tomcat.jdbc.pool.PoolProperties; - - public class SimplePOJOExample { - - public static void main(String[] args) throws Exception { - PoolProperties p = new PoolProperties(); - p.setUrl("jdbc:mysql://localhost:3306/mysql"); - p.setDriverClassName("com.mysql.jdbc.Driver"); - p.setUsername("root"); - p.setPassword("password"); - p.setJmxEnabled(true); - p.setTestWhileIdle(false); - p.setTestOnBorrow(true); - p.setValidationQuery("SELECT 1"); - p.setTestOnReturn(false); - p.setValidationInterval(30000); - p.setTimeBetweenEvictionRunsMillis(30000); - p.setMaxActive(100); - p.setInitialSize(10); - p.setMaxWait(10000); - p.setRemoveAbandonedTimeout(60); - p.setMinEvictableIdleTimeMillis(30000); - p.setMinIdle(10); - p.setLogAbandoned(true); - p.setRemoveAbandoned(true); - p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+ - "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"); - DataSource datasource = new DataSource(); - datasource.setPoolProperties(p); - - Connection con = null; - try { - con = datasource.getConnection(); - Statement st = con.createStatement(); - ResultSet rs = st.executeQuery("select * from user"); - int cnt = 1; - while (rs.next()) { - System.out.println((cnt++)+". Host:" +rs.getString("Host")+ - " User:"+rs.getString("User")+" Password:"+rs.getString("Password")); - } - rs.close(); - st.close(); - } finally { - if (con!=null) try {con.close();}catch (Exception ignore) {} - } - } - - } - -
    - -

    And here is an example on how to configure a resource for JNDI lookups

    - - <Resource name="jdbc/TestDB" - auth="Container" - type="javax.sql.DataSource" - factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" - testWhileIdle="true" - testOnBorrow="true" - testOnReturn="false" - validationQuery="SELECT 1" - validationInterval="30000" - timeBetweenEvictionRunsMillis="30000" - maxActive="100" - minIdle="10" - maxWait="10000" - initialSize="10" - removeAbandonedTimeout="60" - removeAbandoned="true" - logAbandoned="true" - minEvictableIdleTimeMillis="30000" - jmxEnabled="true" - jdbcInterceptors= -"org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer" - username="root" - password="password" - driverClassName="com.mysql.jdbc.Driver" - url="jdbc:mysql://localhost:3306/mysql"/> - - - - -
    - -

    The Tomcat JDBC connection pool supports asynchronous connection retrieval without adding additional threads to the - pool library. It does this by adding a method to the data source called Future<Connection> getConnectionAsync(). - In order to use the async retrieval, two conditions must be met:
    - 1. You must configure the fairQueue property to be true.
    - 2. You will have to cast the data source to org.apache.tomcat.jdbc.pool.DataSource
    - An example of using the async feature is show below. - - - Connection con = null; - try { - Future<Connection> future = datasource.getConnectionAsync(); - while (!future.isDone()) { - System.out.println("Connection is not yet available. Do some background work"); - try { - Thread.sleep(100); //simulate work - }catch (InterruptedException x) { - Thread.currentThread().interrupted(); - } - } - con = future.get(); //should return instantly - Statement st = con.createStatement(); - ResultSet rs = st.executeQuery("select * from user"); - -

    -
    - -

    Interceptors are a powerful way to enable, disable or modify functionality on a specific connection or its sub components. - There are many different use cases for when interceptors are useful. By default, and for performance reasons, the connection pool is stateless. - The only state the pool itself inserts are defaultAutoCommit, defaultReadOnly, defaultTransactionIsolation, defaultCatalog if - these are set. These 4 properties are only set upon connection creation. Should these properties be modified during the usage of the connection, - the pool itself will not reset them.

    -

    An interceptor has to extend the org.apache.tomcat.jdbc.pool.JdbcInterceptor class. This class is fairly simple, - You will need to have a no arg constructor

    - - - public JdbcInterceptor() { - } - -

    - When a connection is borrowed from the pool, the interceptor can initialize or in some other way react to the event by implementing the - - - public abstract void reset(ConnectionPool parent, PooledConnection con); - - method. This method gets called with two parameters, a reference to the connection pool itself ConnectionPool parent - and a reference to the underlying connection PooledConnection con. -

    -

    - When a method on the java.sql.Connection object is invoked, it will cause the - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable - - method to get invoked. The Method method is the actual method invoked, and Object[] args are the arguments. - To look at a very simple example, where we demonstrate how to make the invokation to java.sql.Connection.close() a noop - if the connection has been closed - - - if (CLOSE_VAL==method.getName()) { - if (isClosed()) return null; //noop for already closed. - } - return super.invoke(proxy,method,args); - - There is an observation being made. It is the comparison of the method name. One way to do this would be to do - "close".equals(method.getName()). - Above we see a direct reference comparison between the method name and static final String reference. - According to the JVM spec, method names and static final String end up in a shared constant pool, so the reference comparison should work. - One could of course do this as well: - - - if (compare(CLOSE_VAL,method)) { - if (isClosed()) return null; //noop for already closed. - } - return super.invoke(proxy,method,args); - - The compare(String,Method) will use the useEquals flag on an interceptor and do either reference comparison or - a string value comparison when the useEquals=true flag is set. -

    -

    Pool start/stop
    - When the connection pool is started or closed, you can be notifed. You will only be notified once per interceptor class - even though it is an instance method. and you will be notified using an interceptor currently not attached to a pool. - - public void poolStarted(ConnectionPool pool) { - } - - public void poolClosed(ConnectionPool pool) { - } - - When overriding these methods, don't forget to call super if you are extending a class other than JdbcInterceptor -

    -

    Configuring interceptors
    - Interceptors are configured using the jdbcInterceptors property or the setJdbcInterceptors method. - An interceptor can have properties, and would be configured like this - - String jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState(useEquals=true,fast=yes)" - -

    -

    Interceptor properties
    - Since interceptors can have properties, you need to be able to read the values of these properties within your - interceptor. Taking an example like the one above, you can override the setProperties method. - - public void setProperties(Map<String, InterceptorProperty> properties) { - super.setProperties(properties); - final String myprop = "myprop"; - InterceptorProperty p1 = properties.get(myprop); - if (p1!=null) { - setMyprop(Long.parseLong(p1.getValue())); - } - } - -

    -
    - -

    Connection pools create wrappers around the actual connection in order to properly pool them. - We also create interceptors in these wrappers to be able to perform certain functions. - If there is a need to retrieve the actual connection, one can do so using the javax.sql.PooledConnection - interface. - - Connection con = datasource.getConnection(); - Connection actual = ((javax.sql.PooledConnection)con).getConnection(); - -

    -
    - -
    - -
    -

    We build the JDBC pool code with 1.6, but it is backwards compatible down to 1.5 for runtime environment. For unit test, we use 1.6 and higher

    -

    Other examples of Tomcat configuration for JDBC usage can be found in the Tomcat documentation.

    - -

    Building is pretty simple. The pool has a dependency on tomcat-juli.jar and in case you want the SlowQueryReportJmx

    - - javac -classpath tomcat-juli.jar \ - -d . \ - org/apache/tomcat/jdbc/pool/*.java \ - org/apache/tomcat/jdbc/pool/interceptor/*.java \ - org/apache/tomcat/jdbc/pool/jmx/*.java - -

    - A build file can be found in the Tomcat source repository. -

    -

    - As a convenience, a build file is also included where a simple build command will generate all files needed. - - ant download (downloads dependencies) - ant build (compiles and generates .jar files) - ant dist (creates a release package) - ant test (runs tests, expects a test database to be setup) - -

    -
    -
    - - -
    diff --git a/modules/jdbc-pool/doc/package.xsl b/modules/jdbc-pool/doc/package.xsl deleted file mode 100644 index 2f8905542186..000000000000 --- a/modules/jdbc-pool/doc/package.xsl +++ /dev/null @@ -1,450 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <xsl:value-of select="project/title"/> - <xsl:value-of select="properties/title"/> - - - - - - - - - - - - - - - - - - PAGE HEADER - - - - - -
    - - - - - - - - - - - - PROJECT LOGO - - {$alt} - - - - -

    -
    -
    - APACHE LOGO - - - - - Apache Logo - -
    - - - - HEADER SEPARATOR - - - - - - - RIGHT SIDE MAIN BODY - - - - - FOOTER SEPARATOR - - - - - PAGE FOOTER - - -
    -
    -
    -

    -

    - -
    -
    -
    -
    - Copyright © 1999-2010, Apache Software Foundation -
    -
    - - - -
    - - - - -

    -
      - -
    -
    - - - - - - - -
  • -
    - - - - - - - - - - - - -
    - - - -
    - -
    -
    - - - - - - - - - - - - -
    - - - -
    - -
    -
    - - - - - - - -
    - - - - - - - - - - - - - - - - -
    - - - - - -
    - -
    -            
    -          
    - -
    - - - - - -
    -
    -
    - - - - - - - - - - - - - - - -
    - Attribute - - Description -
    - - - - - - - - -
    -
    - - - - - - - - - - - - - - -
    - Property - - Description -
    - - - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - /images/add.gif - add - - - - - - - /images/update.gif - update - - - - - - - /images/design.gif - design - - - - - - - /images/docs.gif - docs - - - - - - - /images/fix.gif - fix - - - - - - - /images/code.gif - code - - - - - - - - - - - - - - - - - - - -
    - Priority - - Action Item - - Volunteers -
    - - - - - -
    -
    - - - - - - - - - - - - - - - - - - - - -
    diff --git a/modules/jdbc-pool/doc/project.xml b/modules/jdbc-pool/doc/project.xml deleted file mode 100644 index ecc9a70e4aad..000000000000 --- a/modules/jdbc-pool/doc/project.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - Apache Tomcat JDBC Pool - - - The Apache Tomcat Servlet/JSP Container - - - - - - - diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java deleted file mode 100644 index 7c6e49c8b4fd..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java +++ /dev/null @@ -1,218 +0,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.jdbc.naming; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Enumeration; -import java.util.Hashtable; - -import javax.naming.Context; -import javax.naming.Name; -import javax.naming.RefAddr; -import javax.naming.Reference; -import javax.naming.spi.ObjectFactory; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -/** - * Simple way of configuring generic resources by using reflection. - * Example usage: - *
    
    - * <Resource factory="org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory"
    - *              name="jdbc/test"
    - *              type="org.apache.derby.jdbc.ClientXADataSource"
    - *              databaseName="sample"
    - *              createDatabase="create"
    - *              serverName="localhost"
    - *              port="1527"/>
    - * 
    - * - */ -public class GenericNamingResourcesFactory implements ObjectFactory { - private static final Log log = LogFactory.getLog(GenericNamingResourcesFactory.class); - @Override - public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception { - if ((obj == null) || !(obj instanceof Reference)) { - return null; - } - Reference ref = (Reference) obj; - Enumeration refs = ref.getAll(); - - String type = ref.getClassName(); - Object o = Class.forName(type).newInstance(); - - while (refs.hasMoreElements()) { - RefAddr addr = refs.nextElement(); - String param = addr.getType(); - String value = null; - if (addr.getContent()!=null) { - value = addr.getContent().toString(); - } - if (setProperty(o, param, value,false)) { - - } else { - log.debug("Property not configured["+param+"]. No setter found on["+o+"]."); - } - } - return o; - } - - public static boolean setProperty(Object o, String name, String value,boolean invokeSetProperty) { - if (log.isDebugEnabled()) - log.debug("IntrospectionUtils: setProperty(" + - o.getClass() + " " + name + "=" + value + ")"); - - String setter = "set" + capitalize(name); - - try { - Method methods[] = o.getClass().getMethods(); - Method setPropertyMethodVoid = null; - Method setPropertyMethodBool = null; - - // First, the ideal case - a setFoo( String ) method - for (int i = 0; i < methods.length; i++) { - Class paramT[] = methods[i].getParameterTypes(); - if (setter.equals(methods[i].getName()) && paramT.length == 1 - && "java.lang.String".equals(paramT[0].getName())) { - - methods[i].invoke(o, new Object[] { value }); - return true; - } - } - - // Try a setFoo ( int ) or ( boolean ) - for (int i = 0; i < methods.length; i++) { - boolean ok = true; - if (setter.equals(methods[i].getName()) - && methods[i].getParameterTypes().length == 1) { - - // match - find the type and invoke it - Class paramType = methods[i].getParameterTypes()[0]; - Object params[] = new Object[1]; - - // Try a setFoo ( int ) - if ("java.lang.Integer".equals(paramType.getName()) - || "int".equals(paramType.getName())) { - try { - params[0] = new Integer(value); - } catch (NumberFormatException ex) { - ok = false; - } - // Try a setFoo ( long ) - }else if ("java.lang.Long".equals(paramType.getName()) - || "long".equals(paramType.getName())) { - try { - params[0] = new Long(value); - } catch (NumberFormatException ex) { - ok = false; - } - - // Try a setFoo ( boolean ) - } else if ("java.lang.Boolean".equals(paramType.getName()) - || "boolean".equals(paramType.getName())) { - params[0] = new Boolean(value); - - // Try a setFoo ( InetAddress ) - } else if ("java.net.InetAddress".equals(paramType - .getName())) { - try { - params[0] = InetAddress.getByName(value); - } catch (UnknownHostException exc) { - if (log.isDebugEnabled()) - log.debug("IntrospectionUtils: Unable to resolve host name:" + value); - ok = false; - } - - // Unknown type - } else { - if (log.isDebugEnabled()) - log.debug("IntrospectionUtils: Unknown type " + - paramType.getName()); - } - - if (ok) { - methods[i].invoke(o, params); - return true; - } - } - - // save "setProperty" for later - if ("setProperty".equals(methods[i].getName())) { - if (methods[i].getReturnType()==Boolean.TYPE){ - setPropertyMethodBool = methods[i]; - }else { - setPropertyMethodVoid = methods[i]; - } - - } - } - - // Ok, no setXXX found, try a setProperty("name", "value") - if (setPropertyMethodBool != null || setPropertyMethodVoid != null) { - Object params[] = new Object[2]; - params[0] = name; - params[1] = value; - if (setPropertyMethodBool != null) { - try { - return (Boolean) setPropertyMethodBool.invoke(o, params); - }catch (IllegalArgumentException biae) { - //the boolean method had the wrong - //parameter types. lets try the other - if (setPropertyMethodVoid!=null) { - setPropertyMethodVoid.invoke(o, params); - return true; - }else { - throw biae; - } - } - } else { - setPropertyMethodVoid.invoke(o, params); - return true; - } - } - - } catch (IllegalArgumentException ex2) { - log.warn("IAE " + o + " " + name + " " + value, ex2); - } catch (SecurityException ex1) { - if (log.isDebugEnabled()) - log.debug("IntrospectionUtils: SecurityException for " + - o.getClass() + " " + name + "=" + value + ")", ex1); - } catch (IllegalAccessException iae) { - if (log.isDebugEnabled()) - log.debug("IntrospectionUtils: IllegalAccessException for " + - o.getClass() + " " + name + "=" + value + ")", iae); - } catch (InvocationTargetException ie) { - if (log.isDebugEnabled()) - log.debug("IntrospectionUtils: InvocationTargetException for " + - o.getClass() + " " + name + "=" + value + ")", ie); - } - return false; - } - - public static String capitalize(String name) { - if (name == null || name.length() == 0) { - return name; - } - char chars[] = name.toCharArray(); - chars[0] = Character.toUpperCase(chars[0]); - return new String(chars); - } - -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java deleted file mode 100644 index 8b1cca37b9bf..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java +++ /dev/null @@ -1,1154 +0,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.jdbc.pool; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Proxy; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.ConcurrentModificationException; -import java.util.Iterator; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; - -/** - * Implementation of simple connection pool. - * The ConnectionPool uses a {@link PoolProperties} object for storing all the meta information about the connection pool. - * As the underlying implementation, the connection pool uses {@link java.util.concurrent.BlockingQueue} to store active and idle connections. - * A custom implementation of a fair {@link FairBlockingQueue} blocking queue is provided with the connection pool itself. - * @author Filip Hanik - * @version 1.0 - */ - -public class ConnectionPool { - /** - * Prefix type for JMX registration - */ - public static final String POOL_JMX_TYPE_PREFIX = "tomcat.jdbc:type="; - - /** - * Logger - */ - private static final Log log = LogFactory.getLog(ConnectionPool.class); - - //=============================================================================== - // INSTANCE/QUICK ACCESS VARIABLE - //=============================================================================== - /** - * Carries the size of the pool, instead of relying on a queue implementation - * that usually iterates over to get an exact count - */ - private AtomicInteger size = new AtomicInteger(0); - - /** - * All the information about the connection pool - * These are the properties the pool got instantiated with - */ - private PoolConfiguration poolProperties; - - /** - * Contains all the connections that are in use - * TODO - this shouldn't be a blocking queue, simply a list to hold our objects - */ - private BlockingQueue busy; - - /** - * Contains all the idle connections - */ - private BlockingQueue idle; - - /** - * The thread that is responsible for checking abandoned and idle threads - */ - private volatile PoolCleaner poolCleaner; - - /** - * Pool closed flag - */ - private volatile boolean closed = false; - - /** - * Since newProxyInstance performs the same operation, over and over - * again, it is much more optimized if we simply store the constructor ourselves. - */ - private Constructor proxyClassConstructor; - - /** - * Executor service used to cancel Futures - */ - private ThreadPoolExecutor cancellator = new ThreadPoolExecutor(0,1,1000,TimeUnit.MILLISECONDS,new LinkedBlockingQueue()); - - /** - * reference to the JMX mbean - */ - protected org.apache.tomcat.jdbc.pool.jmx.ConnectionPool jmxPool = null; - - /** - * counter to track how many threads are waiting for a connection - */ - private AtomicInteger waitcount = new AtomicInteger(0); - - //=============================================================================== - // PUBLIC METHODS - //=============================================================================== - - /** - * Instantiate a connection pool. This will create connections if initialSize is larger than 0. - * The {@link PoolProperties} should not be reused for another connection pool. - * @param prop PoolProperties - all the properties for this connection pool - * @throws SQLException - */ - public ConnectionPool(PoolConfiguration prop) throws SQLException { - //setup quick access variables and pools - init(prop); - } - - - /** - * Retrieves a Connection future. If a connection is not available, one can block using future.get() - * until a connection has become available. - * If a connection is not retrieved, the Future must be cancelled in order for the connection to be returned - * to the pool. - * @return a Future containing a reference to the connection or the future connection - * @throws SQLException - */ - public Future getConnectionAsync() throws SQLException { - //we can only retrieve a future if the underlying queue supports it. - if (idle instanceof FairBlockingQueue) { - Future pcf = ((FairBlockingQueue)idle).pollAsync(); - return new ConnectionFuture(pcf); - } else if (idle instanceof MultiLockFairBlockingQueue) { - Future pcf = ((MultiLockFairBlockingQueue)idle).pollAsync(); - return new ConnectionFuture(pcf); - } else { - throw new SQLException("Connection pool is misconfigured, doesn't support async retrieval. Set the 'fair' property to 'true'"); - } - } - - /** - * Borrows a connection from the pool. If a connection is available (in the idle queue) or the pool has not reached - * {@link PoolProperties#maxActive maxActive} connections a connection is returned immediately. - * If no connection is available, the pool will attempt to fetch a connection for {@link PoolProperties#maxWait maxWait} milliseconds. - * @return Connection - a java.sql.Connection/javax.sql.PooledConnection reflection proxy, wrapping the underlying object. - * @throws SQLException - if the wait times out or a failure occurs creating a connection - */ - public Connection getConnection() throws SQLException { - //check out a connection - PooledConnection con = borrowConnection(-1); - return setupConnection(con); - } - - - /** - * Returns the name of this pool - * @return String - the name of the pool - */ - public String getName() { - return getPoolProperties().getPoolName(); - } - - /** - * Return the number of threads waiting for a connection - * @return number of threads waiting for a connection - */ - public int getWaitCount() { - return waitcount.get(); - } - - /** - * Returns the pool properties associated with this connection pool - * @return PoolProperties - * - */ - public PoolConfiguration getPoolProperties() { - return this.poolProperties; - } - - /** - * Returns the total size of this pool, this includes both busy and idle connections - * @return int - number of established connections to the database - */ - public int getSize() { - return size.get(); - } - - /** - * Returns the number of connections that are in use - * @return int - number of established connections that are being used by the application - */ - public int getActive() { - return busy.size(); - } - - /** - * Returns the number of idle connections - * @return int - number of established connections not being used - */ - public int getIdle() { - return idle.size(); - } - - /** - * Returns true if {@link #close close} has been called, and the connection pool is unusable - * @return boolean - */ - public boolean isClosed() { - return this.closed; - } - - //=============================================================================== - // PROTECTED METHODS - //=============================================================================== - - - /** - * configures a pooled connection as a proxy. - * This Proxy implements {@link java.sql.Connection} and {@link javax.sql.PooledConnection} interfaces. - * All calls on {@link java.sql.Connection} methods will be propagated down to the actual JDBC connection except for the - * {@link java.sql.Connection#close()} method. - * @param con a {@link PooledConnection} to wrap in a Proxy - * @return a {@link java.sql.Connection} object wrapping a pooled connection. - * @throws SQLException if an interceptor can't be configured, if the proxy can't be instantiated - */ - protected Connection setupConnection(PooledConnection con) throws SQLException { - //fetch previously cached interceptor proxy - one per connection - JdbcInterceptor handler = con.getHandler(); - if (handler==null) { - //build the proxy handler - handler = new ProxyConnection(this,con,getPoolProperties().isUseEquals()); - //set up the interceptor chain - PoolProperties.InterceptorDefinition[] proxies = getPoolProperties().getJdbcInterceptorsAsArray(); - for (int i=proxies.length-1; i>=0; i--) { - try { - //create a new instance - JdbcInterceptor interceptor = proxies[i].getInterceptorClass().newInstance(); - //configure properties - interceptor.setProperties(proxies[i].getProperties()); - //setup the chain - interceptor.setNext(handler); - //call reset - interceptor.reset(this, con); - //configure the last one to be held by the connection - handler = interceptor; - }catch(Exception x) { - SQLException sx = new SQLException("Unable to instantiate interceptor chain."); - sx.initCause(x); - throw sx; - } - } - //cache handler for the next iteration - con.setHandler(handler); - } else { - JdbcInterceptor next = handler; - //we have a cached handler, reset it - while (next!=null) { - next.reset(this, con); - next = next.getNext(); - } - } - - try { - getProxyConstructor(con.getXAConnection() != null); - //create the proxy - //TODO possible optimization, keep track if this connection was returned properly, and don't generate a new facade - Connection connection = (Connection)proxyClassConstructor.newInstance(new Object[] { handler }); - //return the connection - return connection; - }catch (Exception x) { - SQLException s = new SQLException(); - s.initCause(x); - throw s; - } - - } - - /** - * Creates and caches a {@link java.lang.reflect.Constructor} used to instantiate the proxy object. - * We cache this, since the creation of a constructor is fairly slow. - * @return constructor used to instantiate the wrapper object - * @throws NoSuchMethodException - */ - public Constructor getProxyConstructor(boolean xa) throws NoSuchMethodException { - //cache the constructor - if (proxyClassConstructor == null ) { - Class proxyClass = xa ? - Proxy.getProxyClass(ConnectionPool.class.getClassLoader(), new Class[] {java.sql.Connection.class,javax.sql.PooledConnection.class, javax.sql.XAConnection.class}) : - Proxy.getProxyClass(ConnectionPool.class.getClassLoader(), new Class[] {java.sql.Connection.class,javax.sql.PooledConnection.class}); - proxyClassConstructor = proxyClass.getConstructor(new Class[] { InvocationHandler.class }); - } - return proxyClassConstructor; - } - - /** - * Closes the pool and all disconnects all idle connections - * Active connections will be closed upon the {@link java.sql.Connection#close close} method is called - * on the underlying connection instead of being returned to the pool - * @param force - true to even close the active connections - */ - protected void close(boolean force) { - //are we already closed - if (this.closed) return; - //prevent other threads from entering - this.closed = true; - //stop background thread - if (poolCleaner!=null) { - poolCleaner.stopRunning(); - } - - /* release all idle connections */ - BlockingQueue pool = (idle.size()>0)?idle:(force?busy:idle); - while (pool.size()>0) { - try { - //retrieve the next connection - PooledConnection con = pool.poll(1000, TimeUnit.MILLISECONDS); - //close it and retrieve the next one, if one is available - while (con != null) { - //close the connection - if (pool==idle) - release(con); - else - abandon(con); - con = pool.poll(1000, TimeUnit.MILLISECONDS); - } //while - } catch (InterruptedException ex) { - Thread.interrupted(); - } - if (pool.size()==0 && force && pool!=busy) pool = busy; - } - if (this.getPoolProperties().isJmxEnabled()) this.jmxPool = null; - PoolProperties.InterceptorDefinition[] proxies = getPoolProperties().getJdbcInterceptorsAsArray(); - for (int i=0; i(properties.getMaxActive(),false); - //busy = new FairBlockingQueue(); - //make space for 10 extra in case we flow over a bit - if (properties.isFairQueue()) { - idle = new FairBlockingQueue(); - //idle = new MultiLockFairBlockingQueue(); - } else { - idle = new ArrayBlockingQueue(properties.getMaxActive(),properties.isFairQueue()); - } - - //if the evictor thread is supposed to run, start it now - if (properties.isPoolSweeperEnabled()) { - poolCleaner = new PoolCleaner("[Pool-Cleaner]:" + properties.getName(), this, properties.getTimeBetweenEvictionRunsMillis()); - poolCleaner.start(); - } //end if - - //make sure the pool is properly configured - if (properties.getMaxActive()properties.getMaxActive()) { - log.warn("minIdle is larger than maxActive, setting minIdle to: "+properties.getMaxActive()); - properties.setMinIdle(properties.getMaxActive()); - } - if (properties.getMaxIdle()>properties.getMaxActive()) { - log.warn("maxIdle is larger than maxActive, setting maxIdle to: "+properties.getMaxActive()); - properties.setMaxIdle(properties.getMaxActive()); - } - if (properties.getMaxIdle() 0) { - idle.offer(new PooledConnection(poolProperties, this)); - } - } - - /** - * Thread safe way to retrieve a connection from the pool - * @param wait - time to wait, overrides the maxWait from the properties, - * set to -1 if you wish to use maxWait, 0 if you wish no wait time. - * @return PooledConnection - * @throws SQLException - */ - private PooledConnection borrowConnection(int wait) throws SQLException { - - if (isClosed()) { - throw new SQLException("Connection pool closed."); - } //end if - - //get the current time stamp - long now = System.currentTimeMillis(); - //see if there is one available immediately - PooledConnection con = idle.poll(); - - while (true) { - if (con!=null) { - //configure the connection and return it - PooledConnection result = borrowConnection(now, con); - //null should never be returned, but was in a previous impl. - if (result!=null) return result; - } - - //if we get here, see if we need to create one - //this is not 100% accurate since it doesn't use a shared - //atomic variable - a connection can become idle while we are creating - //a new connection - if (size.get() < getPoolProperties().getMaxActive()) { - //atomic duplicate check - if (size.addAndGet(1) > getPoolProperties().getMaxActive()) { - //if we got here, two threads passed through the first if - size.decrementAndGet(); - } else { - //create a connection, we're below the limit - return createConnection(now, con); - } - } //end if - - //calculate wait time for this iteration - long maxWait = wait; - //if the passed in wait time is -1, means we should use the pool property value - if (wait==-1) { - maxWait = (getPoolProperties().getMaxWait()<=0)?Long.MAX_VALUE:getPoolProperties().getMaxWait(); - } - - long timetowait = Math.max(0, maxWait - (System.currentTimeMillis() - now)); - waitcount.incrementAndGet(); - try { - //retrieve an existing connection - con = idle.poll(timetowait, TimeUnit.MILLISECONDS); - } catch (InterruptedException ex) { - Thread.interrupted();//clear the flag, and bail out - SQLException sx = new SQLException("Pool wait interrupted."); - sx.initCause(ex); - throw sx; - } finally { - waitcount.decrementAndGet(); - } - if (maxWait==0 && con == null) { //no wait, return one if we have one - throw new SQLException("[" + Thread.currentThread().getName()+"] " + - "NoWait: Pool empty. Unable to fetch a connection, none available["+busy.size()+" in use]."); - } - //we didn't get a connection, lets see if we timed out - if (con == null) { - if ((System.currentTimeMillis() - now) >= maxWait) { - throw new SQLException("[" + Thread.currentThread().getName()+"] " + - "Timeout: Pool empty. Unable to fetch a connection in " + (maxWait / 1000) + - " seconds, none available["+busy.size()+" in use]."); - } else { - //no timeout, lets try again - continue; - } - } - } //while - } - - /** - * Creates a JDBC connection and tries to connect to the database. - * @param now timestamp of when this was called - * @param notUsed Argument not used - * @return a PooledConnection that has been connected - * @throws SQLException - */ - protected PooledConnection createConnection(long now, - PooledConnection notUsed) throws SQLException { - //no connections where available we'll create one - PooledConnection con = create(); - boolean error = false; - try { - //connect and validate the connection - con.lock(); - con.connect(); - if (con.validate(PooledConnection.VALIDATE_INIT)) { - //no need to lock a new one, its not contented - con.setTimestamp(now); - if (getPoolProperties().isLogAbandoned()) { - con.setStackTrace(getThreadDump()); - } - if (!busy.offer(con)) { - log.debug("Connection doesn't fit into busy array, connection will not be traceable."); - } - return con; - } else { - //validation failed, make sure we disconnect - //and clean up - error =true; - } //end if - } catch (Exception e) { - error = true; - if (log.isDebugEnabled()) - log.debug("Unable to create a new JDBC connection.", e); - if (e instanceof SQLException) { - throw (SQLException)e; - } else { - SQLException ex = new SQLException(e.getMessage()); - ex.initCause(e); - throw ex; - } - } finally { - // con can never be null here - if (error ) { - release(con); - } - con.unlock(); - }//catch - return null; - } - - /** - * Validates and configures a previously idle connection - * @param now - timestamp - * @param con - the connection to validate and configure - * @return con - * @throws SQLException if a validation error happens - */ - protected PooledConnection borrowConnection(long now, PooledConnection con) throws SQLException { - //we have a connection, lets set it up - - //flag to see if we need to nullify - boolean setToNull = false; - try { - con.lock(); - - if (con.isReleased()) { - return null; - } - - if (!con.isDiscarded() && !con.isInitialized()) { - //attempt to connect - con.connect(); - } - if ((!con.isDiscarded()) && con.validate(PooledConnection.VALIDATE_BORROW)) { - //set the timestamp - con.setTimestamp(now); - if (getPoolProperties().isLogAbandoned()) { - //set the stack trace for this pool - con.setStackTrace(getThreadDump()); - } - if (!busy.offer(con)) { - log.debug("Connection doesn't fit into busy array, connection will not be traceable."); - } - return con; - } - //if we reached here, that means the connection - //is either discarded or validation failed. - //we will make one more attempt - //in order to guarantee that the thread that just acquired - //the connection shouldn't have to poll again. - try { - con.reconnect(); - if (con.validate(PooledConnection.VALIDATE_INIT)) { - //set the timestamp - con.setTimestamp(now); - if (getPoolProperties().isLogAbandoned()) { - //set the stack trace for this pool - con.setStackTrace(getThreadDump()); - } - if (!busy.offer(con)) { - log.debug("Connection doesn't fit into busy array, connection will not be traceable."); - } - return con; - } else { - //validation failed. - release(con); - setToNull = true; - throw new SQLException("Failed to validate a newly established connection."); - } - } catch (Exception x) { - release(con); - setToNull = true; - if (x instanceof SQLException) { - throw (SQLException)x; - } else { - SQLException ex = new SQLException(x.getMessage()); - ex.initCause(x); - throw ex; - } - } - } finally { - con.unlock(); - if (setToNull) { - con = null; - } - } - } - - /** - * Determines if a connection should be closed upon return to the pool. - * @param con - the connection - * @param action - the validation action that should be performed - * @return true if the connection should be closed - */ - protected boolean shouldClose(PooledConnection con, int action) { - if (con.isDiscarded()) return true; - if (isClosed()) return true; - if (!con.validate(action)) return true; - if (getPoolProperties().getMaxAge()>0 ) { - return (System.currentTimeMillis()-con.getLastConnected()) > getPoolProperties().getMaxAge(); - } else { - return false; - } - } - - /** - * Returns a connection to the pool - * If the pool is closed, the connection will be released - * If the connection is not part of the busy queue, it will be released. - * If {@link PoolProperties#testOnReturn} is set to true it will be validated - * @param con PooledConnection to be returned to the pool - */ - protected void returnConnection(PooledConnection con) { - if (isClosed()) { - //if the connection pool is closed - //close the connection instead of returning it - release(con); - return; - } //end if - - if (con != null) { - try { - con.lock(); - - if (busy.remove(con)) { - - if (!shouldClose(con,PooledConnection.VALIDATE_RETURN)) { - con.setStackTrace(null); - con.setTimestamp(System.currentTimeMillis()); - if (((idle.size()>=poolProperties.getMaxIdle()) && !poolProperties.isPoolSweeperEnabled()) || (!idle.offer(con))) { - if (log.isDebugEnabled()) { - log.debug("Connection ["+con+"] will be closed and not returned to the pool, idle["+idle.size()+"]>=maxIdle["+poolProperties.getMaxIdle()+"] idle.offer failed."); - } - release(con); - } - } else { - if (log.isDebugEnabled()) { - log.debug("Connection ["+con+"] will be closed and not returned to the pool."); - } - release(con); - } //end if - } else { - if (log.isDebugEnabled()) { - log.debug("Connection ["+con+"] will be closed and not returned to the pool, busy.remove failed."); - } - release(con); - } - } finally { - con.unlock(); - } - } //end if - } //checkIn - - /** - * Determines if a connection should be abandoned based on - * {@link PoolProperties#abandonWhenPercentageFull} setting. - * @return true if the connection should be abandoned - */ - protected boolean shouldAbandon() { - if (poolProperties.getAbandonWhenPercentageFull()==0) return true; - float used = busy.size(); - float max = poolProperties.getMaxActive(); - float perc = poolProperties.getAbandonWhenPercentageFull(); - return (used/max*100f)>=perc; - } - - /** - * Iterates through all the busy connections and checks for connections that have timed out - */ - public void checkAbandoned() { - try { - if (busy.size()==0) return; - Iterator locked = busy.iterator(); - int sto = getPoolProperties().getSuspectTimeout(); - while (locked.hasNext()) { - PooledConnection con = locked.next(); - boolean setToNull = false; - try { - con.lock(); - //the con has been returned to the pool - //ignore it - if (idle.contains(con)) - continue; - long time = con.getTimestamp(); - long now = System.currentTimeMillis(); - if (shouldAbandon() && (now - time) > con.getAbandonTimeout()) { - busy.remove(con); - abandon(con); - setToNull = true; - } else if (sto > 0 && (now - time) > (sto*1000)) { - suspect(con); - } else { - //do nothing - } //end if - } finally { - con.unlock(); - if (setToNull) - con = null; - } - } //while - } catch (ConcurrentModificationException e) { - log.debug("checkAbandoned failed." ,e); - } catch (Exception e) { - log.warn("checkAbandoned failed, it will be retried.",e); - } - } - - /** - * Iterates through the idle connections and resizes the idle pool based on parameters - * {@link PoolProperties#maxIdle}, {@link PoolProperties#minIdle}, {@link PoolProperties#minEvictableIdleTimeMillis} - */ - public void checkIdle() { - try { - if (idle.size()==0) return; - long now = System.currentTimeMillis(); - Iterator unlocked = idle.iterator(); - while ( (idle.size()>=getPoolProperties().getMinIdle()) && unlocked.hasNext()) { - PooledConnection con = unlocked.next(); - boolean setToNull = false; - try { - con.lock(); - //the con been taken out, we can't clean it up - if (busy.contains(con)) - continue; - long time = con.getTimestamp(); - if ((con.getReleaseTime()>0) && ((now - time) > con.getReleaseTime()) && (getSize()>getPoolProperties().getMinIdle())) { - release(con); - idle.remove(con); - setToNull = true; - } else { - //do nothing - } //end if - } finally { - con.unlock(); - if (setToNull) - con = null; - } - } //while - } catch (ConcurrentModificationException e) { - log.debug("checkIdle failed." ,e); - } catch (Exception e) { - log.warn("checkIdle failed, it will be retried.",e); - } - - } - - /** - * Forces a validation of all idle connections if {@link PoolProperties#testWhileIdle} is set. - */ - public void testAllIdle() { - try { - if (idle.size()==0) return; - Iterator unlocked = idle.iterator(); - while (unlocked.hasNext()) { - PooledConnection con = unlocked.next(); - try { - con.lock(); - //the con been taken out, we can't clean it up - if (busy.contains(con)) - continue; - if (!con.validate(PooledConnection.VALIDATE_IDLE)) { - idle.remove(con); - release(con); - } - } finally { - con.unlock(); - } - } //while - } catch (ConcurrentModificationException e) { - log.debug("testAllIdle failed." ,e); - } catch (Exception e) { - log.warn("testAllIdle failed, it will be retried.",e); - } - - } - - /** - * Creates a stack trace representing the existing thread's current state. - * @return a string object representing the current state. - * TODO investigate if we simply should store {@link java.lang.Thread#getStackTrace()} elements - */ - protected static String getThreadDump() { - Exception x = new Exception(); - x.fillInStackTrace(); - return getStackTrace(x); - } - - /** - * Convert an exception into a String - * @param x - the throwable - * @return a string representing the stack trace - */ - public static String getStackTrace(Throwable x) { - if (x == null) { - return null; - } else { - java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream(); - java.io.PrintStream writer = new java.io.PrintStream(bout); - x.printStackTrace(writer); - String result = bout.toString(); - return (x.getMessage()!=null && x.getMessage().length()>0)? x.getMessage()+";"+result:result; - } //end if - } - - - /** - * Create a new pooled connection object. Not connected nor validated. - * @return a pooled connection object - */ - protected PooledConnection create() { - PooledConnection con = new PooledConnection(getPoolProperties(), this); - return con; - } - - /** - * Hook to perform final actions on a pooled connection object once it has been disconnected and will be discarded - * @param con - */ - protected void finalize(PooledConnection con) { - JdbcInterceptor handler = con.getHandler(); - while (handler!=null) { - handler.reset(null, null); - handler=handler.getNext(); - } - } - - /** - * Hook to perform final actions on a pooled connection object once it has been disconnected and will be discarded - * @param con - */ - protected void disconnectEvent(PooledConnection con, boolean finalizing) { - JdbcInterceptor handler = con.getHandler(); - while (handler!=null) { - handler.disconnected(this, con, finalizing); - handler=handler.getNext(); - } - } - - /** - * Return the object that is potentially registered in JMX for notifications - * @return the object implementing the {@link org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean} interface - */ - public org.apache.tomcat.jdbc.pool.jmx.ConnectionPool getJmxPool() { - return jmxPool; - } - - /** - * Create MBean object that can be registered. - */ - protected void createMBean() { - try { - jmxPool = new org.apache.tomcat.jdbc.pool.jmx.ConnectionPool(this); - } catch (Exception x) { - log.warn("Unable to start JMX integration for connection pool. Instance["+getName()+"] can't be monitored.",x); - } - } - - /** - * Tread safe wrapper around a future for the regular queue - * This one retrieves the pooled connection object - * and performs the initialization according to - * interceptors and validation rules. - * This class is thread safe and is cancellable - * @author fhanik - * - */ - protected class ConnectionFuture implements Future, Runnable { - Future pcFuture = null; - AtomicBoolean configured = new AtomicBoolean(false); - CountDownLatch latch = new CountDownLatch(1); - Connection result = null; - SQLException cause = null; - AtomicBoolean cancelled = new AtomicBoolean(false); - public ConnectionFuture(Future pcf) { - this.pcFuture = pcf; - } - - /** - * {@inheritDoc} - */ - public boolean cancel(boolean mayInterruptIfRunning) { - if ((!cancelled.get()) && cancelled.compareAndSet(false, true)) { - //cancel by retrieving the connection and returning it to the pool - ConnectionPool.this.cancellator.execute(this); - } - return true; - } - - /** - * {@inheritDoc} - */ - public Connection get() throws InterruptedException, ExecutionException { - try { - return get(Long.MAX_VALUE, TimeUnit.MILLISECONDS); - }catch (TimeoutException x) { - throw new ExecutionException(x); - } - } - - /** - * {@inheritDoc} - */ - public Connection get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - PooledConnection pc = pcFuture.get(timeout,unit); - if (pc!=null) { - if (result!=null) return result; - if (configured.compareAndSet(false, true)) { - try { - pc = borrowConnection(System.currentTimeMillis(),pc); - result = ConnectionPool.this.setupConnection(pc); - } catch (SQLException x) { - cause = x; - } finally { - latch.countDown(); - } - } else { - //if we reach here, another thread is configuring the actual connection - latch.await(timeout,unit); //this shouldn't block for long - } - if (result==null) throw new ExecutionException(cause); - return result; - } else { - return null; - } - } - - /** - * {@inheritDoc} - */ - public boolean isCancelled() { - return pcFuture.isCancelled() || cancelled.get(); - } - - /** - * {@inheritDoc} - */ - public boolean isDone() { - return pcFuture.isDone(); - } - - /** - * run method to be executed when cancelled by an executor - */ - public void run() { - try { - Connection con = get(); //complete this future - con.close(); //return to the pool - }catch (ExecutionException ex) { - //we can ignore this - }catch (Exception x) { - ConnectionPool.log.error("Unable to cancel ConnectionFuture.",x); - } - } - - } - - protected class PoolCleaner extends Thread { - protected ConnectionPool pool; - protected long sleepTime; - protected volatile boolean run = true; - PoolCleaner(String name, ConnectionPool pool, long sleepTime) { - super(name); - this.setDaemon(true); - this.pool = pool; - this.sleepTime = sleepTime; - if (sleepTime <= 0) { - log.warn("Database connection pool evicter thread interval is set to 0, defaulting to 30 seconds"); - this.sleepTime = 1000 * 30; - } else if (sleepTime < 1000) { - log.warn("Database connection pool evicter thread interval is set to lower than 1 second."); - } - } - - @Override - public void run() { - while (run) { - try { - sleep(sleepTime); - } catch (InterruptedException e) { - // ignore it - Thread.interrupted(); - continue; - } //catch - - if (pool.isClosed()) { - if (pool.getSize() <= 0) { - run = false; - } - } else { - try { - if (pool.getPoolProperties().isRemoveAbandoned()) - pool.checkAbandoned(); - if (pool.getPoolProperties().getMinIdle() - * {@inheritDoc} - */ - public void postDeregister() { - if (oname!=null) unregisterJmx(); - } - - /** - * no-op
    - * {@inheritDoc} - */ - public void postRegister(Boolean registrationDone) { - // NOOP - } - - - /** - * no-op
    - * {@inheritDoc} - */ - public void preDeregister() throws Exception { - // NOOP - } - - /** - * If the connection pool MBean exists, it will be registered during this operation.
    - * {@inheritDoc} - */ - public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { - try { - this.oname = createObjectName(name); - if (oname!=null) registerJmx(); - }catch (MalformedObjectNameException x) { - log.error("Unable to create object name for JDBC pool.",x); - } - return name; - } - - /** - * Creates the ObjectName for the ConnectionPoolMBean object to be registered - * @param original the ObjectName for the DataSource - * @return the ObjectName for the ConnectionPoolMBean - * @throws MalformedObjectNameException - */ - public ObjectName createObjectName(ObjectName original) throws MalformedObjectNameException { - String domain = "tomcat.jdbc"; - Hashtable properties = original.getKeyPropertyList(); - String origDomain = original.getDomain(); - properties.put("type", "ConnectionPool"); - properties.put("class", this.getClass().getName()); - if (original.getKeyProperty("path")!=null) { - properties.put("engine", origDomain); - } - ObjectName name = new ObjectName(domain,properties); - return name; - } - - /** - * Registers the ConnectionPoolMBean under a unique name based on the ObjectName for the DataSource - */ - protected void registerJmx() { - try { - if (pool.getJmxPool()!=null) { - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - mbs.registerMBean(pool.getJmxPool(), oname); - } - } catch (Exception e) { - log.error("Unable to register JDBC pool with JMX",e); - } - } - - /** - * - */ - protected void unregisterJmx() { - try { - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - mbs.unregisterMBean(oname); - } catch (InstanceNotFoundException ignore) { - // NOOP - } catch (Exception e) { - log.error("Unable to unregister JDBC pool with JMX",e); - } - } - - -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java deleted file mode 100644 index 87eea63ad3a7..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java +++ /dev/null @@ -1,529 +0,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.jdbc.pool; - - -import java.io.IOException; -import java.sql.Connection; -import java.util.Hashtable; -import java.util.Properties; - -import javax.management.ObjectName; -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.Name; -import javax.naming.NamingException; -import javax.naming.RefAddr; -import javax.naming.Reference; -import javax.naming.spi.ObjectFactory; -import javax.sql.DataSource; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; - -/** - *

    JNDI object factory that creates an instance of - * BasicDataSource that has been configured based on the - * RefAddr values of the specified Reference, - * which must match the names and data types of the - * BasicDataSource bean properties.

    - *
    - * Properties available for configuration:
    - * Commons DBCP properties
    - *
      - *
    1. initSQL - A query that gets executed once, right after the connection is established.
    2. - *
    3. testOnConnect - run validationQuery after connection has been established.
    4. - *
    5. validationInterval - avoid excess validation, only run validation at most at this frequency - time in milliseconds.
    6. - *
    7. jdbcInterceptors - a semicolon separated list of classnames extending {@link JdbcInterceptor} class.
    8. - *
    9. jmxEnabled - true of false, whether to register the pool with JMX.
    10. - *
    11. fairQueue - true of false, whether the pool should sacrifice a little bit of performance for true fairness.
    12. - *
    - * @author Craig R. McClanahan - * @author Dirk Verbeeck - * @author Filip Hanik - */ -public class DataSourceFactory implements ObjectFactory { - private static final Log log = LogFactory.getLog(DataSourceFactory.class); - - protected final static String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit"; - protected final static String PROP_DEFAULTREADONLY = "defaultReadOnly"; - protected final static String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation"; - protected final static String PROP_DEFAULTCATALOG = "defaultCatalog"; - - protected final static String PROP_DRIVERCLASSNAME = "driverClassName"; - protected final static String PROP_PASSWORD = "password"; - protected final static String PROP_URL = "url"; - protected final static String PROP_USERNAME = "username"; - - protected final static String PROP_MAXACTIVE = "maxActive"; - protected final static String PROP_MAXIDLE = "maxIdle"; - protected final static String PROP_MINIDLE = "minIdle"; - protected final static String PROP_INITIALSIZE = "initialSize"; - protected final static String PROP_MAXWAIT = "maxWait"; - protected final static String PROP_MAXAGE = "maxAge"; - - protected final static String PROP_TESTONBORROW = "testOnBorrow"; - protected final static String PROP_TESTONRETURN = "testOnReturn"; - protected final static String PROP_TESTWHILEIDLE = "testWhileIdle"; - protected final static String PROP_TESTONCONNECT = "testOnConnect"; - protected final static String PROP_VALIDATIONQUERY = "validationQuery"; - protected final static String PROP_VALIDATOR_CLASS_NAME = "validatorClassName"; - - protected final static String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis"; - protected final static String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun"; - protected final static String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis"; - - protected final static String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed"; - - protected final static String PROP_REMOVEABANDONED = "removeAbandoned"; - protected final static String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout"; - protected final static String PROP_LOGABANDONED = "logAbandoned"; - protected final static String PROP_ABANDONWHENPERCENTAGEFULL = "abandonWhenPercentageFull"; - - protected final static String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements"; - protected final static String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements"; - protected final static String PROP_CONNECTIONPROPERTIES = "connectionProperties"; - - protected final static String PROP_INITSQL = "initSQL"; - protected final static String PROP_INTERCEPTORS = "jdbcInterceptors"; - protected final static String PROP_VALIDATIONINTERVAL = "validationInterval"; - protected final static String PROP_JMX_ENABLED = "jmxEnabled"; - protected final static String PROP_FAIR_QUEUE = "fairQueue"; - - protected static final String PROP_USE_EQUALS = "useEquals"; - protected static final String PROP_USE_CON_LOCK = "useLock"; - - protected static final String PROP_DATASOURCE= "dataSource"; - protected static final String PROP_DATASOURCE_JNDI = "dataSourceJNDI"; - - protected static final String PROP_SUSPECT_TIMEOUT = "suspectTimeout"; - - - public static final int UNKNOWN_TRANSACTIONISOLATION = -1; - - public static final String OBJECT_NAME = "object_name"; - - - protected final static String[] ALL_PROPERTIES = { - PROP_DEFAULTAUTOCOMMIT, - PROP_DEFAULTREADONLY, - PROP_DEFAULTTRANSACTIONISOLATION, - PROP_DEFAULTCATALOG, - PROP_DRIVERCLASSNAME, - PROP_MAXACTIVE, - PROP_MAXIDLE, - PROP_MINIDLE, - PROP_INITIALSIZE, - PROP_MAXWAIT, - PROP_TESTONBORROW, - PROP_TESTONRETURN, - PROP_TIMEBETWEENEVICTIONRUNSMILLIS, - PROP_NUMTESTSPEREVICTIONRUN, - PROP_MINEVICTABLEIDLETIMEMILLIS, - PROP_TESTWHILEIDLE, - PROP_TESTONCONNECT, - PROP_PASSWORD, - PROP_URL, - PROP_USERNAME, - PROP_VALIDATIONQUERY, - PROP_VALIDATIONINTERVAL, - PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED, - PROP_REMOVEABANDONED, - PROP_REMOVEABANDONEDTIMEOUT, - PROP_LOGABANDONED, - PROP_POOLPREPAREDSTATEMENTS, - PROP_MAXOPENPREPAREDSTATEMENTS, - PROP_CONNECTIONPROPERTIES, - PROP_INITSQL, - PROP_INTERCEPTORS, - PROP_JMX_ENABLED, - PROP_FAIR_QUEUE, - PROP_USE_EQUALS, - OBJECT_NAME, - PROP_ABANDONWHENPERCENTAGEFULL, - PROP_MAXAGE, - PROP_USE_CON_LOCK, - PROP_DATASOURCE, - PROP_DATASOURCE_JNDI, - }; - - // -------------------------------------------------- ObjectFactory Methods - - /** - *

    Create and return a new BasicDataSource instance. If no - * instance can be created, return null instead.

    - * - * @param obj The possibly null object containing location or - * reference information that can be used in creating an object - * @param name The name of this object relative to nameCtx - * @param nameCtx The context relative to which the name - * parameter is specified, or null if name - * is relative to the default initial context - * @param environment The possibly null environment that is used in - * creating this object - * - * @exception Exception if an exception occurs creating the instance - */ - public Object getObjectInstance(Object obj, Name name, Context nameCtx, - Hashtable environment) throws Exception { - - // We only know how to deal with javax.naming.References - // that specify a class name of "javax.sql.DataSource" - if ((obj == null) || !(obj instanceof Reference)) { - return null; - } - Reference ref = (Reference) obj; - boolean XA = false; - boolean ok = false; - if ("javax.sql.DataSource".equals(ref.getClassName())) { - ok = true; - } - if ("javax.sql.XADataSource".equals(ref.getClassName())) { - ok = true; - XA = true; - } - if (org.apache.tomcat.jdbc.pool.DataSource.class.getName().equals(ref.getClassName())) { - ok = true; - } - - if (!ok) { - log.warn(ref.getClassName()+" is not a valid class name/type for this JNDI factory."); - return null; - } - - - Properties properties = new Properties(); - for (int i = 0; i < ALL_PROPERTIES.length; i++) { - String propertyName = ALL_PROPERTIES[i]; - RefAddr ra = ref.get(propertyName); - if (ra != null) { - String propertyValue = ra.getContent().toString(); - properties.setProperty(propertyName, propertyValue); - } - } - - return createDataSource(properties,nameCtx,XA); - } - - public static PoolConfiguration parsePoolProperties(Properties properties) throws IOException{ - PoolConfiguration poolProperties = new PoolProperties(); - String value = null; - - value = properties.getProperty(PROP_DEFAULTAUTOCOMMIT); - if (value != null) { - poolProperties.setDefaultAutoCommit(Boolean.valueOf(value)); - } - - value = properties.getProperty(PROP_DEFAULTREADONLY); - if (value != null) { - poolProperties.setDefaultReadOnly(Boolean.valueOf(value)); - } - - value = properties.getProperty(PROP_DEFAULTTRANSACTIONISOLATION); - if (value != null) { - int level = UNKNOWN_TRANSACTIONISOLATION; - if ("NONE".equalsIgnoreCase(value)) { - level = Connection.TRANSACTION_NONE; - } else if ("READ_COMMITTED".equalsIgnoreCase(value)) { - level = Connection.TRANSACTION_READ_COMMITTED; - } else if ("READ_UNCOMMITTED".equalsIgnoreCase(value)) { - level = Connection.TRANSACTION_READ_UNCOMMITTED; - } else if ("REPEATABLE_READ".equalsIgnoreCase(value)) { - level = Connection.TRANSACTION_REPEATABLE_READ; - } else if ("SERIALIZABLE".equalsIgnoreCase(value)) { - level = Connection.TRANSACTION_SERIALIZABLE; - } else { - try { - level = Integer.parseInt(value); - } catch (NumberFormatException e) { - System.err.println("Could not parse defaultTransactionIsolation: " + value); - System.err.println("WARNING: defaultTransactionIsolation not set"); - System.err.println("using default value of database driver"); - level = UNKNOWN_TRANSACTIONISOLATION; - } - } - poolProperties.setDefaultTransactionIsolation(level); - } - - value = properties.getProperty(PROP_DEFAULTCATALOG); - if (value != null) { - poolProperties.setDefaultCatalog(value); - } - - value = properties.getProperty(PROP_DRIVERCLASSNAME); - if (value != null) { - poolProperties.setDriverClassName(value); - } - - value = properties.getProperty(PROP_MAXACTIVE); - if (value != null) { - poolProperties.setMaxActive(Integer.parseInt(value)); - } - - value = properties.getProperty(PROP_MAXIDLE); - if (value != null) { - poolProperties.setMaxIdle(Integer.parseInt(value)); - } - - value = properties.getProperty(PROP_MINIDLE); - if (value != null) { - poolProperties.setMinIdle(Integer.parseInt(value)); - } - - value = properties.getProperty(PROP_INITIALSIZE); - if (value != null) { - poolProperties.setInitialSize(Integer.parseInt(value)); - } - - value = properties.getProperty(PROP_MAXWAIT); - if (value != null) { - poolProperties.setMaxWait(Integer.parseInt(value)); - } - - value = properties.getProperty(PROP_TESTONBORROW); - if (value != null) { - poolProperties.setTestOnBorrow(Boolean.valueOf(value).booleanValue()); - } - - value = properties.getProperty(PROP_TESTONRETURN); - if (value != null) { - poolProperties.setTestOnReturn(Boolean.valueOf(value).booleanValue()); - } - - value = properties.getProperty(PROP_TESTONCONNECT); - if (value != null) { - poolProperties.setTestOnConnect(Boolean.valueOf(value).booleanValue()); - } - - value = properties.getProperty(PROP_TIMEBETWEENEVICTIONRUNSMILLIS); - if (value != null) { - poolProperties.setTimeBetweenEvictionRunsMillis(Integer.parseInt(value)); - } - - value = properties.getProperty(PROP_NUMTESTSPEREVICTIONRUN); - if (value != null) { - poolProperties.setNumTestsPerEvictionRun(Integer.parseInt(value)); - } - - value = properties.getProperty(PROP_MINEVICTABLEIDLETIMEMILLIS); - if (value != null) { - poolProperties.setMinEvictableIdleTimeMillis(Integer.parseInt(value)); - } - - value = properties.getProperty(PROP_TESTWHILEIDLE); - if (value != null) { - poolProperties.setTestWhileIdle(Boolean.valueOf(value).booleanValue()); - } - - value = properties.getProperty(PROP_PASSWORD); - if (value != null) { - poolProperties.setPassword(value); - } - - value = properties.getProperty(PROP_URL); - if (value != null) { - poolProperties.setUrl(value); - } - - value = properties.getProperty(PROP_USERNAME); - if (value != null) { - poolProperties.setUsername(value); - } - - value = properties.getProperty(PROP_VALIDATIONQUERY); - if (value != null) { - poolProperties.setValidationQuery(value); - } - - value = properties.getProperty(PROP_VALIDATOR_CLASS_NAME); - if (value != null) { - poolProperties.setValidatorClassName(value); - } - - value = properties.getProperty(PROP_VALIDATIONINTERVAL); - if (value != null) { - poolProperties.setValidationInterval(Long.parseLong(value)); - } - - value = properties.getProperty(PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED); - if (value != null) { - poolProperties.setAccessToUnderlyingConnectionAllowed(Boolean.valueOf(value).booleanValue()); - } - - value = properties.getProperty(PROP_REMOVEABANDONED); - if (value != null) { - poolProperties.setRemoveAbandoned(Boolean.valueOf(value).booleanValue()); - } - - value = properties.getProperty(PROP_REMOVEABANDONEDTIMEOUT); - if (value != null) { - poolProperties.setRemoveAbandonedTimeout(Integer.parseInt(value)); - } - - value = properties.getProperty(PROP_LOGABANDONED); - if (value != null) { - poolProperties.setLogAbandoned(Boolean.valueOf(value).booleanValue()); - } - - value = properties.getProperty(PROP_POOLPREPAREDSTATEMENTS); - if (value != null) { - log.warn(PROP_POOLPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect."); - } - - value = properties.getProperty(PROP_MAXOPENPREPAREDSTATEMENTS); - if (value != null) { - log.warn(PROP_MAXOPENPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect."); - } - - value = properties.getProperty(PROP_CONNECTIONPROPERTIES); - if (value != null) { - Properties p = getProperties(value); - poolProperties.setDbProperties(p); - } else { - poolProperties.setDbProperties(new Properties()); - } - - if (poolProperties.getUsername()!=null) { - poolProperties.getDbProperties().setProperty("user",poolProperties.getUsername()); - } - if (poolProperties.getPassword()!=null) { - poolProperties.getDbProperties().setProperty("password",poolProperties.getPassword()); - } - - value = properties.getProperty(PROP_INITSQL); - if (value != null) { - poolProperties.setInitSQL(value); - } - - value = properties.getProperty(PROP_INTERCEPTORS); - if (value != null) { - poolProperties.setJdbcInterceptors(value); - } - - value = properties.getProperty(PROP_JMX_ENABLED); - if (value != null) { - poolProperties.setJmxEnabled(Boolean.parseBoolean(value)); - } - - value = properties.getProperty(PROP_FAIR_QUEUE); - if (value != null) { - poolProperties.setFairQueue(Boolean.parseBoolean(value)); - } - - value = properties.getProperty(PROP_USE_EQUALS); - if (value != null) { - poolProperties.setUseEquals(Boolean.parseBoolean(value)); - } - - value = properties.getProperty(OBJECT_NAME); - if (value != null) { - poolProperties.setName(ObjectName.quote(value)); - } - - value = properties.getProperty(PROP_ABANDONWHENPERCENTAGEFULL); - if (value != null) { - poolProperties.setAbandonWhenPercentageFull(Integer.parseInt(value)); - } - - value = properties.getProperty(PROP_MAXAGE); - if (value != null) { - poolProperties.setMaxAge(Long.parseLong(value)); - } - - value = properties.getProperty(PROP_USE_CON_LOCK); - if (value != null) { - poolProperties.setUseLock(Boolean.parseBoolean(value)); - } - - value = properties.getProperty(PROP_DATASOURCE); - if (value != null) { - //this should never happen - throw new IllegalArgumentException("Can't set dataSource property as a string, this must be a javax.sql.DataSource object."); - - } - - value = properties.getProperty(PROP_DATASOURCE_JNDI); - if (value != null) { - poolProperties.setDataSourceJNDI(value); - } - - value = properties.getProperty(PROP_SUSPECT_TIMEOUT); - if (value != null) { - poolProperties.setSuspectTimeout(Integer.parseInt(value)); - } - return poolProperties; - } - - /** - * Creates and configures a {@link DataSource} instance based on the - * given properties. - * - * @param properties the datasource configuration properties - * @throws Exception if an error occurs creating the data source - */ - public DataSource createDataSource(Properties properties) throws Exception { - return createDataSource(properties,null,false); - } - public DataSource createDataSource(Properties properties,Context context, boolean XA) throws Exception { - PoolConfiguration poolProperties = DataSourceFactory.parsePoolProperties(properties); - if (poolProperties.getDataSourceJNDI()!=null && poolProperties.getDataSource()==null) { - performJNDILookup(context, poolProperties); - } - org.apache.tomcat.jdbc.pool.DataSource dataSource = XA? - new org.apache.tomcat.jdbc.pool.XADataSource(poolProperties) : - new org.apache.tomcat.jdbc.pool.DataSource(poolProperties); - //initialise the pool itself - dataSource.createPool(); - // Return the configured DataSource instance - return dataSource; - } - - public void performJNDILookup(Context context, PoolConfiguration poolProperties) { - Object jndiDS = null; - try { - if (context!=null) { - jndiDS = context.lookup(poolProperties.getDataSourceJNDI()); - } else { - log.warn("dataSourceJNDI property is configued, but local JNDI context is null."); - } - } catch (NamingException e) { - log.debug("The name \""+poolProperties.getDataSourceJNDI()+"\" can not be found in the local context."); - } - if (jndiDS==null) { - try { - context = (Context) (new InitialContext()); - jndiDS = context.lookup(poolProperties.getDataSourceJNDI()); - } catch (NamingException e) { - log.warn("The name \""+poolProperties.getDataSourceJNDI()+"\" can not be found in the InitialContext."); - } - } - if (jndiDS!=null) { - poolProperties.setDataSource(jndiDS); - } - } - - /** - *

    Parse properties from the string. Format of the string must be [propertyName=property;]*

    - * @param propText - * @return Properties - * @throws Exception - */ - static protected Properties getProperties(String propText) throws IOException { - return PoolProperties.getProperties(propText,null); - } - -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java deleted file mode 100644 index c7966fe1e8c5..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java +++ /dev/null @@ -1,1064 +0,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.jdbc.pool; - -import java.io.PrintWriter; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.Iterator; -import java.util.Properties; -import java.util.concurrent.Future; - -import javax.sql.XAConnection; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorDefinition; - -/** - * - * The DataSource proxy lets us implements methods that don't exist in the current - * compiler JDK but might be methods that are part of a future JDK DataSource interface. - *
    - * It's a trick to work around compiler issues when implementing interfaces. For example, - * I could put in Java 6 methods of javax.sql.DataSource here, and compile it with JDK 1.5 - * and still be able to run under Java 6 without getting NoSuchMethodException. - * - * @author Filip Hanik - * @version 1.0 - */ - -public class DataSourceProxy implements PoolConfiguration { - private static final Log log = LogFactory.getLog(DataSourceProxy.class); - - protected volatile ConnectionPool pool = null; - - protected PoolConfiguration poolProperties = null; - - public DataSourceProxy() { - this(new PoolProperties()); - } - - public DataSourceProxy(PoolConfiguration poolProperties) { - if (poolProperties == null) throw new NullPointerException("PoolConfiguration can not be null."); - this.poolProperties = poolProperties; - } - - - public boolean isWrapperFor(Class iface) throws SQLException { - // we are not a wrapper of anything - return false; - } - - - public T unwrap(Class iface) throws SQLException { - //we can't unwrap anything - return null; - } - - /** - * {@link javax.sql.DataSource#getConnection()} - */ - public Connection getConnection(String username, String password) throws SQLException { - return getConnection(); - } - - public PoolConfiguration getPoolProperties() { - return poolProperties; - } - - /** - * Sets up the connection pool, by creating a pooling driver. - * @return Driver - * @throws SQLException - */ - public synchronized ConnectionPool createPool() throws SQLException { - if (pool != null) { - return pool; - } else { - pool = new ConnectionPool(poolProperties); - return pool; - } - } - - /** - * {@link javax.sql.DataSource#getConnection()} - */ - - public Connection getConnection() throws SQLException { - if (pool == null) - return createPool().getConnection(); - return pool.getConnection(); - } - - /** - * Invokes an sync operation to retrieve the connection. - * @return a Future containing a reference to the connection when it becomes available - * @throws SQLException - */ - public Future getConnectionAsync() throws SQLException { - if (pool == null) - return createPool().getConnectionAsync(); - return pool.getConnectionAsync(); - } - - /** - * {@link javax.sql.XADataSource#getXAConnection()} - */ - public XAConnection getXAConnection() throws SQLException { - Connection con = getConnection(); - if (con instanceof XAConnection) { - return (XAConnection)con; - } else { - try {con.close();} catch (Exception ignore){} - throw new SQLException("Connection from pool does not implement javax.sql.XAConnection"); - } - } - - /** - * {@link javax.sql.XADataSource#getXAConnection(String, String)} - */ - public XAConnection getXAConnection(String username, String password) throws SQLException { - Connection con = getConnection(username, password); - if (con instanceof XAConnection) { - return (XAConnection)con; - } else { - try {con.close();} catch (Exception ignore){} - throw new SQLException("Connection from pool does not implement javax.sql.XAConnection"); - } - } - - - /** - * {@link javax.sql.DataSource#getConnection()} - */ - public PooledConnection getPooledConnection() throws SQLException { - return (PooledConnection) getConnection(); - } - - /** - * {@link javax.sql.DataSource#getConnection()} - */ - public PooledConnection getPooledConnection(String username, - String password) throws SQLException { - return (PooledConnection) getConnection(); - } - - public ConnectionPool getPool() { - return pool; - } - - - public void close() { - close(false); - } - public void close(boolean all) { - try { - if (pool != null) { - final ConnectionPool p = pool; - pool = null; - if (p!=null) { - p.close(all); - } - } - }catch (Exception x) { - log.warn("Error duing connection pool closure.", x); - } - } - - public int getPoolSize() throws SQLException{ - final ConnectionPool p = pool; - if (p == null) return 0; - else return p.getSize(); - } - - @Override - public String toString() { - return super.toString()+"{"+getPoolProperties()+"}"; - } - - -/*-----------------------------------------------------------------------*/ -// PROPERTIES WHEN NOT USED WITH FACTORY -/*------------------------------------------------------------------------*/ - - /** - * {@inheritDoc} - */ - @Override - public String getPoolName() { - return pool.getName(); - } - - - public void setPoolProperties(PoolConfiguration poolProperties) { - this.poolProperties = poolProperties; - } - - /** - * {@inheritDoc} - */ - @Override - public void setDriverClassName(String driverClassName) { - this.poolProperties.setDriverClassName(driverClassName); - } - - /** - * {@inheritDoc} - */ - @Override - public void setInitialSize(int initialSize) { - this.poolProperties.setInitialSize(initialSize); - } - - /** - * {@inheritDoc} - */ - @Override - public void setInitSQL(String initSQL) { - this.poolProperties.setInitSQL(initSQL); - } - - /** - * {@inheritDoc} - */ - @Override - public void setLogAbandoned(boolean logAbandoned) { - this.poolProperties.setLogAbandoned(logAbandoned); - } - - /** - * {@inheritDoc} - */ - @Override - public void setMaxActive(int maxActive) { - this.poolProperties.setMaxActive(maxActive); - } - - /** - * {@inheritDoc} - */ - @Override - public void setMaxIdle(int maxIdle) { - this.poolProperties.setMaxIdle(maxIdle); - } - - /** - * {@inheritDoc} - */ - @Override - public void setMaxWait(int maxWait) { - this.poolProperties.setMaxWait(maxWait); - } - - /** - * {@inheritDoc} - */ - @Override - public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) { - this.poolProperties.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); - } - - /** - * {@inheritDoc} - */ - @Override - public void setMinIdle(int minIdle) { - this.poolProperties.setMinIdle(minIdle); - } - - /** - * {@inheritDoc} - */ - @Override - public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { - this.poolProperties.setNumTestsPerEvictionRun(numTestsPerEvictionRun); - } - - /** - * {@inheritDoc} - */ - @Override - public void setPassword(String password) { - this.poolProperties.setPassword(password); - this.poolProperties.getDbProperties().setProperty("password",this.poolProperties.getPassword()); - } - - /** - * {@inheritDoc} - */ - @Override - public void setRemoveAbandoned(boolean removeAbandoned) { - this.poolProperties.setRemoveAbandoned(removeAbandoned); - } - - /** - * {@inheritDoc} - */ - @Override - public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) { - this.poolProperties.setRemoveAbandonedTimeout(removeAbandonedTimeout); - } - - /** - * {@inheritDoc} - */ - @Override - public void setTestOnBorrow(boolean testOnBorrow) { - this.poolProperties.setTestOnBorrow(testOnBorrow); - } - - /** - * {@inheritDoc} - */ - @Override - public void setTestOnConnect(boolean testOnConnect) { - this.poolProperties.setTestOnConnect(testOnConnect); - } - - /** - * {@inheritDoc} - */ - @Override - public void setTestOnReturn(boolean testOnReturn) { - this.poolProperties.setTestOnReturn(testOnReturn); - } - - /** - * {@inheritDoc} - */ - @Override - public void setTestWhileIdle(boolean testWhileIdle) { - this.poolProperties.setTestWhileIdle(testWhileIdle); - } - - /** - * {@inheritDoc} - */ - @Override - public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) { - this.poolProperties.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); - } - - /** - * {@inheritDoc} - */ - @Override - public void setUrl(String url) { - this.poolProperties.setUrl(url); - } - - /** - * {@inheritDoc} - */ - @Override - public void setUsername(String username) { - this.poolProperties.setUsername(username); - this.poolProperties.getDbProperties().setProperty("user",getPoolProperties().getUsername()); - } - - /** - * {@inheritDoc} - */ - @Override - public void setValidationInterval(long validationInterval) { - this.poolProperties.setValidationInterval(validationInterval); - } - - /** - * {@inheritDoc} - */ - @Override - public void setValidationQuery(String validationQuery) { - this.poolProperties.setValidationQuery(validationQuery); - } - - /** - * {@inheritDoc} - */ - @Override - public void setValidatorClassName(String className) { - this.poolProperties.setValidatorClassName(className); - } - - /** - * {@inheritDoc} - */ - @Override - public void setJdbcInterceptors(String interceptors) { - this.getPoolProperties().setJdbcInterceptors(interceptors); - } - - /** - * {@inheritDoc} - */ - @Override - public void setJmxEnabled(boolean enabled) { - this.getPoolProperties().setJmxEnabled(enabled); - } - - /** - * {@inheritDoc} - */ - @Override - public void setFairQueue(boolean fairQueue) { - this.getPoolProperties().setFairQueue(fairQueue); - } - - /** - * {@inheritDoc} - */ - @Override - public void setUseLock(boolean useLock) { - this.getPoolProperties().setUseLock(useLock); - } - - /** - * {@inheritDoc} - */ - @Override - public void setDefaultCatalog(String catalog) { - this.getPoolProperties().setDefaultCatalog(catalog); - } - - /** - * {@inheritDoc} - */ - @Override - public void setDefaultAutoCommit(Boolean autocommit) { - this.getPoolProperties().setDefaultAutoCommit(autocommit); - } - - /** - * {@inheritDoc} - */ - @Override - public void setDefaultTransactionIsolation(int defaultTransactionIsolation) { - this.getPoolProperties().setDefaultTransactionIsolation(defaultTransactionIsolation); - } - - /** - * {@inheritDoc} - */ - @Override - public void setConnectionProperties(String properties) { - try { - java.util.Properties prop = DataSourceFactory - .getProperties(properties); - Iterator i = prop.keySet().iterator(); - while (i.hasNext()) { - String key = (String) i.next(); - String value = prop.getProperty(key); - getPoolProperties().getDbProperties().setProperty(key, value); - } - - } catch (Exception x) { - log.error("Unable to parse connection properties.", x); - throw new RuntimeException(x); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void setUseEquals(boolean useEquals) { - this.getPoolProperties().setUseEquals(useEquals); - } - - /** - * no-op - * {@link javax.sql.DataSource#getLogWriter} - */ - public PrintWriter getLogWriter() throws SQLException { - return null; - } - - - /** - * no-op - * {@link javax.sql.DataSource#setLogWriter(PrintWriter)} - */ - public void setLogWriter(PrintWriter out) throws SQLException { - // NOOP - } - - /** - * no-op - * {@link javax.sql.DataSource#getLoginTimeout} - */ - public int getLoginTimeout() { - if (poolProperties == null) { - return 0; - } else { - return poolProperties.getMaxWait() / 1000; - } - } - - /** - * {@link javax.sql.DataSource#setLoginTimeout(int)} - */ - public void setLoginTimeout(int i) { - if (poolProperties == null) { - return; - } else { - poolProperties.setMaxWait(1000 * i); - } - - } - - - /** - * {@inheritDoc} - */ - @Override - public int getSuspectTimeout() { - return getPoolProperties().getSuspectTimeout(); - } - - /** - * {@inheritDoc} - */ - @Override - public void setSuspectTimeout(int seconds) { - getPoolProperties().setSuspectTimeout(seconds); - } - - //=============================================================================== -// Expose JMX attributes through Tomcat's dynamic reflection -//=============================================================================== - /** - * If the pool has not been created, it will be created during this call. - * @return the number of established but idle connections - */ - public int getIdle() { - try { - return createPool().getIdle(); - }catch (SQLException x) { - throw new RuntimeException(x); - } - } - - /** - * {@link #getIdle()} - */ - public int getNumIdle() { - return getIdle(); - } - - /** - * Forces an abandon check on the connection pool. - * If connections that have been abandoned exists, they will be closed during this run - */ - public void checkAbandoned() { - try { - createPool().checkAbandoned(); - }catch (SQLException x) { - throw new RuntimeException(x); - } - } - - /** - * Forces a check for resizing of the idle connections - */ - public void checkIdle() { - try { - createPool().checkIdle(); - }catch (SQLException x) { - throw new RuntimeException(x); - } - } - - /** - * @return number of connections in use by the application - */ - public int getActive() { - try { - return createPool().getActive(); - }catch (SQLException x) { - throw new RuntimeException(x); - } - } - - /** - * @return number of connections in use by the application - * {@link DataSource#getActive()} - */ - public int getNumActive() { - return getActive(); - } - - /** - * @return number of threads waiting for a connection - */ - public int getWaitCount() { - try { - return createPool().getWaitCount(); - }catch (SQLException x) { - throw new RuntimeException(x); - } - } - - /** - * @return the current size of the pool - */ - public int getSize() { - try { - return createPool().getSize(); - }catch (SQLException x) { - throw new RuntimeException(x); - } - } - - /** - * Performs a validation on idle connections - */ - public void testIdle() { - try { - createPool().testAllIdle(); - }catch (SQLException x) { - throw new RuntimeException(x); - } - } - //========================================================= - // PROPERTIES / CONFIGURATION - //========================================================= - - /** - * {@inheritDoc} - */ - @Override - public String getConnectionProperties() { - return getPoolProperties().getConnectionProperties(); - } - - /** - * {@inheritDoc} - */ - @Override - public Properties getDbProperties() { - return getPoolProperties().getDbProperties(); - } - - /** - * {@inheritDoc} - */ - @Override - public String getDefaultCatalog() { - return getPoolProperties().getDefaultCatalog(); - } - - /** - * {@inheritDoc} - */ - @Override - public int getDefaultTransactionIsolation() { - return getPoolProperties().getDefaultTransactionIsolation(); - } - - /** - * {@inheritDoc} - */ - @Override - public String getDriverClassName() { - return getPoolProperties().getDriverClassName(); - } - - - /** - * {@inheritDoc} - */ - @Override - public int getInitialSize() { - return getPoolProperties().getInitialSize(); - } - - /** - * {@inheritDoc} - */ - @Override - public String getInitSQL() { - return getPoolProperties().getInitSQL(); - } - - /** - * {@inheritDoc} - */ - @Override - public String getJdbcInterceptors() { - return getPoolProperties().getJdbcInterceptors(); - } - - /** - * {@inheritDoc} - */ - @Override - public int getMaxActive() { - return getPoolProperties().getMaxActive(); - } - - /** - * {@inheritDoc} - */ - @Override - public int getMaxIdle() { - return getPoolProperties().getMaxIdle(); - } - - /** - * {@inheritDoc} - */ - @Override - public int getMaxWait() { - return getPoolProperties().getMaxWait(); - } - - /** - * {@inheritDoc} - */ - @Override - public int getMinEvictableIdleTimeMillis() { - return getPoolProperties().getMinEvictableIdleTimeMillis(); - } - - /** - * {@inheritDoc} - */ - @Override - public int getMinIdle() { - return getPoolProperties().getMinIdle(); - } - - /** - * {@inheritDoc} - */ - @Override - public long getMaxAge() { - return getPoolProperties().getMaxAge(); - } - - /** - * {@inheritDoc} - */ - @Override - public String getName() { - return getPoolProperties().getName(); - } - - /** - * {@inheritDoc} - */ - @Override - public int getNumTestsPerEvictionRun() { - return getPoolProperties().getNumTestsPerEvictionRun(); - } - - /** - * @return DOES NOT RETURN THE PASSWORD, IT WOULD SHOW UP IN JMX - */ - public String getPassword() { - return "Password not available as DataSource/JMX operation."; - } - - /** - * {@inheritDoc} - */ - @Override - public int getRemoveAbandonedTimeout() { - return getPoolProperties().getRemoveAbandonedTimeout(); - } - - - /** - * {@inheritDoc} - */ - @Override - public int getTimeBetweenEvictionRunsMillis() { - return getPoolProperties().getTimeBetweenEvictionRunsMillis(); - } - - /** - * {@inheritDoc} - */ - @Override - public String getUrl() { - return getPoolProperties().getUrl(); - } - - /** - * {@inheritDoc} - */ - @Override - public String getUsername() { - return getPoolProperties().getUsername(); - } - - /** - * {@inheritDoc} - */ - @Override - public long getValidationInterval() { - return getPoolProperties().getValidationInterval(); - } - - /** - * {@inheritDoc} - */ - @Override - public String getValidationQuery() { - return getPoolProperties().getValidationQuery(); - } - - /** - * {@inheritDoc} - */ - @Override - public String getValidatorClassName() { - return getPoolProperties().getValidatorClassName(); - } - - /** - * {@inheritDoc} - */ - @Override - public Validator getValidator() { - return getPoolProperties().getValidator(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isAccessToUnderlyingConnectionAllowed() { - return getPoolProperties().isAccessToUnderlyingConnectionAllowed(); - } - - /** - * {@inheritDoc} - */ - @Override - public Boolean isDefaultAutoCommit() { - return getPoolProperties().isDefaultAutoCommit(); - } - - /** - * {@inheritDoc} - */ - @Override - public Boolean isDefaultReadOnly() { - return getPoolProperties().isDefaultReadOnly(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isLogAbandoned() { - return getPoolProperties().isLogAbandoned(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isPoolSweeperEnabled() { - return getPoolProperties().isPoolSweeperEnabled(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isRemoveAbandoned() { - return getPoolProperties().isRemoveAbandoned(); - } - - /** - * {@inheritDoc} - */ - @Override - public int getAbandonWhenPercentageFull() { - return getPoolProperties().getAbandonWhenPercentageFull(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isTestOnBorrow() { - return getPoolProperties().isTestOnBorrow(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isTestOnConnect() { - return getPoolProperties().isTestOnConnect(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isTestOnReturn() { - return getPoolProperties().isTestOnReturn(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isTestWhileIdle() { - return getPoolProperties().isTestWhileIdle(); - } - - - /** - * {@inheritDoc} - */ - @Override - public Boolean getDefaultAutoCommit() { - return getPoolProperties().getDefaultAutoCommit(); - } - - /** - * {@inheritDoc} - */ - @Override - public Boolean getDefaultReadOnly() { - return getPoolProperties().getDefaultReadOnly(); - } - - /** - * {@inheritDoc} - */ - @Override - public InterceptorDefinition[] getJdbcInterceptorsAsArray() { - return getPoolProperties().getJdbcInterceptorsAsArray(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean getUseLock() { - return getPoolProperties().getUseLock(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isFairQueue() { - return getPoolProperties().isFairQueue(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isJmxEnabled() { - return getPoolProperties().isJmxEnabled(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isUseEquals() { - return getPoolProperties().isUseEquals(); - } - - /** - * {@inheritDoc} - */ - @Override - public void setAbandonWhenPercentageFull(int percentage) { - getPoolProperties().setAbandonWhenPercentageFull(percentage); - } - - /** - * {@inheritDoc} - */ - @Override - public void setAccessToUnderlyingConnectionAllowed(boolean accessToUnderlyingConnectionAllowed) { - getPoolProperties().setAccessToUnderlyingConnectionAllowed(accessToUnderlyingConnectionAllowed); - } - - /** - * {@inheritDoc} - */ - @Override - public void setDbProperties(Properties dbProperties) { - getPoolProperties().setDbProperties(dbProperties); - } - - /** - * {@inheritDoc} - */ - @Override - public void setDefaultReadOnly(Boolean defaultReadOnly) { - getPoolProperties().setDefaultReadOnly(defaultReadOnly); - } - - /** - * {@inheritDoc} - */ - @Override - public void setMaxAge(long maxAge) { - getPoolProperties().setMaxAge(maxAge); - } - - /** - * {@inheritDoc} - */ - @Override - public void setName(String name) { - getPoolProperties().setName(name); - } - - /** - * {@inheritDoc} - */ - public void setDataSource(Object ds) { - getPoolProperties().setDataSource(ds); - } - - /** - * {@inheritDoc} - */ - public Object getDataSource() { - return getPoolProperties().getDataSource(); - } - - - /** - * {@inheritDoc} - */ - public void setDataSourceJNDI(String jndiDS) { - getPoolProperties().setDataSourceJNDI(jndiDS); - } - - /** - * {@inheritDoc} - */ - public String getDataSourceJNDI() { - return getPoolProperties().getDataSourceJNDI(); - } - -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java deleted file mode 100644 index ea56e86717a6..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java +++ /dev/null @@ -1,512 +0,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.jdbc.pool; - -import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.NoSuchElementException; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.locks.ReentrantLock; - -/** - * - * A simple implementation of a blocking queue with fairness waiting. - * invocations to method poll(...) will get handed out in the order they were received. - * Locking is fine grained, a shared lock is only used during the first level of contention, waiting is done in a - * lock per thread basis so that order is guaranteed once the thread goes into a suspended monitor state. - *
    - * Not all of the methods of the {@link java.util.concurrent.BlockingQueue} are implemented. - * @author Filip Hanik - * - */ - -public class FairBlockingQueue implements BlockingQueue { - - /** - * This little sucker is used to reorder the way to do - * {@link java.util.concurrent.locks.Lock#lock()}, - * {@link java.util.concurrent.locks.Lock#unlock()} - * and - * {@link java.util.concurrent.CountDownLatch#countDown()} - * during the {@link #poll(long, TimeUnit)} operation. - * On Linux, it performs much better if we count down while we hold the global - * lock, on Solaris its the other way around. - * Until we have tested other platforms we only check for Linux. - */ - final static boolean isLinux = "Linux".equals(System.getProperty("os.name")) && - (!Boolean.getBoolean(FairBlockingQueue.class.getName()+".ignoreOS")); - - /** - * Phase one entry lock in order to give out - * per-thread-locks for the waiting phase we have - * a phase one lock during the contention period. - */ - final ReentrantLock lock = new ReentrantLock(false); - - /** - * All the objects in the pool are stored in a simple linked list - */ - final LinkedList items; - - /** - * All threads waiting for an object are stored in a linked list - */ - final LinkedList> waiters; - - /** - * Creates a new fair blocking queue. - */ - public FairBlockingQueue() { - items = new LinkedList(); - waiters = new LinkedList>(); - } - - //------------------------------------------------------------------ - // USED BY CONPOOL IMPLEMENTATION - //------------------------------------------------------------------ - /** - * Will always return true, queue is unbounded. - * {@inheritDoc} - */ - public boolean offer(E e) { - //during the offer, we will grab the main lock - final ReentrantLock lock = this.lock; - lock.lock(); - ExchangeCountDownLatch c = null; - try { - //check to see if threads are waiting for an object - if (waiters.size() > 0) { - //if threads are waiting grab the latch for that thread - c = waiters.poll(); - //give the object to the thread instead of adding it to the pool - c.setItem(e); - if (isLinux) c.countDown(); - } else { - //we always add first, so that the most recently used object will be given out - items.addFirst(e); - } - } finally { - lock.unlock(); - } - //if we exchanged an object with another thread, wake it up. - if (!isLinux && c!=null) c.countDown(); - //we have an unbounded queue, so always return true - return true; - } - - /** - * Will never timeout, as it invokes the {@link #offer(Object)} method. - * Once a lock has been acquired, the - * {@inheritDoc} - */ - public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException { - return offer(e); - } - - /** - * Fair retrieval of an object in the queue. - * Objects are returned in the order the threads requested them. - * {@inheritDoc} - */ - public E poll(long timeout, TimeUnit unit) throws InterruptedException { - E result = null; - final ReentrantLock lock = this.lock; - boolean error = true; - //acquire the global lock until we know what to do - lock.lock(); - try { - //check to see if we have objects - result = items.poll(); - if (result==null && timeout>0) { - //the queue is empty we will wait for an object - ExchangeCountDownLatch c = new ExchangeCountDownLatch(1); - //add to the bottom of the wait list - waiters.addLast(c); - //unlock the global lock - lock.unlock(); - //wait for the specified timeout - if (!c.await(timeout, unit)) { - //if we timed out, remove ourselves from the waitlist - lock.lock(); - waiters.remove(c); - lock.unlock(); - } - //return the item we received, can be null if we timed out - result = c.getItem(); - } else { - //we have an object, release - lock.unlock(); - } - error = false; - } finally { - if (error && lock.isHeldByCurrentThread()) { - lock.unlock(); - } - } - return result; - } - - /** - * Request an item from the queue asynchronously - * @return - a future pending the result from the queue poll request - */ - public Future pollAsync() { - Future result = null; - final ReentrantLock lock = this.lock; - boolean error = true; - //grab the global lock - lock.lock(); - try { - //check to see if we have objects in the queue - E item = items.poll(); - if (item==null) { - //queue is empty, add ourselves as waiters - ExchangeCountDownLatch c = new ExchangeCountDownLatch(1); - waiters.addLast(c); - lock.unlock(); - //return a future that will wait for the object - result = new ItemFuture(c); - } else { - lock.unlock(); - //return a future with the item - result = new ItemFuture(item); - } - error = false; - } finally { - if (error && lock.isHeldByCurrentThread()) { - lock.unlock(); - } - } - return result; - } - - /** - * {@inheritDoc} - */ - public boolean remove(Object e) { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return items.remove(e); - } finally { - lock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - public int size() { - return items.size(); - } - - /** - * {@inheritDoc} - */ - public Iterator iterator() { - return new FairIterator(); - } - - /** - * {@inheritDoc} - */ - public E poll() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return items.poll(); - } finally { - lock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - public boolean contains(Object e) { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return items.contains(e); - } finally { - lock.unlock(); - } - } - - - //------------------------------------------------------------------ - // NOT USED BY CONPOOL IMPLEMENTATION - //------------------------------------------------------------------ - /** - * {@inheritDoc} - */ - public boolean add(E e) { - return offer(e); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public int drainTo(Collection c, int maxElements) { - throw new UnsupportedOperationException("int drainTo(Collection c, int maxElements)"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - - public int drainTo(Collection c) { - return drainTo(c,Integer.MAX_VALUE); - } - - /** - * {@inheritDoc} - */ - public void put(E e) throws InterruptedException { - offer(e); - } - - /** - * {@inheritDoc} - */ - public int remainingCapacity() { - return Integer.MAX_VALUE - size(); - } - - /** - * {@inheritDoc} - */ - public E take() throws InterruptedException { - return this.poll(Long.MAX_VALUE, TimeUnit.MILLISECONDS); - } - - /** - * {@inheritDoc} - */ - public boolean addAll(Collection c) { - Iterator i = c.iterator(); - while (i.hasNext()) { - E e = i.next(); - offer(e); - } - return true; - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public void clear() { - throw new UnsupportedOperationException("void clear()"); - - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public boolean containsAll(Collection c) { - throw new UnsupportedOperationException("boolean containsAll(Collection c)"); - } - - /** - * {@inheritDoc} - */ - public boolean isEmpty() { - return size() == 0; - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public boolean removeAll(Collection c) { - throw new UnsupportedOperationException("boolean removeAll(Collection c)"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public boolean retainAll(Collection c) { - throw new UnsupportedOperationException("boolean retainAll(Collection c)"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public Object[] toArray() { - throw new UnsupportedOperationException("Object[] toArray()"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public T[] toArray(T[] a) { - throw new UnsupportedOperationException(" T[] toArray(T[] a)"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public E element() { - throw new UnsupportedOperationException("E element()"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public E peek() { - throw new UnsupportedOperationException("E peek()"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public E remove() { - throw new UnsupportedOperationException("E remove()"); - } - - - - //------------------------------------------------------------------ - // Non cancellable Future used to check and see if a connection has been made available - //------------------------------------------------------------------ - protected class ItemFuture implements Future { - protected volatile T item = null; - protected volatile ExchangeCountDownLatch latch = null; - protected volatile boolean canceled = false; - - public ItemFuture(T item) { - this.item = item; - } - - public ItemFuture(ExchangeCountDownLatch latch) { - this.latch = latch; - } - - public boolean cancel(boolean mayInterruptIfRunning) { - return false; //don't allow cancel for now - } - - public T get() throws InterruptedException, ExecutionException { - if (item!=null) { - return item; - } else if (latch!=null) { - latch.await(); - return latch.getItem(); - } else { - throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception()); - } - } - - public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - if (item!=null) { - return item; - } else if (latch!=null) { - boolean timedout = !latch.await(timeout, unit); - if (timedout) throw new TimeoutException(); - else return latch.getItem(); - } else { - throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception()); - } - } - - public boolean isCancelled() { - return false; - } - - public boolean isDone() { - return (item!=null || latch.getItem()!=null); - } - - } - - //------------------------------------------------------------------ - // Count down latch that can be used to exchange information - //------------------------------------------------------------------ - protected class ExchangeCountDownLatch extends CountDownLatch { - protected volatile T item; - public ExchangeCountDownLatch(int i) { - super(i); - } - public T getItem() { - return item; - } - public void setItem(T item) { - this.item = item; - } - } - - //------------------------------------------------------------------ - // Iterator safe from concurrent modification exceptions - //------------------------------------------------------------------ - protected class FairIterator implements Iterator { - E[] elements = null; - int index; - E element = null; - - public FairIterator() { - final ReentrantLock lock = FairBlockingQueue.this.lock; - lock.lock(); - try { - elements = (E[]) new Object[FairBlockingQueue.this.items.size()]; - FairBlockingQueue.this.items.toArray(elements); - index = 0; - } finally { - lock.unlock(); - } - } - public boolean hasNext() { - return index - * Interceptors can receive a set of properties. Each sub class is responsible for parsing the properties during runtime when they - * are needed or simply override the {@link #setProperties(Map)} method. - * Properties arrive in a key-value pair of Strings as they were received through the configuration. - * This method is called once per cached connection object when the object is first configured. - * - * @author Filip Hanik - * @version 1.0 - */ -public abstract class JdbcInterceptor implements InvocationHandler { - /** - * {@link java.sql.Connection#close()} method name - */ - public static final String CLOSE_VAL = "close"; - /** - * {@link Object#toString()} method name - */ - public static final String TOSTRING_VAL = "toString"; - /** - * {@link java.sql.Connection#isClosed()} method name - */ - public static final String ISCLOSED_VAL = "isClosed"; - /** - * {@link javax.sql.PooledConnection#getConnection()} method name - */ - public static final String GETCONNECTION_VAL = "getConnection"; - /** - * {@link java.sql.Wrapper#unwrap(Class)} method name - */ - public static final String UNWRAP_VAL = "unwrap"; - /** - * {@link java.sql.Wrapper#isWrapperFor(Class)} method name - */ - public static final String ISWRAPPERFOR_VAL = "isWrapperFor"; - - - /** - * Properties for this interceptor. - */ - protected Map properties = null; - - /** - * The next interceptor in the chain - */ - private JdbcInterceptor next = null; - /** - * Property that decides how we do string comparison, default is to use - * {@link String#equals(Object)}. If set to false then the - * equality operator (==) is used. - */ - private boolean useEquals = true; - - /** - * Public constructor for instantation through reflection - */ - public JdbcInterceptor() { - // NOOP - } - - /** - * Gets invoked each time an operation on {@link java.sql.Connection} is invoked. - * {@inheritDoc} - */ - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if (getNext()!=null) return getNext().invoke(this,method,args); - else throw new NullPointerException(); - } - - /** - * Returns the next interceptor in the chain - * @return the next interceptor in the chain - */ - public JdbcInterceptor getNext() { - return next; - } - - /** - * configures the next interceptor in the chain - * @param next - */ - public void setNext(JdbcInterceptor next) { - this.next = next; - } - - /** - * Performs a string comparison, using references unless the useEquals property is set to true. - * @param name1 - * @param name2 - * @return true if name1 is equal to name2 based on {@link #useEquals} - */ - public boolean compare(String name1, String name2) { - if (isUseEquals()) { - return name1.equals(name2); - } else { - return name1==name2; - } - } - - /** - * Compares a method name (String) to a method (Method) - * {@link #compare(String,String)} - * Uses reference comparison unless the useEquals property is set to true - * @param methodName - * @param method - * @return true if the name matches - */ - public boolean compare(String methodName, Method method) { - return compare(methodName, method.getName()); - } - - /** - * Gets called each time the connection is borrowed from the pool - * This means that if an interceptor holds a reference to the connection - * the interceptor can be reused for another connection. - *
    - * This method may be called with null as both arguments when we are closing down the connection. - * @param parent - the connection pool owning the connection - * @param con - the pooled connection - */ - public abstract void reset(ConnectionPool parent, PooledConnection con); - - /** - * Called when {@link java.sql.Connection#close()} is called on the underlying connection. - * This is to notify the interceptors, that the physical connection has been released. - * Implementation of this method should be thought through with care, as no actions should trigger an exception. - * @param parent - the connection pool that this connection belongs to - * @param con - the pooled connection that holds this connection - * @param finalizing - if this connection is finalizing. True means that the pooled connection will not reconnect the underlying connection - */ - public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing) { - } - - - /** - * Returns the properties configured for this interceptor - * @return the configured properties for this interceptor - */ - public Map getProperties() { - return properties; - } - - /** - * Called during the creation of an interceptor - * The properties can be set during the configuration of an interceptor - * Override this method to perform type casts between string values and object properties - * @param properties - */ - public void setProperties(Map properties) { - this.properties = properties; - final String useEquals = "useEquals"; - InterceptorProperty p = properties.get(useEquals); - if (p!=null) { - setUseEquals(Boolean.parseBoolean(p.getValue())); - } - } - - /** - * @return true if the compare method uses the Object.equals(Object) method - * false if comparison is done on a reference level - */ - public boolean isUseEquals() { - return useEquals; - } - - /** - * Set to true if string comparisons (for the {@link #compare(String, Method)} and {@link #compare(String, String)} methods) should use the Object.equals(Object) method - * The default is false - * @param useEquals - */ - public void setUseEquals(boolean useEquals) { - this.useEquals = useEquals; - } - - /** - * This method is invoked by a connection pool when the pool is closed. - * Interceptor classes can override this method if they keep static - * variables or other tracking means around. - * This method is only invoked on a single instance of the interceptor, and not on every instance created. - * @param pool - the pool that is being closed. - */ - public void poolClosed(ConnectionPool pool) { - // NOOP - } - - /** - * This method is invoked by a connection pool when the pool is first started up, usually when the first connection is requested. - * Interceptor classes can override this method if they keep static - * variables or other tracking means around. - * This method is only invoked on a single instance of the interceptor, and not on every instance created. - * @param pool - the pool that is being closed. - */ - public void poolStarted(ConnectionPool pool) { - // NOOP - } - -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/MultiLockFairBlockingQueue.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/MultiLockFairBlockingQueue.java deleted file mode 100644 index f5fd28e836fa..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/MultiLockFairBlockingQueue.java +++ /dev/null @@ -1,537 +0,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.jdbc.pool; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.NoSuchElementException; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.ReentrantLock; - -/** - * EXPERIMENTAL AND NOT YET COMPLETE! - * - * - * An implementation of a blocking queue with fairness waiting and lock dispersal to avoid contention. - * invocations to method poll(...) will get handed out in the order they were received. - * Locking is fine grained, a shared lock is only used during the first level of contention, waiting is done in a - * lock per thread basis so that order is guaranteed once the thread goes into a suspended monitor state. - *
    - * Not all of the methods of the {@link java.util.concurrent.BlockingQueue} are implemented. - * @author Filip Hanik - * - */ - -public class MultiLockFairBlockingQueue implements BlockingQueue { - - final int LOCK_COUNT = Runtime.getRuntime().availableProcessors(); - - final AtomicInteger putQueue = new AtomicInteger(0); - final AtomicInteger pollQueue = new AtomicInteger(0); - - public int getNextPut() { - int idx = Math.abs(putQueue.incrementAndGet()) % LOCK_COUNT; - return idx; - } - - public int getNextPoll() { - int idx = Math.abs(pollQueue.incrementAndGet()) % LOCK_COUNT; - return idx; - } - /** - * Phase one entry lock in order to give out - * per-thread-locks for the waiting phase we have - * a phase one lock during the contention period. - */ - private final ReentrantLock[] locks = new ReentrantLock[LOCK_COUNT]; - - /** - * All the objects in the pool are stored in a simple linked list - */ - final LinkedList[] items; - - /** - * All threads waiting for an object are stored in a linked list - */ - final LinkedList>[] waiters; - - /** - * Creates a new fair blocking queue. - */ - public MultiLockFairBlockingQueue() { - items = new LinkedList[LOCK_COUNT]; - waiters = new LinkedList[LOCK_COUNT]; - for (int i=0; i(); - waiters[i] = new LinkedList>(); - locks[i] = new ReentrantLock(false); - } - } - - //------------------------------------------------------------------ - // USED BY CONPOOL IMPLEMENTATION - //------------------------------------------------------------------ - /** - * Will always return true, queue is unbounded. - * {@inheritDoc} - */ - public boolean offer(E e) { - int idx = getNextPut(); - //during the offer, we will grab the main lock - final ReentrantLock lock = this.locks[idx]; - lock.lock(); - ExchangeCountDownLatch c = null; - try { - //check to see if threads are waiting for an object - if (waiters[idx].size() > 0) { - //if threads are waiting grab the latch for that thread - c = waiters[idx].poll(); - //give the object to the thread instead of adding it to the pool - c.setItem(e); - } else { - //we always add first, so that the most recently used object will be given out - items[idx].addFirst(e); - } - } finally { - lock.unlock(); - } - //if we exchanged an object with another thread, wake it up. - if (c!=null) c.countDown(); - //we have an unbounded queue, so always return true - return true; - } - - /** - * Will never timeout, as it invokes the {@link #offer(Object)} method. - * Once a lock has been acquired, the - * {@inheritDoc} - */ - public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException { - return offer(e); - } - - /** - * Fair retrieval of an object in the queue. - * Objects are returned in the order the threads requested them. - * {@inheritDoc} - */ - public E poll(long timeout, TimeUnit unit) throws InterruptedException { - int idx = getNextPoll(); - E result = null; - final ReentrantLock lock = this.locks[idx]; - boolean error = true; - //acquire the global lock until we know what to do - lock.lock(); - try { - //check to see if we have objects - result = items[idx].poll(); - if (result==null && timeout>0) { - //the queue is empty we will wait for an object - ExchangeCountDownLatch c = new ExchangeCountDownLatch(1); - //add to the bottom of the wait list - waiters[idx].addLast(c); - //unlock the global lock - lock.unlock(); - //wait for the specified timeout - if (!c.await(timeout, unit)) { - //if we timed out, remove ourselves from the waitlist - lock.lock(); - waiters[idx].remove(c); - lock.unlock(); - } - //return the item we received, can be null if we timed out - result = c.getItem(); - } else { - //we have an object, release - lock.unlock(); - } - error = false; - } finally { - if (error && lock.isHeldByCurrentThread()) { - lock.unlock(); - } - } - return result; - } - - /** - * Request an item from the queue asynchronously - * @return - a future pending the result from the queue poll request - */ - public Future pollAsync() { - int idx = getNextPoll(); - Future result = null; - final ReentrantLock lock = this.locks[idx]; - boolean error = true; - //grab the global lock - lock.lock(); - try { - //check to see if we have objects in the queue - E item = items[idx].poll(); - if (item==null) { - //queue is empty, add ourselves as waiters - ExchangeCountDownLatch c = new ExchangeCountDownLatch(1); - waiters[idx].addLast(c); - lock.unlock(); - //return a future that will wait for the object - result = new ItemFuture(c); - } else { - lock.unlock(); - //return a future with the item - result = new ItemFuture(item); - } - error = false; - } finally { - if (error && lock.isHeldByCurrentThread()) { - lock.unlock(); - } - } - return result; - } - - /** - * {@inheritDoc} - */ - public boolean remove(Object e) { - for (int idx=0; idx iterator() { - return new FairIterator(); - } - - /** - * {@inheritDoc} - */ - public E poll() { - int idx = getNextPoll(); - final ReentrantLock lock = this.locks[idx]; - lock.lock(); - try { - return items[idx].poll(); - } finally { - lock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - public boolean contains(Object e) { - for (int idx=0; idx c, int maxElements) { - throw new UnsupportedOperationException("int drainTo(Collection c, int maxElements)"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public int drainTo(Collection c) { - return drainTo(c,Integer.MAX_VALUE); - } - - /** - * {@inheritDoc} - */ - public void put(E e) throws InterruptedException { - offer(e); - } - - /** - * {@inheritDoc} - */ - public int remainingCapacity() { - return Integer.MAX_VALUE - size(); - } - - /** - * {@inheritDoc} - */ - public E take() throws InterruptedException { - return this.poll(Long.MAX_VALUE, TimeUnit.MILLISECONDS); - } - - /** - * {@inheritDoc} - */ - public boolean addAll(Collection c) { - Iterator i = c.iterator(); - while (i.hasNext()) { - E e = i.next(); - offer(e); - } - return true; - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public void clear() { - throw new UnsupportedOperationException("void clear()"); - - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public boolean containsAll(Collection c) { - throw new UnsupportedOperationException("boolean containsAll(Collection c)"); - } - - /** - * {@inheritDoc} - */ - public boolean isEmpty() { - return size() == 0; - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public boolean removeAll(Collection c) { - throw new UnsupportedOperationException("boolean removeAll(Collection c)"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public boolean retainAll(Collection c) { - throw new UnsupportedOperationException("boolean retainAll(Collection c)"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public Object[] toArray() { - throw new UnsupportedOperationException("Object[] toArray()"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public T[] toArray(T[] a) { - throw new UnsupportedOperationException(" T[] toArray(T[] a)"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public E element() { - throw new UnsupportedOperationException("E element()"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public E peek() { - throw new UnsupportedOperationException("E peek()"); - } - - /** - * {@inheritDoc} - * @throws UnsupportedOperationException - this operation is not supported - */ - public E remove() { - throw new UnsupportedOperationException("E remove()"); - } - - - - //------------------------------------------------------------------ - // Non cancellable Future used to check and see if a connection has been made available - //------------------------------------------------------------------ - protected class ItemFuture implements Future { - protected volatile T item = null; - protected volatile ExchangeCountDownLatch latch = null; - protected volatile boolean canceled = false; - - public ItemFuture(T item) { - this.item = item; - } - - public ItemFuture(ExchangeCountDownLatch latch) { - this.latch = latch; - } - - public boolean cancel(boolean mayInterruptIfRunning) { - return false; //don't allow cancel for now - } - - public T get() throws InterruptedException, ExecutionException { - if (item!=null) { - return item; - } else if (latch!=null) { - latch.await(); - return latch.getItem(); - } else { - throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception()); - } - } - - public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - if (item!=null) { - return item; - } else if (latch!=null) { - boolean timedout = !latch.await(timeout, unit); - if (timedout) throw new TimeoutException(); - else return latch.getItem(); - } else { - throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception()); - } - } - - public boolean isCancelled() { - return false; - } - - public boolean isDone() { - return (item!=null || latch.getItem()!=null); - } - - } - - //------------------------------------------------------------------ - // Count down latch that can be used to exchange information - //------------------------------------------------------------------ - protected class ExchangeCountDownLatch extends CountDownLatch { - protected volatile T item; - public ExchangeCountDownLatch(int i) { - super(i); - } - public T getItem() { - return item; - } - public void setItem(T item) { - this.item = item; - } - } - - //------------------------------------------------------------------ - // Iterator safe from concurrent modification exceptions - //------------------------------------------------------------------ - protected class FairIterator implements Iterator { - E[] elements = null; - int index; - E element = null; - - public FairIterator() { - ArrayList list = new ArrayList(MultiLockFairBlockingQueue.this.size()); - for (int idx=0; idx - * NOTE - The "user" and "password" properties will be passed explicitly, so they do not need to be included here. - * The default value is null. - */ - public String getConnectionProperties(); - - /** - * The properties that will be passed into {@link java.sql.Driver#connect(String, Properties)} method. - * Username and password do not need to be stored here, they will be passed into the properties right before the connection is established. - * @param connectionProperties properties - Format of the string is [propertyName=property;]* - * Example: prop1=value1;prop2=value2 - */ - public void setConnectionProperties(String connectionProperties); - - /** - * Returns the database properties that are passed into the {@link java.sql.Driver#connect(String, Properties)} method. - * @return database properties that are passed into the {@link java.sql.Driver#connect(String, Properties)} method. - */ - public Properties getDbProperties(); - - /** - * Overrides the database properties passed into the {@link java.sql.Driver#connect(String, Properties)} method. - * @param dbProperties - */ - public void setDbProperties(Properties dbProperties); - - /** - * The default auto-commit state of connections created by this pool. - * If not set (null), default is JDBC driver default (If set to null then the {@link java.sql.Connection#setAutoCommit(boolean)} method will not be called.) - * @return the default auto commit setting, null is Driver default. - */ - public Boolean isDefaultAutoCommit(); - - /** - * The default auto-commit state of connections created by this pool. - * If not set (null), default is JDBC driver default (If set to null then the {@link java.sql.Connection#setAutoCommit(boolean)} method will not be called.) - * @return the default auto commit setting, null is Driver default. - */ - public Boolean getDefaultAutoCommit(); - - /** - * The default auto-commit state of connections created by this pool. - * If not set (null), default is JDBC driver default (If set to null then the {@link java.sql.Connection#setAutoCommit(boolean)} method will not be called.) - * @param defaultAutoCommit default auto commit setting, null is Driver default. - */ - public void setDefaultAutoCommit(Boolean defaultAutoCommit); - - /** - * If non null, during connection creation the method {@link java.sql.Connection#setCatalog(String)} will be called with the set value. - * @return the default catalog, null if not set and accepting the driver default. - */ - public String getDefaultCatalog(); - - /** - * If non null, during connection creation the method {@link java.sql.Connection#setCatalog(String)} will be called with the set value. - * @param defaultCatalog null if not set and accepting the driver default. - */ - public void setDefaultCatalog(String defaultCatalog); - - /** - * If non null, during connection creation the method {@link java.sql.Connection#setReadOnly(boolean)} will be called with the set value. - * @return null if not set and accepting the driver default otherwise the read only value - */ - public Boolean isDefaultReadOnly(); - - /** - * If non null, during connection creation the method {@link java.sql.Connection#setReadOnly(boolean)} will be called with the set value. - * @return null if not set and accepting the driver default otherwise the read only value - */ - public Boolean getDefaultReadOnly(); - - /** - * If non null, during connection creation the method {@link java.sql.Connection#setReadOnly(boolean)} will be called with the set value. - * @param defaultReadOnly null if not set and accepting the driver default. - */ - public void setDefaultReadOnly(Boolean defaultReadOnly); - - - /** - * Returns the default transaction isolation level. If set to {@link DataSourceFactory#UNKNOWN_TRANSACTIONISOLATION} the method - * {@link java.sql.Connection#setTransactionIsolation(int)} will not be called during connection creation. - * @return driver transaction isolation level, or -1 {@link DataSourceFactory#UNKNOWN_TRANSACTIONISOLATION} if not set. - */ - public int getDefaultTransactionIsolation(); - - /** - * If set to {@link DataSourceFactory#UNKNOWN_TRANSACTIONISOLATION} the method - * {@link java.sql.Connection#setTransactionIsolation(int)} will not be called during connection creation. Otherwise the method - * will be called with the isolation level set by this property. - * @param defaultTransactionIsolation a value of {@link java.sql.Connection#TRANSACTION_NONE}, {@link java.sql.Connection#TRANSACTION_READ_COMMITTED}, - * {@link java.sql.Connection#TRANSACTION_READ_UNCOMMITTED}, {@link java.sql.Connection#TRANSACTION_REPEATABLE_READ}, - * {@link java.sql.Connection#TRANSACTION_SERIALIZABLE} or {@link DataSourceFactory#UNKNOWN_TRANSACTIONISOLATION} - * The last value will not be set on the connection. - */ - public void setDefaultTransactionIsolation(int defaultTransactionIsolation); - - /** - * The fully qualified Java class name of the JDBC driver to be used. The driver has to be accessible from the same classloader as tomcat-jdbc.jar - * @return fully qualified JDBC driver name. - */ - public String getDriverClassName(); - - /** - * The fully qualified Java class name of the JDBC driver to be used. The driver has to be accessible from the same classloader as tomcat-jdbc.jar - * @param driverClassName a fully qualified Java class name of a {@link java.sql.Driver} implementation. - */ - public void setDriverClassName(String driverClassName); - - /** - * Returns the number of connections that will be established when the connection pool is started. - * Default value is 10 - * @return number of connections to be started when pool is started - */ - public int getInitialSize(); - - /** - * Set the number of connections that will be established when the connection pool is started. - * Default value is 10. - * If this value exceeds {@link #setMaxActive(int)} it will automatically be lowered. - * @param initialSize the number of connections to be established. - * - */ - public void setInitialSize(int initialSize); - - /** - * boolean flag to set if stack traces should be logged for application code which abandoned a Connection. - * Logging of abandoned Connections adds overhead for every Connection borrow because a stack trace has to be generated. - * The default value is false. - * @return true if the connection pool logs stack traces when connections are borrowed from the pool. - */ - public boolean isLogAbandoned(); - - /** - * boolean flag to set if stack traces should be logged for application code which abandoned a Connection. - * Logging of abandoned Connections adds overhead for every Connection borrow because a stack trace has to be generated. - * The default value is false. - * @param logAbandoned set to true if stack traces should be recorded when {@link DataSource#getConnection()} is called. - */ - public void setLogAbandoned(boolean logAbandoned); - - /** - * The maximum number of active connections that can be allocated from this pool at the same time. The default value is 100 - * @return the maximum number of connections used by this pool - */ - public int getMaxActive(); - - /** - * The maximum number of active connections that can be allocated from this pool at the same time. The default value is 100 - * @param maxActive hard limit for number of managed connections by this pool - */ - public void setMaxActive(int maxActive); - - - /** - * The maximum number of connections that should be kept in the idle pool if {@link #isPoolSweeperEnabled()} returns false. - * If the If {@link #isPoolSweeperEnabled()} returns true, then the idle pool can grow up to {@link #getMaxActive} - * and will be shrunk according to {@link #getMinEvictableIdleTimeMillis()} setting. - * Default value is maxActive:100 - * @return the maximum number of idle connections. - */ - public int getMaxIdle(); - - /** - * The maximum number of connections that should be kept in the idle pool if {@link #isPoolSweeperEnabled()} returns false. - * If the If {@link #isPoolSweeperEnabled()} returns true, then the idle pool can grow up to {@link #getMaxActive} - * and will be shrunk according to {@link #getMinEvictableIdleTimeMillis()} setting. - * Default value is maxActive:100 - * @param maxIdle the maximum size of the idle pool - */ - public void setMaxIdle(int maxIdle); - - /** - * The maximum number of milliseconds that the pool will wait (when there are no available connections and the - * {@link #getMaxActive} has been reached) for a connection to be returned - * before throwing an exception. Default value is 30000 (30 seconds) - * @return the number of milliseconds to wait for a connection to become available if the pool is maxed out. - */ - public int getMaxWait(); - - /** - * The maximum number of milliseconds that the pool will wait (when there are no available connections and the - * {@link #getMaxActive} has been reached) for a connection to be returned - * before throwing an exception. Default value is 30000 (30 seconds) - * @param maxWait the maximum number of milliseconds to wait. - */ - public void setMaxWait(int maxWait); - - /** - * The minimum amount of time an object must sit idle in the pool before it is eligible for eviction. - * The default value is 60000 (60 seconds). - * @return the minimum amount of idle time in milliseconds before a connection is considered idle and eligible for eviction. - */ - public int getMinEvictableIdleTimeMillis(); - - /** - * The minimum amount of time an object must sit idle in the pool before it is eligible for eviction. - * The default value is 60000 (60 seconds). - * @param minEvictableIdleTimeMillis the number of milliseconds a connection must be idle to be eligible for eviction. - */ - public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis); - - /** - * The minimum number of established connections that should be kept in the pool at all times. - * The connection pool can shrink below this number if validation queries fail and connections get closed. - * Default value is derived from {@link #getInitialSize()} (also see {@link #setTestWhileIdle(boolean)} - * The idle pool will not shrink below this value during an eviction run, hence the number of actual connections - * can be between {@link #getMinIdle()} and somewhere between {@link #getMaxIdle()} and {@link #getMaxActive()} - * @return the minimum number of idle or established connections - */ - public int getMinIdle(); - - /** - * The minimum number of established connections that should be kept in the pool at all times. - * The connection pool can shrink below this number if validation queries fail and connections get closed. - * Default value is derived from {@link #getInitialSize()} (also see {@link #setTestWhileIdle(boolean)} - * The idle pool will not shrink below this value during an eviction run, hence the number of actual connections - * can be between {@link #getMinIdle()} and somewhere between {@link #getMaxIdle()} and {@link #getMaxActive()} - * - * @param minIdle the minimum number of idle or established connections - */ - public void setMinIdle(int minIdle); - - /** - * Returns the name of the connection pool. By default a JVM unique random name is assigned. - * @return the name of the pool, should be unique in a JVM - */ - public String getName(); - - /** - * Sets the name of the connection pool - * @param name the name of the pool, should be unique in a runtime JVM - */ - public void setName(String name); - - /** - * Property not used - * @return unknown value - */ - public int getNumTestsPerEvictionRun(); - - /** - * Property not used - * @param numTestsPerEvictionRun parameter ignored. - */ - public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun); - - /** - * Returns the password used when establishing connections to the database. - * @return the password in string format - */ - public String getPassword(); - - /** - * Sets the password to establish the connection with. - * The password will be included as a database property with the name 'password'. - * @param password - * @see #getDbProperties() - */ - public void setPassword(String password); - - /** - * @see #getName() - * @return name - */ - public String getPoolName(); - - /** - * Returns the username used to establish the connection with - * @return the username used to establish the connection with - */ - public String getUsername(); - - /** - * Sets the username used to establish the connection with - * It will also be a property called 'user' in the database properties. - * @param username - * @see #getDbProperties() - */ - public void setUsername(String username); - - - /** - * boolean flag to remove abandoned connections if they exceed the removeAbandonedTimout. - * If set to true a connection is considered abandoned and eligible for removal if it has - * been in use longer than the {@link #getRemoveAbandonedTimeout()} and the condition for - * {@link #getAbandonWhenPercentageFull()} is met. - * Setting this to true can recover db connections from applications that fail to close a connection. - * See also {@link #isLogAbandoned()} The default value is false. - * @return true if abandoned connections can be closed and expelled out of the pool - */ - public boolean isRemoveAbandoned(); - - /** - * boolean flag to remove abandoned connections if they exceed the removeAbandonedTimout. - * If set to true a connection is considered abandoned and eligible for removal if it has - * been in use longer than the {@link #getRemoveAbandonedTimeout()} and the condition for - * {@link #getAbandonWhenPercentageFull()} is met. - * Setting this to true can recover db connections from applications that fail to close a connection. - * See also {@link #isLogAbandoned()} The default value is false. - * @param removeAbandoned set to true if abandoned connections can be closed and expelled out of the pool - */ - public void setRemoveAbandoned(boolean removeAbandoned); - - /** - * The time in seconds before a connection can be considered abandoned. - * The timer can be reset upon queries using an interceptor. - * @param removeAbandonedTimeout the time in seconds before a used connection can be considered abandoned - * @see org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer - */ - public void setRemoveAbandonedTimeout(int removeAbandonedTimeout); - - /** - * The time in seconds before a connection can be considered abandoned. - * The timer can be reset upon queries using an interceptor. - * @see org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer - * @return the time in seconds before a used connection can be considered abandoned - */ - public int getRemoveAbandonedTimeout(); - - /** - * The indication of whether objects will be validated before being borrowed from the pool. - * If the object fails to validate, it will be dropped from the pool, and we will attempt to borrow another. - * NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. - * Default value is false - * In order to have a more efficient validation, see {@link #setValidationInterval(long)} - * @return true if the connection is to be validated upon borrowing a connection from the pool - * @see #getValidationInterval() - */ - public boolean isTestOnBorrow(); - - /** - * The indication of whether objects will be validated before being borrowed from the pool. - * If the object fails to validate, it will be dropped from the pool, and we will attempt to borrow another. - * NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. - * Default value is false - * In order to have a more efficient validation, see {@link #setValidationInterval(long)} - * @param testOnBorrow set to true if validation should take place before a connection is handed out to the application - * @see #getValidationInterval() - */ - public void setTestOnBorrow(boolean testOnBorrow); - - /** - * The indication of whether objects will be validated after being returned to the pool. - * If the object fails to validate, it will be dropped from the pool. - * NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. - * Default value is false - * In order to have a more efficient validation, see {@link #setValidationInterval(long)} - * @return true if validation should take place after a connection is returned to the pool - * @see #getValidationInterval() - */ - public boolean isTestOnReturn(); - - /** - * The indication of whether objects will be validated after being returned to the pool. - * If the object fails to validate, it will be dropped from the pool. - * NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. - * Default value is false - * In order to have a more efficient validation, see {@link #setValidationInterval(long)} - * @param testOnReturn true if validation should take place after a connection is returned to the pool - * @see #getValidationInterval() - */ - public void setTestOnReturn(boolean testOnReturn); - - - /** - * Set to true if query validation should take place while the connection is idle. - * @return true if validation should take place during idle checks - * @see #setTimeBetweenEvictionRunsMillis(int) - */ - public boolean isTestWhileIdle(); - - /** - * Set to true if query validation should take place while the connection is idle. - * @param testWhileIdle true if validation should take place during idle checks - * @see #setTimeBetweenEvictionRunsMillis(int) - */ - public void setTestWhileIdle(boolean testWhileIdle); - - /** - * The number of milliseconds to sleep between runs of the idle connection validation, abandoned cleaner - * and idle pool resizing. This value should not be set under 1 second. - * It dictates how often we check for idle, abandoned connections, and how often we validate idle connection and resize the idle pool. - * The default value is 5000 (5 seconds) - * @return the sleep time in between validations in milliseconds - */ - public int getTimeBetweenEvictionRunsMillis(); - - /** - * The number of milliseconds to sleep between runs of the idle connection validation, abandoned cleaner - * and idle pool resizing. This value should not be set under 1 second. - * It dictates how often we check for idle, abandoned connections, and how often we validate idle connection and resize the idle pool. - * The default value is 5000 (5 seconds) - * @param timeBetweenEvictionRunsMillis the sleep time in between validations in milliseconds - */ - public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis); - - /** - * The URL used to connect to the database - * @return the configured URL for this connection pool - * @see java.sql.Driver#connect(String, Properties) - */ - public String getUrl(); - - /** - * Sets the URL used to connect to the database - * @param url the configured URL for this connection pool - * @see java.sql.Driver#connect(String, Properties) - */ - public void setUrl(String url); - - /** - * The SQL query that will be used to validate connections from this - * pool before returning them to the caller or pool. - * If specified, this query does not have to return any data, - * it just can't throw a SQLException. - * The default value is null. - * Example values are SELECT 1(mysql), - * select 1 from dual(oracle), - * SELECT 1(MS Sql Server) - * @return the query used for validation or null if no validation is performed - */ - public String getValidationQuery(); - - /** - * The SQL query that will be used to validate connections from this - * pool before returning them to the caller or pool. - * If specified, this query does not have to return any data, - * it just can't throw a SQLException. - * The default value is null. - * Example values are SELECT 1(mysql), - * select 1 from dual(oracle), - * SELECT 1(MS Sql Server) - * @param validationQuery the query used for validation or null if no validation is performed - */ - public void setValidationQuery(String validationQuery); - - /** - * Return the name of the optional validator class - may be null. - * - * @return the name of the optional validator class - may be null - */ - public String getValidatorClassName(); - - /** - * Set the name for an optional validator class which will be used in place of test queries. If set to - * null, standard validation will be used. - * - * @param className the name of the optional validator class - */ - public void setValidatorClassName(String className); - - /** - * @return the optional validator object - may be null - */ - public Validator getValidator(); - - /** - * avoid excess validation, only run validation at most at this frequency - time in milliseconds. - * If a connection is due for validation, but has been validated previously - * within this interval, it will not be validated again. - * The default value is 30000 (30 seconds). - * @return the validation interval in milliseconds - */ - public long getValidationInterval(); - - /** - * avoid excess validation, only run validation at most at this frequency - time in milliseconds. - * If a connection is due for validation, but has been validated previously - * within this interval, it will not be validated again. - * The default value is 30000 (30 seconds). - * @param validationInterval the validation interval in milliseconds - */ - public void setValidationInterval(long validationInterval); - - /** - * A custom query to be run when a connection is first created. The default value is null. - * This query only runs once per connection, and that is when a new connection is established to the database. - * If this value is non null, it will replace the validation query during connection creation. - * @return the init SQL used to run against the DB or null if not set - */ - public String getInitSQL(); - - /** - * A custom query to be run when a connection is first created. The default value is null. - * This query only runs once per connection, and that is when a new connection is established to the database. - * If this value is non null, it will replace the validation query during connection creation. - * @param initSQL the init SQL used to run against the DB or null if no query should be executed - */ - public void setInitSQL(String initSQL); - - /** - * Returns true if we should run the validation query when connecting to the database for the first time on a connection. - * Normally this is always set to false, unless one wants to use the validationQuery as an init query. - * @return true if we should run the validation query upon connect - */ - public boolean isTestOnConnect(); - - /** - * Set to true if we should run the validation query when connecting to the database for the first time on a connection. - * Normally this is always set to false, unless one wants to use the validationQuery as an init query. - * Setting an {@link #setInitSQL(String)} will override this setting, as the init SQL will be used instead of the validation query - * @param testOnConnect set to true if we should run the validation query upon connect - */ - public void setTestOnConnect(boolean testOnConnect); - - /** - * A semicolon separated list of classnames extending {@link org.apache.tomcat.jdbc.pool.JdbcInterceptor} class. - * These interceptors will be inserted as an interceptor into the chain of operations on a java.sql.Connection object. - * Example interceptors are {@link org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer StatementFinalizer} to close all - * used statements during the session. - * {@link org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer ResetAbandonedTimer} resets the timer upon every operation - * on the connection or a statement. - * {@link org.apache.tomcat.jdbc.pool.interceptor.ConnectionState ConnectionState} caches the auto commit, read only and catalog settings to avoid round trips to the DB. - * The default value is null. - * @return the interceptors that are used for connections. - * Example format: 'ConnectionState(useEquals=true,fast=yes);ResetAbandonedTimer' - */ - public String getJdbcInterceptors(); - - /** - * A semicolon separated list of classnames extending {@link org.apache.tomcat.jdbc.pool.JdbcInterceptor} class. - * These interceptors will be inserted as an interceptor into the chain of operations on a java.sql.Connection object. - * Example interceptors are {@link org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer StatementFinalizer} to close all - * used statements during the session. - * {@link org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer ResetAbandonedTimer} resets the timer upon every operation - * on the connection or a statement. - * {@link org.apache.tomcat.jdbc.pool.interceptor.ConnectionState ConnectionState} caches the auto commit, read only and catalog settings to avoid round trips to the DB. - * The default value is null. - * @param jdbcInterceptors the interceptors that are used for connections. - * Example format: 'ConnectionState(useEquals=true,fast=yes);ResetAbandonedTimer' - */ - public void setJdbcInterceptors(String jdbcInterceptors); - - /** - * Returns the {@link #getJdbcInterceptors()} as an array of objects with properties and the classes. - * @return an array of interceptors that have been configured - */ - public InterceptorDefinition[] getJdbcInterceptorsAsArray(); - - - /** - * If set to true, the connection pool creates a {@link org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean} object - * that can be registered with JMX to receive notifications and state about the pool. - * The ConnectionPool object doesn't register itself, as there is no way to keep a static non changing ObjectName across JVM restarts. - * @return true if the mbean object will be created upon startup. - */ - public boolean isJmxEnabled(); - - /** - * If set to true, the connection pool creates a {@link org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean} object - * that can be registered with JMX to receive notifications and state about the pool. - * The ConnectionPool object doesn't register itself, as there is no way to keep a static non changing ObjectName across JVM restarts. - * @param jmxEnabled set to to if the mbean object should be created upon startup. - */ - public void setJmxEnabled(boolean jmxEnabled); - - /** - * Returns true if the pool sweeper is enabled for the connection pool. - * The pool sweeper is enabled if any settings that require async intervention in the pool are turned on - * - boolean result = getTimeBetweenEvictionRunsMillis()>0; - result = result && (isRemoveAbandoned() && getRemoveAbandonedTimeout()>0); - result = result || (isTestWhileIdle() && getValidationQuery()!=null); - return result; - - * - * @return true if a background thread is or will be enabled for this pool - */ - public boolean isPoolSweeperEnabled(); - - /** - * Set to true if you wish the ProxyConnection class to use String.equals instead of - * == when comparing method names. - * This property does not apply to added interceptors as those are configured individually. - * The default value is false. - * @return true if pool uses {@link String#equals(Object)} instead of == when comparing method names on {@link java.sql.Connection} methods - */ - public boolean isUseEquals(); - - /** - * Set to true if you wish the ProxyConnection class to use String.equals instead of - * == when comparing method names. - * This property does not apply to added interceptors as those are configured individually. - * The default value is false. - * @param useEquals set to true if the pool should use {@link String#equals(Object)} instead of == - * when comparing method names on {@link java.sql.Connection} methods - */ - public void setUseEquals(boolean useEquals); - - /** - * Time in milliseconds to keep this connection alive even when used. - * When a connection is returned to the pool, the pool will check to see if the - * ((now - time-when-connected) > maxAge) has been reached, and if so, - * it closes the connection rather than returning it to the pool. - * The default value is 0, which implies that connections will be left open and no - * age check will be done upon returning the connection to the pool. - * This is a useful setting for database sessions that leak memory as it ensures that the session - * will have a finite life span. - * @return the time in milliseconds a connection will be open for when used - */ - public long getMaxAge(); - - /** - * Time in milliseconds to keep this connection alive even when used. - * When a connection is returned to the pool, the pool will check to see if the - * ((now - time-when-connected) > maxAge) has been reached, and if so, - * it closes the connection rather than returning it to the pool. - * The default value is 0, which implies that connections will be left open and no - * age check will be done upon returning the connection to the pool. - * This is a useful setting for database sessions that leak memory as it ensures that the session - * will have a finite life span. - * @param maxAge the time in milliseconds a connection will be open for when used - */ - public void setMaxAge(long maxAge); - - /** - * Return true if a lock should be used when operations are performed on the connection object. - * Should be set to false unless you plan to have a background thread of your own doing idle and abandon checking - * such as JMX clients. If the pool sweeper is enabled, then the lock will automatically be used regardless of this setting. - * @return true if a lock is used. - */ - public boolean getUseLock(); - - /** - * Set to true if a lock should be used when operations are performed on the connection object. - * Should be set to false unless you plan to have a background thread of your own doing idle and abandon checking - * such as JMX clients. If the pool sweeper is enabled, then the lock will automatically be used regardless of this setting. - * @param useLock set to true if a lock should be used on connection operations - */ - public void setUseLock(boolean useLock); - - /** - * Similar to {@link #setRemoveAbandonedTimeout(int)} but instead of treating the connection - * as abandoned, and potentially closing the connection, this simply logs the warning if - * {@link #isLogAbandoned()} returns true. If this value is equal or less than 0, no suspect - * checking will be performed. Suspect checking only takes place if the timeout value is larger than 0 and - * the connection was not abandoned or if abandon check is disabled. If a connection is suspect a WARN message gets - * logged and a JMX notification gets sent once. - * @param seconds - the amount of time in seconds that has to pass before a connection is marked suspect. - */ - public void setSuspectTimeout(int seconds); - - /** - * Returns the time in seconds to pass before a connection is marked an abanoned suspect. - * Any value lesser than or equal to 0 means the check is disabled. - * @return Returns the time in seconds to pass before a connection is marked an abanoned suspect. - */ - public int getSuspectTimeout(); - - /** - * Injects a datasource that will be used to retrieve/create connections. - * If a data source is set, the {@link PoolConfiguration#getUrl()} and {@link PoolConfiguration#getDriverClassName()} methods are ignored - * and not used by the pool. If the {@link PoolConfiguration#getUsername()} and {@link PoolConfiguration#getPassword()} - * values are set, the method {@link javax.sql.DataSource#getConnection(String, String)} method will be called instead of the - * {@link javax.sql.DataSource#getConnection()} method. - * If the data source implements {@link javax.sql.XADataSource} the methods - * {@link javax.sql.XADataSource#getXAConnection()} and {@link javax.sql.XADataSource#getXAConnection(String,String)} - * will be invoked. - * @param ds the {@link javax.sql.DataSource} to be used for creating connections to be pooled. - */ - public void setDataSource(Object ds); - - /** - * Returns a datasource, if one exists that is being used to create connections. - * This method will return null if the pool is using a {@link java.sql.Driver} - * @return the {@link javax.sql.DataSource} to be used for creating connections to be pooled or null if a Driver is used. - */ - public Object getDataSource(); - - /** - * Configure the connection pool to use a DataSource according to {@link PoolConfiguration#setDataSource(Object)} - * But instead of injecting the object, specify the JNDI location. - * After a successful JNDI look, the {@link PoolConfiguration#getDataSource()} will not return null. - * @param jndiDS -the JNDI string @TODO specify the rules here. - */ - public void setDataSourceJNDI(String jndiDS); - - /** - * Returns the JNDI string configured for data source usage. - * @return the JNDI string or null if not set - */ - public String getDataSourceJNDI(); - - -} \ No newline at end of file diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java deleted file mode 100644 index 931ae1cdc9a5..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java +++ /dev/null @@ -1,1035 +0,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.jdbc.pool; - - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.atomic.AtomicInteger; - - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; - -/** - * @author Filip Hanik - * - */ -public class PoolProperties implements PoolConfiguration { - private static final Log log = LogFactory.getLog(PoolProperties.class); - - protected static AtomicInteger poolCounter = new AtomicInteger(0); - protected Properties dbProperties = new Properties(); - protected String url = null; - protected String driverClassName = null; - protected Boolean defaultAutoCommit = null; - protected Boolean defaultReadOnly = null; - protected int defaultTransactionIsolation = DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION; - protected String defaultCatalog = null; - protected String connectionProperties; - protected int initialSize = 10; - protected int maxActive = 100; - protected int maxIdle = maxActive; - protected int minIdle = initialSize; - protected int maxWait = 30000; - protected String validationQuery; - protected String validatorClassName; - protected Validator validator; - protected boolean testOnBorrow = false; - protected boolean testOnReturn = false; - protected boolean testWhileIdle = false; - protected int timeBetweenEvictionRunsMillis = 5000; - protected int numTestsPerEvictionRun; - protected int minEvictableIdleTimeMillis = 60000; - protected final boolean accessToUnderlyingConnectionAllowed = true; - protected boolean removeAbandoned = false; - protected int removeAbandonedTimeout = 60; - protected boolean logAbandoned = false; - protected String name = "Tomcat Connection Pool["+(poolCounter.addAndGet(1))+"-"+System.identityHashCode(PoolProperties.class)+"]"; - protected String password; - protected String username; - protected long validationInterval = 30000; - protected boolean jmxEnabled = true; - protected String initSQL; - protected boolean testOnConnect =false; - protected String jdbcInterceptors=null; - protected boolean fairQueue = true; - protected boolean useEquals = true; - protected int abandonWhenPercentageFull = 0; - protected long maxAge = 0; - protected boolean useLock = false; - protected InterceptorDefinition[] interceptors = null; - protected int suspectTimeout = 0; - protected Object dataSource = null; - protected String dataSourceJNDI = null; - - - /** - * {@inheritDoc} - */ - @Override - public void setAbandonWhenPercentageFull(int percentage) { - if (percentage<0) abandonWhenPercentageFull = 0; - else if (percentage>100) abandonWhenPercentageFull = 100; - else abandonWhenPercentageFull = percentage; - } - - /** - * {@inheritDoc} - */ - @Override - public int getAbandonWhenPercentageFull() { - return abandonWhenPercentageFull; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isFairQueue() { - return fairQueue; - } - - /** - * {@inheritDoc} - */ - @Override - public void setFairQueue(boolean fairQueue) { - this.fairQueue = fairQueue; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isAccessToUnderlyingConnectionAllowed() { - return accessToUnderlyingConnectionAllowed; - } - - /** - * {@inheritDoc} - */ - @Override - public String getConnectionProperties() { - return connectionProperties; - } - - /** - * {@inheritDoc} - */ - @Override - public Properties getDbProperties() { - return dbProperties; - } - - /** - * {@inheritDoc} - */ - @Override - public Boolean isDefaultAutoCommit() { - return defaultAutoCommit; - } - - /** - * {@inheritDoc} - */ - @Override - public String getDefaultCatalog() { - return defaultCatalog; - } - - /** - * {@inheritDoc} - */ - @Override - public Boolean isDefaultReadOnly() { - return defaultReadOnly; - } - - /** - * {@inheritDoc} - */ - @Override - public int getDefaultTransactionIsolation() { - return defaultTransactionIsolation; - } - - /** - * {@inheritDoc} - */ - @Override - public String getDriverClassName() { - return driverClassName; - } - - /** - * {@inheritDoc} - */ - @Override - public int getInitialSize() { - return initialSize; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isLogAbandoned() { - return logAbandoned; - } - - /** - * {@inheritDoc} - */ - @Override - public int getMaxActive() { - return maxActive; - } - - /** - * {@inheritDoc} - */ - @Override - public int getMaxIdle() { - return maxIdle; - } - - /** - * {@inheritDoc} - */ - @Override - public int getMaxWait() { - return maxWait; - } - - /** - * {@inheritDoc} - */ - @Override - public int getMinEvictableIdleTimeMillis() { - return minEvictableIdleTimeMillis; - } - - /** - * {@inheritDoc} - */ - @Override - public int getMinIdle() { - return minIdle; - } - - /** - * {@inheritDoc} - */ - @Override - public String getName() { - return name; - } - - /** - * {@inheritDoc} - */ - @Override - public int getNumTestsPerEvictionRun() { - return numTestsPerEvictionRun; - } - - /** - * {@inheritDoc} - */ - @Override - public String getPassword() { - return password; - } - - /** - * {@inheritDoc} - */ - @Override - public String getPoolName() { - return getName(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isRemoveAbandoned() { - return removeAbandoned; - } - - /** - * {@inheritDoc} - */ - @Override - public int getRemoveAbandonedTimeout() { - return removeAbandonedTimeout; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isTestOnBorrow() { - return testOnBorrow; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isTestOnReturn() { - return testOnReturn; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isTestWhileIdle() { - return testWhileIdle; - } - - /** - * {@inheritDoc} - */ - @Override - public int getTimeBetweenEvictionRunsMillis() { - return timeBetweenEvictionRunsMillis; - } - - /** - * {@inheritDoc} - */ - @Override - public String getUrl() { - return url; - } - - /** - * {@inheritDoc} - */ - @Override - public String getUsername() { - return username; - } - - /** - * {@inheritDoc} - */ - @Override - public String getValidationQuery() { - return validationQuery; - } - - /** - * {@inheritDoc} - */ - @Override - public String getValidatorClassName() { - return validatorClassName; - } - - /** - * {@inheritDoc} - */ - @Override - public Validator getValidator() { - return validator; - } - - /** - * {@inheritDoc} - */ - @Override - public long getValidationInterval() { - return validationInterval; - } - - /** - * {@inheritDoc} - */ - @Override - public String getInitSQL() { - return initSQL; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isTestOnConnect() { - return testOnConnect; - } - - /** - * {@inheritDoc} - */ - @Override - public String getJdbcInterceptors() { - return jdbcInterceptors; - } - - /** - * {@inheritDoc} - */ - @Override - public InterceptorDefinition[] getJdbcInterceptorsAsArray() { - if (interceptors == null) { - if (jdbcInterceptors==null) { - interceptors = new InterceptorDefinition[0]; - } else { - String[] interceptorValues = jdbcInterceptors.split(";"); - InterceptorDefinition[] definitions = new InterceptorDefinition[interceptorValues.length]; - for (int i=0; i validatorClass = (Class)Class.forName(className); - validator = validatorClass.newInstance(); - } catch (ClassNotFoundException e) { - log.warn("The class "+className+" cannot be found.", e); - } catch (ClassCastException e) { - log.warn("The class "+className+" does not implement the Validator interface.", e); - } catch (InstantiationException e) { - log.warn("An object of class "+className+" cannot be instantiated. Make sure that "+ - "it includes an implicit or explicit no-arg constructor.", e); - } catch (IllegalAccessException e) { - log.warn("The class "+className+" or its no-arg constructor are inaccessible.", e); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void setInitSQL(String initSQL) { - this.initSQL = initSQL; - } - - /** - * {@inheritDoc} - */ - @Override - public void setTestOnConnect(boolean testOnConnect) { - this.testOnConnect = testOnConnect; - } - - /** - * {@inheritDoc} - */ - @Override - public void setJdbcInterceptors(String jdbcInterceptors) { - this.jdbcInterceptors = jdbcInterceptors; - this.interceptors = null; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder("ConnectionPool["); - try { - String[] fields = DataSourceFactory.ALL_PROPERTIES; - for (int i=0; i0; - boolean result = timer && (isRemoveAbandoned() && getRemoveAbandonedTimeout()>0); - result = result || (timer && getSuspectTimeout()>0); - result = result || (timer && isTestWhileIdle() && getValidationQuery()!=null); - result = result || (timer && getMinEvictableIdleTimeMillis()>0); - return result; - } - - - public static class InterceptorDefinition { - protected String className; - protected Map properties = new HashMap(); - protected volatile Class clazz = null; - public InterceptorDefinition(String className) { - this.className = className; - } - - public String getClassName() { - return className; - } - public void addProperty(String name, String value) { - InterceptorProperty p = new InterceptorProperty(name,value); - addProperty(p); - } - - public void addProperty(InterceptorProperty p) { - properties.put(p.getName(), p); - } - - public Map getProperties() { - return properties; - } - - public Class getInterceptorClass() throws ClassNotFoundException { - if (clazz==null) { - if (getClassName().indexOf(".")<0) { - if (log.isDebugEnabled()) { - log.debug("Loading interceptor class:"+PoolConfiguration.PKG_PREFIX+getClassName()); - } - clazz = Class.forName(PoolConfiguration.PKG_PREFIX+getClassName(), true, this.getClass().getClassLoader()); - } else { - if (log.isDebugEnabled()) { - log.debug("Loading interceptor class:"+getClassName()); - } - clazz = Class.forName(getClassName(), true, this.getClass().getClassLoader()); - } - } - return (Class)clazz; - } - } - - public static class InterceptorProperty { - String name; - String value; - public InterceptorProperty(String name, String value) { - assert(name!=null); - this.name = name; - this.value = value; - } - public String getName() { - return name; - } - public String getValue() { - return value; - } - - public boolean getValueAsBoolean(boolean def) { - if (value==null) return def; - if ("true".equals(value)) return true; - if ("false".equals(value)) return false; - return def; - } - - public int getValueAsInt(int def) { - if (value==null) return def; - try { - int v = Integer.parseInt(value); - return v; - }catch (NumberFormatException nfe) { - return def; - } - } - - public long getValueAsLong(long def) { - if (value==null) return def; - try { - return Long.parseLong(value); - }catch (NumberFormatException nfe) { - return def; - } - } - - public byte getValueAsByte(byte def) { - if (value==null) return def; - try { - return Byte.parseByte(value); - }catch (NumberFormatException nfe) { - return def; - } - } - - public short getValueAsShort(short def) { - if (value==null) return def; - try { - return Short.parseShort(value); - }catch (NumberFormatException nfe) { - return def; - } - } - - public float getValueAsFloat(float def) { - if (value==null) return def; - try { - return Float.parseFloat(value); - }catch (NumberFormatException nfe) { - return def; - } - } - - public double getValueAsDouble(double def) { - if (value==null) return def; - try { - return Double.parseDouble(value); - }catch (NumberFormatException nfe) { - return def; - } - } - - public char getValueAschar(char def) { - if (value==null) return def; - try { - return value.charAt(0); - }catch (StringIndexOutOfBoundsException nfe) { - return def; - } - } - @Override - public int hashCode() { - return name.hashCode(); - } - @Override - public boolean equals(Object o) { - if (o==this) return true; - if (o instanceof InterceptorProperty) { - InterceptorProperty other = (InterceptorProperty)o; - return other.name.equals(this.name); - } - return false; - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isUseEquals() { - return useEquals; - } - - /** - * {@inheritDoc} - */ - @Override - public void setUseEquals(boolean useEquals) { - this.useEquals = useEquals; - } - - /** - * {@inheritDoc} - */ - @Override - public long getMaxAge() { - return maxAge; - } - - /** - * {@inheritDoc} - */ - @Override - public void setMaxAge(long maxAge) { - this.maxAge = maxAge; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean getUseLock() { - return useLock; - } - - /** - * {@inheritDoc} - */ - @Override - public void setUseLock(boolean useLock) { - this.useLock = useLock; - } - - - /** - * {@inheritDoc} - */ - public void setDataSource(Object ds) { - this.dataSource = ds; - } - - /** - * {@inheritDoc} - */ - public Object getDataSource() { - return dataSource; - } - - - /** - * {@inheritDoc} - */ - public void setDataSourceJNDI(String jndiDS) { - this.dataSourceJNDI = jndiDS; - } - - /** - * {@inheritDoc} - */ - public String getDataSourceJNDI() { - return this.dataSourceJNDI; - } - - - public static Properties getProperties(String propText, Properties props) { - if (props==null) props = new Properties(); - if (propText != null) { - try { - props.load(new ByteArrayInputStream(propText.replace(';', '\n').getBytes())); - }catch (IOException x) { - throw new RuntimeException(x); - } - } - return props; - } -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java deleted file mode 100644 index 69f79978d33e..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java +++ /dev/null @@ -1,614 +0,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.jdbc.pool; - - -import java.sql.SQLException; -import java.sql.Statement; -import java.util.HashMap; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.jdbc.pool.interceptor.ConnectionState; - -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Represents a pooled connection - * and holds a reference to the {@link java.sql.Connection} object - * @author Filip Hanik - * @version 1.0 - */ -public class PooledConnection { - /** - * Logger - */ - private static final Log log = LogFactory.getLog(PooledConnection.class); - - /** - * Validate when connection is borrowed flag - */ - public static final int VALIDATE_BORROW = 1; - /** - * Validate when connection is returned flag - */ - public static final int VALIDATE_RETURN = 2; - /** - * Validate when connection is idle flag - */ - public static final int VALIDATE_IDLE = 3; - /** - * Validate when connection is initialized flag - */ - public static final int VALIDATE_INIT = 4; - - /** - * The properties for the connection pool - */ - protected PoolConfiguration poolProperties; - /** - * The underlying database connection - */ - private volatile java.sql.Connection connection; - - /** - * If using a XAConnection underneath. - */ - private volatile javax.sql.XAConnection xaConnection; - /** - * When we track abandon traces, this string holds the thread dump - */ - private String abandonTrace = null; - /** - * Timestamp the connection was last 'touched' by the pool - */ - private volatile long timestamp; - /** - * Lock for this connection only - */ - private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false); - /** - * Set to true if this connection has been discarded by the pool - */ - private volatile boolean discarded = false; - /** - * The Timestamp when the last time the connect() method was called successfully - */ - private volatile long lastConnected = -1; - /** - * timestamp to keep track of validation intervals - */ - private volatile long lastValidated = System.currentTimeMillis(); - /** - * The parent - */ - protected ConnectionPool parent; - - private HashMap attributes = new HashMap(); - - /** - * Weak reference to cache the list of interceptors for this connection - * so that we don't create a new list of interceptors each time we borrow - * the connection - */ - private volatile JdbcInterceptor handler = null; - - private AtomicBoolean released = new AtomicBoolean(false); - - private volatile boolean suspect = false; - - /** - * Constructor - * @param prop - pool properties - * @param parent - the parent connection pool - */ - public PooledConnection(PoolConfiguration prop, ConnectionPool parent) { - poolProperties = prop; - this.parent = parent; - } - - /** - * Connects the underlying connection to the database. - * @throws SQLException if the method {@link #release()} has been called. - * @throws SQLException if driver instantiation fails - * @throws SQLException if a call to {@link java.sql.Driver#connect(String, java.util.Properties)} fails. - * @throws SQLException if default properties are configured and a call to - * {@link java.sql.Connection#setAutoCommit(boolean)}, {@link java.sql.Connection#setCatalog(String)}, - * {@link java.sql.Connection#setTransactionIsolation(int)} or {@link java.sql.Connection#setReadOnly(boolean)} fails. - */ - public void connect() throws SQLException { - if (released.get()) throw new SQLException("A connection once released, can't be reestablished."); - if (connection != null) { - try { - this.disconnect(false); - } catch (Exception x) { - log.debug("Unable to disconnect previous connection.", x); - } //catch - } //end if - if (poolProperties.getDataSource()==null && poolProperties.getDataSourceJNDI()!=null) { - //TODO lookup JNDI name - } - - if (poolProperties.getDataSource()!=null) { - connectUsingDataSource(); - } else { - connectUsingDriver(); - } - - //set up the default state, unless we expect the interceptor to do it - if (poolProperties.getJdbcInterceptors()==null || poolProperties.getJdbcInterceptors().indexOf(ConnectionState.class.getName())<0) { - if (poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION) connection.setTransactionIsolation(poolProperties.getDefaultTransactionIsolation()); - if (poolProperties.getDefaultReadOnly()!=null) connection.setReadOnly(poolProperties.getDefaultReadOnly().booleanValue()); - if (poolProperties.getDefaultAutoCommit()!=null) connection.setAutoCommit(poolProperties.getDefaultAutoCommit().booleanValue()); - if (poolProperties.getDefaultCatalog()!=null) connection.setCatalog(poolProperties.getDefaultCatalog()); - } - this.discarded = false; - this.lastConnected = System.currentTimeMillis(); - } - - protected void connectUsingDataSource() throws SQLException { - if (poolProperties.getDataSource() instanceof javax.sql.XADataSource) { - javax.sql.XADataSource xds = (javax.sql.XADataSource)poolProperties.getDataSource(); - if (poolProperties.getUsername()!=null && poolProperties.getPassword()!=null) { - xaConnection = xds.getXAConnection(poolProperties.getUsername(), poolProperties.getPassword()); - connection = xaConnection.getConnection(); - } else { - xaConnection = xds.getXAConnection(); - connection = xaConnection.getConnection(); - } - } else if (poolProperties.getDataSource() instanceof javax.sql.DataSource){ - javax.sql.DataSource ds = (javax.sql.DataSource)poolProperties.getDataSource(); - if (poolProperties.getUsername()!=null && poolProperties.getPassword()!=null) { - connection = ds.getConnection(poolProperties.getUsername(), poolProperties.getPassword()); - } else { - connection = ds.getConnection(); - } - } else if (poolProperties.getDataSource() instanceof javax.sql.ConnectionPoolDataSource){ - javax.sql.ConnectionPoolDataSource ds = (javax.sql.ConnectionPoolDataSource)poolProperties.getDataSource(); - if (poolProperties.getUsername()!=null && poolProperties.getPassword()!=null) { - connection = ds.getPooledConnection(poolProperties.getUsername(), poolProperties.getPassword()).getConnection(); - } else { - connection = ds.getPooledConnection().getConnection(); - } - } else { - throw new SQLException("DataSource is of unknown class:"+(poolProperties.getDataSource()!=null?poolProperties.getDataSource().getClass():"null")); - } - } - protected void connectUsingDriver() throws SQLException { - java.sql.Driver driver = null; - try { - driver = (java.sql.Driver) Class.forName(poolProperties.getDriverClassName(), - true, PooledConnection.class.getClassLoader()).newInstance(); - } catch (java.lang.Exception cn) { - if (log.isDebugEnabled()) { - log.debug("Unable to instantiate JDBC driver.", cn); - } - SQLException ex = new SQLException(cn.getMessage()); - ex.initCause(cn); - throw ex; - } - String driverURL = poolProperties.getUrl(); - String usr = poolProperties.getUsername(); - String pwd = poolProperties.getPassword(); - if (usr != null) { - poolProperties.getDbProperties().setProperty("user", usr); - } - if (pwd != null) { - poolProperties.getDbProperties().setProperty("password", pwd); - } - - try { - connection = driver.connect(driverURL, poolProperties.getDbProperties()); - } catch (Exception x) { - if (log.isDebugEnabled()) { - log.debug("Unable to connect to database.", x); - } - if (parent.jmxPool!=null) { - parent.jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_CONNECT, - ConnectionPool.getStackTrace(x)); - } - if (x instanceof SQLException) { - throw (SQLException)x; - } else { - SQLException ex = new SQLException(x.getMessage()); - ex.initCause(x); - throw ex; - } - } - if (connection==null) { - throw new SQLException("Driver:"+driver+" returned null for URL:"+driverURL); - } - } - - /** - * - * @return true if connect() was called successfully and disconnect has not yet been called - */ - public boolean isInitialized() { - return connection!=null; - } - - /** - * Issues a call to {@link #disconnect(boolean)} with the argument false followed by a call to - * {@link #connect()} - * @throws SQLException if the call to {@link #connect()} fails. - */ - public void reconnect() throws SQLException { - this.disconnect(false); - this.connect(); - } //reconnect - - /** - * Disconnects the connection. All exceptions are logged using debug level. - * @param finalize if set to true, a call to {@link ConnectionPool#finalize(PooledConnection)} is called. - */ - private void disconnect(boolean finalize) { - if (isDiscarded()) { - return; - } - setDiscarded(true); - if (connection != null) { - try { - parent.disconnectEvent(this, finalize); - if (xaConnection == null) { - connection.close(); - } else { - xaConnection.close(); - } - }catch (Exception ignore) { - if (log.isDebugEnabled()) { - log.debug("Unable to close underlying SQL connection",ignore); - } - } - } - connection = null; - xaConnection = null; - lastConnected = -1; - if (finalize) parent.finalize(this); - } - - -//============================================================================ -// -//============================================================================ - - /** - * Returns abandon timeout in milliseconds - * @return abandon timeout in milliseconds - */ - public long getAbandonTimeout() { - if (poolProperties.getRemoveAbandonedTimeout() <= 0) { - return Long.MAX_VALUE; - } else { - return poolProperties.getRemoveAbandonedTimeout()*1000; - } //end if - } - - /** - * Returns true if the connection pool is configured - * to do validation for a certain action. - * @param action - * @return - */ - private boolean doValidate(int action) { - if (action == PooledConnection.VALIDATE_BORROW && - poolProperties.isTestOnBorrow()) - return true; - else if (action == PooledConnection.VALIDATE_RETURN && - poolProperties.isTestOnReturn()) - return true; - else if (action == PooledConnection.VALIDATE_IDLE && - poolProperties.isTestWhileIdle()) - return true; - else if (action == PooledConnection.VALIDATE_INIT && - poolProperties.isTestOnConnect()) - return true; - else if (action == PooledConnection.VALIDATE_INIT && - poolProperties.getInitSQL()!=null) - return true; - else - return false; - } - - /**Returns true if the object is still valid. if not - * the pool will call the getExpiredAction() and follow up with one - * of the four expired methods - */ - public boolean validate(int validateAction) { - return validate(validateAction,null); - } - - /** - * Validates a connection. - * @param validateAction the action used. One of {@link #VALIDATE_BORROW}, {@link #VALIDATE_IDLE}, - * {@link #VALIDATE_INIT} or {@link #VALIDATE_RETURN} - * @param sql the SQL to be used during validation. If the {@link PoolConfiguration#setInitSQL(String)} has been called with a non null - * value and the action is {@link #VALIDATE_INIT} the init SQL will be used for validation. - * - * @return true if the connection was validated successfully. It returns true even if validation was not performed, such as when - * {@link PoolConfiguration#setValidationInterval(long)} has been called with a positive value. - *

    - * false if the validation failed. The caller should close the connection if false is returned since a session could have been left in - * an unknown state during initialization. - */ - public boolean validate(int validateAction,String sql) { - if (this.isDiscarded()) { - return false; - } - - if (!doValidate(validateAction)) { - //no validation required, no init sql and props not set - return true; - } - - //Don't bother validating if already have recently enough - long now = System.currentTimeMillis(); - if (validateAction!=VALIDATE_INIT && - poolProperties.getValidationInterval() > 0 && - (now - this.lastValidated) < - poolProperties.getValidationInterval()) { - return true; - } - - if (poolProperties.getValidator() != null) { - return poolProperties.getValidator().validate(connection, validateAction); - } - - String query = sql; - - if (validateAction == VALIDATE_INIT && poolProperties.getInitSQL() != null) { - query = poolProperties.getInitSQL(); - } - - if (query == null) { - query = poolProperties.getValidationQuery(); - } - - Statement stmt = null; - try { - stmt = connection.createStatement(); - stmt.execute(query); - stmt.close(); - this.lastValidated = now; - return true; - } catch (Exception ignore) { - if (log.isDebugEnabled()) - log.debug("Unable to validate object:",ignore); - if (stmt!=null) - try { stmt.close();} catch (Exception ignore2){/*NOOP*/} - } - return false; - } //validate - - /** - * The time limit for how long the object - * can remain unused before it is released - * @return {@link PoolConfiguration#getMinEvictableIdleTimeMillis()} - */ - public long getReleaseTime() { - return this.poolProperties.getMinEvictableIdleTimeMillis(); - } - - /** - * This method is called if (Now - timeCheckedIn > getReleaseTime()) - * This method disconnects the connection, logs an error in debug mode if it happens - * then sets the {@link #released} flag to false. Any attempts to connect this cached object again - * will fail per {@link #connect()} - * The connection pool uses the atomic return value to decrement the pool size counter. - * @return true if this is the first time this method has been called. false if this method has been called before. - */ - public boolean release() { - try { - disconnect(true); - } catch (Exception x) { - if (log.isDebugEnabled()) { - log.debug("Unable to close SQL connection",x); - } - } - return released.compareAndSet(false, true); - - } - - /** - * The pool will set the stack trace when it is check out and - * checked in - * @param trace the stack trace for this connection - */ - - public void setStackTrace(String trace) { - abandonTrace = trace; - } - - /** - * Returns the stack trace from when this connection was borrowed. Can return null if no stack trace was set. - * @return the stack trace or null of no trace was set - */ - public String getStackTrace() { - return abandonTrace; - } - - /** - * Sets a timestamp on this connection. A timestamp usually means that some operation - * performed successfully. - * @param timestamp the timestamp as defined by {@link System#currentTimeMillis()} - */ - public void setTimestamp(long timestamp) { - this.timestamp = timestamp; - setSuspect(false); - } - - - public boolean isSuspect() { - return suspect; - } - - public void setSuspect(boolean suspect) { - this.suspect = suspect; - } - - /** - * An interceptor can call this method with the value true, and the connection will be closed when it is returned to the pool. - * @param discarded - only valid value is true - * @throws IllegalStateException if this method is called with the value false and the value true has already been set. - */ - public void setDiscarded(boolean discarded) { - if (this.discarded && !discarded) throw new IllegalStateException("Unable to change the state once the connection has been discarded"); - this.discarded = discarded; - } - - /** - * Set the timestamp the connection was last validated. - * This flag is used to keep track when we are using a {@link PoolConfiguration#setValidationInterval(long) validation-interval}. - * @param lastValidated a timestamp as defined by {@link System#currentTimeMillis()} - */ - public void setLastValidated(long lastValidated) { - this.lastValidated = lastValidated; - } - - /** - * Sets the pool configuration for this connection and connection pool. - * Object is shared with the {@link ConnectionPool} - * @param poolProperties - */ - public void setPoolProperties(PoolConfiguration poolProperties) { - this.poolProperties = poolProperties; - } - - /** - * Return the timestamps of last pool action. Timestamps are typically set when connections - * are borrowed from the pool. It is used to keep track of {@link PoolConfiguration#setRemoveAbandonedTimeout(int) abandon-timeouts}. - * This timestamp can also be reset by the {@link org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer#invoke(Object, java.lang.reflect.Method, Object[])} - * @return the timestamp of the last pool action as defined by {@link System#currentTimeMillis()} - */ - public long getTimestamp() { - return timestamp; - } - - /** - * Returns the discarded flag. - * @return the discarded flag. If the value is true, - * either {@link #disconnect(boolean)} has been called or it will be called when the connection is returned to the pool. - */ - public boolean isDiscarded() { - return discarded; - } - - /** - * Returns the timestamp of the last successful validation query execution. - * @return the timestamp of the last successful validation query execution as defined by {@link System#currentTimeMillis()} - */ - public long getLastValidated() { - return lastValidated; - } - - /** - * Returns the configuration for this connection and pool - * @return the configuration for this connection and pool - */ - public PoolConfiguration getPoolProperties() { - return poolProperties; - } - - /** - * Locks the connection only if either {@link PoolConfiguration#isPoolSweeperEnabled()} or - * {@link PoolConfiguration#getUseLock()} return true. The per connection lock ensures thread safety is - * multiple threads are performing operations on the connection. - * Otherwise this is a noop for performance - */ - public void lock() { - if (poolProperties.getUseLock() || this.poolProperties.isPoolSweeperEnabled()) { - //optimized, only use a lock when there is concurrency - lock.writeLock().lock(); - } - } - - /** - * Unlocks the connection only if the sweeper is enabled - * Otherwise this is a noop for performance - */ - public void unlock() { - if (poolProperties.getUseLock() || this.poolProperties.isPoolSweeperEnabled()) { - //optimized, only use a lock when there is concurrency - lock.writeLock().unlock(); - } - } - - /** - * Returns the underlying connection - * @return the underlying JDBC connection as it was returned from the JDBC driver - * @see javax.sql.PooledConnection#getConnection() - */ - public java.sql.Connection getConnection() { - return this.connection; - } - - /** - * Returns the underlying XA connection - * @return the underlying XA connection as it was returned from the Datasource - */ - public javax.sql.XAConnection getXAConnection() { - return this.xaConnection; - } - - - /** - * Returns the timestamp of when the connection was last connected to the database. - * ie, a successful call to {@link java.sql.Driver#connect(String, java.util.Properties)}. - * @return the timestamp when this connection was created as defined by {@link System#currentTimeMillis()} - */ - public long getLastConnected() { - return lastConnected; - } - - /** - * Returns the first handler in the interceptor chain - * @return the first interceptor for this connection - */ - public JdbcInterceptor getHandler() { - return handler; - } - - public void setHandler(JdbcInterceptor handler) { - if (this.handler!=null && this.handler!=handler) { - JdbcInterceptor interceptor = this.handler; - while (interceptor!=null) { - interceptor.reset(null, null); - interceptor = interceptor.getNext(); - }//while - }//end if - this.handler = handler; - } - - @Override - public String toString() { - return "PooledConnection["+(connection!=null?connection.toString():"null")+"]"; - } - - /** - * Returns true if this connection has been released and wont be reused. - * @return true if the method {@link #release()} has been called - */ - public boolean isReleased() { - return released.get(); - } - - public HashMap getAttributes() { - return attributes; - } - -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ProxyConnection.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ProxyConnection.java deleted file mode 100644 index 532cb6a247e1..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ProxyConnection.java +++ /dev/null @@ -1,153 +0,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.jdbc.pool; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.sql.SQLException; - -import javax.sql.XAConnection; -/** - * A ProxyConnection object is the bottom most interceptor that wraps an object of type - * {@link PooledConnection}. The ProxyConnection intercepts three methods: - *

      - *
    • {@link java.sql.Connection#close()} - returns the connection to the pool. May be called multiple times.
    • - *
    • {@link java.lang.Object#toString()} - returns a custom string for this object
    • - *
    • {@link javax.sql.PooledConnection#getConnection()} - returns the underlying connection
    • - *
    - * By default method comparisons is done on a String reference level, unless the {@link PoolConfiguration#setUseEquals(boolean)} has been called - * with a true argument. - * @author Filip Hanik - */ -public class ProxyConnection extends JdbcInterceptor { - - protected PooledConnection connection = null; - - protected ConnectionPool pool = null; - - public PooledConnection getConnection() { - return connection; - } - - public void setConnection(PooledConnection connection) { - this.connection = connection; - } - - public ConnectionPool getPool() { - return pool; - } - - public void setPool(ConnectionPool pool) { - this.pool = pool; - } - - protected ProxyConnection(ConnectionPool parent, PooledConnection con, boolean useEquals) throws SQLException { - pool = parent; - connection = con; - setUseEquals(useEquals); - } - - @Override - public void reset(ConnectionPool parent, PooledConnection con) { - this.pool = parent; - this.connection = con; - } - - public boolean isWrapperFor(Class iface) throws SQLException { - if (iface == XAConnection.class && connection.getXAConnection()!=null) { - return true; - } else { - return (iface.isInstance(connection.getConnection())); - } - } - - - public Object unwrap(Class iface) throws SQLException { - if (iface == PooledConnection.class) { - return connection; - }else if (iface == XAConnection.class) { - return connection.getXAConnection(); - } else if (isWrapperFor(iface)) { - return connection.getConnection(); - } else { - throw new SQLException("Not a wrapper of "+iface.getName()); - } - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if (compare(ISCLOSED_VAL,method)) { - return Boolean.valueOf(isClosed()); - } - if (compare(CLOSE_VAL,method)) { - if (isClosed()) return null; //noop for already closed. - PooledConnection poolc = this.connection; - this.connection = null; - pool.returnConnection(poolc); - return null; - } else if (compare(TOSTRING_VAL,method)) { - return this.toString(); - } else if (compare(GETCONNECTION_VAL,method) && connection!=null) { - return connection.getConnection(); - } else if (method.getDeclaringClass().equals(XAConnection.class)) { - try { - return method.invoke(connection.getXAConnection(),args); - }catch (Throwable t) { - if (t instanceof InvocationTargetException) { - InvocationTargetException it = (InvocationTargetException)t; - throw it.getCause()!=null?it.getCause():it; - } else { - throw t; - } - } - } - if (isClosed()) throw new SQLException("Connection has already been closed."); - if (compare(UNWRAP_VAL,method)) { - return unwrap((Class)args[0]); - } else if (compare(ISWRAPPERFOR_VAL,method)) { - return this.isWrapperFor((Class)args[0]); - } - try { - return method.invoke(connection.getConnection(),args); - }catch (Throwable t) { - if (t instanceof InvocationTargetException) { - InvocationTargetException it = (InvocationTargetException)t; - throw it.getCause()!=null?it.getCause():it; - } else { - throw t; - } - } - } - - public boolean isClosed() { - return connection==null || connection.isDiscarded(); - } - - public PooledConnection getDelegateConnection() { - return connection; - } - - public ConnectionPool getParentPool() { - return pool; - } - - @Override - public String toString() { - return "ProxyConnection["+(connection!=null?connection.toString():"null")+"]"; - } - -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/Validator.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/Validator.java deleted file mode 100644 index 4f286ef13f0d..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/Validator.java +++ /dev/null @@ -1,37 +0,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.jdbc.pool; - -import java.sql.Connection; - -/** - * Interface to be implemented by custom validator classes. - * - * @author mpassell - */ -public interface Validator { - /** - * Validate a connection and return a boolean to indicate if it's valid. - * - * @param connection the Connection object to test - * @param validateAction the action used. One of {@link PooledConnection#VALIDATE_BORROW}, - * {@link PooledConnection#VALIDATE_IDLE}, {@link PooledConnection#VALIDATE_INIT} or - * {@link PooledConnection#VALIDATE_RETURN} - * @return true if the connection is valid - */ - public boolean validate(Connection connection, int validateAction); -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/XADataSource.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/XADataSource.java deleted file mode 100644 index ce829d3a682c..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/XADataSource.java +++ /dev/null @@ -1,37 +0,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.jdbc.pool; - -public class XADataSource extends DataSource implements javax.sql.XADataSource { - - /** - * Constructor for reflection only. A default set of pool properties will be created. - */ - public XADataSource() { - super(); - } - - /** - * Constructs a DataSource object wrapping a connection - * @param poolProperties - */ - public XADataSource(PoolConfiguration poolProperties) { - super(poolProperties); - } - -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java deleted file mode 100644 index 19a13ed73b70..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java +++ /dev/null @@ -1,138 +0,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.jdbc.pool.interceptor; - -import java.lang.reflect.Method; - -import org.apache.tomcat.jdbc.pool.ConnectionPool; -import org.apache.tomcat.jdbc.pool.JdbcInterceptor; -import org.apache.tomcat.jdbc.pool.PooledConnection; - -/** - * Abstraction interceptor. This component intercepts all calls to create some type of SQL statement. - * By extending this class, one can intercept queries and update statements by overriding the {@link #createStatement(Object, Method, Object[], Object, long)} - * method. - * @author Filip Hanik - * @version 1.0 - */ -public abstract class AbstractCreateStatementInterceptor extends JdbcInterceptor { - protected static final String CREATE_STATEMENT = "createStatement"; - protected static final int CREATE_STATEMENT_IDX = 0; - protected static final String PREPARE_STATEMENT = "prepareStatement"; - protected static final int PREPARE_STATEMENT_IDX = 1; - protected static final String PREPARE_CALL = "prepareCall"; - protected static final int PREPARE_CALL_IDX = 2; - - protected static final String[] STATEMENT_TYPES = {CREATE_STATEMENT, PREPARE_STATEMENT, PREPARE_CALL}; - protected static final int STATEMENT_TYPE_COUNT = STATEMENT_TYPES.length; - - protected static final String EXECUTE = "execute"; - protected static final String EXECUTE_QUERY = "executeQuery"; - protected static final String EXECUTE_UPDATE = "executeUpdate"; - protected static final String EXECUTE_BATCH = "executeBatch"; - - protected static final String[] EXECUTE_TYPES = {EXECUTE, EXECUTE_QUERY, EXECUTE_UPDATE, EXECUTE_BATCH}; - - public AbstractCreateStatementInterceptor() { - super(); - } - - /** - * {@inheritDoc} - */ - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if (compare(CLOSE_VAL,method)) { - closeInvoked(); - return super.invoke(proxy, method, args); - } else { - boolean process = false; - process = isStatement(method, process); - if (process) { - long start = System.currentTimeMillis(); - Object statement = super.invoke(proxy,method,args); - long delta = System.currentTimeMillis() - start; - return createStatement(proxy,method,args,statement, delta); - } else { - return super.invoke(proxy,method,args); - } - } - } - - /** - * This method will be invoked after a successful statement creation. This method can choose to return a wrapper - * around the statement or return the statement itself. - * If this method returns a wrapper then it should return a wrapper object that implements one of the following interfaces. - * {@link java.sql.Statement}, {@link java.sql.PreparedStatement} or {@link java.sql.CallableStatement} - * @param proxy the actual proxy object - * @param method the method that was called. It will be one of the methods defined in {@link #STATEMENT_TYPES} - * @param args the arguments to the method - * @param statement the statement that the underlying connection created - * @return a {@link java.sql.Statement} object - */ - public abstract Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time); - - /** - * Method invoked when the operation {@link java.sql.Connection#close()} is invoked. - */ - public abstract void closeInvoked(); - - /** - * Returns true if the method that is being invoked matches one of the statement types. - * - * @param method the method being invoked on the proxy - * @param process boolean result used for recursion - * @return returns true if the method name matched - */ - protected boolean isStatement(Method method, boolean process){ - return process(STATEMENT_TYPES, method, process); - } - - /** - * Returns true if the method that is being invoked matches one of the execute types. - * - * @param method the method being invoked on the proxy - * @param process boolean result used for recursion - * @return returns true if the method name matched - */ - protected boolean isExecute(Method method, boolean process){ - return process(EXECUTE_TYPES, method, process); - } - - /* - * Returns true if the method that is being invoked matches one of the method names passed in - * @param names list of method names that we want to intercept - * @param method the method being invoked on the proxy - * @param process boolean result used for recursion - * @return returns true if the method name matched - */ - protected boolean process(String[] names, Method method, boolean process) { - final String name = method.getName(); - for (int i=0; (!process) && i[] constructors = - new Constructor[AbstractCreateStatementInterceptor.STATEMENT_TYPE_COUNT]; - - - public AbstractQueryReport() { - super(); - } - - /** - * Invoked when prepareStatement has been called and completed. - * @param sql - the string used to prepare the statement with - * @param time - the time it took to invoke prepare - */ - protected abstract void prepareStatement(String sql, long time); - - /** - * Invoked when prepareCall has been called and completed. - * @param query - the string used to prepare the statement with - * @param time - the time it took to invoke prepare - */ - protected abstract void prepareCall(String query, long time); - - /** - * Invoked when a query execution, a call to execute/executeQuery or executeBatch failed. - * @param query the query that was executed and failed - * @param args the arguments to the execution - * @param name the name of the method used to execute {@link AbstractCreateStatementInterceptor#isExecute(Method, boolean)} - * @param start the time the query execution started - * @param t the exception that happened - * @return - the SQL that was executed or the string "batch" if it was a batch execution - */ - protected String reportFailedQuery(String query, Object[] args, final String name, long start, Throwable t) { - //extract the query string - String sql = (query==null && args!=null && args.length>0)?(String)args[0]:query; - //if we do batch execution, then we name the query 'batch' - if (sql==null && compare(EXECUTE_BATCH,name)) { - sql = "batch"; - } - return sql; - } - - /** - * Invoked when a query execution, a call to execute/executeQuery or executeBatch succeeded and was within the timing threshold - * @param query the query that was executed and failed - * @param args the arguments to the execution - * @param name the name of the method used to execute {@link AbstractCreateStatementInterceptor#isExecute(Method, boolean)} - * @param start the time the query execution started - * @param delta the time the execution took - * @return - the SQL that was executed or the string "batch" if it was a batch execution - */ - protected String reportQuery(String query, Object[] args, final String name, long start, long delta) { - //extract the query string - String sql = (query==null && args!=null && args.length>0)?(String)args[0]:query; - //if we do batch execution, then we name the query 'batch' - if (sql==null && compare(EXECUTE_BATCH,name)) { - sql = "batch"; - } - return sql; - } - - /** - * Invoked when a query execution, a call to execute/executeQuery or executeBatch succeeded and was exceeded the timing threshold - * @param query the query that was executed and failed - * @param args the arguments to the execution - * @param name the name of the method used to execute {@link AbstractCreateStatementInterceptor#isExecute(Method, boolean)} - * @param start the time the query execution started - * @param delta the time the execution took - * @return - the SQL that was executed or the string "batch" if it was a batch execution - */ - protected String reportSlowQuery(String query, Object[] args, final String name, long start, long delta) { - //extract the query string - String sql = (query==null && args!=null && args.length>0)?(String)args[0]:query; - //if we do batch execution, then we name the query 'batch' - if (sql==null && compare(EXECUTE_BATCH,name)) { - sql = "batch"; - } - return sql; - } - - /** - * returns the query measure threshold. - * This value is in milliseconds. If the query is faster than this threshold than it wont be accounted for - * @return the threshhold in milliseconds - */ - public long getThreshold() { - return threshold; - } - - /** - * Sets the query measurement threshold. The value is in milliseconds. - * If the query goes faster than this threshold it will not be recorded. - * @param threshold set to -1 to record every query. Value is in milliseconds. - */ - public void setThreshold(long threshold) { - this.threshold = threshold; - } - - /** - * Creates a constructor for a proxy class, if one doesn't already exist - * @param idx - the index of the constructor - * @param clazz - the interface that the proxy will implement - * @return - returns a constructor used to create new instances - * @throws NoSuchMethodException - */ - protected Constructor getConstructor(int idx, Class clazz) throws NoSuchMethodException { - if (constructors[idx]==null) { - Class proxyClass = Proxy.getProxyClass(SlowQueryReport.class.getClassLoader(), new Class[] {clazz}); - constructors[idx] = proxyClass.getConstructor(new Class[] { InvocationHandler.class }); - } - return constructors[idx]; - } - - /** - * Creates a statement interceptor to monitor query response times - */ - @Override - public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) { - try { - Object result = null; - String name = method.getName(); - String sql = null; - Constructor constructor = null; - if (compare(CREATE_STATEMENT,name)) { - //createStatement - constructor = getConstructor(CREATE_STATEMENT_IDX,Statement.class); - }else if (compare(PREPARE_STATEMENT,name)) { - //prepareStatement - sql = (String)args[0]; - constructor = getConstructor(PREPARE_STATEMENT_IDX,PreparedStatement.class); - if (sql!=null) { - prepareStatement(sql, time); - } - }else if (compare(PREPARE_CALL,name)) { - //prepareCall - sql = (String)args[0]; - constructor = getConstructor(PREPARE_CALL_IDX,CallableStatement.class); - prepareCall(sql,time); - }else { - //do nothing, might be a future unsupported method - //so we better bail out and let the system continue - return statement; - } - result = constructor.newInstance(new Object[] { new StatementProxy(statement,sql) }); - return result; - }catch (Exception x) { - log.warn("Unable to create statement proxy for slow query report.",x); - } - return statement; - } - - - /** - * Class to measure query execute time - * @author fhanik - * - */ - protected class StatementProxy implements InvocationHandler { - protected boolean closed = false; - protected Object delegate; - protected final String query; - public StatementProxy(Object parent, String query) { - this.delegate = parent; - this.query = query; - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - //get the name of the method for comparison - final String name = method.getName(); - //was close invoked? - boolean close = compare(JdbcInterceptor.CLOSE_VAL,name); - //allow close to be called multiple times - if (close && closed) return null; - //are we calling isClosed? - if (compare(JdbcInterceptor.ISCLOSED_VAL,name)) return Boolean.valueOf(closed); - //if we are calling anything else, bail out - if (closed) throw new SQLException("Statement closed."); - boolean process = false; - //check to see if we are about to execute a query - process = isExecute( method, process); - //if we are executing, get the current time - long start = (process)?System.currentTimeMillis():0; - Object result = null; - try { - //execute the query - result = method.invoke(delegate,args); - }catch (Throwable t) { - reportFailedQuery(query,args,name,start,t); - if (t instanceof InvocationTargetException) { - InvocationTargetException it = (InvocationTargetException)t; - throw it.getCause()!=null?it.getCause():it; - } else { - throw t; - } - } - //measure the time - long delta = (process)?(System.currentTimeMillis()-start):Long.MIN_VALUE; - //see if we meet the requirements to measure - if (delta>threshold) { - try { - //report the slow query - reportSlowQuery(query, args, name, start, delta); - }catch (Exception t) { - if (log.isWarnEnabled()) log.warn("Unable to process slow query",t); - } - } else if (process) { - reportQuery(query, args, name, start, delta); - } - //perform close cleanup - if (close) { - closed=true; - delegate = null; - } - return result; - } - } - -} \ No newline at end of file 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 deleted file mode 100644 index a56d969684ca..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java +++ /dev/null @@ -1,145 +0,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.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.PoolConfiguration; -import org.apache.tomcat.jdbc.pool.PooledConnection; - -/** - * Interceptor that keep track of connection state to avoid roundtrips to the database. - * The {@link org.apache.tomcat.jdbc.pool.ConnectionPool} is optimized to do as little work as possible. - * The pool itself doesn't remember settings like {@link java.sql.Connection#setAutoCommit(boolean)}, - * {@link java.sql.Connection#setReadOnly(boolean)}, {@link java.sql.Connection#setCatalog(String)} or - * {@link java.sql.Connection#setTransactionIsolation(int)}. It relies on the application to remember how and when - * these settings have been applied. - * In the cases where the application code doesn't know or want to keep track of the state, this interceptor helps cache the - * state, and it also avoids roundtrips to the database asking for it. - * @author fhanik - * - */ - -public class ConnectionState extends JdbcInterceptor { - private static final 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; - - - @Override - public void reset(ConnectionPool parent, PooledConnection con) { - if (parent==null || con==null) return; - PoolConfiguration poolProperties = parent.getPoolProperties(); - if (poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION) { - try { - if (transactionIsolation==null || transactionIsolation.intValue()!=poolProperties.getDefaultTransactionIsolation()) { - con.getConnection().setTransactionIsolation(poolProperties.getDefaultTransactionIsolation()); - transactionIsolation = Integer.valueOf(poolProperties.getDefaultTransactionIsolation()); - } - }catch (SQLException x) { - transactionIsolation = null; - log.error("Unable to reset transaction isolation state to connection.",x); - } - } - 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); - } - } - - } - - @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 ConcurrentHashMap>(); - /** - * the queries that are used for this interceptor. - */ - protected ConcurrentHashMap queries = null; - /** - * Maximum number of queries we will be storing - */ - protected int maxQueries= 1000; //don't store more than this amount of queries - - /** - * Returns the query stats for a given pool - * @param poolname - the name of the pool we want to retrieve stats for - * @return a hash map containing statistics for 0 to maxQueries - */ - public static ConcurrentHashMap getPoolStats(String poolname) { - return perPoolStats.get(poolname); - } - - /** - * Creates a slow query report interceptor - */ - public SlowQueryReport() { - super(); - } - - public void setMaxQueries(int maxQueries) { - this.maxQueries = maxQueries; - } - - - @Override - protected String reportFailedQuery(String query, Object[] args, String name, long start, Throwable t) { - String sql = super.reportFailedQuery(query, args, name, start, t); - if (this.maxQueries > 0 ) { - long now = System.currentTimeMillis(); - long delta = now - start; - QueryStats qs = this.getQueryStats(sql); - qs.failure(delta, now); - } - return sql; - } - - @Override - protected String reportSlowQuery(String query, Object[] args, String name, long start, long delta) { - String sql = super.reportSlowQuery(query, args, name, start, delta); - if (this.maxQueries > 0 ) { - QueryStats qs = this.getQueryStats(sql); - qs.add(delta, start); - } - return sql; - } - - /** - * invoked when the connection receives the close request - * Not used for now. - */ - @Override - public void closeInvoked() { - queries = null; - } - - @Override - public void prepareStatement(String sql, long time) { - QueryStats qs = getQueryStats(sql); - qs.prepare(time, System.currentTimeMillis()); - } - - @Override - public void prepareCall(String sql, long time) { - QueryStats qs = getQueryStats(sql); - qs.prepare(time, System.currentTimeMillis()); - } - - /** - * {@inheritDoc} - */ - @Override - public void poolStarted(ConnectionPool pool) { - super.poolStarted(pool); - //see if we already created a map for this pool - queries = SlowQueryReport.perPoolStats.get(pool.getName()); - if (queries==null) { - //create the map to hold our stats - //however TODO we need to improve the eviction - //selection - queries = new ConcurrentHashMap() { - - }; - if (perPoolStats.putIfAbsent(pool.getName(), queries)!=null) { - //there already was one - queries = SlowQueryReport.perPoolStats.get(pool.getName()); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public void poolClosed(ConnectionPool pool) { - perPoolStats.remove(pool.getName()); - super.poolClosed(pool); - } - - protected QueryStats getQueryStats(String sql) { - ConcurrentHashMap queries = SlowQueryReport.this.queries; - if (queries==null) return null; - QueryStats qs = queries.get(sql); - if (qs == null) { - qs = new QueryStats(sql); - if (queries.putIfAbsent(sql,qs)!=null) { - qs = queries.get(sql); - } else { - //we added a new element, see if we need to remove the oldest - if (queries.size() > maxQueries) { - removeOldest(queries); - } - } - } - return qs; - } - - /** - * TODO - implement a better algorithm - * @param queries - */ - protected void removeOldest(ConcurrentHashMap queries) { - Iterator it = queries.keySet().iterator(); - while (queries.size()>maxQueries && it.hasNext()) { - String sql = it.next(); - it.remove(); - if (log.isDebugEnabled()) log.debug("Removing slow query, capacity reached:"+sql); - } - } - - - @Override - public void reset(ConnectionPool parent, PooledConnection con) { - super.reset(parent, con); - if (parent!=null) - queries = SlowQueryReport.perPoolStats.get(parent.getName()); - } - - - @Override - public void setProperties(Map properties) { - super.setProperties(properties); - final String threshold = "threshold"; - final String maxqueries= "maxQueries"; - InterceptorProperty p1 = properties.get(threshold); - InterceptorProperty p2 = properties.get(maxqueries); - if (p1!=null) { - setThreshold(Long.parseLong(p1.getValue())); - } - if (p2!=null) { - setMaxQueries(Integer.parseInt(p2.getValue())); - } - } - - - /** - * - * @author fhanik - * - */ - public static class QueryStats { - static final String[] FIELD_NAMES = new String[] { - "query", - "nrOfInvocations", - "maxInvocationTime", - "maxInvocationDate", - "minInvocationTime", - "minInvocationDate", - "totalInvocationTime", - "failures", - "prepareCount", - "prepareTime", - "lastInvocation" - }; - - static final String[] FIELD_DESCRIPTIONS = new String[] { - "The SQL query", - "The number of query invocations, a call to executeXXX", - "The longest time for this query in milliseconds", - "The time and date for when the longest query took place", - "The shortest time for this query in milliseconds", - "The time and date for when the shortest query took place", - "The total amount of milliseconds spent executing this query", - "The number of failures for this query", - "The number of times this query was prepared (prepareStatement/prepareCall)", - "The total number of milliseconds spent preparing this query", - "The date and time of the last invocation" - }; - - static final OpenType[] FIELD_TYPES = new OpenType[] { - SimpleType.STRING, - SimpleType.INTEGER, - SimpleType.LONG, - SimpleType.LONG, - SimpleType.LONG, - SimpleType.LONG, - SimpleType.LONG, - SimpleType.LONG, - SimpleType.INTEGER, - SimpleType.LONG, - SimpleType.LONG - }; - - private final String query; - private int nrOfInvocations; - private long maxInvocationTime = Long.MIN_VALUE; - private long maxInvocationDate; - private long minInvocationTime = Long.MAX_VALUE; - private long minInvocationDate; - private long totalInvocationTime; - private long failures; - private int prepareCount; - private long prepareTime; - private volatile long lastInvocation = 0; - - public static String[] getFieldNames() { - return FIELD_NAMES; - } - - public static String[] getFieldDescriptions() { - return FIELD_DESCRIPTIONS; - } - - public static OpenType[] getFieldTypes() { - return FIELD_TYPES; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder("QueryStats[query:"); - buf.append(query); - buf.append(", nrOfInvocations:"); - buf.append(nrOfInvocations); - buf.append(", maxInvocationTime:"); - buf.append(maxInvocationTime); - buf.append(", maxInvocationDate:"); - buf.append(new java.util.Date(maxInvocationDate).toGMTString()); - buf.append(", minInvocationTime:"); - buf.append(minInvocationTime); - buf.append(", minInvocationDate:"); - buf.append(new java.util.Date(minInvocationDate).toGMTString()); - buf.append(", totalInvocationTime:"); - buf.append(totalInvocationTime); - buf.append(", averageInvocationTime:"); - buf.append((float)totalInvocationTime / (float)nrOfInvocations); - buf.append(", failures:"); - buf.append(failures); - buf.append(", prepareCount:"); - buf.append(prepareCount); - buf.append(", prepareTime:"); - buf.append(prepareTime); - buf.append("]"); - return buf.toString(); - } - - public CompositeDataSupport getCompositeData(final CompositeType type) throws OpenDataException{ - Object[] values = new Object[] { - query, - Integer.valueOf(nrOfInvocations), - Long.valueOf(maxInvocationTime), - Long.valueOf(maxInvocationDate), - Long.valueOf(minInvocationTime), - Long.valueOf(minInvocationDate), - Long.valueOf(totalInvocationTime), - Long.valueOf(failures), - Integer.valueOf(prepareCount), - Long.valueOf(prepareTime), - Long.valueOf(lastInvocation) - }; - return new CompositeDataSupport(type,FIELD_NAMES,values); - } - - public QueryStats(String query) { - this.query = query; - } - - public void prepare(long invocationTime, long now) { - prepareCount++; - prepareTime+=invocationTime; - - } - - public void add(long invocationTime, long now) { - //not thread safe, but don't sacrifice performance for this kind of stuff - maxInvocationTime = Math.max(invocationTime, maxInvocationTime); - if (maxInvocationTime == invocationTime) { - maxInvocationDate = now; - } - minInvocationTime = Math.min(invocationTime, minInvocationTime); - if (minInvocationTime==invocationTime) { - minInvocationDate = now; - } - nrOfInvocations++; - totalInvocationTime+=invocationTime; - lastInvocation = now; - } - - public void failure(long invocationTime, long now) { - add(invocationTime,now); - failures++; - - } - - public String getQuery() { - return query; - } - - public int getNrOfInvocations() { - return nrOfInvocations; - } - - public long getMaxInvocationTime() { - return maxInvocationTime; - } - - public long getMaxInvocationDate() { - return maxInvocationDate; - } - - public long getMinInvocationTime() { - return minInvocationTime; - } - - public long getMinInvocationDate() { - return minInvocationDate; - } - - public long getTotalInvocationTime() { - return totalInvocationTime; - } - - @Override - public int hashCode() { - return query.hashCode(); - } - - @Override - public boolean equals(Object other) { - if (other instanceof QueryStats) { - QueryStats qs = (QueryStats)other; - return qs.query.equals(this.query); - } - return false; - } - - public boolean isOlderThan(QueryStats other) { - return this.lastInvocation < other.lastInvocation; - } - } - - -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java deleted file mode 100644 index 433519c9082c..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java +++ /dev/null @@ -1,307 +0,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.jdbc.pool.interceptor; - -import java.lang.management.ManagementFactory; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; - -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanRegistrationException; -import javax.management.MalformedObjectNameException; -import javax.management.NotCompliantMBeanException; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.RuntimeOperationsException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenDataException; - -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.PooledConnection; -import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty; -/** - * Publishes data to JMX and provides notifications - * when failures happen. - * @author fhanik - * - */ -public class SlowQueryReportJmx extends SlowQueryReport implements NotificationEmitter, SlowQueryReportJmxMBean{ - public static final String SLOW_QUERY_NOTIFICATION = "SLOW QUERY"; - public static final String FAILED_QUERY_NOTIFICATION = "FAILED QUERY"; - - protected static CompositeType SLOW_QUERY_TYPE; - - private static final Log log = LogFactory.getLog(SlowQueryReportJmx.class); - - - protected static ConcurrentHashMap mbeans = - new ConcurrentHashMap(); - - - //==============================JMX STUFF======================== - protected volatile NotificationBroadcasterSupport notifier = new NotificationBroadcasterSupport(); - - public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException { - notifier.addNotificationListener(listener, filter, handback); - } - - - public MBeanNotificationInfo[] getNotificationInfo() { - return notifier.getNotificationInfo(); - } - - public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { - notifier.removeNotificationListener(listener); - - } - - public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException { - notifier.removeNotificationListener(listener, filter, handback); - - } - - - //==============================JMX STUFF======================== - - protected String poolName = null; - - protected static AtomicLong notifySequence = new AtomicLong(0); - - protected boolean notifyPool = true; - - protected ConnectionPool pool = null; - - protected static CompositeType getCompositeType() { - if (SLOW_QUERY_TYPE==null) { - try { - SLOW_QUERY_TYPE = new CompositeType( - SlowQueryReportJmx.class.getName(), - "Composite data type for query statistics", - QueryStats.getFieldNames(), - QueryStats.getFieldDescriptions(), - QueryStats.getFieldTypes()); - }catch (OpenDataException x) { - log.warn("Unable to initialize composite data type for JMX stats and notifications.",x); - } - } - return SLOW_QUERY_TYPE; - } - - @Override - public void reset(ConnectionPool parent, PooledConnection con) { - // TODO Auto-generated method stub - super.reset(parent, con); - if (parent!=null) { - poolName = parent.getName(); - pool = parent; - registerJmx(); - } - } - - - @Override - public void poolClosed(ConnectionPool pool) { - this.poolName = pool.getName(); - deregisterJmx(); - super.poolClosed(pool); - } - - @Override - public void poolStarted(ConnectionPool pool) { - this.pool = pool; - super.poolStarted(pool); - this.poolName = pool.getName(); - } - - @Override - protected String reportFailedQuery(String query, Object[] args, String name, long start, Throwable t) { - query = super.reportFailedQuery(query, args, name, start, t); - notifyJmx(query,FAILED_QUERY_NOTIFICATION); - return query; - } - - protected void notifyJmx(String query, String type) { - try { - long sequence = notifySequence.incrementAndGet(); - - if (isNotifyPool()) { - if (this.pool!=null && this.pool.getJmxPool()!=null) { - this.pool.getJmxPool().notify(type, query); - } - } else { - if (notifier!=null) { - Notification notification = - new Notification(type, - this, - sequence, - System.currentTimeMillis(), - query); - - notifier.sendNotification(notification); - } - } - } catch (RuntimeOperationsException e) { - if (log.isDebugEnabled()) { - log.debug("Unable to send failed query notification.",e); - } - } - } - - @Override - protected String reportSlowQuery(String query, Object[] args, String name, long start, long delta) { - query = super.reportSlowQuery(query, args, name, start, delta); - notifyJmx(query,SLOW_QUERY_NOTIFICATION); - return query; - } - - /** - * JMX operation - return the names of all the pools - * @return - all the names of pools that we have stored data for - */ - public String[] getPoolNames() { - Set keys = perPoolStats.keySet(); - return keys.toArray(new String[0]); - } - - /** - * JMX operation - return the name of the pool - * @return the name of the pool, unique within the JVM - */ - public String getPoolName() { - return poolName; - } - - - public boolean isNotifyPool() { - return notifyPool; - } - - public void setNotifyPool(boolean notifyPool) { - this.notifyPool = notifyPool; - } - - /** - * JMX operation - remove all stats for this connection pool - */ - public void resetStats() { - ConcurrentHashMap queries = perPoolStats.get(poolName); - if (queries!=null) { - Iterator it = queries.keySet().iterator(); - while (it.hasNext()) it.remove(); - } - } - - /** - * JMX operation - returns all the queries we have collected. - * @return - the slow query report as composite data. - */ - public CompositeData[] getSlowQueriesCD() throws OpenDataException { - CompositeDataSupport[] result = null; - ConcurrentHashMap queries = perPoolStats.get(poolName); - if (queries!=null) { - Set> stats = queries.entrySet(); - if (stats!=null) { - result = new CompositeDataSupport[stats.size()]; - Iterator> it = stats.iterator(); - int pos = 0; - while (it.hasNext()) { - Map.Entry entry = it.next(); - QueryStats qs = entry.getValue(); - result[pos++] = qs.getCompositeData(getCompositeType()); - } - } - } - return result; - } - - protected void deregisterJmx() { - try { - if (mbeans.remove(poolName)!=null) { - ObjectName oname = getObjectName(getClass(),poolName); - ManagementFactory.getPlatformMBeanServer().unregisterMBean(oname); - } - } catch (MBeanRegistrationException e) { - log.debug("Jmx deregistration failed.",e); - } catch (InstanceNotFoundException e) { - log.debug("Jmx deregistration failed.",e); - } catch (MalformedObjectNameException e) { - log.warn("Jmx deregistration failed.",e); - } catch (RuntimeOperationsException e) { - log.warn("Jmx deregistration failed.",e); - } - - } - - - public static ObjectName getObjectName(Class clazz, String poolName) throws MalformedObjectNameException { - ObjectName oname = new ObjectName(ConnectionPool.POOL_JMX_TYPE_PREFIX+clazz.getName()+",name=" + poolName); - return oname; - } - - protected void registerJmx() { - try { - //only if we notify the pool itself - if (isNotifyPool()) { - - } else if (getCompositeType()!=null) { - ObjectName oname = getObjectName(getClass(),poolName); - if (mbeans.putIfAbsent(poolName, this)==null) { - ManagementFactory.getPlatformMBeanServer().registerMBean(this, oname); - } - } else { - log.warn(SlowQueryReport.class.getName()+ "- No JMX support, composite type was not found."); - } - } catch (MalformedObjectNameException e) { - log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e); - } catch (RuntimeOperationsException e) { - log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e); - } catch (MBeanException e) { - log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e); - } catch (InstanceAlreadyExistsException e) { - log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e); - } catch (NotCompliantMBeanException e) { - log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e); - } - } - - @Override - public void setProperties(Map properties) { - super.setProperties(properties); - final String threshold = "notifyPool"; - InterceptorProperty p1 = properties.get(threshold); - if (p1!=null) { - this.setNotifyPool(Boolean.parseBoolean(p1.getValue())); - } - } - - -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java deleted file mode 100644 index 908eb1c53189..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java +++ /dev/null @@ -1,23 +0,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.jdbc.pool.interceptor; - -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.OpenDataException; - -public interface SlowQueryReportJmxMBean { - public CompositeData[] getSlowQueriesCD() throws OpenDataException; -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java deleted file mode 100644 index 27370d0f7511..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java +++ /dev/null @@ -1,258 +0,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.jdbc.pool.interceptor; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.sql.Statement; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.tomcat.jdbc.pool.ConnectionPool; -import org.apache.tomcat.jdbc.pool.PooledConnection; -import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty; - -public class StatementCache extends StatementDecoratorInterceptor { - protected static final String[] ALL_TYPES = new String[] {PREPARE_STATEMENT,PREPARE_CALL}; - protected static final String[] CALLABLE_TYPE = new String[] {PREPARE_CALL}; - protected static final String[] PREPARED_TYPE = new String[] {PREPARE_STATEMENT}; - protected static final String[] NO_TYPE = new String[] {}; - - protected static final String STATEMENT_CACHE_ATTR = StatementCache.class.getName() + ".cache"; - - /*begin properties for the statement cache*/ - private boolean cachePrepared = true; - private boolean cacheCallable = false; - private int maxCacheSize = 50; - private PooledConnection pcon; - private String[] types; - - - public boolean isCachePrepared() { - return cachePrepared; - } - - public boolean isCacheCallable() { - return cacheCallable; - } - - public int getMaxCacheSize() { - return maxCacheSize; - } - - public String[] getTypes() { - return types; - } - - public AtomicInteger getCacheSize() { - return cacheSize; - } - - public void setProperties(Map properties) { - super.setProperties(properties); - InterceptorProperty p = properties.get("prepared"); - if (p!=null) cachePrepared = p.getValueAsBoolean(cachePrepared); - p = properties.get("callable"); - if (p!=null) cacheCallable = p.getValueAsBoolean(cacheCallable); - p = properties.get("max"); - if (p!=null) maxCacheSize = p.getValueAsInt(maxCacheSize); - if (cachePrepared && cacheCallable) { - this.types = ALL_TYPES; - } else if (cachePrepared) { - this.types = PREPARED_TYPE; - } else if (cacheCallable) { - this.types = CALLABLE_TYPE; - } else { - this.types = NO_TYPE; - } - - } - /*end properties for the statement cache*/ - - /*begin the cache size*/ - private static ConcurrentHashMap cacheSizeMap = - new ConcurrentHashMap(); - - private AtomicInteger cacheSize; - - public void poolStarted(ConnectionPool pool) { - cacheSizeMap.putIfAbsent(pool, new AtomicInteger(0)); - super.poolStarted(pool); - } - - public void poolClosed(ConnectionPool pool) { - cacheSizeMap.remove(pool); - super.poolClosed(pool); - } - /*end the cache size*/ - - /*begin the actual statement cache*/ - @Override - public void reset(ConnectionPool parent, PooledConnection con) { - super.reset(parent, con); - if (parent==null) { - cacheSize = null; - this.pcon = null; - } else { - cacheSize = cacheSizeMap.get(parent); - this.pcon = con; - if (!pcon.getAttributes().containsKey(STATEMENT_CACHE_ATTR)) { - ConcurrentHashMap cache = new ConcurrentHashMap(); - pcon.getAttributes().put(STATEMENT_CACHE_ATTR,cache); - } - } - } - - @Override - public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing) { - ConcurrentHashMap statements = - (ConcurrentHashMap)con.getAttributes().get(STATEMENT_CACHE_ATTR); - - if (statements!=null) { - for (Map.Entry p : statements.entrySet()) { - closeStatement(p.getValue()); - } - statements.clear(); - } - - super.disconnected(parent, con, finalizing); - } - - public void closeStatement(CachedStatement st) { - if (st==null) return; - st.forceClose(); - } - - @Override - protected Object createDecorator(Object proxy, Method method, Object[] args, - Object statement, Constructor constructor, String sql) - throws InstantiationException, IllegalAccessException, InvocationTargetException { - boolean process = process(this.types, method, false); - if (process) { - Object result = null; - CachedStatement statementProxy = new CachedStatement((Statement)statement,sql); - result = constructor.newInstance(new Object[] { statementProxy }); - statementProxy.setActualProxy(result); - statementProxy.setConnection(proxy); - statementProxy.setConstructor(constructor); - return result; - } else { - return super.createDecorator(proxy, method, args, statement, constructor, sql); - } - } - - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - boolean process = process(this.types, method, false); - if (process && args.length>0 && args[0] instanceof String) { - CachedStatement statement = isCached((String)args[0]); - if (statement!=null) { - //remove it from the cache since it is used - removeStatement(statement); - return statement.getActualProxy(); - } else { - return super.invoke(proxy, method, args); - } - } else { - return super.invoke(proxy,method,args); - } - } - - public CachedStatement isCached(String sql) { - ConcurrentHashMap cache = - (ConcurrentHashMap)pcon.getAttributes().get(STATEMENT_CACHE_ATTR); - return cache.get(sql); - } - - public boolean cacheStatement(CachedStatement proxy) { - ConcurrentHashMap cache = - (ConcurrentHashMap)pcon.getAttributes().get(STATEMENT_CACHE_ATTR); - if (proxy.getSql()==null) { - return false; - } else if (cache.containsKey(proxy.getSql())) { - return false; - } else if (cacheSize.get()>=maxCacheSize) { - return false; - } else if (cacheSize.incrementAndGet()>maxCacheSize) { - cacheSize.decrementAndGet(); - return false; - } else { - //cache the statement - cache.put(proxy.getSql(), proxy); - return true; - } - } - - public boolean removeStatement(CachedStatement proxy) { - ConcurrentHashMap cache = - (ConcurrentHashMap)pcon.getAttributes().get(STATEMENT_CACHE_ATTR); - if (cache.remove(proxy.getSql()) != null) { - cacheSize.decrementAndGet(); - return true; - } else { - return false; - } - } - /*end the actual statement cache*/ - - - protected class CachedStatement extends StatementDecoratorInterceptor.StatementProxy { - boolean cached = false; - public CachedStatement(Statement parent, String sql) { - super(parent, sql); - } - - @Override - public void closeInvoked() { - //should we cache it - boolean shouldClose = true; - if (cacheSize.get() < maxCacheSize) { - //cache a proxy so that we don't reuse the facade - CachedStatement proxy = new CachedStatement(getDelegate(),getSql()); - try { - //create a new facade - Object actualProxy = getConstructor().newInstance(new Object[] { proxy }); - proxy.setActualProxy(actualProxy); - proxy.setConnection(getConnection()); - proxy.setConstructor(getConstructor()); - if (cacheStatement(proxy)) { - proxy.cached = true; - shouldClose = false; - } - } catch (Exception x) { - removeStatement(proxy); - } - } - closed = true; - delegate = null; - if (shouldClose) { - super.closeInvoked(); - } - - } - - public void forceClose() { - removeStatement(this); - super.closeInvoked(); - } - - } - -} - - diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java deleted file mode 100644 index 922205e4408d..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java +++ /dev/null @@ -1,279 +0,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.jdbc.pool.interceptor; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.sql.CallableStatement; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor; - -/** - * Implementation of JdbcInterceptor that proxies resultSets and statements. - * @author Guillermo Fernandes - */ -public class StatementDecoratorInterceptor extends AbstractCreateStatementInterceptor { - - private static final Log logger = LogFactory.getLog(StatementDecoratorInterceptor.class); - - private static final String[] EXECUTE_QUERY_TYPES = { "executeQuery" }; - - /** - * the constructors that are used to create statement proxies - */ - protected static final Constructor[] constructors = new Constructor[AbstractCreateStatementInterceptor.STATEMENT_TYPE_COUNT]; - - /** - * the constructor to create the resultSet proxies - */ - protected static Constructor resultSetConstructor = null; - - @Override - public void closeInvoked() { - // nothing to do - } - - /** - * Creates a constructor for a proxy class, if one doesn't already exist - * - * @param idx - * - the index of the constructor - * @param clazz - * - the interface that the proxy will implement - * @return - returns a constructor used to create new instances - * @throws NoSuchMethodException - */ - protected Constructor getConstructor(int idx, Class clazz) throws NoSuchMethodException { - if (constructors[idx] == null) { - Class proxyClass = Proxy.getProxyClass(StatementDecoratorInterceptor.class.getClassLoader(), - new Class[] { clazz }); - constructors[idx] = proxyClass.getConstructor(new Class[] { InvocationHandler.class }); - } - return constructors[idx]; - } - - protected Constructor getResultSetConstructor() throws NoSuchMethodException { - if (resultSetConstructor == null) { - Class proxyClass = Proxy.getProxyClass(StatementDecoratorInterceptor.class.getClassLoader(), - new Class[] { ResultSet.class }); - resultSetConstructor = proxyClass.getConstructor(new Class[] { InvocationHandler.class }); - } - return resultSetConstructor; - } - - /** - * Creates a statement interceptor to monitor query response times - */ - @Override - public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) { - try { - String name = method.getName(); - Constructor constructor = null; - String sql = null; - if (compare(CREATE_STATEMENT, name)) { - // createStatement - constructor = getConstructor(CREATE_STATEMENT_IDX, Statement.class); - } else if (compare(PREPARE_STATEMENT, name)) { - // prepareStatement - constructor = getConstructor(PREPARE_STATEMENT_IDX, PreparedStatement.class); - sql = (String)args[0]; - } else if (compare(PREPARE_CALL, name)) { - // prepareCall - constructor = getConstructor(PREPARE_CALL_IDX, CallableStatement.class); - sql = (String)args[0]; - } else { - // do nothing, might be a future unsupported method - // so we better bail out and let the system continue - return statement; - } - return createDecorator(proxy, method, args, statement, constructor, sql); - } catch (Exception x) { - logger.warn("Unable to create statement proxy for slow query report.", x); - } - return statement; - } - - protected Object createDecorator(Object proxy, Method method, Object[] args, - Object statement, Constructor constructor, String sql) - throws InstantiationException, IllegalAccessException, InvocationTargetException { - Object result = null; - StatementProxy statementProxy = new StatementProxy((Statement)statement,sql); - result = constructor.newInstance(new Object[] { statementProxy }); - statementProxy.setActualProxy(result); - statementProxy.setConnection(proxy); - statementProxy.setConnection(constructor); - return result; - } - - protected boolean isExecuteQuery(String methodName) { - return EXECUTE_QUERY_TYPES[0].equals(methodName); - } - - protected boolean isExecuteQuery(Method method) { - return isExecuteQuery(method.getName()); - } - - /** - * Class to measure query execute time - * - * @author fhanik - * - */ - protected class StatementProxy implements InvocationHandler { - - protected boolean closed = false; - protected T delegate; - private Object actualProxy; - private Object connection; - private String sql; - private Constructor constructor; - - public StatementProxy(T delegate, String sql) { - this.delegate = delegate; - this.sql = sql; - } - public T getDelegate() { - return this.delegate; - } - - public String getSql() { - return sql; - } - - public void setConnection(Object proxy) { - this.connection = proxy; - } - public Object getConnection() { - return this.connection; - } - - public void setActualProxy(Object proxy){ - this.actualProxy = proxy; - } - public Object getActualProxy() { - return this.actualProxy; - } - - - public Constructor getConstructor() { - return constructor; - } - public void setConstructor(Constructor constructor) { - this.constructor = constructor; - } - public void closeInvoked() { - if (getDelegate()!=null) { - try { - getDelegate().close(); - }catch (SQLException ignore) { - } - } - closed = true; - delegate = null; - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if (compare(TOSTRING_VAL,method)) { - return toString(); - } - // was close invoked? - boolean close = compare(CLOSE_VAL, method); - // allow close to be called multiple times - if (close && closed) - return null; - // are we calling isClosed? - if (compare(ISCLOSED_VAL, method)) - return Boolean.valueOf(closed); - // if we are calling anything else, bail out - if (closed) - throw new SQLException("Statement closed."); - if (compare(GETCONNECTION_VAL,method)){ - return connection; - } - boolean process = isExecuteQuery(method); - // check to see if we are about to execute a query - // if we are executing, get the current time - Object result = null; - try { - // perform close cleanup - if (close) { - closeInvoked(); - } else { - // execute the query - result = method.invoke(delegate, args); - } - } catch (Throwable t) { - if (t instanceof InvocationTargetException) { - InvocationTargetException it = (InvocationTargetException) t; - throw it.getCause() != null ? it.getCause() : it; - } else { - throw t; - } - } - if (process){ - Constructor cons = getResultSetConstructor(); - result = cons.newInstance(new Object[]{new ResultSetProxy(actualProxy, result)}); - } - return result; - } - - public String toString() { - StringBuffer buf = new StringBuffer(StatementProxy.class.getName()); - buf.append("[Proxy="); - buf.append(System.identityHashCode(this)); - buf.append("; Sql="); - buf.append(getSql()); - buf.append("; Delegate="); - buf.append(getDelegate()); - buf.append("; Connection="); - buf.append(getConnection()); - buf.append("]"); - return buf.toString(); - } - } - - protected class ResultSetProxy implements InvocationHandler { - - private Object st; - private Object delegate; - - public ResultSetProxy(Object st, Object delegate) { - this.st = st; - this.delegate = delegate; - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if (method.getName().equals("getStatement")) { - return this.st; - } else { - return method.invoke(this.delegate, args); - } - } - } -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java deleted file mode 100644 index f05efde7f8c8..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java +++ /dev/null @@ -1,75 +0,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.jdbc.pool.interceptor; - -import java.lang.ref.WeakReference; -import java.lang.reflect.Method; -import java.sql.Statement; -import java.util.ArrayList; - -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.PooledConnection; -/** - * Keeps track of statements associated with a connection and invokes close upon {@link java.sql.Connection#close()} - * Useful for applications that dont close the associated statements after being done with a connection. - * @author fhanik - * - */ -public class StatementFinalizer extends AbstractCreateStatementInterceptor { - private static final Log log = LogFactory.getLog(StatementFinalizer.class); - - protected ArrayList> statements = new ArrayList>(); - - @Override - public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) { - // TODO Auto-generated method stub - try { - if (statement instanceof Statement) - statements.add(new WeakReference((Statement)statement)); - }catch (ClassCastException x) { - //ignore this one - } - return statement; - } - - @Override - public void closeInvoked() { - while (statements.size()>0) { - WeakReference ws = statements.remove(0); - Statement st = ws.get(); - if (st!=null) { - try { - st.close(); - } catch (Exception ignore) { - if (log.isDebugEnabled()) { - log.debug("Unable to closed statement upon connection close.",ignore); - } - } - } - } - } - - @Override - public void reset(ConnectionPool parent, PooledConnection con) { - statements.clear(); - super.reset(parent, con); - } - - -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/mbeans-descriptors.xml b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/mbeans-descriptors.xml deleted file mode 100644 index e312d053b611..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/mbeans-descriptors.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - Slow query - - - - Failed query execution - - - \ No newline at end of file diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java deleted file mode 100644 index b10878dd9f14..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java +++ /dev/null @@ -1,626 +0,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.jdbc.pool.jmx; -/** - * @author Filip Hanik - */ -import java.util.Properties; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.management.MBeanNotificationInfo; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationListener; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.jdbc.pool.PoolConfiguration; -import org.apache.tomcat.jdbc.pool.Validator; -import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorDefinition; - -public class ConnectionPool extends NotificationBroadcasterSupport implements ConnectionPoolMBean { - /** - * logger - */ - private static final Log log = LogFactory.getLog(ConnectionPool.class); - - /** - * the connection pool - */ - protected org.apache.tomcat.jdbc.pool.ConnectionPool pool = null; - /** - * sequence for JMX notifications - */ - protected AtomicInteger sequence = new AtomicInteger(0); - - /** - * Listeners that are local and interested in our notifications, no need for JMX - */ - protected ConcurrentLinkedQueue listeners = new ConcurrentLinkedQueue(); - - public ConnectionPool(org.apache.tomcat.jdbc.pool.ConnectionPool pool) { - super(); - this.pool = pool; - } - - public org.apache.tomcat.jdbc.pool.ConnectionPool getPool() { - return pool; - } - - public PoolConfiguration getPoolProperties() { - return pool.getPoolProperties(); - } - - //================================================================= - // NOTIFICATION INFO - //================================================================= - public static final String NOTIFY_INIT = "INIT FAILED"; - public static final String NOTIFY_CONNECT = "CONNECTION FAILED"; - public static final String NOTIFY_ABANDON = "CONNECTION ABANDONED"; - public static final String SLOW_QUERY_NOTIFICATION = "SLOW QUERY"; - public static final String FAILED_QUERY_NOTIFICATION = "FAILED QUERY"; - public static final String SUSPECT_ABANDONED_NOTIFICATION = "SUSPECT CONNETION ABANDONED"; - - - public MBeanNotificationInfo[] getNotificationInfo() { - MBeanNotificationInfo[] pres = super.getNotificationInfo(); - MBeanNotificationInfo[] loc = getDefaultNotificationInfo(); - MBeanNotificationInfo[] aug = new MBeanNotificationInfo[pres.length + loc.length]; - if (pres.length>0) System.arraycopy(pres, 0, aug, 0, pres.length); - if (loc.length >0) System.arraycopy(loc, 0, aug, pres.length, loc.length); - return aug; - } - - public static MBeanNotificationInfo[] getDefaultNotificationInfo() { - String[] types = new String[] {NOTIFY_INIT, NOTIFY_CONNECT, NOTIFY_ABANDON, SLOW_QUERY_NOTIFICATION, FAILED_QUERY_NOTIFICATION, SUSPECT_ABANDONED_NOTIFICATION}; - String name = Notification.class.getName(); - String description = "A connection pool error condition was met."; - MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description); - return new MBeanNotificationInfo[] {info}; - } - - /** - * Return true if the notification was sent successfully, false otherwise. - * @param type - * @param message - * @return true if the notification succeeded - */ - public boolean notify(final String type, String message) { - try { - Notification n = new Notification( - type, - this, - sequence.incrementAndGet(), - System.currentTimeMillis(), - "["+type+"] "+message); - sendNotification(n); - for (NotificationListener listener : listeners) { - listener.handleNotification(n,this); - } - return true; - }catch (Exception x) { - if (log.isDebugEnabled()) { - log.debug("Notify failed. Type="+type+"; Message="+message,x); - } - return false; - } - - } - - public void addListener(NotificationListener list) { - listeners.add(list); - } - - public boolean removeListener(NotificationListener list) { - return listeners.remove(list); - } - - //================================================================= - // POOL STATS - //================================================================= - - public int getSize() { - return pool.getSize(); - } - - public int getIdle() { - return pool.getIdle(); - } - - public int getActive() { - return pool.getActive(); - } - - public int getNumIdle() { - return getIdle(); - } - - public int getNumActive() { - return getActive(); - } - - public int getWaitCount() { - return pool.getWaitCount(); - } - - //================================================================= - // POOL OPERATIONS - //================================================================= - public void checkIdle() { - pool.checkIdle(); - } - - public void checkAbandoned() { - pool.checkAbandoned(); - } - - public void testIdle() { - pool.testAllIdle(); - } - //================================================================= - // POOL PROPERTIES - //================================================================= - //========================================================= - // PROPERTIES / CONFIGURATION - //========================================================= - - - public String getConnectionProperties() { - return getPoolProperties().getConnectionProperties(); - } - - public Properties getDbProperties() { - return getPoolProperties().getDbProperties(); - } - - public String getDefaultCatalog() { - return getPoolProperties().getDefaultCatalog(); - } - - public int getDefaultTransactionIsolation() { - return getPoolProperties().getDefaultTransactionIsolation(); - } - - public String getDriverClassName() { - return getPoolProperties().getDriverClassName(); - } - - - public int getInitialSize() { - return getPoolProperties().getInitialSize(); - } - - public String getInitSQL() { - return getPoolProperties().getInitSQL(); - } - - public String getJdbcInterceptors() { - return getPoolProperties().getJdbcInterceptors(); - } - - public int getMaxActive() { - return getPoolProperties().getMaxActive(); - } - - public int getMaxIdle() { - return getPoolProperties().getMaxIdle(); - } - - public int getMaxWait() { - return getPoolProperties().getMaxWait(); - } - - public int getMinEvictableIdleTimeMillis() { - return getPoolProperties().getMinEvictableIdleTimeMillis(); - } - - public int getMinIdle() { - return getPoolProperties().getMinIdle(); - } - - public long getMaxAge() { - return getPoolProperties().getMaxAge(); - } - - public String getName() { - return this.getPoolName(); - } - - public int getNumTestsPerEvictionRun() { - return getPoolProperties().getNumTestsPerEvictionRun(); - } - - /** - * @return DOES NOT RETURN THE PASSWORD, IT WOULD SHOW UP IN JMX - */ - public String getPassword() { - return "Password not available as DataSource/JMX operation."; - } - - public int getRemoveAbandonedTimeout() { - return getPoolProperties().getRemoveAbandonedTimeout(); - } - - - public int getTimeBetweenEvictionRunsMillis() { - return getPoolProperties().getTimeBetweenEvictionRunsMillis(); - } - - public String getUrl() { - return getPoolProperties().getUrl(); - } - - public String getUsername() { - return getPoolProperties().getUsername(); - } - - public long getValidationInterval() { - return getPoolProperties().getValidationInterval(); - } - - public String getValidationQuery() { - return getPoolProperties().getValidationQuery(); - } - - /** - * {@inheritDoc} - */ - @Override - public String getValidatorClassName() { - return getPoolProperties().getValidatorClassName(); - } - - /** - * {@inheritDoc} - */ - @Override - public Validator getValidator() { - return getPoolProperties().getValidator(); - } - - public boolean isAccessToUnderlyingConnectionAllowed() { - return getPoolProperties().isAccessToUnderlyingConnectionAllowed(); - } - - public Boolean isDefaultAutoCommit() { - return getPoolProperties().isDefaultAutoCommit(); - } - - public Boolean isDefaultReadOnly() { - return getPoolProperties().isDefaultReadOnly(); - } - - public boolean isLogAbandoned() { - return getPoolProperties().isLogAbandoned(); - } - - public boolean isPoolSweeperEnabled() { - return getPoolProperties().isPoolSweeperEnabled(); - } - - public boolean isRemoveAbandoned() { - return getPoolProperties().isRemoveAbandoned(); - } - - public int getAbandonWhenPercentageFull() { - return getPoolProperties().getAbandonWhenPercentageFull(); - } - - public boolean isTestOnBorrow() { - return getPoolProperties().isTestOnBorrow(); - } - - public boolean isTestOnConnect() { - return getPoolProperties().isTestOnConnect(); - } - - public boolean isTestOnReturn() { - return getPoolProperties().isTestOnReturn(); - } - - public boolean isTestWhileIdle() { - return getPoolProperties().isTestWhileIdle(); - } - - - public Boolean getDefaultAutoCommit() { - return getPoolProperties().getDefaultAutoCommit(); - } - - public Boolean getDefaultReadOnly() { - return getPoolProperties().getDefaultReadOnly(); - } - - public InterceptorDefinition[] getJdbcInterceptorsAsArray() { - return getPoolProperties().getJdbcInterceptorsAsArray(); - } - - public boolean getUseLock() { - return getPoolProperties().getUseLock(); - } - - public boolean isFairQueue() { - return getPoolProperties().isFairQueue(); - } - - public boolean isJmxEnabled() { - return getPoolProperties().isJmxEnabled(); - } - - public boolean isUseEquals() { - return getPoolProperties().isUseEquals(); - } - - public void setAbandonWhenPercentageFull(int percentage) { - getPoolProperties().setAbandonWhenPercentageFull(percentage); - } - - public void setAccessToUnderlyingConnectionAllowed(boolean accessToUnderlyingConnectionAllowed) { - getPoolProperties().setAccessToUnderlyingConnectionAllowed(accessToUnderlyingConnectionAllowed); - } - - public void setDbProperties(Properties dbProperties) { - getPoolProperties().setDbProperties(dbProperties); - } - - public void setDefaultReadOnly(Boolean defaultReadOnly) { - getPoolProperties().setDefaultReadOnly(defaultReadOnly); - } - - public void setMaxAge(long maxAge) { - getPoolProperties().setMaxAge(maxAge); - } - - public void setName(String name) { - getPoolProperties().setName(name); - } - - public String getPoolName() { - return getPoolProperties().getName(); - } - - - public void setConnectionProperties(String connectionProperties) { - getPoolProperties().setConnectionProperties(connectionProperties); - - } - - public void setDefaultAutoCommit(Boolean defaultAutoCommit) { - getPoolProperties().setDefaultAutoCommit(defaultAutoCommit); - } - - public void setDefaultCatalog(String defaultCatalog) { - getPoolProperties().setDefaultCatalog(defaultCatalog); - } - - public void setDefaultTransactionIsolation(int defaultTransactionIsolation) { - getPoolProperties().setDefaultTransactionIsolation(defaultTransactionIsolation); - } - - public void setDriverClassName(String driverClassName) { - getPoolProperties().setDriverClassName(driverClassName); - } - - @Override - public void setFairQueue(boolean fairQueue) { - getPoolProperties().setFairQueue(fairQueue); - } - - @Override - public void setInitialSize(int initialSize) { - // TODO Auto-generated method stub - - } - - @Override - public void setInitSQL(String initSQL) { - // TODO Auto-generated method stub - - } - - @Override - public void setJdbcInterceptors(String jdbcInterceptors) { - // TODO Auto-generated method stub - - } - - @Override - public void setJmxEnabled(boolean jmxEnabled) { - // TODO Auto-generated method stub - - } - - @Override - public void setLogAbandoned(boolean logAbandoned) { - // TODO Auto-generated method stub - - } - - @Override - public void setMaxActive(int maxActive) { - // TODO Auto-generated method stub - - } - - @Override - public void setMaxIdle(int maxIdle) { - // TODO Auto-generated method stub - - } - - @Override - public void setMaxWait(int maxWait) { - // TODO Auto-generated method stub - - } - - @Override - public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) { - // TODO Auto-generated method stub - - } - - @Override - public void setMinIdle(int minIdle) { - // TODO Auto-generated method stub - - } - - @Override - public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { - // TODO Auto-generated method stub - - } - - @Override - public void setPassword(String password) { - // TODO Auto-generated method stub - - } - - @Override - public void setRemoveAbandoned(boolean removeAbandoned) { - // TODO Auto-generated method stub - - } - - @Override - public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) { - // TODO Auto-generated method stub - - } - - @Override - public void setTestOnBorrow(boolean testOnBorrow) { - // TODO Auto-generated method stub - - } - - @Override - public void setTestOnConnect(boolean testOnConnect) { - // TODO Auto-generated method stub - - } - - @Override - public void setTestOnReturn(boolean testOnReturn) { - // TODO Auto-generated method stub - - } - - @Override - public void setTestWhileIdle(boolean testWhileIdle) { - // TODO Auto-generated method stub - - } - - @Override - public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) { - // TODO Auto-generated method stub - - } - - @Override - public void setUrl(String url) { - // TODO Auto-generated method stub - - } - - @Override - public void setUseEquals(boolean useEquals) { - // TODO Auto-generated method stub - - } - - @Override - public void setUseLock(boolean useLock) { - // TODO Auto-generated method stub - - } - - @Override - public void setUsername(String username) { - // TODO Auto-generated method stub - - } - - @Override - public void setValidationInterval(long validationInterval) { - // TODO Auto-generated method stub - - } - - @Override - public void setValidationQuery(String validationQuery) { - // TODO Auto-generated method stub - - } - - /** - * {@inheritDoc} - */ - @Override - public void setValidatorClassName(String className) { - getPoolProperties().setValidatorClassName(className); - } - - /** - * {@inheritDoc} - */ - @Override - public int getSuspectTimeout() { - return getPoolProperties().getSuspectTimeout(); - } - - /** - * {@inheritDoc} - */ - @Override - public void setSuspectTimeout(int seconds) { - //no op - } - - /** - * {@inheritDoc} - */ - public void setDataSource(Object ds) { - getPoolProperties().setDataSource(ds); - } - - /** - * {@inheritDoc} - */ - public Object getDataSource() { - return getPoolProperties().getDataSource(); - } - - - /** - * {@inheritDoc} - */ - public void setDataSourceJNDI(String jndiDS) { - //noop - } - - /** - * {@inheritDoc} - */ - public String getDataSourceJNDI() { - return getPoolProperties().getDataSourceJNDI(); - } - -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java deleted file mode 100644 index 7632d37c4ec3..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java +++ /dev/null @@ -1,54 +0,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.jdbc.pool.jmx; - -import org.apache.tomcat.jdbc.pool.PoolConfiguration; - -public interface ConnectionPoolMBean extends PoolConfiguration { - - //================================================================= - // POOL STATS - //================================================================= - - public int getSize(); - - public int getIdle(); - - public int getActive(); - - public boolean isPoolSweeperEnabled(); - - public int getNumIdle(); - - public int getNumActive(); - - public int getWaitCount(); - - //================================================================= - // POOL OPERATIONS - //================================================================= - public void checkIdle(); - - public void checkAbandoned(); - - public void testIdle(); - - //================================================================= - // POOL NOTIFICATIONS - //================================================================= - - -} diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/mbeans-descriptors.xml b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/mbeans-descriptors.xml deleted file mode 100644 index 897782bd99c7..000000000000 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/mbeans-descriptors.xml +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/modules/jdbc-pool/resources/MANIFEST.MF b/modules/jdbc-pool/resources/MANIFEST.MF deleted file mode 100644 index b61fb99d7b9c..000000000000 --- a/modules/jdbc-pool/resources/MANIFEST.MF +++ /dev/null @@ -1,22 +0,0 @@ -Manifest-Version: 1.0 -Export-Package: - org.apache.tomcat.jdbc.pool;version="@@VERSION@@"; - uses:="javax.management,javax.naming,javax.naming.spi,javax.sql, - org.apache.tomcat.jdbc.pool.jmx", - org.apache.tomcat.jdbc.pool.interceptor;version="@@VERSION@@"; - uses:="javax.management.openmbean,org.apache.tomcat.jdbc.pool", - org.apache.tomcat.jdbc.pool.jmx;version="@@VERSION@@"; - uses:="javax.management,org.apache.tomcat.jdbc.pool" -Ant-Version: Apache Ant 1.7.0 -Bundle-Vendor: Apache Software Foundation -Bundle-Version: @@VERSION@@ -Bundle-Name: Apache Tomcat JDBC Connection Pool -Bundle-ManifestVersion: 2 -Created-By: 11.0-b16 (Sun Microsystems Inc.) -Bundle-SymbolicName: org.apache.tomcat.jdbc -Import-Package: - javax.management;version="0", - javax.management.openmbean;version="0", - javax.naming;version="0", - javax.sql;version="0", - org.apache.juli.logging;version="[6.0.18, 7.0.0)" diff --git a/modules/jdbc-pool/sign.sh b/modules/jdbc-pool/sign.sh deleted file mode 100755 index 182851479e7f..000000000000 --- a/modules/jdbc-pool/sign.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -# 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. - -VERSION=v1.0.8 -for i in $(find output/release/$VERSION -name "*.zip" -o -name "*.tar.gz"); do - echo Signing $i - echo $1|gpg --passphrase-fd 0 -a -b $i -done diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java deleted file mode 100644 index 739347c8c20f..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java +++ /dev/null @@ -1,59 +0,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.jdbc.pool.interceptor; - -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.tomcat.jdbc.pool.ConnectionPool; -import org.apache.tomcat.jdbc.pool.JdbcInterceptor; -import org.apache.tomcat.jdbc.pool.PooledConnection; -import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty; - -public class TestInterceptor extends JdbcInterceptor { - public static boolean poolstarted = false; - public static boolean poolclosed = false; - public static AtomicInteger instancecount = new AtomicInteger(0); - - @Override - public void poolClosed(ConnectionPool pool) { - // TODO Auto-generated method stub - super.poolClosed(pool); - poolclosed = true; - } - - @Override - public void poolStarted(ConnectionPool pool) { - super.poolStarted(pool); - poolstarted = true; - } - - @Override - public void reset(ConnectionPool parent, PooledConnection con) { - // TODO Auto-generated method stub - - } - - @Override - public void setProperties(Map properties) { - instancecount.incrementAndGet(); - super.setProperties(properties); - } - - -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java deleted file mode 100644 index a86e6e970ee2..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java +++ /dev/null @@ -1,116 +0,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.jdbc.test; - -import java.sql.Connection; -import org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer; - -public class AbandonPercentageTest extends DefaultTestCase { - - public AbandonPercentageTest(String name) { - super(name); - } - - public void testDefaultAbandon() throws Exception { - this.init(); - this.datasource.setMaxActive(100); - this.datasource.setMaxIdle(100); - this.datasource.setInitialSize(0); - this.datasource.getPoolProperties().setAbandonWhenPercentageFull(0); - this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100); - this.datasource.getPoolProperties().setRemoveAbandoned(true); - this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1); - Connection con = datasource.getConnection(); - assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive()); - Thread.sleep(2000); - assertEquals("Number of connections active/busy should be 0",0,datasource.getPool().getActive()); - con.close(); - } - - public void testMaxedOutAbandon() throws Exception { - int size = 100; - this.init(); - this.datasource.setMaxActive(size); - this.datasource.setMaxIdle(size); - this.datasource.setInitialSize(0); - this.datasource.getPoolProperties().setAbandonWhenPercentageFull(100); - this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100); - this.datasource.getPoolProperties().setRemoveAbandoned(true); - this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1); - Connection con = datasource.getConnection(); - assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive()); - Thread.sleep(2000); - assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive()); - con.close(); - } - - public void testResetConnection() throws Exception { - int size = 1; - this.init(); - this.datasource.setMaxActive(size); - this.datasource.setMaxIdle(size); - this.datasource.setInitialSize(0); - this.datasource.getPoolProperties().setAbandonWhenPercentageFull(100); - this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100); - this.datasource.getPoolProperties().setRemoveAbandoned(true); - this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1); - this.datasource.getPoolProperties().setJdbcInterceptors(ResetAbandonedTimer.class.getName()); - Connection con = datasource.getConnection(); - assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive()); - for (int i=0; i<20; i++) { - Thread.sleep(200); - con.isClosed(); - } - assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive()); - con.close(); - } - - public void testHalfway() throws Exception { - int size = 100; - this.init(); - this.datasource.setMaxActive(size); - this.datasource.setMaxIdle(size); - this.datasource.setInitialSize(0); - this.datasource.getPoolProperties().setAbandonWhenPercentageFull(50); - this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(500); - this.datasource.getPoolProperties().setRemoveAbandoned(true); - this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1); - Connection[] con = new Connection[size]; - con[0] = datasource.getConnection(); - assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive()); - for (int i=1; i<25; i++) { - con[i] = datasource.getConnection(); - } - assertEquals("Number of connections active/busy should be 25",25,datasource.getPool().getActive()); - Thread.sleep(2500); - assertEquals("Number of connections active/busy should be 25",25,datasource.getPool().getActive()); - this.datasource.getPoolProperties().setRemoveAbandonedTimeout(100); - for (int i=25; i=ConnectCountTest.this.complete) break; - long start = System.nanoTime(); - Connection con = null; - try { - if (async) { - Future cf = ((DataSourceProxy)d).getConnectionAsync(); - con = cf.get(); - } else { - con = d.getConnection(); - } - long delta = System.nanoTime() - start; - totalwait += delta; - maxwait = Math.max(delta, maxwait); - minwait = Math.min(delta, minwait); - nroffetch++; - if (query!=null) { - Statement st = con.createStatement(); - ResultSet rs = st.executeQuery(query); - while (rs.next()) { - } - rs.close(); - st.close(); - } - try { - if (ConnectCountTest.this.sleep>0) sleep(ConnectCountTest.this.sleep); - } catch (InterruptedException x) { - interrupted(); - } - } finally { - long cstart = System.nanoTime(); - if (con!=null) try {con.close();}catch(Exception x) {x.printStackTrace();} - long cdelta = System.nanoTime() - cstart; - totalcmax += cdelta; - cmax = Math.max(cdelta, cmax); - } - totalruntime+=(System.nanoTime()-start); - } - - } catch (Exception x) { - x.printStackTrace(); - } finally { - ConnectCountTest.this.latch.countDown(); - } - if (System.getProperty("print-thread-stats")!=null) { - System.out.println("["+getName()+"] "+ - "\n\tMax time to retrieve connection:"+(((float)maxwait)/1000f/1000f)+" ms."+ - "\n\tTotal time to retrieve connection:"+(((float)totalwait)/1000f/1000f)+" ms."+ - "\n\tAverage time to retrieve connection:"+(((float)totalwait)/1000f/1000f)/(float)nroffetch+" ms."+ - "\n\tMax time to close connection:"+(((float)cmax)/1000f/1000f)+" ms."+ - "\n\tTotal time to close connection:"+(((float)totalcmax)/1000f/1000f)+" ms."+ - "\n\tAverage time to close connection:"+(((float)totalcmax)/1000f/1000f)/(float)nroffetch+" ms."+ - "\n\tRun time:"+(((float)totalruntime)/1000f/1000f)+" ms."+ - "\n\tNr of fetch:"+nroffetch); - } - } - } -} - diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java deleted file mode 100644 index 9242d7d4b7dc..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java +++ /dev/null @@ -1,122 +0,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.jdbc.test; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.Statement; -import java.util.Random; -import java.sql.ResultSet; - -import org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer; - -public class CreateTestTable extends DefaultTestCase { - - public static volatile boolean recreate = Boolean.getBoolean("recreate"); - - public CreateTestTable(String name) { - super(name); - } - - public void testCreateTestTable() throws Exception { - this.init(); - Connection con = datasource.getConnection(); - Statement st = con.createStatement(); - try { - st.execute("create table test(id int not null, val1 varchar(255), val2 varchar(255), val3 varchar(255), val4 varchar(255))"); - }catch (Exception ignore) {} - st.close(); - con.close(); - } - - public int testCheckData() throws Exception { - int count = 0; - String check = "select count (*) from test"; - this.init(); - Connection con = datasource.getConnection(); - Statement st = con.createStatement(); - try { - ResultSet rs = st.executeQuery(check); - - if (rs.next()) - count = rs.getInt(1); - System.out.println("Count:"+count); - }catch (Exception ignore) {} - return count; - } - - public void testPopulateData() throws Exception { - init(); - datasource.setJdbcInterceptors(ResetAbandonedTimer.class.getName()); - String insert = "insert into test values (?,?,?,?,?)"; - this.init(); - this.datasource.setRemoveAbandoned(false); - Connection con = datasource.getConnection(); - if (recreate) { - Statement st = con.createStatement(); - try { - st.execute("drop table test"); - }catch (Exception ignore) {} - st.execute("create table test(id int not null, val1 varchar(255), val2 varchar(255), val3 varchar(255), val4 varchar(255))"); - st.close(); - } - PreparedStatement ps = con.prepareStatement(insert); - ps.setQueryTimeout(0); - for (int i=testCheckData(); i<100000; i++) { - ps.setInt(1,i); - String s = getRandom(); - ps.setString(2, s); - ps.setString(3, s); - ps.setString(4, s); - ps.setString(5, s); - ps.addBatch(); - ps.clearParameters(); - if ((i+1) % 1000 == 0) { - System.out.print("."); - } - if ((i+1) % 10000 == 0) { - System.out.print("\n"+(i+1)); - ps.executeBatch(); - ps.close(); - ps = con.prepareStatement(insert); - ps.setQueryTimeout(0); - } - - } - ps.close(); - con.close(); - } - - public static Random random = new Random(System.currentTimeMillis()); - public static String getRandom() { - StringBuilder s = new StringBuilder(256); - for (int i=0;i<254; i++) { - int b = Math.abs(random.nextInt() % 29); - char c = (char)(b+65); - s.append(c); - } - return s.toString(); - } - - public static void main(String[] args) throws Exception { - recreate = true; - CreateTestTable test = new CreateTestTable("CreateTestTable"); - test.testPopulateData(); - } - -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/DefaultProperties.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/DefaultProperties.java deleted file mode 100644 index 235b55590b33..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/DefaultProperties.java +++ /dev/null @@ -1,74 +0,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.jdbc.test; - -import java.util.Properties; - -import org.apache.tomcat.jdbc.pool.DataSourceFactory; -import org.apache.tomcat.jdbc.pool.PoolProperties; - -/** - * @author Filip Hanik - * @version 1.0 - */ -public class DefaultProperties extends PoolProperties { - public DefaultProperties() { - dbProperties = new Properties(); - - //mysql - //url = System.getProperty("url","jdbc:mysql://localhost:3306/mysql?autoReconnect=true"); - //driverClassName = System.getProperty("driverClassName","com.mysql.jdbc.Driver"); - - //derby - //url = System.getProperty("url","jdbc:derby:derbyDB;create=true"); - //driverClassName = System.getProperty("driverClassName","org.apache.derby.jdbc.EmbeddedDriver"); - - url = System.getProperty("url","jdbc:h2:~/.h2/test;QUERY_TIMEOUT=0;DB_CLOSE_ON_EXIT=FALSE"); - driverClassName = System.getProperty("driverClassName","org.h2.Driver"); - System.setProperty("h2.serverCachedObjects", "10000"); - - password = System.getProperty("password","password"); - username = System.getProperty("username","root"); - - validationQuery = System.getProperty("validationQuery","SELECT 1"); - defaultAutoCommit = true; - defaultReadOnly = false; - defaultTransactionIsolation = DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION; - connectionProperties = null; - defaultCatalog = null; - initialSize = 10; - maxActive = 100; - maxIdle = initialSize; - minIdle = initialSize; - maxWait = 10000; - - testOnBorrow = true; - testOnReturn = false; - testWhileIdle = true; - timeBetweenEvictionRunsMillis = 5000; - numTestsPerEvictionRun = 0; - minEvictableIdleTimeMillis = 1000; - removeAbandoned = true; - removeAbandonedTimeout = 5000; - logAbandoned = true; - validationInterval = 0; //always validate - initSQL = null; - testOnConnect = false;; - dbProperties.setProperty("user",username); - dbProperties.setProperty("password",password); - } -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/DefaultTestCase.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/DefaultTestCase.java deleted file mode 100644 index f19ff638c7fa..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/DefaultTestCase.java +++ /dev/null @@ -1,243 +0,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.jdbc.test; - -import java.lang.reflect.Method; -import java.util.Properties; - -import junit.framework.TestCase; - -import org.apache.tomcat.dbcp.dbcp.BasicDataSource; -import org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory; -import org.apache.tomcat.jdbc.pool.PoolConfiguration; -import org.apache.tomcat.jdbc.pool.PoolProperties; - -//import com.mchange.v2.c3p0.ComboPooledDataSource; -//import com.mchange.v2.log.MLevel; -//import com.mchange.v2.log.MLog; - -/** - * @author Filip Hanik - * @version 1.0 - */ -public class DefaultTestCase extends TestCase { - protected org.apache.tomcat.jdbc.pool.DataSource datasource; - protected BasicDataSource tDatasource; -// protected ComboPooledDataSource c3p0Datasource; - protected int threadcount = 10; - protected int iterations = 100000; - public DefaultTestCase(String name) { - super(name); - } - - @Override - public void setUp() throws Exception { - init(); - } - - public org.apache.tomcat.jdbc.pool.DataSource createDefaultDataSource() { - org.apache.tomcat.jdbc.pool.DataSource datasource = null; - PoolConfiguration p = new DefaultProperties(); - p.setFairQueue(false); - p.setJmxEnabled(false); - p.setTestWhileIdle(false); - p.setTestOnBorrow(false); - p.setTestOnReturn(false); - p.setValidationInterval(30000); - p.setTimeBetweenEvictionRunsMillis(30000); - p.setMaxActive(threadcount); - p.setInitialSize(threadcount); - p.setMaxWait(10000); - p.setRemoveAbandonedTimeout(10); - p.setMinEvictableIdleTimeMillis(10000); - p.setMinIdle(threadcount); - p.setLogAbandoned(false); - p.setRemoveAbandoned(false); - datasource = new org.apache.tomcat.jdbc.pool.DataSource(); - datasource.setPoolProperties(p); - return datasource; - } - - protected void init() throws Exception { - this.datasource = createDefaultDataSource(); - } - - protected void transferProperties() { - try { - Properties p = new Properties(); - for (int i=0; i< ALL_PROPERTIES.length; i++) { - String name = "get" + Character.toUpperCase(ALL_PROPERTIES[i].charAt(0)) + ALL_PROPERTIES[i].substring(1); - String bname = "is" + name.substring(3); - Method get = null; - try { - get = PoolProperties.class.getMethod(name, new Class[0]); - }catch (NoSuchMethodException x) { - try { - get = PoolProperties.class.getMethod(bname, new Class[0]); - }catch (NoSuchMethodException x2) { - System.err.println(x2.getMessage()); - } - } - if (get!=null) { - Object value = get.invoke(datasource.getPoolProperties(), new Object[0]); - if (value!=null) { - p.setProperty(ALL_PROPERTIES[i], value.toString()); - } - } - } - tDatasource = (BasicDataSource) BasicDataSourceFactory.createDataSource(p); - }catch (Exception x) { - x.printStackTrace(); - } - } - - protected void transferPropertiesToC3P0() throws Exception { -// System.setProperty("com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL", "WARNING"); -// MLog.getLogger().setLevel(MLevel.WARNING); -// MLog.getLogger("com").setLevel(MLevel.WARNING); -// //http://www.mchange.com/projects/c3p0/index.html#automaticTestTable -// ComboPooledDataSource c3p0 = new ComboPooledDataSource(); -// c3p0.setAcquireIncrement(1); -// c3p0.setAcquireRetryAttempts(2); -// c3p0.setAcquireRetryDelay(datasource.getPoolProperties().getMaxWait()); -// c3p0.setCheckoutTimeout(datasource.getPoolProperties().getMaxWait()); -// c3p0.setDebugUnreturnedConnectionStackTraces(datasource.getPoolProperties().isLogAbandoned()); -// c3p0.setIdleConnectionTestPeriod(datasource.getPoolProperties().getTimeBetweenEvictionRunsMillis()/1000); -// c3p0.setInitialPoolSize(datasource.getPoolProperties().getInitialSize()); -// c3p0.setMaxIdleTime(datasource.getPoolProperties().getMinEvictableIdleTimeMillis()/1000); -// c3p0.setMaxIdleTimeExcessConnections(datasource.getPoolProperties().getMaxIdle()); -// c3p0.setMaxPoolSize(datasource.getPoolProperties().getMaxActive()); -// c3p0.setMinPoolSize(datasource.getPoolProperties().getMinIdle()); -// c3p0.setPassword(datasource.getPoolProperties().getPassword()); -// c3p0.setPreferredTestQuery(datasource.getPoolProperties().getValidationQuery()); -// c3p0.setTestConnectionOnCheckin(datasource.getPoolProperties().isTestOnReturn()); -// c3p0.setTestConnectionOnCheckout(datasource.getPoolProperties().isTestOnBorrow()); -// c3p0.setUnreturnedConnectionTimeout(datasource.getPoolProperties().getRemoveAbandonedTimeout()); -// c3p0.setUser(datasource.getPoolProperties().getUsername()); -// c3p0.setUsesTraditionalReflectiveProxies(true); -// c3p0.setJdbcUrl(datasource.getPoolProperties().getUrl()); -// c3p0.setDriverClass(datasource.getPoolProperties().getDriverClassName()); -// this.c3p0Datasource = c3p0; - - /** - acquireIncrement - acquireRetryAttempts - acquireRetryDelay - autoCommitOnClose - automaticTestTable - breakAfterAcquireFailure - checkoutTimeout - connectionCustomizerClassName - connectionTesterClassName - debugUnreturnedConnectionStackTraces - factoryClassLocation - forceIgnoreUnresolvedTransactions - idleConnectionTestPeriod - initialPoolSize - maxAdministrativeTaskTime - maxConnectionAge - maxIdleTime - maxIdleTimeExcessConnections - maxPoolSize - maxStatements - maxStatementsPerConnection - minPoolSize - numHelperThreads - overrideDefaultUser - overrideDefaultPassword - password - preferredTestQuery - propertyCycle - testConnectionOnCheckin - testConnectionOnCheckout - unreturnedConnectionTimeout - user - usesTraditionalReflectiveProxies - */ - } - - - @Override - protected void tearDown() throws Exception { - try {datasource.close();}catch(Exception ignore){} - try {tDatasource.close();}catch(Exception ignore){} - //try {((ComboPooledDataSource)c3p0Datasource).close(true);}catch(Exception ignore){} - datasource = null; - tDatasource = null; - //c3p0Datasource = null; - System.gc(); - } - - private final static String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit"; - private final static String PROP_DEFAULTREADONLY = "defaultReadOnly"; - private final static String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation"; - private final static String PROP_DEFAULTCATALOG = "defaultCatalog"; - private final static String PROP_DRIVERCLASSNAME = "driverClassName"; - private final static String PROP_MAXACTIVE = "maxActive"; - private final static String PROP_MAXIDLE = "maxIdle"; - private final static String PROP_MINIDLE = "minIdle"; - private final static String PROP_INITIALSIZE = "initialSize"; - private final static String PROP_MAXWAIT = "maxWait"; - private final static String PROP_TESTONBORROW = "testOnBorrow"; - private final static String PROP_TESTONRETURN = "testOnReturn"; - private final static String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis"; - private final static String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun"; - private final static String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis"; - private final static String PROP_TESTWHILEIDLE = "testWhileIdle"; - private final static String PROP_PASSWORD = "password"; - private final static String PROP_URL = "url"; - private final static String PROP_USERNAME = "username"; - private final static String PROP_VALIDATIONQUERY = "validationQuery"; - private final static String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed"; - private final static String PROP_REMOVEABANDONED = "removeAbandoned"; - private final static String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout"; - private final static String PROP_LOGABANDONED = "logAbandoned"; - private final static String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements"; - private final static String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements"; - private final static String PROP_CONNECTIONPROPERTIES = "connectionProperties"; - - private final static String[] ALL_PROPERTIES = { - PROP_DEFAULTAUTOCOMMIT, - PROP_DEFAULTREADONLY, - PROP_DEFAULTTRANSACTIONISOLATION, - PROP_DEFAULTCATALOG, - PROP_DRIVERCLASSNAME, - PROP_MAXACTIVE, - PROP_MAXIDLE, - PROP_MINIDLE, - PROP_INITIALSIZE, - PROP_MAXWAIT, - PROP_TESTONBORROW, - PROP_TESTONRETURN, - PROP_TIMEBETWEENEVICTIONRUNSMILLIS, - PROP_NUMTESTSPEREVICTIONRUN, - PROP_MINEVICTABLEIDLETIMEMILLIS, - PROP_TESTWHILEIDLE, - PROP_PASSWORD, - PROP_URL, - PROP_USERNAME, - PROP_VALIDATIONQUERY, - PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED, - PROP_REMOVEABANDONED, - PROP_REMOVEABANDONEDTIMEOUT, - PROP_LOGABANDONED, - PROP_CONNECTIONPROPERTIES - }; - - - -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/FairnessTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/FairnessTest.java deleted file mode 100644 index b296eeefa5f0..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/FairnessTest.java +++ /dev/null @@ -1,283 +0,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.jdbc.test; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.sql.Connection; -import java.sql.Statement; -import java.sql.ResultSet; - -import javax.sql.DataSource; - -import org.apache.tomcat.jdbc.pool.DataSourceProxy; - -/** - * @author Filip Hanik - * @version 1.0 - */ -public class FairnessTest extends DefaultTestCase { - public FairnessTest(String name) { - super(name); - } - - protected boolean run = true; - protected long sleep = Long.getLong("sleep", 10); - protected long complete = Long.getLong("complete",20000); - protected boolean printthread = Boolean.getBoolean("printthread"); - CountDownLatch latch = null; - protected void printThreadResults(TestThread[] threads, String name, int active, int expected) { - long minfetch = Long.MAX_VALUE, maxfetch = Long.MIN_VALUE, totalfetch = 0; - long maxwait = 0, minwait = Long.MAX_VALUE, averagewait = 0, totalwait = 0; - float avgfetch = 0; - for (int i=0; i=FairnessTest.this.complete) break; - long start = System.nanoTime(); - Connection con = null; - try { - if (async) { - Future cf = ((DataSourceProxy)d).getConnectionAsync(); - con = cf.get(); - } else { - con = d.getConnection(); - } - long delta = System.nanoTime() - start; - totalwait += delta; - maxwait = Math.max(delta, maxwait); - minwait = Math.min(delta, minwait); - nroffetch++; - if (query!=null) { - Statement st = con.createStatement(); - ResultSet rs = st.executeQuery(query); - while (rs.next()) { - } - rs.close(); - st.close(); - } - try { - if (FairnessTest.this.sleep>0) sleep(FairnessTest.this.sleep); - } catch (InterruptedException x) { - interrupted(); - } - } finally { - long cstart = System.nanoTime(); - if (con!=null) try {con.close();}catch(Exception x) {x.printStackTrace();} - long cdelta = System.nanoTime() - cstart; - totalcmax += cdelta; - cmax = Math.max(cdelta, cmax); - } - totalruntime+=(System.nanoTime()-start); - } - - } catch (Exception x) { - x.printStackTrace(); - } finally { - FairnessTest.this.latch.countDown(); - } - if (System.getProperty("print-thread-stats")!=null) { - System.out.println("["+getName()+"] "+ - "\n\tMax time to retrieve connection:"+(((float)maxwait)/1000f/1000f)+" ms."+ - "\n\tTotal time to retrieve connection:"+(((float)totalwait)/1000f/1000f)+" ms."+ - "\n\tAverage time to retrieve connection:"+(((float)totalwait)/1000f/1000f)/(float)nroffetch+" ms."+ - "\n\tMax time to close connection:"+(((float)cmax)/1000f/1000f)+" ms."+ - "\n\tTotal time to close connection:"+(((float)totalcmax)/1000f/1000f)+" ms."+ - "\n\tAverage time to close connection:"+(((float)totalcmax)/1000f/1000f)/(float)nroffetch+" ms."+ - "\n\tRun time:"+(((float)totalruntime)/1000f/1000f)+" ms."+ - "\n\tNr of fetch:"+nroffetch); - } - } - } -} - diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/SimplePOJOAsyncExample.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/SimplePOJOAsyncExample.java deleted file mode 100644 index c3cd07100c32..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/SimplePOJOAsyncExample.java +++ /dev/null @@ -1,80 +0,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.jdbc.test; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.Statement; -import java.util.concurrent.Future; - -import org.apache.tomcat.jdbc.pool.DataSource; -import org.apache.tomcat.jdbc.pool.PoolConfiguration; -import org.apache.tomcat.jdbc.pool.PoolProperties; - -public class SimplePOJOAsyncExample { - - public static void main(String[] args) throws Exception { - PoolConfiguration p = new PoolProperties(); - p.setFairQueue(true); - p.setUrl("jdbc:mysql://localhost:3306/mysql?autoReconnect=true"); - p.setDriverClassName("com.mysql.jdbc.Driver"); - p.setUsername("root"); - p.setPassword("password"); - p.setJmxEnabled(true); - p.setTestWhileIdle(false); - p.setTestOnBorrow(true); - p.setValidationQuery("SELECT 1"); - p.setTestOnReturn(false); - p.setValidationInterval(30000); - p.setTimeBetweenEvictionRunsMillis(30000); - p.setMaxActive(100); - p.setInitialSize(10); - p.setMaxWait(10000); - p.setRemoveAbandonedTimeout(60); - p.setMinEvictableIdleTimeMillis(30000); - p.setMinIdle(10); - p.setLogAbandoned(true); - p.setRemoveAbandoned(true); - p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"); - DataSource datasource = new DataSource(); - datasource.setPoolProperties(p); - - Connection con = null; - try { - Future future = datasource.getConnectionAsync(); - while (!future.isDone()) { - System.out.println("Connection is not yet available. Do some background work"); - try { - Thread.sleep(100); //simulate work - }catch (InterruptedException x) { - Thread.interrupted(); - } - } - con = future.get(); //should return instantly - Statement st = con.createStatement(); - ResultSet rs = st.executeQuery("select * from user"); - int cnt = 1; - while (rs.next()) { - System.out.println((cnt++)+". Host:" +rs.getString("Host")+" User:"+rs.getString("User")+" Password:"+rs.getString("Password")); - } - rs.close(); - st.close(); - } finally { - if (con!=null) try {con.close();}catch (Exception ignore) {} - } - } - -} \ No newline at end of file diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/SimplePOJOExample.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/SimplePOJOExample.java deleted file mode 100644 index 50368574bd3d..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/SimplePOJOExample.java +++ /dev/null @@ -1,70 +0,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.jdbc.test; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.Statement; - -import org.apache.tomcat.jdbc.pool.DataSource; -import org.apache.tomcat.jdbc.pool.PoolConfiguration; -import org.apache.tomcat.jdbc.pool.PoolProperties; - -public class SimplePOJOExample { - - public static void main(String[] args) throws Exception { - PoolConfiguration p = new PoolProperties(); - p.setUrl("jdbc:mysql://localhost:3306/mysql?autoReconnect=true"); - p.setDriverClassName("com.mysql.jdbc.Driver"); - p.setUsername("root"); - p.setPassword("password"); - p.setJmxEnabled(true); - p.setTestWhileIdle(false); - p.setTestOnBorrow(true); - p.setValidationQuery("SELECT 1"); - p.setTestOnReturn(false); - p.setValidationInterval(30000); - p.setTimeBetweenEvictionRunsMillis(30000); - p.setMaxActive(100); - p.setInitialSize(10); - p.setMaxWait(10000); - p.setRemoveAbandonedTimeout(60); - p.setMinEvictableIdleTimeMillis(30000); - p.setMinIdle(10); - p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"); - p.setLogAbandoned(true); - p.setRemoveAbandoned(true); - DataSource datasource = new DataSource(); - datasource.setPoolProperties(p); - - Connection con = null; - try { - con = datasource.getConnection(); - Statement st = con.createStatement(); - ResultSet rs = st.executeQuery("select * from user"); - int cnt = 1; - while (rs.next()) { - System.out.println((cnt++)+". Host:" +rs.getString("Host")+" User:"+rs.getString("User")+" Password:"+rs.getString("Password")); - } - rs.close(); - st.close(); - } finally { - if (con!=null) try {con.close();}catch (Exception ignore) {} - } - } - -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/StarvationTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/StarvationTest.java deleted file mode 100644 index 8013ba53548f..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/StarvationTest.java +++ /dev/null @@ -1,111 +0,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.jdbc.test; - -import java.sql.Connection; -import java.sql.SQLException; - -/** - * If a connection is abandoned and closed, - * then that should free up a spot in the pool, and other threads - * that are waiting should not time out and throw an error but be - * able to acquire a connection, since one was just released. - * @author fhanik - * - */ -public class StarvationTest extends DefaultTestCase { - - public StarvationTest(String name) { - super(name); - } - - private void config() { - datasource.getPoolProperties().setMaxActive(1); - datasource.getPoolProperties().setMaxIdle(1); - datasource.getPoolProperties().setInitialSize(1); - datasource.getPoolProperties().setRemoveAbandoned(true); - datasource.getPoolProperties().setRemoveAbandonedTimeout(5); - datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(500); - datasource.getPoolProperties().setMaxWait(10000); - datasource.getPoolProperties().setLogAbandoned(true); - } - -// public void testDBCPConnectionStarvation() throws Exception { -// init(); -// config(); -// this.transferProperties(); -// this.tDatasource.getConnection().close(); -// javax.sql.DataSource datasource = this.tDatasource; -// Connection con1 = datasource.getConnection(); -// Connection con2 = null; -// try { -// con2 = datasource.getConnection(); -// try { -// con2.setCatalog("mysql");//make sure connection is valid -// }catch (SQLException x) { -// assertFalse("2nd Connection is not valid:"+x.getMessage(),true); -// } -// assertTrue("Connection 1 should be closed.",con1.isClosed()); //first connection should be closed -// }catch (Exception x) { -// assertFalse("Connection got starved:"+x.getMessage(),true); -// }finally { -// if (con2!=null) con2.close(); -// } -// -// } - - public void testConnectionStarvation() throws Exception { - init(); - config(); - Connection con1 = datasource.getConnection(); - Connection con2 = null; - try { - con2 = datasource.getConnection(); - try { - con2.setCatalog("mysql");//make sure connection is valid - }catch (SQLException x) { - assertFalse("2nd Connection is not valid:"+x.getMessage(),true); - } - assertTrue("Connection 1 should be closed.",con1.isClosed()); //first connection should be closed - }catch (Exception x) { - assertFalse("Connection got starved:"+x.getMessage(),true); - }finally { - if (con2!=null) con2.close(); - } - } - - public void testFairConnectionStarvation() throws Exception { - init(); - config(); - datasource.getPoolProperties().setFairQueue(true); - Connection con1 = datasource.getConnection(); - Connection con2 = null; - try { - con2 = datasource.getConnection(); - try { - con2.setCatalog("mysql");//make sure connection is valid - }catch (SQLException x) { - assertFalse("2nd Connection is not valid:"+x.getMessage(),true); - } - assertTrue("Connection 1 should be closed.",con1.isClosed()); //first connection should be closed - }catch (Exception x) { - assertFalse("Connection got starved:"+x.getMessage(),true); - }finally { - if (con2!=null) con2.close(); - } - } -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/StatementFinalizerTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/StatementFinalizerTest.java deleted file mode 100644 index b2570a579462..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/StatementFinalizerTest.java +++ /dev/null @@ -1,41 +0,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.jdbc.test; - -import java.sql.Connection; -import java.sql.Statement; - -import org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer; - -public class StatementFinalizerTest extends DefaultTestCase { - - public StatementFinalizerTest(String name) { - super(name); - } - - public void testStatementFinalization() throws Exception { - this.init(); - datasource.setJdbcInterceptors(StatementFinalizer.class.getName()); - Connection con = datasource.getConnection(); - Statement st = con.createStatement(); - assertFalse("Statement should not be closed.",st.isClosed()); - con.close(); - assertTrue("Statement should be closed.",st.isClosed()); - } - -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestAsyncQueue.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestAsyncQueue.java deleted file mode 100644 index 7f21c5208bfe..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestAsyncQueue.java +++ /dev/null @@ -1,86 +0,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.jdbc.test; - -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import org.apache.tomcat.jdbc.pool.FairBlockingQueue; - -import junit.framework.TestCase; - -public class TestAsyncQueue extends TestCase { - protected FairBlockingQueue queue = null; - @Override - protected void setUp() throws Exception { - super.setUp(); - this.queue = new FairBlockingQueue(); - } - - @Override - protected void tearDown() throws Exception { - this.queue = null; - super.tearDown(); - } - - - public void testAsyncPoll1() throws Exception { - Object item = new Object(); - queue.offer(item); - Future future = queue.pollAsync(); - assertEquals(future.get(),item); - } - - public void testAsyncPoll2() throws Exception { - Object item = new Object(); - OfferThread thread = new OfferThread(item,5000); - thread.start(); - Future future = queue.pollAsync(); - try { - future.get(2000, TimeUnit.MILLISECONDS); - assertFalse("Request should have timed out",true); - }catch (TimeoutException x) { - assertTrue("Request timed out properly",true); - }catch (Exception x) { - assertTrue("Request threw an error",false); - x.printStackTrace(); - } - assertEquals(future.get(),item); - } - - protected class OfferThread extends Thread { - Object item = null; - long delay = 5000; - volatile boolean offered = false; - public OfferThread(Object i, long d) { - this.item = i; - this.delay = d; - this.setDaemon(false); - this.setName(TestAsyncQueue.class.getName()+"-OfferThread"); - } - @Override - public void run() { - try { - sleep(delay); - }catch (Exception ignore){} - offered = true; - TestAsyncQueue.this.queue.offer(item); - } - } -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestConcurrency.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestConcurrency.java deleted file mode 100644 index 6a22d0a3df14..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestConcurrency.java +++ /dev/null @@ -1,211 +0,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.jdbc.test; - -import java.sql.Connection; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.tomcat.jdbc.pool.DataSource; -import org.apache.tomcat.jdbc.test.driver.Driver; - -public class TestConcurrency extends DefaultTestCase { - - public static final boolean debug = Boolean.getBoolean("jdbc.debug"); - - protected volatile DataSource ds = null; - - public TestConcurrency(String name) { - super(name); - } - - @Override - public void setUp() { - // TODO Auto-generated method stub - ds = createDefaultDataSource(); - ds.getPoolProperties().setDriverClassName(Driver.class.getName()); - ds.getPoolProperties().setUrl(Driver.url); - ds.getPoolProperties().setInitialSize(0); - ds.getPoolProperties().setMaxIdle(0); - ds.getPoolProperties().setMinIdle(0); - ds.getPoolProperties().setMaxActive(10); - ds.getPoolProperties().setRemoveAbandoned(true); - ds.getPoolProperties().setLogAbandoned(true); - ds.getPoolProperties().setTestWhileIdle(true); - ds.getPoolProperties().setMinEvictableIdleTimeMillis(750); - ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(25); - ds.setFairQueue(true); - } - - @Override - protected void tearDown() throws Exception { - ds.close(true); - Driver.reset(); - super.tearDown(); - } - - public void testSimple() throws Exception { - ds.getConnection().close(); - final int iter = 1000 * 10; - final AtomicInteger loopcount = new AtomicInteger(0); - final Runnable run = new Runnable() { - public void run() { - try { - while (loopcount.incrementAndGet() < iter) { - Connection con = ds.getConnection(); - Thread.sleep(10); - con.close(); - } - }catch (Exception x) { - loopcount.set(iter); //stops the test - x.printStackTrace(); - } - } - }; - Thread[] threads = new Thread[20]; - for (int i=0; i map = SlowQueryReport.getPoolStats(datasource.getPool().getName()); - assertNotNull(map); - assertEquals(1,map.size()); - String key = map.keySet().iterator().next(); - SlowQueryReport.QueryStats stats = map.get(key); - System.out.println("Stats:"+stats); - - for (int i=0; i map = SlowQueryReport.getPoolStats(datasource.getPool().getName()); - assertNotNull(map); - assertEquals(1,map.size()); - String key = map.keySet().iterator().next(); - SlowQueryReport.QueryStats stats = map.get(key); - System.out.println("Stats:"+stats); - ClientListener listener = new ClientListener(); - ConnectionPool pool = datasource.getPool(); - ManagementFactory.getPlatformMBeanServer().addNotificationListener( - SlowQueryReportJmx.getObjectName(SlowQueryReportJmx.class, pool.getName()), - listener, - null, - null); - - for (int i=0; i map = SlowQueryReport.getPoolStats(datasource.getPool().getName()); - assertNotNull(map); - assertEquals(0,map.size()); - ConnectionPool pool = datasource.getPool(); - con.close(); - tearDown(); - assertNull(SlowQueryReport.getPoolStats(pool.getName())); - } - - public void testFailedSql() throws Exception { - int count = 3; - this.init(); - this.datasource.setMaxActive(1); - this.datasource.setJdbcInterceptors(SlowQueryReport.class.getName()); - Connection con = this.datasource.getConnection(); - String slowSql = "select 1 from non_existent"; - int exceptionCount = 0; - for (int i=0; i map = SlowQueryReport.getPoolStats(datasource.getPool().getName()); - assertNotNull(map); - assertEquals(1,map.size()); - ConnectionPool pool = datasource.getPool(); - String key = map.keySet().iterator().next(); - SlowQueryReport.QueryStats stats = map.get(key); - System.out.println("Stats:"+stats); - con.close(); - tearDown(); - assertNull(SlowQueryReport.getPoolStats(pool.getName())); - } - - - public class ClientListener implements NotificationListener { - volatile int notificationCount = 0; - public void handleNotification(Notification notification, - Object handback) { - notificationCount++; - System.out.println("\nReceived notification:"); - System.out.println("\tClassName: " + notification.getClass().getName()); - System.out.println("\tSource: " + notification.getSource()); - System.out.println("\tType: " + notification.getType()); - System.out.println("\tMessage: " + notification.getMessage()); - if (notification instanceof AttributeChangeNotification) { - AttributeChangeNotification acn = - (AttributeChangeNotification) notification; - System.out.println("\tAttributeName: " + acn.getAttributeName()); - System.out.println("\tAttributeType: " + acn.getAttributeType()); - System.out.println("\tNewValue: " + acn.getNewValue()); - System.out.println("\tOldValue: " + acn.getOldValue()); - } - } - } - - -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestStatementCache.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestStatementCache.java deleted file mode 100644 index d3d57400f1cc..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestStatementCache.java +++ /dev/null @@ -1,133 +0,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.jdbc.test; - -import java.sql.Connection; -import java.sql.PreparedStatement; - -import org.apache.tomcat.jdbc.pool.interceptor.StatementCache; - -public class TestStatementCache extends DefaultTestCase { - - - public TestStatementCache(String name) { - super(name); - } - - private static volatile TestStatementCacheInterceptor interceptor = null; - - - @Override - protected void tearDown() throws Exception { - // TODO Auto-generated method stub - this.interceptor = null; - super.tearDown(); - } - - - private void config(boolean cachePrepared, boolean cacheCallable, int max) { - datasource.getPoolProperties().setJdbcInterceptors(TestStatementCacheInterceptor.class.getName()+ - "(prepared="+cachePrepared+",callable="+cacheCallable+",max="+max+")"); - } - - public void testIsCacheEnabled() throws Exception { - init(); - config(true,true,50); - datasource.getConnection().close(); - assertNotNull("Interceptor was not created.", interceptor); - } - - public void testCacheProperties() throws Exception { - init(); - config(true,true,50); - datasource.getConnection().close(); - assertEquals(true, interceptor.isCacheCallable()); - assertEquals(true, interceptor.isCachePrepared()); - assertEquals(50,interceptor.getMaxCacheSize()); - } - - public void testCacheProperties2() throws Exception { - init(); - config(false,false,100); - datasource.getConnection().close(); - assertEquals(false, interceptor.isCacheCallable()); - assertEquals(false, interceptor.isCachePrepared()); - assertEquals(100,interceptor.getMaxCacheSize()); - } - - public void testPreparedStatementCache() throws Exception { - init(); - config(true,false,100); - Connection con = datasource.getConnection(); - PreparedStatement ps1 = con.prepareStatement("select 1"); - PreparedStatement ps2 = con.prepareStatement("select 1"); - assertEquals(0,interceptor.getCacheSize().get()); - ps1.close(); - assertTrue(ps1.isClosed()); - assertEquals(1,interceptor.getCacheSize().get()); - PreparedStatement ps3 = con.prepareStatement("select 1"); - assertEquals(0,interceptor.getCacheSize().get()); - ps2.close(); - assertTrue(ps2.isClosed()); - ps3.close(); - assertTrue(ps3.isClosed()); - assertEquals(1,interceptor.getCacheSize().get()); - } - - public void testPreparedStatementCache2() throws Exception { - init(); - config(false,false,100); - Connection con = datasource.getConnection(); - PreparedStatement ps1 = con.prepareStatement("select 1"); - PreparedStatement ps2 = con.prepareStatement("select 1"); - assertEquals(0,interceptor.getCacheSize().get()); - ps1.close(); - assertTrue(ps1.isClosed()); - assertEquals(0,interceptor.getCacheSize().get()); - PreparedStatement ps3 = con.prepareStatement("select 1"); - assertEquals(0,interceptor.getCacheSize().get()); - ps2.close(); - assertTrue(ps2.isClosed()); - ps3.close(); - assertTrue(ps3.isClosed()); - assertEquals(0,interceptor.getCacheSize().get()); - } - - public void testCallableStatementCache() throws Exception { - } - - public void testMaxCacheSize() throws Exception { - init(); - config(true,false,100); - Connection con1 = datasource.getConnection(); - Connection con2 = datasource.getConnection(); - for (int i=0; i<120; i++) { - Connection con = (i%2==0)?con1:con2; - PreparedStatement ps = con.prepareStatement("select "+i); - ps.close(); - } - assertEquals(100,interceptor.getCacheSize().get()); - } - - - public static class TestStatementCacheInterceptor extends StatementCache { - public TestStatementCacheInterceptor() { - TestStatementCache.interceptor = this; - } - } - -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSuspectTimeout.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSuspectTimeout.java deleted file mode 100644 index b4b18d98f75b..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSuspectTimeout.java +++ /dev/null @@ -1,49 +0,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.jdbc.test; - -import java.sql.Connection; - -import org.apache.tomcat.jdbc.pool.PooledConnection; - - -public class TestSuspectTimeout extends DefaultTestCase { - - public TestSuspectTimeout(String name) { - super(name); - } - - public void testSuspect() throws Exception { - this.init(); - this.datasource.setMaxActive(100); - this.datasource.setMaxIdle(100); - this.datasource.setInitialSize(0); - this.datasource.getPoolProperties().setAbandonWhenPercentageFull(0); - this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100); - this.datasource.getPoolProperties().setRemoveAbandoned(true); - this.datasource.getPoolProperties().setRemoveAbandonedTimeout(100); - this.datasource.getPoolProperties().setSuspectTimeout(1); - this.datasource.getPoolProperties().setLogAbandoned(true); - Connection con = datasource.getConnection(); - assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive()); - Thread.sleep(3000); - PooledConnection pcon = con.unwrap(PooledConnection.class); - assertTrue("Connection should be marked suspect",pcon.isSuspect()); - con.close(); - } -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestTimeout.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestTimeout.java deleted file mode 100644 index 6697e9a1c65e..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestTimeout.java +++ /dev/null @@ -1,93 +0,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.jdbc.test; - -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author Filip Hanik - * @version 1.0 - */ -public class TestTimeout extends DefaultTestCase { - public TestTimeout(String name) { - super(name); - } - - AtomicInteger counter = new AtomicInteger(0); - - public void testCheckoutTimeout() throws Exception { - try { - init(); - this.datasource.getPoolProperties().setTestWhileIdle(true); - this.datasource.getPoolProperties().setTestOnBorrow(false); - this.datasource.getPoolProperties().setTestOnReturn(false); - this.datasource.getPoolProperties().setValidationInterval(30000); - this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(1000); - this.datasource.getPoolProperties().setMaxActive(20); - this.datasource.getPoolProperties().setMaxWait(3000); - this.datasource.getPoolProperties().setRemoveAbandonedTimeout(5); - this.datasource.getPoolProperties().setMinEvictableIdleTimeMillis(5000); - this.datasource.getPoolProperties().setMinIdle(5); - this.datasource.getPoolProperties().setLogAbandoned(true); - System.out.println("About to test connection pool:"+datasource); - for (int i = 0; i < 21; i++) { - long now = System.currentTimeMillis(); - this.datasource.getConnection(); - long delta = System.currentTimeMillis()-now; - System.out.println("Got connection #"+i+" in "+delta+" ms."); - } - assertTrue(false); - } catch ( Exception x ) { - assertTrue(true); - }finally { - Thread.sleep(2000); - tearDown(); - } - } - - public void testCheckoutTimeoutFair() throws Exception { - try { - init(); - this.datasource.getPoolProperties().setFairQueue(true); - this.datasource.getPoolProperties().setTestWhileIdle(true); - this.datasource.getPoolProperties().setTestOnBorrow(false); - this.datasource.getPoolProperties().setTestOnReturn(false); - this.datasource.getPoolProperties().setValidationInterval(30000); - this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(1000); - this.datasource.getPoolProperties().setMaxActive(20); - this.datasource.getPoolProperties().setMaxWait(3000); - this.datasource.getPoolProperties().setRemoveAbandonedTimeout(5); - this.datasource.getPoolProperties().setMinEvictableIdleTimeMillis(5000); - this.datasource.getPoolProperties().setMinIdle(5); - this.datasource.getPoolProperties().setLogAbandoned(true); - System.out.println("About to test connection pool:"+datasource); - for (int i = 0; i < 21; i++) { - long now = System.currentTimeMillis(); - this.datasource.getConnection(); - long delta = System.currentTimeMillis()-now; - System.out.println("Got connection #"+i+" in "+delta+" ms."); - } - assertTrue(false); - } catch ( Exception x ) { - assertTrue(true); - }finally { - Thread.sleep(2000); - tearDown(); - } - } - -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TwoDataSources.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TwoDataSources.java deleted file mode 100644 index 2a500e7ae412..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TwoDataSources.java +++ /dev/null @@ -1,65 +0,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.jdbc.test; - -import java.sql.Connection; - -public class TwoDataSources extends DefaultTestCase { - - public TwoDataSources(String name) { - super(name); - } - - public void testTwoDataSources() throws Exception { - org.apache.tomcat.jdbc.pool.DataSource d1 = this.createDefaultDataSource(); - org.apache.tomcat.jdbc.pool.DataSource d2 = this.createDefaultDataSource(); - d1.setRemoveAbandoned(true); - d1.setRemoveAbandonedTimeout(10); - d1.setTimeBetweenEvictionRunsMillis(1000); - d2.setRemoveAbandoned(false); - Connection c1 = d1.getConnection(); - Connection c2 = d2.getConnection(); - Thread.sleep(5000); - try { - c1.createStatement(); - assertTrue("Connection should have been abandoned.",false); - }catch (Exception x) { - assertTrue("This is correct, c1 is abandoned",true); - } - - try { - c2.createStatement(); - assertTrue("Connection should not have been abandoned.",true); - }catch (Exception x) { - assertTrue("Connection c2 should be working",false); - } - try { - assertTrue("Connection should have been closed.",c1.isClosed()); - }catch (Exception x) { - assertTrue("This is correct, c1 is closed",true); - } - try { - assertFalse("Connection c2 should not have been closed.",c2.isClosed()); - }catch (Exception x) { - assertTrue("Connection c2 should be working",false); - } - - - } - -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Connection.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Connection.java deleted file mode 100644 index b37d37d405a8..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Connection.java +++ /dev/null @@ -1,223 +0,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.jdbc.test.driver; - -import java.sql.Array; -import java.sql.Blob; -import java.sql.CallableStatement; -import java.sql.Clob; -import java.sql.DatabaseMetaData; -import java.sql.NClob; -import java.sql.PreparedStatement; -import java.sql.SQLClientInfoException; -import java.sql.SQLException; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Savepoint; -import java.sql.Statement; -import java.sql.Struct; -import java.util.Map; -import java.util.Properties; - -public class Connection implements java.sql.Connection { - - public void clearWarnings() throws SQLException { - } - - public void close() throws SQLException { - Driver.disconnectCount.incrementAndGet(); - } - - public void commit() throws SQLException { - } - - public Array createArrayOf(String typeName, Object[] elements) throws SQLException { - return null; - } - - public Blob createBlob() throws SQLException { - return null; - } - - public Clob createClob() throws SQLException { - return null; - } - - public NClob createNClob() throws SQLException { - return null; - } - - public SQLXML createSQLXML() throws SQLException { - return null; - } - - public Statement createStatement() throws SQLException { - return new org.apache.tomcat.jdbc.test.driver.Statement(); - } - - public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { - return new org.apache.tomcat.jdbc.test.driver.Statement(); - } - - public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - return new org.apache.tomcat.jdbc.test.driver.Statement(); - } - - public Struct createStruct(String typeName, Object[] attributes) throws SQLException { - return null; - } - - public boolean getAutoCommit() throws SQLException { - return false; - } - - public String getCatalog() throws SQLException { - return null; - } - - public Properties getClientInfo() throws SQLException { - return null; - } - - public String getClientInfo(String name) throws SQLException { - return null; - } - - public int getHoldability() throws SQLException { - return 0; - } - - public DatabaseMetaData getMetaData() throws SQLException { - return null; - } - - public int getTransactionIsolation() throws SQLException { - return 0; - } - - public Map> getTypeMap() throws SQLException { - return null; - } - - public SQLWarning getWarnings() throws SQLException { - return null; - } - - public boolean isClosed() throws SQLException { - return false; - } - - public boolean isReadOnly() throws SQLException { - return false; - } - - public boolean isValid(int timeout) throws SQLException { - return false; - } - - public String nativeSQL(String sql) throws SQLException { - return null; - } - - public CallableStatement prepareCall(String sql) throws SQLException { - return new org.apache.tomcat.jdbc.test.driver.Statement(); - } - - public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - return new org.apache.tomcat.jdbc.test.driver.Statement(); - } - - public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - return new org.apache.tomcat.jdbc.test.driver.Statement(); - } - - public PreparedStatement prepareStatement(String sql) throws SQLException { - return new org.apache.tomcat.jdbc.test.driver.Statement(); - } - - public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { - return new org.apache.tomcat.jdbc.test.driver.Statement(); - } - - - public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { - return new org.apache.tomcat.jdbc.test.driver.Statement(); - } - - public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { - return new org.apache.tomcat.jdbc.test.driver.Statement(); - } - - public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - return new org.apache.tomcat.jdbc.test.driver.Statement(); - } - - - public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - return new org.apache.tomcat.jdbc.test.driver.Statement(); - } - - public void releaseSavepoint(Savepoint savepoint) throws SQLException { - } - - public void rollback() throws SQLException { - } - - public void rollback(Savepoint savepoint) throws SQLException { - } - - public void setAutoCommit(boolean autoCommit) throws SQLException { - } - - public void setCatalog(String catalog) throws SQLException { - } - - public void setClientInfo(Properties properties) throws SQLClientInfoException { - } - - public void setClientInfo(String name, String value) throws SQLClientInfoException { - } - - public void setHoldability(int holdability) throws SQLException { - } - - public void setReadOnly(boolean readOnly) throws SQLException { - } - - public Savepoint setSavepoint() throws SQLException { - return null; - } - - public Savepoint setSavepoint(String name) throws SQLException { - return null; - } - - public void setTransactionIsolation(int level) throws SQLException { - } - - public void setTypeMap(Map> map) throws SQLException { - } - - public boolean isWrapperFor(Class iface) throws SQLException { - return false; - } - - public T unwrap(Class iface) throws SQLException { - return null; - } - -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Driver.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Driver.java deleted file mode 100644 index 0a27d1beb9f8..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Driver.java +++ /dev/null @@ -1,72 +0,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.jdbc.test.driver; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.DriverPropertyInfo; -import java.sql.SQLException; -import java.util.Properties; -import java.util.concurrent.atomic.AtomicInteger; - -public class Driver implements java.sql.Driver { - public static final String url = "jdbc:tomcat:test"; - public static final AtomicInteger connectCount = new AtomicInteger(0); - public static final AtomicInteger disconnectCount = new AtomicInteger(0); - - public static void reset() { - connectCount.set(0); - disconnectCount.set(0); - } - - static { - try { - DriverManager.registerDriver(new Driver()); - }catch (Exception x) { - x.printStackTrace(); - throw new RuntimeException(x); - } - } - - public Driver() { - } - - public boolean acceptsURL(String url) throws SQLException { - return url == Driver.url; - } - - public Connection connect(String url, Properties info) throws SQLException { - connectCount.addAndGet(1); - return new org.apache.tomcat.jdbc.test.driver.Connection(); - } - - public int getMajorVersion() { - return 0; - } - - public int getMinorVersion() { - return 0; - } - - public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { - return null; - } - - public boolean jdbcCompliant() { - return false; - } -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/ResultSet.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/ResultSet.java deleted file mode 100644 index 9986c48a3b55..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/ResultSet.java +++ /dev/null @@ -1,1200 +0,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.jdbc.test.driver; - -import java.io.InputStream; -import java.io.Reader; -import java.math.BigDecimal; -import java.net.URL; -import java.sql.Array; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Date; -import java.sql.NClob; -import java.sql.Ref; -import java.sql.ResultSetMetaData; -import java.sql.RowId; -import java.sql.SQLException; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.Calendar; -import java.util.Map; - -public class ResultSet implements java.sql.ResultSet { - boolean hasNext = true; - - public boolean absolute(int row) throws SQLException { - return false; - } - - public void afterLast() throws SQLException { - } - - public void beforeFirst() throws SQLException { - } - - public void cancelRowUpdates() throws SQLException { - } - - public void clearWarnings() throws SQLException { - } - public void close() throws SQLException { - } - - public void deleteRow() throws SQLException { - } - - public int findColumn(String columnLabel) throws SQLException { - return 0; - } - - public boolean first() throws SQLException { - return hasNext; - } - - public Array getArray(int columnIndex) throws SQLException { - return null; - } - - public Array getArray(String columnLabel) throws SQLException { - return null; - } - - @Override - public InputStream getAsciiStream(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public InputStream getAsciiStream(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public BigDecimal getBigDecimal(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public BigDecimal getBigDecimal(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public BigDecimal getBigDecimal(int columnIndex, int scale) - throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public BigDecimal getBigDecimal(String columnLabel, int scale) - throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public InputStream getBinaryStream(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public InputStream getBinaryStream(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Blob getBlob(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Blob getBlob(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean getBoolean(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean getBoolean(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public byte getByte(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public byte getByte(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public byte[] getBytes(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public byte[] getBytes(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Reader getCharacterStream(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Reader getCharacterStream(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Clob getClob(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Clob getClob(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getConcurrency() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String getCursorName() throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Date getDate(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Date getDate(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Date getDate(int columnIndex, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Date getDate(String columnLabel, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public double getDouble(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public double getDouble(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getFetchDirection() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getFetchSize() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public float getFloat(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public float getFloat(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getHoldability() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getInt(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getInt(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public long getLong(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public long getLong(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public ResultSetMetaData getMetaData() throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Reader getNCharacterStream(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Reader getNCharacterStream(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public NClob getNClob(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public NClob getNClob(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getNString(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getNString(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Object getObject(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Object getObject(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Object getObject(int columnIndex, Map> map) - throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Object getObject(String columnLabel, Map> map) - throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Ref getRef(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Ref getRef(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getRow() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public RowId getRowId(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public RowId getRowId(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public SQLXML getSQLXML(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public SQLXML getSQLXML(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public short getShort(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public short getShort(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public Statement getStatement() throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getString(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getString(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Time getTime(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Time getTime(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Time getTime(int columnIndex, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Time getTime(String columnLabel, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Timestamp getTimestamp(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Timestamp getTimestamp(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Timestamp getTimestamp(int columnIndex, Calendar cal) - throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Timestamp getTimestamp(String columnLabel, Calendar cal) - throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getType() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public URL getURL(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public URL getURL(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public InputStream getUnicodeStream(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public InputStream getUnicodeStream(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public SQLWarning getWarnings() throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public void insertRow() throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public boolean isAfterLast() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isBeforeFirst() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isClosed() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isFirst() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isLast() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean last() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void moveToCurrentRow() throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void moveToInsertRow() throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public boolean next() throws SQLException { - boolean next = hasNext; - hasNext = false; - // TODO Auto-generated method stub - return next; - } - - @Override - public boolean previous() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void refreshRow() throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public boolean relative(int rows) throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean rowDeleted() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean rowInserted() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean rowUpdated() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void setFetchDirection(int direction) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setFetchSize(int rows) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateArray(int columnIndex, Array x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateArray(String columnLabel, Array x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateAsciiStream(int columnIndex, InputStream x) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateAsciiStream(String columnLabel, InputStream x) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateAsciiStream(int columnIndex, InputStream x, int length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateAsciiStream(String columnLabel, InputStream x, int length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateAsciiStream(int columnIndex, InputStream x, long length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateAsciiStream(String columnLabel, InputStream x, long length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBigDecimal(int columnIndex, BigDecimal x) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBigDecimal(String columnLabel, BigDecimal x) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBinaryStream(int columnIndex, InputStream x) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBinaryStream(String columnLabel, InputStream x) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBinaryStream(int columnIndex, InputStream x, int length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBinaryStream(String columnLabel, InputStream x, int length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBinaryStream(int columnIndex, InputStream x, long length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBinaryStream(String columnLabel, InputStream x, - long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBlob(int columnIndex, Blob x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBlob(String columnLabel, Blob x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBlob(int columnIndex, InputStream inputStream) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBlob(String columnLabel, InputStream inputStream) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBlob(int columnIndex, InputStream inputStream, long length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBlob(String columnLabel, InputStream inputStream, - long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBoolean(int columnIndex, boolean x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBoolean(String columnLabel, boolean x) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateByte(int columnIndex, byte x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateByte(String columnLabel, byte x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBytes(int columnIndex, byte[] x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateBytes(String columnLabel, byte[] x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateCharacterStream(int columnIndex, Reader x) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateCharacterStream(String columnLabel, Reader reader) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateCharacterStream(int columnIndex, Reader x, int length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateCharacterStream(String columnLabel, Reader reader, - int length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateCharacterStream(int columnIndex, Reader x, long length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateCharacterStream(String columnLabel, Reader reader, - long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateClob(int columnIndex, Clob x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateClob(String columnLabel, Clob x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateClob(int columnIndex, Reader reader) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateClob(String columnLabel, Reader reader) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateClob(int columnIndex, Reader reader, long length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateClob(String columnLabel, Reader reader, long length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateDate(int columnIndex, Date x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateDate(String columnLabel, Date x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateDouble(int columnIndex, double x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateDouble(String columnLabel, double x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateFloat(int columnIndex, float x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateFloat(String columnLabel, float x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateInt(int columnIndex, int x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateInt(String columnLabel, int x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateLong(int columnIndex, long x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateLong(String columnLabel, long x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNCharacterStream(int columnIndex, Reader x) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNCharacterStream(String columnLabel, Reader reader) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNCharacterStream(int columnIndex, Reader x, long length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNCharacterStream(String columnLabel, Reader reader, - long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNClob(int columnIndex, NClob clob) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNClob(String columnLabel, NClob clob) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNClob(int columnIndex, Reader reader) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNClob(String columnLabel, Reader reader) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNClob(int columnIndex, Reader reader, long length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNClob(String columnLabel, Reader reader, long length) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNString(int columnIndex, String string) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNString(String columnLabel, String string) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNull(int columnIndex) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateNull(String columnLabel) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateObject(int columnIndex, Object x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateObject(String columnLabel, Object x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateObject(int columnIndex, Object x, int scaleOrLength) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateObject(String columnLabel, Object x, int scaleOrLength) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateRef(int columnIndex, Ref x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateRef(String columnLabel, Ref x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateRow() throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateRowId(int columnIndex, RowId x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateRowId(String columnLabel, RowId x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateSQLXML(int columnIndex, SQLXML xmlObject) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateSQLXML(String columnLabel, SQLXML xmlObject) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateShort(int columnIndex, short x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateShort(String columnLabel, short x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateString(int columnIndex, String x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateString(String columnLabel, String x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateTime(int columnIndex, Time x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateTime(String columnLabel, Time x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateTimestamp(int columnIndex, Timestamp x) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void updateTimestamp(String columnLabel, Timestamp x) - throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public boolean wasNull() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public T unwrap(Class iface) throws SQLException { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Statement.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Statement.java deleted file mode 100644 index d7d5f9e2180d..000000000000 --- a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Statement.java +++ /dev/null @@ -1,1293 +0,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.jdbc.test.driver; - -import java.io.InputStream; -import java.io.Reader; -import java.math.BigDecimal; -import java.net.URL; -import java.sql.Array; -import java.sql.Blob; -import java.sql.CallableStatement; -import java.sql.Clob; -import java.sql.Connection; -import java.sql.Date; -import java.sql.NClob; -import java.sql.ParameterMetaData; -import java.sql.Ref; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.RowId; -import java.sql.SQLException; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.Calendar; -import java.util.Map; - -public class Statement implements CallableStatement { - - @Override - public Array getArray(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Array getArray(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public BigDecimal getBigDecimal(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public BigDecimal getBigDecimal(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Blob getBlob(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Blob getBlob(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean getBoolean(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean getBoolean(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public byte getByte(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public byte getByte(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public byte[] getBytes(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public byte[] getBytes(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Reader getCharacterStream(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Reader getCharacterStream(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Clob getClob(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Clob getClob(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Date getDate(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Date getDate(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Date getDate(int parameterIndex, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Date getDate(String parameterName, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public double getDouble(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public double getDouble(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public float getFloat(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public float getFloat(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getInt(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getInt(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public long getLong(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public long getLong(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public Reader getNCharacterStream(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Reader getNCharacterStream(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public NClob getNClob(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public NClob getNClob(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getNString(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getNString(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Object getObject(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Object getObject(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Object getObject(int parameterIndex, Map> map) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Object getObject(String parameterName, Map> map) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Ref getRef(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Ref getRef(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public RowId getRowId(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public RowId getRowId(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public SQLXML getSQLXML(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public SQLXML getSQLXML(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public short getShort(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public short getShort(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String getString(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getString(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Time getTime(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Time getTime(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Time getTime(int parameterIndex, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Time getTime(String parameterName, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Timestamp getTimestamp(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Timestamp getTimestamp(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public URL getURL(int parameterIndex) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public URL getURL(String parameterName) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void registerOutParameter(String parameterName, int sqlType) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setAsciiStream(String parameterName, InputStream x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBinaryStream(String parameterName, InputStream x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBlob(String parameterName, Blob x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBlob(String parameterName, InputStream inputStream) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBoolean(String parameterName, boolean x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setByte(String parameterName, byte x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBytes(String parameterName, byte[] x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setCharacterStream(String parameterName, Reader reader) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setCharacterStream(String parameterName, Reader reader, int length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setClob(String parameterName, Clob x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setClob(String parameterName, Reader reader) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setClob(String parameterName, Reader reader, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setDate(String parameterName, Date x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setDate(String parameterName, Date x, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setDouble(String parameterName, double x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setFloat(String parameterName, float x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setInt(String parameterName, int x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setLong(String parameterName, long x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNCharacterStream(String parameterName, Reader value) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNClob(String parameterName, NClob value) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNClob(String parameterName, Reader reader) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNClob(String parameterName, Reader reader, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNString(String parameterName, String value) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNull(String parameterName, int sqlType) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNull(String parameterName, int sqlType, String typeName) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setObject(String parameterName, Object x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setRowId(String parameterName, RowId x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setShort(String parameterName, short x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setString(String parameterName, String x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setTime(String parameterName, Time x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setTime(String parameterName, Time x, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setTimestamp(String parameterName, Timestamp x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setURL(String parameterName, URL val) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public boolean wasNull() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void addBatch() throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void clearParameters() throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public boolean execute() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public ResultSet executeQuery() throws SQLException { - // TODO Auto-generated method stub - return new org.apache.tomcat.jdbc.test.driver.ResultSet(); - } - - @Override - public int executeUpdate() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public ResultSetMetaData getMetaData() throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public ParameterMetaData getParameterMetaData() throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setArray(int parameterIndex, Array x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBlob(int parameterIndex, Blob x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBoolean(int parameterIndex, boolean x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setByte(int parameterIndex, byte x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setBytes(int parameterIndex, byte[] x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setClob(int parameterIndex, Clob x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setClob(int parameterIndex, Reader reader) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setDate(int parameterIndex, Date x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setDouble(int parameterIndex, double x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setFloat(int parameterIndex, float x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setInt(int parameterIndex, int x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setLong(int parameterIndex, long x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNClob(int parameterIndex, NClob value) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNClob(int parameterIndex, Reader reader) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNString(int parameterIndex, String value) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNull(int parameterIndex, int sqlType) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setObject(int parameterIndex, Object x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setRef(int parameterIndex, Ref x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setRowId(int parameterIndex, RowId x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setShort(int parameterIndex, short x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setString(int parameterIndex, String x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setTime(int parameterIndex, Time x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setURL(int parameterIndex, URL x) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void addBatch(String sql) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void cancel() throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void clearBatch() throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void clearWarnings() throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void close() throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public boolean execute(String sql) throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean execute(String sql, int[] columnIndexes) throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean execute(String sql, String[] columnNames) throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public int[] executeBatch() throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public ResultSet executeQuery(String sql) throws SQLException { - // TODO Auto-generated method stub - return new org.apache.tomcat.jdbc.test.driver.ResultSet(); - } - - @Override - public int executeUpdate(String sql) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int executeUpdate(String sql, String[] columnNames) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public Connection getConnection() throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getFetchDirection() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getFetchSize() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public ResultSet getGeneratedKeys() throws SQLException { - // TODO Auto-generated method stub - return new org.apache.tomcat.jdbc.test.driver.ResultSet(); - } - - @Override - public int getMaxFieldSize() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getMaxRows() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public boolean getMoreResults() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean getMoreResults(int current) throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public int getQueryTimeout() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public ResultSet getResultSet() throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getResultSetConcurrency() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getResultSetHoldability() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getResultSetType() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getUpdateCount() throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public SQLWarning getWarnings() throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean isClosed() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isPoolable() throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void setCursorName(String name) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setEscapeProcessing(boolean enable) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setFetchDirection(int direction) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setFetchSize(int rows) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setMaxFieldSize(int max) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setMaxRows(int max) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setPoolable(boolean poolable) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public void setQueryTimeout(int seconds) throws SQLException { - // TODO Auto-generated method stub - - } - - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - // TODO Auto-generated method stub - return false; - } - - @Override - public T unwrap(Class iface) throws SQLException { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/modules/tomcat-lite/.classpath b/modules/tomcat-lite/.classpath deleted file mode 100644 index bfb992185b51..000000000000 --- a/modules/tomcat-lite/.classpath +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/modules/tomcat-lite/.project b/modules/tomcat-lite/.project deleted file mode 100644 index b4c826d41daf..000000000000 --- a/modules/tomcat-lite/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - tomcat-lite - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/modules/tomcat-lite/build.xml b/modules/tomcat-lite/build.xml deleted file mode 100644 index dd3799818be0..000000000000 --- a/modules/tomcat-lite/build.xml +++ /dev/null @@ -1,325 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/modules/tomcat-lite/ivy.xml b/modules/tomcat-lite/ivy.xml deleted file mode 100644 index b0fcbbd0b889..000000000000 --- a/modules/tomcat-lite/ivy.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - diff --git a/modules/tomcat-lite/java/org/apache/coyote/lite/LiteProtocolHandler.java b/modules/tomcat-lite/java/org/apache/coyote/lite/LiteProtocolHandler.java deleted file mode 100644 index 541ac19668fc..000000000000 --- a/modules/tomcat-lite/java/org/apache/coyote/lite/LiteProtocolHandler.java +++ /dev/null @@ -1,426 +0,0 @@ -package org.apache.coyote.lite; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import org.apache.coyote.ActionCode; -import org.apache.coyote.ActionHook; -import org.apache.coyote.Adapter; -import org.apache.coyote.InputBuffer; -import org.apache.coyote.OutputBuffer; -import org.apache.coyote.ProtocolHandler; -import org.apache.coyote.Request; -import org.apache.coyote.Response; -import org.apache.tomcat.lite.http.HttpClient; -import org.apache.tomcat.lite.http.HttpChannel; -import org.apache.tomcat.lite.http.HttpConnectionPool; -import org.apache.tomcat.lite.http.HttpConnector; -import org.apache.tomcat.lite.http.HttpRequest; -import org.apache.tomcat.lite.http.HttpResponse; -import org.apache.tomcat.lite.http.HttpServer; -import org.apache.tomcat.lite.http.MultiMap; -import org.apache.tomcat.lite.http.HttpChannel.HttpService; -import org.apache.tomcat.lite.http.HttpConnectionPool.RemoteServer; -import org.apache.tomcat.lite.http.HttpConnector.HttpChannelEvents; -import org.apache.tomcat.lite.http.HttpConnector.HttpConnection; -import org.apache.tomcat.lite.http.MultiMap.Entry; -import org.apache.tomcat.lite.io.CBuffer; -import org.apache.tomcat.lite.io.IOConnector; -import org.apache.tomcat.lite.io.SocketConnector; -import org.apache.tomcat.lite.io.SslProvider; -import org.apache.tomcat.util.buf.ByteChunk; -import org.apache.tomcat.util.buf.MessageBytes; -import org.apache.tomcat.util.http.MimeHeaders; -import org.apache.tomcat.util.modeler.Registry; - -/** - * Work in progress - use the refactored http as a coyote connector. - * Just basic requests work right now - need to implement all the - * methods of coyote. - * - * - * @author Costin Manolache - */ -public class LiteProtocolHandler implements ProtocolHandler { - - Adapter adapter; - Map attributes = new HashMap(); - - - HttpConnector httpConnServer; - int port = 8999; - - // Tomcat JMX integration - Registry registry; - - public LiteProtocolHandler() { - } - - @Override - public void destroy() throws Exception { - } - - @Override - public Adapter getAdapter() { - return adapter; - } - - @Override - public Object getAttribute(String name) { - // TODO: dynamic - return attributes.get(name); - } - - @Override - public Iterator getAttributeNames() { - return attributes.keySet().iterator(); - } - - @Override - public void init() throws Exception { - registry = Registry.getRegistry(null, null); - httpConnServer = HttpServer.newServer(port); - - httpConnServer.getDispatcher().setDefaultService(new HttpService() { - @Override - public void service(HttpRequest httpReq, HttpResponse httpRes) - throws IOException { - coyoteService(httpReq, httpRes); - } - - }); - final String base = "" + port; - bind("Httpconnector-" + port, httpConnServer); - bind("HttpconnectorPool-" + port, httpConnServer.cpool); - IOConnector io = httpConnServer.getIOConnector(); - int ioLevel = 0; - while (io != null) { - bind("IOConnector-" + (ioLevel++) + "-" + base, io); - if (io instanceof SocketConnector) { - bind("NioThread-" + base, - ((SocketConnector) io).getSelector()); - - } - io = io.getNet(); - } - httpConnServer.cpool.setEvents(new HttpConnectionPool.HttpConnectionPoolEvents() { - - @Override - public void closedConnection(RemoteServer host, HttpConnection con) { - unbind("HttpConnection-" + base + "-" + con.getId()); - } - - @Override - public void newConnection(RemoteServer host, HttpConnection con) { - bind("HttpConnection-" + base + "-" + con.getId(), con); - } - - @Override - public void newTarget(RemoteServer host) { - bind("AsyncHttp-" + base + "-" + host.target, host); - } - - @Override - public void targetRemoved(RemoteServer host) { - unbind("AsyncHttp-" + base + "-" + host.target); - } - - }); - - httpConnServer.setOnCreate(new HttpChannelEvents() { - @Override - public void onCreate(HttpChannel data, HttpConnector extraData) - throws IOException { - bind("AsyncHttp-" + base + "-" + data.getId(), data); - } - @Override - public void onDestroy(HttpChannel data, HttpConnector extraData) - throws IOException { - unbind("AsyncHttp-" + base + "-" + data.getId()); - } - }); - - // TODO: process attributes via registry !! - - } - - private void bind(String name, Object o) { - try { - registry.registerComponent(o, "TomcatLite:name=" + name, null); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void unbind(String name) { - registry.unregisterComponent("name=" + name); - } - - @Override - public void pause() throws Exception { - } - - @Override - public void resume() throws Exception { - } - - @Override - public void setAdapter(Adapter adapter) { - this.adapter = adapter; - - } - - @Override - public void setAttribute(String name, Object value) { - attributes.put(name, value); - } - - @Override - public void start() throws Exception { - httpConnServer.start(); - } - - public void setPort(int port) { - this.port = port; - } - - /** - * Wrap old tomcat buffer to lite buffer. - */ - private void wrap(MessageBytes dest, CBuffer buffer) { - dest.setChars(buffer.array(), buffer.position(), - buffer.length()); - } - - /** - * Main lite service method, will wrap to coyote request - */ - private void coyoteService(final HttpRequest httpReq, final HttpResponse httpRes) { - // TODO: reuse, per req - RequestData rc = new RequestData(); - rc.init(httpReq, httpRes); - - try { - adapter.service(rc.req, rc.res); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - /** - * ActionHook implementation, include coyote request/response objects. - */ - public class RequestData implements ActionHook { - private final class LiteOutputBuffer implements OutputBuffer { - @Override - public int doWrite(org.apache.tomcat.util.buf.ByteChunk chunk, - Response response) throws IOException { - httpRes.getBody().append(chunk.getBuffer(), chunk.getStart(), - chunk.getLength()); - return chunk.getLength(); - } - } - - OutputBuffer outputBuffer = new LiteOutputBuffer(); - // TODO: recycle, etc. - Request req = new Request(); - - Response res = new Response(); - HttpResponse httpRes; - HttpRequest httpReq; - - InputBuffer inputBuffer = new InputBuffer() { - @Override - public int doRead(ByteChunk bchunk, Request request) - throws IOException { - httpReq.getBody().waitData(httpReq.getHttpChannel().getIOTimeout()); - int rd = - httpReq.getBody().read(bchunk.getBytes(), - bchunk.getStart(), bchunk.getBytes().length); - if (rd > 0) { - bchunk.setEnd(bchunk.getEnd() + rd); - } - return rd; - } - }; - - public RequestData() { - req.setInputBuffer(inputBuffer); - res.setOutputBuffer(outputBuffer); - req.setResponse(res); - res.setRequest(req); - res.setHook(this); - } - - public void init(HttpRequest httpReq, HttpResponse httpRes) { - this.httpRes = httpRes; - this.httpReq = httpReq; - // TODO: turn http request into a coyote request - copy all fields, - // add hooks where needed. - - wrap(req.decodedURI(), httpReq.decodedURI()); - wrap(req.method(), httpReq.method()); - wrap(req.protocol(), httpReq.protocol()); - wrap(req.requestURI(), httpReq.requestURI()); - wrap(req.queryString(), httpReq.queryString()); - - req.setServerPort(httpReq.getServerPort()); - req.serverName().setString(req.localName().toString()); - - MultiMap mimeHeaders = httpReq.getMimeHeaders(); - MimeHeaders coyoteHeaders = req.getMimeHeaders(); - for (int i = 0; i < mimeHeaders.size(); i++ ) { - Entry entry = mimeHeaders.getEntry(i); - MessageBytes val = - coyoteHeaders.addValue(entry.getName().toString()); - val.setString(entry.getValue().toString()); - } - } - - /** - * Send an action to the connector. - * - * @param actionCode Type of the action - * @param param Action parameter - */ - public void action(ActionCode actionCode, Object param) { - - if (actionCode == ActionCode.ACTION_POST_REQUEST) { - commit(); // make sure it's sent - on errors - } else if (actionCode == ActionCode.ACTION_COMMIT) { - commit(); - } else if (actionCode == ActionCode.ACTION_ACK) { - // Done automatically by http connector - } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) { - try { - httpReq.send(); - } catch (IOException e) { - httpReq.getHttpChannel().abort(e); - res.setErrorException(e); - } - - } else if (actionCode == ActionCode.ACTION_CLOSE) { - // Close - - // End the processing of the current request, and stop any further - // transactions with the client - -// comet = false; -// try { -// outputBuffer.endRequest(); -// } catch (IOException e) { -// // Set error flag -// error = true; -// } - - } else if (actionCode == ActionCode.ACTION_RESET) { - // Reset response - // Note: This must be called before the response is committed - httpRes.getBody().clear(); - - } else if (actionCode == ActionCode.ACTION_CUSTOM) { - - // Do nothing - - } else if (actionCode == ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE) { - req.remoteAddr().setString(httpReq.remoteAddr().toString()); - } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_NAME_ATTRIBUTE) { - req.localName().setString(httpReq.localName().toString()); - } else if (actionCode == ActionCode.ACTION_REQ_HOST_ATTRIBUTE) { - req.remoteHost().setString(httpReq.remoteHost().toString()); - } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE) { - req.localAddr().setString(httpReq.localAddr().toString()); - } else if (actionCode == ActionCode.ACTION_REQ_REMOTEPORT_ATTRIBUTE) { - req.setRemotePort(httpReq.getRemotePort()); - } else if (actionCode == ActionCode.ACTION_REQ_LOCALPORT_ATTRIBUTE) { - req.setLocalPort(httpReq.getLocalPort()); - } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) { - - Object sslAtt = httpReq.getHttpChannel().getNet().getAttribute(SslProvider.ATT_SSL_CIPHER); - req.setAttribute("javax.servlet.request.cipher_suite", sslAtt); - - sslAtt = httpReq.getHttpChannel().getNet().getAttribute(SslProvider.ATT_SSL_KEY_SIZE); - req.setAttribute("javax.servlet.request.key_size", sslAtt); - - sslAtt = httpReq.getHttpChannel().getNet().getAttribute(SslProvider.ATT_SSL_SESSION_ID); - req.setAttribute("javax.servlet.request.ssl_session", sslAtt); - - } else if (actionCode == ActionCode.ACTION_REQ_SSL_CERTIFICATE) { - - Object cert = httpReq.getHttpChannel().getNet().getAttribute(SslProvider.ATT_SSL_CERT); - req.setAttribute("javax.servlet.request.X509Certificate", cert); - - } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) { - ByteChunk body = (ByteChunk) param; - httpReq.getBody().clear(); - try { - httpReq.getBody().append(body.getBuffer(), body.getStart(), body.getLength()); - } catch (IOException e) { - e.printStackTrace(); - } - - } else if (actionCode == ActionCode.ACTION_AVAILABLE) { - req.setAvailable(httpReq.getBody().available()); - } else if (actionCode == ActionCode.ACTION_COMET_BEGIN) { -// comet = true; - } else if (actionCode == ActionCode.ACTION_COMET_END) { -// comet = false; - } else if (actionCode == ActionCode.ACTION_COMET_CLOSE) { - //no op - } else if (actionCode == ActionCode.ACTION_COMET_SETTIMEOUT) { - //no op -// } else if (actionCode == ActionCode.ACTION_ASYNC_START) { -// //TODO SERVLET3 - async -// } else if (actionCode == ActionCode.ACTION_ASYNC_COMPLETE) { -// //TODO SERVLET3 - async -// } else if (actionCode == ActionCode.ACTION_ASYNC_SETTIMEOUT) { -// //TODO SERVLET3 - async - } - - - } - - private void commit() { - if (res.isCommitted()) - return; - - // TODO: copy headers, fields - httpRes.setStatus(res.getStatus()); - httpRes.setMessage(res.getMessage()); - MultiMap mimeHeaders = httpRes.getMimeHeaders(); - MimeHeaders coyoteHeaders = res.getMimeHeaders(); - for (int i = 0; i < coyoteHeaders.size(); i++ ) { - MessageBytes name = coyoteHeaders.getName(i); - MessageBytes val = coyoteHeaders.getValue(i); - Entry entry = mimeHeaders.addEntry(name.toString()); - entry.getValue().set(val.toString()); - } - String contentType = res.getContentType(); - if (contentType != null) { - mimeHeaders.addEntry("Content-Type").getValue().set(contentType); - } - String contentLang = res.getContentType(); - if (contentLang != null) { - mimeHeaders.addEntry("Content-Language").getValue().set(contentLang); - } - long contentLength = res.getContentLengthLong(); - if (contentLength != -1) { - httpRes.setContentLength(contentLength); - } - String lang = res.getContentLanguage(); - if (lang != null) { - httpRes.setHeader("Content-Language", lang); - } - - try { - httpReq.send(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - } -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/BaseMapper.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/BaseMapper.java deleted file mode 100644 index 129b4dceb85e..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/BaseMapper.java +++ /dev/null @@ -1,1112 +0,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.lite.http; - - -import java.io.IOException; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.http.HttpChannel.HttpService; -import org.apache.tomcat.lite.io.CBuffer; -import org.apache.tomcat.lite.io.FileConnector; -import org.apache.tomcat.lite.io.BBucket; - -/** - * Mapper, which implements the servlet API mapping rules (which are derived - * from the HTTP rules). - * - * This class doesn't use JNDI. - */ -public class BaseMapper { - - private static Logger logger = - Logger.getLogger(BaseMapper.class.getName()); - - // TODO: - /** - * Mapping should be done on bytes - as received from net, before - * translation to chars. This would allow setting the default charset - * for the context - or even executing the servlet and letting it specify - * the charset to use for further decoding. - * - */ - public static interface Mapper { - public void map(BBucket host, BBucket url, MappingData md); - } - - - /** - * Like BaseMapper, for a Context. - */ - public static class ServiceMapper extends BaseMapper { - /** - * Context associated with this wrapper, used for wrapper mapping. - */ - public BaseMapper.Context contextMapElement = new BaseMapper.Context(this); - - /** - * Set context, used for wrapper mapping (request dispatcher). - * - * @param welcomeResources Welcome files defined for this context - */ - public void setContext(String path, String[] welcomeResources) { - contextMapElement.name = path; - contextMapElement.welcomeResources = welcomeResources; - } - - - /** - * Add a wrapper to the context associated with this wrapper. - * - * @param path Wrapper mapping - * @param wrapper The Wrapper object - */ - public void addWrapper(String path, Object wrapper) { - addWrapper(contextMapElement, path, wrapper); - } - - - public void addWrapper(String path, Object wrapper, boolean jspWildCard) { - addWrapper(contextMapElement, path, wrapper, jspWildCard); - } - - - /** - * Remove a wrapper from the context associated with this wrapper. - * - * @param path Wrapper mapping - */ - public void removeWrapper(String path) { - removeWrapper(contextMapElement, path); - } - - -// /** -// * Map the specified URI relative to the context, -// * mutating the given mapping data. -// * -// * @param uri URI -// * @param mappingData This structure will contain the result of the mapping -// * operation -// */ -// public void map(CBuffer uri, MappingData mappingData) -// throws Exception { -// -// CBuffer uricc = uri.getCharBuffer(); -// internalMapWrapper(contextMapElement, uricc, mappingData); -// -// } - } - - /** - * Array containing the virtual hosts definitions. - */ - Host[] hosts = new Host[0]; - - /** - * If no other host is found. - * For single-host servers ( most common ) this is the only one - * used. - */ - Host defaultHost = new Host(); - - public BaseMapper() { - defaultHost.contextList = new ContextList(); - } - - // --------------------------------------------------------- Public Methods - - public synchronized Host addHost(String name) { - if (name == null) { - name = "localhost"; - } - Host[] newHosts = new Host[hosts.length + 1]; - Host newHost = new Host(); - newHost.name = name; - newHost.contextList = new ContextList(); - - if (insertMap(hosts, newHosts, newHost)) { - hosts = newHosts; - } - return newHost; - } - - - /** - * Remove a host from the mapper. - * - * @param name Virtual host name - */ - public synchronized void removeHost(String name) { - // Find and remove the old host - int pos = find(hosts, name); - if (pos < 0) { - return; - } - Object host = hosts[pos].object; - Host[] newHosts = new Host[hosts.length - 1]; - if (removeMap(hosts, newHosts, name)) { - hosts = newHosts; - } - // Remove all aliases (they will map to the same host object) - for (int i = 0; i < newHosts.length; i++) { - if (newHosts[i].object == host) { - Host[] newHosts2 = new Host[hosts.length - 1]; - if (removeMap(hosts, newHosts2, newHosts[i].name)) { - hosts = newHosts2; - } - } - } - } - - /** - * Add an alias to an existing host. - * @param name The name of the host - * @param alias The alias to add - */ - public synchronized void addHostAlias(String name, String alias) { - int pos = find(hosts, name); - if (pos < 0) { - // Should not be adding an alias for a host that doesn't exist but - // just in case... - return; - } - Host realHost = hosts[pos]; - - Host[] newHosts = new Host[hosts.length + 1]; - Host newHost = new Host(); - newHost.name = alias; - newHost.contextList = realHost.contextList; - newHost.object = realHost; - if (insertMap(hosts, newHosts, newHost)) { - hosts = newHosts; - } - } - - private Host getHost(String host) { - return getHost(CBuffer.newInstance().append(host)); - } - - private Host getHost(CBuffer host) { - if (hosts == null || hosts.length <= 1 || host == null - || host.length() == 0 || host.equals("")) { - return defaultHost; - } else { - Host[] hosts = this.hosts; - // TODO: if hosts.length == 1 or defaultHost ? - int pos = findIgnoreCase(hosts, host); - if ((pos != -1) && (host.equalsIgnoreCase(hosts[pos].name))) { - return hosts[pos]; - } else { - return defaultHost; - } - } - } - - private Host getOrCreateHost(String hostName) { - Host host = getHost(CBuffer.newInstance().append(hostName)); - if (host == null) { - host = addHost(hostName); - } - return host; - } - - // Contexts - - /** - * Add a new Context to an existing Host. - * - * @param hostName Virtual host name this context belongs to - * @param path Context path - * @param context Context object - * @param welcomeResources Welcome files defined for this context - * @param resources Static resources of the context - * @param ctxService - */ - public BaseMapper.Context addContext(String hostName, String path, Object context, - String[] welcomeResources, FileConnector resources, - HttpChannel.HttpService ctxService) { - - if (path == null) { - path = "/"; - } - - Host host = getOrCreateHost(hostName); - - int slashCount = slashCount(path); - synchronized (host) { - BaseMapper.Context[] contexts = host.contextList.contexts; - // Update nesting - if (slashCount > host.contextList.nesting) { - host.contextList.nesting = slashCount; - } - for (int i = 0; i < contexts.length; i++) { - if (path.equals(contexts[i].name)) { - return contexts[i]; - } - } - BaseMapper.Context[] newContexts = new BaseMapper.Context[contexts.length + 1]; - BaseMapper.Context newContext = new BaseMapper.Context(this); - newContext.name = path; - newContext.object = context; - if (welcomeResources != null) { - newContext.welcomeResources = welcomeResources; - } - newContext.resources = resources; - if (ctxService != null) { - newContext.defaultWrapper = new BaseMapper.ServiceMapping(); - newContext.defaultWrapper.object = ctxService; - } - - if (insertMap(contexts, newContexts, newContext)) { - host.contextList.contexts = newContexts; - } - return newContext; - } - - } - - - /** - * Remove a context from an existing host. - * - * @param hostName Virtual host name this context belongs to - * @param path Context path - */ - public void removeContext(String hostName, String path) { - Host host = getHost(hostName); - synchronized (host) { - BaseMapper.Context[] contexts = host.contextList.contexts; - if( contexts.length == 0 ){ - return; - } - BaseMapper.Context[] newContexts = new BaseMapper.Context[contexts.length - 1]; - if (removeMap(contexts, newContexts, path)) { - host.contextList.contexts = newContexts; - // Recalculate nesting - host.contextList.nesting = 0; - for (int i = 0; i < newContexts.length; i++) { - int slashCount = slashCount(newContexts[i].name); - if (slashCount > host.contextList.nesting) { - host.contextList.nesting = slashCount; - } - } - } - } - } - - - /** - * Add a new Wrapper to an existing Context. - * - * @param hostName Virtual host name this wrapper belongs to - * @param contextPath Context path this wrapper belongs to - * @param path Wrapper mapping - * @param wrapper Wrapper object - */ - public void addWrapper(String hostName, String contextPath, String path, - Object wrapper) { - addWrapper(hostName, contextPath, path, wrapper, false); - } - - - public void addWrapper(String hostName, String contextPath, String path, - Object wrapper, boolean jspWildCard) { - Host host = getHost(hostName); - BaseMapper.Context[] contexts = host.contextList.contexts; - int pos2 = find(contexts, contextPath); - if( pos2<0 ) { - logger.severe("No context found: " + contextPath ); - return; - } - BaseMapper.Context context = contexts[pos2]; - if (context.name.equals(contextPath)) { - addWrapper(context, path, wrapper, jspWildCard); - } - } - - - public void addWrapper(BaseMapper.Context context, String path, Object wrapper) { - addWrapper(context, path, wrapper, false); - } - - - /** - * Adds a wrapper to the given context. - * - * @param context The context to which to add the wrapper - * @param path Wrapper mapping - * @param wrapper The Wrapper object - * @param jspWildCard true if the wrapper corresponds to the JspServlet - * and the mapping path contains a wildcard; false otherwise - */ - protected void addWrapper(BaseMapper.Context context, String path, Object wrapper, - boolean jspWildCard) { - - synchronized (context) { - BaseMapper.ServiceMapping newWrapper = new BaseMapper.ServiceMapping(); - newWrapper.object = wrapper; - newWrapper.jspWildCard = jspWildCard; - if (path.endsWith("/*")) { - // Wildcard wrapper - newWrapper.name = path.substring(0, path.length() - 2); - BaseMapper.ServiceMapping[] oldWrappers = context.wildcardWrappers; - BaseMapper.ServiceMapping[] newWrappers = - new BaseMapper.ServiceMapping[oldWrappers.length + 1]; - if (insertMap(oldWrappers, newWrappers, newWrapper)) { - context.wildcardWrappers = newWrappers; - int slashCount = slashCount(newWrapper.name); - if (slashCount > context.nesting) { - context.nesting = slashCount; - } - } - } else if (path.startsWith("*.")) { - // Extension wrapper - newWrapper.name = path.substring(2); - BaseMapper.ServiceMapping[] oldWrappers = context.extensionWrappers; - BaseMapper.ServiceMapping[] newWrappers = - new BaseMapper.ServiceMapping[oldWrappers.length + 1]; - if (insertMap(oldWrappers, newWrappers, newWrapper)) { - context.extensionWrappers = newWrappers; - } - } else if (path.equals("/")) { - // Default wrapper - newWrapper.name = ""; - context.defaultWrapper = newWrapper; - } else { - // Exact wrapper - newWrapper.name = path; - BaseMapper.ServiceMapping[] oldWrappers = context.exactWrappers; - BaseMapper.ServiceMapping[] newWrappers = - new BaseMapper.ServiceMapping[oldWrappers.length + 1]; - if (insertMap(oldWrappers, newWrappers, newWrapper)) { - context.exactWrappers = newWrappers; - } - } - } - } - - /** - * Remove a wrapper from an existing context. - * - * @param hostName Virtual host name this wrapper belongs to - * @param contextPath Context path this wrapper belongs to - * @param path Wrapper mapping - */ - public void removeWrapper(String hostName, String contextPath, - String path) { - Host host = getHost(hostName); - BaseMapper.Context[] contexts = host.contextList.contexts; - int pos2 = find(contexts, contextPath); - if (pos2 < 0) { - return; - } - BaseMapper.Context context = contexts[pos2]; - if (context.name.equals(contextPath)) { - removeWrapper(context, path); - } - } - - protected void removeWrapper(BaseMapper.Context context, String path) { - synchronized (context) { - if (path.endsWith("/*")) { - // Wildcard wrapper - String name = path.substring(0, path.length() - 2); - BaseMapper.ServiceMapping[] oldWrappers = context.wildcardWrappers; - BaseMapper.ServiceMapping[] newWrappers = - new BaseMapper.ServiceMapping[oldWrappers.length - 1]; - if (removeMap(oldWrappers, newWrappers, name)) { - // Recalculate nesting - context.nesting = 0; - for (int i = 0; i < newWrappers.length; i++) { - int slashCount = slashCount(newWrappers[i].name); - if (slashCount > context.nesting) { - context.nesting = slashCount; - } - } - context.wildcardWrappers = newWrappers; - } - } else if (path.startsWith("*.")) { - // Extension wrapper - String name = path.substring(2); - BaseMapper.ServiceMapping[] oldWrappers = context.extensionWrappers; - BaseMapper.ServiceMapping[] newWrappers = - new BaseMapper.ServiceMapping[oldWrappers.length - 1]; - if (removeMap(oldWrappers, newWrappers, name)) { - context.extensionWrappers = newWrappers; - } - } else if (path.equals("/")) { - // Default wrapper - context.defaultWrapper = null; - } else { - // Exact wrapper - String name = path; - BaseMapper.ServiceMapping[] oldWrappers = context.exactWrappers; - BaseMapper.ServiceMapping[] newWrappers = - new BaseMapper.ServiceMapping[oldWrappers.length - 1]; - if (removeMap(oldWrappers, newWrappers, name)) { - context.exactWrappers = newWrappers; - } - } - } - } - - /** - * Map the specified host name and URI, mutating the given mapping data. - * - * @param host Virtual host name - * @param uri URI - * @param mappingData This structure will contain the result of the mapping - * operation - */ - public void map(CBuffer host, CBuffer uri, - MappingData mappingData) - throws Exception { - - internalMap(host.length() == 0 ? null : - host, uri, mappingData); - } - - - // -------------------------------------------------------- Private Methods - - // public Context mapContext(CBuffer host, CBuffer url); - - /** - * Map the specified URI. - */ - private final void internalMap(CBuffer host, CBuffer uri, - MappingData mappingData) - throws Exception { - BaseMapper.Context[] contexts = null; - BaseMapper.Context context = null; - int nesting = 0; - - // Virtual host mapping - Host mappedHost = getHost(host); - contexts = mappedHost.contextList.contexts; - nesting = mappedHost.contextList.nesting; - - // Context mapping - if (contexts.length == 0) { - return; - } - - if (mappingData.context == null) { - if (nesting < 1 || contexts.length == 1 && "".equals(contexts[0].name)) { - // if 1 context (default) -> fast return - context = contexts[0]; - } else if (nesting == 1) { - // if all contexts are 1-component-only - int nextSlash = uri.indexOf('/', 1); - if (nextSlash == -1) { - nextSlash = uri.length(); - } - mappingData.contextPath.set(uri, 0, nextSlash); - int pos = find(contexts, uri); - if (pos == -1) { - pos = find(contexts, "/"); - } - if (pos >= 0) { - context = contexts[pos]; - } - } else { - int pos = find(contexts, uri); - if (pos >= 0) { - int lastSlash = -1; - int length = -1; - boolean found = false; - CBuffer tmp = mappingData.tmpPrefix; - tmp.wrap(uri, 0, uri.length()); - - while (pos >= 0) { - if (tmp.startsWith(contexts[pos].name)) { - length = contexts[pos].name.length(); - if (tmp.length() == length) { - found = true; - break; - } else if (tmp.startsWithIgnoreCase("/", length)) { - found = true; - break; - } - } - if (lastSlash == -1) { - lastSlash = tmp.nthSlash(nesting + 1); - } else { - lastSlash = tmp.lastIndexOf('/'); - } - tmp.delete(lastSlash); - pos = find(contexts, tmp); - } - - if (!found) { - if (contexts[0].name.equals("")) { - context = contexts[0]; - } - } else { - context = contexts[pos]; - } - } - } - - if (context != null) { - mappingData.context = context.object; - mappingData.contextPath.set(context.name); - } - } - - // Wrapper mapping - if ((context != null) && (mappingData.getServiceObject() == null)) { - internalMapWrapper(context, uri, mappingData); - } - - } - - - /** - * Wrapper mapping, using servlet rules. - */ - protected final void internalMapWrapper( - BaseMapper.Context context, - CBuffer url, - MappingData mappingData) - throws Exception { - - boolean noServletPath = false; - if (url.length() < context.name.length()) { - throw new IOException("Invalid mapping " + context.name + " " + - url); - } - - try { - // Set the servlet path. - mappingData.tmpServletPath.set(url, - context.name.length(), - url.length() - context.name.length()); - - if (mappingData.tmpServletPath.length() == 0) { - mappingData.tmpServletPath.append('/'); - // This is just the context /example or / - if (!context.name.equals("/")) { - noServletPath = true; - } - } - - mapAfterContext(context, url, mappingData.tmpServletPath, mappingData, - noServletPath); - } catch (ArrayIndexOutOfBoundsException ex) { - System.err.println(1); - } - } - - void mapAfterContext(BaseMapper.Context context, - CBuffer url, CBuffer urlNoContext, - MappingData mappingData, boolean noServletPath) - throws Exception { - - - // Rule 1 -- Exact Match - BaseMapper.ServiceMapping[] exactWrappers = context.exactWrappers; - internalMapExactWrapper(exactWrappers, urlNoContext, mappingData); - - // Rule 2 -- Prefix Match - boolean checkJspWelcomeFiles = false; - BaseMapper.ServiceMapping[] wildcardWrappers = context.wildcardWrappers; - if (mappingData.getServiceObject() == null) { - - internalMapWildcardWrapper(wildcardWrappers, context.nesting, - urlNoContext, mappingData); - - if (mappingData.getServiceObject() != null - && mappingData.service.jspWildCard) { - if (urlNoContext.lastChar() == '/') { - /* - * Path ending in '/' was mapped to JSP servlet based on - * wildcard match (e.g., as specified in url-pattern of a - * jsp-property-group. - * Force the context's welcome files, which are interpreted - * as JSP files (since they match the url-pattern), to be - * considered. See Bugzilla 27664. - */ - mappingData.service = null; - checkJspWelcomeFiles = true; - } else { - // See Bugzilla 27704 - mappingData.wrapperPath.set(urlNoContext); - mappingData.pathInfo.recycle(); - } - } - } - - if(mappingData.getServiceObject() == null && noServletPath) { - // The path is empty, redirect to "/" - mappingData.redirectPath.set(context.name); - mappingData.redirectPath.append("/"); - return; - } - - // Rule 3 -- Extension Match - BaseMapper.ServiceMapping[] extensionWrappers = context.extensionWrappers; - if (mappingData.getServiceObject() == null && !checkJspWelcomeFiles) { - internalMapExtensionWrapper(extensionWrappers, urlNoContext, mappingData); - } - - // Rule 4 -- Welcome resources processing for servlets - if (mappingData.getServiceObject() == null) { - boolean checkWelcomeFiles = checkJspWelcomeFiles; - if (!checkWelcomeFiles) { - checkWelcomeFiles = (urlNoContext.lastChar() == '/'); - } - if (checkWelcomeFiles) { - for (int i = 0; (i < context.welcomeResources.length) - && (mappingData.getServiceObject() == null); i++) { - - CBuffer wpath = mappingData.tmpWelcome; - wpath.set(urlNoContext); - wpath.append(context.welcomeResources[i]); - - // Rule 4a -- Welcome resources processing for exact macth - internalMapExactWrapper(exactWrappers, urlNoContext, mappingData); - - // Rule 4b -- Welcome resources processing for prefix match - if (mappingData.getServiceObject() == null) { - internalMapWildcardWrapper - (wildcardWrappers, context.nesting, - urlNoContext, mappingData); - } - - // Rule 4c -- Welcome resources processing - // for physical folder - if (mappingData.getServiceObject() == null - && context.resources != null) { - String pathStr = urlNoContext.toString(); - - mapWelcomResource(context, urlNoContext, mappingData, - extensionWrappers, pathStr); - - } - } - } - - } - - - // Rule 7 -- Default servlet - if (mappingData.getServiceObject() == null && !checkJspWelcomeFiles) { - if (context.defaultWrapper != null) { - mappingData.service = context.defaultWrapper; - mappingData.requestPath.set(urlNoContext); - mappingData.wrapperPath.set(urlNoContext); - } - // Redirection to a folder - if (context.resources != null && urlNoContext.lastChar() != '/') { - String pathStr = urlNoContext.toString(); - mapDefaultServlet(context, urlNoContext, mappingData, - url, - pathStr); - } - } - } - - /** - * Filesystem-dependent method: - * if pathStr corresponds to a directory, we'll need to redirect with / - * at end. - */ - protected void mapDefaultServlet(BaseMapper.Context context, - CBuffer path, - MappingData mappingData, - CBuffer url, - String pathStr) throws IOException { - - if (context.resources != null - && context.resources.isDirectory(pathStr)) { - mappingData.redirectPath.set(url); - mappingData.redirectPath.append("/"); - } else { - mappingData.requestPath.set(pathStr); - mappingData.wrapperPath.set(pathStr); - } - } - - - /** - * Filesystem dependent method: - * check if a resource exists in filesystem. - */ - protected void mapWelcomResource(BaseMapper.Context context, CBuffer path, - MappingData mappingData, - BaseMapper.ServiceMapping[] extensionWrappers, String pathStr) { - - if (context.resources != null && - context.resources.isFile(pathStr)) { - internalMapExtensionWrapper(extensionWrappers, - path, mappingData); - if (mappingData.getServiceObject() == null - && context.defaultWrapper != null) { - mappingData.service = context.defaultWrapper; - mappingData.requestPath.set(path); - mappingData.wrapperPath.set(path); - mappingData.requestPath.set(pathStr); - mappingData.wrapperPath.set(pathStr); - } - } - } - - /** - * Exact mapping. - */ - private final void internalMapExactWrapper - (BaseMapper.ServiceMapping[] wrappers, CBuffer path, MappingData mappingData) { - int pos = find(wrappers, path); - if ((pos != -1) && (path.equals(wrappers[pos].name))) { - mappingData.requestPath.set(wrappers[pos].name); - mappingData.wrapperPath.set(wrappers[pos].name); - mappingData.service = wrappers[pos]; - } - } - - - /** - * Prefix mapping. ( /foo/* ) - */ - private final void internalMapWildcardWrapper - (BaseMapper.ServiceMapping[] wrappers, int nesting, CBuffer path, - MappingData mappingData) { - - int lastSlash = -1; - int length = -1; - - CBuffer tmp = mappingData.tmpPrefix; - tmp.wrap(path, 0, path.length()); - - int pos = find(wrappers, tmp); - if (pos != -1) { - boolean found = false; - while (pos >= 0) { - if (tmp.startsWith(wrappers[pos].name)) { - length = wrappers[pos].name.length(); - if (tmp.length() == length) { - found = true; - break; - } else if (tmp.startsWithIgnoreCase("/", length)) { - found = true; - break; - } - } - if (lastSlash == -1) { - lastSlash = tmp.nthSlash(nesting + 1); - } else { - lastSlash = tmp.lastIndexOf('/'); - } - tmp.delete(lastSlash); - pos = find(wrappers, tmp); - } - if (found) { - mappingData.wrapperPath.set(wrappers[pos].name); - - if (path.length() > length) { - mappingData.pathInfo.set - (path, length, path.length() - length); - } - mappingData.requestPath.set(path); - - mappingData.service = wrappers[pos]; - } - } - } - - - /** - * Extension mappings. - */ - protected final void internalMapExtensionWrapper - (BaseMapper.ServiceMapping[] wrappers, CBuffer path, MappingData mappingData) { - - int dot = path.getExtension(mappingData.ext, '/', '.'); - if (dot >= 0) { - int pos = find(wrappers, mappingData.ext); - - if ((pos != -1) - && (mappingData.ext.equals(wrappers[pos].name))) { - - mappingData.wrapperPath.set(path); - mappingData.requestPath.set(path); - - mappingData.service = wrappers[pos]; - } - } - } - - - /** - * Find a map elemnt given its name in a sorted array of map elements. - * This will return the index for the closest inferior or equal item in the - * given array. - */ - private static final int find(BaseMapper.Mapping[] map, CBuffer name) { - - int a = 0; - int b = map.length - 1; - - // Special cases: -1 and 0 - if (b == -1) { - return -1; - } - - if (name.compare(map[0].name) < 0 ) { - return -1; - } - if (b == 0) { - return 0; - } - - int i = 0; - while (true) { - i = (b + a) / 2; - int result = name.compare(map[i].name); - if (result == 1) { - a = i; - } else if (result == 0) { - return i; - } else { - b = i; - } - if ((b - a) == 1) { - int result2 = name.compare(map[b].name); - if (result2 < 0) { - return a; - } else { - return b; - } - } - } - - } - - /** - * Find a map elemnt given its name in a sorted array of map elements. - * This will return the index for the closest inferior or equal item in the - * given array. - */ - private static final int findIgnoreCase(BaseMapper.Mapping[] map, - CBuffer name) { - int a = 0; - int b = map.length - 1; - - // Special cases: -1 and 0 - if (b == -1) { - return -1; - } - if (name.compareIgnoreCase(map[0].name) < 0 ) { - return -1; - } - if (b == 0) { - return 0; - } - - int i = 0; - while (true) { - i = (b + a) / 2; - int result = name.compareIgnoreCase(map[i].name); - if (result == 1) { - a = i; - } else if (result == 0) { - return i; - } else { - b = i; - } - if ((b - a) == 1) { - int result2 = name.compareIgnoreCase(map[b].name); - if (result2 < 0) { - return a; - } else { - return b; - } - } - } - - } - - - /** - * Find a map element given its name in a sorted array of map elements. - * This will return the index for the closest inferior or equal item in the - * given array. - */ - private static final int find(BaseMapper.Mapping[] map, String name) { - - int a = 0; - int b = map.length - 1; - - // Special cases: -1 and 0 - if (b == -1) { - return -1; - } - - if (name.compareTo(map[0].name) < 0) { - return -1; - } - if (b == 0) { - return 0; - } - - int i = 0; - while (true) { - i = (b + a) / 2; - int result = name.compareTo(map[i].name); - if (result > 0) { - a = i; - } else if (result == 0) { - return i; - } else { - b = i; - } - if ((b - a) == 1) { - int result2 = name.compareTo(map[b].name); - if (result2 < 0) { - return a; - } else { - return b; - } - } - } - - } - - - /** - * Return the slash count in a given string. - */ - private static final int slashCount(String name) { - int pos = -1; - int count = 0; - while ((pos = name.indexOf('/', pos + 1)) != -1) { - count++; - } - return count; - } - - - /** - * Insert into the right place in a sorted MapElement array, and prevent - * duplicates. - */ - private static final boolean insertMap - (BaseMapper.Mapping[] oldMap, BaseMapper.Mapping[] newMap, BaseMapper.Mapping newElement) { - int pos = find(oldMap, newElement.name); - if ((pos != -1) && (newElement.name.equals(oldMap[pos].name))) { - return false; - } - System.arraycopy(oldMap, 0, newMap, 0, pos + 1); - newMap[pos + 1] = newElement; - System.arraycopy - (oldMap, pos + 1, newMap, pos + 2, oldMap.length - pos - 1); - return true; - } - - - /** - * Insert into the right place in a sorted MapElement array. - */ - private static final boolean removeMap - (BaseMapper.Mapping[] oldMap, BaseMapper.Mapping[] newMap, String name) { - int pos = find(oldMap, name); - if ((pos != -1) && (name.equals(oldMap[pos].name))) { - System.arraycopy(oldMap, 0, newMap, 0, pos); - System.arraycopy(oldMap, pos + 1, newMap, pos, - oldMap.length - pos - 1); - return true; - } - return false; - } - - - // ------------------------------------------------- MapElement Inner Class - - - protected static final class Host - extends BaseMapper.Mapping { - //Map contexts = new HashMap(); - //Context rootContext; - - public ContextList contextList = null; - - } - - - // ------------------------------------------------ ContextList Inner Class - - // Shared among host aliases. - protected static final class ContextList { - - public BaseMapper.Context[] contexts = new BaseMapper.Context[0]; - public int nesting = 0; - - } - - - public static final class Context extends BaseMapper.Mapping { - - Context(BaseMapper mapper) { - this.mapper = mapper; - } - public BaseMapper mapper; - public String[] welcomeResources = new String[0]; - public FileConnector resources = null; - - public BaseMapper.ServiceMapping defaultWrapper = null; - - public BaseMapper.ServiceMapping[] exactWrappers = new BaseMapper.ServiceMapping[0]; - public BaseMapper.ServiceMapping[] wildcardWrappers = new BaseMapper.ServiceMapping[0]; - public BaseMapper.ServiceMapping[] extensionWrappers = new BaseMapper.ServiceMapping[0]; - public int nesting = 0; - - public void addWrapper(String path, HttpService service) { - mapper.addWrapper(this, path, service); - } - - } - - - public static class ServiceMapping extends BaseMapper.Mapping { - public boolean jspWildCard = false; - // If set, the service will run in the selector thread ( should - // be non-blocking ) - public boolean selectorThread = false; - - } - - - protected static abstract class Mapping { - public String name = null; - public Object object = null; - - public String toString() { - if (name == null || "".equals(name)) { - return "DEFAULT"; - } - return name; - } - } - - - // ---------------------------------------------------- Context Inner Class - - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/CompressFilter.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/CompressFilter.java deleted file mode 100644 index d78c55e59f62..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/CompressFilter.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.io.IOException; -import java.nio.ByteBuffer; - -import org.apache.tomcat.lite.io.BBucket; -import org.apache.tomcat.lite.io.IOBuffer; - -import com.jcraft.jzlib.JZlib; -import com.jcraft.jzlib.ZStream; - -public class CompressFilter { - - // Stream format: RFC1950 - // 1CMF 1FLG [4DICTID] DATA 4ADLER - // CMF: CINFO + CM (compression method). == x8 - // 78 == deflate with 32k window, i.e. max window - - // FLG: 2bit level, 1 bit FDICT, 5 bit FCHECK - // Cx, Dx - no dict; Fx, Ex - dict ( for BEST_COMPRESSION ) - - // Overhead: 6 bytes without dict, 10 with dict - // data is encoded in blocks - there is a 'block end' marker and - // 'last block'. - - // Flush: http://www.bolet.org/~pornin/deflate-flush.html - // inflater needs about 9 bits - // Z_SYNC_FLUSH: send empty block, 00 00 FF FF - seems recomended - // PPP can skip this - there is a record format on top - // Z_PARTIAL_FLUSH: standard for SSH - - ZStream cStream; - ZStream dStream; - - byte[] dict; - long dictId; - - public CompressFilter() { - } - - public void recycle() { - if (cStream == null) { - return; - } - cStream.free(); - cStream = null; - dStream.free(); - dStream = null; - } - - public void init() { - if (cStream != null) { - return; - } - // can't call: cStream.free(); - will kill the adler, NPE - cStream = new ZStream(); - // BEST_COMRESSION results in 256Kb per Deflate - // 15 == default = 32k window - cStream.deflateInit(JZlib.Z_BEST_SPEED, 10); - - dStream = new ZStream(); - dStream.inflateInit(); - - } - - CompressFilter setDictionary(byte[] dict, long id) { - init(); - this.dict = dict; - this.dictId = id; - cStream.deflateSetDictionary(dict, dict.length); - return this; - } - - void compress(IOBuffer in, IOBuffer out) throws IOException { - init(); - BBucket bb = in.popFirst(); - - while (bb != null) { - // TODO: only the last one needs flush - - // TODO: size missmatches ? - compress(bb, out, false); - bb = in.popFirst(); - } - - if (in.isClosedAndEmpty()) { - compressEnd(out); - } - } - - void compress(BBucket bb, IOBuffer out, boolean last) throws IOException { - // TODO: only the last one needs flush - - // TODO: size missmatches ? - init(); - int flush = JZlib.Z_PARTIAL_FLUSH; - - cStream.next_in = bb.array(); - cStream.next_in_index = bb.position(); - cStream.avail_in = bb.remaining(); - - while (true) { - ByteBuffer outB = out.getWriteBuffer(); - cStream.next_out = outB.array(); - cStream.next_out_index = outB.position(); - cStream.avail_out = outB.remaining(); - - int err = cStream.deflate(flush); - check(err, cStream); - outB.position(cStream.next_out_index); - out.releaseWriteBuffer(1); - if (cStream.avail_out > 0 || cStream.avail_in == 0) { - break; - } - } - - if (last) { - compressEnd(out); - } - } - - private void compressEnd(IOBuffer out) throws IOException { - while (true) { - ByteBuffer outB = out.getWriteBuffer(); - cStream.next_out = outB.array(); - - cStream.next_out_index = outB.position(); - cStream.avail_out = outB.remaining(); - cStream.deflate(JZlib.Z_FINISH); - cStream.deflateEnd(); - - outB.position(cStream.next_out_index); - out.releaseWriteBuffer(1); - if (cStream.avail_out > 0) { - break; - } - } - } - - void decompress(IOBuffer in, IOBuffer out) throws IOException { - decompress(in, out, in.available()); - } - - void decompress(IOBuffer in, IOBuffer out, int len) throws IOException { - init(); - BBucket bb = in.peekFirst(); - - while (bb != null && len > 0) { - dStream.next_in = bb.array(); - dStream.next_in_index = bb.position(); - int rd = Math.min(bb.remaining(), len); - dStream.avail_in = rd; - - while (true) { - ByteBuffer outB = out.getWriteBuffer(); - - dStream.next_out = outB.array(); - dStream.next_out_index = outB.position(); - dStream.avail_out = outB.remaining(); - - int err = dStream.inflate(JZlib.Z_SYNC_FLUSH); - if (err == JZlib.Z_NEED_DICT && dict != null) { - // dStream.adler has the dict id - not sure how to check - if (dictId != 0 && dStream.adler != dictId) { - throw new IOException("Invalid dictionary"); - } - if (dictId == 0) { - // initDict should pass a real dict id. - System.err.println("Missing dict ID: " + dStream.adler); - } - dStream.inflateSetDictionary(dict, dict.length); - err = dStream.inflate(JZlib.Z_SYNC_FLUSH); - } - outB.position(dStream.next_out_index); - out.releaseWriteBuffer(1); - - if (err == JZlib.Z_STREAM_END) { - err = dStream.inflateEnd(); - out.close(); - check(err, dStream); - // move in back, not consummed - bb.position(dStream.next_in_index); - return; - } - check(err, dStream); - - if (dStream.avail_out > 0 || dStream.avail_in == 0) { - break; - } - } - - in.advance(rd); // consummed - len -= rd; - bb = in.peekFirst(); - } - - if (in.isClosedAndEmpty()) { - // Shouldn't happen - input was not properly closed.. - // This should throw an exception, inflateEnd will check the CRC - int err = dStream.inflateEnd(); - out.close(); - check(err, dStream); - out.close(); - } - } - - private void check(int err, ZStream stream) throws IOException { - if (err != JZlib.Z_OK) { - throw new IOException(err + " " + stream.msg); - } - } - - boolean isCompressed(HttpMessage http) { - return false; - } - - boolean needsCompression(HttpMessage in, HttpMessage out) { - return false; - } - - -} - diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/ContentType.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/ContentType.java deleted file mode 100644 index c98276cfa02d..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/ContentType.java +++ /dev/null @@ -1,96 +0,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.lite.http; - - -/** - * Usefull methods for Content-Type processing - * - * @author James Duncan Davidson [duncan@eng.sun.com] - * @author James Todd [gonzo@eng.sun.com] - * @author Jason Hunter [jch@eng.sun.com] - * @author Harish Prabandham - * @author costin@eng.sun.com - */ -public class ContentType { - - /** - * Parse the character encoding from the specified content type header. - * If the content type is null, or there is no explicit character encoding, - * null is returned. - * - * @param contentType a content type header - */ - public static String getCharsetFromContentType(String contentType) { - - if (contentType == null) - return (null); - int start = contentType.indexOf("charset="); - if (start < 0) - return (null); - String encoding = contentType.substring(start + 8); - int end = encoding.indexOf(';'); - if (end >= 0) - encoding = encoding.substring(0, end); - encoding = encoding.trim(); - if ((encoding.length() > 2) && (encoding.startsWith("\"")) - && (encoding.endsWith("\""))) - encoding = encoding.substring(1, encoding.length() - 1); - return (encoding.trim()); - - } - - - /** - * Returns true if the given content type contains a charset component, - * false otherwise. - * - * @param type Content type - * @return true if the given content type contains a charset component, - * false otherwise - */ - public static boolean hasCharset(String type) { - - boolean hasCharset = false; - - int len = type.length(); - int index = type.indexOf(';'); - while (index != -1) { - index++; - while (index < len && Character.isWhitespace(type.charAt(index))) { - index++; - } - if (index+8 < len - && type.charAt(index) == 'c' - && type.charAt(index+1) == 'h' - && type.charAt(index+2) == 'a' - && type.charAt(index+3) == 'r' - && type.charAt(index+4) == 's' - && type.charAt(index+5) == 'e' - && type.charAt(index+6) == 't' - && type.charAt(index+7) == '=') { - hasCharset = true; - break; - } - index = type.indexOf(';', index); - } - - return hasCharset; - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/DefaultHttpConnector.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/DefaultHttpConnector.java deleted file mode 100644 index d798d8b77364..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/DefaultHttpConnector.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import org.apache.tomcat.lite.io.SocketConnector; - -public class DefaultHttpConnector { - - public synchronized static HttpConnector getNew() { - return new HttpConnector(new SocketConnector()); - } - - public synchronized static HttpConnector get() { - if (DefaultHttpConnector.socketConnector == null) { - socketConnector = - new SocketConnector(); - } - return new HttpConnector(socketConnector); - } - - private static SocketConnector socketConnector; - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/Dispatcher.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/Dispatcher.java deleted file mode 100644 index e47f5df4acc6..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/Dispatcher.java +++ /dev/null @@ -1,199 +0,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.lite.http; - -import java.io.IOException; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.http.HttpChannel.HttpService; -import org.apache.tomcat.lite.http.HttpChannel.RequestCompleted; -import org.apache.tomcat.lite.io.CBuffer; -import org.apache.tomcat.lite.io.FileConnector; - -/** - * This class has several functions: - * - maps the request to another HttpService - * - decide if the request should be run in the selector thread - * or in a thread pool - * - finalizes the request ( close / flush ) - * - detects if the request is complete or set callbacks - * for receive/flush/done. - * - */ -public class Dispatcher implements HttpService { - - private BaseMapper mapper; - static boolean debug = false; - static Logger log = Logger.getLogger("Mapper"); - Executor tp = Executors.newCachedThreadPool(); - - public Dispatcher() { - init(); - } - - protected void init() { - mapper = new BaseMapper(); - } - - public void runService(HttpChannel ch) { - runService(ch, true); - } - - public void runService(HttpChannel ch, boolean recycle) { - MappingData mapRes = ch.getRequest().getMappingData(); - HttpService h = (HttpService) mapRes.getServiceObject(); - try { - h.service(ch.getRequest(), ch.getResponse()); - if (!ch.getRequest().isAsyncStarted()) { - ch.complete(); - if (recycle) { - ch.release(); // recycle objects. - } - } else { - // Nothing - complete must be called when done. - } - } catch (IOException e) { - e.printStackTrace(); - } catch( Throwable t ) { - t.printStackTrace(); - } - } - - @Override - public void service(HttpRequest httpReq, HttpResponse httpRes) throws IOException { - service(httpReq, httpRes, false, true); - } - - /** - * Process the request/response in the current thread, without - * release ( recycle ) at the end. - * - * For use by tests and/or in-memory running of servlets. - * - * If no connection is associated with the request - the - * output will remain in the out buffer. - */ - public void run(HttpRequest httpReq, HttpResponse httpRes) throws IOException { - service(httpReq, httpRes, true, false); - } - - - public void service(HttpRequest httpReq, HttpResponse httpRes, boolean noThread, boolean recycle) - throws IOException { - long t0 = System.currentTimeMillis(); - HttpChannel http = httpReq.getHttpChannel(); - - http.setCompletedCallback(doneCallback); - - try { - // compute decodedURI - not done by connector - MappingData mapRes = httpReq.getMappingData(); - mapRes.recycle(); - - mapper.map(httpReq.serverName(), - httpReq.decodedURI(), mapRes); - - HttpService h = (HttpService) mapRes.getServiceObject(); - - if (h != null) { - if (debug) { - log.info(">>>>>>>> START: " + http.getRequest().method() + " " + - http.getRequest().decodedURI() + " " + - h.getClass().getSimpleName()); - } - - if (mapRes.service.selectorThread || noThread) { - runService(http, recycle); - } else { - tp.execute(httpReq.getHttpChannel().dispatcherRunnable); - } - - } else { - httpRes.setStatus(404); - http.complete(); - } - - } catch (IOException ex) { - if ("Broken pipe".equals(ex.getMessage())) { - log.warning("Connection interrupted while writting"); - } - throw ex; - } catch( Throwable t ) { - t.printStackTrace(); - httpRes.setStatus(500); - http.abort(t); - } - } - - private RequestCompleted doneCallback = new RequestCompleted() { - @Override - public void handle(HttpChannel client, Object extraData) throws IOException { - if (debug) { - log.info("<<<<<<<< DONE: " + client.getRequest().method() + " " + - client.getRequest().decodedURI() + " " + - client.getResponse().getStatus() + " " - ); - } - } - }; - - public BaseMapper.Context addContext(String hostname, String ctxPath, - Object ctx, String[] welcomeResources, FileConnector resources, - HttpService ctxService) { - return mapper.addContext(hostname, ctxPath, ctx, welcomeResources, resources, - ctxService); - } - - public BaseMapper.Context addContext(String ctxPath) { - return mapper.addContext(null, ctxPath, null, null, null, - null); - } - - public void map(CBuffer hostMB, CBuffer urlMB, MappingData md) { - try { - mapper.map(hostMB, urlMB, md); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - public void map(BaseMapper.Context ctx, - CBuffer uri, MappingData md) { - try { - mapper.internalMapWrapper(ctx, uri, md); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - public void addWrapper(BaseMapper.Context ctx, String path, - HttpService service) { - mapper.addWrapper(ctx, path, service); - } - - - public void setDefaultService(HttpService service) { - BaseMapper.Context mCtx = - mapper.addContext(null, "/", null, null, null, null); - mapper.addWrapper(mCtx, "/", service); - } - - -} \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/Http11Connection.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/Http11Connection.java deleted file mode 100644 index 4b26ee9522e2..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/Http11Connection.java +++ /dev/null @@ -1,1459 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.http.HttpConnector.HttpConnection; -import org.apache.tomcat.lite.http.HttpMessage.HttpMessageBytes; -import org.apache.tomcat.lite.io.BBucket; -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.CBuffer; -import org.apache.tomcat.lite.io.DumpChannel; -import org.apache.tomcat.lite.io.FastHttpDateFormat; -import org.apache.tomcat.lite.io.Hex; -import org.apache.tomcat.lite.io.IOBuffer; -import org.apache.tomcat.lite.io.IOChannel; -import org.apache.tomcat.lite.io.IOConnector; - -public class Http11Connection extends HttpConnection - implements IOConnector.ConnectedCallback { - public static final String CHUNKED = "chunked"; - - public static final String CLOSE = "close"; - - public static final String KEEPALIVE_S = "keep-alive"; - - public static final String CONNECTION = "connection"; - - public static final String TRANSFERENCODING = "transfer-encoding"; - - - protected static Logger log = Logger.getLogger("Http11Connection"); - static final byte COLON = (byte) ':'; - - // super.net is the socket - - boolean debug; - BBuffer line = BBuffer.wrapper(); - boolean endSent = false; - - BodyState receiveBodyState = new BodyState(); - BodyState sendBodyState = new BodyState(); - - BBuffer headW = BBuffer.wrapper(); - - boolean headersReceived = false; - boolean bodyReceived = false; - - /** - * Close connection when done writting, no content-length/chunked, - * or no keep-alive ( http/1.0 ) or error. - * - * ServerMode: set if HTTP/0.9 &1.0 || !keep-alive - * ClientMode: not currently used - */ - boolean keepAlive = true; - - protected boolean http11 = true; - protected boolean http10 = false; - protected boolean http09 = false; - - HttpConnection switchedProtocol = null; - - private int requestCount = 0; - - // dataReceived and endSendReceive - private Object readLock = new Object(); - - public Http11Connection(HttpConnector httpConnector) { - this.httpConnector = httpConnector; - if (httpConnector != null) { - debug = httpConnector.debugHttp; - } - } - - public void beforeRequest() { - nextRequest(); - headRecvBuf.recycle(); - } - - public void nextRequest() { - endSent = false; - keepAlive = true; - receiveBodyState.recycle(); - sendBodyState.recycle(); - http11 = true; - http09 = false; - http10 = false; - headersReceived = false; - bodyReceived = false; - } - - public Http11Connection serverMode() { - serverMode = true; - return this; - } - - private boolean readHead() throws IOException { - while (true) { - int read; - if (requestCount == 0 && headRecvBuf.remaining() < 4) { - // requests have at least 4 bytes - detect protocol - read = net.getIn().read(headRecvBuf, 4); - if (read < 0) { - return closeInHead(); - } - if (read < 4) { - return false; // need more - } - // we have at least 4 bytes - if (headRecvBuf.get(0) == 0x80 && - headRecvBuf.get(1) == 0x01) { - // SPDY signature ( experimental ) - switchedProtocol = new SpdyConnection(httpConnector, - remoteHost); - if (serverMode) { - switchedProtocol.serverMode = true; - } - switchedProtocol.withExtraBuffer(headRecvBuf); - // Will also call handleReceived - switchedProtocol.setSink(net); - return false; - } - - } - - // we know we have one - read = net.getIn().readLine(headRecvBuf); - // Remove starting empty lines. - headRecvBuf.skipEmptyLines(); - - // Do we have another full line in the input ? - if (BBuffer.hasLFLF(headRecvBuf)) { - break; // done - } - if (read == 0) { // no more data - return false; - } - if (read < 0) { - return closeInHead(); - } - } - - - return true; - } - - private boolean closeInHead() throws IOException { - if (debug) { - trace("CLOSE while reading HEAD"); - } - // too early - we don't have the head - abort("Close in head"); - return false; - } - - // Unit tests use this to access the HttpChannel - protected HttpChannel checkHttpChannel() throws IOException { - if (switchedProtocol != null) { - return switchedProtocol.checkHttpChannel(); - } - if (activeHttp == null) { - if (serverMode) { - activeHttp = httpConnector.getServer(); - activeHttp.setConnection(this); - if (httpConnector.defaultService != null) { - activeHttp.setHttpService(httpConnector.defaultService); - } - } else { - } - } - return activeHttp; - } - - @Override - public void dataReceived(IOBuffer netx) throws IOException { - if (switchedProtocol != null) { - switchedProtocol.dataReceived(netx); - return; - } - //trace("handleReceived " + headersReceived); - if (!checkKeepAliveClient()) { - return; // we were in client keep alive mode - } - // endSendReceived uses same lock - it will call this - // to check outstanding bytes - synchronized (readLock) { - if (bodyReceived) { - return; // leave data in net buffer, for next req - } - - if (!headersReceived) { - if (!readHead()) { - return; - } - } - - // We have a header - if (activeHttp == null) { - if (checkHttpChannel() == null) { - return; - } - } - - IOBuffer receiveBody = activeHttp.receiveBody; - - if (!headersReceived) { - headRecvBuf.wrapTo(headW); - parseMessage(activeHttp, headW); - // Part of parseMessage we can switch the protocol - if (switchedProtocol != null) { - return; - } - - if (serverMode && activeHttp.httpReq.decodedUri.remaining() == 0) { - abort(activeHttp, "Invalid url"); - } - - headersReceived = true; - // Send header callbacks - we process any incoming data - // first, so callbacks have more info - trace("Send headers received callback " + activeHttp.httpService); - activeHttp.handleHeadersReceived(activeHttp.inMessage); - } - - // any remaining data will be processed as part of the - // body - or left in the channel until endSendReceive() - - if (!bodyReceived) { - // Will close receiveBody when it consummed enough - rawDataReceived(activeHttp, receiveBody, net.getIn()); - // Did we process anything ? - if (receiveBody.getBufferCount() > 0) { - activeHttp.sendHandleReceivedCallback(); // callback - } - } - // Receive has marked the body as closed - if (receiveBody.isAppendClosed()) { - bodyReceived = true; - activeHttp.handleEndReceive(); - } - - - if (net.getIn().isClosedAndEmpty()) { - // If not already closed. - closeStreamOnEnd("closed after body"); - } - - } - } - - /** - * We got data while in client keep alive ( no activeHttp ) - * - * @return false if there is an error - */ - private boolean checkKeepAliveClient() throws IOException { - // Client, no active connection ( keep alive ) - if (!serverMode && activeHttp == null) { - if (net.getIn().isClosedAndEmpty() || !net.isOpen()) { - // server disconnected, fine - httpConnector.cpool.stopKeepAlive(this); - return false; - } - if (net.getIn().available() == 0) { - return true; - } - log.warning("Unexpected message from server in client keep alive " - + net.getIn() + ": " + net.getIn().readAll(null)); - if (net.isOpen()) { - net.close(); - } - return false; - } - return true; - } - - private void processProtocol(CBuffer protocolMB) throws IOException { - http11 = false; - http09 = false; - http10 = false; - - if (protocolMB.equals(HttpChannel.HTTP_11)) { - http11 = true; - } else if (protocolMB.equals(HttpChannel.HTTP_10)) { - http10 = true; - } else if (protocolMB.equals("")) { - http09 = true; - } else { - http11 = true; // hopefully will be backward compat - } - } - - void closeStreamOnEnd(String cause) { - if (debug) { - log.info("Not reusing connection because: " + cause); - } - keepAlive = false; - } - - boolean keepAlive() { - if (httpConnector != null) { - if (serverMode && !httpConnector.serverKeepAlive) { - keepAlive = false; - } - if (!serverMode && !httpConnector.clientKeepAlive) { - keepAlive = false; - } - } - if (http09) { - keepAlive = false; - } - if (net != null && !net.isOpen()) { - keepAlive = false; - } - return keepAlive; - } - - @Override - protected void endSendReceive(HttpChannel http) throws IOException { - if (switchedProtocol != null) { - switchedProtocol.endSendReceive(http); - return; - } - chunk.recycle(); - rchunk.recycle(); - boolean keepAlive = keepAlive(); - if (!keepAlive) { - if (debug) { - log.info("--- Close socket, no keepalive " + net); - } - if (net != null) { - net.close(); - net.startSending(); - - } - } - - requestCount++; - beforeRequest(); - httpConnector.cpool.afterRequest(http, this, true); - - if (serverMode && keepAlive) { - handleReceived(net); // will attempt to read next req - } - } - - private void trace(String s) { - if(debug) { - log.info(this.toString() + " " + activeHttp + " " + s); - } - } - - private boolean isDone(BodyState bodys, IOBuffer body) { - if (bodys.noBody) { - return true; - } - if (bodys.isContentDelimited()) { - if (!bodys.chunked && bodys.remaining == 0) { - return true; - } else if (bodys.chunked && body.isAppendClosed()) { - return true; - } - } - return false; - } - - void parseMessage(HttpChannel http, BBuffer headB) throws IOException { - //Parse the response - line.recycle(); - headB.readLine(line); - - HttpMessageBytes msgBytes; - - if (serverMode) { - msgBytes = http.httpReq.getMsgBytes(); - parseRequestLine(line, msgBytes.method(), - msgBytes.url(), - msgBytes.query(), - msgBytes.protocol()); - } else { - msgBytes = http.httpRes.getMsgBytes(); - parseResponseLine(line, msgBytes.protocol(), - msgBytes.status(), msgBytes.message()); - } - - parseHeaders(http, msgBytes, headB); - - http.inMessage.state = HttpMessage.State.BODY_DATA; - - http.inMessage.processReceivedHeaders(); - - // TODO: hook to allow specific charsets ( can be done later ) - processProtocol(http.inMessage.protocol()); - - if (serverMode) { - // requested connection:close/keepAlive and proto - updateKeepAlive(http.getRequest().getMimeHeaders(), true); - - processExpectation(http); - - processContentDelimitation(receiveBodyState, http.getRequest()); - // Spec: - // The presence of a message-body in a request is signaled by the - // inclusion of a Content-Length or Transfer-Encoding header field in - // the request's message-headers - // Server should read - but ignore .. - receiveBodyState.noBody = !receiveBodyState.isContentDelimited(); - - updateCloseOnEnd(receiveBodyState, http, http.receiveBody); - - /* - * The presence of a message-body in a request is signaled by the - * inclusion of a Content-Length or Transfer-Encoding header field in - * the request's message-headers. A message-body MUST NOT be included - * in a request if the specification of the request method - * (section 5.1.1) does not allow sending an entity-body in requests. - * A server SHOULD read and forward a message-body on any request; if the request method does not include defined semantics for an entity-body, then the message-body SHOULD be ignored when handling the request. - */ - if (!receiveBodyState.isContentDelimited()) { - // No body - http.getIn().close(); - } - - } else { - receiveBodyState.noBody = !http.getResponse().hasBody(); - - updateKeepAlive(http.getResponse().getMimeHeaders(), false); - - if (statusDropsConnection(http.getResponse().getStatus())) { - closeStreamOnEnd("response status drops connection"); - } - IOBuffer body = http.receiveBody; - processContentDelimitation(receiveBodyState, http.getResponse()); - - if (isDone(receiveBodyState, body)) { - body.close(); - } - - if (!receiveBodyState.isContentDelimited()) { - closeStreamOnEnd("not content delimited"); - } - } - - } - - private void processExpectation(HttpChannel http) throws IOException { - http.expectation = false; - MultiMap headers = http.getRequest().getMimeHeaders(); - - CBuffer expect = headers.getHeader("expect"); - if ((expect != null) - && (expect.indexOf("100-continue") != -1)) { - http.expectation = true; - - // TODO: configure, use the callback or the servlet 'read'. - net.getOut().append("HTTP/1.1 100 Continue\r\n\r\n"); - net.startSending(); - } - } - - - /** - * Updates chunked, contentLength, remaining - based - * on headers - */ - private void processContentDelimitation(BodyState bodys, - HttpMessage httpMsg) { - - bodys.contentLength = httpMsg.getContentLength(); - if (bodys.contentLength >= 0) { - bodys.remaining = bodys.contentLength; - } - - // TODO: multiple transfer encoding headers, only process the last - String transferEncodingValue = httpMsg.getHeader(TRANSFERENCODING); - if (transferEncodingValue != null) { - int startPos = 0; - int commaPos = transferEncodingValue.indexOf(','); - String encodingName = null; - while (commaPos != -1) { - encodingName = transferEncodingValue.substring - (startPos, commaPos).toLowerCase().trim(); - if ("chunked".equalsIgnoreCase(encodingName)) { - bodys.chunked = true; - } - startPos = commaPos + 1; - commaPos = transferEncodingValue.indexOf(',', startPos); - } - encodingName = transferEncodingValue.substring(startPos) - .toLowerCase().trim(); - if ("chunked".equals(encodingName)) { - bodys.chunked = true; - httpMsg.chunked = true; - } else { - System.err.println("TODO: ABORT 501"); - //return 501; // Currently only chunked is supported for - // transfer encoding. - } - } - - if (bodys.chunked) { - bodys.remaining = 0; - } - } - - /** - * Read the request line. This function is meant to be used during the - * HTTP request header parsing. Do NOT attempt to read the request body - * using it. - * - * @throws IOException If an exception occurs during the underlying socket - * read operations, or if the given buffer is not big enough to accomodate - * the whole line. - */ - boolean parseRequestLine(BBuffer line, - BBuffer methodMB, BBuffer requestURIMB, - BBuffer queryMB, - BBuffer protoMB) - throws IOException { - - line.readToSpace(methodMB); - line.skipSpace(); - - line.readToDelimOrSpace(HttpChannel.QUESTION, requestURIMB); - if (line.remaining() > 0 && line.get(0) == HttpChannel.QUESTION) { - // Has query - line.readToSpace(queryMB); - // don't include '?' - queryMB.position(queryMB.position() + 1); - } else { - queryMB.setBytes(line.array(), line.position(), 0); - } - line.skipSpace(); - - line.readToSpace(protoMB); - - // proto is optional ( for 0.9 ) - return requestURIMB.remaining() > 0; - } - - boolean parseResponseLine(BBuffer line, - BBuffer protoMB, BBuffer statusCode, BBuffer status) - throws IOException { - line.skipEmptyLines(); - - line.readToSpace(protoMB); - line.skipSpace(); - line.readToSpace(statusCode); - line.skipSpace(); - line.wrapTo(status); - - // message may be empty - return statusCode.remaining() > 0; - } - - List connectionHeaders = new ArrayList(); - - private void parseHeaders(HttpChannel http, HttpMessageBytes msgBytes, - BBuffer head) - throws IOException { - - head.readLine(line); - - int idx = 0; - - BBuffer upgrade = null; - - while(line.remaining() > 0) { - // not empty.. - idx = msgBytes.addHeader(); - BBuffer nameBuf = msgBytes.getHeaderName(idx); - BBuffer valBuf = msgBytes.getHeaderValue(idx); - parseHeader(http, head, line, nameBuf, valBuf); - - // TODO: process 'interesting' headers here. - if (nameBuf.equalsIgnoreCase("connection")) { - // TODO: save and remove if not recognized - } - if (nameBuf.equalsIgnoreCase("upgrade")) { - upgrade = valBuf; - } - } - - if (upgrade != null) { - if (upgrade.equalsIgnoreCase("WebSocket")) { - - } else if (upgrade.equalsIgnoreCase("SPDY/1.0")) { - - } - } - - // TODO: process connection headers - } - - /** - * Parse one header. - * Line must be populated. On return line will be populated - * with the next header: - * - * @param line current header line, not empty. - */ - int parseHeader(HttpChannel http, BBuffer head, - BBuffer line, BBuffer name, BBuffer value) - throws IOException { - - int newPos = line.readToDelimOrSpace(COLON, name); - line.skipSpace(); - if (line.readByte() != COLON) { - throw new IOException("Missing ':' in header name " + line); - } - line.skipSpace(); - line.read(value); // remaining of the line - - while (true) { - head.readLine(line); - if (line.remaining() == 0) { - break; - } - int first = line.get(0); - if (first != BBuffer.SP && first != BBuffer.HT) { - break; - } - // continuation line - append it to value - value.setEnd(line.getEnd()); - line.position(line.limit()); - } - - // We may want to keep the original and use separate buffer ? - http.normalizeHeader(value); - return 1; - } - - private int receiveDone(HttpChannel http, IOBuffer body, boolean frameError) throws IOException { - // Content-length case, we're done reading - body.close(); - - http.error = frameError; - if (frameError) { - closeStreamOnEnd("frame error"); - } - - return DONE; - } - - /** - * Called when raw body data is received. - * Callback should not consume past the end of the body. - * @param rawReceiveBuffers - * - */ - private void rawDataReceived(HttpChannel http, IOBuffer body, - IOBuffer rawReceiveBuffers) throws IOException { - // TODO: Make sure we don't process more than we need ( eat next req ). - // If we read too much: leave it in readBuf, the finalzation code - // should skip KeepAlive and start processing it. - // we need to read at least something - to detect -1 ( we could - // suspend right away, but seems safer - BodyState bodys = receiveBodyState; - - while (http.inMessage.state == HttpMessage.State.BODY_DATA) { - if (receiveBodyState.noBody) { - receiveDone(http, body, false); - return; - } - if (rawReceiveBuffers.isClosedAndEmpty()) { - if (receiveBodyState.isContentDelimited()) { - if (receiveBodyState.contentLength >= 0 && receiveBodyState.remaining == 0) { - receiveDone(http, body, false); - } else { - // End of input - other side closed, no more data - //log.info("CLOSE while reading " + this); - // they're not supposed to close ! - receiveDone(http, body, true); - } - } else { - receiveDone(http, body, false); // ok - } - // input connection closed ? - closeStreamOnEnd("Closed input"); - return; - } - BBucket rawBuf = rawReceiveBuffers.peekFirst(); - if (rawBuf == null) { - return; // need more data - } - - if (!bodys.isContentDelimited()) { - while (true) { - BBucket first = rawReceiveBuffers.popFirst(); - if (first == null) { - break; // will go back to check if done. - } else { - received(body, first); - } - } - } else { - - if (bodys.contentLength >= 0 && bodys.remaining == 0) { - receiveDone(http, body, false); - return; - } - - if (bodys.chunked && bodys.remaining == 0) { - int rc = NEED_MORE; - // TODO: simplify, use readLine() - while (rc == NEED_MORE) { - rc = rchunk.parseChunkHeader(rawReceiveBuffers); - if (rc == ERROR) { - http.abort("Chunk error"); - receiveDone(http, body, true); - return; - } else if (rc == NEED_MORE) { - return; - } - } - if (rc == 0) { // last chunk - receiveDone(http, body, false); - return; - } else { - bodys.remaining = rc; - } - } - - rawBuf = (BBucket) rawReceiveBuffers.peekFirst(); - if (rawBuf == null) { - return; // need more data - } - - - if (bodys.remaining < rawBuf.remaining()) { - // To buffer has more data than we need. - int lenToConsume = (int) bodys.remaining; - BBucket sb = rawReceiveBuffers.popLen(lenToConsume); - received(body, sb); - //log.info("Queue received buffer " + this + " " + lenToConsume); - bodys.remaining = 0; - } else { - BBucket first = rawReceiveBuffers.popFirst(); - bodys.remaining -= first.remaining(); - received(body, first); - //log.info("Queue full received buffer " + this + " RAW: " + rawReceiveBuffers); - } - if (bodys.contentLength >= 0 && bodys.remaining == 0) { - // Content-Length, all done - body.close(); - receiveDone(http, body, false); - } - } - } - } - - private void received(IOBuffer body, BBucket bb) throws IOException { - body.queue(bb); - } - - - protected void sendRequest(HttpChannel http) - throws IOException { - if (switchedProtocol != null) { - switchedProtocol.sendRequest(http); - return; - } - - // Update transfer fields based on headers. - processProtocol(http.getRequest().protocol()); - updateKeepAlive(http.getRequest().getMimeHeaders(), true); - - // Update Host header - if (http.getRequest().getMimeHeaders().getHeader("Host") == null) { - String target = http.getTarget(); - if (target == null) { - throw new IOException("Missing host header"); - } - CBuffer hostH = http.getRequest().getMimeHeaders().addValue("Host"); - if (target.endsWith(":80")) { - hostH.set(target.substring(0, target.length() - 3)); - } else { - hostH.set(target); - } - } - - processContentDelimitation(sendBodyState, - http.getRequest()); - - - CBuffer method = http.getRequest().method(); - if (method.equals("GET") || method.equals("HEAD")) { - // TODO: add the others - sendBodyState.noBody = true; - } - - // 1.0: The presence of an entity body in a request is signaled by - // the inclusion of a Content-Length header field in the request - // message headers. HTTP/1.0 requests containing an entity body - // must include a valid Content-Length header field. - if (http10 && !sendBodyState.isContentDelimited()) { - // Will not close connection - just flush and mark the body - // as sent - sendBodyState.noBody = true; - } - - if (sendBodyState.noBody) { - http.getRequest().getMimeHeaders().remove(HttpChannel.CONTENT_LENGTH); - http.getRequest().getMimeHeaders().remove(TRANSFERENCODING); - http.getOut().close(); - } else { - long contentLength = - http.getRequest().getContentLength(); - if (contentLength < 0) { - http.getRequest().getMimeHeaders().addValue("Transfer-Encoding"). - set(CHUNKED); - } - } - - updateCloseOnEnd(sendBodyState, http, http.sendBody); - - try { - serialize(http.getRequest(), net.getOut()); - if (http.debug) { - http.trace("S: \n" + net.getOut()); - } - - if (http.outMessage.state == HttpMessage.State.HEAD) { - http.outMessage.state = HttpMessage.State.BODY_DATA; - } - - - // TODO: add any body and flush. More body can be added later - - // including 'end'. - - http.startSending(); - } catch (Throwable t) { - log.log(Level.SEVERE, "Error sending request", t); - abort(t.getMessage()); - } - - } - - - /** - * Determine if we must drop the connection because of the HTTP status - * code. Use the same list of codes as Apache/httpd. - */ - private boolean statusDropsConnection(int status) { - return status == 400 /* SC_BAD_REQUEST */ || - status == 408 /* SC_REQUEST_TIMEOUT */ || - status == 411 /* SC_LENGTH_REQUIRED */ || - status == 413 /* SC_REQUEST_ENTITY_TOO_LARGE */ || - status == 414 /* SC_REQUEST_URI_TOO_LARGE */ || - status == 500 /* SC_INTERNAL_SERVER_ERROR */ || - status == 503 /* SC_SERVICE_UNAVAILABLE */ || - status == 501 /* SC_NOT_IMPLEMENTED */; - } - - protected void sendResponseHeaders(HttpChannel http) - throws IOException { - if (switchedProtocol != null) { - switchedProtocol.sendResponseHeaders(http); - return; - } - - if (!serverMode) { - throw new IOException("Only in server mode"); - } - endSent = false; - IOBuffer sendBody = http.sendBody; - HttpResponse res = http.getResponse(); - if (res.isCommitted()) { - return; - } - res.setCommitted(true); - - sendBodyState.noBody = !res.hasBody(); - - if (statusDropsConnection(res.getStatus())) { - closeStreamOnEnd("status drops connection"); - } - if (http.error) { - closeStreamOnEnd("error"); - } - - MultiMap headers = res.getMimeHeaders(); - - // Add date header - if (headers.getHeader("Date") == null) { - headers.setValue("Date").set(FastHttpDateFormat.getCurrentDate()); - } - - // Add server header - if (http.serverHeader.length() > 0) { - headers.setValue("Server").set(http.serverHeader); - } - - // Decide on a transfer encoding for out. - if (keepAlive()) { // request and user allows keep alive - int cl = res.getContentLength(); - - if (http10) { - if (cl < 0 && !sendBodyState.noBody && - sendBody.isAppendClosed()) { - // We can generate content-lenght - cl = sendBody.available(); - res.setContentLength(cl); - } - if (cl < 0 && !sendBodyState.noBody) { - closeStreamOnEnd("HTTP/1.0 without content length"); - } else { - headers.setValue(CONNECTION).set(KEEPALIVE_S); - } - } else { // http11 - if (!sendBodyState.noBody) { - if (cl < 0) { - res.getMimeHeaders().setValue(TRANSFERENCODING).set(CHUNKED); - } - } - } - } else { - headers.setValue(CONNECTION).set(CLOSE); - // since we close the connection - don't bother with - // transfer encoding - headers.remove(TRANSFERENCODING); - } - - // Update our internal state based on headers we just set. - processContentDelimitation(sendBodyState, res); - updateCloseOnEnd(sendBodyState, http, sendBody); - - - if (http.debug) { - http.trace("Send response headers " + net); - } - if (net != null) { - serialize(res, net.getOut()); - } - - if (http.outMessage.state == HttpMessage.State.HEAD) { - http.outMessage.state = HttpMessage.State.BODY_DATA; - } - - if (isDone(sendBodyState, sendBody)) { - http.getOut().close(); - } - - if (net != null) { - net.startSending(); - } - } - - private void abort(String t) throws IOException { - abort(activeHttp, t); - } - - private void updateCloseOnEnd(BodyState bodys, HttpChannel http, IOBuffer body) { - if (!bodys.isContentDelimited() && !bodys.noBody) { - closeStreamOnEnd("not content delimited"); - } - } - - /** - * Disconnect abruptly - client closed, frame errors, etc - * @param t - * @throws IOException - */ - public void abort(HttpChannel http, String t) throws IOException { - if (switchedProtocol != null) { - switchedProtocol.abort(http, t); - return; - } - keepAlive = false; - if (net != null ) { - if (net.isOpen()) { - net.close(); - net.startSending(); - } - } - if (http != null) { - http.abort(t); - } - } - - /** - * Update keepAlive based on Connection header and protocol. - */ - private void updateKeepAlive(MultiMap headers, boolean request) { - if (http09) { - closeStreamOnEnd("http 0.9"); - return; - } - - // TODO: also need to remove headers matching connection - // ( like 'upgrade') - - CBuffer value = headers.getHeader(CONNECTION); - // TODO: split it by space - if (value != null) { - value.toLower(); - if (value.indexOf(CLOSE) >= 0) { - // 1.1 ( but we accept it for 1.0 too ) - closeStreamOnEnd("connection close"); - } - if (http10 && value.indexOf(KEEPALIVE_S) < 0) { - // Keep-Alive required for http/1.0 - closeStreamOnEnd("connection != keep alive"); - } - // we have connection: keepalive, good - } else { - // no connection header - for 1.1 default is keepAlive, - // for 10 it's close - if (http10) { - closeStreamOnEnd("http1.0 no connection header"); - } - } - } - - @Override - public void startSending() throws IOException { - if (switchedProtocol != null) { - switchedProtocol.startSending(); - return; - } - - } - - @Override - public void startSending(HttpChannel http) throws IOException { - if (switchedProtocol != null) { - switchedProtocol.startSending(http); - return; - } - http.send(); // if needed - - if (net == null) { - return; // not connected yet. - } - - if (net.getOut().isAppendClosed()) { - abort("Net closed"); - } else { - flushToNext(http.sendBody, net.getOut()); - net.startSending(); - } - - } - - protected void outClosed(HttpChannel http) throws IOException { - if (switchedProtocol != null) { - switchedProtocol.outClosed(http); - return; - } - // TODO: move it ? - if (sendBodyState.isContentDelimited() && !http.error) { - if (!sendBodyState.chunked && - sendBodyState.remaining - http.getOut().available() > 0) { - http.abort("CLOSE CALLED WITHOUT FULL LEN"); - } - } - - } - - @Override - public void handleFlushed(IOChannel net) throws IOException { - if (switchedProtocol != null) { - switchedProtocol.handleFlushed(net); - return; - } - if (activeHttp != null) { - activeHttp.flushLock.signal(this); - activeHttp.handleFlushed(this); - if (activeHttp.sendBody.isClosedAndEmpty()) { - activeHttp.handleEndSent(); - } - } - } - - - private void flushToNext(IOBuffer body, IOBuffer out) throws IOException { - - synchronized (this) { - // TODO: better head support - if (sendBodyState.noBody) { - for (int i = 0; i < body.getBufferCount(); i++) { - Object bc = body.peekBucket(i); - if (bc instanceof BBucket) { - ((BBucket) bc).release(); - } - } - body.clear(); - return; - } - - // TODO: only send < remainingWrite, if buffer - // keeps changing after startWrite() is called (shouldn't) - - if (sendBodyState.chunked) { - sendChunked(sendBodyState, body, out); - } else if (sendBodyState.contentLength >= 0) { - // content-length based - sendContentLen(sendBodyState, body, out); - } else { - sendCloseDelimited(body, out); - } - } - } - - private void sendCloseDelimited(IOBuffer body, IOBuffer out) throws IOException { - // Close delimitation - while (true) { - Object bc = body.popFirst(); - if (bc == null) { - break; - } - out.queue(bc); - } - if (body.isClosedAndEmpty()) { - out.close(); // no content-delimitation - } - } - - /** - * Convert the request to bytes, ready to send. - */ - public static void serialize(HttpRequest req, IOBuffer rawSendBuffers2) throws IOException { - rawSendBuffers2.append(req.method()); - rawSendBuffers2.append(BBuffer.SP); - - // TODO: encode or use decoded - rawSendBuffers2.append(req.requestURI()); - if (req.queryString().length() > 0) { - rawSendBuffers2.append("?"); - rawSendBuffers2.append(req.queryString()); - } - - rawSendBuffers2.append(BBuffer.SP); - rawSendBuffers2.append(req.protocol()); - rawSendBuffers2.append(BBuffer.CRLF_BYTES); - - serializeHeaders(req.getMimeHeaders(), rawSendBuffers2); - } - - /** - * Convert the response to bytes, ready to send. - */ - public static void serialize(HttpResponse res, IOBuffer rawSendBuffers2) throws IOException { - - rawSendBuffers2.append(res.protocol()).append(' '); - String status = Integer.toString(res.getStatus()); - rawSendBuffers2.append(status).append(' '); - if (res.getMessageBuffer().length() > 0) { - rawSendBuffers2.append(res.getMessage()); - } else { - rawSendBuffers2 - .append(res.getMessage(res.getStatus())); - } - rawSendBuffers2.append(BBuffer.CRLF_BYTES); - // Headers - serializeHeaders(res.getMimeHeaders(), rawSendBuffers2); - } - - public static void serializeHeaders(MultiMap mimeHeaders, IOBuffer rawSendBuffers2) throws IOException { - for (int i = 0; i < mimeHeaders.size(); i++) { - CBuffer name = mimeHeaders.getName(i); - CBuffer value = mimeHeaders.getValue(i); - if (name.length() == 0 || value.length() == 0) { - continue; - } - rawSendBuffers2.append(name); - rawSendBuffers2.append(Http11Connection.COLON); - rawSendBuffers2.append(value); - rawSendBuffers2.append(BBuffer.CRLF_BYTES); - } - rawSendBuffers2.append(BBuffer.CRLF_BYTES); - } - - - private boolean sendContentLen(BodyState bodys, IOBuffer body, IOBuffer out) throws IOException { - while (true) { - BBucket bucket = body.peekFirst(); - if (bucket == null) { - break; - } - int len = bucket.remaining(); - if (len <= bodys.remaining) { - bodys.remaining -= len; - bucket = body.popFirst(); - out.queue(bucket); - } else { - // Write over the end of the buffer ! - log.severe("write more than Content-Length"); - len = (int) bodys.remaining; - // data between position and limit - bucket = body.popLen((int) bodys.remaining); - out.queue(bucket); - while (bucket != null) { - bucket = body.popFirst(); - if (bucket != null) { - bucket.release(); - } - } - - // forced close - //close(); - bodys.remaining = 0; - return true; - } - } - if (body.isClosedAndEmpty()) { - //http.rawSendBuffers.queue(IOBrigade.MARK); - if (bodys.remaining > 0) { - closeStreamOnEnd("sent more than content-length"); - log.severe("Content-Length > body"); - } - return true; - } - return false; - } - - private boolean sendChunked(BodyState bodys, IOBuffer body, IOBuffer out) throws IOException { - int len = body.available(); - - if (len > 0) { - ByteBuffer sendChunkBuffer = chunk.prepareChunkHeader(len); - bodys.remaining = len; - out.queue(sendChunkBuffer); - while (bodys.remaining > 0) { - BBucket bc = body.popFirst(); - bodys.remaining -= bc.remaining(); - out.queue(bc); - } - } - - if (body.isClosedAndEmpty()) { - synchronized(this) { - if (!endSent) { - out.append(chunk.endChunk()); - endSent = true; - } - } - return true; - } else { - return false; - } - } - - // used for chunk parsing/end - ChunkState chunk = new ChunkState(); - ChunkState rchunk = new ChunkState(); - static final int NEED_MORE = -1; - static final int ERROR = -4; - static final int DONE = -5; - - - static class ChunkState { - static byte[] END_CHUNK_BYTES = { - (byte) '\r', (byte) '\n', - (byte) '0', - (byte) '\r', (byte) '\n', - (byte) '\r', (byte) '\n'}; - - - int partialChunkLen; - boolean readDigit = false; - boolean trailer = false; - protected boolean needChunkCrlf = false; - - // Buffer used for chunk length conversion. - protected byte[] sendChunkLength = new byte[10]; - - /** End chunk marker - will include chunked end or empty */ - protected BBuffer endSendBuffer = BBuffer.wrapper(); - - public ChunkState() { - sendChunkLength[8] = (byte) '\r'; - sendChunkLength[9] = (byte) '\n'; - } - - void recycle() { - partialChunkLen = 0; - readDigit = false; - trailer = false; - needChunkCrlf = false; - endSendBuffer.recycle(); - } - - /** - * Parse the header of a chunk. - * A chunk header can look like - * A10CRLF - * F23;chunk-extension to be ignoredCRLF - * The letters before CRLF but after the trailer mark, must be valid hex digits, - * we should not parse F23IAMGONNAMESSTHISUP34CRLF as a valid header - * according to spec - */ - int parseChunkHeader(IOBuffer buffer) throws IOException { - if (buffer.peekFirst() == null) { - return NEED_MORE; - } - if (needChunkCrlf) { - // TODO: Trailing headers - int c = buffer.read(); - if (c == BBuffer.CR) { - if (buffer.peekFirst() == null) { - return NEED_MORE; - } - c = buffer.read(); - } - if (c == BBuffer.LF) { - needChunkCrlf = false; - } else { - System.err.println("Bad CRLF " + c); - return ERROR; - } - } - - while (true) { - if (buffer.peekFirst() == null) { - return NEED_MORE; - } - int c = buffer.read(); - - if (c == BBuffer.CR) { - continue; - } else if (c == BBuffer.LF) { - break; - } else if (c == HttpChannel.SEMI_COLON) { - trailer = true; - } else if (c == BBuffer.SP) { - // ignore - } else if (trailer) { - // ignore - } else { - //don't read data after the trailer - if (Hex.DEC[c] != -1) { - readDigit = true; - partialChunkLen *= 16; - partialChunkLen += Hex.DEC[c]; - } else { - //we shouldn't allow invalid, non hex characters - //in the chunked header - log.info("Chunk parsing error1 " + c + " " + buffer); - //http.abort("Chunk error"); - return ERROR; - } - } - } - - if (!readDigit) { - log.info("Chunk parsing error2 " + buffer); - return ERROR; - } - - needChunkCrlf = true; // next time I need to parse CRLF - int result = partialChunkLen; - partialChunkLen = 0; - trailer = false; - readDigit = false; - return result; - } - - - ByteBuffer prepareChunkHeader(int current) { - int pos = 7; // 8, 9 are CRLF - while (current > 0) { - int digit = current % 16; - current = current / 16; - sendChunkLength[pos--] = Hex.HEX[digit]; - } - if (needChunkCrlf) { - sendChunkLength[pos--] = (byte) '\n'; - sendChunkLength[pos--] = (byte) '\r'; - } else { - needChunkCrlf = true; - } - // TODO: pool - this may stay in the queue while we flush more - ByteBuffer chunkBB = ByteBuffer.allocate(16); - chunkBB.put(sendChunkLength, pos + 1, 9 - pos); - chunkBB.flip(); - return chunkBB; - } - - public BBuffer endChunk() { - if (! needChunkCrlf) { - endSendBuffer.setBytes(END_CHUNK_BYTES, 2, - END_CHUNK_BYTES.length - 2); // CRLF - } else { // 0 - endSendBuffer.setBytes(END_CHUNK_BYTES, 0, - END_CHUNK_BYTES.length); - } - return endSendBuffer; - } - } - - static class BodyState { - /** response: HEAD or 1xx, 204, 304 status - * req: missing content-length or transfer-encoding - */ - protected boolean noBody = false; - protected boolean chunked = false; - protected long contentLength = -1; // C-L header - /** Bytes remaining in the current chunk or body ( if CL ) */ - protected long remaining = 0; // both chunked and C-L - - public void recycle() { - chunked = false; - remaining = 0; - contentLength = -1; - noBody = false; - } - public boolean isContentDelimited() { - return chunked || contentLength >= 0; - } - - } - - public String toString() { - if (switchedProtocol != null) { - return switchedProtocol.toString(); - } - - return (serverMode ? "SR " : "CL ") + - (keepAlive() ? " KA " : "") + - (headersReceived ? " HEAD " : "") + - (bodyReceived ? " BODY " : "") - ; - } - - @Override - public void handleConnected(IOChannel net) throws IOException { - HttpChannel httpCh = activeHttp; - - if (!net.isOpen()) { - httpCh.abort(net.lastException()); - return; - } - - boolean ssl = httpCh.getRequest().isSecure(); - if (ssl) { - String[] hostPort = httpCh.getTarget().split(":"); - - IOChannel ch1 = httpConnector.sslProvider.channel(net, - hostPort[0], Integer.parseInt(hostPort[1])); - //net.setHead(ch1); - net = ch1; - } - if (httpConnector.debugHttp) { - net = DumpChannel.wrap("Http-Client-", net); - } - - setSink(net); - - sendRequest(httpCh); - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpChannel.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpChannel.java deleted file mode 100644 index 07ed719a2275..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpChannel.java +++ /dev/null @@ -1,830 +0,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.lite.http; - -import java.io.IOException; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.http.HttpConnector.HttpConnection; -import org.apache.tomcat.lite.io.BBucket; -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.FutureCallbacks; -import org.apache.tomcat.lite.io.IOBuffer; -import org.apache.tomcat.lite.io.IOChannel; -import org.apache.tomcat.lite.io.IOConnector; - -/** - * HTTP async client and server, based on tomcat NIO/APR connectors - * - * 'Input', 'read', 'Recv' refers to information we get from the remote side - - * the request body for server-mode or response body for client. - * - * 'Output', 'write', 'Send' is for info we send - the post in client mode - * and the response body for server mode. - * - * @author Costin Manolache - */ -public class HttpChannel extends IOChannel { - - static final int HEADER_SIZE = 8192; - - static AtomicInteger serCnt = new AtomicInteger(); - - public static final String CONTENT_LENGTH= "Content-Length"; - - public static final String HTTP_10 = "HTTP/1.0"; - - public static final String HTTP_11 = "HTTP/1.1"; - - /** - * SEMI_COLON. - */ - public static final byte SEMI_COLON = (byte) ';'; - - public static final byte QUESTION = (byte) '?'; - - - protected static Logger log = Logger.getLogger("HttpChannel"); - - - boolean debug = false; - - // ---- Callbacks and locks - - FutureCallbacks doneLock = new FutureCallbacks(); - FutureCallbacks headersReceivedLock = - new FutureCallbacks(); - /** - * Called when the incoming headers have been received. - * ( response for client mode, request for server mode ) - * @throws IOException - */ - protected HttpService httpService; - /** - * Called when: - * - body sent - * - body received - * - release() called - either service() done or client done with the - * buffers. - * - * After this callback: - * - socket closed if closeOnEndSend, or put in keep-alive - * - AsyncHttp.recycle() - * - returned to the pool. - */ - private RequestCompleted doneAllCallback; - protected boolean sendReceiveDone = false; - - // Will be signalled (open) when the buffer is empty. - FutureCallbacks flushLock = new FutureCallbacks(); - - FutureCallbacks doneFuture; - boolean doneCallbackCalled = false; - - - // ---------- - - // Set if Exect: 100-continue was set on reqest. - // If this is the case - body won't be sent until - // server responds ( client ) and server will only - // read body after ack() - or skip to next request - // without swallowing the body. - protected boolean expectation = false; - - /** Ready for recycle, if send/receive are done */ - protected boolean release = false; - - // ----------- - - protected boolean headersDone = false; - protected boolean error = false; - protected boolean abortDone = false; - - - protected int ser; // id - for jmx registration and logs - protected int channelId; - - /** - * Null after endSendReceive and before sending the request - */ - HttpConnection conn; - - HttpConnector httpConnector; - - // Different ways to point to request response (server/client) - HttpRequest httpReq; - HttpResponse httpRes; - HttpMessage inMessage; - HttpMessage outMessage; - // receive can be for request ( server mode ) or response ( client ) - IOBuffer receiveBody = new IOBuffer(); - - // notify us that user called close() - IOBuffer sendBody = new IOBuffer() { - public void close() throws IOException { - if (isAppendClosed()) { - return; - } - super.close(); - outClosed(); - } - }; - - - // Server side only - protected String serverHeader = "TomcatLite"; - - long ioTimeout = 30 * 60000; // 30 min seems high enough - - - public HttpChannel() { - ser = serCnt.incrementAndGet(); - httpReq = new HttpRequest(this); - httpRes = new HttpResponse(this); - init(); - serverMode(false); - } - - /** - * Close the connection, return to pool. Called if a - * framing error happens, or if we want to force the connection - * to close, without waiting for all data to be sent/received. - * @param t - * - * @throws IOException - */ - public void abort(Throwable t) { - abort(t.toString()); - } - - public void abort(String t) { - synchronized (this) { - if (abortDone) { - return; - } - abortDone = true; - } - try { - checkRelease(); - trace("abort " + t); - if (conn != null) { - conn.abort(this, t); - } - inMessage.state = HttpMessage.State.DONE; - outMessage.state = HttpMessage.State.DONE; - sendReceiveDone = true; - error = true; - handleEndSendReceive(); - } catch (Throwable ex) { - log.severe("Exception in abort " + ex); - } - } - - /** - * If release was called - throw exception, you shouldn't use - * the object again. - * @throws IOException - */ - private void checkRelease() throws IOException { - if (release && sendReceiveDone) { - throw new IOException("Object released"); - } - } - - public IOChannel getSink() { - if (conn == null) { - return null; - } - return conn.getSink(); - } - - - /** - * Called when the request is done. Need to send remaining byte. - * - */ - public void complete() throws IOException { - checkRelease(); - if (!getOut().isAppendClosed()) { - getOut().close(); - } - if (!getIn().isAppendClosed()) { - getIn().close(); - } - - startSending(); - } - - public int doRead(BBuffer chunk) - throws IOException { - checkRelease(); - BBucket next = null; - while (true) { - getIn().waitData(0); - next = (BBucket) getIn().popFirst(); - if (next != null) { - break; - } else if (getIn().isAppendClosed()) { - return -1; - } else { - System.err.println("Spurious waitData signal, no data"); - } - } - chunk.append(next.array(), next.position(), next.remaining()); - int read = next.remaining(); - next.release(); - return read; - } - - public HttpConnector getConnector() { - return httpConnector; - } - - public boolean getError() { - return error; - } - - // ---------------- Writting ------------------------------- - - public String getId() { - return Integer.toString(ser); - } - - public IOBuffer getIn() { - return receiveBody; - } - - - public long getIOTimeout() { - return ioTimeout; - } - - // TODO: replace with getSocketChannel - used for remote addr, etc - public IOChannel getNet() { - if (conn == null) { - return null; - } - return conn.getSink(); - } - - - public IOBuffer getOut() { - return sendBody; - } - - public HttpRequest getRequest() { - return httpReq; - } - - - public HttpResponse getResponse() { - return httpRes; - } - - - public String getState() { - return - conn + - "RCV=[" + inMessage.state.toString() + " " + - receiveBody.toString() - + "] SND=[" + outMessage.state.toString() - + " " + sendBody.toString() + "]"; - } - - - public String getStatus() { - return getResponse().getStatus() + " " + getResponse().getMessage(); - } - - - public String getTarget() { - if (target == null) { - return ":0"; // server mode ? - } - return target.toString(); - } - - - /** - * Called from IO thread, after the request body - * is completed ( or if there is no req body ) - * @throws IOException - */ - protected void handleEndReceive() throws IOException { - if (inMessage.state == HttpMessage.State.DONE) { - return; - } - if (debug) { - trace("END_RECV"); - } - getIn().close(); - - inMessage.state = HttpMessage.State.DONE; - handleEndSendReceive(); - } - - /* - * Called when sending, receiving and processing is done. - * Can be called: - * - from IO thread, if this is a result of a read/write event that - * finished the send/recev pair. - * - from an arbitrary thread, if read was complete and the last write - * was a success and done in that thread ( write is not bound to IO thr) - * - */ - protected void handleEndSendReceive() throws IOException { - // make sure the callback was called ( needed for abort ) - handleHeadersReceived(inMessage); - - this.doneLock.signal(this); - synchronized (this) { - if (doneCallbackCalled) { - return; - } - if (outMessage.state != HttpMessage.State.DONE || - inMessage.state != HttpMessage.State.DONE) { - return; - } - doneCallbackCalled = true; - } - - getIn().close(); - - if (doneAllCallback != null) { - doneAllCallback.handle(this, error ? new Throwable() : null); - } - - if (conn != null) { - conn.endSendReceive(this); - } - - conn = null; - - if (debug) { - trace("END_SEND_RECEIVE" - + (release ? " REL" : "")); - } - - synchronized(this) { - sendReceiveDone = true; - maybeRelease(); - } - } - - /** - * called from IO thread OR servlet thread when last block has been sent. - * If not using the socket ( net.getOut().flushCallback ) - this must - * be called explicitely after flushing the body. - */ - void handleEndSent() throws IOException { - if (outMessage.state == HttpMessage.State.DONE) { - // Only once. - if (debug) { - trace("Duplicate END SEND"); - } - return; - } - outMessage.state = HttpMessage.State.DONE; - - getOut().close(); - - // Make sure the send/receive callback is called once - if (debug) { - trace("END_SEND"); - } - handleEndSendReceive(); - } - - // ----- End Selector thread callbacks ---- - public void handleError(String type) { - System.err.println("Error " + type + " " + outMessage.state); - } - - void handleHeadersReceived(HttpMessage in) throws IOException { - if (!headersDone) { - headersDone = true; - headersReceivedLock.signal(this); - if (httpService != null) { - try { - httpService.service(getRequest(), getResponse()); - } catch (Throwable t) { - t.printStackTrace(); - abort(t); - } - } - } - } - - - private void init() { - headersDone = false; - sendReceiveDone = false; - - receiveBody.recycle(); - sendBody.recycle(); - expectation = false; - - error = false; - abortDone = false; - - - getRequest().recycle(); - getResponse().recycle(); - target = null; - - doneLock.recycle(); - headersReceivedLock.recycle(); - flushLock.recycle(); - - doneCallbackCalled = false; - // Will be set again after pool - setHttpService(null); - doneAllCallback = null; - release = false; - } - - public boolean isDone() { - return outMessage.state == HttpMessage.State.DONE && inMessage.state == HttpMessage.State.DONE; - } - - /** - * Called when all done: - * - service finished ( endService was called ) - * - output written - * - input read - * - * or by abort(). - * - * @throws IOException - */ - private void maybeRelease() throws IOException { - synchronized (this) { - if (release && sendReceiveDone) { - if (debug) { - trace("RELEASE"); - } - if (getConnector() != null) { - getConnector().returnToPool(this); - } else { - log.severe("Attempt to release with no pool"); - } - } - } - } - - - /* - The field-content does not include any leading or trailing LWS: - linear white space occurring before the first non-whitespace - character of the field-value or after the last non-whitespace - character of the field-value. Such leading or trailing LWS MAY - be removed without changing the semantics of the field value. - Any LWS that occurs between field-content MAY be replaced with - a single Http11Parser.SP before interpreting the field value or forwarding - the message downstream. - */ - int normalizeHeader(BBuffer value) { - byte[] buf = value.array(); - int cstart = value.position(); - int end = value.limit(); - - int realPos = cstart; - int lastChar = cstart; - byte chr = 0; - boolean gotSpace = true; - - for (int i = cstart; i < end; i++) { - chr = buf[i]; - if (chr == BBuffer.CR) { - // skip - } else if(chr == BBuffer.LF) { - // skip - } else if (chr == BBuffer.SP || chr == BBuffer.HT) { - if (gotSpace) { - // skip - } else { - buf[realPos++] = BBuffer.SP; - gotSpace = true; - } - } else { - buf[realPos++] = chr; - lastChar = realPos; // to skip trailing spaces - gotSpace = false; - } - } - realPos = lastChar; - - // so buffer is clean - for (int i = realPos; i < end; i++) { - buf[i] = BBuffer.SP; - } - value.setEnd(realPos); - return realPos; - } - - - protected void recycle() { - if (debug) { - trace("RECYCLE"); - } - init(); - } - - /** - * Finalize sending and receiving. - * Indicates client is no longer interested, some IO may still be in flight. - * If in a POST and you're not interested in the body - it may be - * better to call abort(). - * - * MUST be called to allow connection reuse and pooling. - * - * @throws IOException - */ - public void release() throws IOException { - synchronized(this) { - if (release) { - return; - } - trace("RELEASE"); - release = true; - // If send/receive is done - we can reuse this object - maybeRelease(); - } - } - - public void send() throws IOException { - checkRelease(); - if (httpReq == inMessage) { - conn.sendResponseHeaders(this); - } else { - if (getRequest().isCommitted()) { - return; - } - getRequest().setCommitted(true); - - outMessage.state = HttpMessage.State.HEAD; - - getConnector().connectAndSend(this); - } - } - - /** Called when the outgoing stream is closed: - * - by an explicit call to close() - * - when all content has been sent. - */ - protected void outClosed() throws IOException { - if (conn != null) { - conn.outClosed(this); - } - } - - public HttpChannel serverMode(boolean enabled) { - if (enabled) { - httpReq.setBody(receiveBody); - httpRes.setBody(sendBody); - inMessage = httpReq; - outMessage = httpRes; - } else { - httpReq.setBody(sendBody); - httpRes.setBody(receiveBody); - inMessage = httpRes; - outMessage = httpReq; - } - if (debug) { - } - return this; - } - - public void setCompletedCallback(RequestCompleted doneAllCallback) - throws IOException { - this.doneAllCallback = doneAllCallback; - synchronized (this) { - if (doneCallbackCalled) { - return; - } - if (outMessage.state != HttpMessage.State.DONE || inMessage.state != HttpMessage.State.DONE) { - return; - } - } - doneCallbackCalled = true; - if (doneAllCallback != null) { - doneAllCallback.handle(this, error ? new Throwable() : null); - } - } - - public void setConnector(HttpConnector pool) { - this.httpConnector = pool; - } - - public void setHttpService(HttpService headersReceivedCallback) { - this.httpService = headersReceivedCallback; - } - - public void setIOTimeout(long timeout) { - ioTimeout = timeout; - } - - - public void setTarget(String host) { - this.target = host; - } - - public void startSending() throws IOException { - checkRelease(); - if (conn != null) { - conn.startSending(this); - } - } - - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append("id=").append(ser) - .append(",rs=").append(getState()) - .append(")"); - return sb.toString(); - } - - - void trace(String msg) { - if(debug) { - log.info(this.toString() + " " + msg + " done=" + doneCallbackCalled); - } - } - - @Override - public void waitFlush(long timeMs) throws IOException { - if (getOut().getBufferCount() == 0) { - return; - } - flushLock.waitSignal(timeMs); - } - - public HttpChannel setConnection(HttpConnection conn) { - this.conn = conn; - return this; - } - - /** - * Normalize URI. - *

    - * This method normalizes "\", "//", "/./" and "/../". This method will - * return false when trying to go above the root, or if the URI contains - * a null byte. - * - * @param uriMB URI to be normalized, will be modified - */ - public static boolean normalize(BBuffer uriBC) { - - byte[] b = uriBC.array(); - int start = uriBC.getStart(); - int end = uriBC.getEnd(); - - // URL * is acceptable - if ((end - start == 1) && b[start] == (byte) '*') - return true; - - if (b[start] != '/') { - // TODO: http://.... URLs - return true; - } - - int pos = 0; - int index = 0; - - // Replace '\' with '/' - // Check for null byte - for (pos = start; pos < end; pos++) { - if (b[pos] == (byte) '\\') - b[pos] = (byte) '/'; - if (b[pos] == (byte) 0) - return false; - } - - // The URL must start with '/' - if (b[start] != (byte) '/') { - return false; - } - - // Replace "//" with "/" - for (pos = start; pos < (end - 1); pos++) { - if (b[pos] == (byte) '/') { - while ((pos + 1 < end) && (b[pos + 1] == (byte) '/')) { - copyBytes(b, pos, pos + 1, end - pos - 1); - end--; - } - } - } - - // If the URI ends with "/." or "/..", then we append an extra "/" - // Note: It is possible to extend the URI by 1 without any side effect - // as the next character is a non-significant WS. - if (((end - start) >= 2) && (b[end - 1] == (byte) '.')) { - if ((b[end - 2] == (byte) '/') - || ((b[end - 2] == (byte) '.') - && (b[end - 3] == (byte) '/'))) { - b[end] = (byte) '/'; - end++; - } - } - - uriBC.setEnd(end); - - index = 0; - - // Resolve occurrences of "/./" in the normalized path - while (true) { - index = uriBC.indexOf("/./", 0, 3, index); - if (index < 0) - break; - copyBytes(b, start + index, start + index + 2, - end - start - index - 2); - end = end - 2; - uriBC.setEnd(end); - } - - index = 0; - - // Resolve occurrences of "/../" in the normalized path - while (true) { - index = uriBC.indexOf("/../", 0, 4, index); - if (index < 0) - break; - // Prevent from going outside our context - if (index == 0) - return false; - int index2 = -1; - for (pos = start + index - 1; (pos >= 0) && (index2 < 0); pos --) { - if (b[pos] == (byte) '/') { - index2 = pos; - } - } - copyBytes(b, start + index2, start + index + 3, - end - start - index - 3); - end = end + index2 - index - 3; - uriBC.setEnd(end); - index = index2; - } - - //uriBC.setBytes(b, start, end); - uriBC.setEnd(end); - return true; - - } - - /** - * Copy an array of bytes to a different position. Used during - * normalization. - */ - private static void copyBytes(byte[] b, int dest, int src, int len) { - for (int pos = 0; pos < len; pos++) { - b[pos + dest] = b[pos + src]; - } - } - - - /** - * This method will be called when the http headers have been received - - * the body may or may not be available. - * - * In server mode this is equivalent with a servlet request. - * This is also called for http client, when the response headers - * are received. - * - * TODO: rename it to HttMessageReceived or something similar. - */ - public static interface HttpService { - void service(HttpRequest httpReq, HttpResponse httpRes) throws IOException; - } - - /** - * Called when both request and response bodies have been sent/ - * received. After this call the HttpChannel will be disconnected - * from the http connection, which can be used for other requests. - */ - public static interface RequestCompleted { - void handle(HttpChannel data, Object extraData) throws IOException; - } - - Runnable dispatcherRunnable = new Runnable() { - @Override - public void run() { - getConnector().getDispatcher().runService(HttpChannel.this); - } - }; - - -} \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpClient.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpClient.java deleted file mode 100644 index 61d60f59d66b..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpClient.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import org.apache.tomcat.lite.io.SocketConnector; -import org.apache.tomcat.lite.io.SslProvider; -import org.apache.tomcat.lite.io.jsse.JsseSslProvider; - -/** - * Entry point for http client code. - * - * ( initial version after removing 'integration', will add settings, - * defaults, helpers ) - */ -public class HttpClient { - static SslProvider sslConC = new JsseSslProvider(); - - public synchronized static HttpConnector newClient() { - return new HttpConnector(new SocketConnector()).withSsl(sslConC); - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpConnectionPool.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpConnectionPool.java deleted file mode 100644 index 447935475de8..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpConnectionPool.java +++ /dev/null @@ -1,399 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.http.HttpConnector.HttpConnection; -import org.apache.tomcat.lite.io.IOChannel; -import org.apache.tomcat.lite.io.IOConnector; - -/** - * - Holds references to all active and kept-alive connections. - * - makes decisions on accepting more connections, closing old - * connections, etc - * - */ -public class HttpConnectionPool { - // TODO: add timeouts, limits per host/total, expire old entries - - public static interface HttpConnectionPoolEvents { - public void newTarget(RemoteServer host); - - public void targetRemoved(RemoteServer host); - - public void newConnection(RemoteServer host, HttpConnection con); - public void closedConnection(RemoteServer host, HttpConnection con); - } - - /** - * Connections for one remote host. - * This should't be restricted by IP:port or even hostname, - * for example if a server has multiple IPs or LB replicas - any would work. - */ - public static class RemoteServer { - // all access sync on RemoteServer - private SpdyConnection spdy; - - // all access sync on RemoteServer - private ArrayList connections - = new ArrayList(); - - Queue pending = new LinkedList(); - - - // TODO: setter, default from connector - private int maxConnections = 20; - - AtomicInteger activeRequests = new AtomicInteger(); - AtomicInteger totalRequests = new AtomicInteger(); - private volatile long lastActivity; - - public String target; - - public synchronized List getConnections() - { - return new ArrayList(connections); - } - - public synchronized Collection getActives() { - ArrayList actives = new ArrayList(); - for (Http11Connection con: connections) { - if (con.activeHttp != null) { - actives.add(con.activeHttp); - } - } - if (spdy != null) { - actives.addAll(spdy.getActives()); - } - - return actives; - } - - public synchronized void touch() { - lastActivity = System.currentTimeMillis(); - } - } - - private HttpConnectionPoolEvents poolEvents; - - private static Logger log = Logger.getLogger("HttpConnector"); - - // visible for debugging - will be made private, with accessor - /** - * Map from client names to socket pools. - */ - public Map hosts = new HashMap(); - - // Statistics - public AtomicInteger waitingSockets = new AtomicInteger(); - public AtomicInteger closedSockets = new AtomicInteger(); - - public AtomicInteger hits = new AtomicInteger(); - public AtomicInteger misses = new AtomicInteger(); - public AtomicInteger queued = new AtomicInteger(); - - public AtomicInteger activeRequests = new AtomicInteger(); - - private static boolean debug = false; - HttpConnector httpConnector; - - public HttpConnectionPool(HttpConnector httpConnector) { - this.httpConnector = httpConnector; - } - - public int getTargetCount() { - return hosts.size(); - } - - public int getSocketCount() { - return waitingSockets.get(); - } - - public int getClosedSockets() { - return closedSockets.get(); - } - - public Set getKeepAliveTargets() { - return hosts.keySet(); - } - - public List getServers() { - return new ArrayList(hosts.values()); - } - - public void setEvents(HttpConnectionPoolEvents events) { - this.poolEvents = events; - } - /** - * Stop all cached connections. - */ - public void clear() throws IOException { - synchronized (hosts) { - int active = 0; - for (RemoteServer rs: hosts.values()) { - synchronized (rs) { - int hostActive = 0; - if (rs.spdy != null) { - if (rs.spdy.channels.size() == 0) { - rs.spdy.close(); - rs.spdy = null; - } else { - hostActive += rs.spdy.channels.size(); - } - } - for (Http11Connection con: rs.connections) { - if (con.activeHttp == null) { - con.close(); - } else { - hostActive++; - } - } - if (hostActive != rs.activeRequests.get()) { - log.warning("Active missmatch " + rs.target + " " + - hostActive + " " - + rs.activeRequests.get()); - rs.activeRequests.set(hostActive); - } - active += hostActive; - } - } - if (active != this.activeRequests.get()) { - log.warning("Active missmatch " + active + " " - + activeRequests.get()); - activeRequests.set(active); - } - } - } - - /** - * Stop all active and cached connections - * @throws IOException - */ - public void abort() throws IOException { - // TODO - clear(); - hosts.clear(); - } - - /** - * @param key host:port, or some other key if multiple hosts:ips - * are connected to equivalent servers ( LB ) - * @param httpCh - * @throws IOException - */ - public void send(HttpChannel httpCh) - throws IOException { - String target = httpCh.getTarget(); - HttpConnection con = null; - // TODO: check ssl on connection - now if a second request - // is received on a ssl connection - we just send it - boolean ssl = httpCh.getRequest().isSecure(); - - HttpConnectionPool.RemoteServer remoteServer = null; - synchronized (hosts) { - remoteServer = hosts.get(target); - if (remoteServer == null) { - remoteServer = new HttpConnectionPool.RemoteServer(); - remoteServer.target = target; - hosts.put(target, remoteServer); - } - } - - // TODO: remove old servers and connections - - // Temp magic - until a better negotiation is defined - boolean forceSpdy = "SPDY/1.0".equals(httpCh.getRequest().getProtocol()); - if (forceSpdy) { - // switch back the protocol - httpCh.getRequest().setProtocol("HTTP/1.1"); - } - - activeRequests.incrementAndGet(); - remoteServer.activeRequests.incrementAndGet(); - - // if we already have a spdy connection or explicitely - // requested. - if (forceSpdy || remoteServer.spdy != null) { - synchronized (remoteServer) { - if (remoteServer.spdy == null) { - remoteServer.spdy = new SpdyConnection(httpConnector, - remoteServer); - } - con = remoteServer.spdy; - } - - // Will be queued - multiple threads may try to send - // at the same time, and we need to queue anyways. - con.sendRequest(httpCh); - } else { - synchronized (remoteServer) { - Http11Connection hcon; - for (int i = 0; i < remoteServer.connections.size(); i++) { - hcon = (Http11Connection) remoteServer.connections.get(i); - if (hcon != null && hcon.activeHttp == null) { - hcon.beforeRequest(); // recycle - - hcon.activeHttp = httpCh; - con = hcon; - break; - } - } - if (con == null) { -// if (remoteServer.connections.size() > remoteServer.maxConnections) { -// remoteServer.pending.add(httpCh); -// queued.incrementAndGet(); -// if (debug) { -// log.info("Queue: " + target + " " + remoteServer.connections.size()); -// } -// return; -// } - hcon = new Http11Connection(httpConnector); - hcon.setTarget(target); - hcon.activeHttp = httpCh; - hcon.remoteHost = remoteServer; - remoteServer.connections.add(hcon); - con = hcon; - } - } - - - // we got a connection - make sure we're connected - http11ConnectOrSend(httpCh, target, con, ssl); - } - } - - private void http11ConnectOrSend(HttpChannel httpCh, String target, - HttpConnection con, boolean ssl) throws IOException { - httpCh.setConnection(con); - - if (con.isOpen()) { - hits.incrementAndGet(); -// if (debug) { -// log.info("HTTP_CONNECT: Reuse connection " + target + " " + this); -// } - con.sendRequest(httpCh); - } else { - misses.incrementAndGet(); - if (debug) { - log.info("HTTP_CONNECT: Start connection " + target + " " + this); - } - httpConnect(httpCh, target, ssl, - (Http11Connection) con); - } - } - - void httpConnect(HttpChannel httpCh, String target, - boolean ssl, IOConnector.ConnectedCallback cb) - throws IOException { - if (debug) { - log.info("HTTP_CONNECT: New connection " + target); - } - String[] hostPort = target.split(":"); - - int targetPort = ssl ? 443 : 80; - if (hostPort.length > 1) { - targetPort = Integer.parseInt(hostPort[1]); - } - - httpConnector.getIOConnector().connect(hostPort[0], targetPort, - cb); - } - - public void afterRequest(HttpChannel http, HttpConnection con, - boolean keepAlive) - throws IOException { - activeRequests.decrementAndGet(); - if (con.remoteHost != null) { - con.remoteHost.touch(); - con.remoteHost.activeRequests.decrementAndGet(); - } - if (con.serverMode) { - afterServerRequest(con, keepAlive); - } else { - afterClientRequest(con); - } - } - - private void afterClientRequest(HttpConnection con) - throws IOException { - RemoteServer remoteServer = con.remoteHost; - HttpChannel req = null; - - // If we have pending requests ( because too many active limit ), pick - // one and send it. - synchronized (remoteServer) { - // If closed - we can remove the object - or - // let a background thread do it, in case it's needed - // again. - if (remoteServer.pending.size() == 0) { - con.activeHttp = null; - return; - } - req = remoteServer.pending.remove(); - con.activeHttp = req; - if (debug) { - log.info("After request: send pending " + remoteServer.pending.size()); - } - } - - http11ConnectOrSend(req, con.getTarget().toString(), - con, req.getRequest().isSecure()); - } - - RemoteServer serverPool = new RemoteServer(); - - public void afterServerRequest(HttpConnection con, boolean keepAlive) - throws IOException { - con.activeHttp = null; - if (!keepAlive) { - synchronized (serverPool) { - // I could also reuse the object. - serverPool.connections.remove(con); - } - } - } - - public HttpConnection accepted(IOChannel accepted) { - Http11Connection con = new Http11Connection(httpConnector); - con.remoteHost = serverPool; - synchronized (serverPool) { - serverPool.connections.add(con); - } - return con; - } - - - // Called by handleClosed - void stopKeepAlive(IOChannel schannel) { - CharSequence target = schannel.getTarget(); - HttpConnectionPool.RemoteServer remoteServer = null; - synchronized (hosts) { - remoteServer = hosts.get(target); - if (remoteServer == null) { - return; - } - } - synchronized (remoteServer) { - if (remoteServer.connections.remove(schannel)) { - waitingSockets.decrementAndGet(); - if (remoteServer.connections.size() == 0) { - hosts.remove(target); - } - } - } - } - - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpConnector.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpConnector.java deleted file mode 100644 index 722dda2287a8..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpConnector.java +++ /dev/null @@ -1,514 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Timer; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.http.HttpChannel.HttpService; -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.DumpChannel; -import org.apache.tomcat.lite.io.IOBuffer; -import org.apache.tomcat.lite.io.IOChannel; -import org.apache.tomcat.lite.io.IOConnector; -import org.apache.tomcat.lite.io.SslProvider; -import org.apache.tomcat.lite.io.IOConnector.DataReceivedCallback; - -/** - * Manages HttpChannels and associated socket pool. - * - * - * @author Costin Manolache - */ -public class HttpConnector { - - public static interface HttpChannelEvents { - /** HttpChannel object created. It'll be used many times. - * @throws IOException - */ - public void onCreate(HttpChannel ch, HttpConnector con) throws IOException; - - /** - * HttpChannel object no longer needed, out of pool. - * @throws IOException - */ - public void onDestroy(HttpChannel ch, HttpConnector con) throws IOException; - } - - private static Logger log = Logger.getLogger("HttpConnector"); - - /** - * Cache HttpChannel/request/buffers - */ - private int maxHttpPoolSize = 50; - - /** - * Max number of connections to keep alive. - * Each connection holds a header buffer and the socket. - * ( we could skip the header buffer ) - */ - private int maxSocketPoolSize = 500; // 10000; - - private int keepAliveTimeMs = 300000; - - private List httpChannelPool = new ArrayList(); - - protected IOConnector ioConnector; - - // for https connections - protected SslProvider sslProvider; - - boolean debugHttp = false; - boolean debug = false; - - boolean clientKeepAlive = true; - boolean serverKeepAlive = true; - - HttpChannelEvents httpEvents; - - public AtomicInteger inUse = new AtomicInteger(); - public AtomicInteger newHttpChannel = new AtomicInteger(); - public AtomicInteger totalHttpChannel = new AtomicInteger(); - public AtomicInteger totalClientHttpChannel = new AtomicInteger(); - public AtomicInteger recycledChannels = new AtomicInteger(); - public AtomicInteger reusedChannels = new AtomicInteger(); - - public HttpConnectionPool cpool = new HttpConnectionPool(this); - - // Host + context mapper. - Dispatcher dispatcher; - protected HttpService defaultService; - int port = 8080; - - private Timer timer; - - boolean compression = true; - - boolean serverSSL = false; - - private static Timer defaultTimer = new Timer(true); - - public HttpConnector(IOConnector ioConnector) { - this.ioConnector = ioConnector; - dispatcher = new Dispatcher(); - defaultService = dispatcher; - if (ioConnector != null) { - timer = ioConnector.getTimer(); - } else { - // tests - timer = defaultTimer; - } - } - - protected HttpConnector() { - this(null); - } - - public Dispatcher getDispatcher() { - return dispatcher; - } - - public HttpConnectionPool getConnectionPool() { - return cpool; - } - - public HttpConnector withIOConnector(IOConnector selectors) { - ioConnector = selectors; - return this; - } - - public void setDebug(boolean b) { - this.debug = b; - } - - public void setDebugHttp(boolean b) { - this.debugHttp = b; - } - - public HttpConnector withSsl(SslProvider ssl) { - sslProvider = ssl; - return this; - } - - HttpConnector setServerSsl(boolean b) { - serverSSL = b; - return this; - } - - public SslProvider getSslProvider() { - return sslProvider; - } - - /** - * Allow or disable compression for this connector. - * Compression is enabled by default. - */ - public HttpConnector setCompression(boolean b) { - this.compression = b; - return this; - } - - public void setClientKeepAlive(boolean b) { - this.clientKeepAlive = b; - } - - public void setServerKeepAlive(boolean b) { - this.serverKeepAlive = b; - } - - public boolean isDebug() { - return debug; - } - - public boolean isClientKeepAlive() { - return clientKeepAlive; - } - - public boolean isServerKeepAlive() { - return serverKeepAlive; - } - - public int getInUse() { - return inUse.get(); - } - - public int getMaxHttpPoolSize() { - return maxHttpPoolSize; - } - - public void setMaxHttpPoolSize(int maxHttpPoolSize) { - this.maxHttpPoolSize = maxHttpPoolSize; - } - - public void setOnCreate(HttpChannelEvents callback) { - httpEvents = callback; - } - - /** - * Override to create customized client/server connections. - * - * @return - * @throws IOException - */ - protected HttpChannel create() throws IOException { - HttpChannel res = new HttpChannel(); - newHttpChannel.incrementAndGet(); - res.setConnector(this); - if (httpEvents != null) { - httpEvents.onCreate(res, this); - } - if (debugHttp) { - res.debug = debugHttp; - } - return res; - } - - public HttpChannel get(String host, int port) throws IOException { - HttpChannel http = get(false); - http.setTarget(host + ":" + port); - return http; - } - - public HttpChannel getServer() { - try { - return get(true); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } - } - - public HttpRequest request(String host, int port) throws IOException { - HttpChannel http = get(false); - http.setTarget(host + ":" + port); - return http.getRequest(); - - } - - public HttpRequest request(CharSequence urlString) throws IOException { - return get(urlString).getRequest(); - } - - /** - * Get an existing AsyncHttp object. Since it uses many buffers and - * objects - it's more efficient to pool it. - * - * release will return the object to the pool. - * @throws IOException - */ - public HttpChannel get(CharSequence urlString) throws IOException { - URL url = new URL(urlString.toString()); - String host = url.getHost(); - int port = url.getPort(); - boolean secure = "http".equals(url.getAuthority()); - if (port == -1) { - port = secure ? 443: 80; - } - // TODO: insert SSL filter - HttpChannel http = get(false); - http.setTarget(host + ":" + port); - String path = url.getFile(); // path + qry - // TODO: query string - http.getRequest().requestURI().set(path); - return http; - } - - protected HttpChannel get(boolean server) throws IOException { - HttpChannel processor = null; - synchronized (httpChannelPool) { - int cnt = httpChannelPool.size(); - if (cnt > 0) { - processor = httpChannelPool.remove(cnt - 1); - } - } - boolean reuse = false; - totalHttpChannel.incrementAndGet(); - if (!server) { - totalClientHttpChannel.incrementAndGet(); - } - if (processor == null) { - processor = create(); - } else { - reuse = true; - reusedChannels.incrementAndGet(); - processor.release = false; - } - processor.serverMode(server); - if (debug) { - log.info((reuse ? "REUSE ": "Create ") + - (server? " S" : "") - + " id=" + processor.ser + - " " + processor + - " size=" + httpChannelPool.size()); - } - - processor.setConnector(this); - inUse.incrementAndGet(); - return processor; - } - - protected void returnToPool(HttpChannel http) throws IOException { - inUse.decrementAndGet(); - recycledChannels.incrementAndGet(); - int size = 0; - boolean pool = false; - - http.recycle(); - http.setConnection(null); - http.setConnector(null); - - // No more data - release the object - synchronized (httpChannelPool) { - size = httpChannelPool.size(); - if (httpChannelPool.contains(http)) { - log.severe("Duplicate element in pool !"); - } else if (size < maxHttpPoolSize) { - httpChannelPool.add(http); - pool = true; - } - } - - if (!pool && httpEvents != null) { - httpEvents.onDestroy(http, this); - } - if (debug) { - log.info((pool ? "Return " : "Destroy ") - + http.getTarget() + " obj=" + - http + " size=" + size); - } - } - - - public IOConnector getIOConnector() { - return ioConnector; - } - - - public void setHttpService(HttpService s) { - defaultService = s; - } - - public void start() throws IOException { - if (ioConnector != null) { - ioConnector.acceptor(new AcceptorCallback(), - Integer.toString(port), null); - } - } - - /** - * - * TODO: only clean our state and sockets we listen on. - * - */ - public void stop() { - if (ioConnector != null) { - ioConnector.stop(); - } - } - - protected void connectAndSend(HttpChannel httpCh) throws IOException { - cpool.send(httpCh); - - } - - private class AcceptorCallback implements IOConnector.ConnectedCallback { - @Override - public void handleConnected(IOChannel accepted) throws IOException { - handleAccepted(accepted); - } - } - - public HttpConnection handleAccepted(IOChannel accepted) throws IOException { - // TODO: reuse - HttpConnection shttp = cpool.accepted(accepted); - shttp.serverMode = true; - - IOChannel head = accepted; - IOChannel ch; - - String id = null; - if (debugHttp) { - id = port + "-" + accepted.getFirst().getAttribute(IOChannel.ATT_REMOTE_PORT); - log.info("Accepted " + id); - head = DumpChannel.wrap("SSL-" + id, head); - } - - // TODO: seems cleaner this way... - if (serverSSL) { - ch = sslProvider.serverChannel(head); - head.setHead(ch); - head = ch; - - if (debugHttp) { - head = DumpChannel.wrap("CLEAR-" + id, head); - } - } - - shttp.setSink(head); - - // Will read any data in the channel, notify data available up - accepted.handleReceived(accepted); - return shttp; - } - - public HttpConnector setPort(int port2) { - this.port = port2; - return this; - } - - /** - * Actual HTTP/1.1 wire protocol. - * - */ - public static abstract class HttpConnection extends IOChannel - implements DataReceivedCallback - { - protected HttpConnector httpConnector; - protected boolean serverMode = false; - - protected BBuffer headRecvBuf = BBuffer.allocate(8192); - protected CompressFilter compress = new CompressFilter(); - - protected boolean secure = false; - - protected HttpConnectionPool.RemoteServer remoteHost; - // If set, the connection is in use ( active ) - // null == keep alive. Changes synchronized on remoteHost - // before/after request - protected HttpChannel activeHttp; - - @Override - public final void handleReceived(IOChannel ch) throws IOException { - int before = ch.getIn().available(); - dataReceived(ch.getIn()); - } - - protected HttpChannel checkHttpChannel() throws IOException { - return null; - } - - /** - * Called before a new request is sent, on a channel that is - * reused. - */ - public void beforeRequest() { - } - - public void setSink(IOChannel ch) throws IOException { - this.net = ch; - ch.setDataReceivedCallback(this); - ch.setDataFlushedCallback(this); - // we may have data in the buffer; - handleReceived(ch); - } - - - /** - * Incoming data. - */ - public abstract void dataReceived(IOBuffer iob) throws IOException; - - /** - * Framing error, client interrupt, etc. - */ - public void abort(HttpChannel http, String t) throws IOException { - } - - protected void sendRequest(HttpChannel http) - throws IOException { - } - - protected void sendResponseHeaders(HttpChannel http) - throws IOException { - } - - public void startSending(HttpChannel http) throws IOException { - } - - @Override - public IOBuffer getIn() { - return net == null ? null : net.getIn(); - } - - @Override - public IOBuffer getOut() { - return net == null ? null : net.getOut(); - } - - @Override - public void startSending() throws IOException { - } - - /** Called when the outgoing stream is closed: - * - by an explicit call to close() - * - when all content has been sent. - */ - protected void outClosed(HttpChannel http) throws IOException { - } - - /** - * Called by HttpChannel when both input and output are fully - * sent/received. When this happens the request is no longer associated - * with the Connection, and the connection can be re-used. - * - * The channel can still be used to access the retrieved data that may - * still be buffered until HttpChannel.release() is called. - * - * This method will be called only once, for both succesful and aborted - * requests. - */ - protected abstract void endSendReceive(HttpChannel httpChannel) throws IOException; - - public void withExtraBuffer(BBuffer received) { - return; - } - - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpMessage.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpMessage.java deleted file mode 100644 index cfeac7e0b879..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpMessage.java +++ /dev/null @@ -1,508 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Locale; -import java.util.TimeZone; - -import org.apache.tomcat.lite.http.HttpChannel.RequestCompleted; -import org.apache.tomcat.lite.http.HttpConnector.HttpConnection; -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.BufferedIOReader; -import org.apache.tomcat.lite.io.CBuffer; -import org.apache.tomcat.lite.io.FastHttpDateFormat; -import org.apache.tomcat.lite.io.IOBuffer; -import org.apache.tomcat.lite.io.IOInputStream; -import org.apache.tomcat.lite.io.IOOutputStream; -import org.apache.tomcat.lite.io.IOReader; -import org.apache.tomcat.lite.io.IOWriter; -import org.apache.tomcat.lite.io.UrlEncoding; - - -/** - * Basic Http request or response message. - * - * Because the HttpChannel can be used for both client and - * server, and to make proxy and other code simpler - the request - * and response are represented by the same class. - * - * @author Costin Manolache - */ -public abstract class HttpMessage { - - public static enum State { - HEAD, - BODY_DATA, - DONE - } - - /** - * Raw, off-the-wire message. - */ - public static class HttpMessageBytes { - BBuffer head1 = BBuffer.wrapper(); - BBuffer head2 = BBuffer.wrapper(); - BBuffer proto = BBuffer.wrapper(); - - BBuffer query = BBuffer.wrapper(); - - List headerNames = new ArrayList(); - List headerValues = new ArrayList(); - - int headerCount; - - public BBuffer status() { - return head1; - } - - public BBuffer method() { - return head1; - } - - public BBuffer url() { - return head2; - } - - public BBuffer query() { - return query; - } - - public BBuffer protocol() { - return proto; - } - - public BBuffer message() { - return head2; - } - - public int addHeader() { - if (headerCount >= headerNames.size()) { - // make space for the new header. - headerNames.add(BBuffer.wrapper()); - headerValues.add(BBuffer.wrapper()); - } - return headerCount++; - } - - public BBuffer getHeaderName(int i) { - if (i >= headerNames.size()) { - return null; - } - return headerNames.get(i); - } - - public BBuffer getHeaderValue(int i) { - if (i >= headerValues.size()) { - return null; - } - return headerValues.get(i); - } - - public void recycle() { - head1.recycle(); - head2.recycle(); - proto.recycle(); - query.recycle(); - headerCount = 0; - for (int i = 0; i < headerCount; i++) { - headerNames.get(i).recycle(); - headerValues.get(i).recycle(); - } - } - } - - protected static final TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT"); - - private HttpMessageBytes msgBytes = new HttpMessageBytes(); - - protected HttpMessage.State state = HttpMessage.State.HEAD; - - protected HttpChannel httpCh; - - protected MultiMap headers = new MultiMap().insensitive(); - - protected CBuffer protoMB; - - // Cookies - protected boolean cookiesParsed = false; - - // TODO: cookies parsed when headers are added ! - protected ArrayList cookies; - protected ArrayList cookiesCache; - - protected UrlEncoding urlDecoder = new UrlEncoding(); - protected String charEncoding; - - IOReader reader; - BufferedIOReader bufferedReader; - HttpWriter writer; - IOWriter conv; - - IOOutputStream out; - private IOInputStream in; - - boolean commited; - - protected IOBuffer body; - - long contentLength = -2; - boolean chunked; - - /** - * The set of SimpleDateFormat formats to use in getDateHeader(). - * - * Notice that because SimpleDateFormat is not thread-safe, we can't - * declare formats[] as a static variable. - */ - protected SimpleDateFormat formats[] = null; - - - BBuffer clBuffer = BBuffer.allocate(64); - - public HttpMessage(HttpChannel httpCh) { - this.httpCh = httpCh; - - out = new IOOutputStream(httpCh.getOut(), httpCh); - conv = new IOWriter(httpCh); - writer = new HttpWriter(this, out, conv); - - in = new IOInputStream(httpCh, httpCh.getIOTimeout()); - - reader = new IOReader(httpCh.getIn()); - bufferedReader = new BufferedIOReader(reader); - - cookies = new ArrayList(); - cookiesCache = new ArrayList(); - protoMB = CBuffer.newInstance(); - } - - public void addHeader(String name, String value) { - getMimeHeaders().addValue(name).set(value); - } - - public void setHeader(String name, String value) { - getMimeHeaders().setValue(name).set(value); - } - - public void setMimeHeaders(MultiMap resHeaders) { - this.headers = resHeaders; - } - - public String getHeader(String name) { - CBuffer cb = headers.getHeader(name); - return (cb == null) ? null : cb.toString(); - } - - public MultiMap getMimeHeaders() { - return headers; - } - - /** - * Return the value of the specified date header, if any; otherwise - * return -1. - * - * @param name Name of the requested date header - * - * @exception IllegalArgumentException if the specified header value - * cannot be converted to a date - */ - public long getDateHeader(String name) { - - String value = getHeader(name); - if (value == null) - return (-1L); - if (formats == null) { - formats = new SimpleDateFormat[] { - new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US), - new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US), - new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) - }; - formats[0].setTimeZone(GMT_ZONE); - formats[1].setTimeZone(GMT_ZONE); - formats[2].setTimeZone(GMT_ZONE); - } - - // Attempt to convert the date header in a variety of formats - long result = FastHttpDateFormat.parseDate(value, formats); - if (result != (-1L)) { - return result; - } - throw new IllegalArgumentException(value); - - } - - - public Collection getHeaderNames() { - - MultiMap headers = getMimeHeaders(); - int n = headers.size(); - ArrayList result = new ArrayList(); - for (int i = 0; i < n; i++) { - result.add(headers.getName(i).toString()); - } - return result; - } - - public boolean containsHeader(String name) { - return headers.getHeader(name) != null; - } - - public void setContentLength(long len) { - contentLength = len; - clBuffer.setLong(len); - setCLHeader(); - } - - public void setContentLength(int len) { - contentLength = len; - clBuffer.setLong(len); - setCLHeader(); - } - - private void setCLHeader() { - MultiMap.Entry clB = headers.setEntry("content-length"); - clB.valueB = clBuffer; - } - - public long getContentLengthLong() { - if (contentLength == -2) { - CBuffer clB = headers.getHeader("content-length"); - contentLength = (clB == null) ? - -1 : clB.getLong(); - } - return contentLength; - } - - public int getContentLength() { - long length = getContentLengthLong(); - - if (length < Integer.MAX_VALUE) { - return (int) length; - } - return -1; - } - - public String getContentType() { - CBuffer contentTypeMB = headers.getHeader("content-type"); - if (contentTypeMB == null) { - return null; - } - return contentTypeMB.toString(); - } - - public void setContentType(String contentType) { - CBuffer clB = getMimeHeaders().getHeader("content-type"); - if (clB == null) { - setHeader("Content-Type", contentType); - } else { - clB.set(contentType); - } - } - - /** - * Get the character encoding used for this request. - * Need a field because it can be overriden. Used to construct the - * Reader. - */ - public String getCharacterEncoding() { - if (charEncoding != null) - return charEncoding; - - charEncoding = ContentType.getCharsetFromContentType(getContentType()); - return charEncoding; - } - - private static final String DEFAULT_ENCODING = "ISO-8859-1"; - - public String getEncoding() { - String charEncoding = getCharacterEncoding(); - if (charEncoding == null) { - return DEFAULT_ENCODING; - } else { - return charEncoding; - } - } - - public void setCharacterEncoding(String enc) - throws UnsupportedEncodingException { - this.charEncoding = enc; - } - - - public void recycle() { - commited = false; - headers.recycle(); - protoMB.set("HTTP/1.1"); - for (int i = 0; i < cookies.size(); i++) { - cookies.get(i).recycle(); - } - cookies.clear(); - charEncoding = null; - bufferedReader.recycle(); - - writer.recycle(); - conv.recycle(); - - contentLength = -2; - chunked = false; - clBuffer.recycle(); - state = State.HEAD; - cookiesParsed = false; - getMsgBytes().recycle(); - - } - - - public String getProtocol() { - return protoMB.toString(); - } - - public void setProtocol(String proto) { - protoMB.set(proto); - } - - public CBuffer protocol() { - return protoMB; - } - - public ServerCookie getCookie(String name) { - for (ServerCookie sc: getServerCookies()) { - if (sc.getName().equalsIgnoreCase(name)) { - return sc; - } - } - return null; - } - - public List getServerCookies() { - if (!cookiesParsed) { - cookiesParsed = true; - ServerCookie.processCookies(cookies, cookiesCache, getMsgBytes()); - } - return cookies; - } - - public UrlEncoding getURLDecoder() { - return urlDecoder; - } - - public boolean isCommitted() { - return commited; - } - - public void setCommitted(boolean b) { - commited = b; - } - - public HttpChannel getHttpChannel() { - return httpCh; - } - - public IOBuffer getBody() { - return body; - } - - void setBody(IOBuffer body) { - this.body = body; - } - - public void flush() throws IOException { - httpCh.startSending(); - } - - // not servlet input stream - public IOInputStream getBodyInputStream() { - return in; - } - - public InputStream getInputStream() { - return in; - } - - public IOOutputStream getOutputStream() { - return out; - } - - public IOOutputStream getBodyOutputStream() { - return out; - } - - public IOReader getBodyReader() throws IOException { - reader.setEncoding(getCharacterEncoding()); - return reader; - } - - public BBuffer readAll(BBuffer chunk, long to) throws IOException { - return httpCh.readAll(chunk, to); - } - - public BBuffer readAll() throws IOException { - return httpCh.readAll(null, httpCh.ioTimeout); - } - - /** - * We're done with this object, it can be recycled. - * Any use after this should throw exception or affect an - * unrelated request. - */ - public void release() throws IOException { - httpCh.release(); - } - - public void setCompletedCallback(RequestCompleted doneAllCallback) throws IOException { - httpCh.setCompletedCallback(doneAllCallback); - } - - public void setReadTimeout(long to) { - reader.setTimeout(to); - } - - /** - * Returns a buffered reader. - */ - public BufferedReader getReader() throws IOException { - reader.setEncoding(getCharacterEncoding()); - return bufferedReader; - } - - public PrintWriter getWriter() { - return new PrintWriter(getBodyWriter()); - } - - public HttpWriter getBodyWriter() { - conv.setEncoding(getCharacterEncoding()); - return writer; - } - - - protected void processMimeHeaders() { - for (int idx = 0; idx < getMsgBytes().headerCount; idx++) { - BBuffer nameBuf = getMsgBytes().getHeaderName(idx); - BBuffer valBuf = getMsgBytes().getHeaderValue(idx); - - MultiMap.Entry header = headers.addEntry(nameBuf); - header.valueB = valBuf; - } - } - - - protected abstract void processReceivedHeaders() throws IOException; - - public abstract boolean hasBody(); - - public HttpMessageBytes getMsgBytes() { - // TODO: serialize if not set - return msgBytes; - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpRequest.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpRequest.java deleted file mode 100644 index 3ec8477b0aa3..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpRequest.java +++ /dev/null @@ -1,1019 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.io.IOException; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; - -import org.apache.tomcat.lite.http.HttpChannel.HttpService; -import org.apache.tomcat.lite.http.MultiMap.Entry; -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.CBuffer; -import org.apache.tomcat.lite.io.Hex; -import org.apache.tomcat.lite.io.IOBuffer; -import org.apache.tomcat.lite.io.IOChannel; -import org.apache.tomcat.lite.io.IOReader; -import org.apache.tomcat.lite.io.IOWriter; -import org.apache.tomcat.lite.io.UrlEncoding; - -public class HttpRequest extends HttpMessage { - public static final String DEFAULT_CHARACTER_ENCODING="ISO-8859-1"; - - protected CBuffer schemeMB; - protected CBuffer methodMB; - protected CBuffer remoteAddrMB; - protected CBuffer remoteHostMB; - protected int remotePort; - - protected CBuffer localNameMB; - protected CBuffer localAddrMB; - protected int localPort = -1; - - // Host: header, or default:80 - protected CBuffer serverNameMB; - protected int serverPort = -1; - - - // ==== Derived fields, computed after request is received === - - protected CBuffer requestURI; - protected CBuffer queryMB; - - protected BBuffer decodedUri = BBuffer.allocate(); - protected CBuffer decodedUriMB; - - // Decoded query - protected MultiMap parameters; - - boolean parametersParsed = false; - - protected IOWriter charEncoder = new IOWriter(null); - protected IOReader charDecoder = new IOReader(null); - protected UrlEncoding urlEncoding = new UrlEncoding(); - - // Reference to 'real' request object - // will not be recycled - public Object nativeRequest; - public Object wrapperRequest; - - boolean ssl = false; - - boolean async = false; - - CBuffer requestURL = CBuffer.newInstance(); - - private Map attributes = new HashMap(); - - /** - * Mapping data. - */ - protected MappingData mappingData = new MappingData(); - - - HttpRequest(HttpChannel httpCh) { - super(httpCh); - decodedUriMB = CBuffer.newInstance(); - requestURI = CBuffer.newInstance(); - queryMB = CBuffer.newInstance(); - serverNameMB = CBuffer.newInstance(); - - parameters = new MultiMap(); - - schemeMB = - CBuffer.newInstance(); - methodMB = CBuffer.newInstance(); - initRemote(); - } - - protected void initRemote() { - remoteAddrMB = CBuffer.newInstance(); - localNameMB = CBuffer.newInstance(); - remoteHostMB = CBuffer.newInstance(); - localAddrMB = CBuffer.newInstance(); - } - - public void recycle() { - super.recycle(); - schemeMB.recycle(); - methodMB.set("GET"); - requestURI.recycle(); - requestURL.recycle(); - queryMB.recycle(); - decodedUriMB.recycle(); - - parameters.recycle(); - remoteAddrMB.recycle(); - remoteHostMB.recycle(); - parametersParsed = false; - ssl = false; - async = false; - asyncTimeout = -1; - charEncoder.recycle(); - - localPort = -1; - remotePort = -1; - localAddrMB.recycle(); - localNameMB.recycle(); - - serverPort = -1; - serverNameMB.recycle(); - decodedUri.recycle(); - decodedQuery.recycle(); - } - - public Object getAttribute(String name) { - return attributes.get(name); - } - - public void setAttribute(String name, Object o) { - if (o == null) { - attributes.remove(name); - } else { - attributes.put(name, o); - } - } - // getAttributeNames not supported - - public Map attributes() { - return attributes; - } - - - public CBuffer method() { - return methodMB; - } - - public String getMethod() { - return methodMB.toString(); - } - - public void setMethod(String method) { - methodMB.set(method); - } - - public CBuffer scheme() { - return schemeMB; - } - - public String getScheme() { - String scheme = schemeMB.toString(); - if (scheme == null) { - return "http"; - } - return scheme; - } - - public void setScheme(String s) { - schemeMB.set(s); - } - - public MappingData getMappingData() { - return (mappingData); - } - - /** - * Return the portion of the request URI used to select the Context - * of the Request. - */ - public String getContextPath() { - return (getMappingData().contextPath.toString()); - } - - public String getPathInfo() { - CBuffer pathInfo = getMappingData().pathInfo; - if (pathInfo.length() == 0) { - return null; - } - return (getMappingData().pathInfo.toString()); - } - - /** - * Return the portion of the request URI used to select the servlet - * that will process this request. - */ - public String getServletPath() { - return (getMappingData().wrapperPath.toString()); - } - - /** - * Parse query parameters - but not POST body. - * - * If you don't call this method, getParameters() will - * also read the body for POST with x-www-url-encoded - * mime type. - */ - public void parseQueryParameters() { - parseQuery(); - } - - /** - * Explicitely parse the body, adding the parameters to - * those from the query ( if already parsed ). - * - * By default servlet mode ( both query and body ) is used. - */ - public void parsePostParameters() { - parseBody(); - } - - MultiMap getParameters() { - if (!parametersParsed) { - parseQuery(); - parseBody(); - } - return parameters; - } - - public Enumeration getParameterNames() { - return getParameters().names(); - } - - /** - * Expensive, creates a copy on each call. - * @param name - * @return - */ - public String[] getParameterValues(String name) { - Entry entry = getParameters().getEntry(name); - if (entry == null) { - return null; - } - String[] values = new String[entry.values.size()]; - for (int j = 0; j < values.length; j++) { - values[j] = entry.values.get(j).toString(); - } - return values; - } - - // Inefficient - we convert from a different representation. - public Map getParameterMap() { - // we could allow 'locking' - I don't think this is - // a very useful optimization - Map map = new HashMap(); - for (int i = 0; i < getParameters().size(); i++) { - Entry entry = getParameters().getEntry(i); - if (entry == null) { - continue; - } - if (entry.key == null) { - continue; - } - String name = entry.key.toString(); - String[] values = new String[entry.values.size()]; - for (int j = 0; j < values.length; j++) { - values[j] = entry.values.get(j).toString(); - } - map.put(name, values); - } - return map; - } - - public String getParameter(String name) { - CharSequence value = getParameters().get(name); - if (value == null) { - return null; - } - return value.toString(); - } - - public void setParameter(String name, String value) { - getParameters().set(name, value); - } - - public void addParameter(String name, String values) { - getParameters().add(name, values); - } - - public CBuffer queryString() { - return queryMB; - } - - // TODO - void serializeParameters(Appendable cc) throws IOException { - int keys = parameters.size(); - boolean notFirst = false; - for (int i = 0; i < parameters.size(); i++) { - Entry entry = parameters.getEntry(i); - for (int j = 0; j < entry.values.size(); j++) { - // TODO: Uencode - if (notFirst) { - cc.append('&'); - } else { - notFirst = true; - } - cc.append(entry.key); - cc.append("="); - cc.append(entry.values.get(j).getValue()); - } - } - } - - public void setURI(CharSequence encoded) { - decodedUriMB.recycle(); - decodedUriMB.append(encoded); - // TODO: generate % encoding ( reverse of decodeRequest ) - } - - public CBuffer decodedURI() { - return decodedUriMB; - } - - public CBuffer requestURI() { - return requestURI; - } - - public CBuffer requestURL() { - CBuffer url = requestURL; - url.recycle(); - - String scheme = getScheme(); - int port = getServerPort(); - if (port < 0) - port = 80; // Work around java.net.URL bug - - url.append(scheme); - url.append("://"); - url.append(getServerName()); - if ((scheme.equals("http") && (port != 80)) - || (scheme.equals("https") && (port != 443))) { - url.append(':'); - url.append(port); - } - // Decoded !! - url.append(getRequestURI()); - - return (url); - - } - - /** - * Not decoded - %xx as in original. - * @return - */ - public String getRequestURI() { - return requestURI.toString(); - } - - public void setRequestURI(String encodedUri) { - requestURI.set(encodedUri); - } - - CBuffer getOrAdd(String name) { - CBuffer header = getMimeHeaders().getHeader(name); - if (header == null) { - header = getMimeHeaders().addValue(name); - } - return header; - } - - /** - * Set the Host header of the request. - * @param target - */ - public void setHost(String target) { - serverNameMB.recycle(); - getOrAdd("Host").set(target); - } - - // XXX - public CBuffer serverName() { - if (serverNameMB.length() == 0) { - parseHost(); - } - return serverNameMB; - } - - public String getServerName() { - return serverName().toString(); - } - - public void setServerName(String name) { - serverName().set(name); - } - - public int getServerPort() { - serverName(); - return serverPort; - } - - public void setServerPort(int serverPort ) { - this.serverPort=serverPort; - } - - public CBuffer remoteAddr() { - if (remoteAddrMB.length() == 0) { - HttpChannel asyncHttp = getHttpChannel(); - IOChannel iochannel = asyncHttp.getNet().getFirst(); - remoteAddrMB.set((String) - iochannel.getAttribute(IOChannel.ATT_REMOTE_ADDRESS)); - } - return remoteAddrMB; - } - - public CBuffer remoteHost() { - if (remoteHostMB.length() == 0) { - HttpChannel asyncHttp = getHttpChannel(); - IOChannel iochannel = asyncHttp.getNet().getFirst(); - remoteHostMB.set((String) - iochannel.getAttribute(IOChannel.ATT_REMOTE_HOSTNAME)); - } - return remoteHostMB; - } - - public CBuffer localName() { - return localNameMB; - } - - public CBuffer localAddr() { - return localAddrMB; - } - - public int getRemotePort(){ - if (remotePort == -1) { - HttpChannel asyncHttp = getHttpChannel(); - IOChannel iochannel = asyncHttp.getNet().getFirst(); - remotePort = (Integer) iochannel.getAttribute(IOChannel.ATT_REMOTE_PORT); - } - return remotePort; - } - - public void setRemotePort(int port){ - this.remotePort = port; - } - - public int getLocalPort(){ - if (localPort == -1) { - HttpChannel asyncHttp = getHttpChannel(); - IOChannel iochannel = asyncHttp.getNet().getFirst(); - localPort = (Integer) iochannel.getAttribute(IOChannel.ATT_LOCAL_PORT); - } - return localPort; - } - - public void setLocalPort(int port){ - this.localPort = port; - } - - public HttpResponse waitResponse() throws IOException { - return waitResponse(httpCh.ioTimeout); - } - - public void send(HttpService headersCallback, long timeout) throws IOException { - if (headersCallback != null) { - httpCh.setHttpService(headersCallback); - } - - httpCh.send(); - } - - public void send(HttpService headersCallback) throws IOException { - send(headersCallback, httpCh.ioTimeout); - } - - public void send() throws IOException { - send(null, httpCh.ioTimeout); - } - - public HttpResponse waitResponse(long timeout) throws IOException { - // TODO: close out if post - httpCh.send(); - - httpCh.headersReceivedLock.waitSignal(timeout); - - return httpCh.getResponse(); - } - - /** - * Parse host. - * @param serverNameMB2 - * @throws IOException - */ - boolean parseHost() { - MultiMap.Entry hostHF = getMimeHeaders().getEntry("Host"); - if (hostHF == null) { - // HTTP/1.0 - // Default is what the socket tells us. Overriden if a host is - // found/parsed - return true; - } - - BBuffer valueBC = hostHF.valueB; - if (valueBC == null) { - valueBC = BBuffer.allocate(); - hostHF.getValue().toAscii(valueBC); - } - byte[] valueB = valueBC.array(); - int valueL = valueBC.getLength(); - int valueS = valueBC.getStart(); - - int colonPos = valueBC.indexOf(':', 0); - - serverNameMB.recycle(); - - boolean ipv6 = (valueB[valueS] == '['); - boolean bracketClosed = false; - for (int i = 0; i < valueL; i++) { - char b = (char) valueB[i + valueS]; - if (b == ':') { - if (!ipv6 || bracketClosed) { - colonPos = i; - break; - } - } - serverNameMB.append(b); - if (b == ']') { - bracketClosed = true; - } - } - - if (colonPos < 0) { - if (!ssl) { - setServerPort(80); - } else { - setServerPort(443); - } - } else { - int port = 0; - int mult = 1; - for (int i = valueL - 1; i > colonPos; i--) { - int charValue = Hex.DEC[(int) valueB[i + valueS]]; - if (charValue == -1) { - // we don't return 400 - could do it - return false; - } - port = port + (charValue * mult); - mult = 10 * mult; - } - setServerPort(port); - - } - return true; - } - - // TODO: this is from coyote - MUST be rewritten !!! - // - cleaner - // - chunked encoding for body - // - buffer should be in a pool, etc. - /** - * Post data buffer. - */ - public final static int CACHED_POST_LEN = 8192; - - public byte[] postData = null; - - private long asyncTimeout = -1; - - /** - * Parse request parameters. - */ - protected void parseQuery() { - - parametersParsed = true; - - // getCharacterEncoding() may have been overridden to search for - // hidden form field containing request encoding - String enc = getEncoding(); - -// boolean useBodyEncodingForURI = connector.getUseBodyEncodingForURI(); -// if (enc != null) { -// parameters.setEncoding(enc); -//// if (useBodyEncodingForURI) { -//// parameters.setQueryStringEncoding(enc); -//// } -// } else { -// parameters.setEncoding(DEFAULT_CHARACTER_ENCODING); -//// if (useBodyEncodingForURI) { -//// parameters.setQueryStringEncoding -//// (DEFAULT_CHARACTER_ENCODING); -//// } -// } - - handleQueryParameters(); - } - - // Copy - will be modified by decoding - BBuffer decodedQuery = BBuffer.allocate(1024); - - CBuffer tmpNameC = CBuffer.newInstance(); - BBuffer tmpName = BBuffer.wrapper(); - BBuffer tmpValue = BBuffer.wrapper(); - - CBuffer tmpNameCB = CBuffer.newInstance(); - CBuffer tmpValueCB = CBuffer.newInstance(); - - /** - * Process the query string into parameters - */ - public void handleQueryParameters() { - if( queryMB.length() == 0) { - return; - } - - decodedQuery.recycle(); - decodedQuery.append(getMsgBytes().query()); - // TODO: option 'useBodyEncodingForUri' - versus UTF or ASCII - String queryStringEncoding = getEncoding(); - processParameters( decodedQuery, queryStringEncoding ); - } - - public void processParameters( BBuffer bc, String encoding ) { - if( bc.isNull()) - return; - if (bc.remaining() ==0) { - return; - } - processParameters( bc.array(), bc.getOffset(), - bc.getLength(), encoding); - } - - public void processParameters( byte bytes[], int start, int len, - String enc ) { - int end=start+len; - int pos=start; - - do { - boolean noEq=false; - int valStart=-1; - int valEnd=-1; - - int nameStart=pos; - int nameEnd=BBuffer.indexOf(bytes, nameStart, end, '=' ); - // Workaround for a&b&c encoding - int nameEnd2=BBuffer.indexOf(bytes, nameStart, end, '&' ); - if( (nameEnd2!=-1 ) && - ( nameEnd==-1 || nameEnd > nameEnd2) ) { - nameEnd=nameEnd2; - noEq=true; - valStart=nameEnd; - valEnd=nameEnd; - } - if( nameEnd== -1 ) - nameEnd=end; - - if( ! noEq ) { - valStart= (nameEnd < end) ? nameEnd+1 : end; - valEnd=BBuffer.indexOf(bytes, valStart, end, '&'); - if( valEnd== -1 ) valEnd = (valStart < end) ? end : valStart; - } - - pos=valEnd+1; - - if( nameEnd<=nameStart ) { - // No name eg ...&=xx&... will trigger this - continue; - } - - // TODO: use CBuffer, recycle - tmpName.setBytes( bytes, nameStart, nameEnd-nameStart ); - tmpValue.setBytes( bytes, valStart, valEnd-valStart ); - - try { - parameters.add(urlDecode(tmpName, enc), - urlDecode(tmpValue, enc)); - } catch (IOException e) { - // ignored - } - } while( pos nameEnd2) ) { -// nameEnd=nameEnd2; -// noEq=true; -// valStart=nameEnd; -// valEnd=nameEnd; -// } -// if( nameEnd== -1 ) -// nameEnd=end; -// -// if( ! noEq ) { -// valStart= (nameEnd < end) ? nameEnd+1 : end; -// valEnd=CBuffer.indexOf(bytes, valStart, end, '&'); -// if( valEnd== -1 ) valEnd = (valStart < end) ? end : valStart; -// } -// -// pos=valEnd+1; -// -// if( nameEnd<=nameStart ) { -// // No name eg ...&=xx&... will trigger this -// continue; -// } -// -// // TODO: use CBuffer, recycle -// tmpNameCB.recycle(); -// tmpValueCB.recycle(); -// -// tmpNameCB.wrap( bytes, nameStart, nameEnd ); -// tmpValueCB.wrap( bytes, valStart, valEnd ); -// -// //CharChunk name = new CharChunk(); -// //CharChunk value = new CharChunk(); -// // TODO: -// try { -// parameters.add(urlDecode(tmpName, enc), -// urlDecode(tmpValue, enc)); -// } catch (IOException e) { -// // ignored -// } -// } while( pos= 0) { - contentType = contentType.substring(0, semicolon).trim(); - } else { - contentType = contentType.trim(); - } - if (!("application/x-www-form-urlencoded".equals(contentType))) - return; - - int len = getContentLength(); - - if (len > 0) { - try { - byte[] formData = null; - if (len < CACHED_POST_LEN) { - if (postData == null) - postData = new byte[CACHED_POST_LEN]; - formData = postData; - } else { - formData = new byte[len]; - } - int actualLen = readPostBody(formData, len); - if (actualLen == len) { - processParameters(formData, 0, len); - } - } catch (Throwable t) { - ; // Ignore - } - } - - } - - /** - * Read post body in an array. - */ - protected int readPostBody(byte body[], int len) - throws IOException { - - int offset = 0; - do { - int inputLen = getBodyInputStream().read(body, offset, len - offset); - if (inputLen <= 0) { - return offset; - } - offset += inputLen; - } while ((len - offset) > 0); - return len; - - } - - // Async support - a subset of servlet spec, the fancy stuff is in the - // facade. - - public boolean isAsyncStarted() { - return async; - } - - public void async() { - this.async = true; - } - - public void setAsyncTimeout(long timeout) { - this.asyncTimeout = timeout; - } - - /** - * Server mode, request just received. - */ - protected void processReceivedHeaders() throws IOException { - BBuffer url = getMsgBytes().url(); - if (url.remaining() == 0) { - System.err.println("No input"); - } - if (url.get(0) == 'h') { - int firstSlash = url.indexOf('/', 0); - schemeMB.appendAscii(url.array(), - url.getStart(), firstSlash + 2); - if (!schemeMB.equals("http://") && - !schemeMB.equals("https://")) { - httpCh.getResponse().setStatus(400); - httpCh.abort("Error normalizing url " + - getMsgBytes().url()); - return; - } - - int urlStart = url.indexOf('/', firstSlash + 2); - serverNameMB.recycle(); - serverNameMB.appendAscii(url.array(), - url.getStart() + firstSlash + 2, urlStart - firstSlash - 2); - - url.position(url.getStart() + urlStart); - } - if (!httpCh.normalize(getMsgBytes().url())) { - httpCh.getResponse().setStatus(400); - httpCh.abort("Error normalizing url " + - getMsgBytes().url()); - return; - } - - method().set(getMsgBytes().method()); - requestURI().set(getMsgBytes().url()); - queryString().set(getMsgBytes().query()); - protocol().set(getMsgBytes().protocol()); - - processMimeHeaders(); - - // URL decode and normalize - decodedUri.append(getMsgBytes().url()); - - getURLDecoder().urlDecode(decodedUri, false); - - // Need to normalize again - %decoding may decode / - if (!httpCh.normalize(decodedUri)) { - httpCh.getResponse().setStatus(400); - httpCh.abort("Invalid decoded uri " + decodedUri); - return; - } - decodedURI().set(decodedUri); - - // default response protocol - httpCh.getResponse().protocol().set(getMsgBytes().protocol()); - } - - - public boolean hasBody() { - return chunked || contentLength >= 0; - } - - /** - * Convert (if necessary) and return the absolute URL that represents the - * resource referenced by this possibly relative URL. If this URL is - * already absolute, return it unchanged. - * - * @param location URL to be (possibly) converted and then returned - * - * @exception IllegalArgumentException if a MalformedURLException is - * thrown when converting the relative URL to an absolute one - */ - public void toAbsolute(String location, CBuffer cb) { - - cb.recycle(); - if (location == null) - return; - - boolean leadingSlash = location.startsWith("/"); - if (leadingSlash || !hasScheme(location)) { - - String scheme = getScheme(); - String name = serverName().toString(); - int port = getServerPort(); - - cb.append(scheme); - cb.append("://", 0, 3); - cb.append(name); - if ((scheme.equals("http") && port != 80) - || (scheme.equals("https") && port != 443)) { - cb.append(':'); - String portS = port + ""; - cb.append(portS); - } - if (!leadingSlash) { - String relativePath = decodedURI().toString(); - int pos = relativePath.lastIndexOf('/'); - relativePath = relativePath.substring(0, pos); - - //String encodedURI = null; - urlEncoding.urlEncode(relativePath, cb, charEncoder); - //encodedURI = urlEncoder.encodeURL(relativePath); - //redirectURLCC.append(encodedURI, 0, encodedURI.length()); - cb.append('/'); - } - - cb.append(location); - } else { - cb.append(location); - } - - } - - /** - * Determine if a URI string has a scheme component. - */ - public static boolean hasScheme(String uri) { - int len = uri.length(); - for(int i=0; i < len ; i++) { - char c = uri.charAt(i); - if(c == ':') { - return i > 0; - } else if(!isSchemeChar(c)) { - return false; - } - } - return false; - } - - /** - * Determine if the character is allowed in the scheme of a URI. - * See RFC 2396, Section 3.1 - */ - private static boolean isSchemeChar(char c) { - return Character.isLetterOrDigit(c) || - c == '+' || c == '-' || c == '.'; - } - - public IOWriter getCharEncoder() { - return charEncoder; - } - - public IOReader getCharDecoder() { - return charDecoder; - } - - public UrlEncoding getUrlEncoding() { - return urlEncoding; - } - - public BBuffer toBytes(CBuffer cb, BBuffer bb) { - if (bb == null) { - bb = BBuffer.allocate(cb.length()); - } - getCharEncoder().encodeAll(cb, bb, "UTF-8"); - return bb; - } - - public String toString() { - IOBuffer out = new IOBuffer(); - try { - Http11Connection.serialize(this, out); - return out.readAll(null).toString(); - } catch (IOException e) { - return "Invalid request"; - } - } - - public boolean isSecure() { - return ssl; - } - - public HttpRequest setSecure(boolean ssl) { - this.ssl = ssl; - return this; - } -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpResponse.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpResponse.java deleted file mode 100644 index 39f2ffa57921..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpResponse.java +++ /dev/null @@ -1,581 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.io.IOException; -import java.util.HashMap; - -import org.apache.tomcat.lite.io.BBucket; -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.CBuffer; - -public class HttpResponse extends HttpMessage { - - /* - * Server status codes; see RFC 2068. - */ - - /** - * Status code (100) indicating the client can continue. - */ - - public static final int SC_CONTINUE = 100; - - - /** - * Status code (101) indicating the server is switching protocols - * according to Upgrade header. - */ - - public static final int SC_SWITCHING_PROTOCOLS = 101; - - /** - * Status code (200) indicating the request succeeded normally. - */ - - public static final int SC_OK = 200; - - /** - * Status code (201) indicating the request succeeded and created - * a new resource on the server. - */ - - public static final int SC_CREATED = 201; - - /** - * Status code (202) indicating that a request was accepted for - * processing, but was not completed. - */ - - public static final int SC_ACCEPTED = 202; - - /** - * Status code (203) indicating that the meta information presented - * by the client did not originate from the server. - */ - - public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203; - - /** - * Status code (204) indicating that the request succeeded but that - * there was no new information to return. - */ - - public static final int SC_NO_CONTENT = 204; - - /** - * Status code (205) indicating that the agent SHOULD reset - * the document view which caused the request to be sent. - */ - - public static final int SC_RESET_CONTENT = 205; - - /** - * Status code (206) indicating that the server has fulfilled - * the partial GET request for the resource. - */ - - public static final int SC_PARTIAL_CONTENT = 206; - - /** - * Used by Webdav. - */ - public static final int SC_MULTI_STATUS = 207; - // This one collides with HTTP 1.1 - // "207 Partial Update OK" - - /** - * Status code (300) indicating that the requested resource - * corresponds to any one of a set of representations, each with - * its own specific location. - */ - - public static final int SC_MULTIPLE_CHOICES = 300; - - /** - * Status code (301) indicating that the resource has permanently - * moved to a new location, and that future references should use a - * new URI with their requests. - */ - - public static final int SC_MOVED_PERMANENTLY = 301; - - /** - * Status code (302) indicating that the resource has temporarily - * moved to another location, but that future references should - * still use the original URI to access the resource. - * - * This definition is being retained for backwards compatibility. - * SC_FOUND is now the preferred definition. - */ - - public static final int SC_MOVED_TEMPORARILY = 302; - - /** - * Status code (302) indicating that the resource reside - * temporarily under a different URI. Since the redirection might - * be altered on occasion, the client should continue to use the - * Request-URI for future requests.(HTTP/1.1) To represent the - * status code (302), it is recommended to use this variable. - */ - - public static final int SC_FOUND = 302; - - /** - * Status code (303) indicating that the response to the request - * can be found under a different URI. - */ - - public static final int SC_SEE_OTHER = 303; - - /** - * Status code (304) indicating that a conditional GET operation - * found that the resource was available and not modified. - */ - - public static final int SC_NOT_MODIFIED = 304; - - /** - * Status code (305) indicating that the requested resource - * MUST be accessed through the proxy given by the - * Location field. - */ - - public static final int SC_USE_PROXY = 305; - - /** - * Status code (307) indicating that the requested resource - * resides temporarily under a different URI. The temporary URI - * SHOULD be given by the Location - * field in the response. - */ - - public static final int SC_TEMPORARY_REDIRECT = 307; - - /** - * Status code (400) indicating the request sent by the client was - * syntactically incorrect. - */ - - public static final int SC_BAD_REQUEST = 400; - - /** - * Status code (401) indicating that the request requires HTTP - * authentication. - */ - - public static final int SC_UNAUTHORIZED = 401; - - /** - * Status code (402) reserved for future use. - */ - - public static final int SC_PAYMENT_REQUIRED = 402; - - /** - * Status code (403) indicating the server understood the request - * but refused to fulfill it. - */ - - public static final int SC_FORBIDDEN = 403; - - /** - * Status code (404) indicating that the requested resource is not - * available. - */ - - public static final int SC_NOT_FOUND = 404; - - /** - * Status code (405) indicating that the method specified in the - * Request-Line is not allowed for the resource - * identified by the Request-URI. - */ - - public static final int SC_METHOD_NOT_ALLOWED = 405; - - /** - * Status code (406) indicating that the resource identified by the - * request is only capable of generating response entities which have - * content characteristics not acceptable according to the accept - * headers sent in the request. - */ - - public static final int SC_NOT_ACCEPTABLE = 406; - - /** - * Status code (407) indicating that the client MUST first - * authenticate itself with the proxy. - */ - - public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407; - - /** - * Status code (408) indicating that the client did not produce a - * request within the time that the server was prepared to wait. - */ - - public static final int SC_REQUEST_TIMEOUT = 408; - - /** - * Status code (409) indicating that the request could not be - * completed due to a conflict with the current state of the - * resource. - */ - - public static final int SC_CONFLICT = 409; - - /** - * Status code (410) indicating that the resource is no longer - * available at the server and no forwarding address is known. - * This condition SHOULD be considered permanent. - */ - - public static final int SC_GONE = 410; - - /** - * Status code (411) indicating that the request cannot be handled - * without a defined Content-Length. - */ - - public static final int SC_LENGTH_REQUIRED = 411; - - /** - * Status code (412) indicating that the precondition given in one - * or more of the request-header fields evaluated to false when it - * was tested on the server. - */ - - public static final int SC_PRECONDITION_FAILED = 412; - - /** - * Status code (413) indicating that the server is refusing to process - * the request because the request entity is larger than the server is - * willing or able to process. - */ - - public static final int SC_REQUEST_ENTITY_TOO_LARGE = 413; - - /** - * Status code (414) indicating that the server is refusing to service - * the request because the Request-URI is longer - * than the server is willing to interpret. - */ - - public static final int SC_REQUEST_URI_TOO_LONG = 414; - - /** - * Status code (415) indicating that the server is refusing to service - * the request because the entity of the request is in a format not - * supported by the requested resource for the requested method. - */ - - public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415; - - /** - * Status code (416) indicating that the server cannot serve the - * requested byte range. - */ - - public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416; - - /** - * Status code (417) indicating that the server could not meet the - * expectation given in the Expect request header. - */ - - public static final int SC_EXPECTATION_FAILED = 417; - - /** - * Status code (423) indicating the destination resource of a - * method is locked, and either the request did not contain a - * valid Lock-Info header, or the Lock-Info header identifies - * a lock held by another principal. - */ - public static final int SC_LOCKED = 423; - - /** - * Status code (500) indicating an error inside the HTTP server - * which prevented it from fulfilling the request. - */ - - public static final int SC_INTERNAL_SERVER_ERROR = 500; - - /** - * Status code (501) indicating the HTTP server does not support - * the functionality needed to fulfill the request. - */ - - public static final int SC_NOT_IMPLEMENTED = 501; - - /** - * Status code (502) indicating that the HTTP server received an - * invalid response from a server it consulted when acting as a - * proxy or gateway. - */ - - public static final int SC_BAD_GATEWAY = 502; - - /** - * Status code (503) indicating that the HTTP server is - * temporarily overloaded, and unable to handle the request. - */ - - public static final int SC_SERVICE_UNAVAILABLE = 503; - - /** - * Status code (504) indicating that the server did not receive - * a timely response from the upstream server while acting as - * a gateway or proxy. - */ - - public static final int SC_GATEWAY_TIMEOUT = 504; - - /** - * Status code (505) indicating that the server does not support - * or refuses to support the HTTP protocol version that was used - * in the request message. - */ - - public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505; - - // will not be recycled - public Object nativeResponse; - - protected CBuffer message = CBuffer.newInstance(); - - int status = -1; - - HttpResponse(HttpChannel httpCh) { - super(httpCh); - } - - public void recycle() { - super.recycle(); - message.recycle(); - status = -1; - } - - public void setMessage(String s) { - message.set(filter(s)); - } - - public String getMessage() { - return message.toString(); - } - - public CBuffer getMessageBuffer() { - return message; - } - - byte[] S_200 = new byte[] { '2', '0', '0' }; - - public void setStatus(int i) { - status = i; - } - - public void sendError(int status) { - this.status = status; - } - - public void sendError(int status, String msg) { - message.set(msg); - } - - public int getStatus() { - if (status >= 0) { - return status; - } - if (getMsgBytes().status().isNull()) { - status = 200; - } else { - try { - status = getMsgBytes().status().getInt(); - } catch(NumberFormatException ex) { - status = 500; - httpCh.log.severe("Invalid status " + getMsgBytes().status()); - } - } - return status; - } - - public HttpRequest getRequest() { - return getHttpChannel().getRequest(); - } - - // Http client mode. - protected void processReceivedHeaders() throws IOException { - protocol().set(getMsgBytes().protocol()); - message.set(getMsgBytes().message()); - processMimeHeaders(); - // TODO: if protocol == 1.0 and we requested 1.1, downgrade getHttpChannel().pro - try { - status = getStatus(); - } catch (Throwable t) { - getHttpChannel().log.warning("Invalid status " + getMsgBytes().status() + " " + getMessage()); - } - } - - /** - * All responses to the HEAD request method MUST NOT include a - * message-body, even though the presence of entity- header fields might - * lead one to believe they do. All 1xx (informational), 204 (no content) - * , and 304 (not modified) responses MUST NOT include a message-body. All - * other responses do include a message-body, although it MAY be of zero - * length. - */ - public boolean hasBody() { - if (httpCh.getRequest().method().equals("HEAD")) { - return false; - } - if (status >= 100 && status < 200) { - return false; - } - // what about (status == 205) ? - if ((status == 204) - || (status == 304)) { - return false; - } - return true; - } - - /** Get the status string associated with a status code. - * No I18N - return the messages defined in the HTTP spec. - * ( the user isn't supposed to see them, this is the last - * thing to translate) - * - * Common messages are cached. - * - */ - static BBucket getMessage( int status ) { - // method from Response. - - // Does HTTP requires/allow international messages or - // are pre-defined? The user doesn't see them most of the time - switch( status ) { - case 200: - return st_200; - case 302: - return st_302; - case 400: - return st_400; - case 404: - return st_404; - } - BBucket bb = stats.get(status); - if (bb == null) { - return st_unknown; - } - return bb; - } - - public static String getStatusText(int code) { - return getMessage(code).toString(); - } - - static BBucket st_unknown = BBuffer.wrapper("No Message"); - static BBucket st_200 = BBuffer.wrapper("OK"); - static BBucket st_302= BBuffer.wrapper("Moved Temporarily"); - static BBucket st_400= BBuffer.wrapper("Bad Request"); - static BBucket st_404= BBuffer.wrapper("Not Found"); - - static HashMap stats = new HashMap(); - private static void addStatus(int stat, String msg) { - stats.put(stat, BBuffer.wrapper(msg)); - } - - static { - addStatus(100, "Continue"); - addStatus(101, "Switching Protocols"); - addStatus(200, "OK"); - addStatus(201, "Created"); - addStatus(202, "Accepted"); - addStatus(203, "Non-Authoritative Information"); - addStatus(204, "No Content"); - addStatus(205, "Reset Content"); - addStatus(206, "Partial Content"); - addStatus(207, "Multi-Status"); - addStatus(300, "Multiple Choices"); - addStatus(301, "Moved Permanently"); - addStatus(302, "Moved Temporarily"); - addStatus(303, "See Other"); - addStatus(304, "Not Modified"); - addStatus(305, "Use Proxy"); - addStatus(307, "Temporary Redirect"); - addStatus(400, "Bad Request"); - addStatus(401, "Unauthorized"); - addStatus(402, "Payment Required"); - addStatus(403, "Forbidden"); - addStatus(404, "Not Found"); - addStatus(405, "Method Not Allowed"); - addStatus(406, "Not Acceptable"); - addStatus(407, "Proxy Authentication Required"); - addStatus(408, "Request Timeout"); - addStatus(409, "Conflict"); - addStatus(410, "Gone"); - addStatus(411, "Length Required"); - addStatus(412, "Precondition Failed"); - addStatus(413, "Request Entity Too Large"); - addStatus(414, "Request-URI Too Long"); - addStatus(415, "Unsupported Media Type"); - addStatus(416, "Requested Range Not Satisfiable"); - addStatus(417, "Expectation Failed"); - addStatus(422, "Unprocessable Entity"); - addStatus(423, "Locked"); - addStatus(424, "Failed Dependency"); - addStatus(500, "Internal Server Error"); - addStatus(501, "Not Implemented"); - addStatus(502, "Bad Gateway"); - addStatus(503, "Service Unavailable"); - addStatus(504, "Gateway Timeout"); - addStatus(505, "HTTP Version Not Supported"); - addStatus(507, "Insufficient Storage"); - addStatus(SC_LOCKED, "Locked"); - - - } - - /** - * Filter the specified message string for characters that are sensitive - * in HTML. This avoids potential attacks caused by including JavaScript - * codes in the request URL that is often reported in error messages. - * - * @param message The message string to be filtered - */ - private static String filter(String message) { - - if (message == null) - return (null); - if (message.indexOf('<') < 0 && - message.indexOf('>') < 0 && - message.indexOf('&') < 0 && - message.indexOf('"') < 0) { - return message; - } - - char content[] = new char[message.length()]; - message.getChars(0, message.length(), content, 0); - - StringBuffer result = new StringBuffer(content.length + 50); - for (int i = 0; i < content.length; i++) { - switch (content[i]) { - case '<': - result.append("<"); - break; - case '>': - result.append(">"); - break; - case '&': - result.append("&"); - break; - case '"': - result.append("""); - break; - default: - result.append(content[i]); - } - } - return (result.toString()); - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpServer.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpServer.java deleted file mode 100644 index e8182d982b71..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpServer.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import org.apache.tomcat.lite.io.SocketConnector; -import org.apache.tomcat.lite.io.SslProvider; -import org.apache.tomcat.lite.io.jsse.JsseSslProvider; - -/** - * Main entry point for HTTP server code. - * - * ( initial draft - will replace statics, add helpers, etc ) - */ -public class HttpServer { - static SslProvider sslConC = new JsseSslProvider(); - - public synchronized static HttpConnector newServer(int port) { - return new HttpConnector(new SocketConnector()). - withSsl(sslConC).setPort(port); - } - - public synchronized static HttpConnector newSslServer(int port) { - // DHE broken in harmony - will replace with a flag - // SslConnector.setEnabledCiphers(new String[] { - // "TLS_RSA_WITH_3DES_EDE_CBC_SHA" - // }); - // -cipher DES-CBC3-SHA - - SslProvider sslCon = new JsseSslProvider(); - - return new HttpConnector(new SocketConnector()). - withSsl(sslCon).setPort(port).setServerSsl(true); - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpWriter.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpWriter.java deleted file mode 100644 index 2d8f91abd126..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/HttpWriter.java +++ /dev/null @@ -1,313 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.io.IOException; -import java.io.Writer; - -import org.apache.tomcat.lite.io.IOOutputStream; -import org.apache.tomcat.lite.io.IOWriter; - -/** - * Implement character translation and buffering. - * - * The actual buffering happens in the IOBuffer - we translate the - * chars as soon as we get them. - * - * For servlet compat you can set a buffer size and a flush() will happen - * when the number of chars have been written. Note that writes at a lower - * layer can be done and are not counted. - * - * @author Costin Manolache - */ -public class HttpWriter extends Writer { - - public static final String DEFAULT_ENCODING = "ISO-8859-1"; - public static final int DEFAULT_BUFFER_SIZE = 8*1024; - - // ----------------------------------------------------- Instance Variables - HttpMessage message; - - /** - * The byte buffer. - */ - protected IOOutputStream bb; - - int bufferSize = DEFAULT_BUFFER_SIZE; - - /** - * Number of chars written. - */ - protected int wSinceFlush = 0; - - - /** - * Flag which indicates if the output buffer is closed. - */ - protected boolean closed = false; - - /** - * Encoding to use. - * TODO: isn't it redundant ? enc, gotEnc, conv plus the enc in the bb - */ - protected String enc; - - - /** - * Encoder is set. - */ - protected boolean gotEnc = false; - - - /** - * List of encoders. The writer is reused - the encoder mapping - * avoids creating expensive objects. In future it'll contain nio.Charsets - */ - //protected Map encoders = new HashMap(); - - - /** - * Current char to byte converter. TODO: replace with Charset - */ - private IOWriter conv; - - /** - * Suspended flag. All output bytes will be swallowed if this is true. - */ - protected boolean suspended = false; - - - // ----------------------------------------------------------- Constructors - - - /** - * Default constructor. Allocate the buffer with the default buffer size. - * @param out - */ - public HttpWriter(HttpMessage message, IOOutputStream out, - IOWriter conv) { - this.message = message; - bb = out; - this.conv = conv; - } - - // ------------------------------------------------------------- Properties - - - /** - * Is the response output suspended ? - * - * @return suspended flag value - */ - public boolean isSuspended() { - return this.suspended; - } - - - /** - * Set the suspended flag. - * - * @param suspended New suspended flag value - */ - public void setSuspended(boolean suspended) { - this.suspended = suspended; - } - - - // --------------------------------------------------------- Public Methods - - - /** - * Recycle the output buffer. - */ - public void recycle() { - wSinceFlush = 0; - bb.recycle(); - closed = false; - suspended = false; - -// if (conv != null) { -// conv.recycle(); -// } - - gotEnc = false; - enc = null; - } - - public void close() - throws IOException { - - if (closed) - return; - if (suspended) - return; - - push(); - closed = true; - - bb.close(); - } - - - /** - * Flush bytes or chars contained in the buffer. - * - * @throws IOException An underlying IOException occurred - */ - public void flush() - throws IOException { - push(); - bb.flush(); // will send the data - wSinceFlush = 0; - } - - /** - * Flush chars to the byte buffer. - */ - public void push() - throws IOException { - - if (suspended) - return; - getConv().push(); - - } - - - private void updateSize(int cnt) throws IOException { - wSinceFlush += cnt; - if (wSinceFlush > bufferSize) { - flush(); - } - } - - public void write(int c) - throws IOException { - if (suspended) - return; - getConv().write(c); - updateSize(1); - } - - - public void write(char c[]) - throws IOException { - write(c, 0, c.length); - } - - - public void write(char c[], int off, int len) - throws IOException { - if (suspended) - return; - getConv().write(c, off, len); - updateSize(len); - } - - - public void write(StringBuffer sb) - throws IOException { - if (suspended) - return; - int len = sb.length(); - getConv().write(sb.toString()); - updateSize(len); - } - - - /** - * Append a string to the buffer - */ - public void write(String s, int off, int len) - throws IOException { - if (suspended) - return; - if (s==null) - s="null"; - getConv().write( s, off, len ); - updateSize(len); - } - - - public void write(String s) - throws IOException { - if (s==null) - s="null"; - write(s, 0, s.length()); - } - - public void println() throws IOException { - write("\n"); - } - - public void println(String s) throws IOException { - write(s); - write("\n"); - } - - public void print(String s) throws IOException { - write(s); - } - - public void checkConverter() - throws IOException { -// if (gotEnc) { -// return; -// } -// if (enc == null) { -// enc = message.getCharacterEncoding(); -// } -// -// gotEnc = true; -// if (enc == null) -// enc = DEFAULT_ENCODING; -// conv = (C2BConverter) encoders.get(enc); -// -// if (conv == null) { -// conv = C2BConverter.newConverter(message.getBodyOutputStream(), -// enc); -// encoders.put(enc, conv); -// -// } - } - - public int getWrittenSinceFlush() { - return wSinceFlush; - } - - - public void setBufferSize(int size) { - if (size > bufferSize) { - bufferSize = size; - } - } - - /** - * Clear any data that was buffered. - */ - public void reset() { - if (conv != null) { - conv.recycle(); - } - wSinceFlush = 0; - gotEnc = false; - enc = null; - bb.reset(); - } - - - public int getBufferSize() { - return bufferSize; - } - - protected IOWriter getConv() throws IOException { - checkConverter(); - return conv; - } - - public void println(CharSequence key) throws IOException { - // TODO: direct - println(key.toString()); - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/MappingData.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/MappingData.java deleted file mode 100644 index 67c0c135b0f9..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/MappingData.java +++ /dev/null @@ -1,69 +0,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.lite.http; - -import org.apache.tomcat.lite.io.CBuffer; - - -/** - * Mapping data. - * - * @author Remy Maucherat - */ -public class MappingData { - - public Object context = null; // ServletContextImpl - - public BaseMapper.Context contextMap; - - public BaseMapper.ServiceMapping service = null; - - public CBuffer contextPath = CBuffer.newInstance(); - public CBuffer requestPath = CBuffer.newInstance(); - public CBuffer wrapperPath = CBuffer.newInstance(); - public CBuffer pathInfo = CBuffer.newInstance(); - - public CBuffer redirectPath = CBuffer.newInstance(); - - // Extension - CBuffer ext = CBuffer.newInstance(); - CBuffer tmpPrefix = CBuffer.newInstance(); - - // Excluding context path, with a '/' added if needed - CBuffer tmpServletPath = CBuffer.newInstance(); - - // Excluding context path, with a '/' added if needed - CBuffer tmpWelcome = CBuffer.newInstance(); - - public void recycle() { - service = null; - context = null; - pathInfo.recycle(); - requestPath.recycle(); - wrapperPath.recycle(); - contextPath.recycle(); - redirectPath.recycle(); - contextMap = null; - } - - - public Object getServiceObject() { - return service == null ? null : service.object; - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/MultiMap.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/MultiMap.java deleted file mode 100644 index 97fca7cd6f1c..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/MultiMap.java +++ /dev/null @@ -1,357 +0,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.lite.http; - -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.CBucket; -import org.apache.tomcat.lite.io.CBuffer; - -/** - * Map used to represent headers and parameters ( could be used - * for cookies too ) - * - * It'll avoid garbage collection, like original tomcat classes, - * by converting to chars and strings late. - * - * Not thread safe. - */ -public class MultiMap { - - public static class Entry { - // Wrappers from the head message bytes. - BBuffer nameB; - BBuffer valueB; - - CBuffer key = CBuffer.newInstance(); - private CBuffer value = CBuffer.newInstance(); - - /** - * For the first entry with a given name: list of all - * other entries, including this one, with same name. - * - * For second or more: empty list - */ - public List values = new ArrayList(); - - public void recycle() { - key.recycle(); - value.recycle(); - //next=null; - nameB = null; - valueB = null; - values.clear(); - } - - public CBuffer getName() { - if (key.length() == 0 && nameB != null) { - key.set(nameB); - } - return key; - } - - public CBuffer getValue() { - if (value.length() == 0 && valueB != null) { - value.set(valueB); - } - return value; - } - - /** Important - used by values iterator, returns strings - * from each entry - */ - public String toString() { - return getValue().toString(); - } - - } - - // active entries - protected int count; - - // The key will be converted to lower case - boolean toLower = false; - - // Some may be inactive - up to count. - protected List entries = new ArrayList(); - - // 2 options: convert all header/param names to String - // or use a temp CBuffer to map - Map map = - new HashMap(); - - public void recycle() { - for (int i = 0; i < count; i++) { - Entry entry = entries.get(i); - entry.recycle(); - } - count = 0; - map.clear(); - } - - // ----------- Mutations ------------------------ - - protected Entry newEntry() { - return new Entry(); - } - - /** - * Adds a partially constructed field entry. - * Updates count - but will not affect the map. - */ - private Entry getEntryForAdd() { - Entry entry; - if (count >= entries.size()) { - entry = newEntry(); - entries.add(entry); - } else { - entry = entries.get(count); - } - count++; - return entry; - } - - - /** Create a new named header , return the CBuffer - * container for the new value - */ - public Entry addEntry(CharSequence name ) { - Entry mh = getEntryForAdd(); - mh.getName().append(name); - if (toLower) { - mh.getName().toLower(); - } - updateMap(mh); - return mh; - } - - /** Create a new named header , return the CBuffer - * container for the new value - */ - public Entry addEntry(BBuffer name ) { - Entry mh = getEntryForAdd(); - mh.nameB = name; - if (toLower) { - mh.getName().toLower(); - } - updateMap(mh); - - return mh; - } - - private void updateMap(Entry mh) { - Entry topEntry = map.get(mh.getName()); - - if (topEntry == null) { - map.put(mh.getName(), mh); - mh.values.add(mh); - } else { - topEntry.values.add(mh); - } - } - - - - public void remove(CharSequence key) { - CBucket ckey = key(key); - Entry entry = getEntry(ckey); - if (entry != null) { - map.remove(ckey); - - for (int i = count - 1; i >= 0; i--) { - entry = entries.get(i); - if (entry.getName().equals(key)) { - entry.recycle(); - entries.remove(i); - count--; - } - } - } - } - - // --------------- Key-based access -------------- - CBuffer tmpKey = CBuffer.newInstance(); - - /** - * Finds and returns a header field with the given name. If no such - * field exists, null is returned. If more than one such field is - * in the header, an arbitrary one is returned. - */ - public CBuffer getHeader(String name) { - for (int i = 0; i < count; i++) { - if (entries.get(i).getName().equalsIgnoreCase(name)) { - return entries.get(i).getValue(); - } - } - return null; - } - - private CBucket key(CharSequence key) { - if (key instanceof CBucket) { - CBucket res = (CBucket) key; - if (!toLower || !res.hasUpper()) { - return res; - } - } - tmpKey.recycle(); - tmpKey.append(key); - if (toLower) { - tmpKey.toLower(); - } - return tmpKey; - } - - public Entry getEntry(CharSequence key) { - Entry entry = map.get(key(key)); - return entry; - } - - public Entry getEntry(CBucket buf) { - // lowercase ? - Entry entry = map.get(buf); - return entry; - } - - public Enumeration names() { - return new IteratorEnumerator(map.keySet().iterator()); - } - - // ----------- Index access -------------- - - /** - * Number of entries ( including those with same key - * - * @return - */ - public int size() { - return count; - } - - - public CharSequence getKey(int idx) { - return entries.get(idx).key; - } - - public Entry getEntry(int idx) { - return entries.get(idx); - } - - /** - * Returns the Nth header name, or null if there is no such header. - * This may be used to iterate through all header fields. - */ - public CBuffer getName(int n) { - return n < count ? entries.get(n).getName() : null; - } - - /** - * Returns the Nth header value, or null if there is no such header. - * This may be used to iterate through all header fields. - */ - public CBuffer getValue(int n) { - return n >= 0 && n < count ? entries.get(n).getValue() : null; - } - - // ----------- Helpers -------------- - public void add(CharSequence key, CharSequence value) { - Entry mh = addEntry(key); - mh.value.append(value); - } - - /** Create a new named header , return the CBuffer - * container for the new value - */ - public CBuffer addValue( String name ) { - return addEntry(name).getValue(); - } - - public Entry setEntry( String name ) { - remove(name); - return addEntry(name); - } - - public void set(CharSequence key, CharSequence value) { - remove(key); - add(key, value); - } - - public CBuffer setValue( String name ) { - remove(name); - return addValue(name); - } - - public CBuffer get(CharSequence key) { - Entry entry = getEntry(key); - return (entry == null) ? null : entry.value; - } - - public String getString(CharSequence key) { - Entry entry = getEntry(key); - return (entry == null) ? null : entry.value.toString(); - } - - - // -------------- support classes ---------------- - - public static class IteratorEnumerator implements Enumeration { - private final Iterator keyI; - - public IteratorEnumerator(Iterator iterator) { - this.keyI = iterator; - } - - - public boolean hasMoreElements() { - return keyI.hasNext(); - } - - - public String nextElement() { - return keyI.next().toString(); - } - - } - - public static final Enumeration EMPTY = - new Enumeration() { - - @Override - public boolean hasMoreElements() { - return false; - } - - @Override - public String nextElement() { - return null; - } - - }; - - public MultiMap insensitive() { - toLower = true; - return this; - } - - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/ServerCookie.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/ServerCookie.java deleted file mode 100644 index c80ef5de9053..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/ServerCookie.java +++ /dev/null @@ -1,819 +0,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.lite.http; - -import java.io.Serializable; -import java.text.DateFormat; -import java.text.FieldPosition; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.TimeZone; - -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.CBuffer; - - -/** - * Server-side cookie representation. - * Allows recycling and uses MessageBytes as low-level - * representation ( and thus the byte-> char conversion can be delayed - * until we know the charset ). - * - * Tomcat.core uses this recyclable object to represent cookies, - * and the facade will convert it to the external representation. - */ -public class ServerCookie implements Serializable { - - // Version 0 (Netscape) attributes - private BBuffer name = BBuffer.allocate(); - private BBuffer value = BBuffer.allocate(); - - private CBuffer nameC = CBuffer.newInstance(); - - // Expires - Not stored explicitly. Generated from Max-Age (see V1) - private BBuffer path = BBuffer.allocate(); - private BBuffer domain = BBuffer.allocate(); - private boolean secure; - - // Version 1 (RFC2109) attributes - private BBuffer comment = BBuffer.allocate(); - private int maxAge = -1; - private int version = 0; - - // Other fields - private static final String OLD_COOKIE_PATTERN = - "EEE, dd-MMM-yyyy HH:mm:ss z"; - private static final ThreadLocal OLD_COOKIE_FORMAT = - new ThreadLocal() { - protected DateFormat initialValue() { - DateFormat df = - new SimpleDateFormat(OLD_COOKIE_PATTERN, Locale.US); - df.setTimeZone(TimeZone.getTimeZone("GMT")); - return df; - } - }; - - private static final String ancientDate; - - - static { - ancientDate = OLD_COOKIE_FORMAT.get().format(new Date(10000)); - } - - /** - * If set to true, we parse cookies according to the servlet spec, - */ - public static final boolean STRICT_SERVLET_COMPLIANCE = - Boolean.valueOf(System.getProperty("org.apache.catalina.STRICT_SERVLET_COMPLIANCE", "false")).booleanValue(); - - /** - * If set to false, we don't use the IE6/7 Max-Age/Expires work around - */ - public static final boolean ALWAYS_ADD_EXPIRES = - Boolean.valueOf(System.getProperty("org.apache.tomcat.util.http.ServerCookie.ALWAYS_ADD_EXPIRES", "true")).booleanValue(); - - // Note: Servlet Spec =< 2.5 only refers to Netscape and RFC2109, - // not RFC2965 - - // Version 1 (RFC2965) attributes - // TODO Add support for CommentURL - // Discard - implied by maxAge <0 - // TODO Add support for Port - - public ServerCookie() { - } - - public void recycle() { - path.recycle(); - name.recycle(); - value.recycle(); - comment.recycle(); - maxAge=-1; - path.recycle(); - domain.recycle(); - version=0; - secure=false; - } - - public BBuffer getComment() { - return comment; - } - - public BBuffer getDomain() { - return domain; - } - - public void setMaxAge(int expiry) { - maxAge = expiry; - } - - public int getMaxAge() { - return maxAge; - } - - public BBuffer getPath() { - return path; - } - - public void setSecure(boolean flag) { - secure = flag; - } - - public boolean getSecure() { - return secure; - } - - public BBuffer getName() { - return name; - } - - public BBuffer getValue() { - return value; - } - - public int getVersion() { - return version; - } - - public void setVersion(int v) { - version = v; - } - - - // -------------------- utils -------------------- - - public String toString() { - return "Cookie " + getName() + "=" + getValue() + " ; " - + getVersion() + " " + getPath() + " " + getDomain(); - } - - private static final String tspecials = ",; "; - private static final String tspecials2 = "()<>@,;:\\\"/[]?={} \t"; - private static final String tspecials2NoSlash = "()<>@,;:\\\"[]?={} \t"; - - /* - * Tests a string and returns true if the string counts as a - * reserved token in the Java language. - * - * @param value the String to be tested - * - * @return true if the String is a reserved - * token; false if it is not - */ - public static boolean isToken(String value) { - return isToken(value,null); - } - - public static boolean isToken(String value, String literals) { - String tspecials = (literals==null?ServerCookie.tspecials:literals); - if( value==null) return true; - int len = value.length(); - - for (int i = 0; i < len; i++) { - char c = value.charAt(i); - - if (tspecials.indexOf(c) != -1) - return false; - } - return true; - } - - public static boolean containsCTL(String value, int version) { - if( value==null) return false; - int len = value.length(); - for (int i = 0; i < len; i++) { - char c = value.charAt(i); - if (c < 0x20 || c >= 0x7f) { - if (c == 0x09) - continue; //allow horizontal tabs - return true; - } - } - return false; - } - - public static boolean isToken2(String value) { - return isToken2(value,null); - } - - public static boolean isToken2(String value, String literals) { - String tspecials2 = (literals==null?ServerCookie.tspecials2:literals); - if( value==null) return true; - int len = value.length(); - - for (int i = 0; i < len; i++) { - char c = value.charAt(i); - if (tspecials2.indexOf(c) != -1) - return false; - } - return true; - } - - // -------------------- Cookie parsing tools - - - /** - * Return the header name to set the cookie, based on cookie version. - */ - public String getCookieHeaderName() { - return getCookieHeaderName(version); - } - - /** - * Return the header name to set the cookie, based on cookie version. - */ - public static String getCookieHeaderName(int version) { - // TODO Re-enable logging when RFC2965 is implemented - // log( (version==1) ? "Set-Cookie2" : "Set-Cookie"); - if (version == 1) { - // XXX RFC2965 not referenced in Servlet Spec - // Set-Cookie2 is not supported by Netscape 4, 6, IE 3, 5 - // Set-Cookie2 is supported by Lynx and Opera - // Need to check on later IE and FF releases but for now... - // RFC2109 - return "Set-Cookie"; - // return "Set-Cookie2"; - } else { - // Old Netscape - return "Set-Cookie"; - } - } - - // TODO RFC2965 fields also need to be passed - public static void appendCookieValue( StringBuffer headerBuf, - int version, - String name, - String value, - String path, - String domain, - String comment, - int maxAge, - boolean isSecure, - boolean isHttpOnly) - { - StringBuffer buf = new StringBuffer(); - // Servlet implementation checks name - buf.append( name ); - buf.append("="); - // Servlet implementation does not check anything else - - version = maybeQuote2(version, buf, value,true); - - // Add version 1 specific information - if (version == 1) { - // Version=1 ... required - buf.append ("; Version=1"); - - // Comment=comment - if ( comment!=null ) { - buf.append ("; Comment="); - maybeQuote2(version, buf, comment); - } - } - - // Add domain information, if present - if (domain!=null) { - buf.append("; Domain="); - maybeQuote2(version, buf, domain); - } - - // Max-Age=secs ... or use old "Expires" format - // TODO RFC2965 Discard - if (maxAge >= 0) { - if (version > 0) { - buf.append ("; Max-Age="); - buf.append (maxAge); - } - // IE6, IE7 and possibly other browsers don't understand Max-Age. - // They do understand Expires, even with V1 cookies! - if (version == 0 || ALWAYS_ADD_EXPIRES) { - // Wdy, DD-Mon-YY HH:MM:SS GMT ( Expires Netscape format ) - buf.append ("; Expires="); - // To expire immediately we need to set the time in past - if (maxAge == 0) - buf.append( ancientDate ); - else - OLD_COOKIE_FORMAT.get().format( - new Date(System.currentTimeMillis() + - maxAge*1000L), - buf, new FieldPosition(0)); - } - } - - // Path=path - if (path!=null) { - buf.append ("; Path="); - if (version==0) { - maybeQuote2(version, buf, path); - } else { - maybeQuote2(version, buf, path, ServerCookie.tspecials2NoSlash, false); - } - } - - // Secure - if (isSecure) { - buf.append ("; Secure"); - } - - // HttpOnly - if (isHttpOnly) { - buf.append("; HttpOnly"); - } - headerBuf.append(buf); - } - - public static boolean alreadyQuoted (String value) { - if (value==null || value.length()==0) return false; - return (value.charAt(0)=='\"' && value.charAt(value.length()-1)=='\"'); - } - - /** - * Quotes values using rules that vary depending on Cookie version. - * @param version - * @param buf - * @param value - */ - public static int maybeQuote2 (int version, StringBuffer buf, String value) { - return maybeQuote2(version,buf,value,false); - } - - public static int maybeQuote2 (int version, StringBuffer buf, String value, boolean allowVersionSwitch) { - return maybeQuote2(version,buf,value,null,allowVersionSwitch); - } - - public static int maybeQuote2 (int version, StringBuffer buf, String value, String literals, boolean allowVersionSwitch) { - if (value==null || value.length()==0) { - buf.append("\"\""); - }else if (containsCTL(value,version)) - throw new IllegalArgumentException("Control character in cookie value, consider BASE64 encoding your value"); - else if (alreadyQuoted(value)) { - buf.append('"'); - buf.append(escapeDoubleQuotes(value,1,value.length()-1)); - buf.append('"'); - } else if (allowVersionSwitch && (!STRICT_SERVLET_COMPLIANCE) && version==0 && !isToken2(value, literals)) { - buf.append('"'); - buf.append(escapeDoubleQuotes(value,0,value.length())); - buf.append('"'); - version = 1; - } else if (version==0 && !isToken(value,literals)) { - buf.append('"'); - buf.append(escapeDoubleQuotes(value,0,value.length())); - buf.append('"'); - } else if (version==1 && !isToken2(value,literals)) { - buf.append('"'); - buf.append(escapeDoubleQuotes(value,0,value.length())); - buf.append('"'); - }else { - buf.append(value); - } - return version; - } - - - /** - * Escapes any double quotes in the given string. - * - * @param s the input string - * @param beginIndex start index inclusive - * @param endIndex exclusive - * @return The (possibly) escaped string - */ - private static String escapeDoubleQuotes(String s, int beginIndex, int endIndex) { - - if (s == null || s.length() == 0 || s.indexOf('"') == -1) { - return s; - } - - StringBuffer b = new StringBuffer(); - for (int i = beginIndex; i < endIndex; i++) { - char c = s.charAt(i); - if (c == '\\' ) { - b.append(c); - //ignore the character after an escape, just append it - if (++i>=endIndex) throw new IllegalArgumentException("Invalid escape character in cookie value."); - b.append(s.charAt(i)); - } else if (c == '"') - b.append('\\').append('"'); - else - b.append(c); - } - - return b.toString(); - } - - /** - * Unescapes any double quotes in the given cookie value. - * - * @param bc The cookie value to modify - */ - public static void unescapeDoubleQuotes(BBuffer bc) { - - if (bc == null || bc.getLength() == 0 || bc.indexOf('"', 0) == -1) { - return; - } - - int src = bc.getStart(); - int end = bc.getEnd(); - int dest = src; - byte[] buffer = bc.array(); - - while (src < end) { - if (buffer[src] == '\\' && src < end && buffer[src+1] == '"') { - src++; - } - buffer[dest] = buffer[src]; - dest ++; - src ++; - } - bc.setEnd(dest); - } - - /* - List of Separator Characters (see isSeparator()) - Excluding the '/' char violates the RFC, but - it looks like a lot of people put '/' - in unquoted values: '/': ; //47 - '\t':9 ' ':32 '\"':34 '\'':39 '(':40 ')':41 ',':44 ':':58 ';':59 '<':60 - '=':61 '>':62 '?':63 '@':64 '[':91 '\\':92 ']':93 '{':123 '}':125 - */ - public static final char SEPARATORS[] = { '\t', ' ', '\"', '\'', '(', ')', ',', - ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' }; - - protected static final boolean separators[] = new boolean[128]; - static { - for (int i = 0; i < 128; i++) { - separators[i] = false; - } - for (int i = 0; i < SEPARATORS.length; i++) { - separators[SEPARATORS[i]] = true; - } - } - - /** Add all Cookie found in the headers of a request. - */ - public static void processCookies(List cookies, - List cookiesCache, - HttpMessage.HttpMessageBytes msgBytes ) { - - // process each "cookie" header - for (int i = 0; i < msgBytes.headerCount; i++) { - if (msgBytes.getHeaderName(i).equalsIgnoreCase("Cookie")) { - BBuffer bc = msgBytes.getHeaderValue(i); - if (bc.remaining() == 0) { - continue; - } - processCookieHeader(cookies, cookiesCache, - bc.array(), - bc.getOffset(), - bc.getLength()); - - } - - } - } - - /** - * Returns true if the byte is a separator character as - * defined in RFC2619. Since this is called often, this - * function should be organized with the most probable - * outcomes first. - * JVK - */ - private static final boolean isSeparator(final byte c) { - if (c > 0 && c < 126) - return separators[c]; - else - return false; - } - - /** - * Returns true if the byte is a whitespace character as - * defined in RFC2619 - * JVK - */ - private static final boolean isWhiteSpace(final byte c) { - // This switch statement is slightly slower - // for my vm than the if statement. - // Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-164) - /* - switch (c) { - case ' ':; - case '\t':; - case '\n':; - case '\r':; - case '\f':; - return true; - default:; - return false; - } - */ - if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f') - return true; - else - return false; - } - - /** - * Parses a cookie header after the initial "Cookie:" - * [WS][$]token[WS]=[WS](token|QV)[;|,] - * RFC 2965 - * JVK - */ - public static final void processCookieHeader( - List cookies, - List cookiesCache, - byte bytes[], int off, int len){ - if( len<=0 || bytes==null ) return; - int end=off+len; - int pos=off; - int nameStart=0; - int nameEnd=0; - int valueStart=0; - int valueEnd=0; - int version = 0; - ServerCookie sc=null; - boolean isSpecial; - boolean isQuoted; - - while (pos < end) { - isSpecial = false; - isQuoted = false; - - // Skip whitespace and non-token characters (separators) - while (pos < end && - (isSeparator(bytes[pos]) || isWhiteSpace(bytes[pos]))) - {pos++; } - - if (pos >= end) - return; - - // Detect Special cookies - if (bytes[pos] == '$') { - isSpecial = true; - pos++; - } - - // Get the cookie name. This must be a token - valueEnd = valueStart = nameStart = pos; - pos = nameEnd = getTokenEndPosition(bytes,pos,end); - - // Skip whitespace - while (pos < end && isWhiteSpace(bytes[pos])) {pos++; } - - - // Check for an '=' -- This could also be a name-only - // cookie at the end of the cookie header, so if we - // are past the end of the header, but we have a name - // skip to the name-only part. - if (pos < end && bytes[pos] == '=') { - - // Skip whitespace - do { - pos++; - } while (pos < end && isWhiteSpace(bytes[pos])); - - if (pos >= end) - return; - - // Determine what type of value this is, quoted value, - // token, name-only with an '=', or other (bad) - switch (bytes[pos]) { - case '"': // Quoted Value - isQuoted = true; - valueStart=pos + 1; // strip " - // getQuotedValue returns the position before - // at the last qoute. This must be dealt with - // when the bytes are copied into the cookie - valueEnd=getQuotedValueEndPosition(bytes, - valueStart, end); - // We need pos to advance - pos = valueEnd; - // Handles cases where the quoted value is - // unterminated and at the end of the header, - // e.g. [myname="value] - if (pos >= end) - return; - break; - case ';': - case ',': - // Name-only cookie with an '=' after the name token - // This may not be RFC compliant - valueStart = valueEnd = -1; - // The position is OK (On a delimiter) - break; - default: - if (!isSeparator(bytes[pos])) { - // Token - valueStart=pos; - // getToken returns the position at the delimeter - // or other non-token character - valueEnd=getTokenEndPosition(bytes, valueStart, end); - // We need pos to advance - pos = valueEnd; - } else { - // INVALID COOKIE, advance to next delimiter - // The starting character of the cookie value was - // not valid. - //log("Invalid cookie. Value not a token or quoted value"); - while (pos < end && bytes[pos] != ';' && - bytes[pos] != ',') - {pos++; } - pos++; - // Make sure no special avpairs can be attributed to - // the previous cookie by setting the current cookie - // to null - sc = null; - continue; - } - } - } else { - // Name only cookie - valueStart = valueEnd = -1; - pos = nameEnd; - - } - - // We should have an avpair or name-only cookie at this - // point. Perform some basic checks to make sure we are - // in a good state. - - // Skip whitespace - while (pos < end && isWhiteSpace(bytes[pos])) {pos++; } - - - // Make sure that after the cookie we have a separator. This - // is only important if this is not the last cookie pair - while (pos < end && bytes[pos] != ';' && bytes[pos] != ',') { - pos++; - } - - pos++; - - /* - if (nameEnd <= nameStart || valueEnd < valueStart ) { - // Something is wrong, but this may be a case - // of having two ';' characters in a row. - // log("Cookie name/value does not conform to RFC 2965"); - // Advance to next delimiter (ignoring everything else) - while (pos < end && bytes[pos] != ';' && bytes[pos] != ',') - { pos++; }; - pos++; - // Make sure no special cookies can be attributed to - // the previous cookie by setting the current cookie - // to null - sc = null; - continue; - } - */ - - // All checks passed. Add the cookie, start with the - // special avpairs first - if (isSpecial) { - isSpecial = false; - // $Version must be the first avpair in the cookie header - // (sc must be null) - if (equals( "Version", bytes, nameStart, nameEnd) && - sc == null) { - // Set version - if( bytes[valueStart] =='1' && valueEnd == (valueStart+1)) { - version=1; - } else { - // unknown version (Versioning is not very strict) - } - continue; - } - - // We need an active cookie for Path/Port/etc. - if (sc == null) { - continue; - } - - // Domain is more common, so it goes first - if (equals( "Domain", bytes, nameStart, nameEnd)) { - sc.getDomain().setBytes( bytes, - valueStart, - valueEnd-valueStart); - continue; - } - - if (equals( "Path", bytes, nameStart, nameEnd)) { - sc.getPath().setBytes( bytes, - valueStart, - valueEnd-valueStart); - continue; - } - - - if (equals( "Port", bytes, nameStart, nameEnd)) { - // sc.getPort is not currently implemented. - // sc.getPort().setBytes( bytes, - // valueStart, - // valueEnd-valueStart ); - continue; - } - - // Unknown cookie, complain - //log("Unknown Special Cookie"); - - } else { // Normal Cookie - // use a previous value from cache, if any (to avoid GC - tomcat - // legacy ) - if (cookiesCache.size() > cookies.size()) { - sc = cookiesCache.get(cookies.size()); - cookies.add(sc); - } else { - sc = new ServerCookie(); - cookiesCache.add(sc); - cookies.add(sc); - } - sc.setVersion( version ); - sc.getName().append( bytes, nameStart, - nameEnd-nameStart); - - if (valueStart != -1) { // Normal AVPair - sc.getValue().append( bytes, valueStart, - valueEnd-valueStart); - if (isQuoted) { - // We know this is a byte value so this is safe - ServerCookie.unescapeDoubleQuotes( - sc.getValue()); - } - } else { - // Name Only - sc.getValue().recycle(); - } - sc.nameC.recycle(); - sc.nameC.append(sc.getName()); - continue; - } - } - } - - /** - * Given the starting position of a token, this gets the end of the - * token, with no separator characters in between. - * JVK - */ - private static final int getTokenEndPosition(byte bytes[], int off, int end){ - int pos = off; - while (pos < end && !isSeparator(bytes[pos])) {pos++; } - - if (pos > end) - return end; - return pos; - } - - /** - * Given a starting position after an initial quote chracter, this gets - * the position of the end quote. This escapes anything after a '\' char - * JVK RFC 2616 - */ - private static final int getQuotedValueEndPosition(byte bytes[], int off, int end){ - int pos = off; - while (pos < end) { - if (bytes[pos] == '"') { - return pos; - } else if (bytes[pos] == '\\' && pos < (end - 1)) { - pos+=2; - } else { - pos++; - } - } - // Error, we have reached the end of the header w/o a end quote - return end; - } - - - public static boolean equals( String s, byte b[], int start, int end) { - int blen = end-start; - if (b == null || blen != s.length()) { - return false; - } - int boff = start; - for (int i = 0; i < blen; i++) { - if (b[boff++] != s.charAt(i)) { - return false; - } - } - return true; - } - -} - diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/SpdyConnection.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/SpdyConnection.java deleted file mode 100644 index 770ca2ec3fbf..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/SpdyConnection.java +++ /dev/null @@ -1,820 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.http.HttpConnectionPool.RemoteServer; -import org.apache.tomcat.lite.http.HttpMessage.HttpMessageBytes; -import org.apache.tomcat.lite.io.BBucket; -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.CBuffer; -import org.apache.tomcat.lite.io.DumpChannel; -import org.apache.tomcat.lite.io.IOBuffer; -import org.apache.tomcat.lite.io.IOChannel; -import org.apache.tomcat.lite.io.IOConnector; - -/* - * TODO: expectations ? - * Fix docs - order matters - * Crashes in chrome - * - * Test with unit tests or: - * google-chrome --use-flip=no-ssl - * --user-data-dir=/home/$USER/.config/google-chrome/Test - * http://localhost:8802/hello - */ - -public class SpdyConnection extends HttpConnector.HttpConnection - implements IOConnector.ConnectedCallback { - - - /** Use compression for headers. Will magically turn to false - * if the first request doesn't have x8xx ( i.e. compress header ) - */ - boolean headerCompression = true; - boolean firstFrame = true; - - public static long DICT_ID = 3751956914L; - private static String SPDY_DICT_S = - "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-" + - "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi" + - "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser" + - "-agent10010120020120220320420520630030130230330430530630740040140240340440" + - "5406407408409410411412413414415416417500501502503504505accept-rangesageeta" + - "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic" + - "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran" + - "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati" + - "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo" + - "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe" + - "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic" + - "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1" + - ".1statusversionurl "; - public static byte[] SPDY_DICT = SPDY_DICT_S.getBytes(); - // C code uses this - not in the spec - static { - SPDY_DICT[SPDY_DICT.length - 1] = (byte) 0; - } - - - protected static Logger log = Logger.getLogger("SpdyConnection"); - - /** - * @param spdyConnector - * @param remoteServer - */ - SpdyConnection(HttpConnector spdyConnector, RemoteServer remoteServer) { - this.httpConnector = spdyConnector; - this.remoteHost = remoteServer; - this.target = remoteServer.target; - } - - AtomicInteger streamErrors = new AtomicInteger(); - - AtomicInteger lastInStream = new AtomicInteger(); - AtomicInteger lastOutStream = new AtomicInteger(); - - // TODO: use int map - Map channels = new HashMap(); - - SpdyConnection.Frame currentInFrame = null; - - SpdyConnection.Frame lastFrame = null; // for debug - - BBuffer outFrameBuffer = BBuffer.allocate(); - BBuffer inFrameBuffer = BBuffer.allocate(); - - BBuffer headW = BBuffer.wrapper(); - - CompressFilter headCompressIn = new CompressFilter() - .setDictionary(SPDY_DICT, DICT_ID); - - CompressFilter headCompressOut = new CompressFilter() - .setDictionary(SPDY_DICT, DICT_ID); - - IOBuffer headerCompressBuffer = new IOBuffer(); - IOBuffer headerDeCompressBuffer = new IOBuffer(); - - AtomicInteger inFrames = new AtomicInteger(); - AtomicInteger inDataFrames = new AtomicInteger(); - AtomicInteger inSyncStreamFrames = new AtomicInteger(); - AtomicInteger inBytes = new AtomicInteger(); - - AtomicInteger outFrames = new AtomicInteger(); - AtomicInteger outDataFrames = new AtomicInteger(); - AtomicInteger outBytes = new AtomicInteger(); - - - volatile boolean connecting = false; - volatile boolean connected = false; - - // TODO: detect if it's spdy or http based on bit 8 - - @Override - public void withExtraBuffer(BBuffer received) { - inFrameBuffer = received; - } - - @Override - public void dataReceived(IOBuffer iob) throws IOException { - // Only one thread doing receive at a time. - synchronized (inFrameBuffer) { - while (true) { - int avail = iob.available(); - if (avail == 0) { - return; - } - if (currentInFrame == null) { - if (inFrameBuffer.remaining() + avail < 8) { - return; - } - if (inFrameBuffer.remaining() < 8) { - int headRest = 8 - inFrameBuffer.remaining(); - int rd = iob.read(inFrameBuffer, headRest); - } - currentInFrame = new SpdyConnection.Frame(); // TODO: reuse - currentInFrame.parse(this, inFrameBuffer); - } - if (iob.available() < currentInFrame.length) { - return; - } - // We have a full frame. Process it. - onFrame(iob); - - // TODO: extra checks, make sure the frame is correct and - // it consumed all data. - currentInFrame = null; - } - } - } - - - /** - * Frame received. Must consume all data for the frame. - * - * @param iob - * @throws IOException - */ - protected void onFrame(IOBuffer iob) throws IOException { - // TODO: make sure we have enough data. - lastFrame = currentInFrame; - inFrames.incrementAndGet(); - inBytes.addAndGet(currentInFrame.length + 8); - - if (currentInFrame.c) { - if (currentInFrame.type == SpdyConnection.Frame.TYPE_HELO) { - // receivedHello = currentInFrame; - } else if (currentInFrame.type == SpdyConnection.Frame.TYPE_SYN_STREAM) { - inSyncStreamFrames.incrementAndGet(); - HttpChannel ch = new HttpChannel(); // TODO: reuse - ch.channelId = SpdyConnection.readInt(iob); - ch.setConnection(this); - ch.httpConnector = this.httpConnector; - if (serverMode) { - ch.serverMode(true); - } - if (this.httpConnector.defaultService != null) { - ch.setHttpService(this.httpConnector.defaultService); - } - - synchronized (channels) { - channels.put(ch.channelId, ch); - } - - try { - // pri and unused - SpdyConnection.readShort(iob); - - HttpMessageBytes reqBytes = ch.getRequest().getMsgBytes(); - - processHeaders(iob, ch, reqBytes); - } catch (Throwable t) { - log.log(Level.SEVERE, "Error parsing head", t); - abort("Error reading headers " + t); - return; - } - ch.getRequest().processReceivedHeaders(); - - ch.handleHeadersReceived(ch.getRequest()); - - if ((currentInFrame.flags & SpdyConnection.Frame.FLAG_HALF_CLOSE) != 0) { - ch.getIn().close(); - ch.handleEndReceive(); - } - } else if (currentInFrame.type == SpdyConnection.Frame.TYPE_SYN_REPLY) { - int chId = SpdyConnection.readInt(iob); - HttpChannel ch; - synchronized (channels) { - ch = channels.get(chId); - if (ch == null) { - abort("Channel not found"); - } - } - try { - SpdyConnection.readShort(iob); - - HttpMessageBytes resBytes = ch.getResponse().getMsgBytes(); - - BBuffer head = processHeaders(iob, ch, resBytes); - } catch (Throwable t) { - log.log(Level.SEVERE, "Error parsing head", t); - abort("Error reading headers " + t); - return; - } - ch.getResponse().processReceivedHeaders(); - - ch.handleHeadersReceived(ch.getResponse()); - - if ((currentInFrame.flags & SpdyConnection.Frame.FLAG_HALF_CLOSE) != 0) { - ch.getIn().close(); - ch.handleEndReceive(); - } - } else { - log.warning("Unknown frame type " + currentInFrame.type); - iob.advance(currentInFrame.length); - } - } else { - inDataFrames.incrementAndGet(); - // data frame - part of an existing stream - HttpChannel ch; - synchronized (channels) { - ch = channels.get(currentInFrame.streamId); - } - if (ch == null) { - log.warning("Unknown stream "); - net.close(); - net.startSending(); - return; - } - int len = currentInFrame.length; - while (len > 0) { - BBucket bb = iob.peekFirst(); - if (bb == null) { - // we should have all data - abort("Unexpected short read"); - return; - } - if (len > bb.remaining()) { - ch.getIn().append(bb); - len -= bb.remaining(); - bb.position(bb.limit()); - } else { - ch.getIn().append(bb, len); - bb.position(bb.position() + len); - len = 0; - } - } - ch.sendHandleReceivedCallback(); - - if ((currentInFrame.flags & SpdyConnection.Frame.FLAG_HALF_CLOSE) != 0) { - ch.handleEndReceive(); - } - } - firstFrame = false; - } - - /** - * On frame error. - */ - private void abort(String msg) throws IOException { - streamErrors.incrementAndGet(); - synchronized(channels) { - for (HttpChannel ch : channels.values()) { - ch.abort(msg); - } - } - close(); - } - - private BBuffer processHeaders(IOBuffer iob, HttpChannel ch, - HttpMessageBytes reqBytes) throws IOException { - int nvCount = 0; - if (firstFrame) { - int res = iob.peek() & 0xFF; - if ((res & 0x0F) != 8) { - headerCompression = false; - } - } - headRecvBuf.recycle(); - if (headerCompression) { - // 0x800 headers seems a bit too much - assume compressed. - // I wish this was a flag... - headerDeCompressBuffer.recycle(); - // stream id ( 4 ) + unused ( 2 ) - // nvCount is compressed in impl - spec is different - headCompressIn.decompress(iob, headerDeCompressBuffer, - currentInFrame.length - 6); - headerDeCompressBuffer.copyAll(headRecvBuf); - headerDeCompressBuffer.recycle(); - nvCount = readShort(headRecvBuf); - } else { - nvCount = readShort(iob); - // 8 = stream Id (4) + pri/unused (2) + nvCount (2) - // we know we have enough data - int rd = iob.read(headRecvBuf, currentInFrame.length - 8); - if (rd != currentInFrame.length - 8) { - abort("Unexpected incomplete read"); - } - } - // Wrapper - so we don't change position in head - headRecvBuf.wrapTo(headW); - - BBuffer nameBuf = BBuffer.wrapper(); - BBuffer valBuf = BBuffer.wrapper(); - - for (int i = 0; i < nvCount; i++) { - - int nameLen = SpdyConnection.readShort(headW); - if (nameLen > headW.remaining()) { - abort("Name too long"); - } - - nameBuf.setBytes(headW.array(), headW.position(), - nameLen); - headW.advance(nameLen); - - int valueLen = SpdyConnection.readShort(headW); - valBuf.setBytes(headW.array(), headW.position(), - valueLen); - headW.advance(valueLen); - - // TODO: no need to send version, method if default - - if (nameBuf.equals("method")) { - valBuf.wrapTo(reqBytes.method()); - } else if (nameBuf.equals("version")) { - valBuf.wrapTo(reqBytes.protocol()); - } else if (nameBuf.equals("url")) { - valBuf.wrapTo(reqBytes.url()); - // TODO: spdy uses full URL, we may want to trim - // also no host header - } else { - int idx = reqBytes.addHeader(); - nameBuf.wrapTo(reqBytes.getHeaderName(idx)); - valBuf.wrapTo(reqBytes.getHeaderValue(idx)); - } - - // TODO: repeated values are separated by a 0 - } - return headW; - } - - @Override - protected synchronized void sendRequest(HttpChannel http) throws IOException { - if (serverMode) { - throw new IOException("Only in client mode"); - } - if (!checkConnection(http)) { - return; - } - MultiMap mimeHeaders = http.getRequest().getMimeHeaders(); - - BBuffer headBuf = BBuffer.allocate(); - SpdyConnection.appendShort(headBuf, mimeHeaders.size() + 3); - serializeMime(mimeHeaders, headBuf); - - // TODO: url - with host prefix , method - // optimize... - SpdyConnection.appendAsciiHead(headBuf, "version"); - SpdyConnection.appendAsciiHead(headBuf, "HTTP/1.1"); - - SpdyConnection.appendAsciiHead(headBuf, "method"); - SpdyConnection.appendAsciiHead(headBuf, http.getRequest().getMethod()); - - SpdyConnection.appendAsciiHead(headBuf, "url"); - // TODO: url - SpdyConnection.appendAsciiHead(headBuf, http.getRequest().requestURL()); - - if (headerCompression && httpConnector.compression) { - headerCompressBuffer.recycle(); - headCompressOut.compress(headBuf, headerCompressBuffer, false); - headBuf.recycle(); - headerCompressBuffer.copyAll(headBuf); - } - - // Frame head - 8 - BBuffer out = BBuffer.allocate(); - // Syn-reply - out.putByte(0x80); - out.putByte(0x01); - out.putByte(0x00); - out.putByte(0x01); - - CBuffer method = http.getRequest().method(); - if (method.equals("GET") || method.equals("HEAD")) { - http.getOut().close(); - } - - if (http.getOut().isAppendClosed()) { - out.putByte(0x01); // closed - } else { - out.putByte(0x00); - } - - // Length, channel id (4) + unused (2) - headBuf has header count - // and headers - SpdyConnection.append24(out, headBuf.remaining() + 6); - - if (serverMode) { - http.channelId = 2 * lastOutStream.incrementAndGet(); - } else { - http.channelId = 2 * lastOutStream.incrementAndGet() + 1; - } - SpdyConnection.appendInt(out, http.channelId); - - http.setConnection(this); - - synchronized (channels) { - channels.put(http.channelId, http); - } - - out.putByte(0x00); // no priority - out.putByte(0x00); - - sendFrame(out, headBuf); - - if (http.outMessage.state == HttpMessage.State.HEAD) { - http.outMessage.state = HttpMessage.State.BODY_DATA; - } - if (http.getOut().isAppendClosed()) { - http.handleEndSent(); - } - - // Any existing data - //sendData(http); - } - - - public synchronized Collection getActives() { - synchronized(channels) { - return channels.values(); - } - } - - @Override - protected synchronized void sendResponseHeaders(HttpChannel http) throws IOException { - if (!serverMode) { - throw new IOException("Only in server mode"); - } - - if (http.getResponse().isCommitted()) { - return; - } - http.getResponse().setCommitted(true); - - MultiMap mimeHeaders = http.getResponse().getMimeHeaders(); - - BBuffer headBuf = BBuffer.allocate(); - - - //mimeHeaders.remove("content-length"); - BBuffer headers = headBuf; - if (headerCompression) { - headers = BBuffer.allocate(); - } - - //SpdyConnection.appendInt(headers, http.channelId); - //headers.putByte(0); - //headers.putByte(0); - SpdyConnection.appendShort(headers, mimeHeaders.size() + 2); - - // chrome will crash if we don't send the header - serializeMime(mimeHeaders, headers); - - // Must be at the end - SpdyConnection.appendAsciiHead(headers, "status"); - SpdyConnection.appendAsciiHead(headers, - Integer.toString(http.getResponse().getStatus())); - - SpdyConnection.appendAsciiHead(headers, "version"); - SpdyConnection.appendAsciiHead(headers, "HTTP/1.1"); - - if (headerCompression) { - headerCompressBuffer.recycle(); - headCompressOut.compress(headers, headerCompressBuffer, false); - headerCompressBuffer.copyAll(headBuf); - headerCompressBuffer.recycle(); - } - - BBuffer frameHead = BBuffer.allocate(); - // Syn-reply - frameHead.putByte(0x80); // Control - frameHead.putByte(0x01); // version - frameHead.putByte(0x00); // 00 02 - SYN_REPLY - frameHead.putByte(0x02); - - // It seems piggibacking data is not allowed - frameHead.putByte(0x00); - - int len = headBuf.remaining() + 6; - SpdyConnection.append24(frameHead, len); - -// // Stream-Id, unused - SpdyConnection.appendInt(frameHead, http.channelId); - frameHead.putByte(0); - frameHead.putByte(0); - - sendFrame(frameHead, headBuf); - } - - - public void startSending(HttpChannel http) throws IOException { - http.send(); // if needed - - if (net != null) { - sendData(http); - net.startSending(); - } - } - - private void sendData(HttpChannel http) throws IOException { - int avail = http.getOut().available(); - boolean closed = http.getOut().isAppendClosed(); - if (avail > 0 || closed) { - sendDataFrame(http.getOut(), avail, - http.channelId, closed); - if (avail > 0) { - getOut().advance(avail); - } - } - if (closed) { - http.handleEndSent(); - } - } - - private BBuffer serializeMime(MultiMap mimeHeaders, BBuffer headBuf) - throws IOException { - - // TODO: duplicated headers not allowed - for (int i = 0; i < mimeHeaders.size(); i++) { - CBuffer name = mimeHeaders.getName(i); - CBuffer value = mimeHeaders.getValue(i); - if (name.length() == 0 || value.length() == 0) { - continue; - } - SpdyConnection.appendShort(headBuf, name.length()); - name.toAscii(headBuf); - SpdyConnection.appendShort(headBuf, value.length()); - value.toAscii(headBuf); - } - return headBuf; - } - - - private synchronized void sendFrame(BBuffer out, BBuffer headBuf) - throws IOException { - if (net == null) { - return; // unit test - } - outBytes.addAndGet(out.remaining()); - net.getOut().append(out); - if (headBuf != null) { - net.getOut().append(headBuf); - outBytes.addAndGet(headBuf.remaining()); - } - net.startSending(); - outFrames.incrementAndGet(); - } - - public synchronized void sendDataFrame(IOBuffer out2, int avail, - int channelId, boolean last) throws IOException { - if (net == null) { - return; // unit test - } - outFrameBuffer.recycle(); - SpdyConnection.appendInt(outFrameBuffer, channelId); // first bit 0 ? - if (last) { - outFrameBuffer.putByte(0x01); // closed - } else { - outFrameBuffer.putByte(0x00); - } - - // TODO: chunk if too much data ( at least at 24 bits) - SpdyConnection.append24(outFrameBuffer, avail); - - outBytes.addAndGet(outFrameBuffer.remaining() + avail); - net.getOut().append(outFrameBuffer); - - if (avail > 0) { - net.getOut().append(out2, avail); - } - net.startSending(); - outDataFrames.incrementAndGet(); - } - - static void appendInt(BBuffer headBuf, int length) throws IOException { - headBuf.putByte((length & 0xFF000000) >> 24); - headBuf.putByte((length & 0xFF0000) >> 16); - headBuf.putByte((length & 0xFF00) >> 8); - headBuf.putByte((length & 0xFF)); - } - - static void append24(BBuffer headBuf, int length) throws IOException { - headBuf.putByte((length & 0xFF0000) >> 16); - headBuf.putByte((length & 0xFF00) >> 8); - headBuf.putByte((length & 0xFF)); - } - - static void appendAsciiHead(BBuffer headBuf, CBuffer s) throws IOException { - appendShort(headBuf, s.length()); - for (int i = 0; i < s.length(); i++) { - headBuf.append(s.charAt(i)); - } - } - - static void appendShort(BBuffer headBuf, int length) throws IOException { - if (length > 0xFFFF) { - throw new IOException("Too long"); - } - headBuf.putByte((length & 0xFF00) >> 8); - headBuf.putByte((length & 0xFF)); - } - - static void appendAsciiHead(BBuffer headBuf, String s) throws IOException { - SpdyConnection.appendShort(headBuf, s.length()); - for (int i = 0; i < s.length(); i++) { - headBuf.append(s.charAt(i)); - } - } - - static int readShort(BBuffer iob) throws IOException { - int res = iob.readByte(); - return res << 8 | iob.readByte(); - } - - static int readShort(IOBuffer iob) throws IOException { - int res = iob.read(); - return res << 8 | iob.read(); - } - - static int readInt(IOBuffer iob) throws IOException { - int res = 0; - for (int i = 0; i < 4; i++) { - int b0 = iob.read(); - res = res << 8 | b0; - } - return res; - } - - public static class Frame { - int flags; - - int length; - - boolean c; // for control - - int version; - - int type; - - int streamId; // for data - - static int TYPE_HELO = 4; - - static int TYPE_SYN_STREAM = 1; - - static int TYPE_SYN_REPLY = 2; - - static int FLAG_HALF_CLOSE = 1; - - public void parse(SpdyConnection spdyConnection, - BBuffer iob) throws IOException { - int b0 = iob.read(); - if (b0 < 128) { - // data frame - c = false; - streamId = b0; - for (int i = 0; i < 3; i++) { - b0 = iob.read(); - streamId = streamId << 8 | b0; - } - } else { - c = true; - b0 -= 128; - version = ((b0 << 8) | iob.read()); - if (version != 1) { - spdyConnection.abort("Wrong version"); - return; - } - b0 = iob.read(); - type = ((b0 << 8) | iob.read()); - } - - flags = iob.read(); - for (int i = 0; i < 3; i++) { - b0 = iob.read(); - length = length << 8 | b0; - } - - iob.recycle(); - } - - } - - @Override - protected void endSendReceive(HttpChannel http) throws IOException { - synchronized (channels) { - HttpChannel doneHttp = channels.remove(http.channelId); - if (doneHttp != http) { - log.severe("Error removing " + doneHttp + " " + http); - } - } - httpConnector.cpool.afterRequest(http, this, true); - } - - /** - * Framing error, client interrupt, etc. - */ - public void abort(HttpChannel http, String t) throws IOException { - // TODO: send interrupt signal - - } - - - private boolean checkConnection(HttpChannel http) throws IOException { - synchronized(this) { - if (net == null || !isOpen()) { - connected = false; - } - - if (!connected) { - if (!connecting) { - // TODO: secure set at start ? - connecting = true; - httpConnector.cpool.httpConnect(http, - target.toString(), - http.getRequest().isSecure(), this); - } - - synchronized (remoteHost) { - remoteHost.pending.add(http); - httpConnector.cpool.queued.incrementAndGet(); - } - return false; - } - } - - return true; - } - - @Override - public void handleConnected(IOChannel net) throws IOException { - HttpChannel httpCh = null; - if (!net.isOpen()) { - while (true) { - synchronized (remoteHost) { - if (remoteHost.pending.size() == 0) { - return; - } - httpCh = remoteHost.pending.remove(); - } - httpCh.abort("Can't connect"); - } - } - - synchronized (remoteHost) { - httpCh = remoteHost.pending.peek(); - } - if (httpCh != null) { - secure = httpCh.getRequest().isSecure(); - if (secure) { - if (httpConnector.debugHttp) { - net = DumpChannel.wrap("SPDY-SSL", net); - } - String[] hostPort = httpCh.getTarget().split(":"); - - IOChannel ch1 = httpConnector.sslProvider.channel(net, - hostPort[0], Integer.parseInt(hostPort[1])); - //net.setHead(ch1); - net = ch1; - } - } - if (httpConnector.debugHttp) { - net = DumpChannel.wrap("SPDY", net); - } - - setSink(net); - - synchronized(this) { - connecting = false; - connected = true; - } - - while (true) { - synchronized (remoteHost) { - if (remoteHost.pending.size() == 0) { - return; - } - httpCh = remoteHost.pending.remove(); - } - sendRequest(httpCh); - } - - } -} \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/http/package.html b/modules/tomcat-lite/java/org/apache/tomcat/lite/http/package.html deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/BBucket.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/BBucket.java deleted file mode 100644 index e68c62bc8afa..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/BBucket.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.nio.ByteBuffer; - - - -/** - * Holds raw data. Similar interface with a ByteBuffer in 'channel write' - * or 'read mode'. Data is between position and limit - there is no - * switching. - * - * TODO: FileBucket, DirectBufferBucket, CharBucket, ... - * - * @author Costin Manolache - */ -public interface BBucket { - - public void release(); - - public byte[] array(); - public int position(); - public int remaining(); - public int limit(); - - public boolean hasRemaining(); - - public void position(int newStart); - - /** - * Return a byte buffer, with data between position and limit. - * Changes in the ByteBuffer position will not be reflected - * in the IOBucket. - * - * @return - */ - public ByteBuffer getByteBuffer(); - - -} \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/BBuffer.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/BBuffer.java deleted file mode 100644 index f4053a056d08..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/BBuffer.java +++ /dev/null @@ -1,1204 +0,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.lite.io; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Serializable; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; - -/* - * In a server it is very important to be able to operate on - * the original byte[] without converting everything to chars. - * Some protocols are ASCII only, and some allow different - * non-UNICODE encodings. The encoding is not known beforehand, - * and can even change during the execution of the protocol. - * ( for example a multipart message may have parts with different - * encoding ) - * - * For HTTP it is not very clear how the encoding of RequestURI - * and mime values can be determined, but it is a great advantage - * to be able to parse the request without converting to string. - */ - -// Renamed from ByteChunk to make it easier to write code using both - -/** - * This class is used to represent a chunk of bytes, and utilities to manipulate - * byte[]. - * - * The buffer can be modified and used for both input and output. - * - * There are 2 modes: The chunk can be associated with a sink - ByteInputChannel - * or ByteOutputChannel, which will be used when the buffer is empty ( on input - * ) or filled ( on output ). For output, it can also grow. This operating mode - * is selected by calling setLimit() or allocate(initial, limit) with limit != - * -1. - * - * Various search and append method are defined - similar with String and - * StringBuffer, but operating on bytes. - * - * This is important because it allows processing the http headers directly on - * the received bytes, without converting to chars and Strings until the strings - * are needed. In addition, the charset is determined later, from headers or - * user code. - * - * - * @author dac@sun.com - * @author James Todd [gonzo@sun.com] - * @author Costin Manolache - * @author Remy Maucherat - */ -public class BBuffer implements Cloneable, Serializable, - BBucket { - - /** - * Default encoding used to convert to strings. It should be UTF8, but: - * - the servlet API requires 8859_1 as default - * - - */ - public static final String DEFAULT_CHARACTER_ENCODING = "ISO-8859-1"; - - // byte[] - private byte[] buff; - - private int start = 0; - - private int end; - - private ByteBuffer byteBuffer; - - public static final String CRLF = "\r\n"; - - /* Various constant "strings" */ - public static final byte[] CRLF_BYTES = convertToBytes(BBuffer.CRLF); - - /** - * HT. - */ - public static final byte HT = (byte) '\t'; - - /** - * SP. - */ - public static final byte SP = (byte) ' '; - - /** - * LF. - */ - public static final byte LF = (byte) '\n'; - - /** - * CR. - */ - public static final byte CR = (byte) '\r'; - - //private int useCount; - - - private static final boolean[] isDigit = new boolean[256]; - - static Charset UTF8; - - public static final byte A = (byte) 'A'; - - public static final byte Z = (byte) 'Z'; - - public static final byte a = (byte) 'a'; - - public static final byte LC_OFFSET = A - a; - private static final byte[] toLower = new byte[256]; - private static final boolean[] isUpper = new boolean[256]; - - static { - for (int i = 0; i < 256; i++) { - toLower[i] = (byte)i; - } - - for (int lc = 'a'; lc <= 'z'; lc++) { - int uc = lc + 'A' - 'a'; - toLower[uc] = (byte)lc; - isUpper[uc] = true; - } - } - - static { - for (int d = '0'; d <= '9'; d++) { - isDigit[d] = true; - } - UTF8 = Charset.forName("UTF-8"); - } - - public static BBuffer allocate() { - return new BBuffer(); - } - - public static BBuffer allocate(int initial) { - return new BBuffer().makeSpace(initial); - } - - - public static BBuffer allocate(String msg) { - BBuffer bc = allocate(); - byte[] data = msg.getBytes(); - bc.append(data, 0, data.length); - return bc; - } - - public static BBuffer wrapper(String msg) { - BBuffer bc = new IOBucketWrap(); - byte[] data = msg.getBytes(); - bc.setBytes(data, 0, data.length); - return bc; - } - - public static BBuffer wrapper() { - return new IOBucketWrap(); - } - - public static BBuffer wrapper(BBuffer bb) { - BBuffer res = new IOBucketWrap(); - res.setBytes(bb.array(), bb.position(), bb.remaining()); - return res; - } - - public static BBuffer wrapper(byte b[], int off, int len) { - BBuffer res = new IOBucketWrap(); - res.setBytes(b, off, len); - return res; - } - - public static BBuffer wrapper(BBucket bb, int start, int len) { - BBuffer res = new IOBucketWrap(); - res.setBytes(bb.array(), bb.position() + start, len); - return res; - } - - /** - * Creates a new, uninitialized ByteChunk object. - */ - private BBuffer() { - } - - public void append(BBuffer src) { - append(src.array(), src.getStart(), src.getLength()); - } - - /** - * Add data to the buffer - */ - public void append(byte src[], int off, int len) { - // will grow, up to limit - makeSpace(len); - - // assert: makeSpace made enough space - System.arraycopy(src, off, buff, end, len); - end += len; - return; - } - - // -------------------- Adding data to the buffer -------------------- - /** - * Append a char, by casting it to byte. This IS NOT intended for unicode. - * - * @param c - */ - public void append(char c) { - put((byte) c); - } - - // -------------------- Removing data from the buffer -------------------- - - /** - * Returns the message bytes. - */ - @Override - public byte[] array() { - return buff; - } - - public int capacity() { - return buff.length; - } - - public boolean equals(BBuffer bb) { - return equals(bb.array(), bb.getStart(), bb.getLength()); - } - - public boolean equals(byte b2[], int off2, int len2) { - byte b1[] = buff; - if (b1 == null && b2 == null) - return true; - - int len = end - start; - if (len2 != len || b1 == null || b2 == null) - return false; - - int off1 = start; - - while (len-- > 0) { - if (b1[off1++] != b2[off2++]) { - return false; - } - } - return true; - } - - - public boolean equals(char c2[], int off2, int len2) { - // XXX works only for enc compatible with ASCII/UTF !!! - byte b1[] = buff; - if (c2 == null && b1 == null) - return true; - - if (b1 == null || c2 == null || end - start != len2) { - return false; - } - int off1 = start; - int len = end - start; - - while (len-- > 0) { - if ((char) b1[off1++] != c2[off2++]) { - return false; - } - } - return true; - } - - // -------------------- Conversion and getters -------------------- - - /** - * Compares the message bytes to the specified String object. - * - * @param s - * the String to compare - * @return true if the comparison succeeded, false otherwise - */ - public boolean equals(String s) { - // XXX ENCODING - this only works if encoding is UTF8-compat - // ( ok for tomcat, where we compare ascii - header names, etc )!!! - - byte[] b = buff; - int blen = end - start; - if (b == null || blen != s.length()) { - return false; - } - int boff = start; - for (int i = 0; i < blen; i++) { - if (b[boff++] != s.charAt(i)) { - return false; - } - } - return true; - } - - /** - * Compares the message bytes to the specified String object. - * - * @param s - * the String to compare - * @return true if the comparison succeeded, false otherwise - */ - public boolean equalsIgnoreCase(String s) { - byte[] b = buff; - int blen = end - start; - if (b == null || blen != s.length()) { - return false; - } - int boff = start; - for (int i = 0; i < blen; i++) { - if (toLower(b[boff++]) != toLower(s.charAt(i))) { - return false; - } - } - return true; - } - - public int get(int off) { - if (start + off >= end) { - throw new ArrayIndexOutOfBoundsException(); - } - return buff[start + off] & 0xFF; - } - - /** - * Return a byte buffer. Changes in the ByteBuffer position will - * not be reflected in the IOBucket - * @return - */ - public ByteBuffer getByteBuffer() { - if (byteBuffer == null || byteBuffer.array() != buff) { - byteBuffer = ByteBuffer.wrap(buff, start, end - start); - } else { - byteBuffer.position(start); - byteBuffer.limit(end); - } - return byteBuffer; - } - - // -------------------- - public BBuffer getClone() { - try { - return (BBuffer) this.clone(); - } catch (Exception ex) { - return null; - } - } - - public int getEnd() { - return end; - } - - public int getInt() { - return parseInt(buff, start, end - start); - } - /** - * Returns the length of the bytes. XXX need to clean this up - */ - public int getLength() { - return end - start; - } - - public long getLong() { - return parseLong(buff, start, end - start); - } - - public int getOffset() { - return start; - } - - // -------------------- equals -------------------- - - /** - * Returns the start offset of the bytes. For output this is the end of the - * buffer. - */ - public int getStart() { - return start; - } - - public ByteBuffer getWriteByteBuffer(int space) { - if (space == 0) { - space = 16; - } - makeSpace(space); - if (byteBuffer == null || byteBuffer.array() != buff) { - byteBuffer = ByteBuffer.wrap(buff, end, buff.length); - } else { - byteBuffer.position(end); - byteBuffer.limit(buff.length); - } - return byteBuffer; - } - - // -------------------- Hash code -------------------- - public int hashCode() { - return hashBytes(buff, start, end - start); - } - - public boolean hasLFLF() { - return hasLFLF(this); - } - - public boolean hasRemaining() { - return start < end; - } - - /** - * Returns true if the message bytes starts with the specified string. - * - * @param s - * the string - */ -// public boolean startsWith(String s) { -// // Works only if enc==UTF -// byte[] b = buff; -// int blen = s.length(); -// if (b == null || blen > end - start) { -// return false; -// } -// int boff = start; -// for (int i = 0; i < blen; i++) { -// if (b[boff++] != s.charAt(i)) { -// return false; -// } -// } -// return true; -// } - - /* Returns true if the message bytes start with the specified byte array */ -// public boolean startsWith(byte[] b2) { -// byte[] b1 = buff; -// if (b1 == null && b2 == null) { -// return true; -// } -// -// int len = end - start; -// if (b1 == null || b2 == null || b2.length > len) { -// return false; -// } -// for (int i = start, j = 0; i < end && j < b2.length;) { -// if (b1[i++] != b2[j++]) -// return false; -// } -// return true; -// } - - /** - * Returns true if the message bytes starts with the specified string. - * - * @param c - * the character - * @param starting - * The start position - */ - public int indexOf(char c, int starting) { - int ret = indexOf(buff, start + starting, end, c); - return (ret >= start) ? ret - start : -1; - } - - /** - * Returns true if the message bytes starts with the specified string. - * - * @param s - * the string - * @param pos - * The position - */ -// public boolean startsWithIgnoreCase(String s, int pos) { -// byte[] b = buff; -// int len = s.length(); -// if (b == null || len + pos > end - start) { -// return false; -// } -// int off = start + pos; -// for (int i = 0; i < len; i++) { -// if (Ascii.toLower(b[off++]) != Ascii.toLower(s.charAt(i))) { -// return false; -// } -// } -// return true; -// } - public int indexOf(String src) { - return indexOf(src, 0, src.length(), 0); - } - - public int indexOf(String src, int srcOff, int srcLen, int myOff) { - if ("".equals(src)) { - return myOff; - } - char first = src.charAt(srcOff); - - // Look for first char - int srcEnd = srcOff + srcLen; - - for (int i = myOff + start; i <= (end - srcLen); i++) { - if (buff[i] != first) - continue; - // found first char, now look for a match - int myPos = i + 1; - for (int srcPos = srcOff + 1; srcPos < srcEnd;) { - if (buff[myPos++] != src.charAt(srcPos++)) - break; - if (srcPos == srcEnd) - return i - start; // found it - } - } - return -1; - } - - // hash ignoring case -// public int hashIgnoreCase() { -// return hashBytesIC(buff, start, end - start); -// } - - public boolean isNull() { - return start == end; - } - -// private static int hashBytesIC(byte bytes[], int start, int bytesLen) { -// int max = start + bytesLen; -// byte bb[] = bytes; -// int code = 0; -// for (int i = start; i < max; i++) { -// code = code * 37 + Ascii.toLower(bb[i]); -// } -// return code; -// } - - @Override - public int limit() { - return end; - } - - public void limit(int newEnd) { - end = newEnd; - } - - /** - * Make space for len chars. - * If len is small, allocate a reserve space too. - */ - public BBuffer makeSpace(int count) { - byte[] tmp = null; - - int newSize; - int desiredSize = end + count; - - if (buff == null) { - if (desiredSize < 16) - desiredSize = 16; // take a minimum - buff = new byte[desiredSize]; - start = 0; - end = 0; - return this; - } - - // limit < buf.length ( the buffer is already big ) - // or we already have space XXX - if (desiredSize <= buff.length) { - return this; - } - // grow in larger chunks - if (desiredSize < 2 * buff.length) { - newSize = buff.length * 2; - tmp = new byte[newSize]; - } else { - newSize = buff.length * 2 + count; - tmp = new byte[newSize]; - } - - System.arraycopy(buff, start, tmp, 0, end - start); - buff = tmp; - tmp = null; - end = end - start; - start = 0; - return this; - } - -// /** -// * Find a character, no side effects. -// * -// * @return index of char if found, -1 if not -// */ -// public static int findChars(byte buf[], int start, int end, byte c[]) { -// int clen = c.length; -// int offset = start; -// while (offset < end) { -// for (int i = 0; i < clen; i++) -// if (buf[offset] == c[i]) { -// return offset; -// } -// offset++; -// } -// return -1; -// } - -// /** -// * Find the first character != c -// * -// * @return index of char if found, -1 if not -// */ -// public static int findNotChars(byte buf[], int start, int end, byte c[]) { -// int clen = c.length; -// int offset = start; -// boolean found; -// -// while (offset < end) { -// found = true; -// for (int i = 0; i < clen; i++) { -// if (buf[offset] == c[i]) { -// found = false; -// break; -// } -// } -// if (found) { // buf[offset] != c[0..len] -// return offset; -// } -// offset++; -// } -// return -1; -// } - - @Override - public int position() { - return start; - } - - public void advance(int len) { - start += len; - } - - @Override - public void position(int newStart) { - start = newStart; - } - - public void put(byte b) { - makeSpace(1); - buff[end++] = b; - } - - public void putByte(int b) { - makeSpace(1); - buff[end++] = (byte) b; - } - - public int read(BBuffer res) { - res.setBytes(buff, start, remaining()); - end = start; - return res.remaining(); - } - - /** - * Read a chunk from is. - * - * You don't need to use buffered input stream, we do the - * buffering. - */ - public int read(InputStream is) throws IOException { - makeSpace(1024); - int res = is.read(buff, end, buff.length - end); - if (res > 0) { - end += res; - } - return res; - } - - public int readAll(InputStream is) throws IOException { - int size = 0; - while (true) { - int res = read(is); - if (res < 0) { - return size; - } - size += res; - } - } - - public int readByte() { - if (start == end) { - return -1; - } - return buff[start++]; - } - - - /** - * Read a line - excluding the line terminator, which is consummed as - * well but not included in the response. - * - * Line can end with CR, LF or CR/LF - * - * @param res - * @return number of bytes read, or -1 if line ending not found in buffer. - */ - public int readLine(BBuffer res) { - int cstart = start; - while(start < end) { - byte chr = buff[start++]; - if (chr == CR || chr == LF) { - res.setBytes(buff, cstart, start - cstart -1); - if (chr == CR) { - if (start < end) { - byte chr2 = buff[start]; - if (chr2 == LF) { - start++; - } - } - } - return res.remaining(); - } - } - start = cstart; - return -1; - } - /** - * Consume up to but not including delim. - * - */ - public final int readToDelimOrSpace(byte delim, - BBuffer res) { - int resStart = start; - while (true) { - if (start >= end) { - break; - } - byte chr = buff[start]; - if (chr == delim || chr == SP || chr == HT) { - break; - } - start++; - } - res.setBytes(buff, resStart, start - resStart); - return res.remaining(); - } - - - /** - * Consume all up to the first space or \t, which will be the - * first character in the buffer. - * - * Consumed data is wrapped in res. - */ - public int readToSpace(BBuffer res) { - int resStart = start; - while (true) { - if (start >= end) { - break; - } - if (buff[start] == SP - || buff[start] == HT) { - break; - } - start++; - } - res.setBytes(buff, resStart, start - resStart); - return res.remaining(); - } - /** - * Resets the message buff to an uninitialized state. - */ - public void recycle() { - start = 0; - end = 0; - } - @Override - public void release() { -// synchronized (this) { -// useCount--; -// if (useCount == -1) { -// // all slices have been released - -// // TODO: callback, return to pool -// } -// } - } - public int remaining() { - return end - start; - } - - public void reset() { - buff = null; - } - - // -------------------- Setup -------------------- - /** - * Sets the message bytes to the specified subarray of bytes. - * - * @param b - * the ascii bytes - * @param off - * the start offset of the bytes - * @param len - * the length of the bytes - */ - public void setBytes(byte[] b, int off, int len) { - throw new RuntimeException("Can't setBytes on allocated buffer"); - } - - public void wrap(BBucket b) { - setBytes(b.array(), b.position(), b.remaining()); - } - - public void wrap(ByteBuffer b) { - setBytes(b.array(), b.position(), b.remaining()); - } - - protected void setBytesInternal(byte[] b, int off, int len) { - buff = b; - start = off; - end = start + len; - } - -// public final void lowerCase() { -// while (start < end) { -// byte chr = buff[start]; -// if ((chr >= A) && (chr <= Z)) { -// buff[start] = (byte) (chr - LC_OFFSET); -// } -// start++; -// } -// } - - public void setEnd(int i) { - end = i; - } - - /** - * The old code from MessageBytes, used for setContentLength - * and setStatus. - * TODO: just use StringBuilder, the method is faster. - */ - public void setLong(long l) { - if (array() == null) { - makeSpace(20); - } - long current = l; - byte[] buf = array(); - int start = 0; - int end = 0; - if (l == 0) { - buf[end++] = (byte) '0'; - } else if (l < 0) { - current = -l; - buf[end++] = (byte) '-'; - } - while (current > 0) { - int digit = (int) (current % 10); - current = current / 10; - buf[end++] = Hex.HEX[digit]; - } - setOffset(0); - setEnd(end); - // Inverting buffer - end--; - if (l < 0) { - start++; - } - while (end > start) { - byte temp = buf[start]; - buf[start] = buf[end]; - buf[end] = temp; - start++; - end--; - } - } - - public void setOffset(int off) { - if (end < off) - end = off; - start = off; - } - - - public int skipEmptyLines() { - int resStart = start; - while (buff[start] == CR || buff[start] == LF) { - start++; - if (start == end) { - break; - } - } - return start - resStart; - } - - public int skipSpace() { - int cstart = start; - while (true) { - if (start >= end) { - return start - cstart; - } - if ((buff[start] == SP) || (buff[start] == HT)) { - start++; - } else { - return start - cstart; - } - } - } - - public int read() { - if (end == start) { - return -1; - } - return (buff[start++] & 0xFF); - - } - - public int substract(BBuffer src) { - - if (end == start) { - return -1; - } - - int len = getLength(); - src.append(buff, start, len); - start = end; - return len; - - } - - public int substract(byte src[], int off, int len) { - - if ((end - start) == 0) { - return -1; - } - - int n = len; - if (len > getLength()) { - n = getLength(); - } - System.arraycopy(buff, start, src, off, n); - start += n; - return n; - - } - - public String toString() { - return toString(DEFAULT_CHARACTER_ENCODING); - } - - public String toString(String enc) { - if (null == buff) { - return null; - } else if (end == start) { - return ""; - } - - String strValue = null; - try { - if (enc == null) { - enc = DEFAULT_CHARACTER_ENCODING; - } - - strValue = new String(buff, start, end - start, enc); - /* - * Does not improve the speed too much on most systems, it's safer - * to use the "clasical" new String(). - * - * Most overhead is in creating char[] and copying, the internal - * implementation of new String() is very close to what we do. The - * decoder is nice for large buffers and if we don't go to String ( - * so we can take advantage of reduced GC) - * - * // Method is commented out, in: return B2CConverter.decodeString( - * enc ); - */ - } catch (java.io.UnsupportedEncodingException e) { - // Use the platform encoding in that case; the usage of a bad - // encoding will have been logged elsewhere already - strValue = new String(buff, start, end - start); - } - return strValue; - } - - public void wrapTo(BBuffer res) { - res.setBytes(buff, start, remaining()); - } - - /** - * Convert specified String to a byte array. This ONLY WORKS for ascii, UTF - * chars will be truncated. - * - * @param value - * to convert to byte array - * @return the byte array value - */ - public static final byte[] convertToBytes(String value) { - byte[] result = new byte[value.length()]; - for (int i = 0; i < value.length(); i++) { - result[i] = (byte) value.charAt(i); - } - return result; - } - - /** - * Find a character, no side effects. - * - * @return index of char if found, -1 if not - */ - public static int findChar(byte buf[], int start, int end, char c) { - byte b = (byte) c; - int offset = start; - while (offset < end) { - if (buf[offset] == b) { - return offset; - } - offset++; - } - return -1; - } - private static int hashBytes(byte buff[], int start, int bytesLen) { - int max = start + bytesLen; - byte bb[] = buff; - int code = 0; - for (int i = start; i < max; i++) { - code = code * 31 + bb[i]; - // TODO: if > 0x7F, convert to chars / switch to UTF8 - } - return code; - } - - public static boolean hasLFLF(BBucket bucket) { - int pos = bucket.position(); - int lastValid = bucket.limit(); - byte[] buf = bucket.array(); - - for (int i = pos; i < lastValid; i++) { - byte chr = buf[i]; - if (chr == LF) { - if (i + 1 < lastValid && buf[i + 1] == CR) { - // \n\r\n - i++; - } - if (i + 1 < lastValid && buf[i + 1] == LF) { - return true; // \n\n - } - } else if (chr == CR) { - if (i + 1 < lastValid && buf[i + 1] == CR) { - return true; // \r\r - } - if (i + 1 < lastValid && buf[i + 1] == LF) { - // \r\n - i++; // skip LF - if (i + 1 < lastValid && buf[i + 1] == CR && - i + 2 < lastValid && buf[i + 2] == LF) { - i++; - return true; - } - } - - } - } - return false; - } - - public static int indexOf(byte bytes[], int off, int end, char qq) { - // Works only for UTF - while (off < end) { - byte b = bytes[off]; - if (b == qq) - return off; - off++; - } - return -1; - } - - /** - * Returns true if the specified ASCII character is a digit. - */ - - public static boolean isDigit(int c) { - return isDigit[c & 0xff]; - } - - /** - * Parses an unsigned integer from the specified subarray of bytes. - * @param b the bytes to parse - * @param off the start offset of the bytes - * @param len the length of the bytes - * @exception NumberFormatException if the integer format was invalid - */ - public static int parseInt(byte[] b, int off, int len) - throws NumberFormatException - { - int c; - - if (b == null || len <= 0 || !isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - - int n = c - '0'; - - while (--len > 0) { - if (!isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - n = n * 10 + c - '0'; - } - - return n; - } - - /** - * Parses an unsigned long from the specified subarray of bytes. - * @param b the bytes to parse - * @param off the start offset of the bytes - * @param len the length of the bytes - * @exception NumberFormatException if the long format was invalid - */ - public static long parseLong(byte[] b, int off, int len) - throws NumberFormatException - { - int c; - - if (b == null || len <= 0 || !isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - - long n = c - '0'; - long m; - - while (--len > 0) { - if (!isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - m = n * 10 + c - '0'; - - if (m < n) { - // Overflow - throw new NumberFormatException(); - } else { - n = m; - } - } - - return n; - } - - - - /** - * Returns the lower case equivalent of the specified ASCII character. - */ - public static int toLower(int c) { - if (c > 0x7f) return c; - return toLower[c & 0xff] & 0xff; - } - - /** - * Returns true if the specified ASCII character is upper case. - */ - - public static boolean isUpper(int c) { - return c < 0x7f && isUpper[c]; - } - - /** - * A slice of a bucket, holding reference to a parent bucket. - * - * This is used when a filter splits a bucket - the original - * will be replaced with 1 or more slices. When all slices are - * released, the parent will also be released. - * - * It is not possible to add data. - * - * @author Costin Manolache - */ - static class IOBucketWrap extends BBuffer { - //IOBucket parent; - - - public BBuffer makeSpace(int count) { - throw new RuntimeException("Attempting to change buffer " + - "on a wrapped BBuffer"); - } - - public void release() { -// if (parent != null) { -// parent.release(); -// } - } - - public void setBytes(byte[] b, int off, int len) { - super.setBytesInternal(b, off, len); - } - } - - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/BufferedIOReader.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/BufferedIOReader.java deleted file mode 100644 index a0a00aedd66e..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/BufferedIOReader.java +++ /dev/null @@ -1,380 +0,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.lite.io; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.Reader; -import java.nio.CharBuffer; - - -/** - * Cut&pasted from Harmony buffered reader ( apache license ). - * Changes: - * - additional method to recycle to avoid re-allocating on - * each request. - */ -public class BufferedIOReader extends BufferedReader { - - // Not recycled - the buffer is tied to the message/IOReader - IOReader in; - - private String enc; - boolean closed; - private char[] buf; - private int marklimit = -1; - - private int count; - - private int markpos = -1; - - private int pos; - - public BufferedIOReader(IOReader realReader) { - // we're not using super - we override all methods, but need the - // signature - super(DUMMY_READER, 1); - this.in = realReader; - buf = new char[8192]; - } - - public void recycle() { - enc = null; - closed = false; - - if (in != null) { - in.recycle(); - } - marklimit = -1; - count = 0; - markpos = -1; - pos = 0; - } - - private void checkClosed() throws IOException { - if (closed) throw new IOException("closed"); - } - - public int read(CharBuffer target) throws IOException { - checkClosed(); - int len = target.remaining(); - int n = read(target.array(), target.position(), target.remaining()); - if (n > 0) - target.position(target.position() + n); - return n; - } - - - public int read(char[] cbuf) throws IOException { - return read(cbuf, 0, cbuf.length); - } - - - /** - * Closes this reader. This implementation closes the buffered source reader - * and releases the buffer. Nothing is done if this reader has already been - * closed. - * - * @throws IOException - * if an error occurs while closing this reader. - */ - @Override - public void close() throws IOException { - synchronized (lock) { - if (!isClosed()) { - in.close(); - closed = true; - // buf remains - } - } - } - - private int fillbuf() throws IOException { - if (markpos == -1 || (pos - markpos >= marklimit)) { - /* Mark position not set or exceeded readlimit */ - int result = in.read(buf, 0, buf.length); - if (result > 0) { - markpos = -1; - pos = 0; - count = result == -1 ? 0 : result; - } - return result; - } - if (markpos == 0 && marklimit > buf.length) { - /* Increase buffer size to accommodate the readlimit */ - int newLength = buf.length * 2; - if (newLength > marklimit) { - newLength = marklimit; - } - char[] newbuf = new char[newLength]; - System.arraycopy(buf, 0, newbuf, 0, buf.length); - buf = newbuf; - } else if (markpos > 0) { - System.arraycopy(buf, markpos, buf, 0, buf.length - markpos); - } - - /* Set the new position and mark position */ - pos -= markpos; - count = markpos = 0; - int charsread = in.read(buf, pos, buf.length - pos); - count = charsread == -1 ? pos : pos + charsread; - return charsread; - } - - private boolean isClosed() { - return closed; - } - - @Override - public void mark(int readlimit) throws IOException { - if (readlimit < 0) { - throw new IllegalArgumentException(); - } - synchronized (lock) { - checkClosed(); - marklimit = readlimit; - markpos = pos; - } - } - - @Override - public boolean markSupported() { - return true; - } - - @Override - public int read() throws IOException { - synchronized (lock) { - checkClosed(); - /* Are there buffered characters available? */ - if (pos < count || fillbuf() != -1) { - return buf[pos++]; - } - markpos = -1; - return -1; - } - } - - @Override - public int read(char[] buffer, int offset, int length) throws IOException { - synchronized (lock) { - checkClosed(); - if (offset < 0 || offset > buffer.length - length || length < 0) { - throw new IndexOutOfBoundsException(); - } - if (length == 0) { - return 0; - } - int required; - if (pos < count) { - /* There are bytes available in the buffer. */ - int copylength = count - pos >= length ? length : count - pos; - System.arraycopy(buf, pos, buffer, offset, copylength); - pos += copylength; - if (copylength == length || !in.ready()) { - return copylength; - } - offset += copylength; - required = length - copylength; - } else { - required = length; - } - - while (true) { - int read; - /* - * If we're not marked and the required size is greater than the - * buffer, simply read the bytes directly bypassing the buffer. - */ - if (markpos == -1 && required >= buf.length) { - read = in.read(buffer, offset, required); - if (read == -1) { - return required == length ? -1 : length - required; - } - } else { - if (fillbuf() == -1) { - return required == length ? -1 : length - required; - } - read = count - pos >= required ? required : count - pos; - System.arraycopy(buf, pos, buffer, offset, read); - pos += read; - } - required -= read; - if (required == 0) { - return length; - } - if (!in.ready()) { - return length - required; - } - offset += read; - } - } - } - - /** - * Returns the next line of text available from this reader. A line is - * represented by zero or more characters followed by {@code '\n'}, - * {@code '\r'}, {@code "\r\n"} or the end of the reader. The string does - * not include the newline sequence. - * - * @return the contents of the line or {@code null} if no characters were - * read before the end of the reader has been reached. - * @throws IOException - * if this reader is closed or some other I/O error occurs. - */ - public String readLine() throws IOException { - synchronized (lock) { - checkClosed(); - /* Are there buffered characters available? */ - if ((pos >= count) && (fillbuf() == -1)) { - return null; - } - for (int charPos = pos; charPos < count; charPos++) { - char ch = buf[charPos]; - if (ch > '\r') { - continue; - } - if (ch == '\n') { - String res = new String(buf, pos, charPos - pos); - pos = charPos + 1; - return res; - } else if (ch == '\r') { - String res = new String(buf, pos, charPos - pos); - pos = charPos + 1; - if (((pos < count) || (fillbuf() != -1)) - && (buf[pos] == '\n')) { - pos++; - } - return res; - } - } - - char eol = '\0'; - StringBuilder result = new StringBuilder(80); - /* Typical Line Length */ - - result.append(buf, pos, count - pos); - pos = count; - while (true) { - /* Are there buffered characters available? */ - if (pos >= count) { - if (eol == '\n') { - return result.toString(); - } - // attempt to fill buffer - if (fillbuf() == -1) { - // characters or null. - return result.length() > 0 || eol != '\0' ? result - .toString() : null; - } - } - for (int charPos = pos; charPos < count; charPos++) { - if (eol == '\0') { - if ((buf[charPos] == '\n' || buf[charPos] == '\r')) { - eol = buf[charPos]; - } - } else if (eol == '\r' && (buf[charPos] == '\n')) { - if (charPos > pos) { - result.append(buf, pos, charPos - pos - 1); - } - pos = charPos + 1; - return result.toString(); - } else { - if (charPos > pos) { - result.append(buf, pos, charPos - pos - 1); - } - pos = charPos; - return result.toString(); - } - } - if (eol == '\0') { - result.append(buf, pos, count - pos); - } else { - result.append(buf, pos, count - pos - 1); - } - pos = count; - } - } - - } - - - @Override - public boolean ready() throws IOException { - synchronized (lock) { - checkClosed(); - return ((count - pos) > 0) || in.ready(); - } - } - - @Override - public void reset() throws IOException { - synchronized (lock) { - checkClosed(); - if (markpos == -1) { - throw new IOException("No mark"); - } - pos = markpos; - } - } - - @Override - public long skip(long amount) throws IOException { - if (amount < 0) { - throw new IllegalArgumentException(); - } - synchronized (lock) { - checkClosed(); - if (amount < 1) { - return 0; - } - if (count - pos >= amount) { - pos += amount; - return amount; - } - - long read = count - pos; - pos = count; - while (read < amount) { - if (fillbuf() == -1) { - return read; - } - if (count - pos >= amount - read) { - pos += amount - read; - return amount; - } - // Couldn't get all the characters, skip what we read - read += (count - pos); - pos = count; - } - return amount; - } - } - - private static Reader DUMMY_READER = new Reader() { - @Override - public void close() throws IOException { - } - - @Override - public int read(char[] cbuf, int off, int len) throws IOException { - return 0; - } - }; - - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/CBucket.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/CBucket.java deleted file mode 100644 index aed8d971b98d..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/CBucket.java +++ /dev/null @@ -1,508 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.Serializable; -import java.nio.CharBuffer; - -/** - * Wraps a char[]. - * - * Doesn't provide any mutation methods. Classes in this package - * have access to the buffer, for conversions. - * - * - * @author Costin Manolache - */ -public class CBucket implements CharSequence, Comparable, Serializable { - protected char value[]; - - protected int start; - - protected int end; - - // Reused. - protected CharBuffer cb; - - // cache - protected String strValue; - protected int hash; - - public CBucket() { - } - - /** - * Used by IOWriter for conversion. Will not modify the content. - */ - CharBuffer getNioBuffer() { - if (cb == null || cb.array() != value) { - cb = CharBuffer.wrap(value, start, end - start); - } else { - cb.position(start); - cb.limit(end); - } - return cb; - } - - public void recycle() { - start = 0; - end = 0; - value = null; - strValue = null; - hash = 0; - } - - public String toString() { - if (null == value) { - return null; - } else if (end - start == 0) { - return ""; - } - if (strValue == null) { - strValue = new String(value, start, end - start); - } - return strValue; - } - - /** - * Same as String - */ - public int hashCode() { - int h = hash; - if (h == 0) { - int off = start; - char val[] = value; - - for (int i = start; i < end; i++) { - h = 31*h + val[off++]; - } - hash = h; - } - return h; - } - - public long getLong() { - return parseLong(value, start, end - start); - } - - public int getInt() { - return parseInt(value, start, end - start); - } - - public static int parseInt(char[] b, int off, int len) - throws NumberFormatException - { - int c; - - if (b == null || len <= 0 || !BBuffer.isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - - int n = c - '0'; - - while (--len > 0) { - if (!BBuffer.isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - n = n * 10 + c - '0'; - } - - return n; - } - - - public static long parseLong(char[] b, int off, int len) - throws NumberFormatException - { - int c; - - if (b == null || len <= 0 || !BBuffer.isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - - long n = c - '0'; - long m; - - while (--len > 0) { - if (!BBuffer.isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - m = n * 10 + c - '0'; - - if (m < n) { - // Overflow - throw new NumberFormatException(); - } else { - n = m; - } - } - - return n; - } - - - /** - * Compares the message bytes to the specified String object. - * - * @param s - * the String to compare - * @return true if the comparison succeeded, false otherwise - */ - public boolean equals(String s) { - char[] c = value; - int len = end - start; - if (c == null || len != s.length()) { - return false; - } - int off = start; - for (int i = 0; i < len; i++) { - if (c[off++] != s.charAt(i)) { - return false; - } - } - return true; - } - - /** - * Compares the message bytes to the specified String object. - * - * @param s - * the String to compare - * @return true if the comparison succeeded, false otherwise - */ - public boolean equalsIgnoreCase(String s) { - char[] c = value; - int len = end - start; - if (c == null || len != s.length()) { - return false; - } - int off = start; - for (int i = 0; i < len; i++) { - if (BBuffer.toLower(c[off++]) != BBuffer.toLower(s.charAt(i))) { - return false; - } - } - return true; - } - - public boolean equals(Object obj) { - if (obj instanceof CBuffer) { - CBuffer cc = (CBuffer) obj; - return equals(cc.value, cc.start, cc.length()); - } else if (obj instanceof String) { - return equals((String)obj); - } - return false; - } - - public boolean equals(char b2[], int off2, int len2) { - char b1[] = value; - if (b1 == null && b2 == null) - return true; - - if (b1 == null || b2 == null || end - start != len2) { - return false; - } - int off1 = start; - int len = end - start; - while (len-- > 0) { - if (b1[off1++] != b2[off2++]) { - return false; - } - } - return true; - } - - public boolean equals(byte b2[], int off2, int len2) { - char b1[] = value; - if (b2 == null && b1 == null) - return true; - - if (b1 == null || b2 == null || end - start != len2) { - return false; - } - int off1 = start; - int len = end - start; - - while (len-- > 0) { - if (b1[off1++] != (char) b2[off2++]) { - return false; - } - } - return true; - } - - - /** - * Returns true if the message bytes starts with the specified string. - * - * @param s - * the string - */ - public boolean startsWith(String s) { - char[] c = value; - int len = s.length(); - if (c == null || len > end - start) { - return false; - } - int off = start; - for (int i = 0; i < len; i++) { - if (c[off++] != s.charAt(i)) { - return false; - } - } - return true; - } - - /** - * Returns true if the message bytes starts with the specified string. - * - * @param s - * the string - */ - public boolean startsWithIgnoreCase(String s, int pos) { - char[] c = value; - int len = s.length(); - if (c == null || len + pos > end - start) { - return false; - } - int off = start + pos; - for (int i = 0; i < len; i++) { - if (BBuffer.toLower(c[off++]) != BBuffer.toLower(s.charAt(i))) { - return false; - } - } - return true; - } - - public int indexOf(char c) { - return indexOf(c, start); - } - - public int lastIndexOf(char c) { - return lastIndexOf(c, 0, end - start); - } - - /** - */ - public int lastIndexOf(char c, int off, int len) { - char[] buf = value; - int slash = -1; - for (int i = start + len - 1; i >= start + off; i--) { - if (buf[i] == c) { - slash = i - start; - break; - } - } - return slash; - } - - /** - * Returns true if the message bytes starts with the specified string. - * - * @param c - * the character - */ - public int indexOf(char c, int starting) { - int ret = indexOf(value, start + starting, end, c); - return (ret >= start) ? ret - start : -1; - } - - public static int indexOf(char chars[], int off, int cend, char qq) { - while (off < cend) { - char b = chars[off]; - if (b == qq) - return off; - off++; - } - return -1; - } - - public int indexOf(String src) { - return indexOf(src, 0, src.length(), 0); - } - - public int indexOf(String src, int srcOff, int srcLen, int myOff) { - char first = src.charAt(srcOff); - - // Look for first char - int srcEnd = srcOff + srcLen; - - for (int i = myOff + start; i <= (end - srcLen); i++) { - if (value[i] != first) - continue; - // found first char, now look for a match - int myPos = i + 1; - for (int srcPos = srcOff + 1; srcPos < srcEnd;) { - if (value[myPos++] != src.charAt(srcPos++)) - break; - if (srcPos == srcEnd) - return i - start; // found it - } - } - return -1; - } - - public char lastChar() { - return value[end - 1]; - } - - public char charAt(int index) { - return value[index + start]; - } - - public void wrap(char[] buff, int start, int end) { - if (value != null) { - throw new RuntimeException("Can wrap only once"); - } - this.value = buff; - this.start = start; - this.end = end; - } - - public CharSequence subSequence(int sstart, int send) { - CBucket seq = new CBucket(); - seq.wrap(this.value, start + sstart, start + send); - return seq; - } - - public int length() { - return end - start; - } - - @Override - public int compareTo(Object o) { - // Code based on Harmony - if (o instanceof CBuffer) { - CBuffer dest = (CBuffer) o; - int o1 = start, o2 = dest.start, result; - int len = end - start; - int destLen = dest.end - dest.start; - int fin = (len < destLen ? - end : start + destLen); - char[] target = dest.value; - while (o1 < fin) { - if ((result = value[o1++] - target[o2++]) != 0) { - return result; - } - } - return len - destLen; - - } else if (o instanceof CharSequence) { - CharSequence dest = (CharSequence) o; - int o1 = start, o2 = 0, result; - int len = end - start; - int destLen = dest.length(); - int fin = (len < destLen ? - end : start + destLen); - while (o1 < fin) { - if ((result = value[o1++] - dest.charAt(o2++)) != 0) { - return result; - } - } - return len - destLen; - - } else { - throw new RuntimeException("CompareTo not supported " + o); - } - } - - /** - * Compare given char chunk with String ignoring case. - * Return -1, 0 or +1 if inferior, equal, or superior to the String. - */ - public final int compareIgnoreCase(String compareTo) { - int result = 0; - char[] c = value; - int len = compareTo.length(); - if ((end - start) < len) { - len = end - start; - } - for (int i = 0; (i < len) && (result == 0); i++) { - if (BBuffer.toLower(c[i + start]) > BBuffer.toLower(compareTo.charAt(i))) { - result = 1; - } else if (BBuffer.toLower(c[i + start]) < BBuffer.toLower(compareTo.charAt(i))) { - result = -1; - } - } - if (result == 0) { - if (compareTo.length() > (end - start)) { - result = -1; - } else if (compareTo.length() < (end - start)) { - result = 1; - } - } - return result; - } - - /** - * Compare given char chunk with String. - * Return -1, 0 or +1 if inferior, equal, or superior to the String. - */ - public final int compare(String compareTo) { - int result = 0; - char[] c = value; - int len = compareTo.length(); - if ((end - start) < len) { - len = end - start; - } - for (int i = 0; (i < len) && (result == 0); i++) { - if (c[i + start] > compareTo.charAt(i)) { - result = 1; - } else if (c[i + start] < compareTo.charAt(i)) { - result = -1; - } - } - if (result == 0) { - if (compareTo.length() > (end - start)) { - result = -1; - } else if (compareTo.length() < (end - start)) { - result = 1; - } - } - return result; - } - - public int getExtension(CBuffer ext, char slashC, char dotC) { - int slash = lastIndexOf(slashC); - if (slash < 0) { - slash = 0; - } - int dot = lastIndexOf(dotC, slash, length()); - if (dot < 0) { - return -1; - } - ext.wrap(this, dot + 1, length()); - return dot; - } - - /** - * Find the position of the nth slash, in the given char chunk. - */ - public final int nthSlash(int n) { - char[] c = value; - int pos = start; - int count = 0; - - while (pos < end) { - if ((c[pos++] == '/') && ((++count) == n)) { - pos--; - break; - } - } - - return pos - start; - } - - - public boolean hasUpper() { - for (int i = start; i < end; i++) { - char c = value[i]; - if (c < 0x7F && BBuffer.isUpper(c)) { - return true; - } - } - return false; - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/CBuffer.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/CBuffer.java deleted file mode 100644 index c66f85644ab9..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/CBuffer.java +++ /dev/null @@ -1,387 +0,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.lite.io; - -import java.io.IOException; -import java.nio.CharBuffer; - - -/** - * Similar with StringBuilder or StringBuffer, but with access to the - * raw buffer - this avoids copying the data. - * - * Utilities to manipluate char chunks. While String is the easiest way to - * manipulate chars ( search, substrings, etc), it is known to not be the most - * efficient solution - Strings are designed as imutable and secure objects. - * - * @author dac@sun.com - * @author James Todd [gonzo@sun.com] - * @author Costin Manolache - * @author Remy Maucherat - */ -public class CBuffer extends CBucket implements Cloneable, - Appendable { - - - /** - * Creates a new, uninitialized CharChunk object. - */ - public static CBuffer newInstance() { - return new CBuffer(); - } - - private CBuffer() { - } - - /** - * Resets the message bytes to an uninitialized state. - */ - public void recycle() { - dirty(); - start = 0; - end = 0; - } - - /** - * Same as String - */ - public int hashCode() { - int h = 0; - int off = start; - char val[] = value; - - for (int i = start; i < end; i++) { - h = 31*h + val[off++]; - } - return h; - } - - public String toString() { - if (null == value) { - return null; - } else if (end - start == 0) { - return ""; - } - return new String(value, start, end - start); - } - - public void wrap(char[] buff, int start, int end) { - dirty(); - this.value = buff; - this.start = start; - this.end = end; - } - - public void wrap(CBucket buff, int off, int srcEnd) { - dirty(); - this.value = buff.value; - this.start = buff.start + off; - this.end = this.start + srcEnd - off; - } - - - // ----------- Used for IOWriter / conversion --------- - - public char[] array() { - return value; - } - - public int position() { - return start; - } - - CharBuffer getAppendCharBuffer() { - makeSpace(16); - if (cb == null || cb.array() != value) { - cb = CharBuffer.wrap(value, end, value.length - end); - } else { - cb.position(end); - cb.limit(value.length); - } - return cb; - } - - void returnNioBuffer(CharBuffer c) { - dirty(); - start = c.position(); - } - - void returnAppendCharBuffer(CharBuffer c) { - dirty(); - end = c.position(); - } - - // -------- Delete / replace --------------- - - /** - * 'Delete' all chars after offset. - * - * @param offset - */ - public void delete(int offset) { - dirty(); - end = start + offset; - } - - // -------------------- Adding data -------------------- - - /** - * Append methods take start and end - similar with this one. - * The source is not modified. - */ - @Override - public CBuffer append(CharSequence csq, int astart, int aend) - throws IOException { - makeSpace(aend - astart); - - for (int i = astart; i < aend; i++) { - value[end++] = csq.charAt(i); - } - return this; - } - - public CBuffer append(char b) { - makeSpace(1); - value[end++] = b; - return this; - } - - public CBuffer append(int i) { - // TODO: can be optimizeed... - append(Integer.toString(i)); - return this; - } - - /** - * Add data to the buffer - */ - public CBuffer append(char src[], int srcStart, int srcEnd) { - int len = srcEnd - srcStart; - if (len == 0) { - return this; - } - // will grow, up to limit - makeSpace(len); - - // assert: makeSpace made enough space - System.arraycopy(src, srcStart, value, end, len); - end += len; - return this; - } - - /** - * Add data to the buffer - */ - public CBuffer append(StringBuffer sb) { - int len = sb.length(); - if (len == 0) { - return this; - } - makeSpace(len); - sb.getChars(0, len, value, end); - end += len; - return this; - } - - /** - * Append a string to the buffer - */ - public CBuffer append(String s) { - if (s == null || s.length() == 0) { - return this; - } - append(s, 0, s.length()); - return this; - } - - - /** - * Append a string to the buffer - */ - public CBuffer append(String s, int off, int srcEnd) { - if (s == null) - return this; - - // will grow, up to limit - makeSpace(srcEnd - off); - - // assert: makeSpace made enough space - s.getChars(off, srcEnd, value, end); - end += srcEnd - off; - return this; - } - - // TODO: long, int conversions -> get from harmony Long - public CBuffer appendInt(int i) { - // TODO: copy from harmony StringBuffer - append(Integer.toString(i)); - return this; - } - - - public Appendable append(CharSequence cs) { - if (cs instanceof CBuffer) { - CBuffer src = (CBuffer) cs; - append(src.value, src.start, src.end); - } else if (cs instanceof String) { - append((String) cs); - } else { - for (int i = 0; i < cs.length(); i++) { - append(cs.charAt(i)); - } - } - return this; - } - - public CBuffer append(CBuffer src) { - append(src.value, src.start, src.end); - return this; - } - - - public CBuffer append(BBucket bb) { - byte[] bbuf = bb.array(); - int start = bb.position(); - appendAscii(bbuf, start, bb.remaining()); - return this; - } - - public CBuffer appendAscii(byte[] bbuf, int start, int len) { - makeSpace(len); - char[] cbuf = value; - for (int i = 0; i < len; i++) { - cbuf[end + i] = (char) (bbuf[i + start] & 0xff); - } - end += len; - return this; - } - - - public void toAscii(BBuffer bb) { - for (int i = start; i < end; i++) { - bb.append(value[i]); - } - } - - /** - * Append and advance CharBuffer. - * - * @param c - */ - public CBuffer put(CharBuffer c) { - append(c.array(), c.position(), c.limit()); - c.position(c.limit()); - return this; - } - - // ------------- 'set' methods --------------- - // equivalent with clean + append - - public CBuffer set(CBuffer csq, int off, int len) { - recycle(); - append(csq.value, csq.start + off, csq.start + off + len); - return this; - } - - public CBuffer setChars(char[] c, int off, int len) { - recycle(); - append(c, off, off + len); - return this; - } - - public CBuffer set(BBucket bb) { - recycle(); - byte[] bbuf = bb.array(); - int start = bb.position(); - appendAscii(bbuf, start, bb.remaining()); - return this; - } - - public CBuffer set(CharSequence csq) { - recycle(); - append(csq); - return this; - } - - public CBuffer set(CBuffer csq) { - recycle(); - append(csq); - return this; - } - - public CBuffer set(String csq) { - recycle(); - append(csq); - return this; - } - - private void dirty() { - hash = 0; - strValue = null; - } - - /** - * Make space for len chars. If len is small, allocate a reserve space too. - * Never grow bigger than limit. - */ - private void makeSpace(int count) { - dirty(); - char[] tmp = null; - - int newSize; - int desiredSize = end + count; - - if (value == null) { - if (desiredSize < 256) - desiredSize = 256; // take a minimum - value = new char[desiredSize]; - } - - // limit < buf.length ( the buffer is already big ) - // or we already have space XXX - if (desiredSize <= value.length) { - return; - } - // grow in larger chunks - if (desiredSize < 2 * value.length) { - newSize = value.length * 2; - tmp = new char[newSize]; - } else { - newSize = value.length * 2 + count; - tmp = new char[newSize]; - } - - System.arraycopy(value, 0, tmp, 0, end); - value = tmp; - tmp = null; - } - - public void toLower() { - for (int i = start; i < end; i++) { - char c = value[i]; - if (c < 0x7F) { - if (BBuffer.isUpper(c)) { - value[i] = (char) BBuffer.toLower(c); - } - - } - } - } - - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/DumpChannel.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/DumpChannel.java deleted file mode 100644 index 744cbe191268..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/DumpChannel.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -// TODO: dump to a file, hex, etc. - -/** - * For debug - will print all bytes that go trough the channel - */ -public class DumpChannel extends IOChannel { - - IOBuffer in = new IOBuffer(this); - IOBuffer out = new IOBuffer(this); - static final boolean dumpToFile = false; - static int idCnt = 0; - - DumpChannel(String id) { - this.id = id + idCnt++; - } - - public static IOChannel wrap(String id, IOChannel net) throws IOException { - if (id == null) { - id = ""; - } - DumpChannel dmp = new DumpChannel(id + idCnt++); - net.setHead(dmp); - return dmp; - } - - public String toString() { - return "Dump-" + id + "-" + net.toString(); - } - - @Override - public void handleReceived(IOChannel ch) throws IOException { - processInput(ch.getIn()); - } - - private void processInput(IOBuffer netIn) throws IOException { - boolean any = false; - while (true) { - BBucket first = netIn.popFirst(); - if (first == null) { - if (netIn.isClosedAndEmpty()) { - out("IN", first, true); - in.close(); - any = true; - } - if (any) { - sendHandleReceivedCallback(); - } - return; - } - any = true; - out("IN", first, false); - if (!in.isAppendClosed()) { - in.queue(first); - } - } - } - - public void startSending() throws IOException { - while (true) { - BBucket first = out.popFirst(); - if (first == null) { - if (out.isClosedAndEmpty()) { - out("OUT", first, true); - net.getOut().close(); - } - - net.startSending(); - return; - } - // Dump - out("OUT", first, net.getOut().isAppendClosed()); - net.getOut().queue(first); - } - } - - static int did = 0; - - protected void out(String dir, BBucket first, boolean closed) { - // Dump - if (first != null) { - String hd = Hex.getHexDump(first.array(), first.position(), - first.remaining(), true); - System.err.println("\n" + dir + ": " + id + " " + - (closed ? "CLS" : "") + - + first.remaining() + "\n" + - hd); - } else { - System.err.println("\n" + dir + ": " + id + " " + - (closed ? "CLS " : "") + - "END\n"); - } - if (dumpToFile && first != null) { - try { - OutputStream os = new FileOutputStream("dmp" + did++); - os.write(first.array(), first.position(), first.remaining()); - os.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - @Override - public IOBuffer getIn() { - return in; - } - - @Override - public IOBuffer getOut() { - return out; - } -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/FastHttpDateFormat.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/FastHttpDateFormat.java deleted file mode 100644 index 568176789a4c..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/FastHttpDateFormat.java +++ /dev/null @@ -1,231 +0,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.lite.io; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Utility class to generate HTTP dates. - * - * @author Remy Maucherat - */ -public final class FastHttpDateFormat { - - - // -------------------------------------------------------------- Variables - - - protected static final int CACHE_SIZE = - Integer.parseInt(System.getProperty("org.apache.tomcat.util.http.FastHttpDateFormat.CACHE_SIZE", "1000")); - - - /** - * HTTP date format. - */ - protected static final SimpleDateFormat format = - new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); - - - /** - * The set of SimpleDateFormat formats to use in getDateHeader(). - */ - protected static final SimpleDateFormat formats[] = { - new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US), - new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US), - new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) - }; - - - protected final static TimeZone gmtZone = TimeZone.getTimeZone("GMT"); - - - /** - * GMT timezone - all HTTP dates are on GMT - */ - static { - - format.setTimeZone(gmtZone); - - formats[0].setTimeZone(gmtZone); - formats[1].setTimeZone(gmtZone); - formats[2].setTimeZone(gmtZone); - - } - - - /** - * Instant on which the currentDate object was generated. - */ - protected static long currentDateGenerated = 0L; - - - /** - * Current formatted date. - */ - protected static String currentDate = null; - - - /** - * Formatter cache. - */ - protected static final ConcurrentHashMap formatCache = - new ConcurrentHashMap(CACHE_SIZE); - - - /** - * Parser cache. - */ - protected static final ConcurrentHashMap parseCache = - new ConcurrentHashMap(CACHE_SIZE); - - - // --------------------------------------------------------- Public Methods - - - /** - * Get the current date in HTTP format. - */ - public static final String getCurrentDate() { - - long now = System.currentTimeMillis(); - if ((now - currentDateGenerated) > 1000) { - synchronized (format) { - if ((now - currentDateGenerated) > 1000) { - currentDateGenerated = now; - currentDate = format.format(new Date(now)); - } - } - } - return currentDate; - - } - - - /** - * Get the HTTP format of the specified date. - */ - public static final String formatDate - (long value, DateFormat threadLocalformat) { - - Long longValue = new Long(value); - String cachedDate = formatCache.get(longValue); - if (cachedDate != null) - return cachedDate; - - String newDate = null; - Date dateValue = new Date(value); - if (threadLocalformat != null) { - newDate = threadLocalformat.format(dateValue); - updateFormatCache(longValue, newDate); - } else { - synchronized (formatCache) { - synchronized (format) { - newDate = format.format(dateValue); - } - updateFormatCache(longValue, newDate); - } - } - return newDate; - - } - - - /** - * Try to parse the given date as a HTTP date. - */ - public static final long parseDate(String value, - DateFormat[] threadLocalformats) { - - Long cachedDate = parseCache.get(value); - if (cachedDate != null) - return cachedDate.longValue(); - - Long date = null; - if (threadLocalformats != null) { - date = internalParseDate(value, threadLocalformats); - updateParseCache(value, date); - } else { - synchronized (parseCache) { - date = internalParseDate(value, formats); - updateParseCache(value, date); - } - } - if (date == null) { - return (-1L); - } else { - return date.longValue(); - } - - } - - - /** - * Parse date with given formatters. - */ - private static final Long internalParseDate - (String value, DateFormat[] formats) { - Date date = null; - for (int i = 0; (date == null) && (i < formats.length); i++) { - try { - date = formats[i].parse(value); - } catch (ParseException e) { - ; - } - } - if (date == null) { - return null; - } - return new Long(date.getTime()); - } - - - /** - * Update cache. - */ - private static void updateFormatCache(Long key, String value) { - if (value == null) { - return; - } - if (formatCache.size() > CACHE_SIZE) { - formatCache.clear(); - } - formatCache.put(key, value); - } - - - /** - * Update cache. - */ - private static void updateParseCache(String key, Long value) { - if (value == null) { - return; - } - if (parseCache.size() > CACHE_SIZE) { - parseCache.clear(); - } - parseCache.put(key, value); - } - - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/FileConnector.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/FileConnector.java deleted file mode 100644 index 5fb452524f8f..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/FileConnector.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - - -/** - * Initial abstraction for non-blocking File access and to - * support other abstraction. - * - * Tomcat uses JNDI - but that's blocking, does lots of data copy, - * is complex. - * - * Work in progress.. - */ -public abstract class FileConnector extends IOConnector { - - public static class FileInfo { - String type; - int mode; - long size; - - } - - public abstract boolean isDirectory(String path); - - public abstract boolean isFile(String path); -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/FileConnectorJavaIo.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/FileConnectorJavaIo.java deleted file mode 100644 index 2b6de3b30616..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/FileConnectorJavaIo.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.File; -import java.io.IOException; - - -/** - * Catalina uses JNDI to abstract filesystem - this is both heavy and - * a bit complex. - * - * This is also a bit complex - but hopefully we can implement it as - * non-blocking and without much copy. - * - */ -public class FileConnectorJavaIo extends FileConnector { - File base; - - public FileConnectorJavaIo(File file) { - this.base = file; - } - - @Override - public boolean isDirectory(String path) { - File file = new File(base, path); - return file.isDirectory(); - } - - @Override - public boolean isFile(String path) { - File file = new File(base, path); - return file.exists() && !file.isDirectory(); - } - - @Override - public void acceptor(ConnectedCallback sc, - CharSequence port, - Object extra) throws IOException { - // TODO: unix domain socket impl. - // Maybe: detect new files in the filesystem ? - } - - @Override - public void connect(String host, int port, ConnectedCallback sc) - throws IOException { - } - -} \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/FutureCallbacks.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/FutureCallbacks.java deleted file mode 100644 index fd3b4be4f7cc..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/FutureCallbacks.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.locks.AbstractQueuedSynchronizer; - - - -/** - * Support for blocking calls and callbacks. - * - * Unlike FutureTask, it is possible to reuse this and hopefully - * easier to extends. Also has callbacks. - * - * @author Costin Manolache - */ -public class FutureCallbacks implements Future { - - // Other options: ReentrantLock uses AbstractQueueSynchronizer, - // more complex. Same for CountDownLatch - // FutureTask - uses Sync as well, ugly interface with - // Callable, can't be recycled. - // Mina: simple object lock, doesn't extend java.util.concurent.Future - - private Sync sync = new Sync(); - - private V value; - - public static interface Callback { - public void run(V param); - } - - private List> callbacks = new ArrayList(); - - public FutureCallbacks() { - } - - /** - * Unlocks the object if it was locked. Should be called - * when the object is reused. - * - * Callbacks will not be invoked. - */ - public void reset() { - sync.releaseShared(0); - sync.reset(); - } - - public void recycle() { - callbacks.clear(); - sync.releaseShared(0); - sync.reset(); - } - - /** - * Unlocks object and calls the callbacks. - * @param v - * - * @throws IOException - */ - public void signal(V v) throws IOException { - sync.releaseShared(0); - onSignal(v); - } - - protected boolean isSignaled() { - return true; - } - - /** - * Override to call specific callbacks - */ - protected void onSignal(V v) { - for (Callback cb: callbacks) { - if (cb != null) { - cb.run(v); - } - } - } - - /** - * Set the response. Will cause the callback to be called and lock to be - * released. - * - * @param value - * @throws IOException - */ - public void setValue(V value) throws IOException { - synchronized (this) { - this.value = value; - signal(value); - } - } - - public void waitSignal(long to) throws IOException { - try { - get(to, TimeUnit.MILLISECONDS); - } catch (InterruptedException e1) { - throw new WrappedException(e1); - } catch (TimeoutException e1) { - throw new WrappedException(e1); - } catch (ExecutionException e) { - throw new WrappedException(e); - } - } - - @Override - public V get() throws InterruptedException, ExecutionException { - sync.acquireSharedInterruptibly(0); - return value; - } - - @Override - public V get(long timeout, TimeUnit unit) throws InterruptedException, - ExecutionException, TimeoutException { - if (!sync.tryAcquireSharedNanos(0, unit.toNanos(timeout))) { - throw new TimeoutException("Waiting " + timeout); - } - return value; - } - - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return sync.isSignaled(); - } - - private class Sync extends AbstractQueuedSynchronizer { - - static final int DONE = 1; - static final int BLOCKED = 0; - Object result; - Throwable t; - - @Override - protected int tryAcquireShared(int ignore) { - return getState() == DONE ? 1 : -1; - } - - @Override - protected boolean tryReleaseShared(int ignore) { - setState(DONE); - return true; - } - - public void reset() { - setState(BLOCKED); - } - - boolean isSignaled() { - return getState() == DONE; - } - } -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/Hex.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/Hex.java deleted file mode 100644 index 832b81375a08..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/Hex.java +++ /dev/null @@ -1,249 +0,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.lite.io; - -import java.io.ByteArrayOutputStream; - -/** - * Tables useful when converting byte arrays to and from strings of hexadecimal - * digits. - * Code from Ajp11, from Apache's JServ. - * - * @author Craig R. McClanahan - */ - -public final class Hex { - - - // -------------------------------------------------------------- Constants - - /** - * Table for HEX to DEC byte translation. - */ - public static final int[] DEC = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 00, 01, 02, 03, 04, 05, 06, 07, 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - }; - - - /** - * Table for DEC to HEX byte translation. - */ - public static final byte[] HEX = - { (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', - (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', - (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f' }; - - - // --------------------------------------------------------- Static Methods - - - /** - * Convert a String of hexadecimal digits into the corresponding - * byte array by encoding each two hexadecimal digits as a byte. - * - * @param digits Hexadecimal digits representation - * - * @exception IllegalArgumentException if an invalid hexadecimal digit - * is found, or the input string contains an odd number of hexadecimal - * digits - */ - public static byte[] convert(String digits) { - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - for (int i = 0; i < digits.length(); i += 2) { - char c1 = digits.charAt(i); - if ((i+1) >= digits.length()) - throw new IllegalArgumentException - ("hexUtil.odd"); - char c2 = digits.charAt(i + 1); - byte b = 0; - if ((c1 >= '0') && (c1 <= '9')) - b += ((c1 - '0') * 16); - else if ((c1 >= 'a') && (c1 <= 'f')) - b += ((c1 - 'a' + 10) * 16); - else if ((c1 >= 'A') && (c1 <= 'F')) - b += ((c1 - 'A' + 10) * 16); - else - throw new IllegalArgumentException - ("hexUtil.bad"); - if ((c2 >= '0') && (c2 <= '9')) - b += (c2 - '0'); - else if ((c2 >= 'a') && (c2 <= 'f')) - b += (c2 - 'a' + 10); - else if ((c2 >= 'A') && (c2 <= 'F')) - b += (c2 - 'A' + 10); - else - throw new IllegalArgumentException - ("hexUtil.bad"); - baos.write(b); - } - return (baos.toByteArray()); - - } - - - /** - * Convert a byte array into a printable format containing a - * String of hexadecimal digit characters (two per byte). - * - * @param bytes Byte array representation - */ - public static String convert(byte bytes[]) { - - StringBuffer sb = new StringBuffer(bytes.length * 2); - for (int i = 0; i < bytes.length; i++) { - sb.append(convertDigit((bytes[i] >> 4))); - sb.append(convertDigit((bytes[i] & 0x0f))); - } - return (sb.toString()); - - } - - - /** - * Convert 4 hex digits to an int, and return the number of converted - * bytes. - * - * @param hex Byte array containing exactly four hexadecimal digits - * - * @exception IllegalArgumentException if an invalid hexadecimal digit - * is included - */ - public static int convert2Int( byte[] hex ) { - // Code from Ajp11, from Apache's JServ - - // assert b.length==4 - // assert valid data - int len; - if(hex.length < 4 ) return 0; - if( DEC[hex[0]]<0 ) - throw new IllegalArgumentException("hexUtil.bad"); - len = DEC[hex[0]]; - len = len << 4; - if( DEC[hex[1]]<0 ) - throw new IllegalArgumentException("hexUtil.bad"); - len += DEC[hex[1]]; - len = len << 4; - if( DEC[hex[2]]<0 ) - throw new IllegalArgumentException("hexUtil.bad"); - len += DEC[hex[2]]; - len = len << 4; - if( DEC[hex[3]]<0 ) - throw new IllegalArgumentException("hexUtil.bad"); - len += DEC[hex[3]]; - return len; - } - - - - /** - * Provide a mechanism for ensuring this class is loaded. - */ - public static void load() { - // Nothing to do - } - - /** - * [Private] Convert the specified value (0 .. 15) to the corresponding - * hexadecimal digit. - * - * @param value Value to be converted - */ - private static char convertDigit(int value) { - - value &= 0x0f; - if (value >= 10) - return ((char) (value - 10 + 'a')); - else - return ((char) (value + '0')); - - } - - /** - * getHexValue displays a formatted hex - * representation of the passed byte array. It also - * allows for only a specified offset and length of - * a particular array to be returned. - * - * @param bytes byte[] array to process. - * @param pos offset to begin processing. - * @param len number of bytes to process. - * @return String formatted hex representation of processed - * array. - */ - public static String getHexDump(byte[] bytes, int pos, int len, - boolean displayOffset) { - StringBuffer out = new StringBuffer( len * 2 ); - - for (int j = 0; j < len; j += 16) { - hexLine(out, bytes, pos + j, pos + len, displayOffset); - } - - return out.toString(); - } - - private static void hexLine(StringBuffer out, - byte[] bytes, int start, int end, - boolean displayOffset) { - - if ( displayOffset ) { - out.append(convertDigit((int) (start >> 12))); - out.append(convertDigit((int) (start >> 8))); - out.append(convertDigit((int) (start >> 4))); - out.append(convertDigit(start & 0x0F)); - out.append(": "); - } - for (int i = start; i < start + 16; i++) { - - if (i < end) { - out.append(convertDigit((int) (bytes[i] >> 4))); - out.append(convertDigit(bytes[i] & 0x0F)); - out.append(" "); - } else { - out.append(" "); - } - } - - out.append(" | "); - - for (int i = start; i < start + 16 && i < end; i++) { - if( ! Character.isISOControl( (char)bytes[i] )) { - out.append( new Character((char)bytes[i]) ); - } else { - out.append( "." ); - } - } - - out.append("\n"); - } -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOBuffer.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOBuffer.java deleted file mode 100644 index 70e7795433a8..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOBuffer.java +++ /dev/null @@ -1,698 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.LinkedList; -import java.util.logging.Logger; - - -// TODO: append() will trigger callbacks - do it explicitely !!! -// TODO: queue() shouldn't modify the buffer - - -/** - * A list of data buckets. - * - * @author Costin Manolache - */ -public class IOBuffer { - static Logger log = Logger.getLogger("IOBrigade"); - - static int ALLOC_SIZE = 8192; - long defaultTimeout = Long.MAX_VALUE; - - private LinkedList buffers = new LinkedList(); - - // close() has been called for out, - // or EOF/FIN received for in. It may still have data. - boolean closeQueued; - - // Will be signalled (open) when there is data in the buffer. - // also used to sync on. - FutureCallbacks hasDataLock = new FutureCallbacks() { - protected boolean isSignaled() { - return hasData(); - } - }; - - // may be null - protected IOChannel ch; - - // Support for appending - needs improvements. - // appendable buffer is part of the buffer list if it has - // data, and kept here if empty. - BBuffer appendable; - boolean appending = false; - ByteBuffer writeBuffer; - - - public IOBuffer() { - } - - public IOBuffer(IOChannel ch) { - this.ch = ch; - } - - public IOChannel getChannel() { - return ch; - } - - // ===== Buffer access ===== - - - /** - * Return first non-empty buffer. - * - * The append buffer is part of the buffer list, and is left alone and - * empty. - * - * @return - */ - public BBucket peekFirst() { - synchronized (buffers) { - BBucket o = (buffers.size() == 0) ? null : buffers.getFirst(); - - while (true) { - boolean empty = o == null || isEmpty(o); - if (o == null) { - //hasDataLock.reset(); - return null; // no data in buffers - } - // o != null - if (empty) { - buffers.removeFirst(); - o = (buffers.size() == 0) ? null : buffers.getFirst(); - } else { - return o; - } - } - } - } - - public BBucket peekBucket(int idx) { - synchronized (buffers) { - return buffers.get(idx); - } - } - - - public void advance(int len) { - while (len > 0) { - BBucket first = peekFirst(); - if (first == null) { - return; - } - if (len > first.remaining()) { - len -= first.remaining(); - first.position(first.limit()); - } else { - first.position(first.position() + len); - len = 0; - } - } - } - - public void queue(String s) throws IOException { - // TODO: decode with prober charset - byte[] bytes = s.getBytes("UTF8"); - queueInternal(BBuffer.wrapper(bytes, 0, bytes.length)); - } - - public void queue(BBuffer bc) throws IOException { - queueInternal(bc); - } - - public void queue(Object bb) throws IOException { - queueInternal(bb); - } - - private void queueInternal(Object bb) throws IOException { - if (closeQueued) { - throw new IOException("Closed"); - } - synchronized (buffers) { - if (appending) { - throw new RuntimeException("Unexpected queue while " + - "appending"); - } - BBucket add = wrap(bb); - buffers.add(add); - //log.info("QUEUED: " + add.remaining() + " " + this); - notifyDataAvailable(add); - } - - } - - public int getBufferCount() { - peekFirst(); - synchronized (buffers) { - return buffers.size(); - } - } - - public void clear() { - synchronized (buffers) { - buffers.clear(); - } - } - - public void recycle() { - closeQueued = false; - clear(); - // Normally unlocked - hasDataLock.recycle(); - - appending = false; - appendable = null; - } - - // =================== - /** - * Closed for append. It may still have data. - * @return - */ - public boolean isClosedAndEmpty() { - return closeQueued && 0 == getBufferCount(); - } - - - /** - * Mark as closed - but will not send data. - */ - public void close() throws IOException { - if (closeQueued) { - return; - } - closeQueued = true; - notifyDataAvailable(null); - } - - - private boolean isEmpty(BBucket o) { - if (o instanceof BBucket && - ((BBucket) o).remaining() == 0) { - return true; - } - return false; - } - - private BBucket wrap(Object src) { - if (src instanceof byte[]) { - return BBuffer.wrapper((byte[]) src, 0, ((byte[]) src).length); - } - if (src instanceof ByteBuffer) { - //return src; - ByteBuffer bb = (ByteBuffer) src; - return BBuffer.wrapper(bb.array(), bb.position(), - bb.remaining()); - } - if (src instanceof byte[]) { - byte[] bb = (byte[]) src; - return BBuffer.wrapper(bb, 0, bb.length); - } - return (BBucket) src; - } - - protected void notifyDataAvailable(Object bb) throws IOException { - synchronized (hasDataLock) { - hasDataLock.signal(this); // or bb ? - } - } - - public boolean hasData() { - return closeQueued || peekFirst() != null; - } - - public void waitData(long timeMs) throws IOException { - if (timeMs == 0) { - timeMs = defaultTimeout; - } - synchronized (hasDataLock) { - if (hasData()) { - return; - } - hasDataLock.reset(); - } - hasDataLock.waitSignal(timeMs); - } - - - public boolean isAppendClosed() { - return closeQueued; - } - - // =================== Helper methods ================== - - /** - * Non-blocking read. - * - * @return -1 if EOF, -2 if no data available, or 0..255 for normal read. - */ - public int read() throws IOException { - if (isClosedAndEmpty()) { - return -1; - } - BBucket bucket = peekFirst(); - if (bucket == null) { - return -2; - } - int res = bucket.array()[bucket.position()]; - bucket.position(bucket.position() + 1); - return res & 0xFF; - } - - public int peek() throws IOException { - BBucket bucket = peekFirst(); - if (bucket == null) { - return -1; - } - int res = bucket.array()[bucket.position()]; - return res; - } - - public int find(char c) { - int pos = 0; - for (int i = 0; i < buffers.size(); i++) { - BBucket bucket = buffers.get(i); - if (bucket == null || bucket.remaining() == 0) { - continue; - } - int found= BBuffer.findChar(bucket.array(), bucket.position(), - bucket.limit(), c); - if (found >= 0) { - return pos + found; - } - pos += bucket.remaining(); - } - return -1; - } - - public int readLine(BBuffer bc) throws IOException { - return readToDelim(bc, '\n'); - } - - /** - * Copy up to and including "delim". - * - * @return number of bytes read, or -1 for end of stream. - */ - int readToDelim(BBuffer bc, int delim) throws IOException { - int len = 0; - for (int idx = 0; idx < buffers.size(); idx++) { - BBucket bucket = buffers.get(idx); - if (bucket == null || bucket.remaining() == 0) { - continue; - } - byte[] data = bucket.array(); - int end = bucket.limit(); - int start = bucket.position(); - for (int i = start; i < end; i++) { - byte chr = data[i]; - bc.put(chr); - if (chr == delim) { - bucket.position(i + 1); - len += (i - start + 1); - return len; - } - } - bucket.position(end); // empty - should be removed - } - if (len == 0 && isClosedAndEmpty()) { - return -1; - } - return len; - } - - - public int write(ByteBuffer bb) throws IOException { - int len = bb.remaining(); - int pos = bb.position(); - if (len == 0) { - return 0; - } - append(bb); - bb.position(pos + len); - return len; - } - - public int read(byte[] buf, int off, int len) throws IOException { - if (isClosedAndEmpty()) { - return -1; - } - int rd = 0; - while (true) { - BBucket bucket = peekFirst(); - if (bucket == null) { - return rd; - } - int toCopy = Math.min(len, bucket.remaining()); - System.arraycopy(bucket.array(), bucket.position(), - buf, off + rd, toCopy); - bucket.position(bucket.position() + toCopy); - rd += toCopy; - len -= toCopy; - if (len == 0) { - return rd; - } - } - - } - - public int read(BBuffer bb, int len) throws IOException { - bb.makeSpace(len); - int rd = read(bb.array(), bb.limit(), len); - if (rd < 0) { - return rd; - } - bb.limit(bb.limit() + rd); - return rd; - } - - /** - * Non-blocking read. - */ - public int read(ByteBuffer bb) { - if (isClosedAndEmpty()) { - return -1; - } - int len = 0; - while (true) { - int space = bb.remaining(); // to append - if (space == 0) { - return len; - } - BBucket first = peekFirst(); - if (first == null) { - return len; - } - BBucket iob = ((BBucket) first); - if (space > iob.remaining()) { - space = iob.remaining(); - } - bb.put(iob.array(), iob.position(), space); - - iob.position(iob.position() + space); - iob.release(); - len += space; - } - } - - - public BBuffer readAll(BBuffer chunk) throws IOException { - if (chunk == null) { - chunk = allocate(); - } - while (true) { - if (isClosedAndEmpty()) { - return chunk; - } - BBucket first = peekFirst(); - if (first == null) { - return chunk; - } - BBucket iob = ((BBucket) first); - chunk.append(iob.array(), iob.position(), iob.remaining()); - iob.position(iob.position() + iob.remaining()); - iob.release(); - - } - } - - private BBuffer allocate() { - int size = 0; - for (int i = 0; i < getBufferCount(); i++) { - BBucket first = peekBucket(i); - if (first != null) { - size += first.remaining(); - } - } - return BBuffer.allocate(size); - } - - public BBuffer copyAll(BBuffer chunk) throws IOException { - if (chunk == null) { - chunk = allocate(); - } - for (int i = 0; i < getBufferCount(); i++) { - BBucket iob = peekBucket(i); - chunk.append(iob.array(), iob.position(), iob.remaining()); - } - return chunk; - } - - public IOBuffer append(InputStream is) throws IOException { - while (true) { - ByteBuffer bb = getWriteBuffer(); - int rd = is.read(bb.array(), bb.position(), bb.remaining()); - if (rd <= 0) { - return this; - } - bb.position(bb.position() + rd); - releaseWriteBuffer(rd); - } - } - - public IOBuffer append(BBuffer bc) throws IOException { - return append(bc.array(), bc.getStart(), bc.getLength()); - } - - public IOBuffer append(byte[] data) throws IOException { - return append(data, 0, data.length); - } - - public IOBuffer append(byte[] data, int start, int len) throws IOException { - if (closeQueued) { - throw new IOException("Closed"); - } - ByteBuffer bb = getWriteBuffer(); - - int i = start; - int end = start + len; - while (i < end) { - int rem = Math.min(end - i, bb.remaining()); - // to write - bb.put(data, i, rem); - i += rem; - if (bb.remaining() < 8) { - releaseWriteBuffer(1); - bb = getWriteBuffer(); - } - } - - releaseWriteBuffer(1); - return this; - } - - public IOBuffer append(int data) throws IOException { - if (closeQueued) { - throw new IOException("Closed"); - } - ByteBuffer bb = getWriteBuffer(); - bb.put((byte) data); - releaseWriteBuffer(1); - return this; - } - - public IOBuffer append(ByteBuffer cs) throws IOException { - return append(cs.array(), cs.position() + cs.arrayOffset(), - cs.remaining()); - } - - /** - * Append a buffer. The buffer will not be modified. - */ - public IOBuffer append(BBucket cs) throws IOException { - append(cs.array(), cs.position(), cs.remaining()); - return this; - } - - /** - * Append a buffer. The buffer will not be modified. - */ - public IOBuffer append(BBucket cs, int len) throws IOException { - append(cs.array(), cs.position(), len); - return this; - } - - public IOBuffer append(IOBuffer cs) throws IOException { - for (int i = 0; i < cs.getBufferCount(); i++) { - BBucket o = cs.peekBucket(i); - append(o); - } - - return this; - } - - public IOBuffer append(IOBuffer cs, int len) throws IOException { - for (int i = 0; i < cs.getBufferCount(); i++) { - BBucket o = cs.peekBucket(i); - append(o); - } - - return this; - } - - public IOBuffer append(CharSequence cs) throws IOException { - byte[] data = cs.toString().getBytes(); - append(data, 0, data.length); - return this; - } - - public IOBuffer append(char c) throws IOException { - ByteBuffer bb = getWriteBuffer(); - bb.put((byte) c); - releaseWriteBuffer(1); - return this; - } - - /** - * All operations that iterate over buffers must be - * sync - * @return - */ - public synchronized int available() { - int a = 0; - int cnt = buffers.size(); - for (int i = 0; i < cnt; i++) { - a += buffers.get(i).remaining(); - } - return a; - } - - public String toString() { - return "IOB:{c:" + getBufferCount() + - ", b:" + available() + - (isAppendClosed() ? ", C}" : " }"); - } - - public BBucket popLen(int lenToConsume) { - BBucket o = peekFirst(); // skip empty - if (o == null) { - return null; - } - BBucket sb = BBuffer.wrapper(o.array(), - o.position(), lenToConsume); - o.position(o.position() + lenToConsume); - return sb; - } - - public BBucket popFirst() { - BBucket o = peekFirst(); // skip empty - if (o == null) { - return null; - } - if (o == appendable) { - synchronized (buffers) { - // TODO: concurrency ??? - BBucket sb = - BBuffer.wrapper(appendable.array(), - appendable.position(), - appendable.limit() - appendable.position()); - appendable.position(appendable.limit()); - return sb; - } - } else { - buffers.removeFirst(); - } - return o; - } - - - public ByteBuffer getWriteBuffer() throws IOException { - synchronized (buffers) { - if (closeQueued) { - throw new IOException("Closed"); - } - BBucket last = (buffers.size() == 0) ? - null : buffers.getLast(); - if (last == null || last != appendable || - last.array().length - last.limit() < 16) { - last = BBuffer.allocate(ALLOC_SIZE); - } - appending = true; - appendable = (BBuffer) last; - - if (writeBuffer == null || writeBuffer.array() != appendable.array()) { - writeBuffer = ByteBuffer.wrap(appendable.array()); - } - writeBuffer.position(appendable.limit()); - writeBuffer.limit(appendable.array().length); - return writeBuffer; - } - } - - public void releaseWriteBuffer(int read) throws IOException { - synchronized (buffers) { - if (!appending) { - throw new IOException("Not appending"); - } - if (writeBuffer != null) { - if (appendable.limit() != writeBuffer.position()) { - appendable.limit(writeBuffer.position()); - // We have some more data. - if (buffers.size() == 0 || - buffers.getLast() != appendable) { - buffers.add(appendable); - } - notifyDataAvailable(appendable); - } - } - appending = false; - } - } - - - // ------ More utilities - for parsing request ( later )------- -// public final int skipBlank(ByteBuffer bb, int start) { -// // Skipping blank lines -// byte chr = 0; -// do { -// if (!bb.hasRemaining()) { -// return -1; -// } -// chr = bb.get(); -// } while ((chr == HttpParser.CR) || (chr == HttpParser.LF)); -// return bb.position(); -//} - -//public final int readToDelimAndLowerCase(ByteBuffer bb, -// byte delim, -// boolean lower) { -// boolean space = false; -// byte chr = 0; -// while (!space) { -// if (!bb.hasRemaining()) { -// return -1; -// } -// chr = bb.get(); -// if (chr == delim) { -// space = true; -// } -// if (lower && (chr >= HttpParser.A) && (chr <= HttpParser.Z)) { -// bb.put(bb.position() - 1, -// (byte) (chr - HttpParser.LC_OFFSET)); -// } -// } -// return bb.position(); -//} - -//public boolean skipSpace(ByteBuffer bb) { -// boolean space = true; -// while (space) { -// if (!bb.hasRemaining()) { -// return false; -// } -// byte chr = bb.get(); -// if ((chr == HttpParser.SP) || (chr == HttpParser.HT)) { -// // -// } else { -// space = false; -// bb.position(bb.position() -1); // move back -// } -// } -// return true; -//} -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOChannel.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOChannel.java deleted file mode 100644 index f3ccb4c671e7..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOChannel.java +++ /dev/null @@ -1,371 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.ByteChannel; - - - -/** - * Buffered, non-blocking ByteChannel. - * - * write() data will be added to the buffer. Call startSending() to - * flush. - * - * - * - * - you can use it as a normal non-blocking ByteChannel. - * - you can call getRead - * - * Very different from MINA IoFilters, also much lower level. - * - * - * @author Costin Manolache - */ -public abstract class IOChannel implements ByteChannel, IOConnector.DataReceivedCallback, - IOConnector.DataFlushedCallback { - - /** - * If this channel wraps another channel - for example a socket. - * Will be null if this is the 'root' channel - a socket, memory. - */ - protected IOChannel net; - - /** - * Set with another channel layered on top of the current channel. - */ - protected IOChannel head; - - protected String id; - - /** - * A string that can be parsed to extract the target. - * host:port for normal sockets - */ - protected CharSequence target; - - /** - * Connector that created the channel. - */ - protected IOConnector connector; - - /** - * Callbacks. Will be moved if a new head is inserted. - */ - protected IOConnector.ConnectedCallback connectedCallback; - - /** - * Will be called if any data is received. - * Will also be called on close. Close with lastException set indicates - * an error condition. - */ - protected IOConnector.DataReceivedCallback dataReceivedCallback; - - /** - * Out data is buffered, then sent with startSending. - * This callback indicates the data has been sent. Can be used - * to implement blocking flush. - */ - protected IOConnector.DataFlushedCallback dataFlushedCallback; - - // Last activity timestamp. - // TODO: update and use it ( placeholder ) - public long ts; - - /** - * If an async exception happens. - */ - protected Throwable lastException; - - protected IOChannel() { - } - - public void setConnectedCallback(IOConnector.ConnectedCallback connectedCallback) { - this.connectedCallback = connectedCallback; - } - - public void setDataReceivedCallback(IOConnector.DataReceivedCallback dataReceivedCallback) { - this.dataReceivedCallback = dataReceivedCallback; - } - - /** - * Callback called when the bottom ( OS ) channel has finished flushing. - * - * @param dataFlushedCallback - */ - public void setDataFlushedCallback(IOConnector.DataFlushedCallback dataFlushedCallback) { - this.dataFlushedCallback = dataFlushedCallback; - } - - // Input - public abstract IOBuffer getIn(); - - // Output - public abstract IOBuffer getOut(); - - - /** - * From downstream ( NET ). Pass it to the next channel. - */ - public void handleReceived(IOChannel net) throws IOException { - sendHandleReceivedCallback(); - } - - /** - * Called from lower layer (NET) when the last flush is - * done and all buffers have been sent to OS ( or - * intended recipient ). - * - * Will call the callback or next filter, may do additional - * processing. - * - * @throws IOException - */ - public void handleFlushed(IOChannel net) throws IOException { - sendHandleFlushedCallback(); - } - - private void sendHandleFlushedCallback() throws IOException { - try { - if (dataFlushedCallback != null) { - dataFlushedCallback.handleFlushed(this); - } - if (head != null) { - head.handleFlushed(this); - } - } catch (Throwable t) { - close(); - if (t instanceof IOException) { - throw (IOException) t; - } else { - throw new WrappedException("Error in handleFlushed", t); - } - } - } - - - /** - * Notify next channel or callback that data has been received. - * Called after a lower channel gets more data ( in the IOThread - * for example ). - * - * Also called when closed stream is detected. Can be called - * to just force upper layers to check for data. - */ - public void sendHandleReceivedCallback() throws IOException { - try { - if (dataReceivedCallback != null) { - dataReceivedCallback.handleReceived(this); - } - if (head != null) { - head.handleReceived(this); - } - } catch (Throwable t) { - t.printStackTrace(); - try { - close(); - } catch(Throwable t2) { - t2.printStackTrace(); - } - if (t instanceof IOException) { - throw (IOException) t; - } else { - throw new WrappedException(t); - } - } - } - - /** - * Return last IO exception. - * - * The channel is async, exceptions can happen at any time. - * The normal callback will be called ( connected, received ), it - * should check if the channel is closed and the exception. - */ - public Throwable lastException() { - return lastException; - } - - public void close() throws IOException { - shutdownOutput(); - // Should it read the buffers ? - - if (getIn() == null || getIn().isAppendClosed()) { - return; - } else { - getIn().close(); - sendHandleReceivedCallback(); - } - getIn().hasDataLock.signal(getIn()); - } - - public boolean isOpen() { - return getIn() != null && - getOut() != null && - !getIn().isAppendClosed() && !getOut().isAppendClosed(); - } - - public void shutdownOutput() throws IOException { - if (getOut() == null || getOut().isAppendClosed()) { - return; - } else { - getOut().close(); - startSending(); - } - } - - public void setSink(IOChannel previous) throws IOException { - this.net = previous; - } - - public IOChannel getSink() { - return net; - } - - // Chaining/filtering - - /** - * Called to add an filter after the current channel, for - * example set SSL on top of a socket channel. - * - * The 'next' channel will have the received/flushed callbacks - * of the current channel. The current channel's callbacks will - * be reset. - * - * "Head" is from STREAMS. - * - * @throws IOException - */ - public IOChannel setHead(IOChannel head) throws IOException { - this.head = head; - head.setSink(this); - - // TODO: do we want to migrate them automatically ? - head.setDataReceivedCallback(dataReceivedCallback); - head.setDataFlushedCallback(dataFlushedCallback); - // app.setClosedCallback(closedCallback); - - dataReceivedCallback = null; - dataFlushedCallback = null; - return this; - } - - public IOChannel getFirst() { - IOChannel first = this; - while (true) { - if (!(first instanceof IOChannel)) { - return first; - } - IOChannel before = ((IOChannel) first).getSink(); - if (before == null) { - return first; - } else { - first = before; - } - } - } - - // Socket support - - public void readInterest(boolean b) throws IOException { - if (net != null) { - net.readInterest(b); - } - } - - // Helpers - - public int read(ByteBuffer bb) throws IOException { - return getIn().read(bb); - } - - public int readNonBlocking(ByteBuffer bb) throws IOException { - return getIn().read(bb); - } - - public void waitFlush(long timeMs) throws IOException { - return; - } - - public int readBlocking(ByteBuffer bb, long timeMs) throws IOException { - getIn().waitData(timeMs); - return getIn().read(bb); - } - - /** - * Capture all output in a buffer. - */ - public BBuffer readAll(BBuffer chunk, long to) - throws IOException { - if (chunk == null) { - chunk = BBuffer.allocate(); - } - while (true) { - getIn().waitData(to); - BBucket next = getIn().peekFirst(); - if (getIn().isClosedAndEmpty() && next == null) { - return chunk; - } - if (next == null) { - continue; // false positive - } - chunk.append(next.array(), next.position(), next.remaining()); - getIn().advance(next.remaining()); - } - } - - public int write(ByteBuffer bb) throws IOException { - return getOut().write(bb); - } - - public void write(byte[] data) throws IOException { - getOut().append(data, 0, data.length); - } - - public void write(String string) throws IOException { - write(string.getBytes()); - } - - /** - * Send data in out to the intended recipient. - * This is not blocking. - */ - public abstract void startSending() throws IOException; - - - public void setId(String id) { - this.id = id; - } - - public String getId() { - return id; - } - - public CharSequence getTarget() { - if (net != null) { - return net.getTarget(); - } - return target; - } - - public void setTarget(CharSequence target) { - this.target = target; - } - - public static final String ATT_REMOTE_HOSTNAME = "RemoteHostname"; - public static final String ATT_LOCAL_HOSTNAME = "LocalHostname"; - public static final String ATT_REMOTE_PORT = "RemotePort"; - public static final String ATT_LOCAL_PORT = "LocalPort"; - public static final String ATT_LOCAL_ADDRESS = "LocalAddress"; - public static final String ATT_REMOTE_ADDRESS = "RemoteAddress"; - - public Object getAttribute(String name) { - if (net != null) { - return net.getAttribute(name); - } - return null; - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOConnector.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOConnector.java deleted file mode 100644 index d8375f9ce936..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOConnector.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; -import java.util.Timer; - - -/** - * Factory for IOChannels, with support for caching. - * - * - * @author Costin Manolache - */ -public abstract class IOConnector { - - public static interface DataReceivedCallback { - /** - * Called when data or EOF has been received. - */ - public void handleReceived(IOChannel ch) throws IOException; - } - - /** - * Callback for accept and connect. - * - * Will also be called if an error happens while connecting, in - * which case the connection will be closed. - */ - public static interface ConnectedCallback { - public void handleConnected(IOChannel ch) throws IOException; - } - - public static interface DataFlushedCallback { - public void handleFlushed(IOChannel ch) throws IOException; - } - - protected Timer timer; - - public Timer getTimer() { - return timer; - } - - /** - * If the connector is layered on top of a different connector, - * return the lower layer ( for example the socket connector) - */ - public IOConnector getNet() { - return null; - } - - public abstract void acceptor(IOConnector.ConnectedCallback sc, - CharSequence port, Object extra) - throws IOException; - - // TODO: failures ? - // TODO: use String target or url - public abstract void connect(String host, int port, - IOConnector.ConnectedCallback sc) throws IOException; - - public void stop() { - if (timer != null) { - timer.cancel(); - } - } -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOInputStream.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOInputStream.java deleted file mode 100644 index 3c167f170950..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOInputStream.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; -import java.io.InputStream; - - -/** - * Similar with ServletInputStream - adds readLine(byte[]..), using - * a IOBuffer. - * - * - * - * @author Costin Manolache - */ -public class IOInputStream extends InputStream { - - IOBuffer bb; - long timeout; - - public IOInputStream(IOChannel httpCh, long to) { - bb = httpCh.getIn(); - this.timeout = to; - } - - @Override - public int read() throws IOException { - // getReadableBucket/peekFirst returns a buffer with at least - // 1 byte in it. - if (bb.isClosedAndEmpty()) { - return -1; - } - bb.waitData(timeout); - if (bb.isClosedAndEmpty()) { - return -1; - } - - return bb.read(); - } - - public int read(byte[] buf, int off, int len) throws IOException { - if (bb.isClosedAndEmpty()) { - return -1; - } - bb.waitData(timeout); - if (bb.isClosedAndEmpty()) { - return -1; - } - return bb.read(buf, off, len); - } - - /** - * Servlet-style read line: terminator is \n or \r\n, left in buffer. - */ - public int readLine(byte[] b, int off, int len) throws IOException { - if (len <= 0) { - return 0; - } - int count = 0, c; - - while ((c = read()) != -1) { - b[off++] = (byte)c; - count++; - if (c == '\n' || count == len) { - break; - } - } - return count > 0 ? count : -1; - } -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOOutputStream.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOOutputStream.java deleted file mode 100644 index 9b67b486c6cc..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOOutputStream.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.CharConversionException; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.text.MessageFormat; - -/** - * Same methods with ServletOutputStream. - * - * There is no restriction in using the Writer and InputStream at the - * same time - the servlet layer will impose it for compat. You can also use - * IOBuffer directly. - * - * If you mix stream and writer: - * - call BufferWriter.push() to make sure all chars are sent down - * - the BufferOutputStream doesn't cache any data, all goes to the - * IOBuffer. - * - flush() on BufferOutputStream and BufferWriter will send the data - * to the network and block until it gets to the socket ( so it can - * throw exception ). - * - You can also use non-blocking flush methods in IOBuffer, and a - * callback if you want to know when the write was completed. - * - * @author Costin Manolache - */ -public class IOOutputStream extends OutputStream { - - IOBuffer bb; - IOChannel ch; - int bufferSize = 8 * 1024; - - int wSinceFlush = 0; - - public IOOutputStream(IOBuffer out, IOChannel httpMessage) { - this.bb = out; - ch = httpMessage; - } - - public void recycle() { - wSinceFlush = 0; - bufferSize = 8 * 1024; - } - - public void reset() { - wSinceFlush = 0; - bb.clear(); - } - - public int getWrittenSinceFlush() { - return wSinceFlush; - } - - - public int getBufferSize() { - return bufferSize; - } - - public void setBufferSize(int size) { - if (size > bufferSize) { - bufferSize = size; - } - } - - private void updateSize(int cnt) throws IOException { - wSinceFlush += cnt; - if (wSinceFlush > bufferSize) { - flush(); - } - } - - @Override - public void write(int b) throws IOException { - bb.append((char) b); - updateSize(1); - } - - @Override - public void write(byte data[]) throws IOException { - write(data, 0, data.length); - } - - @Override - public void write(byte data[], int start, int len) throws IOException { - bb.append(data, start, len); - updateSize(len); - } - - public void flush() throws IOException { - if (ch != null) { - ch.startSending(); - - ch.waitFlush(Long.MAX_VALUE); - } - wSinceFlush = 0; - } - - public void close() throws IOException { - flush(); - bb.close(); - } - - - public void write(ByteBuffer source) throws IOException { - write(source.array(), source.position(), source.remaining()); - source.position(source.limit()); - } - - public void print(String s) throws IOException { - if (s==null) s="null"; - int len = s.length(); - for (int i = 0; i < len; i++) { - char c = s.charAt (i); - - // - // XXX NOTE: This is clearly incorrect for many strings, - // but is the only consistent approach within the current - // servlet framework. It must suffice until servlet output - // streams properly encode their output. - // - if ((c & 0xff00) != 0) { // high order byte must be zero - String errMsg = "Not ISO-8859-1"; - Object[] errArgs = new Object[1]; - errArgs[0] = new Character(c); - errMsg = MessageFormat.format(errMsg, errArgs); - throw new CharConversionException(errMsg); - } - write (c); - } - } - - - public void print(boolean b) throws IOException { - String msg; - if (b) { - msg = "true"; - } else { - msg = "false"; - } - print(msg); - } - - public void print(char c) throws IOException { - print(String.valueOf(c)); - } - - public void print(int i) throws IOException { - print(String.valueOf(i)); - } - - public void print(long l) throws IOException { - print(String.valueOf(l)); - } - - public void print(float f) throws IOException { - print(String.valueOf(f)); - } - - public void print(double d) throws IOException { - print(String.valueOf(d)); - } - - public void println() throws IOException { - print("\r\n"); - } - - public void println(String s) throws IOException { - print(s); - println(); - } - - public void println(boolean b) throws IOException { - print(b); - println(); - } - - public void println(char c) throws IOException { - print(c); - println(); - } - - public void println(int i) throws IOException { - print(i); - println(); - } - - public void println(long l) throws IOException { - print(l); - println(); - } - - public void println(float f) throws IOException { - print(f); - println(); - } - - public void println(double d) throws IOException { - print(d); - println(); - } -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOReader.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOReader.java deleted file mode 100644 index 4d0fadedca0e..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOReader.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; -import java.io.Reader; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CoderResult; -import java.nio.charset.CodingErrorAction; -import java.nio.charset.MalformedInputException; -import java.nio.charset.UnmappableCharacterException; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - - -/** - * Conversion from Bytes to Chars and support for decoding. - * - * Replaces tomcat B2CConverter with NIO equivalent. B2CConverter was a hack - * (re)using an dummy InputStream backed by a ByteChunk. - * - * @author Costin Manolache - */ -public class IOReader extends Reader { - - IOBuffer iob; - Map decoders = new HashMap(); - CharsetDecoder decoder; - - private static boolean REUSE = true; - String enc; - private boolean closed; - public static final String DEFAULT_ENCODING = "ISO-8859-1"; - long timeout = 0; - - public IOReader(IOBuffer iob) { - this.iob = iob; - } - - public void setTimeout(long to) { - timeout = to; - } - - public void setEncoding(String charset) { - enc = charset; - if (enc == null) { - enc = DEFAULT_ENCODING; - } - decoder = REUSE ? decoders.get(enc) : null; - if (decoder == null) { - decoder = Charset.forName(enc).newDecoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); - if (REUSE) { - decoders.put(enc, decoder); - } - } - } - - public String getEncoding() { - return enc; - } - - public void recycle() { - if (decoder != null) { - decoder.reset(); - } - closed = false; - enc = null; - } - - private void checkClosed() throws IOException { - if (closed) throw new IOException("closed"); - } - - public boolean ready() { - return iob.peekFirst() != null; - } - - public int read(java.nio.CharBuffer target) throws IOException { - int len = target.remaining(); - char[] cbuf = new char[len]; - int n = read(cbuf, 0, len); - if (n > 0) - target.put(cbuf, 0, n); - return n; - } - - public int read() throws IOException { - char cb[] = new char[1]; - if (read(cb, 0, 1) == -1) - return -1; - else - return cb[0]; - } - - @Override - public void close() throws IOException { - closed = true; - iob.close(); - } - - /** - * Used if a bucket ends on a char boundary - */ - BBuffer underFlowBuffer = BBuffer.allocate(10); - public static AtomicInteger underFlows = new AtomicInteger(); - - /** - * Decode all bytes - for example a URL or header. - */ - public void decodeAll(BBucket bb, CBuffer c) { - - while (bb.hasRemaining()) { - CharBuffer charBuffer = c.getAppendCharBuffer(); - CoderResult res = decode1(bb, charBuffer, true); - c.returnAppendCharBuffer(charBuffer); - if (res != CoderResult.OVERFLOW) { - if (res == CoderResult.UNDERFLOW || bb.hasRemaining()) { - System.err.println("Ignored trailing bytes " + bb.remaining()); - } - return; - } - } - - } - - /** - * Do one decode pass. - */ - public CoderResult decode1(BBucket bb, CharBuffer c, boolean eof) { - ByteBuffer b = bb.getByteBuffer(); - - if (underFlowBuffer.hasRemaining()) { - // Need to get rid of the underFlow first - for (int i = 0; i < 10; i++) { - underFlowBuffer.put(b.get()); - bb.position(b.position()); - ByteBuffer ub = underFlowBuffer.getByteBuffer(); - CoderResult res = decoder.decode(ub, c, eof); - if (! ub.hasRemaining()) { - // underflow resolved - break; - } - if (res == CoderResult.OVERFLOW) { - return res; - } - } - if (underFlowBuffer.hasRemaining()) { - throw new RuntimeException("Can't resolve underflow after " + - "10 bytes"); - } - } - - CoderResult res = decoder.decode(b, c, eof); - bb.position(b.position()); - - if (res == CoderResult.UNDERFLOW && bb.hasRemaining()) { - // b ends on a boundary - underFlowBuffer.append(bb.array(), bb.position(), bb.remaining()); - bb.position(bb.limit()); - } - return res; - } - - @Override - public int read(char[] cbuf, int offset, int length) throws IOException { - checkClosed(); - if (length == 0) { - return 0; - } - // we can either allocate a new CharBuffer or use a - // static one and copy. Seems simpler this way - needs some - // load test, but InputStreamReader seems to do the same. - CharBuffer out = CharBuffer.wrap(cbuf, offset, length); - - CoderResult result = CoderResult.UNDERFLOW; - - BBucket bucket = iob.peekFirst(); - - // Consume as much as possible without blocking - while (result == CoderResult.UNDERFLOW) { - // fill the buffer if needed - if (bucket == null || ! bucket.hasRemaining()) { - if (out.position() > offset) { - // we could return the result without blocking read - break; - } - bucket = null; - while (bucket == null) { - iob.waitData(timeout); - bucket = iob.peekFirst(); - if (bucket == null && iob.isClosedAndEmpty()) { - // EOF, we couldn't decode anything - break; - } - } - - if (bucket == null) { - // eof - break; - } - } - - result = decode1(bucket, out, false); - } - - if (result == CoderResult.UNDERFLOW && iob.isClosedAndEmpty()) { - // Flush out any remaining data - ByteBuffer bytes = bucket == null ? - underFlowBuffer.getByteBuffer() : bucket.getByteBuffer(); - result = decoder.decode(bytes, out, true); - if (bucket == null) { - underFlowBuffer.position(bytes.position()); - } else { - bucket.position(bytes.position()); - } - - decoder.flush(out); - decoder.reset(); - } - - if (result.isMalformed()) { - throw new MalformedInputException(result.length()); - } else if (result.isUnmappable()) { - throw new UnmappableCharacterException(result.length()); - } - - int rd = out.position() - offset; - return rd == 0 ? -1 : rd; - } -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOWriter.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOWriter.java deleted file mode 100644 index 2def8e8ba261..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/IOWriter.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; -import java.io.Writer; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CoderResult; -import java.nio.charset.CodingErrorAction; -import java.util.HashMap; -import java.util.Map; - -/** - * Converts chars to bytes, and associated encoding. - * - * Replaces C2B from old tomcat. - * - * @author Costin Manolache - */ -public class IOWriter extends Writer { - - IOBuffer iob; - Map encoders = new HashMap(); - CharsetEncoder encoder; - - private static boolean REUSE = true; - String enc; - private boolean closed; - IOChannel ioCh; - - public IOWriter(IOChannel iob) { - this.ioCh = iob; - if (iob != null) { - this.iob = iob.getOut(); - } - } - - public void setEncoding(String charset) { - if (charset == null) { - charset = "UTF-8"; - } - enc = charset; - encoder = getEncoder(charset); - if (encoder == null) { - encoder = Charset.forName(charset).newEncoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); - if (REUSE) { - encoders.put(charset, encoder); - } - } - } - - CharsetEncoder getEncoder(String charset) { - if (charset == null) { - charset = "UTF-8"; - } - encoder = REUSE ? encoders.get(charset) : null; - if (encoder == null) { - encoder = Charset.forName(charset).newEncoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); - if (REUSE) { - encoders.put(charset, encoder); - } - } - return encoder; - } - - public String getEncoding() { - return enc; - } - - public void recycle() { - if (encoder != null) { - encoder.reset(); - } - closed = false; - enc = null; - } - - - private void checkClosed() throws IOException { - if (closed) throw new IOException("closed"); - } - - @Override - public void close() throws IOException { - closed = true; - // flush the buffer ? - ByteBuffer out = iob.getWriteBuffer(); - encoder.flush(out); - iob.releaseWriteBuffer(1); - - iob.close(); - } - - /** - * Used if a bucket ends on a char boundary - */ - CBuffer underFlowBuffer = CBuffer.newInstance(); - - public void encode1(CBuffer cc, - BBuffer bb, CharsetEncoder encoder, boolean eof) { - CharBuffer c = cc.getNioBuffer(); - ByteBuffer b = bb.getWriteByteBuffer(c.remaining() * 2); - encode1(c, b, encoder, eof); - cc.returnNioBuffer(c); - bb.limit(b.position()); - } - - /** - * - * @param cc - * @return - */ - public void encode1(CharBuffer c, - ByteBuffer b, CharsetEncoder encoder, boolean eof) { - - // TODO: buffer growth in caller - - CoderResult res = encoder.encode(c, b, eof); - if (res == CoderResult.OVERFLOW) { - // bb is full - next call will get a larger buffer ( it - // grows ) or maybe will be flushed. - } - if (res == CoderResult.UNDERFLOW && c.remaining() > 0 && !eof) { - // TODO: if eof -> exception ? - // cc has remaining chars - for example a surrogate start. - underFlowBuffer.put(c); - } - - } - - public void encodeAll(CBuffer cc, - BBuffer bb, CharsetEncoder encoder, boolean eof) { - while (cc.length() > 0) { - encode1(cc, bb, encoder, eof); - } - } - - public void encodeAll(CBuffer cc, - BBuffer bb, String cs) { - encodeAll(cc, bb, getEncoder(cs), true); - } - - @Override - public void flush() throws IOException { - if (ioCh != null) { - ioCh.startSending(); - } - } - - // TODO: use it for utf-8 - public static int char2utf8(byte[] ba, int off, char c, char c1) { - int i = 0; - if (c < 0x80) { - ba[off++] = (byte) (c & 0xFF); - return 1; - } else if (c < 0x800) - { - ba[off++] = (byte) (0xC0 | c >> 6); - ba[off++] = (byte) (0x80 | c & 0x3F); - return 2; - } - else if (c < 0x10000) - { - ba[off++] = (byte) ((0xE0 | c >> 12)); - ba[off++] = (byte) ((0x80 | c >> 6 & 0x3F)); - ba[off++] = (byte) ((0x80 | c & 0x3F)); - return 3; - } - else if (c < 0x200000) - { - ba[off++] = (byte) ((0xF0 | c >> 18)); - ba[off++] = (byte) ((0x80 | c >> 12 & 0x3F)); - ba[off++] = (byte) ((0x80 | c >> 6 & 0x3F)); - ba[off++] = (byte) ((0x80 | c & 0x3F)); - return 4; - } - - - return i; - } - - - /** - * Just send the chars to the byte[], without flushing down. - * - * @throws IOException - */ - public void push() throws IOException { - // we don't cache here. - } - - @Override - public void write(char[] cbuf, int off, int len) throws IOException { - checkClosed(); - CharBuffer cb = CharBuffer.wrap(cbuf, off, len); - - while (cb.remaining() > 0) { - ByteBuffer wb = iob.getWriteBuffer(); - encode1(cb, wb, encoder, false); - iob.releaseWriteBuffer(1); - } - } - - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/MemoryIOConnector.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/MemoryIOConnector.java deleted file mode 100644 index 5f6b50c01d24..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/MemoryIOConnector.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; -import java.util.Timer; - -public class MemoryIOConnector extends IOConnector { - - public static class MemoryIOChannel extends IOChannel { - IOBuffer netIn = new IOBuffer(this) { - protected void notifyDataAvailable(Object bb) throws IOException { - sendHandleReceivedCallback(); - super.notifyDataAvailable(bb); - } - }; - IOBuffer netOut = new IOBuffer(this); - - /** - * All flushed output will be saved to 'out'. - */ - public BBuffer out = BBuffer.allocate(4096); - - public MemoryIOChannel() { - } - - public void startSending() throws IOException { - // - IOBuffer bb = netOut; - while (true) { - if (bb.isClosedAndEmpty()) { - break; - } - BBucket first = bb.peekFirst(); - if (first == null) { - break; - } - BBucket iob = ((BBucket) first); - out.append(iob.array(), iob.position(), iob.remaining()); - bb.advance(iob.remaining()); - iob.release(); - } - - handleFlushed(this); - } - - @Override - public IOBuffer getIn() { - return netIn; - } - @Override - public IOBuffer getOut() { - return netOut; - } - } - - // TODO: in-process communication without sockets for testing - ConnectedCallback acceptor; - MemoryIOConnector server; - - public MemoryIOConnector() { - timer = new Timer(true); - } - - public MemoryIOConnector withServer(MemoryIOConnector server) { - this.server = server; - return server; - } - - @Override - public void acceptor(ConnectedCallback sc, CharSequence port, Object extra) - throws IOException { - this.acceptor = sc; - } - - @Override - public void connect(String host, int port, ConnectedCallback sc) - throws IOException { - IOChannel ch = new MemoryIOChannel(); - IOChannel sch = new MemoryIOChannel(); - // TODO: mix - if (server != null && server.acceptor != null) { - server.acceptor.handleConnected(sch); - } - sc.handleConnected(ch); - } - -} \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/NioChannel.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/NioChannel.java deleted file mode 100644 index 559a9e5414a9..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/NioChannel.java +++ /dev/null @@ -1,198 +0,0 @@ -package org.apache.tomcat.lite.io; - -import java.io.IOException; -import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.nio.channels.ByteChannel; -import java.nio.channels.Channel; - - -/** - * Wrapper around the real channel, with selector-specific info. - * - * It is stored as an attachment in the selector. - */ -public class NioChannel implements ByteChannel { - - public static interface NioChannelCallback { - public void handleConnected(NioChannel ch) throws IOException; - public void handleClosed(NioChannel ch) throws IOException; - public void handleReadable(NioChannel ch) throws IOException; - public void handleWriteable(NioChannel ch) throws IOException; - - } - - NioChannel(NioThread sel) { - this.sel = sel; - } - - // APR long is wrapped in a ByteChannel as well - with few other longs. - Channel channel; - - // sync access. - Object selKey; - - NioThread sel; - - /** - * If != 0 - the callback will be notified closely after this time. - * Used for timeouts. - */ - long nextTimeEvent = 0; - - // Callbacks - Runnable timeEvent; - - NioChannelCallback callback; - - - Throwable lastException; - - // True if the callback wants to be notified of read/write - boolean writeInterest; - boolean readInterest; - - // shutdownOutput has been called ? - private boolean outClosed = false; - - // read() returned -1 OR input buffer closed ( no longer interested ) - boolean inClosed = false; - - // Saved to allow debug messages for bad interest/looping - int lastReadResult; - int zeroReads = 0; - int lastWriteResult; - - protected NioChannel() { - - } - - public NioThread getSelectorThread() { - return sel; - } - - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append("SelData/") - .append(writeInterest ? "W/" : "") - .append(readInterest ? "R/" : "") - .append(outClosed ? "Out-CLOSE/" : "") - .append(inClosed ? "In-CLOSE/" : "") - .append("/") - .append(channel.toString()); - - return sb.toString(); - } - - public Channel getChannel() { - return channel; - } - - public boolean isOpen() { - // in and out open - return channel.isOpen() && !outClosed && !inClosed; - } - - public int read(ByteBuffer bb) throws IOException { - return sel.readNonBlocking(this, bb); - } - - public int write(ByteBuffer bb) throws IOException { - return sel.writeNonBlocking(this, bb); - } - - public void readInterest(boolean b) throws IOException { - sel.readInterest(this, b); - } - - public void writeInterest() throws IOException { - sel.writeInterest(this); - } - - public InetAddress getAddress(boolean remote) { - return sel.getAddress(this, remote); - } - - public int getPort(boolean remote) { - return sel.getPort(this, remote); - } - - /** - * Run in selector thread. - */ - public void runInSelectorThread(Runnable t) throws IOException { - sel.runInSelectorThread(t); - } - - /** - * Request a timer event. The thread will generate the events at - * a configurable interval - for example no more often than 0.5 sec. - */ - public void setTimer(long timeMs, Runnable cb) { - this.nextTimeEvent = timeMs; - this.timeEvent = cb; - } - - /** - * shutdown out + in - * If there is still data in the input buffer - RST will be sent - * instead of FIN. - * - * - * The proper way to close a connection is to shutdownOutput() first, - * wait until read() return -1, then call close(). - * - * If read() returns -1, you need to finish sending, call shutdownOutput() - * than close. - * If read() returns -1 and there is an error - call close() - * directly. - * - */ - @Override - public void close() throws IOException { - shutdownOutput(); - inputClosed(); - } - - /** - * Send TCP close(FIN). HTTP uses this to transmit end of body. The other end - * detects this with a '-1' in read(). - * - * All other forms of close() are reported as exceptions in read(). - * - * @throws IOException - */ - public void shutdownOutput() throws IOException { - synchronized (channel) { - if (!outClosed) { - outClosed = true; - try { - sel.shutdownOutput(this); - } catch (IOException ex) { - // ignore - } - } - if (inClosed) { - sel.close(this, null); - } - } - } - - void inputClosed() throws IOException { - synchronized (channel) { - if (inClosed) { - // already closed - return; - } - inClosed = true; // detected end - if (outClosed) { - sel.close(this, null); - } else { - // Don't close the channel - write may still work ? - readInterest(false); - } - } - } - - boolean closeCalled = false; -} \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/NioThread.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/NioThread.java deleted file mode 100644 index 3b6e649252ac..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/NioThread.java +++ /dev/null @@ -1,1154 +0,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.lite.io; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketAddress; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.nio.channels.ByteChannel; -import java.nio.channels.Channel; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.nio.channels.spi.SelectorProvider; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.io.NioChannel.NioChannelCallback; - -/** - * Abstract NIO/APR to avoid some of the complexity and allow more code - * sharing and experiments. - * - * SelectorThread provides non-blocking methods for read/write and generates - * callbacks using SelectorCallback. It has no buffers of its own. - * - * This is non-blocking, non-buffering and uses callbacks. - * - * @author Costin Manolache - */ -public class NioThread implements Runnable { - - // ----------- IO handling ----------- - protected long inactivityTimeout = 5000; - protected Thread selectorThread; - - - static Logger log = Logger.getLogger("NIO"); - - Selector selector; - - // will be processed in the selector thread - List readInterest = new ArrayList(); - List writeInterest = new ArrayList(); - List connectAcceptInterest = new ArrayList(); - List updateCallback = new ArrayList(); - List closeInterest = new LinkedList(); - List runnableInterest = new ArrayList(); - - // Statistics - AtomicInteger opened = new AtomicInteger(); - AtomicInteger closed = new AtomicInteger(); - AtomicInteger loops = new AtomicInteger(); - - AtomicInteger callbackCount = new AtomicInteger(); - AtomicLong callbackTotalTime = new AtomicLong(); - long maxCallbackTime = 0; - - // actives are also stored in the Selector. This is only updated in the main - // thread - public ArrayList active = new ArrayList(); - - public static boolean debug = false; - boolean debugWakeup = false; - boolean running = true; - - long lastWakeup = System.currentTimeMillis(); // last time we woke - long nextWakeup; // next scheduled wakeup - - // Normally select will wait for the next time event - if it's - // too far in future, maxSleep will override it. - private long maxSleep = 600000; - long sleepTime = maxSleep; - - // Never sleep less than minSleep. This defines the resulution for - // time events. - private long minSleep = 100; - - boolean daemon = false; - - // TODO: trace log - record all events with timestamps, replay - - public NioThread(String name, boolean daemon) { - try { - selectorThread = (name == null) ? new Thread(this) : - new Thread(this, name); - - selector = Selector.open(); - // TODO: start it on-demand, close it when not in use - selectorThread.setDaemon(daemon); - this.daemon = daemon; - - selectorThread.start(); - - } catch(IOException e) { - throw new RuntimeException(e); - } - } - - /** - * Opened sockets, waiting for something ( close at least ) - */ - public int getOpen() { - return opened.get(); - } - - /** - * Closed - we're done with them. - */ - public int getClosed() { - return closed.get(); - } - - public int getActive() { - return active.size(); - } - - public int getCallbacks() { - return callbackCount.get(); - } - - public long getMaxCallbackTime() { - return maxCallbackTime; - } - - public long getAvgCallbackTime() { - int cnt = callbackCount.get(); - if (cnt == 0) { - return 0; - } - return callbackTotalTime.get() / cnt; - } - - /** - * How many times we looped - */ - public int getLoops() { - return loops.get(); - } - - public long getLastWakeup() { - return lastWakeup; - } - - public long getTimeSinceLastWakeup() { - return System.currentTimeMillis() - lastWakeup; - } - - /** - * Close all resources, stop accepting, stop the thread. - * The actual stop will happen in background. - */ - public void stop() { - running = false; - if (debug) { - log.info("Selector thread stop " + this); - } - selector.wakeup(); - } - - public void run() { - int sloops = 0; - if (debug) { - log.info("Start NIO thread, daemon=" + daemon); - } - while (running) { - // if we want timeouts - set here. - try { - loops.incrementAndGet(); - - // Check if new requests were added - processPending(); - - // Timers - long now = System.currentTimeMillis(); - if (nextWakeup < now) { - // We don't want to iterate on every I/O - updateSleepTimeAndProcessTimeouts(now); - } - - int selected = selector.select(sleepTime); - - lastWakeup = System.currentTimeMillis(); - long slept = lastWakeup - now; - - if (debugWakeup && selected == 0) { - if (sleepTime < maxSleep - 1000) { // short wakeup - log.info("Wakeup " + selected + " " + slept - + " " + sleepTime); - } - } - if (slept < 10 && selected == 0) { - if (sloops > 50) { - sloops = 0; - log.severe("Looping !"); - resetSelector(); - } - sloops++; - } - - // handle events for existing req first. - if (selected != 0) { - sloops = 0; - int callbackCnt = 0; - Set sel = selector.selectedKeys(); - Iterator i = sel.iterator(); - - while (i.hasNext()) { - callbackCnt++; - long beforeCallback = System.currentTimeMillis(); - SelectionKey sk = i.next(); - i.remove(); - - boolean valid = sk.isValid(); - int readyOps = (valid) ? sk.readyOps() : 0; - - NioChannel ch = (NioChannel) sk.attachment(); - if (debugWakeup) { - log.info("Wakeup selCnt=" + selected + " slept=" + (lastWakeup - now) + - " ready: " + readyOps + " v=" + - sk.isValid() + " ch=" + ch); - } - if (ch == null) { - log.severe("Missing channel"); - sk.cancel(); - continue; - } - if (ch.selKey != sk) { - // if (ch.selKey != null) { // null if closed - log.severe("Invalid state, selKey doesn't match "); - ch.selKey = sk; - } - if (ch.channel != sk.channel()) { - ch.channel = sk.channel(); - log.severe("Invalid state, channel doesn't match "); - } - - if (!sk.isValid()) { - if (debug) { - log.info("!isValid, closed socket " + ch); - } - ch.close(); - continue; - } - - try { - int ready = sk.readyOps(); - // callbacks - if (sk.isValid() && sk.isAcceptable()) { - handleAccept(ch, sk); - } - - if (sk.isValid() && sk.isConnectable()) { - sk.interestOps(sk.interestOps() & ~SelectionKey.OP_CONNECT); - SocketChannel sc = (SocketChannel) sk.channel(); - handleConnect(ch, sc); - } - - if (sk.isValid() && sk.isWritable()) { - // Needs to be explicitely re-enabled by callback - // if more data. - sk.interestOps(sk.interestOps() & ~SelectionKey.OP_WRITE); - ch.writeInterest = false; - handleDataWriteable(ch); - } - - if (sk.isValid() && sk.isReadable()) { - // Leave readable interest ! - handleReadable(ch); - } - - long callbackTime = - System.currentTimeMillis() - beforeCallback; - - if (callbackTime > 250) { - log.warning("Callback too long ! ops=" + ready + - " time=" + callbackTime + " ch=" + ch + - " " + callbackCnt); - } - if (callbackTime > maxCallbackTime) { - maxCallbackTime = callbackTime; - } - callbackCount.incrementAndGet(); - this.callbackTotalTime.addAndGet(callbackTime); - - } catch (Throwable t) { - log.log(Level.SEVERE, "SelectorThread: Channel error, closing", t); - ch.lastException = t; - ch.close(); - } - - } - // All at once - sel.clear(); - } - - } catch (Throwable e) { - log.log(Level.SEVERE, "SelectorThread: Error in select", e); - } - } // while(running) - log.info("SelectorThread done"); - } - - private void log(String msg, int selected, long slept, SelectionKey sk, int readyOps) { - log.info(msg + " " + selected - + " " + slept - + " ready: " + readyOps + " " - + sk.readyOps() + " " + sk); - } - - private void resetSelector() throws IOException, ClosedChannelException { - // Let's close all sockets - one is bad, but we can't do much. - Set keys = selector.keys(); - //Set keys = selector.keys(); - ArrayList oldCh = new ArrayList(); - ArrayList interests = new ArrayList(); - for (SelectionKey k : keys) { - NioChannel cd = (NioChannel) k.attachment(); - interests.add(k.interestOps()); - oldCh.add(cd); - k.cancel(); - } - - selector.close(); - selector = Selector.open(); - for (int i = 0; i < oldCh.size(); i++) { - NioChannel selectorData = oldCh.get(i); - if (selectorData == null) { - continue; - } - int interest = interests.get(i); - if (selectorData.channel instanceof ServerSocketChannel) { - ServerSocketChannel socketChannel = - (ServerSocketChannel) selectorData.channel; - selectorData.selKey = socketChannel.register(selector, SelectionKey.OP_ACCEPT); - } else { - SocketChannel socketChannel = - (SocketChannel) selectorData.channel; - if (interest != 0) { - selectorData.selKey = socketChannel.register(selector, - interest); - } - - } - } - } - - private void handleReadable(NioChannel ch) throws IOException { - ch.lastReadResult = 0; - if (ch.callback != null) { - ch.callback.handleReadable(ch); - } - if (ch.lastReadResult != 0 && ch.readInterest && !ch.inClosed) { - log.warning("LOOP: read interest" + - " after incomplete read"); - ch.close(); - } - } - - private void handleDataWriteable(NioChannel ch) throws IOException { - ch.lastWriteResult = 0; - if (ch.callback != null) { - ch.callback.handleWriteable(ch); - } - if (ch.lastWriteResult > 0 && ch.writeInterest) { - log.warning("SelectorThread: write interest" + - " after incomplete write, LOOP"); - } - } - - private void handleConnect(NioChannel ch, SocketChannel sc) - throws IOException, SocketException { - try { - if (!sc.finishConnect()) { - log.warning("handleConnected - finishConnect returns false"); - } - ch.sel = this; - //sc.socket().setSoLinger(true, 0); - if (debug) { - log.info("connected() " + ch + " isConnected()=" + sc.isConnected() + " " + - sc.isConnectionPending()); - } - - readInterest(ch, true); - } catch (Throwable t) { - close(ch, t); - } - try { - if (ch.callback != null) { - ch.callback.handleConnected(ch); - } - } catch(Throwable t1) { - log.log(Level.WARNING, "Error in connect callback", t1); - } - - } - - private void handleAccept(NioChannel ch, SelectionKey sk) - throws IOException, ClosedChannelException { - SelectableChannel selc = sk.channel(); - ServerSocketChannel ssc=(ServerSocketChannel)selc; - SocketChannel sockC = ssc.accept(); - sockC.configureBlocking(false); - - NioChannel acceptedChannel = new NioChannel(this); - acceptedChannel.selKey = sockC.register(selector, - SelectionKey.OP_READ, - acceptedChannel); - acceptedChannel.channel = sockC; - - synchronized (active) { - active.add(acceptedChannel); - } - - // Find the callback for the new socket - if (ch.callback != null) { - // TODO: use future ! - try { - ch.callback.handleConnected(acceptedChannel); - } catch (Throwable t) { - log.log(Level.SEVERE, "SelectorThread: Channel error, closing ", t); - acceptedChannel.lastException = t; - acceptedChannel.close(); - } - } - - //sk.interestOps(sk.interestOps() | SelectionKey.OP_ACCEPT); - if (debug) { - log.info("handleAccept " + ch); - } - } - - - public void shutdownOutput(NioChannel ch) throws IOException { - Channel channel = ch.channel; - if (channel instanceof SocketChannel) { - SocketChannel sc = (SocketChannel) channel; - if (sc.isOpen() && sc.isConnected()) { - if (debug) { - log.info("Half shutdown " + ch); - } - sc.socket().shutdownOutput(); // TCP end to the other side - } - } - } - - /** - * Called from the IO thread - */ - private void closeIOThread(NioChannel ch, boolean remove) { - SelectionKey sk = (SelectionKey) ch.selKey; - Channel channel = ch.channel; - try { - synchronized(closeInterest) { - if (ch.closeCalled) { - if (debug) { - log.severe("Close called 2x "); - } - return; - } - ch.closeCalled = true; - int o = opened.decrementAndGet(); - if (debug) { - log.info("-------------> close: " + ch + " t=" + ch.lastException); - } - if (sk != null) { - if (sk.isValid()) { - sk.interestOps(0); - } - sk.cancel(); - ch.selKey = null; - } - - if (channel instanceof SocketChannel) { - SocketChannel sc = (SocketChannel) channel; - - if (sc.isConnected()) { - if (debug) { - log.info("Close socket, opened=" + o); - } - try { - sc.socket().shutdownInput(); - } catch(IOException io1) { - } - try { - sc.socket().shutdownOutput(); // TCP end to the other side - } catch(IOException io1) { - } - sc.socket().close(); - } - } - channel.close(); - - closed.incrementAndGet(); - - if (ch.callback != null) { - ch.callback.handleClosed(ch); - } - // remove from active - false only if already removed - if (remove) { - synchronized (active) { - boolean removed = active.remove(ch); - } - } - } - } catch (IOException ex2) { - log.log(Level.SEVERE, "SelectorThread: Error closing socket ", ex2); - } - } - - // --------------- Socket op abstractions ------------ - - public int readNonBlocking(NioChannel selectorData, ByteBuffer bb) - throws IOException { - try { - int off = bb.position(); - - int done = 0; - - done = ((SocketChannel) selectorData.channel).read(bb); - - if (debug) { - log.info("-------------readNB rd=" + done + " bb.limit=" + - bb.limit() + " pos=" + bb.position() + " " + selectorData); - } - if (done > 0) { - if (debug) { - if (!bb.isDirect()) { - String s = new String(bb.array(), off, - bb.position() - off); - log.info("Data:\n" + s); - } else { - log.info("Data: " + bb.toString()); - } - } - selectorData.zeroReads = 0; - } else if (done < 0) { - if (debug) { - log.info("SelectorThread: EOF while reading " + selectorData); - } - } else { - // need more... - if (selectorData.lastReadResult == 0) { - selectorData.zeroReads++; - if (selectorData.zeroReads > 6) { - log.severe("LOOP 0 reading "); - selectorData.lastException = new IOException("Polling read"); - selectorData.close(); - return -1; - } - } - } - selectorData.lastReadResult = done; - return done; - } catch(IOException ex) { - if (debug) { - log.info("readNB error rd=" + -1 + " bblen=" + - (bb.limit() - bb.position()) + " " + selectorData + " " + ex); - } - // common case: other side closed the connection. No need for trace - if (ex.toString().indexOf("Connection reset by peer") < 0) { - ex.printStackTrace(); - } - selectorData.lastException = ex; - selectorData.close(); - return -1; - } - } - - /** - * May be called from any thread - */ - public int writeNonBlocking(NioChannel selectorData, ByteBuffer bb) - throws IOException { - try { - if (debug) { - log.info("writeNB pos=" + bb.position() + " len=" + - (bb.limit() - bb.position()) + " " + selectorData); - if (!bb.isDirect()) { - String s = new String(bb.array(), bb.position(), - - bb.limit() - bb.position()); - log.info("Data:\n" + s); - } - } - if (selectorData.writeInterest) { - // writeInterest will be false after a callback, if it is - // set it means we want to wait for the callback. - if (debug) { - log.info("Prevent writeNB when writeInterest is set"); - } - return 0; - } - - int done = 0; - done = ((SocketChannel) selectorData.channel).write(bb); - selectorData.lastWriteResult = done; - return done; - } catch(IOException ex) { - if (debug) { - log.info("writeNB error pos=" + bb.position() + " len=" + - (bb.limit() - bb.position()) + " " + selectorData + " " + - ex); - } - //ex.printStackTrace(); - selectorData.lastException = ex; - selectorData.close(); - throw ex; - // return -1; - } - } - - public int getPort(NioChannel sd, boolean remote) { - SocketChannel socketChannel = (SocketChannel) sd.channel; - - if (remote) { - return socketChannel.socket().getPort(); - } else { - return socketChannel.socket().getLocalPort(); - } - } - - public InetAddress getAddress(NioChannel sd, boolean remote) { - SocketChannel socketChannel = (SocketChannel) sd.channel; - - if (remote) { - return socketChannel.socket().getInetAddress(); - } else { - return socketChannel.socket().getLocalAddress(); - } - } - - /** - */ - public void connect(String host, int port, NioChannelCallback cstate) - throws IOException { - connect(new InetSocketAddress(host, port), cstate); - } - - - public void connect(SocketAddress sa, NioChannelCallback cstate) - throws IOException { - connect(sa, cstate, null); - } - - public void connect(SocketAddress sa, NioChannelCallback cstate, - NioChannel filter) - throws IOException { - - SocketChannel socketChannel = SocketChannel.open(); - socketChannel.configureBlocking(false); - NioChannel selectorData = new NioChannel(this); - selectorData.sel = this; - selectorData.callback = cstate; - selectorData.channel = socketChannel; - selectorData.channel = socketChannel; // no key - - socketChannel.connect(sa); - opened.incrementAndGet(); - - synchronized (connectAcceptInterest) { - connectAcceptInterest.add(selectorData); - } - selector.wakeup(); - } - - // TODO - public void configureSocket(ByteChannel ch, - boolean noDelay) throws IOException { - SocketChannel sockC = (SocketChannel) ch; - sockC.socket().setTcpNoDelay(noDelay); - } - - // TODO - public void setSocketOptions(NioChannel selectorData, - int linger, - boolean tcpNoDelay, - int socketTimeout) - throws IOException { - - SocketChannel socketChannel = - (SocketChannel) selectorData.channel; - Socket socket = socketChannel.socket(); - - if(linger >= 0 ) - socket.setSoLinger( true, linger); - if( tcpNoDelay ) - socket.setTcpNoDelay(tcpNoDelay); - if( socketTimeout > 0 ) - socket.setSoTimeout( socketTimeout ); - } - - /** - * Can be called from multiple threads or multiple times. - */ - public int close(NioChannel selectorData, Throwable exception) throws IOException { - synchronized (closeInterest) { - if (exception != null) { - selectorData.lastException = exception; - } - selectorData.readInterest = false; - if (isSelectorThread()) { - closeIOThread(selectorData, true); - return 0; - } - if (!selectorData.inClosed) { - closeInterest.add(selectorData); - } - } - selector.wakeup(); - return 0; - } - - - public void acceptor(NioChannelCallback cstate, - int port, - InetAddress inet, - int backlog, - int serverTimeout) - throws IOException - { - ServerSocketChannel ssc=ServerSocketChannel.open(); - ServerSocket serverSocket = ssc.socket(); - - SocketAddress sa = null; - - if (inet == null) { - sa = new InetSocketAddress( port ); - } else { - sa = new InetSocketAddress(inet, port); - } - if (backlog > 0) { - serverSocket.bind( sa , backlog); - } else { - serverSocket.bind(sa); - } - if( serverTimeout >= 0 ) { - serverSocket.setSoTimeout( serverTimeout ); - } - - - ssc.configureBlocking(false); - - NioChannel selectorData = new NioChannel(this); - selectorData.channel = ssc; // no key yet - selectorData.callback = cstate; - // key will be set in pending - - // TODO: add SSL here - - synchronized (connectAcceptInterest) { - connectAcceptInterest.add(selectorData); - } - selector.wakeup(); - } - - public void runInSelectorThread(Runnable cb) throws IOException { - if (isSelectorThread()) { - cb.run(); - } else { - synchronized (runnableInterest) { - runnableInterest.add(cb); - } - selector.wakeup(); - } - } - - /** - * Example config: - * - * www stream tcp wait USER PATH_TO_tomcatInetd.sh - * - * For a different port, you need to add it to /etc/services. - * - * 'wait' is critical - the common use of inetd is 'nowait' for - * tcp services, which doesn't make sense for java ( too slow startup - * time ). It may make sense in future with something like android VM. - * - * In 'wait' mode, inetd will pass the acceptor socket to java - so - * you can listen on port 80 and run as regular user with no special - * code and magic. - * If tomcat dies, inetd will get back the acceptor and on next connection - * restart tomcat. - * - * This also works with xinetd. It might work with Apple launchd. - * - * TODO: detect inactivity for N minutes, exist - to free resources. - */ - public void inetdAcceptor(NioChannelCallback cstate) throws IOException { - SelectorProvider sp=SelectorProvider.provider(); - - Channel ch=sp.inheritedChannel(); - if(ch!=null ) { - log.info("Inherited: " + ch.getClass().getName()); - // blocking mode - ServerSocketChannel ssc=(ServerSocketChannel)ch; - ssc.configureBlocking(false); - - NioChannel selectorData = new NioChannel(this); - selectorData.channel = ssc; - selectorData.callback = cstate; - - synchronized (connectAcceptInterest) { - connectAcceptInterest.add(selectorData); - } - selector.wakeup(); - } else { - log.severe("No inet socket "); - throw new IOException("Invalid inheritedChannel"); - } - } - - // -------------- Housekeeping ------------- - /** - * Same as APR connector - iterate over tasks, get - * smallest timeout - * @throws IOException - */ - void updateSleepTimeAndProcessTimeouts(long now) - throws IOException { - long min = Long.MAX_VALUE; - // TODO: test with large sets, maybe sort - synchronized (active) { - Iterator activeIt = active.iterator(); - - while(activeIt.hasNext()) { - NioChannel selectorData = activeIt.next(); - if (! selectorData.channel.isOpen()) { - if (debug) { - log.info("Found closed socket, removing " + - selectorData.channel); - } -// activeIt.remove(); -// selectorData.close(); - } - - long t = selectorData.nextTimeEvent; - if (t == 0) { - continue; - } - if (t < now) { - // Timeout - if (debug) { - log.info("Time event " + selectorData); - } - if (selectorData.timeEvent != null) { - selectorData.timeEvent.run(); - } - // TODO: make sure this is updated if it was selected - continue; - } - if (t < min) { - min = t; - } - } - } - long nextSleep = min - now; - if (nextSleep > maxSleep) { - sleepTime = maxSleep; - } else if (nextSleep < minSleep) { - sleepTime = minSleep; - } else { - sleepTime = nextSleep; - } - nextWakeup = now + sleepTime; - } - - /** - * Request a callback whenever data can be written. - * When the callback is invoked, the write interest is removed ( to avoid - * looping ). If the write() operation doesn't complete, you must call - * writeInterest - AND stop writing, some implementations will throw - * exception. write() will actually attempt to detect this and avoid the - * error. - * - * @param sc - */ - public void writeInterest(NioChannel selectorData) { - // TODO: suspended ? - - SelectionKey sk = (SelectionKey) selectorData.selKey; - if (!sk.isValid()) { - return; - } - selectorData.writeInterest = true; - int interest = sk.interestOps(); - if ((interest & SelectionKey.OP_WRITE) != 0) { - return; - } - if (Thread.currentThread() == selectorThread) { - interest = - interest | SelectionKey.OP_WRITE; - sk.interestOps(interest); - if (debug) { - log.info("Write interest " + selectorData + " i=" + interest); - } - return; - } - if (debug) { - log.info("Pending write interest " + selectorData); - } - synchronized (writeInterest) { - writeInterest.add(selectorData); - } - selector.wakeup(); - } - - - public void readInterest(NioChannel selectorData, boolean b) throws IOException { - if (Thread.currentThread() == selectorThread) { - selectorData.readInterest = b; - selThreadReadInterest(selectorData); - return; - } - SelectionKey sk = (SelectionKey) selectorData.selKey; - if (sk == null) { - close(selectorData, null); - return; - } - int interest = sk.interestOps(); - selectorData.readInterest = b; - if (b && (interest & SelectionKey.OP_READ) != 0) { - return; - } - if (!b && (interest & SelectionKey.OP_READ) == 0) { - return; - } - // Schedule the interest update. - synchronized (readInterest) { - readInterest.add(selectorData); - } - if (debug) { - log.info("Registering pending read interest"); - } - selector.wakeup(); - } - - - private void selThreadReadInterest(NioChannel selectorData) throws IOException { - SelectionKey sk = (SelectionKey) selectorData.selKey; - if (sk == null) { - if (selectorData.readInterest) { - if (debug) { - log.info("Register again for read interest"); - } - SocketChannel socketChannel = - (SocketChannel) selectorData.channel; - if (socketChannel.isOpen()) { - selectorData.sel = this; - selectorData.selKey = - socketChannel.register(selector, - SelectionKey.OP_READ, selectorData); - selectorData.channel = socketChannel; - } - } - return; - } - if (!sk.isValid()) { - return; - } - int interest = sk.interestOps(); - if (sk != null && sk.isValid()) { - if (selectorData.readInterest) { -// if ((interest | SelectionKey.OP_READ) != 0) { -// return; -// } - interest = - interest | SelectionKey.OP_READ; - } else { -// if ((interest | SelectionKey.OP_READ) == 0) { -// return; -// } - interest = - interest & ~SelectionKey.OP_READ; - } - if (interest == 0) { - if (!selectorData.inClosed) { - new Throwable().printStackTrace(); - log.warning("No interest(rd removed) " + selectorData); - } - // TODO: should we remove it ? It needs to be re-activated - // later. - sk.cancel(); //?? - selectorData.selKey = null; - } else { - sk.interestOps(interest); - } - if (debug) { - log.info(((selectorData.readInterest) - ? "RESUME read " : "SUSPEND read ") - + selectorData); - } - } - } - - - private void processPendingConnectAccept() throws IOException { - synchronized (connectAcceptInterest) { - Iterator ci = connectAcceptInterest.iterator(); - - while (ci.hasNext()) { - NioChannel selectorData = ci.next(); - - // Find host, port - initiate connection - try { - // Accept interest ? - if (selectorData.channel instanceof ServerSocketChannel) { - ServerSocketChannel socketChannel = - (ServerSocketChannel) selectorData.channel; - selectorData.sel = this; - selectorData.selKey = - socketChannel.register(selector, - SelectionKey.OP_ACCEPT, selectorData); - - selectorData.channel = socketChannel; - synchronized (active) { - active.add(selectorData); - } - if (debug) { - log.info("Pending acceptor added: " + selectorData); - } - } else { - SocketChannel socketChannel = - (SocketChannel) selectorData.channel; - selectorData.sel = this; - selectorData.selKey = - socketChannel.register(selector, - SelectionKey.OP_CONNECT, selectorData); - synchronized (active) { - active.add(selectorData); - } - if (debug) { - log.info("Pending connect added: " + selectorData); - } - } - } catch (Throwable e) { - log.log(Level.SEVERE, "error registering connect/accept", - e); - } - } - connectAcceptInterest.clear(); - } - } - - private void processPending() throws IOException { - if (closeInterest.size() > 0) { - synchronized (closeInterest) { - List closeList = new ArrayList(closeInterest); - closeInterest.clear(); - - Iterator ci = closeList.iterator(); - - while (ci.hasNext()) { - try { - NioChannel selectorData = ci.next(); - closeIOThread(selectorData, true); - } catch (Throwable t) { - t.printStackTrace(); - } - } - } - } - processPendingConnectAccept(); - processPendingReadWrite(); - - if (runnableInterest.size() > 0) { - synchronized (runnableInterest) { - Iterator ci = runnableInterest.iterator(); - while (ci.hasNext()) { - Runnable cstate = ci.next(); - try { - cstate.run(); - } catch (Throwable t) { - t.printStackTrace(); - } - if (debug) { - log.info("Run in selthread: " + cstate); - } - } - runnableInterest.clear(); - } - } - //processPendingUpdateCallback(); - } - - private void processPendingReadWrite() throws IOException { - // Update interest - if (readInterest.size() > 0) { - synchronized (readInterest) { - Iterator ci = readInterest.iterator(); - while (ci.hasNext()) { - NioChannel cstate = ci.next(); - selThreadReadInterest(cstate); - if (debug) { - log.info("Read interest added: " + cstate); - } - } - readInterest.clear(); - } - } - if (writeInterest.size() > 0) { - synchronized (writeInterest) { - Iterator ci = writeInterest.iterator(); - while (ci.hasNext()) { - NioChannel cstate = ci.next(); - // Fake callback - will update as side effect - handleDataWriteable(cstate); - if (debug) { - log.info("Write interest, calling dataWritable: " + cstate); - } - } - writeInterest.clear(); - } - } - } - - - protected boolean isSelectorThread() { - return Thread.currentThread() == selectorThread; - } - - public static boolean isSelectorThread(IOChannel ch) { - SocketIOChannel sc = (SocketIOChannel) ch.getFirst(); - return Thread.currentThread() == sc.ch.sel.selectorThread; - } - -} \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/SocketConnector.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/SocketConnector.java deleted file mode 100644 index 93bae2ad43c9..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/SocketConnector.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.Timer; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.io.NioChannel.NioChannelCallback; - -/** - * Class for handling sockets. It manages a pool of SelectorThreads, fully - * non-blocking. There is no caching or buffer management. SelectorChannel - * represents on connection. - * - * In the old types, the connector was socket-centric, and quite ugly. After - * many refactoring the buffers ( buckets and brigade ) and callbacks are - * used everywhere, and the sockets play a supporting role. - * - * TODO: discover if APR is available and use it, or fall back to NIO. - * - * @author Costin Manolache - */ -public class SocketConnector extends IOConnector { - static Logger log = Logger.getLogger(SocketConnector.class.getName()); - static boolean debug = false; - - // TODO: pool, balanced usage - // TODO: bind into OM or callback when created - - private NioThread selector; - - // For resolving DNS ( i.e. connect ) - Executor threadPool = Executors.newCachedThreadPool(); - - public SocketConnector() { - timer = new Timer(true); - } - - public SocketConnector(int port) { - timer = new Timer(true); - } - - /** - * This may be blocking - involves host resolution, connect. - * If the IP address is provided - it shouldn't block. - */ - @Override - public void connect(final String host, final int port, - final IOConnector.ConnectedCallback sc) throws IOException { - final SocketIOChannel ioch = new SocketIOChannel(this, null, host + ":" + port); - ioch.setConnectedCallback(sc); - threadPool.execute(new Runnable() { - @Override - public void run() { - try { - getSelector().connect(new InetSocketAddress(host, port), ioch, null); - } catch (Throwable e) { - e.printStackTrace(); - try { - sc.handleConnected(ioch); - ioch.close(); - } catch (Throwable e1) { - e1.printStackTrace(); - } - } - } - }); - } - - /** - * Create a new server socket, register the callback. - * If port == 0 it'll use the inherited channel, i.e. inetd mode. - * TODO: if port == -1, detect a free port. May block. - */ - public void acceptor(final IOConnector.ConnectedCallback sc, - final CharSequence address, Object extra) - throws IOException - { - final int port = Integer.parseInt(address.toString()); - NioChannelCallback acceptCb = new NioChannelCallback() { - @Override - public void handleClosed(NioChannel ch) throws IOException { - } - - @Override - public void handleConnected(NioChannel ch) throws IOException { - SocketIOChannel ioch = new SocketIOChannel(SocketConnector.this, - ch, ":" + port); - sc.handleConnected(ioch); - } - - @Override - public void handleReadable(NioChannel ch) throws IOException { - } - - @Override - public void handleWriteable(NioChannel ch) throws IOException { - } - }; - - if (port == -1) { - // TODO: find an unused port - } else if (port == 0) { - getSelector().inetdAcceptor(acceptCb); - } else { - getSelector().acceptor(acceptCb, port, null, 200, 20000); - } - } - - static int id = 0; - - public synchronized NioThread getSelector() { - if (selector == null) { - String name = "SelectorThread-" + id++; - selector = new NioThread(name, true); - } - - return selector; - } - - public void stop() { - getSelector().stop(); - } - - - // TODO: suspendAccept(boolean) - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/SocketIOChannel.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/SocketIOChannel.java deleted file mode 100644 index 88a964d9bc51..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/SocketIOChannel.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; -import java.net.InetAddress; -import java.nio.ByteBuffer; - -import org.apache.tomcat.lite.io.NioChannel.NioChannelCallback; - -/** - * Buffered socket channel - */ -public class SocketIOChannel extends IOChannel implements NioChannelCallback { - IOBuffer out; - IOBuffer in; - - NioChannel ch; - - SocketIOChannel(IOConnector connector, NioChannel data, - String target) - throws IOException { - this.connector = connector; - in = new IOBuffer(this); - out = new IOBuffer(this); - this.ch = data; - setOutBuffer(out); - setChannel(data); - this.target = target; - } - - void setChannel(NioChannel data) { - this.ch = data; - if (ch != null) { - ch.callback = this; - } - } - - - @Override - public IOBuffer getIn() { - return in; - } - - @Override - public IOBuffer getOut() { - return out; - } - - /** - * Both in and out open - */ - public boolean isOpen() { - if (ch == null) { - return false; - } - return ch.isOpen() && ch.channel != null && - ch.channel.isOpen() && !getIn().isAppendClosed() && - !getOut().isAppendClosed(); - } - - NioChannel getSelectorChannel() { - return ch; - } - - public String toString() { - return ch.toString(); - } - - public void setOutBuffer(IOBuffer out) { - this.out = out; - } - - ByteBuffer flushBuffer; - - /** - * Send as much as possible. - * - * Adjust write interest so we can send more when possible. - */ - private void flush(NioChannel ch) throws IOException { - synchronized (this) { - if (ch == null) { - if (out.isClosedAndEmpty()) { - return; - } - throw new IOException("flush() with closed socket"); - } - while (true) { - if (out.isClosedAndEmpty()) { - ch.shutdownOutput(); - break; - } - BBucket bb = out.peekFirst(); - if (bb == null) { - break; - } - flushBuffer = getReadableBuffer(flushBuffer, bb); - int before = flushBuffer.position(); - - int done = 0; - while (flushBuffer.remaining() > 0) { - try { - done = ch.write(flushBuffer); - } catch (IOException ex) { - // can't write - was closed ! - done = -1; - } - - if (done < 0) { - ch.close(); - out.close(); - handleFlushed(this); - //throw new IOException("Closed while writting "); - return; - } - if (done == 0) { - bb.position(flushBuffer.position()); - ch.writeInterest(); // it is cleared on next dataWriteable - return; - } - } - releaseReadableBuffer(flushBuffer, bb); - } - handleFlushed(this); - - } - } - - /** - * Data available for read, called from IO thread. - * You MUST read all data ( i.e. until read() returns 0). - * - * OP_READ remain active - call readInterest(false) to disable - - * for example to suspend reading if buffer is full. - */ - public void handleReceived(IOChannel net) throws IOException { - // All data will go to currentReceiveBuffer, until it's full. - // Then a new buffer will be allocated/pooled. - - // When we fill the buffers or finish this round of reading - - // we place the Buckets in the queue, as 'readable' buffers. - boolean newData = false; - try { - int read = 0; - synchronized(in) { - // data between 0 and position - int total = 0; - while (true) { - if (in.isAppendClosed()) { // someone closed me ? - ch.inputClosed(); // remove read interest. - // if outClosed - close completely - newData = true; - break; - } - - ByteBuffer bb = in.getWriteBuffer(); - read = ch.read(bb); - in.releaseWriteBuffer(read); - - if (in == null) { // Detached. - break; - } - - if (read < 0) { - // mark the in buffer as closed - in.close(); - ch.inputClosed(); - newData = true; - break; - } - if (read == 0) { - break; - } - total += read; - newData = true; - } - } // sync - if (newData) { - super.sendHandleReceivedCallback(); - } - - } catch (Throwable t) { - close(); - if (t instanceof IOException) { - throw (IOException) t; - } else { - throw new IOException(t.toString()); - } - } - } - - public static final ByteBuffer getReadableBuffer(ByteBuffer orig, BBucket bucket) { - if (orig == null || orig.array() != bucket.array()) { - orig = ByteBuffer.wrap(bucket.array()); - } - orig.position(bucket.position()); - orig.limit(bucket.limit()); - return orig; - } - - public static final void releaseReadableBuffer(ByteBuffer bb, BBucket bucket) { - bucket.position(bb.position()); - } - - - public void readInterest(boolean b) throws IOException { - ch.readInterest(b); - } - - public InetAddress getAddress(boolean remote) { - return ch.getAddress(remote); - } - - @Override - public Object getAttribute(String name) { - if (ATT_REMOTE_HOSTNAME.equals(name)) { - return getAddress(true).getHostName(); - } else if (ATT_LOCAL_HOSTNAME.equals(name)) { - return getAddress(false).getHostName(); - } else if (ATT_REMOTE_ADDRESS.equals(name)) { - return getAddress(true).getHostAddress(); - } else if (ATT_LOCAL_ADDRESS.equals(name)) { - return getAddress(false).getHostAddress(); - } else if (ATT_REMOTE_PORT.equals(name)) { - return ch.getPort(true); - } else if (ATT_LOCAL_PORT.equals(name)) { - return ch.getPort(false); - } - return null; - } - - public void startSending() throws IOException { - flush(ch); - } - - public void shutdownOutput() throws IOException { - getOut().close(); - if (ch != null) { - startSending(); - } - } - - @Override - public void handleClosed(NioChannel ch) throws IOException { - lastException = ch.lastException; - closed(); // our callback. - } - - public void closed() throws IOException { - getIn().close(); - sendHandleReceivedCallback(); - //super.closed(); - } - - @Override - public void handleConnected(NioChannel ch) throws IOException { - setChannel(ch); - connectedCallback.handleConnected(this); - } - - @Override - public void handleReadable(NioChannel ch) throws IOException { - handleReceived(this); - } - - @Override - public void handleWriteable(NioChannel ch) throws IOException { - flush(ch); - } -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/SslProvider.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/SslProvider.java deleted file mode 100644 index 94e86ae4a0f3..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/SslProvider.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; - -public interface SslProvider { - - public static final String ATT_SSL_CERT = "SslCert"; - public static final String ATT_SSL_CIPHER = "SslCipher"; - public static final String ATT_SSL_KEY_SIZE = "SslKeySize"; - public static final String ATT_SSL_SESSION_ID = "SslSessionId"; - - /** - * Wrap channel with SSL. - * - * The result will start a handshake - */ - public IOChannel channel(IOChannel net, String host, int port) - throws IOException; - - public IOChannel serverChannel(IOChannel net) throws IOException; - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/UrlEncoding.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/UrlEncoding.java deleted file mode 100644 index 3266491365f4..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/UrlEncoding.java +++ /dev/null @@ -1,215 +0,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.lite.io; - -import java.io.CharConversionException; -import java.io.IOException; -import java.nio.charset.CharsetEncoder; -import java.util.BitSet; - - -/** - * Support for %xx URL encoding. - * - * @author Costin Manolache - */ -public final class UrlEncoding { - - protected static final boolean ALLOW_ENCODED_SLASH = - Boolean.valueOf( - System.getProperty( - "org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", - "false")).booleanValue(); - - public UrlEncoding() { - } - - // Utilities for URL encoding. - static BitSet SAFE_CHARS_URL = new BitSet(128); - static BitSet SAFE_CHARS = new BitSet(128); - BBuffer tmpBuffer = BBuffer.allocate(1024); - CBuffer tmpCharBuffer = CBuffer.newInstance(); - - public void urlEncode(CBuffer url, CBuffer encoded, IOWriter enc) { - tmpBuffer.recycle(); - urlEncode(url, tmpBuffer, encoded, enc.getEncoder("UTF-8"), - SAFE_CHARS_URL, true, enc); - } - - public void urlEncode(String url, CBuffer encoded, IOWriter enc) { - tmpCharBuffer.recycle(); - tmpCharBuffer.append(url); - urlEncode(tmpCharBuffer, encoded, enc); - } - - /** Only works for UTF-8 or charsets preserving ascii. - * - * @param url - * @param tmpBuffer - * @param encoded - * @param utf8Enc - * @param safeChars - */ - public void urlEncode(CBuffer url, - BBuffer tmpBuffer, - CBuffer encoded, - CharsetEncoder utf8Enc, - BitSet safeChars, boolean last, IOWriter enc) { - // tomcat charset-encoded each character first. I don't think - // this is needed. - - // TODO: space to + - enc.encodeAll(url, tmpBuffer, utf8Enc, last); - byte[] array = tmpBuffer.array(); - for (int i = tmpBuffer.position(); i < tmpBuffer.limit(); i++) { - int c = array[i]; - if (safeChars.get(c)) { - encoded.append((char) c); - } else { - encoded.append('%'); - char ch = Character.forDigit((c >> 4) & 0xF, 16); - encoded.append(ch); - ch = Character.forDigit(c & 0xF, 16); - encoded.append(ch); - } - } - } - - static { - initSafeChars(SAFE_CHARS); - initSafeChars(SAFE_CHARS_URL); - SAFE_CHARS_URL.set('/'); - } - - private static void initSafeChars(BitSet safeChars) { - int i; - for (i = 'a'; i <= 'z'; i++) { - safeChars.set(i); - } - for (i = 'A'; i <= 'Z'; i++) { - safeChars.set(i); - } - for (i = '0'; i <= '9'; i++) { - safeChars.set(i); - } - // safe - safeChars.set('-'); - safeChars.set('_'); - safeChars.set('.'); - - // Dangerous: someone may treat this as " " - // RFC1738 does allow it, it's not reserved - // safeChars.set('+'); - // extra - safeChars.set('*'); - // tomcat has them - not sure if this is correct - safeChars.set('$'); // ? - safeChars.set('!'); // ? - safeChars.set('\''); // ? - safeChars.set('('); // ? - safeChars.set(')'); // ? - safeChars.set(','); // ? - } - - public void urlDecode(BBuffer bb, CBuffer dest, boolean q, - IOReader charDec) throws IOException { - // Replace %xx - tmpBuffer.append(bb); - urlDecode(tmpBuffer, q); - charDec.decodeAll(bb, dest); - } - - - public void urlDecode(BBuffer bb, CBuffer dest, - IOReader charDec) throws IOException { - // Replace %xx - tmpBuffer.append(bb); - urlDecode(tmpBuffer, true); - charDec.decodeAll(bb, dest); - } - - - /** - * URLDecode, will modify the source. This is only at byte level - - * it needs conversion to chars using the right charset. - * - * @param query Converts '+' to ' ' and allow '/' - */ - public void urlDecode(BBuffer mb, boolean query) throws IOException { - int start = mb.getOffset(); - byte buff[] = mb.array(); - int end = mb.getEnd(); - - int idx = BBuffer.indexOf(buff, start, end, '%'); - int idx2 = -1; - if (query) - idx2 = BBuffer.indexOf(buff, start, end, '+'); - if (idx < 0 && idx2 < 0) { - return; - } - - // idx will be the smallest positive inxes ( first % or + ) - if (idx2 >= 0 && idx2 < idx) - idx = idx2; - if (idx < 0) - idx = idx2; - - //boolean noSlash = !query; - - for (int j = idx; j < end; j++, idx++) { - if (buff[j] == '+' && query) { - buff[idx] = (byte) ' '; - } else if (buff[j] != '%') { - buff[idx] = buff[j]; - } else { - // read next 2 digits - if (j + 2 >= end) { - throw new CharConversionException("EOF"); - } - byte b1 = buff[j + 1]; - byte b2 = buff[j + 2]; - if (!isHexDigit(b1) || !isHexDigit(b2)) - throw new CharConversionException("isHexDigit"); - - j += 2; - int res = x2c(b1, b2); -// if (noSlash && (res == '/')) { -// throw new CharConversionException("noSlash " + mb); -// } - buff[idx] = (byte) res; - } - } - - mb.setEnd(idx); - - return; - } - - - private static boolean isHexDigit(int c) { - return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); - } - - private static int x2c(byte b1, byte b2) { - int digit = (b1 >= 'A') ? ((b1 & 0xDF) - 'A') + 10 : (b1 - '0'); - digit *= 16; - digit += (b2 >= 'A') ? ((b2 & 0xDF) - 'A') + 10 : (b2 - '0'); - return digit; - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/WrappedException.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/WrappedException.java deleted file mode 100644 index 3d8a281a767c..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/WrappedException.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; - -/** - * For specific exceptions - also has cause ( good if compiling against - * JDK1.5 ) - * - * @author Costin Manolache - */ -public class WrappedException extends IOException { - - public WrappedException() { - super(); - } - - public WrappedException(String message) { - super(message); - } - - public WrappedException(String message, Throwable cause) { - super(message); - initCause(cause); - } - - public WrappedException(Throwable cause) { - super(""); - initCause(cause); - } - - - public static class ClientAbortException extends WrappedException { - public ClientAbortException(Throwable throwable) { - super(null, throwable); - } - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/jsse/JsseSslProvider.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/jsse/JsseSslProvider.java deleted file mode 100644 index 56c80b1387b9..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/jsse/JsseSslProvider.java +++ /dev/null @@ -1,466 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io.jsse; - -import java.io.ByteArrayInputStream; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.Socket; -import java.security.Key; -import java.security.KeyFactory; -import java.security.KeyManagementException; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.Principal; -import java.security.PrivateKey; -import java.security.UnrecoverableKeyException; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.RSAKeyGenParameterSpec; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLPeerUnverifiedException; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509ExtendedKeyManager; -import javax.net.ssl.X509TrustManager; - -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.DumpChannel; -import org.apache.tomcat.lite.io.IOChannel; -import org.apache.tomcat.lite.io.IOConnector; -import org.apache.tomcat.lite.io.SocketConnector; -import org.apache.tomcat.lite.io.SslProvider; -import org.apache.tomcat.lite.io.WrappedException; -import org.apache.tomcat.lite.io.IOConnector.ConnectedCallback; - - -public class JsseSslProvider implements SslProvider { - - /** - * TODO: option to require validation. - * TODO: remember cert signature. This is needed to support self-signed - * certs, like those used by the test. - * - */ - public static class BasicTrustManager implements X509TrustManager { - - private X509Certificate[] chain; - - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - this.chain = chain; - } - - public void checkServerTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - this.chain = chain; - } - - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - } - - public static TrustManager[] trustAllCerts = new TrustManager[] { - new BasicTrustManager() }; - - static String[] enabledCiphers; - - static final boolean debug = false; - - IOConnector net; - private KeyManager[] keyManager; - SSLContext sslCtx; - boolean server; - private TrustManager[] trustManagers; - - public AtomicInteger handshakeCount = new AtomicInteger(); - public AtomicInteger handshakeOk = new AtomicInteger(); - public AtomicInteger handshakeErr = new AtomicInteger(); - public AtomicInteger handshakeTime = new AtomicInteger(); - - Executor handshakeExecutor = Executors.newCachedThreadPool(); - static int id = 0; - - public JsseSslProvider() { - } - - public static void setEnabledCiphers(String[] enabled) { - enabledCiphers = enabled; - } - - public void start() { - - } - - SSLContext getSSLContext() { - if (sslCtx == null) { - try { - sslCtx = SSLContext.getInstance("TLS"); - if (trustManagers == null) { - trustManagers = - new TrustManager[] {new BasicTrustManager()}; - - } - sslCtx.init(keyManager, trustManagers, null); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } catch (KeyManagementException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - return sslCtx; - } - - public IOConnector getNet() { - if (net == null) { - getSSLContext(); - net = new SocketConnector(); - } - return net; - } - - @Override - public IOChannel channel(IOChannel net, String host, int port) throws IOException { - if (debug) { - net = DumpChannel.wrap("S-ENC-" + id, net); - } - SslChannel ch = new SslChannel() - .setTarget(host, port) - .setSslContext(getSSLContext()) - .setSslProvider(this); - net.setHead(ch); - return ch; - } - - @Override - public SslChannel serverChannel(IOChannel net) throws IOException { - SslChannel ch = new SslChannel() - .setSslContext(getSSLContext()) - .setSslProvider(this).withServer(); - ch.setSink(net); - return ch; - } - - public void acceptor(final ConnectedCallback sc, CharSequence port, Object extra) - throws IOException { - getNet().acceptor(new ConnectedCallback() { - @Override - public void handleConnected(IOChannel ch) throws IOException { - IOChannel first = ch; - if (debug) { - first = DumpChannel.wrap("S-ENC-" + id, ch); - } - - IOChannel sslch = serverChannel(first); - sslch.setSink(first); - first.setHead(sslch); - - if (debug) { - sslch = DumpChannel.wrap("S-CLR-" + id, sslch); - id++; - } - - sc.handleConnected(sslch); - } - }, port, extra); - } - - public void connect(final String host, final int port, final ConnectedCallback sc) - throws IOException { - getNet().connect(host, port, new ConnectedCallback() { - - @Override - public void handleConnected(IOChannel ch) throws IOException { - IOChannel first = ch; - if (debug) { - first = DumpChannel.wrap("ENC-" + id, first); - } - - IOChannel sslch = channel(first, host, port); -// first.setHead(sslch); - - if (debug) { - sslch = DumpChannel.wrap("CLR-" + id, sslch); - id++; - } - - sc.handleConnected(sslch); - } - - }); - } - - public JsseSslProvider withKeyManager(KeyManager[] kms) { - this.keyManager = kms; - return this; - } - - public JsseSslProvider setKeystoreFile(String file, String pass) throws IOException { - return setKeystore(new FileInputStream(file), pass); - } - - public JsseSslProvider setKeystoreResource(String res, String pass) throws IOException { - return setKeystore(this.getClass().getClassLoader().getResourceAsStream(res), - pass); - } - - public JsseSslProvider setKeystore(InputStream file, String pass) { - char[] passphrase = pass.toCharArray(); - KeyStore ks; - try { - String type = KeyStore.getDefaultType(); - System.err.println("Keystore: " + type); - // Java: JKS - // Android: BKS - ks = KeyStore.getInstance(type); - ks.load(file, passphrase); - KeyManagerFactory kmf = - KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, passphrase); - - TrustManagerFactory tmf = - TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(ks); - - keyManager = kmf.getKeyManagers(); - trustManagers = tmf.getTrustManagers(); - } catch (KeyStoreException e) { - // No JKS keystore ? - // TODO Auto-generated catch block - }catch (NoSuchAlgorithmException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (FileNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (UnrecoverableKeyException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - return this; - } - - public JsseSslProvider setKeys(X509Certificate cert, PrivateKey privKey) { - keyManager = new KeyManager[] { - new TestKeyManager(cert, privKey) - }; - return this; - } - - public JsseSslProvider setKeyFiles(String certPem, String keyFile) - throws IOException { - - - return this; - } - - public JsseSslProvider setKeyRes(String certPem, String keyFile) - throws IOException { - setKeys(this.getClass().getClassLoader().getResourceAsStream(certPem), - this.getClass().getClassLoader().getResourceAsStream(keyFile)); - return this; - } - - private void setKeys(InputStream certPem, - InputStream keyDer) throws IOException { - BBuffer keyB = BBuffer.allocate(2048); - keyB.readAll(keyDer); - byte[] key = new byte[keyB.remaining()]; - keyB.getByteBuffer().get(key); - - setKeys(certPem, key); - } - - public JsseSslProvider setKeys(String certPem, byte[] keyBytes) throws IOException{ - InputStream is = new ByteArrayInputStream(certPem.getBytes()); - return setKeys(is, keyBytes); - } - - /** - * Initialize using a PEM certificate and key bytes. - * ( TODO: base64 dep to set the key as PEM ) - * - * openssl genrsa 1024 > host.key - * openssl pkcs8 -topk8 -nocrypt -in host.key -inform PEM - * -out host.der -outform DER - * openssl req -new -x509 -nodes -sha1 -days 365 -key host.key > host.cert - * - */ - public JsseSslProvider setKeys(InputStream certPem, byte[] keyBytes) throws IOException{ - // convert key - try { - KeyFactory kf = KeyFactory.getInstance("RSA"); - PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec(keyBytes); - PrivateKey priv = kf.generatePrivate (keysp); - - // Convert cert pem to certificate - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - final X509Certificate cert = (X509Certificate) cf.generateCertificate(certPem); - - setKeys(cert, priv); - } catch (Throwable t) { - throw new WrappedException(t); - } - return this; - } - - public class TestKeyManager extends X509ExtendedKeyManager { - X509Certificate cert; - PrivateKey privKey; - - public TestKeyManager(X509Certificate cert2, PrivateKey privKey2) { - cert = cert2; - privKey = privKey2; - } - - public String chooseEngineClientAlias(String[] keyType, - java.security.Principal[] issuers, javax.net.ssl.SSLEngine engine) { - return "client"; - } - - public String chooseEngineServerAlias(String keyType, - java.security.Principal[] issuers, javax.net.ssl.SSLEngine engine) { - return "server"; - } - - public String chooseClientAlias(String[] keyType, - Principal[] issuers, Socket socket) { - return "client"; - } - - public String chooseServerAlias(String keyType, - Principal[] issuers, Socket socket) { - return "server"; - } - - public X509Certificate[] getCertificateChain(String alias) { - return new X509Certificate[] {cert}; - } - - public String[] getClientAliases(String keyType, Principal[] issuers) { - return null; - } - - public PrivateKey getPrivateKey(String alias) { - - return privKey; - } - - public String[] getServerAliases(String keyType, Principal[] issuers) { - return null; - } - } - - // TODO: add a mode that trust a defined list of certs, like SSH - - /** - * Make URLConnection accept all certificates. - * Use only for testing ! - */ - public static void testModeURLConnection() { - try { - SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(null, JsseSslProvider.trustAllCerts, null); - - javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory( - sc.getSocketFactory()); - javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier( - new HostnameVerifier() { - - @Override - public boolean verify(String hostname, - SSLSession session) { - try { - Certificate[] certs = session.getPeerCertificates(); - // TODO... - // see org/apache/http/conn/ssl/AbstractVerifier - } catch (SSLPeerUnverifiedException e) { - e.printStackTrace(); - } - return true; - } - - }); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - // Utilities - public static byte[] getPrivateKeyFromStore(String file, String pass) - throws Exception { - KeyStore store = KeyStore.getInstance("JKS"); - store.load(new FileInputStream(file), pass.toCharArray()); - Key key = store.getKey("tomcat", "changeit".toCharArray()); - PrivateKey pk = (PrivateKey) key; - byte[] encoded = pk.getEncoded(); - return encoded; - } - - public static byte[] getCertificateFromStore(String file, String pass) - throws Exception { - KeyStore store = KeyStore.getInstance("JKS"); - store.load(new FileInputStream(file), pass.toCharArray()); - Certificate certificate = store.getCertificate("tomcat"); - - return certificate.getEncoded(); - } - - public static KeyPair generateRsaOrDsa(boolean rsa) throws Exception { - if (rsa) { - KeyPairGenerator keyPairGen = - KeyPairGenerator.getInstance("RSA"); - keyPairGen.initialize(1024); - - RSAKeyGenParameterSpec keySpec = new RSAKeyGenParameterSpec(1024, - RSAKeyGenParameterSpec.F0); - keyPairGen.initialize(keySpec); - - KeyPair rsaKeyPair = keyPairGen.generateKeyPair(); - - return rsaKeyPair; - } else { - KeyPairGenerator keyPairGen = - KeyPairGenerator.getInstance("DSA"); - keyPairGen.initialize(1024); - - KeyPair pair = keyPairGen.generateKeyPair(); - - return pair; - } - } - - /** - * I know 2 ways to generate certs: - * - keytool - * - openssl req -x509 -nodes -days 365 \ - * -newkey rsa:1024 -keyout mycert.pem -out mycert.pem - * openssl s_server -accept 9443 -cert mycert.pem -debug -msg -state -www - */ -} \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/jsse/SslChannel.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/jsse/SslChannel.java deleted file mode 100644 index df4425b313ef..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/jsse/SslChannel.java +++ /dev/null @@ -1,636 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io.jsse; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.security.GeneralSecurityException; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLEngineResult; -import javax.net.ssl.SSLException; -import javax.net.ssl.SSLPeerUnverifiedException; -import javax.net.ssl.SSLSession; -import javax.net.ssl.SSLEngineResult.HandshakeStatus; -import javax.net.ssl.SSLEngineResult.Status; - -import org.apache.tomcat.lite.io.IOBuffer; -import org.apache.tomcat.lite.io.IOChannel; -import org.apache.tomcat.lite.io.SslProvider; - -class SslChannel extends IOChannel implements Runnable { - - static Logger log = Logger.getLogger("SSL"); - - static ByteBuffer EMPTY = ByteBuffer.allocate(0); - - - SSLEngine sslEngine; - // Last result - SSLEngineResult unwrapR; - - boolean handshakeDone = false; - boolean handshakeInProgress = false; - Object handshakeSync = new Object(); - boolean flushing = false; - - IOBuffer in = new IOBuffer(this); - IOBuffer out = new IOBuffer(this); - - long handshakeTimeout = 20000; - // Used for session reuse - String host; - int port; - - ByteBuffer myAppOutData; - ByteBuffer myNetOutData; - private static boolean debugWrap = false; - - /* - * Special: SSL works in packet mode, and we may receive an incomplete - * packet. This should be in compacted write mode (i.e. data from 0 to pos, - * limit at end ) - */ - ByteBuffer myNetInData; - ByteBuffer myAppInData; - boolean client = true; - - private SSLContext sslCtx; - - private boolean closeHandshake = false; - - public SslChannel() { - } - - /** - * Setting the host/port enables clients to reuse SSL session - - * less traffic and encryption overhead at startup, assuming the - * server caches the session ( i.e. single server or distributed cache ). - * - * SSL ticket extension is another possibility. - */ - public SslChannel setTarget(String host, int port) { - this.host = host; - this.port = port; - return this; - } - - private synchronized void initSsl() throws GeneralSecurityException { - if (sslEngine != null) { - log.severe("Double initSsl"); - return; - } - - if (client) { - if (port > 0) { - sslEngine = sslCtx.createSSLEngine(host, port); - } else { - sslEngine = sslCtx.createSSLEngine(); - } - sslEngine.setUseClientMode(client); - } else { - sslEngine = sslCtx.createSSLEngine(); - sslEngine.setUseClientMode(false); - - } - - // Some VMs have broken ciphers. - if (JsseSslProvider.enabledCiphers != null) { - sslEngine.setEnabledCipherSuites(JsseSslProvider.enabledCiphers); - } - - SSLSession session = sslEngine.getSession(); - - int packetBuffer = session.getPacketBufferSize(); - myAppOutData = ByteBuffer.allocate(session.getApplicationBufferSize()); - myNetOutData = ByteBuffer.allocate(packetBuffer); - myAppInData = ByteBuffer.allocate(session.getApplicationBufferSize()); - myNetInData = ByteBuffer.allocate(packetBuffer); - myNetInData.flip(); - myNetOutData.flip(); - myAppInData.flip(); - myAppOutData.flip(); - } - - public SslChannel withServer() { - client = false; - return this; - } - - - @Override - public synchronized void setSink(IOChannel net) throws IOException { - try { - if (sslEngine == null) { - initSsl(); - } - super.setSink(net); - } catch (GeneralSecurityException e) { - log.log(Level.SEVERE, "Error initializing ", e); - } - } - - @Override - public IOBuffer getIn() { - return in; - } - - @Override - public IOBuffer getOut() { - return out; - } - - /** - * Typically called when a dataReceived callback is passed up. - * It's up to the higher layer to decide if it can handle more data - * and disable read interest and manage its buffers. - * - * We have to use one buffer. - * @throws IOException - */ - public int processInput(IOBuffer netIn, IOBuffer appIn) throws IOException { - if (log.isLoggable(Level.FINEST)) { - log.info("JSSE: processInput " + handshakeInProgress + " " + netIn.getBufferCount()); - } - synchronized(handshakeSync) { - if (!handshakeDone && !handshakeInProgress) { - handshakeInProgress = true; - handleHandshking(); - return 0; - } - if (handshakeInProgress) { - return 0; // leave it there - } - } - return processRealInput(netIn, appIn); - } - - private synchronized int processRealInput(IOBuffer netIn, IOBuffer appIn) throws IOException { - int rd = 0; - boolean needsMore = true; - boolean notEnough = false; - - while (needsMore) { - if (netIn.isClosedAndEmpty()) { - appIn.close(); - sendHandleReceivedCallback(); - return -1; - } - myNetInData.compact(); - int rdNow; - try { - rdNow = netIn.read(myNetInData); - } finally { - myNetInData.flip(); - } - if (rdNow == 0 && (myNetInData.remaining() == 0 || - notEnough)) { - return rd; - } - if (rdNow == -1) { - appIn.close(); - sendHandleReceivedCallback(); - return rd; - } - - notEnough = true; // next read of 0 - while (myNetInData.remaining() > 0) { - myAppInData.compact(); - try { - unwrapR = sslEngine.unwrap(myNetInData, myAppInData); - } catch (SSLException ex) { - log.warning("Read error: " + ex); - close(); - return -1; - } finally { - myAppInData.flip(); - } - if (myAppInData.remaining() > 0) { - in.write(myAppInData); // all will be written - } - if (unwrapR.getStatus() == Status.CLOSED) { - in.close(); - if (unwrapR.getHandshakeStatus() == HandshakeStatus.NEED_WRAP) { - // TODO: send/receive one more packet ( handshake mode ? ) - synchronized(handshakeSync) { - handshakeInProgress = true; - closeHandshake = true; - } - handleHandshking(); - - startSending(); - } - break; - } - - if (unwrapR.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { - tasks(); - } - if (unwrapR.getStatus() == Status.BUFFER_OVERFLOW) { - log.severe("Unhandled overflow " + unwrapR); - break; - } - if (unwrapR.getStatus() == Status.BUFFER_UNDERFLOW) { - // harmless - //log.severe("Unhandled underflow " + unwrapR); - break; - } - } - sendHandleReceivedCallback(); - - - } - return rd; - } - - protected SSLEngineResult.HandshakeStatus tasks() { - Runnable r = null; - while ( (r = sslEngine.getDelegatedTask()) != null) { - r.run(); - } - return sslEngine.getHandshakeStatus(); - } - - public void startSending() throws IOException { - - flushing = true; - boolean needHandshake = false; - synchronized(handshakeSync) { - if (handshakeInProgress) { - return; // don't bother me. - } - if (!handshakeDone) { - handshakeInProgress = true; - needHandshake = true; - } - } - if (needHandshake) { - handleHandshking(); - return; // can't write yet. - } - - startRealSending(); - } - - public void close() throws IOException { - if (net.getOut().isAppendClosed()) { - return; - } - sslEngine.closeOutbound(); // mark as closed - synchronized(myNetOutData) { - myNetOutData.compact(); - - SSLEngineResult wrap; - try { - wrap = sslEngine.wrap(EMPTY, myNetOutData); - if (wrap.getStatus() != Status.CLOSED) { - log.warning("Unexpected close status " + wrap); - } - } catch (Throwable t ) { - log.info("Error wrapping " + myNetOutData); - } finally { - myNetOutData.flip(); - } - if (myNetOutData.remaining() > 0) { - net.getOut().write(myNetOutData); - } - } - // TODO: timer to close socket if we don't get - // clean close handshake - super.close(); - } - - private Object sendLock = new Object(); - - private JsseSslProvider sslProvider; - - private void startRealSending() throws IOException { - // Only one thread at a time - synchronized (sendLock) { - while (true) { - - myAppOutData.compact(); - int rd; - try { - rd = out.read(myAppOutData); - } finally { - myAppOutData.flip(); - } - if (rd == 0) { - break; - } - if (rd < 0) { - close(); - break; - } - - SSLEngineResult wrap; - synchronized(myNetOutData) { - myNetOutData.compact(); - try { - wrap = sslEngine.wrap(myAppOutData, - myNetOutData); - } finally { - myNetOutData.flip(); - } - net.getOut().write(myNetOutData); - } - if (wrap != null) { - switch (wrap.getStatus()) { - case BUFFER_UNDERFLOW: { - break; - } - case OK: { - break; - } - case BUFFER_OVERFLOW: { - throw new IOException("Overflow"); - } - } - } - } - } - - net.startSending(); - } - - - // SSL handshake require slow tasks - that will need to be executed in a - // thread anyways. Better to keep it simple ( the code is very complex ) - - // and do the initial handshake in a thread, not in the IO thread. - // We'll need to unregister and register again from the selector. - private void handleHandshking() { - if (log.isLoggable(Level.FINEST)) { - log.info("Starting handshake"); - } - synchronized(handshakeSync) { - handshakeInProgress = true; - } - - sslProvider.handshakeExecutor.execute(this); - } - - private void endHandshake() throws IOException { - if (log.isLoggable(Level.FINEST)) { - log.info("Handshake done " + net.getIn().available()); - } - synchronized(handshakeSync) { - handshakeDone = true; - handshakeInProgress = false; - } - if (flushing) { - flushing = false; - startSending(); - } - if (myNetInData.remaining() > 0 || net.getIn().available() > 0) { - // Last SSL packet also includes data. - handleReceived(net); - } - } - - /** - * Actual handshake magic, in background thread. - */ - public void run() { - try { - boolean initial = true; - SSLEngineResult wrap = null; - - HandshakeStatus hstatus = sslEngine.getHandshakeStatus(); - if (!closeHandshake && - (hstatus == HandshakeStatus.NOT_HANDSHAKING || initial)) { - sslEngine.beginHandshake(); - hstatus = sslEngine.getHandshakeStatus(); - } - - long t0 = System.currentTimeMillis(); - - while (hstatus != HandshakeStatus.NOT_HANDSHAKING - && hstatus != HandshakeStatus.FINISHED - && !net.getIn().isAppendClosed()) { - if (System.currentTimeMillis() - t0 > handshakeTimeout) { - throw new TimeoutException(); - } - if (wrap != null && wrap.getStatus() == Status.CLOSED) { - break; - } - if (log.isLoggable(Level.FINEST)) { - log.info("-->doHandshake() loop: status = " + hstatus + " " + - sslEngine.getHandshakeStatus()); - } - - if (hstatus == HandshakeStatus.NEED_WRAP) { - // || initial - for client - initial = false; - synchronized(myNetOutData) { - while (hstatus == HandshakeStatus.NEED_WRAP) { - myNetOutData.compact(); - try { - wrap = sslEngine.wrap(myAppOutData, myNetOutData); - } catch (Throwable t) { - log.log(Level.SEVERE, "Wrap error", t); - close(); - return; - } finally { - myNetOutData.flip(); - } - if (myNetOutData.remaining() > 0) { - net.getOut().write(myNetOutData); - } - hstatus = wrap.getHandshakeStatus(); - } - } - net.startSending(); - } else if (hstatus == HandshakeStatus.NEED_UNWRAP) { - while (hstatus == HandshakeStatus.NEED_UNWRAP) { - // If we have few remaining bytes - process them - if (myNetInData.remaining() > 0) { - myAppInData.clear(); - if (debugWrap) { - log.info("UNWRAP: rem=" + myNetInData.remaining()); - } - wrap = sslEngine.unwrap(myNetInData, myAppInData); - hstatus = wrap.getHandshakeStatus(); - myAppInData.flip(); - if (myAppInData.remaining() > 0) { - log.severe("Unexpected data after unwrap"); - } - if (wrap.getStatus() == Status.CLOSED) { - break; - } - } - // Still need unwrap - if (wrap == null - || wrap.getStatus() == Status.BUFFER_UNDERFLOW - || (hstatus == HandshakeStatus.NEED_UNWRAP && myNetInData.remaining() == 0)) { - myNetInData.compact(); - // non-blocking - int rd; - try { - rd = net.getIn().read(myNetInData); - if (debugWrap) { - log.info("Read: " + rd); - } - } finally { - myNetInData.flip(); - } - if (rd == 0) { - if (debugWrap) { - log.info("Wait: " + handshakeTimeout); - } - net.getIn().waitData(handshakeTimeout); - rd = net.getIn().read(myNetInData); - if (debugWrap) { - log.info("Read after wait: " + rd); - } - } - if (rd < 0) { - // in closed - break; - } - } - if (log.isLoggable(Level.FINEST)) { - log.info("Unwrap chunk done " + hstatus + " " + wrap - + " " + sslEngine.getHandshakeStatus()); - } - - } - - // rd may have some input bytes. - } else if (hstatus == HandshakeStatus.NEED_TASK) { - long t0task = System.currentTimeMillis(); - Runnable r; - while ((r = sslEngine.getDelegatedTask()) != null) { - r.run(); - } - long t1task = System.currentTimeMillis(); - hstatus = sslEngine.getHandshakeStatus(); - if (log.isLoggable(Level.FINEST)) { - log.info("Tasks done in " + (t1task - t0task) + " new status " + - hstatus); - } - - } - if (hstatus == HandshakeStatus.NOT_HANDSHAKING) { - //log.warning("NOT HANDSHAKING " + this); - break; - } - } - endHandshake(); - processRealInput(net.getIn(), in); - } catch (Throwable t) { - log.log(Level.SEVERE, "Error handshaking", t); - try { - close(); - net.close(); - sendHandleReceivedCallback(); - } catch (IOException ex) { - log.log(Level.SEVERE, "Error closing", ex); - } - } - } - - - @Override - public void handleReceived(IOChannel ch) throws IOException { - processInput(net.getIn(), in); - // Maybe we don't have data - that's fine. - sendHandleReceivedCallback(); - } - - SslChannel setSslContext(SSLContext sslCtx) { - this.sslCtx = sslCtx; - return this; - } - - SslChannel setSslProvider(JsseSslProvider con) { - this.sslProvider = con; - return this; - } - - public Object getAttribute(String name) { - if (SslProvider.ATT_SSL_CERT.equals(name)) { - try { - return sslEngine.getSession().getPeerCertificateChain(); - } catch (SSLPeerUnverifiedException e) { - return null; // no re-negotiation - } - } else if (SslProvider.ATT_SSL_CIPHER.equals(name)) { - return sslEngine.getSession().getCipherSuite(); - } else if (SslProvider.ATT_SSL_KEY_SIZE.equals(name)) { - // looks like we need to get it from the string cipher - CipherData c_aux[] = ciphers; - - int size = 0; - String cipherSuite = sslEngine.getSession().getCipherSuite(); - for (int i = 0; i < c_aux.length; i++) { - if (cipherSuite.indexOf(c_aux[i].phrase) >= 0) { - size = c_aux[i].keySize; - break; - } - } - return size; - } else if (SslProvider.ATT_SSL_SESSION_ID.equals(name)) { - byte [] ssl_session = sslEngine.getSession().getId(); - if ( ssl_session == null) - return null; - StringBuilder buf=new StringBuilder(); - for(int x=0; x2) digit=digit.substring(digit.length()-2); - buf.append(digit); - } - return buf.toString(); - } - - if (net != null) { - return net.getAttribute(name); - } - return null; - } - - - /** - * Simple data class that represents the cipher being used, along with the - * corresponding effective key size. The specified phrase must appear in the - * name of the cipher suite to be recognized. - */ - - static final class CipherData { - - public String phrase = null; - - public int keySize = 0; - - public CipherData(String phrase, int keySize) { - this.phrase = phrase; - this.keySize = keySize; - } - - } - - - /** - * A mapping table to determine the number of effective bits in the key - * when using a cipher suite containing the specified cipher name. The - * underlying data came from the TLS Specification (RFC 2246), Appendix C. - */ - static final CipherData ciphers[] = { - new CipherData("_WITH_NULL_", 0), - new CipherData("_WITH_IDEA_CBC_", 128), - new CipherData("_WITH_RC2_CBC_40_", 40), - new CipherData("_WITH_RC4_40_", 40), - new CipherData("_WITH_RC4_128_", 128), - new CipherData("_WITH_DES40_CBC_", 40), - new CipherData("_WITH_DES_CBC_", 56), - new CipherData("_WITH_3DES_EDE_CBC_", 168), - new CipherData("_WITH_AES_128_CBC_", 128), - new CipherData("_WITH_AES_256_CBC_", 256) - }; - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/package.html b/modules/tomcat-lite/java/org/apache/tomcat/lite/io/package.html deleted file mode 100644 index 07a0f305c1af..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/io/package.html +++ /dev/null @@ -1,7 +0,0 @@ -IO layer based on tomcat coyote connector and utils. - -There are many big changes: -

      -
    • -
    • -
    \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/CopyCallback.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/CopyCallback.java deleted file mode 100644 index 2372859efebb..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/CopyCallback.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.proxy; - -import java.io.IOException; -import java.nio.ByteBuffer; - -import org.apache.tomcat.lite.http.HttpChannel; -import org.apache.tomcat.lite.io.IOBuffer; -import org.apache.tomcat.lite.io.IOChannel; -import org.apache.tomcat.lite.io.IOConnector; - -/** - * Used by socks and http proxy. Will copy received data to a different - * channel. - */ -public class CopyCallback implements IOConnector.DataReceivedCallback { - IOChannel mOutBuffer; - - public CopyCallback(IOChannel sc) { - mOutBuffer = sc; - } - - @Override - public void handleReceived(IOChannel ch) throws IOException { - IOBuffer inBuffer = ch.getIn(); - IOChannel outBuffer = mOutBuffer; - if (outBuffer == null && - ch instanceof HttpChannel) { - outBuffer = - (IOChannel) ((HttpChannel)ch).getRequest().getAttribute("P"); - } - // body. - while (true) { - if (outBuffer == null || outBuffer.getOut() == null) { - return; - } - if (outBuffer.getOut().isAppendClosed()) { - return; - } - - ByteBuffer bb = outBuffer.getOut().getWriteBuffer(); - int rd = inBuffer.read(bb); - outBuffer.getOut().releaseWriteBuffer(rd); - - if (rd == 0) { - outBuffer.startSending(); - return; - } - if (rd < 0) { - outBuffer.getOut().close(); - outBuffer.startSending(); - return; - } - } - } - } \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/HttpProxyService.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/HttpProxyService.java deleted file mode 100644 index 63b17375ae3a..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/HttpProxyService.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.proxy; - -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.http.HttpChannel; -import org.apache.tomcat.lite.http.HttpConnector; -import org.apache.tomcat.lite.http.HttpRequest; -import org.apache.tomcat.lite.http.HttpResponse; -import org.apache.tomcat.lite.http.MultiMap; -import org.apache.tomcat.lite.http.HttpChannel.HttpService; -import org.apache.tomcat.lite.http.HttpChannel.RequestCompleted; -import org.apache.tomcat.lite.io.CBuffer; -import org.apache.tomcat.lite.io.IOChannel; -import org.apache.tomcat.lite.io.IOConnector; -import org.apache.tomcat.lite.io.CBuffer; -import org.apache.tomcat.lite.io.SocketConnector; - -/** - * Http callback for the server-side. Will forward all requests to - * a remote http server - either using proxy mode ( GET http://... ) or - * forward requests ( GET /foo -> will be served by the remote server ). - * - * This is not blocking (except the connect, which currenly blocks on dns). - */ -public class HttpProxyService implements HttpService { - - // target - when used in forwarding mode. - String target = "localhost"; - int port = 8802; - - static Logger log = Logger.getLogger("HttpProxy"); - public static boolean debug = false; - boolean keepOpen = true; - - // client side - this connect to the real server that generates the resp. - ProxyClientCallback clientHeadersReceived = new ProxyClientCallback(); - - HttpConnector httpConnector; - IOConnector ioConnector; - - public HttpProxyService withSelector(IOConnector pool) { - this.ioConnector = pool; - return this; - } - - public HttpProxyService withHttpClient(HttpConnector pool) { - this.httpConnector = pool; - return this; - } - - public HttpProxyService withTarget(String host, int port) { - this.target = host; - this.port = port; - return this; - } - - private IOConnector getSelector() { - if (ioConnector == null) { - ioConnector = new SocketConnector(); - } - return ioConnector; - } - - private HttpConnector getHttpConnector() { - if (httpConnector == null) { - httpConnector = new HttpConnector(getSelector()); - } - return httpConnector; - } - - // Connects to the target CONNECT server, as client, forwards - static class ProxyConnectClientConnection implements IOConnector.ConnectedCallback { - - IOChannel serverNet; - private HttpChannel serverHttp; - - public ProxyConnectClientConnection(HttpChannel sproc) throws IOException { - this.serverNet = sproc.getSink(); - this.serverHttp = sproc; - } - - @Override - public void handleConnected(IOChannel ioch) throws IOException { - if (!ioch.isOpen()) { - serverNet.close(); - log.severe("Connection failed"); - return; - } - afterClientConnect(ioch); - - ioch.setDataReceivedCallback(new CopyCallback(serverNet)); - //ioch.setDataFlushedCallback(new ProxyFlushedCallback(serverNet, ioch)); - serverNet.setDataReceivedCallback(new CopyCallback(ioch)); - //serverNet.setDataFlushedCallback(new ProxyFlushedCallback(ioch, serverNet)); - - ioch.sendHandleReceivedCallback(); - } - - static byte[] OK = "HTTP/1.1 200 OK\r\n\r\n".getBytes(); - - protected void afterClientConnect(IOChannel clientCh) throws IOException { - serverNet.getOut().queue(OK); - serverNet.startSending(); - - serverHttp.release(); // no longer used - } - } - - /** - * Parse the req, dispatch the connection. - */ - @Override - public void service(HttpRequest serverHttpReq, HttpResponse serverHttpRes) - throws IOException { - - String dstHost = target; // default target ( for normal req ). - int dstPort = port; - - // TODO: more flexibility/callbacks on selecting the target, acl, etc - if (serverHttpReq.method().equals("CONNECT")) { - // SSL proxy - just connect and forward all packets - // TODO: optimize, add error checking - String[] hostPort = serverHttpReq.requestURI().toString().split(":"); - String host = hostPort[0]; - int port = 443; - if (hostPort.length > 1) { - port = Integer.parseInt(hostPort[1]); - } - if (log.isLoggable(Level.FINE)) { - HttpChannel server = serverHttpReq.getHttpChannel(); - log.info("NEW: " + server.getId() + " " + dstHost + " " + - server.getRequest().getMethod() + - " " + server.getRequest().getRequestURI() + " " + - server.getIn()); - } - - try { - getSelector().connect(host, port, - new ProxyConnectClientConnection(serverHttpReq.getHttpChannel())); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return; - } - - - CBuffer origURIx = serverHttpReq.requestURI(); -// String origURI = origURIx.toString(); -// if (origURI.startsWith("http://")) { -// // Real proxy - extract client address, modify the uri. -// // TODO: optimize the strings. -// int start = origURI.indexOf('/', 7); -// String hostPortS = (start == -1) ? -// origURI.subSequence(7, origURI.length()).toString() : -// origURI.subSequence(7, start).toString(); -// String[] hostPort = hostPortS.split(":"); -// -// dstHost = hostPort[0]; -// dstPort = (hostPort.length > 1) ? Integer.parseInt(hostPort[1]) : -// 80; -// -// if (start >= 0) { -// serverHttpReq.requestURI().set(origURI.substring(start)); -// } else { -// serverHttpReq.requestURI().set("/"); -// } -// } else { - // Adjust the host header. - CBuffer hostHdr = - serverHttpReq.getMimeHeaders().getHeader("host"); - if (hostHdr != null) { - hostHdr.recycle(); - CBuffer cb = hostHdr; - cb.append(dstHost); - if (dstPort != 80) { - cb.append(':'); - cb.appendInt(dstPort); - } - } -// } - if (debug) { - HttpChannel server = serverHttpReq.getHttpChannel(); - log.info("START: " + server.getId() + " " + dstHost + " " + - server.getRequest().getMethod() + - " " + server.getRequest().getRequestURI() + " " + - server.getIn()); - } - - // Send the request with a non-blocking write - HttpChannel serverHttp = serverHttpReq.getHttpChannel(); - - // Client connection - HttpChannel httpClient = getHttpConnector().get(dstHost, dstPort); - - serverHttp.getRequest().setAttribute("CLIENT", httpClient); - httpClient.getRequest().setAttribute("SERVER", serverHttp); - serverHttp.getRequest().setAttribute("P", httpClient); - httpClient.getRequest().setAttribute("P", serverHttp); - - httpClient.setHttpService(clientHeadersReceived); - - // Will send the original request (TODO: small changes) - // Response is not affected ( we use the callback ) - httpClient.getRequest().method().set(serverHttp.getRequest().method()); - httpClient.getRequest().requestURI().set(serverHttp.getRequest().requestURI()); - if (serverHttp.getRequest().queryString().length() != 0) { - httpClient.getRequest().queryString().set(serverHttp.getRequest().queryString()); - } - - httpClient.getRequest().protocol().set(serverHttp.getRequest().protocol()); - - //cstate.reqHeaders.addValue(name) - copyHeaders(serverHttp.getRequest().getMimeHeaders(), - httpClient.getRequest().getMimeHeaders() /*dest*/); - - // For debug - httpClient.getRequest().getMimeHeaders().remove("Accept-Encoding"); - - if (!keepOpen) { - httpClient.getRequest().getMimeHeaders().setValue("Connection").set("Close"); - } - - // Any data - serverHttp.setDataReceivedCallback(copy); - copy.handleReceived(serverHttp); - - httpClient.send(); - - - //serverHttp.handleReceived(serverHttp.getSink()); - //httpClient.flush(); // send any data still there - - httpClient.setCompletedCallback(done); - // Will call release() - serverHttp.setCompletedCallback(done); - - serverHttpReq.async(); - } - - static HttpDoneCallback done = new HttpDoneCallback(); - static CopyCallback copy = new CopyCallback(null); - // POST: after sendRequest(ch) we need to forward the body !! - - - static void copyHeaders(MultiMap mimeHeaders, MultiMap dest) - throws IOException { - for (int i = 0; i < mimeHeaders.size(); i++) { - CBuffer name = mimeHeaders.getName(i); - CBuffer val = dest.addValue(name.toString()); - val.set(mimeHeaders.getValue(i)); - } - } - - /** - * HTTP _CLIENT_ callback - from tomcat to final target. - */ - public class ProxyClientCallback implements HttpService { - /** - * Headers received from the client (content http server). - * TODO: deal with version missmatches. - */ - @Override - public void service(HttpRequest clientHttpReq, HttpResponse clientHttpRes) throws IOException { - HttpChannel serverHttp = (HttpChannel) clientHttpReq.getAttribute("SERVER"); - - try { - serverHttp.getResponse().setStatus(clientHttpRes.getStatus()); - serverHttp.getResponse().getMessageBuffer().set(clientHttpRes.getMessageBuffer()); - copyHeaders(clientHttpRes.getMimeHeaders(), - serverHttp.getResponse().getMimeHeaders()); - - serverHttp.getResponse().getMimeHeaders().addValue("TomcatProxy").set("True"); - - clientHttpReq.getHttpChannel().setDataReceivedCallback(copy); - copy.handleReceived(clientHttpReq.getHttpChannel()); - - serverHttp.startSending(); - - - //clientHttpReq.flush(); // send any data still there - - // if (clientHttpReq.getHttpChannel().getIn().isClosedAndEmpty()) { - // serverHttp.getOut().close(); // all data from client already in buffers - // } - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - - static final class HttpDoneCallback implements RequestCompleted { - - public HttpDoneCallback() { - } - - @Override - public void handle(HttpChannel doneCh, Object extraData) throws IOException { - HttpChannel serverCh = - (HttpChannel) doneCh.getRequest().getAttribute("SERVER"); - HttpChannel clientCh = doneCh; - String tgt = "C"; - if (serverCh == null) { - serverCh = doneCh; - clientCh = - (HttpChannel) doneCh.getRequest().getAttribute("CLIENT"); - tgt = "S"; - } - if (serverCh == null || clientCh == null) { - return; - } - if (doneCh.getError()) { - serverCh.abort("Proxy error"); - clientCh.abort("Proxy error"); - return; - } - - if (log.isLoggable(Level.FINE)) { - HttpChannel peerCh = - (HttpChannel) doneCh.getRequest().getAttribute("SERVER"); - if (peerCh == null) { - peerCh = - (HttpChannel) doneCh.getRequest().getAttribute("CLIENT"); - } else { - - } - log.info(tgt + " " + peerCh.getId() + " " + - doneCh.getTarget() + " " + - doneCh.getRequest().getMethod() + - " " + doneCh.getRequest().getRequestURI() + " " + - doneCh.getResponse().getStatus() + " IN:" + doneCh.getIn() - + " OUT:" + doneCh.getOut() + - " SIN:" + peerCh.getIn() + - " SOUT:" + peerCh.getOut() ); - } - // stop forwarding. After this call the client object will be - // recycled - //clientCB.outBuffer = null; - - // We must releaes both at same time - synchronized (this) { - - serverCh.complete(); - - if (clientCh.getRequest().getAttribute("SERVER") == null) { - return; - } - if (clientCh.isDone() && serverCh.isDone()) { - clientCh.getRequest().setAttribute("SERVER", null); - serverCh.getRequest().setAttribute("CLIENT", null); - clientCh.getRequest().setAttribute("P", null); - serverCh.getRequest().setAttribute("P", null); - // Reuse the objects. - serverCh.release(); - clientCh.release(); - } - } - } - } - - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/ProxyFlushedCallback.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/ProxyFlushedCallback.java deleted file mode 100644 index 05df0ca5e633..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/ProxyFlushedCallback.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.proxy; - -import java.io.IOException; - -import org.apache.tomcat.lite.io.IOChannel; -import org.apache.tomcat.lite.io.IOConnector; - -public final class ProxyFlushedCallback implements IOConnector.DataFlushedCallback { - IOChannel peerCh; - - public ProxyFlushedCallback(IOChannel ch2, IOChannel clientChannel2) { - peerCh = ch2; - } - - @Override - public void handleFlushed(IOChannel ch) throws IOException { - if (ch.getOut().isClosedAndEmpty()) { - if (!peerCh.getOut().isAppendClosed()) { - peerCh.close(); - } - } - } -} \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/SocksServer.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/SocksServer.java deleted file mode 100644 index 8170afed1607..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/SocksServer.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.proxy; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.io.IOBuffer; -import org.apache.tomcat.lite.io.IOChannel; -import org.apache.tomcat.lite.io.IOConnector; -import org.apache.tomcat.lite.io.SocketConnector; - -/** - * A test for the selector package, and helper for the proxy - - * a SOCKS4a server. - * - * Besides the connection initialization, it's almost the - * same as the CONNECT method in http proxy. - * - * http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol - * http://www.smartftp.com/Products/SmartFTP/RFC/socks4a.protocol - * http://www.faqs.org/rfcs/rfc1928.html - * https://svn.torproject.org/svn/tor/trunk/doc/spec/socks-extensions.txt - * - * In firefox, set network.proxy.socks_remote_dns = true to do DNS via proxy. - * - * Also interesting: - * http://transocks.sourceforge.net/ - * - * @author Costin Manolache - */ -public class SocksServer implements Runnable, IOConnector.ConnectedCallback { - protected int port = 2080; - - protected IOConnector ioConnector; - protected static Logger log = Logger.getLogger("SocksServer"); - - protected long idleTimeout = 10 * 60000; // 10 min - - protected long lastConnection = 0; - protected long totalConTime = 0; - protected AtomicInteger totalConnections = new AtomicInteger(); - - protected AtomicInteger active = new AtomicInteger(); - - protected long inBytes; - protected long outBytes; - protected static int sockets; - - public int getPort() { - return port; - } - - public int getActive() { - return active.get(); - } - - public int getTotal() { - return totalConnections.get(); - } - - public void setPort(int port) { - this.port = port; - } - - public void handleAccepted(IOChannel accepted) throws IOException { - lastConnection = System.currentTimeMillis(); - active.incrementAndGet(); - totalConnections.incrementAndGet(); - sockets++; - - final SocksServerConnection socksCon = new SocksServerConnection(accepted); - socksCon.pool = ioConnector; - socksCon.server = this; - - accepted.setDataReceivedCallback(socksCon); - socksCon.handleReceived(accepted); - } - - /** - * Exit if no activity happens. - */ - public void setIdleTimeout(long to) { - idleTimeout = to; - } - - public long getIdleTimeout() { - return idleTimeout; - } - - public void stop() { - ioConnector.stop(); - } - - public void initServer() throws IOException { - if (ioConnector == null) { - ioConnector = new SocketConnector(); - } - ioConnector.acceptor(this, Integer.toString(port), null); - - final Timer timer = new Timer(true /* daemon */); - timer.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - try { - // if lastConnection == 0 - it'll terminate on first timer - float avg = (totalConnections.get() > 0) ? - totalConTime / totalConnections.get() : 0; - System.err.println("Socks:" - + "\ttotal=" + totalConnections - + "\tin=" + inBytes - + "\tout=" + outBytes - + "\tavg=" + (int) avg); - if (active.get() <= 0 - && idleTimeout > 0 - && System.currentTimeMillis() - lastConnection > idleTimeout) { - System.err.println("Idle timeout"); - stop(); - this.cancel(); - timer.cancel(); - } - } catch (Throwable t) { - log.log(Level.SEVERE, "Error in timer", t); - } - } - }, 5 * 60 * 1000, 5 * 60 * 1000); // 5 - - - } - - - public static class SocksServerConnection implements IOConnector.DataReceivedCallback, IOConnector.ConnectedCallback { - - protected SocksServer server; - - boolean headReceived; - boolean head5Received = false; - - ByteBuffer headBuffer = ByteBuffer.allocate(256); - ByteBuffer headReadBuffer = headBuffer.duplicate(); - - ByteBuffer headResBuffer = ByteBuffer.allocate(256); - IOConnector pool; - byte ver; - byte cmd; - long startTime = System.currentTimeMillis(); - - static final int CMD_CONNECT = 0; - static final byte CMD_RESOLVE = (byte) 0xF0; - - int port; - byte[] hostB = new byte[4]; - CharBuffer userId = CharBuffer.allocate(256); - CharBuffer hostName = CharBuffer.allocate(256); - - SocketAddress sa = null; - - private byte atyp; - - IOChannel serverCh; - - public SocksServerConnection(IOChannel accepted) { - this.serverCh = accepted; - } - - protected void afterClientConnect(IOChannel clientCh) throws IOException { - headResBuffer.clear(); - if (ver == 4) { - headResBuffer.put((byte) 0); - headResBuffer.put((byte) 90); - for (int i = 0; i < 6; i++ ) { - headResBuffer.put((byte) 0); - } - } else { - headResBuffer.put((byte) 5); - headResBuffer.put((byte) 0); - headResBuffer.put((byte) 0); - headResBuffer.put((byte) 1); // ip - - headResBuffer.put(hostB); - int port2 = (Integer) clientCh.getAttribute(IOChannel.ATT_REMOTE_PORT); - headResBuffer.putShort((short) port2); - } - - headResBuffer.flip(); - - serverCh.getOut().queue(headResBuffer); - log.fine("Connected " + sa.toString()); - - if (headReadBuffer.remaining() > 0) { - serverCh.getOut().queue(headReadBuffer); - } - serverCh.startSending(); - } - - public void afterClose() { - long conTime = System.currentTimeMillis() - startTime; - int a = server.active.decrementAndGet(); - if (a < 0) { - System.err.println("negative !!"); - server.active.set(0); - } -// System.err.println(sa + "\tsR:" + -// received -// + "\tcR:" + clientReceived -// + "\tactive:" + a -// + "\ttotC:" + server.totalConnections -// + "\ttime:" + conTime); -// server.inBytes += received; -// server.totalConTime += conTime; -// server.outBytes += clientReceived; - } - - - protected int parseHead() throws IOException { - // data is between 0 and pos. - int pos = headBuffer.position(); - headReadBuffer.clear(); - headReadBuffer.limit(pos); - if (headReadBuffer.remaining() < 2) { - return -1; - } - - ByteBuffer bb = headReadBuffer; - ver = bb.get(); - if (ver == 5) { - return parseHead5(); - } - if (headReadBuffer.remaining() < 8) { - return -1; - } - cmd = bb.get(); - port = bb.getShort(); - bb.get(hostB); - userId.clear(); - int rc = readStringZ(bb, userId); - // Mozilla userid: MOZ ... - if (rc == -1) { - return rc; - } - if (hostB[0] == 0 && hostB[1] == 0 && hostB[2] == 0) { - // 0.0.0.x - atyp = 3; - hostName.clear(); - rc = readStringZ(bb, hostName); - if (rc == -1) { - return rc; - } - } else { - atyp = 1; - } - - headReceived = true; - - return 4; - } - - protected int parseHead5_2() throws IOException { - // data is between 0 and pos. - int pos = headBuffer.position(); - - headReadBuffer.clear(); - headReadBuffer.limit(pos); - - if (headReadBuffer.remaining() < 7) { - return -1; - } - - ByteBuffer bb = headReadBuffer; - ver = bb.get(); - cmd = bb.get(); - bb.get(); // reserved - atyp = bb.get(); - if (atyp == 1) { - bb.get(hostB); - } else if (atyp == 3) { - hostName.clear(); - int rc = readStringN(bb, hostName); - if (rc == -1) { - return rc; - } - } // ip6 not supported right now, easy to add - - port = bb.getShort(); - - head5Received = true; - - return 5; - } - - private int parseHead5() { - ByteBuffer bb = headReadBuffer; - int nrMethods = ((int)bb.get()) & 0xFF; - if (bb.remaining() < nrMethods) { - return -1; - } - for (int i = 0; i < nrMethods; i++) { - // ignore - bb.get(); - } - return 5; - } - - private int readStringZ(ByteBuffer bb, CharBuffer bc) throws IOException { - bc.clear(); - while (true) { - if (!bb.hasRemaining()) { - return -1; // not complete - } - byte b = bb.get(); - if (b == 0) { - bc.flip(); - return 0; - } else { - bc.put((char) b); - } - } - } - - private int readStringN(ByteBuffer bb, CharBuffer bc) throws IOException { - bc.clear(); - int len = ((int) bb.get()) & 0xff; - for (int i = 0; i < len; i++) { - if (!bb.hasRemaining()) { - return -1; // not complete - } - byte b = bb.get(); - bc.put((char) b); - } - bc.flip(); - return len; - } - - static ExecutorService connectTP = Executors.newCachedThreadPool(); - - protected void startClientConnection() throws IOException { - // TODO: use different thread ? - if (atyp == 3) { - connectTP.execute(new Runnable() { - - public void run() { - try { - sa = new InetSocketAddress(hostName.toString(), port); - pool.connect(hostName.toString(), port, - SocksServerConnection.this); - } catch (Exception ex) { - log.severe("Error connecting"); - } - } - }); - } else { - InetAddress addr = InetAddress.getByAddress(hostB); - pool.connect(addr.toString(), port, this); - } // TODO: ip6 - } - - public void handleConnected(IOChannel ioch) throws IOException { - ioch.setDataReceivedCallback(new CopyCallback(serverCh)); - //ioch.setDataFlushedCallback(new ProxyFlushedCallback(serverCh, ioch)); - - serverCh.setDataReceivedCallback(new CopyCallback(ioch)); - //serverCh.setDataFlushedCallback(new ProxyFlushedCallback(ioch, serverCh)); - - afterClientConnect(ioch); - - ioch.sendHandleReceivedCallback(); - } - - - @Override - public void handleReceived(IOChannel net) throws IOException { - IOBuffer ch = net.getIn(); - //SelectorChannel ch = (SelectorChannel) ioch; - if (!headReceived) { - int rd = ch.read(headBuffer); - if (rd == 0) { - return; - } - if (rd == -1) { - ch.close(); - } - - rd = parseHead(); - if (rd < 0) { - return; // need more - } - if (rd == 5) { - headResBuffer.clear(); - headResBuffer.put((byte) 5); - headResBuffer.put((byte) 0); - headResBuffer.flip(); - net.getOut().queue(headResBuffer); - net.startSending(); - headReceived = true; - headBuffer.clear(); - return; - } else { - headReceived = true; - head5Received = true; - startClientConnection(); - } - } - - if (!head5Received) { - int rd = ch.read(headBuffer); - if (rd == 0) { - return; - } - if (rd == -1) { - ch.close(); - } - - rd = parseHead5_2(); - if (rd < 0) { - return; // need more - } - - startClientConnection(); - } - } - } - - @Override - public void run() { - try { - initServer(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - @Override - public void handleConnected(IOChannel ch) throws IOException { - handleAccepted(ch); - } -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/StaticContentService.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/StaticContentService.java deleted file mode 100644 index c45b2110decb..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/proxy/StaticContentService.java +++ /dev/null @@ -1,129 +0,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.lite.proxy; - -import java.io.FileInputStream; -import java.io.IOException; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.http.HttpRequest; -import org.apache.tomcat.lite.http.HttpResponse; -import org.apache.tomcat.lite.http.HttpChannel.HttpService; -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.BBucket; -import org.apache.tomcat.lite.io.IOBuffer; - -/* - * - * Serve static content, from memory. - */ -public class StaticContentService implements HttpService { - protected Logger log = Logger.getLogger("coyote.static"); - protected BBucket mb; - - protected boolean chunked = false; - int code = 200; - - protected String contentType = "text/plain"; - - - public StaticContentService() { - } - - /** - * Used for testing chunked encoding. - * @return - */ - public StaticContentService chunked() { - chunked = true; - return this; - } - - public StaticContentService setData(byte[] data) { - mb = BBuffer.wrapper(data, 0, data.length); - return this; - } - - public StaticContentService setStatus(int status) { - this.code = status; - return this; - } - - public StaticContentService withLen(int len) { - byte[] data = new byte[len]; - for (int i = 0; i < len; i++) { - data[i] = 'A'; - } - mb = BBuffer.wrapper(data, 0, data.length); - return this; - } - - - public StaticContentService setData(CharSequence data) { - try { - IOBuffer tmp = new IOBuffer(null); - tmp.append(data); - mb = tmp.readAll(null); - } catch (IOException e) { - } - return this; - } - - public StaticContentService setContentType(String ct) { - this.contentType = ct; - return this; - } - - public void setFile(String path) { - try { - FileInputStream fis = new FileInputStream(path); - BBuffer bc = BBuffer.allocate(4096); - - byte b[] = new byte[4096]; - int rd = 0; - while ((rd = fis.read(b)) > 0) { - bc.append(b, 0, rd); - } - mb = bc; - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public void service(HttpRequest httpReq, HttpResponse res) throws IOException { - - res.setStatus(code); - - if (!chunked) { - res.setContentLength(mb.remaining()); - } - res.setContentType(contentType); - - int len = mb.remaining(); - int first = 0; - - if (chunked) { - first = len / 2; - res.getBody() - .queue(BBuffer.wrapper(mb, 0, first)); - res.flush(); - } - - res.getBody().queue(BBuffer.wrapper(mb, 0, len - first)); - } -} \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/service/IOStatus.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/service/IOStatus.java deleted file mode 100644 index fe5a65070f08..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/service/IOStatus.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.service; - -import java.io.IOException; -import java.util.List; - -import org.apache.tomcat.lite.http.HttpConnectionPool; -import org.apache.tomcat.lite.http.HttpRequest; -import org.apache.tomcat.lite.http.HttpResponse; -import org.apache.tomcat.lite.http.HttpWriter; -import org.apache.tomcat.lite.http.HttpChannel.HttpService; -import org.apache.tomcat.lite.http.HttpConnectionPool.RemoteServer; -import org.apache.tomcat.lite.http.HttpConnector.HttpConnection; -import org.apache.tomcat.lite.io.IOChannel; - -/** - * Dump status of a connection pool. - */ -public class IOStatus implements HttpService { - - private HttpConnectionPool pool; - - public IOStatus(HttpConnectionPool pool) { - this.pool = pool; - } - - @Override - public void service(HttpRequest httpReq, HttpResponse httpRes) - throws IOException { - HttpConnectionPool sc = pool; - HttpWriter out = httpRes.getBodyWriter(); - - httpRes.setContentType("text/plain"); - // TODO: use JMX/DynamicObject to get all public info - out.println("hosts=" + sc.getTargetCount()); - out.println("waiting=" + sc.getSocketCount()); - out.println("closed=" + sc.getClosedSockets()); - out.println(); - - for (RemoteServer remote: sc.getServers()) { - out.append(remote.target); - out.append("="); - List connections = remote.getConnections(); - out.println(Integer.toString(connections.size())); - - for (IOChannel ch: connections) { - out.println(ch.getId() + - " " + ch.toString()); - } - out.println(); - } - - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/service/LogConfig.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/service/LogConfig.java deleted file mode 100644 index ab5a3d207dc6..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/service/LogConfig.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2004 Costin Manolache - * 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.lite.service; - -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.http.HttpRequest; -import org.apache.tomcat.lite.http.HttpResponse; -import org.apache.tomcat.lite.http.HttpChannel.HttpService; - -/** - * Log configuration - * - */ -public class LogConfig implements HttpService { - - /** - * Framework can set this attribute with comma separated - * list of loggers to set to debug level. - * This is used at startup. - */ - public void setDebug(String debug) { - for (String log : debug.split(",")) { - Logger logger = Logger.getLogger(log); - logger.setLevel(Level.INFO); - } - } - - /** - * - */ - public void setWarn(String nodebug) { - for (String log : nodebug.split(",")) { - Logger logger = Logger.getLogger(log); - logger.setLevel(Level.WARNING); - } - } - - @Override - public void service(HttpRequest httpReq, HttpResponse httpRes) - throws IOException { - String debug = httpReq.getParameter("debug"); - setDebug(debug); - String warn = httpReq.getParameter("warn"); - setWarn(warn); - } -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/util/FastHttpDateFormat.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/util/FastHttpDateFormat.java deleted file mode 100644 index fe3c69a40b7a..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/util/FastHttpDateFormat.java +++ /dev/null @@ -1,231 +0,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.lite.util; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Utility class to generate HTTP dates. - * - * @author Remy Maucherat - */ -public final class FastHttpDateFormat { - - - // -------------------------------------------------------------- Variables - - - protected static final int CACHE_SIZE = - Integer.parseInt(System.getProperty("org.apache.tomcat.util.http.FastHttpDateFormat.CACHE_SIZE", "1000")); - - - /** - * HTTP date format. - */ - protected static final SimpleDateFormat format = - new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); - - - /** - * The set of SimpleDateFormat formats to use in getDateHeader(). - */ - protected static final SimpleDateFormat formats[] = { - new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US), - new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US), - new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) - }; - - - protected final static TimeZone gmtZone = TimeZone.getTimeZone("GMT"); - - - /** - * GMT timezone - all HTTP dates are on GMT - */ - static { - - format.setTimeZone(gmtZone); - - formats[0].setTimeZone(gmtZone); - formats[1].setTimeZone(gmtZone); - formats[2].setTimeZone(gmtZone); - - } - - - /** - * Instant on which the currentDate object was generated. - */ - protected static long currentDateGenerated = 0L; - - - /** - * Current formatted date. - */ - protected static String currentDate = null; - - - /** - * Formatter cache. - */ - protected static final ConcurrentHashMap formatCache = - new ConcurrentHashMap(CACHE_SIZE); - - - /** - * Parser cache. - */ - protected static final ConcurrentHashMap parseCache = - new ConcurrentHashMap(CACHE_SIZE); - - - // --------------------------------------------------------- Public Methods - - - /** - * Get the current date in HTTP format. - */ - public static final String getCurrentDate() { - - long now = System.currentTimeMillis(); - if ((now - currentDateGenerated) > 1000) { - synchronized (format) { - if ((now - currentDateGenerated) > 1000) { - currentDateGenerated = now; - currentDate = format.format(new Date(now)); - } - } - } - return currentDate; - - } - - - /** - * Get the HTTP format of the specified date. - */ - public static final String formatDate - (long value, DateFormat threadLocalformat) { - - Long longValue = new Long(value); - String cachedDate = formatCache.get(longValue); - if (cachedDate != null) - return cachedDate; - - String newDate = null; - Date dateValue = new Date(value); - if (threadLocalformat != null) { - newDate = threadLocalformat.format(dateValue); - updateFormatCache(longValue, newDate); - } else { - synchronized (formatCache) { - synchronized (format) { - newDate = format.format(dateValue); - } - updateFormatCache(longValue, newDate); - } - } - return newDate; - - } - - - /** - * Try to parse the given date as a HTTP date. - */ - public static final long parseDate(String value, - DateFormat[] threadLocalformats) { - - Long cachedDate = parseCache.get(value); - if (cachedDate != null) - return cachedDate.longValue(); - - Long date = null; - if (threadLocalformats != null) { - date = internalParseDate(value, threadLocalformats); - updateParseCache(value, date); - } else { - synchronized (parseCache) { - date = internalParseDate(value, formats); - updateParseCache(value, date); - } - } - if (date == null) { - return (-1L); - } else { - return date.longValue(); - } - - } - - - /** - * Parse date with given formatters. - */ - private static final Long internalParseDate - (String value, DateFormat[] formats) { - Date date = null; - for (int i = 0; (date == null) && (i < formats.length); i++) { - try { - date = formats[i].parse(value); - } catch (ParseException e) { - ; - } - } - if (date == null) { - return null; - } - return new Long(date.getTime()); - } - - - /** - * Update cache. - */ - private static void updateFormatCache(Long key, String value) { - if (value == null) { - return; - } - if (formatCache.size() > CACHE_SIZE) { - formatCache.clear(); - } - formatCache.put(key, value); - } - - - /** - * Update cache. - */ - private static void updateParseCache(String key, Long value) { - if (value == null) { - return; - } - if (parseCache.size() > CACHE_SIZE) { - parseCache.clear(); - } - parseCache.put(key, value); - } - - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/util/LocaleParser.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/util/LocaleParser.java deleted file mode 100644 index fafdbffb8d16..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/util/LocaleParser.java +++ /dev/null @@ -1,394 +0,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.lite.util; - -import java.util.ArrayList; -import java.util.Locale; -import java.util.TreeMap; - - -/** - * Utility class for string parsing that is higher performance than - * StringParser for simple delimited text cases. Parsing is performed - * by setting the string, and then using the findXxxx() and - * skipXxxx() families of methods to remember significant - * offsets. To retrieve the parsed substrings, call the extract() - * method with the appropriate saved offset values. - * - * @author Craig R. McClanahan - */ -public final class LocaleParser { - - public LocaleParser() { - this(null); - } - - public LocaleParser(String string) { - setString(string); - } - - public TreeMap parseLocale(String value) { - // Store the accumulated languages that have been requested in - // a local collection, sorted by the quality value (so we can - // add Locales in descending order). The values will be ArrayLists - // containing the corresponding Locales to be added - TreeMap locales = new TreeMap(); - - // Preprocess the value to remove all whitespace - int white = value.indexOf(' '); - if (white < 0) - white = value.indexOf('\t'); - if (white >= 0) { - StringBuilder sb = new StringBuilder(); - int len = value.length(); - for (int i = 0; i < len; i++) { - char ch = value.charAt(i); - if ((ch != ' ') && (ch != '\t')) - sb.append(ch); - } - value = sb.toString(); - } - - LocaleParser parser = this; - // Process each comma-delimited language specification - parser.setString(value); // ASSERT: parser is available to us - int length = parser.getLength(); - while (true) { - - // Extract the next comma-delimited entry - int start = parser.getIndex(); - if (start >= length) - break; - int end = parser.findChar(','); - String entry = parser.extract(start, end).trim(); - parser.advance(); // For the following entry - - // Extract the quality factor for this entry - double quality = 1.0; - int semi = entry.indexOf(";q="); - if (semi >= 0) { - try { - quality = Double.parseDouble(entry.substring(semi + 3)); - } catch (NumberFormatException e) { - quality = 0.0; - } - entry = entry.substring(0, semi); - } - - // Skip entries we are not going to keep track of - if (quality < 0.00005) - continue; // Zero (or effectively zero) quality factors - if ("*".equals(entry)) - continue; // FIXME - "*" entries are not handled - - // Extract the language and country for this entry - String language = null; - String country = null; - String variant = null; - int dash = entry.indexOf('-'); - if (dash < 0) { - language = entry; - country = ""; - variant = ""; - } else { - language = entry.substring(0, dash); - country = entry.substring(dash + 1); - int vDash = country.indexOf('-'); - if (vDash > 0) { - String cTemp = country.substring(0, vDash); - variant = country.substring(vDash + 1); - country = cTemp; - } else { - variant = ""; - } - } - - // Add a new Locale to the list of Locales for this quality level - Locale locale = new Locale(language, country, variant); - Double key = new Double(-quality); // Reverse the order - ArrayList values = (ArrayList) locales.get(key); - if (values == null) { - values = new ArrayList(); - locales.put(key, values); - } - values.add(locale); - - } - - return locales; - } - - /** - * The characters of the current string, as a character array. Stored - * when the string is first specified to speed up access to characters - * being compared during parsing. - */ - private char chars[] = null; - - - /** - * The zero-relative index of the current point at which we are - * positioned within the string being parsed. NOTE: - * the value of this index can be one larger than the index of the last - * character of the string (i.e. equal to the string length) if you - * parse off the end of the string. This value is useful for extracting - * substrings that include the end of the string. - */ - private int index = 0; - - - /** - * The length of the String we are currently parsing. Stored when the - * string is first specified to avoid repeated recalculations. - */ - private int length = 0; - - - /** - * The String we are currently parsing. - */ - private String string = null; - - - // ------------------------------------------------------------- Properties - - - /** - * Return the zero-relative index of our current parsing position - * within the string being parsed. - */ - public int getIndex() { - - return (this.index); - - } - - - /** - * Return the length of the string we are parsing. - */ - public int getLength() { - - return (this.length); - - } - - - /** - * Return the String we are currently parsing. - */ - public String getString() { - - return (this.string); - - } - - - /** - * Set the String we are currently parsing. The parser state is also reset - * to begin at the start of this string. - * - * @param string The string to be parsed. - */ - public void setString(String string) { - - this.string = string; - if (string != null) { - this.length = string.length(); - chars = this.string.toCharArray(); - } else { - this.length = 0; - chars = new char[0]; - } - reset(); - - } - - - // --------------------------------------------------------- Public Methods - - - /** - * Advance the current parsing position by one, if we are not already - * past the end of the string. - */ - public void advance() { - - if (index < length) - index++; - - } - - - /** - * Extract and return a substring that starts at the specified position, - * and extends to the end of the string being parsed. If this is not - * possible, a zero-length string is returned. - * - * @param start Starting index, zero relative, inclusive - */ - public String extract(int start) { - - if ((start < 0) || (start >= length)) - return (""); - else - return (string.substring(start)); - - } - - - /** - * Extract and return a substring that starts at the specified position, - * and ends at the character before the specified position. If this is - * not possible, a zero-length string is returned. - * - * @param start Starting index, zero relative, inclusive - * @param end Ending index, zero relative, exclusive - */ - public String extract(int start, int end) { - - if ((start < 0) || (start >= end) || (end > length)) - return (""); - else - return (string.substring(start, end)); - - } - - - /** - * Return the index of the next occurrence of the specified character, - * or the index of the character after the last position of the string - * if no more occurrences of this character are found. The current - * parsing position is updated to the returned value. - * - * @param ch Character to be found - */ - public int findChar(char ch) { - - while ((index < length) && (ch != chars[index])) - index++; - return (index); - - } - - - /** - * Return the index of the next occurrence of a non-whitespace character, - * or the index of the character after the last position of the string - * if no more non-whitespace characters are found. The current - * parsing position is updated to the returned value. - */ - public int findText() { - - while ((index < length) && isWhite(chars[index])) - index++; - return (index); - - } - - - /** - * Return the index of the next occurrence of a whitespace character, - * or the index of the character after the last position of the string - * if no more whitespace characters are found. The current parsing - * position is updated to the returned value. - */ - public int findWhite() { - - while ((index < length) && !isWhite(chars[index])) - index++; - return (index); - - } - - - /** - * Reset the current state of the parser to the beginning of the - * current string being parsed. - */ - public void reset() { - - index = 0; - - } - - - /** - * Advance the current parsing position while it is pointing at the - * specified character, or until it moves past the end of the string. - * Return the final value. - * - * @param ch Character to be skipped - */ - public int skipChar(char ch) { - - while ((index < length) && (ch == chars[index])) - index++; - return (index); - - } - - - /** - * Advance the current parsing position while it is pointing at a - * non-whitespace character, or until it moves past the end of the string. - * Return the final value. - */ - public int skipText() { - - while ((index < length) && !isWhite(chars[index])) - index++; - return (index); - - } - - - /** - * Advance the current parsing position while it is pointing at a - * whitespace character, or until it moves past the end of the string. - * Return the final value. - */ - public int skipWhite() { - - while ((index < length) && isWhite(chars[index])) - index++; - return (index); - - } - - - // ------------------------------------------------------ Protected Methods - - - /** - * Is the specified character considered to be whitespace? - * - * @param ch Character to be checked - */ - protected boolean isWhite(char ch) { - - if ((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n')) - return (true); - else - return (false); - - } - - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/util/MimeMap.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/util/MimeMap.java deleted file mode 100644 index bedb0ff0e453..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/util/MimeMap.java +++ /dev/null @@ -1,195 +0,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.lite.util; - -import java.net.FileNameMap; -import java.util.Enumeration; -import java.util.Hashtable; - - -/** - * A mime type map that implements the java.net.FileNameMap interface. - * - * @author James Duncan Davidson [duncan@eng.sun.com] - * @author Jason Hunter [jch@eng.sun.com] - */ -public class MimeMap implements FileNameMap { - - // Defaults - all of them are "well-known" types, - // you can add using normal web.xml. - - public static Hashtable defaultMap = - new Hashtable(101); - static { - defaultMap.put("txt", "text/plain"); - defaultMap.put("css", "text/css"); - defaultMap.put("html","text/html"); - defaultMap.put("htm", "text/html"); - defaultMap.put("gif", "image/gif"); - defaultMap.put("jpg", "image/jpeg"); - defaultMap.put("jpe", "image/jpeg"); - defaultMap.put("jpeg", "image/jpeg"); - defaultMap.put("png", "image/png"); - defaultMap.put("java", "text/plain"); - defaultMap.put("body", "text/html"); - defaultMap.put("rtx", "text/richtext"); - defaultMap.put("tsv", "text/tab-separated-values"); - defaultMap.put("etx", "text/x-setext"); - defaultMap.put("ps", "application/x-postscript"); - defaultMap.put("class", "application/java"); - defaultMap.put("csh", "application/x-csh"); - defaultMap.put("sh", "application/x-sh"); - defaultMap.put("tcl", "application/x-tcl"); - defaultMap.put("tex", "application/x-tex"); - defaultMap.put("texinfo", "application/x-texinfo"); - defaultMap.put("texi", "application/x-texinfo"); - defaultMap.put("t", "application/x-troff"); - defaultMap.put("tr", "application/x-troff"); - defaultMap.put("roff", "application/x-troff"); - defaultMap.put("man", "application/x-troff-man"); - defaultMap.put("me", "application/x-troff-me"); - defaultMap.put("ms", "application/x-wais-source"); - defaultMap.put("src", "application/x-wais-source"); - defaultMap.put("zip", "application/zip"); - defaultMap.put("bcpio", "application/x-bcpio"); - defaultMap.put("cpio", "application/x-cpio"); - defaultMap.put("gtar", "application/x-gtar"); - defaultMap.put("shar", "application/x-shar"); - defaultMap.put("sv4cpio", "application/x-sv4cpio"); - defaultMap.put("sv4crc", "application/x-sv4crc"); - defaultMap.put("tar", "application/x-tar"); - defaultMap.put("ustar", "application/x-ustar"); - defaultMap.put("dvi", "application/x-dvi"); - defaultMap.put("hdf", "application/x-hdf"); - defaultMap.put("latex", "application/x-latex"); - defaultMap.put("bin", "application/octet-stream"); - defaultMap.put("oda", "application/oda"); - defaultMap.put("pdf", "application/pdf"); - defaultMap.put("ps", "application/postscript"); - defaultMap.put("eps", "application/postscript"); - defaultMap.put("ai", "application/postscript"); - defaultMap.put("rtf", "application/rtf"); - defaultMap.put("nc", "application/x-netcdf"); - defaultMap.put("cdf", "application/x-netcdf"); - defaultMap.put("cer", "application/x-x509-ca-cert"); - defaultMap.put("exe", "application/octet-stream"); - defaultMap.put("gz", "application/x-gzip"); - defaultMap.put("Z", "application/x-compress"); - defaultMap.put("z", "application/x-compress"); - defaultMap.put("hqx", "application/mac-binhex40"); - defaultMap.put("mif", "application/x-mif"); - defaultMap.put("ief", "image/ief"); - defaultMap.put("tiff", "image/tiff"); - defaultMap.put("tif", "image/tiff"); - defaultMap.put("ras", "image/x-cmu-raster"); - defaultMap.put("pnm", "image/x-portable-anymap"); - defaultMap.put("pbm", "image/x-portable-bitmap"); - defaultMap.put("pgm", "image/x-portable-graymap"); - defaultMap.put("ppm", "image/x-portable-pixmap"); - defaultMap.put("rgb", "image/x-rgb"); - defaultMap.put("xbm", "image/x-xbitmap"); - defaultMap.put("xpm", "image/x-xpixmap"); - defaultMap.put("xwd", "image/x-xwindowdump"); - defaultMap.put("au", "audio/basic"); - defaultMap.put("snd", "audio/basic"); - defaultMap.put("aif", "audio/x-aiff"); - defaultMap.put("aiff", "audio/x-aiff"); - defaultMap.put("aifc", "audio/x-aiff"); - defaultMap.put("wav", "audio/x-wav"); - defaultMap.put("mpeg", "video/mpeg"); - defaultMap.put("mpg", "video/mpeg"); - defaultMap.put("mpe", "video/mpeg"); - defaultMap.put("qt", "video/quicktime"); - defaultMap.put("mov", "video/quicktime"); - defaultMap.put("avi", "video/x-msvideo"); - defaultMap.put("movie", "video/x-sgi-movie"); - defaultMap.put("avx", "video/x-rad-screenplay"); - defaultMap.put("wrl", "x-world/x-vrml"); - defaultMap.put("mpv2", "video/mpeg2"); - - /* Add XML related MIMEs */ - - defaultMap.put("xml", "text/xml"); - defaultMap.put("xsl", "text/xml"); - defaultMap.put("svg", "image/svg+xml"); - defaultMap.put("svgz", "image/svg+xml"); - defaultMap.put("wbmp", "image/vnd.wap.wbmp"); - defaultMap.put("wml", "text/vnd.wap.wml"); - defaultMap.put("wmlc", "application/vnd.wap.wmlc"); - defaultMap.put("wmls", "text/vnd.wap.wmlscript"); - defaultMap.put("wmlscriptc", "application/vnd.wap.wmlscriptc"); - } - - - private Hashtable map = new Hashtable(); - - public void addContentType(String extn, String type) { - map.put(extn, type.toLowerCase()); - } - - public Enumeration getExtensions() { - return map.keys(); - } - - public String getMimeType(String ext) { - return getContentTypeFor(ext); - } - - public String getContentType(String extn) { - String type = (String)map.get(extn.toLowerCase()); - if( type == null ) type=(String)defaultMap.get( extn ); - return type; - } - - public void removeContentType(String extn) { - map.remove(extn.toLowerCase()); - } - - /** Get extension of file, without fragment id - */ - public static String getExtension( String fileName ) { - // play it safe and get rid of any fragment id - // that might be there - int length=fileName.length(); - - int newEnd = fileName.lastIndexOf('#'); - if( newEnd== -1 ) newEnd=length; - // Instead of creating a new string. - // if (i != -1) { - // fileName = fileName.substring(0, i); - // } - int i = fileName.lastIndexOf('.', newEnd ); - if (i != -1) { - return fileName.substring(i + 1, newEnd ); - } else { - // no extension, no content type - return null; - } - } - - public String getContentTypeFor(String fileName) { - String extn=getExtension( fileName ); - if (extn!=null) { - return getContentType(extn); - } else { - // no extension, no content type - return null; - } - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/util/Range.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/util/Range.java deleted file mode 100644 index 6bc1f5f96f8c..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/util/Range.java +++ /dev/null @@ -1,160 +0,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.lite.util; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.StringTokenizer; - -/** - * Utils to process HTTP/1.1 ranges. Used by default servlet, could - * be used by any servlet that needs to deal with ranges. - * - * It is very good to support ranges if you have large content. In most - * cases supporting one range is enough - getting multiple ranges doesn't - * seem very common, and it's complex (multipart response). - * - * @author Costin Manolache - * @author Remy Maucherat - * @author - see DefaultServlet in Catalin for other contributors - */ -public class Range { - - public long start; - public long end; - public long length; - - /** - * Validate range. - */ - public boolean validate() { - if (end >= length) - end = length - 1; - return ( (start >= 0) && (end >= 0) && (start <= end) - && (length > 0) ); - } - - public void recycle() { - start = 0; - end = 0; - length = 0; - } - - /** Parse ranges. - * - * @return null if the range is invalid or can't be parsed - */ - public static ArrayList parseRanges(long fileLength, - String rangeHeader) throws IOException { - ArrayList result = new ArrayList(); - StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ","); - - // Parsing the range list - while (commaTokenizer.hasMoreTokens()) { - String rangeDefinition = commaTokenizer.nextToken().trim(); - - Range currentRange = new Range(); - currentRange.length = fileLength; - - int dashPos = rangeDefinition.indexOf('-'); - - if (dashPos == -1) { - return null; - } - - if (dashPos == 0) { - try { - long offset = Long.parseLong(rangeDefinition); - currentRange.start = fileLength + offset; - currentRange.end = fileLength - 1; - } catch (NumberFormatException e) { - return null; - } - } else { - - try { - currentRange.start = Long.parseLong - (rangeDefinition.substring(0, dashPos)); - if (dashPos < rangeDefinition.length() - 1) - currentRange.end = Long.parseLong - (rangeDefinition.substring - (dashPos + 1, rangeDefinition.length())); - else - currentRange.end = fileLength - 1; - } catch (NumberFormatException e) { - return null; - } - - } - if (!currentRange.validate()) { - return null; - } - result.add(currentRange); - } - return result; - } - - - /** - * Parse the Content-Range header. Used with PUT or in response. - * - * @return Range - */ - public static Range parseContentRange(String rangeHeader) - throws IOException { - if (rangeHeader == null) - return null; - - // bytes is the only range unit supported - if (!rangeHeader.startsWith("bytes")) { - return null; - } - - rangeHeader = rangeHeader.substring(6).trim(); - - int dashPos = rangeHeader.indexOf('-'); - int slashPos = rangeHeader.indexOf('/'); - - if (dashPos == -1) { - return null; - } - - if (slashPos == -1) { - return null; - } - - Range range = new Range(); - - try { - range.start = Long.parseLong(rangeHeader.substring(0, dashPos)); - range.end = - Long.parseLong(rangeHeader.substring(dashPos + 1, slashPos)); - range.length = Long.parseLong - (rangeHeader.substring(slashPos + 1, rangeHeader.length())); - } catch (NumberFormatException e) { - return null; - } - - if (!range.validate()) { - return null; - } - - return range; - } - -} \ No newline at end of file diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/util/URLEncoder.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/util/URLEncoder.java deleted file mode 100644 index 4364aea86ce0..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/util/URLEncoder.java +++ /dev/null @@ -1,227 +0,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.lite.util; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import java.util.BitSet; - -/** - * - * This class is very similar to the java.net.URLEncoder class. - * - * Unfortunately, with java.net.URLEncoder there is no way to specify to the - * java.net.URLEncoder which characters should NOT be encoded. - * - * This code was moved from DefaultServlet.java - * - * @author Craig R. McClanahan - * @author Remy Maucherat - */ -public class URLEncoder { - protected static final char[] hexadecimal = - {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F'}; - - //Array containing the safe characters set. - protected BitSet safeChars = new BitSet(128); - - public URLEncoder() { - for (char i = 'a'; i <= 'z'; i++) { - addSafeCharacter(i); - } - for (char i = 'A'; i <= 'Z'; i++) { - addSafeCharacter(i); - } - for (char i = '0'; i <= '9'; i++) { - addSafeCharacter(i); - } - //safe - safeChars.set('$'); - safeChars.set('-'); - safeChars.set('_'); - safeChars.set('.'); - - // Dangerous: someone may treat this as " " - // RFC1738 does allow it, it's not reserved - // safeChars.set('+'); - //extra - safeChars.set('!'); - safeChars.set('*'); - safeChars.set('\''); - safeChars.set('('); - safeChars.set(')'); - safeChars.set(','); - } - - public void addSafeCharacter( char c ) { - safeChars.set( c ); - } - - public String encodeURL(String path) { - return encodeURL(path, "UTF-8", true); - } - - public String encodeURL(String path, String enc, boolean allowSlash) { - int maxBytesPerChar = 10; - - StringBuffer rewrittenPath = new StringBuffer(path.length()); - ByteArrayOutputStream buf = new ByteArrayOutputStream(maxBytesPerChar); - OutputStreamWriter writer = null; - try { - writer = new OutputStreamWriter(buf, enc); - } catch (UnsupportedEncodingException e1) { - // shouldn't happen. - } - - for (int i = 0; i < path.length(); i++) { - int c = (int) path.charAt(i); - if (c < 128 && safeChars.get(c) || allowSlash && c == '/') { - rewrittenPath.append((char)c); - } else { - // convert to external encoding before hex conversion - try { - writer.write((char)c); - if (c >= 0xD800 && c <= 0xDBFF) { - if ( (i+1) < path.length()) { - int d = path.charAt(i+1); - if (d >= 0xDC00 && d <= 0xDFFF) { - writer.write((char) d); - i++; - } - } - } - writer.flush(); - } catch(IOException e) { - buf.reset(); - continue; - } - byte[] ba = buf.toByteArray(); - for (int j = 0; j < ba.length; j++) { - // Converting each byte in the buffer - byte toEncode = ba[j]; - rewrittenPath.append('%'); - int low = (int) (toEncode & 0x0f); - int high = (int) ((toEncode & 0xf0) >> 4); - rewrittenPath.append(hexadecimal[high]); - rewrittenPath.append(hexadecimal[low]); - } - buf.reset(); - } - } - return rewrittenPath.toString(); - } - - /** - * Decode and return the specified URL-encoded String. - * - * @param str The url-encoded string - * @param enc The encoding to use; if null, the default encoding is used - * @exception IllegalArgumentException if a '%' character is not followed - * by a valid 2-digit hexadecimal number - */ - public static String URLDecode(String str, String enc) { - - if (str == null) - return (null); - - // use the specified encoding to extract bytes out of the - // given string so that the encoding is not lost. If an - // encoding is not specified, let it use platform default - byte[] bytes = null; - try { - if (enc == null) { - bytes = str.getBytes(); - } else { - bytes = str.getBytes(enc); - } - } catch (UnsupportedEncodingException uee) {} - - return URLDecode(bytes, enc); - - } - - - /** - * Decode and return the specified URL-encoded String. - * When the byte array is converted to a string, the system default - * character encoding is used... This may be different than some other - * servers. - * - * @param str The url-encoded string - * - * @exception IllegalArgumentException if a '%' character is not followed - * by a valid 2-digit hexadecimal number - */ - public static String URLDecode(String str) { - - return URLDecode(str, null); - - } - - /** - * Decode and return the specified URL-encoded byte array. - * - * @param bytes The url-encoded byte array - * @param enc The encoding to use; if null, the default encoding is used - * @exception IllegalArgumentException if a '%' character is not followed - * by a valid 2-digit hexadecimal number - */ - private static String URLDecode(byte[] bytes, String enc) { - - if (bytes == null) - return (null); - - int len = bytes.length; - int ix = 0; - int ox = 0; - while (ix < len) { - byte b = bytes[ix++]; // Get byte to test - if (b == '+') { - b = (byte)' '; - } else if (b == '%') { - b = (byte) ((convertHexDigit(bytes[ix++]) << 4) - + convertHexDigit(bytes[ix++])); - } - bytes[ox++] = b; - } - if (enc != null) { - try { - return new String(bytes, 0, ox, enc); - } catch (Exception e) { - e.printStackTrace(); - } - } - return new String(bytes, 0, ox); - - } - - /** - * Convert a byte character value to hexidecimal digit value. - * - * @param b the character value byte - */ - private static byte convertHexDigit( byte b ) { - if ((b >= '0') && (b <= '9')) return (byte)(b - '0'); - if ((b >= 'a') && (b <= 'f')) return (byte)(b - 'a' + 10); - if ((b >= 'A') && (b <= 'F')) return (byte)(b - 'A' + 10); - return 0; - } - -} diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/util/UrlUtils.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/util/UrlUtils.java deleted file mode 100644 index c0d9df0d95c4..000000000000 --- a/modules/tomcat-lite/java/org/apache/tomcat/lite/util/UrlUtils.java +++ /dev/null @@ -1,84 +0,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.lite.util; - -public class UrlUtils { - - /** Used by webdav. - * - * Return a context-relative path, beginning with a "/", that represents - * the canonical version of the specified path after ".." and "." elements - * are resolved out. If the specified path attempts to go outside the - * boundaries of the current context (i.e. too many ".." path elements - * are present), return null instead. - * - * @param path Path to be normalized - */ - public static String normalize(String path) { - - if (path == null) - return null; - - // Create a place for the normalized path - String normalized = path; - - if (normalized.equals("/.")) - return "/"; - - // Normalize the slashes and add leading slash if necessary - if (normalized.indexOf('\\') >= 0) - normalized = normalized.replace('\\', '/'); - - if (!normalized.startsWith("/")) - normalized = "/" + normalized; - - // Resolve occurrences of "//" in the normalized path - while (true) { - int index = normalized.indexOf("//"); - if (index < 0) - break; - normalized = normalized.substring(0, index) + - normalized.substring(index + 1); - } - - // Resolve occurrences of "/./" in the normalized path - while (true) { - int index = normalized.indexOf("/./"); - if (index < 0) - break; - normalized = normalized.substring(0, index) + - normalized.substring(index + 2); - } - - // Resolve occurrences of "/../" in the normalized path - while (true) { - int index = normalized.indexOf("/../"); - if (index < 0) - break; - if (index == 0) - return (null); // Trying to go outside our context - int index2 = normalized.lastIndexOf('/', index - 1); - normalized = normalized.substring(0, index2) + - normalized.substring(index + 3); - } - - // Return the normalized path that we have completed - return (normalized); - } - -} diff --git a/modules/tomcat-lite/pom.xml b/modules/tomcat-lite/pom.xml deleted file mode 100644 index d44cd77d2320..000000000000 --- a/modules/tomcat-lite/pom.xml +++ /dev/null @@ -1,118 +0,0 @@ - - 4.0.0 - - org.apache.tomcat.lite - lite - - 0.0.1-SNAPSHOT - - - - com.jcraft - jzlib - 1.0.7 - jar - compile - - - javax.servlet - servlet-api - 2.5 - - - junit - junit - 3.8.2 - jar - compile - - - commons-codec - commons-codec - 1.4 - jar - compile - - - org.apache.tomcat - jasper - 6.0.20 - jar - compile - - - org.apache.tomcat - jasper-jdt - 6.0.20 - jar - compile - - - org.apache.tomcat - jasper-el - 6.0.20 - jar - compile - - - asm - asm - 3.1 - jar - compile - - - asm - asm-tree - 3.1 - jar - compile - - - org.apache.tomcat - coyote - 6.0.20 - - - org.apache.ant - ant - 1.7.1 - - - - - - java - - test - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.6 - 1.6 - - org/apache/coyote/servlet/** - **/ServletApi30.java - - - org/apache/coyote/servlet/** - **/ServletApi30.java - - - - - - - - test - - **/*.java - - - - - - diff --git a/modules/tomcat-lite/test/org/apache/coyote/lite/ServletTests.java b/modules/tomcat-lite/test/org/apache/coyote/lite/ServletTests.java deleted file mode 100644 index f7ce095a0153..000000000000 --- a/modules/tomcat-lite/test/org/apache/coyote/lite/ServletTests.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - */ -package org.apache.coyote.lite; - -import java.io.File; -import java.io.IOException; - -import javax.servlet.ServletException; - -import org.apache.catalina.LifecycleException; -import org.apache.tomcat.test.watchdog.WatchdogClient; - -import junit.framework.Test; - -/** - * Wrapper to run watchdog. - * - */ -public class ServletTests extends WatchdogClient { - - - public ServletTests() { - super(); - goldenDir = getWatchdogdir() + "/src/clients/org/apache/jcheck/servlet/client/"; - testMatch = - //"HttpServletResponseWrapperSetStatusMsgTest"; - //"ServletContextAttributeAddedEventTest"; - null; - // ex: "ServletToJSP"; - file = getWatchdogdir() + "/src/conf/servlet-gtest.xml"; - targetMatch = "gtestservlet-test"; - - port = 8883; - exclude = new String[] { - "DoInit1Test", // tomcat returns 404 if perm. unavailable - "HttpServletDoInit1Test", - "GetMajorVersionTest", // tomcat7 - "GetMinorVersionTest", - "ServletToJSPErrorPageTest", - "ServletToJSPError502PageTest", - }; - } - - public ServletTests(String name) { - this(); - super.single = name; - port = 8883; - } - - protected void beforeSuite() { - // required for the tests - System.setProperty("org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER", - "true"); - - try { - initServerWithWatchdog(getWatchdogdir()); - } catch (ServletException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - public void initServerWithWatchdog(String wdDir) throws ServletException, - IOException { - Tomcat tomcat = new Tomcat(); - tomcat.setPort(port); - - File f = new File(wdDir + "/build/webapps"); - tomcat.setBaseDir(f.getAbsolutePath()); - - for (String s : new String[] { - "servlet-compat", - "servlet-tests", - "jsp-tests"} ) { - tomcat.addWebapp("/" + s, f.getCanonicalPath() + "/" + s); - } - - TomcatStandaloneMain.setUp(tomcat, port); - - try { - tomcat.start(); - } catch (LifecycleException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - System.err.println("Init done"); - } - - /** - * Magic JUnit method - */ - public static Test suite() { - return new ServletTests().getSuite(); - } -} diff --git a/modules/tomcat-lite/test/org/apache/coyote/lite/Tomcat.java b/modules/tomcat-lite/test/org/apache/coyote/lite/Tomcat.java deleted file mode 100644 index 880165b6954c..000000000000 --- a/modules/tomcat-lite/test/org/apache/coyote/lite/Tomcat.java +++ /dev/null @@ -1,914 +0,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.coyote.lite; - -import java.io.File; -import java.io.IOException; -import java.security.Principal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.servlet.Servlet; -import javax.servlet.ServletException; - -import org.apache.catalina.Container; -import org.apache.catalina.Context; -import org.apache.catalina.Lifecycle; -import org.apache.catalina.LifecycleEvent; -import org.apache.catalina.LifecycleException; -import org.apache.catalina.LifecycleListener; -import org.apache.catalina.Realm; -import org.apache.catalina.connector.Connector; -import org.apache.catalina.core.StandardContext; -import org.apache.catalina.core.StandardEngine; -import org.apache.catalina.core.StandardHost; -import org.apache.catalina.core.StandardServer; -import org.apache.catalina.core.StandardService; -import org.apache.catalina.core.StandardWrapper; -import org.apache.catalina.realm.RealmBase; -import org.apache.catalina.session.StandardManager; -import org.apache.catalina.startup.ContextConfig; - -// This class is here for compat with Tomcat6. - -// TODO: lazy init for the temp dir - only when a JSP is compiled or -// get temp dir is called we need to create it. This will avoid the -// need for the baseDir - -// TODO: allow contexts without a base dir - i.e. -// only programmatic. This would disable the default servlet. - -/** - * Minimal tomcat starter for embedding/unit tests. - * - * Tomcat supports multiple styles of configuration and - * startup - the most common and stable is server.xml-based, - * implemented in org.apache.catalina.startup.Bootstrap. - * - * This class is for use in apps that embed tomcat. - * Requirements: - * - * - all tomcat classes and possibly servlets are in the classpath. - * ( for example all is in one big jar, or in eclipse CP, or in any other - * combination ) - * - * - we need one temporary directory for work files - * - * - no config file is required. This class provides methods to - * use if you have a webapp with a web.xml file, but it is - * optional - you can use your own servlets. - * - * This class provides a main() and few simple CLI arguments, - * see setters for doc. It can be used for simple tests and - * demo. - * - * @see TestTomcat for examples on how to use this - * @author Costin Manolache - */ -public class Tomcat { - // Single engine, service, server, connector - few cases need more, - // they can use server.xml - protected StandardServer server; - protected StandardService service; - protected StandardEngine engine; - protected Connector connector; // for more - customize the classes - - boolean started = false; - // To make it a bit easier to config for the common case - // ( one host, one context ). - protected StandardHost host; - - // TODO: it's easy to add support for more hosts - but is it - // really needed ? - - // TODO: allow use of in-memory connector - - protected int port = 8080; - protected String hostname = "localhost"; - protected String basedir; - - // Default in-memory realm, will be set by default on - // created contexts. Can be replaced with setRealm() on - // the context. - protected Realm defaultRealm; - private Map userPass = new HashMap(); - private Map> userRoles = - new HashMap>(); - private Map userPrincipals = new HashMap(); - - public Tomcat() { - // NOOP - } - - /** - * Tomcat needs a directory for temp files. This should be the - * first method called. - * - * By default, if this method is not called, we use: - * - system properties - catalina.base, catalina.home - * - $HOME/tomcat.$PORT - * ( /tmp doesn't seem a good choice for security ). - * - * - * TODO: better default ? Maybe current dir ? - * TODO: disable work dir if not needed ( no jsp, etc ). - */ - public void setBaseDir(String basedir) { - this.basedir = basedir; - } - - /** - * Set the port for the default connector. Must - * be called before start(). - */ - public void setPort(int port) { - this.port = port; - } - - /** - * The the hostname of the default host, default is - * 'localhost'. - */ - public void setHostname(String s) { - hostname = s; - } - - /** - * Add a webapp using normal WEB-INF/web.xml if found. - * - * @param contextPath - * @param baseDir - * @return new StandardContext - * @throws ServletException - */ - public StandardContext addWebapp(String contextPath, - String baseDir) throws ServletException { - - return addWebapp(getHost(), contextPath, baseDir); - } - - - /** - * Add a context - programmatic mode, no web.xml used. - * - * API calls equivalent with web.xml: - * - * context-param - * ctx.addParameter("name", "value"); - * - * - * error-page - * ErrorPage ep = new ErrorPage(); - * ep.setErrorCode(500); - * ep.setLocation("/error.html"); - * ctx.addErrorPage(ep); - * - * ctx.addMimeMapping("ext", "type"); - * - * Note: If you reload the Context, all your configuration will be lost. If - * you need reload support, consider using a LifecycleListener to provide - * your configuration. - * - * TODO: add the rest - * - * @param contextPath "/" for root context. - * @param baseDir base dir for the context, for static files. Must exist, - * relative to the server home - */ - public StandardContext addContext(String contextPath, - String baseDir) { - return addContext(getHost(), contextPath, baseDir); - } - - /** - * Equivalent with - * . - * - * In general it is better/faster to use the method that takes a - * Servlet as param - this one can be used if the servlet is not - * commonly used, and want to avoid loading all deps. - * ( for example: jsp servlet ) - * - * You can customize the returned servlet, ex: - * - * wrapper.addInitParameter("name", "value"); - * - * @param contextPath Context to add Servlet to - * @param servletName Servlet name (used in mappings) - * @param servletClass The class to be used for the Servlet - * @return The wrapper for the servlet - */ - public StandardWrapper addServlet(String contextPath, - String servletName, - String servletClass) { - Container ctx = getHost().findChild(contextPath); - return addServlet((StandardContext) ctx, - servletName, servletClass); - } - - /** - * Static version of {@link #addServlet(String, String, String)} - * @param ctx Context to add Servlet to - * @param servletName Servlet name (used in mappings) - * @param servletClass The class to be used for the Servlet - * @return The wrapper for the servlet - */ - public static StandardWrapper addServlet(StandardContext ctx, - String servletName, - String servletClass) { - // will do class for name and set init params - StandardWrapper sw = (StandardWrapper)ctx.createWrapper(); - sw.setServletClass(servletClass); - sw.setName(servletName); - ctx.addChild(sw); - - return sw; - } - - /** - * Add an existing Servlet to the context with no class.forName or - * initialisation. - * @param contextPath Context to add Servlet to - * @param servletName Servlet name (used in mappings) - * @param servlet The Servlet to add - * @return The wrapper for the servlet - */ - public StandardWrapper addServlet(String contextPath, - String servletName, - Servlet servlet) { - Container ctx = getHost().findChild(contextPath); - return addServlet((StandardContext) ctx, - servletName, servlet); - } - - /** - * Static version of {@link #addServlet(String, String, Servlet)}. - * @param ctx Context to add Servlet to - * @param servletName Servlet name (used in mappings) - * @param servlet The Servlet to add - * @return The wrapper for the servlet - */ - public static StandardWrapper addServlet(StandardContext ctx, - String servletName, - Servlet servlet) { - // will do class for name and set init params - StandardWrapper sw = new ExistingStandardWrapper(servlet); - sw.setName(servletName); - ctx.addChild(sw); - - return sw; - } - - - /** - * Initialize and start the server. - * @throws LifecycleException - */ - public void start() throws LifecycleException { - if (started) { - return; - } - started = true; - getServer(); - getConnector(); - server.start(); - } - - /** - * Stop the server. - * @throws LifecycleException - */ - public void stop() throws LifecycleException { - getServer().stop(); - } - - - /** - * Add a user for the in-memory realm. All created apps use this - * by default, can be replaced using setRealm(). - * - */ - public void addUser(String user, String pass) { - userPass.put(user, pass); - } - - /** - * @see #addUser(String, String) - */ - public void addRole(String user, String role) { - List roles = userRoles.get(user); - if (roles == null) { - roles = new ArrayList(); - userRoles.put(user, roles); - } - roles.add(role); - } - - // ------- Extra customization ------- - // You can tune individual tomcat objects, using internal APIs - - /** - * Get the default http connector. You can set more - * parameters - the port is already initialized. - * - * Alternatively, you can construct a Connector and set any params, - * then call addConnector(Connector) - * - * @return A connector object that can be customized - */ - public Connector getConnector() { - getServer(); - if (connector != null) { - return connector; - } - // This will load Apr connector if available, - // default to nio. I'm having strange problems with apr - // and for the use case the speed benefit wouldn't matter. - - //connector = new Connector("HTTP/1.1"); - try { - connector = new Connector("org.apache.coyote.http11.Http11Protocol"); - connector.setPort(port); - service.addConnector( connector ); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return connector; - } - - public void setConnector(Connector connector) { - this.connector = connector; - } - - /** - * Get the service object. Can be used to add more - * connectors and few other global settings. - */ - public StandardService getService() { - getServer(); - return service; - } - - /** - * Sets the current host - all future webapps will - * be added to this host. When tomcat starts, the - * host will be the default host. - * - * @param host - */ - public void setHost(StandardHost host) { - this.host = host; - } - - public StandardHost getHost() { - if (host == null) { - host = new StandardHost(); - host.setName(hostname); - - getEngine().addChild( host ); - } - return host; - } - - /** - * Set a custom realm for auth. If not called, a simple - * default will be used, using an internal map. - * - * Must be called before adding a context. - */ - public void setDefaultRealm(Realm realm) { - defaultRealm = realm; - } - - - /** - * Access to the engine, for further customization. - */ - public StandardEngine getEngine() { - if(engine == null ) { - getServer(); - engine = new StandardEngine(); - engine.setName( "Tomcat" ); - engine.setDefaultHost(hostname); - service.setContainer(engine); - } - return engine; - } - - /** - * Get the server object. You can add listeners and few more - * customizations. JNDI is disabled by default. - */ - public StandardServer getServer() { - - if (server != null) { - return server; - } - - initBaseDir(); - - System.setProperty("catalina.useNaming", "false"); - - server = new StandardServer(); - server.setPort( -1 ); - - service = new StandardService(); - service.setName("Tomcat"); - server.addService( service ); - return server; - } - - public StandardContext addContext(StandardHost host, - String contextPath, - String dir) { - silence(contextPath); - StandardContext ctx = new StandardContext(); - ctx.setPath( contextPath ); - ctx.setDocBase(dir); - ctx.addLifecycleListener(new FixContextListener()); - - if (host == null) { - getHost().addChild(ctx); - } else { - host.addChild(ctx); - } - return ctx; - } - - public StandardContext addWebapp(StandardHost host, - String url, String path) { - silence(url); - - StandardContext ctx = new StandardContext(); - ctx.setPath( url ); - ctx.setDocBase(path); - if (defaultRealm == null) { - initSimpleAuth(); - } - ctx.setRealm(defaultRealm); - ctx.addLifecycleListener(new DefaultWebXmlListener()); - - ContextConfig ctxCfg = new ContextConfig(); - ctx.addLifecycleListener( ctxCfg ); - // prevent it from looking ( if it finds one - it'll have dup error ) - ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML"); - - if (host == null) { - getHost().addChild(ctx); - } else { - host.addChild(ctx); - } - - return ctx; - } - - - // ---------- Helper methods and classes ------------------- - - /** - * Initialize an in-memory realm. You can replace it - * for contexts with a real one. - */ - protected void initSimpleAuth() { - defaultRealm = new RealmBase() { - @Override - protected String getName() { - return "Simple"; - } - - @Override - protected String getPassword(String username) { - return userPass.get(username); - } - - @Override - protected Principal getPrincipal(final String username) { - Principal p = userPrincipals.get(username); - if (p == null) { - String pass = userPass.get(username); - if (pass != null) { - p = new Principal() { - - @Override - public String getName() { - return username; - } - - }; - } - } - return p; - } - - }; - } - - protected void initBaseDir() { - if (basedir == null) { - basedir = System.getProperty("catalina.base"); - } - if (basedir == null) { - basedir = System.getProperty("catalina.home"); - } - if (basedir == null) { - // Create a temp dir. - basedir = System.getProperty("user.dir") + - "/tomcat." + port; - File home = new File(basedir); - home.mkdir(); - if (!home.isAbsolute()) { - try { - basedir = home.getCanonicalPath(); - } catch (IOException e) { - basedir = home.getAbsolutePath(); - } - } - } - System.setProperty("catalina.home", basedir); - System.setProperty("catalina.base", basedir); - } - - static String[] silences = new String[] { - "org.apache.coyote.http11.Http11Protocol", - "org.apache.catalina.core.StandardService", - "org.apache.catalina.core.StandardEngine", - "org.apache.catalina.startup.ContextConfig", - "org.apache.catalina.core.ApplicationContext", - "org.apache.catalina.core.AprLifecycleListener" - }; - - /** - * Controls if the loggers will be silenced or not. - * @param silent true sets the log level to WARN for the - * loggers that log information on Tomcat start up. This - * prevents the usual startup information being logged. - * false sets the log level to the default - * level of INFO. - */ - public void setSilent(boolean silent) { - for (String s : silences) { - if (silent) { - Logger.getLogger(s).setLevel(Level.WARNING); - } else { - Logger.getLogger(s).setLevel(Level.INFO); - } - } - } - - private void silence(String ctx) { - String base = "org.apache.catalina.core.ContainerBase.[default].["; - base += getHost().getName(); - base += "].["; - base += ctx; - base += "]"; - Logger.getLogger(base).setLevel(Level.WARNING); - } - - /** - * Enables JNDI naming which is disabled by default. - */ - public void enableNaming() { - // Make sure getServer() has been called as that is where naming is - // disabled - getServer(); - - System.setProperty("catalina.useNaming", "true"); - String value = "org.apache.naming"; - String oldValue = - System.getProperty(javax.naming.Context.URL_PKG_PREFIXES); - if (oldValue != null) { - value = value + ":" + oldValue; - } - System.setProperty(javax.naming.Context.URL_PKG_PREFIXES, value); - value = System.getProperty - (javax.naming.Context.INITIAL_CONTEXT_FACTORY); - if (value == null) { - System.setProperty - (javax.naming.Context.INITIAL_CONTEXT_FACTORY, - "org.apache.naming.java.javaURLContextFactory"); - } - } - - /** - * Provide default configuration for a context. This is the programmatic - * equivalent of the default web.xml. - * - * TODO: in normal tomcat, if default-web.xml is not found, use this - * method - * - * @param contextPath The context to set the defaults for - */ - public void initWebappDefaults(String contextPath) { - Container ctx = getHost().findChild(contextPath); - initWebappDefaults((StandardContext) ctx); - } - - /** - * Static version of {@link #initWebappDefaults(String)} - * @param ctx The context to set the defaults for - */ - public static void initWebappDefaults(StandardContext ctx) { - // Default servlet - StandardWrapper servlet = addServlet( - ctx, "default", "org.apache.catalina.servlets.DefaultServlet"); - servlet.setLoadOnStartup(1); - - // JSP servlet (by class name - to avoid loading all deps) - servlet = addServlet( - ctx, "jsp", "org.apache.jasper.servlet.JspServlet"); - servlet.addInitParameter("fork", "false"); - servlet.setLoadOnStartup(3); - - // Servlet mappings - ctx.addServletMapping("/", "default"); - ctx.addServletMapping("*.jsp", "jsp"); - ctx.addServletMapping("*.jspx", "jsp"); - - // Sessions - ctx.setManager( new StandardManager()); - ctx.setSessionTimeout(30); - - // MIME mappings - for (int i = 0; i < DEFAULT_MIME_MAPPINGS.length; ) { - ctx.addMimeMapping(DEFAULT_MIME_MAPPINGS[i++], - DEFAULT_MIME_MAPPINGS[i++]); - } - - // Welcome files - ctx.addWelcomeFile("index.html"); - ctx.addWelcomeFile("index.htm"); - ctx.addWelcomeFile("index.jsp"); - } - - - /** - * Fix startup sequence - required if you don't use web.xml. - * - * The start() method in context will set 'configured' to false - and - * expects a listener to set it back to true. - */ - public static class FixContextListener implements LifecycleListener { - - public void lifecycleEvent(LifecycleEvent event) { - try { - Context context = (Context) event.getLifecycle(); - if (event.getType().equals(Lifecycle.START_EVENT)) { - context.setConfigured(true); - } - } catch (ClassCastException e) { - return; - } - } - - } - - - /** - * Fix reload - required if reloading and using programmatic configuration. - * When a context is reloaded, any programmatic configuration is lost. This - * listener sets the equivalent of conf/web.xml when the context starts. The - * context needs to be an instance of StandardContext for this listener to - * have any effect. - */ - public static class DefaultWebXmlListener implements LifecycleListener { - public void lifecycleEvent(LifecycleEvent event) { - if (Lifecycle.BEFORE_START_EVENT.equals(event.getType()) && - event.getLifecycle() instanceof StandardContext) { - initWebappDefaults((StandardContext) event.getLifecycle()); - } - } - } - - - /** - * Helper class for wrapping existing servlets. This disables servlet - * lifecycle and normal reloading, but also reduces overhead and provide - * more direct control over the servlet. - */ - public static class ExistingStandardWrapper extends StandardWrapper { - private Servlet existing; - boolean init = false; - - public ExistingStandardWrapper( Servlet existing ) { - this.existing = existing; - } - @Override - public synchronized Servlet loadServlet() throws ServletException { - if (!init) { - existing.init(facade); - init = true; - } - return existing; - - } - @Override - public long getAvailable() { - return 0; - } - @Override - public boolean isUnavailable() { - return false; - } - } - - /** - * TODO: would a properties resource be better ? Or just parsing - * /etc/mime.types ? - * This is needed because we don't use the default web.xml, where this - * is encoded. - */ - public static final String[] DEFAULT_MIME_MAPPINGS = { - "abs", "audio/x-mpeg", - "ai", "application/postscript", - "aif", "audio/x-aiff", - "aifc", "audio/x-aiff", - "aiff", "audio/x-aiff", - "aim", "application/x-aim", - "art", "image/x-jg", - "asf", "video/x-ms-asf", - "asx", "video/x-ms-asf", - "au", "audio/basic", - "avi", "video/x-msvideo", - "avx", "video/x-rad-screenplay", - "bcpio", "application/x-bcpio", - "bin", "application/octet-stream", - "bmp", "image/bmp", - "body", "text/html", - "cdf", "application/x-cdf", - "cer", "application/x-x509-ca-cert", - "class", "application/java", - "cpio", "application/x-cpio", - "csh", "application/x-csh", - "css", "text/css", - "dib", "image/bmp", - "doc", "application/msword", - "dtd", "application/xml-dtd", - "dv", "video/x-dv", - "dvi", "application/x-dvi", - "eps", "application/postscript", - "etx", "text/x-setext", - "exe", "application/octet-stream", - "gif", "image/gif", - "gtar", "application/x-gtar", - "gz", "application/x-gzip", - "hdf", "application/x-hdf", - "hqx", "application/mac-binhex40", - "htc", "text/x-component", - "htm", "text/html", - "html", "text/html", - "hqx", "application/mac-binhex40", - "ief", "image/ief", - "jad", "text/vnd.sun.j2me.app-descriptor", - "jar", "application/java-archive", - "java", "text/plain", - "jnlp", "application/x-java-jnlp-file", - "jpe", "image/jpeg", - "jpeg", "image/jpeg", - "jpg", "image/jpeg", - "js", "text/javascript", - "jsf", "text/plain", - "jspf", "text/plain", - "kar", "audio/x-midi", - "latex", "application/x-latex", - "m3u", "audio/x-mpegurl", - "mac", "image/x-macpaint", - "man", "application/x-troff-man", - "mathml", "application/mathml+xml", - "me", "application/x-troff-me", - "mid", "audio/x-midi", - "midi", "audio/x-midi", - "mif", "application/x-mif", - "mov", "video/quicktime", - "movie", "video/x-sgi-movie", - "mp1", "audio/x-mpeg", - "mp2", "audio/x-mpeg", - "mp3", "audio/x-mpeg", - "mp4", "video/mp4", - "mpa", "audio/x-mpeg", - "mpe", "video/mpeg", - "mpeg", "video/mpeg", - "mpega", "audio/x-mpeg", - "mpg", "video/mpeg", - "mpv2", "video/mpeg2", - "ms", "application/x-wais-source", - "nc", "application/x-netcdf", - "oda", "application/oda", - "odb", "application/vnd.oasis.opendocument.database", - "odc", "application/vnd.oasis.opendocument.chart", - "odf", "application/vnd.oasis.opendocument.formula", - "odg", "application/vnd.oasis.opendocument.graphics", - "odi", "application/vnd.oasis.opendocument.image", - "odm", "application/vnd.oasis.opendocument.text-master", - "odp", "application/vnd.oasis.opendocument.presentation", - "ods", "application/vnd.oasis.opendocument.spreadsheet", - "odt", "application/vnd.oasis.opendocument.text", - "otg", "application/vnd.oasis.opendocument.graphics-template", - "oth", "application/vnd.oasis.opendocument.text-web", - "otp", "application/vnd.oasis.opendocument.presentation-template", - "ots", "application/vnd.oasis.opendocument.spreadsheet-template ", - "ott", "application/vnd.oasis.opendocument.text-template", - "ogx", "application/ogg", - "ogv", "video/ogg", - "oga", "audio/ogg", - "ogg", "audio/ogg", - "spx", "audio/ogg", - "faca", "audio/flac", - "anx", "application/annodex", - "axa", "audio/annodex", - "axv", "video/annodex", - "xspf", "application/xspf+xml", - "pbm", "image/x-portable-bitmap", - "pct", "image/pict", - "pdf", "application/pdf", - "pgm", "image/x-portable-graymap", - "pic", "image/pict", - "pict", "image/pict", - "pls", "audio/x-scpls", - "png", "image/png", - "pnm", "image/x-portable-anymap", - "pnt", "image/x-macpaint", - "ppm", "image/x-portable-pixmap", - "ppt", "application/vnd.ms-powerpoint", - "pps", "application/vnd.ms-powerpoint", - "ps", "application/postscript", - "psd", "image/x-photoshop", - "qt", "video/quicktime", - "qti", "image/x-quicktime", - "qtif", "image/x-quicktime", - "ras", "image/x-cmu-raster", - "rdf", "application/rdf+xml", - "rgb", "image/x-rgb", - "rm", "application/vnd.rn-realmedia", - "roff", "application/x-troff", - "rtf", "application/rtf", - "rtx", "text/richtext", - "sh", "application/x-sh", - "shar", "application/x-shar", - /*"shtml", "text/x-server-parsed-html",*/ - "smf", "audio/x-midi", - "sit", "application/x-stuffit", - "snd", "audio/basic", - "src", "application/x-wais-source", - "sv4cpio", "application/x-sv4cpio", - "sv4crc", "application/x-sv4crc", - "svg", "image/svg+xml", - "svgz", "image/svg+xml", - "swf", "application/x-shockwave-flash", - "t", "application/x-troff", - "tar", "application/x-tar", - "tcl", "application/x-tcl", - "tex", "application/x-tex", - "texi", "application/x-texinfo", - "texinfo", "application/x-texinfo", - "tif", "image/tiff", - "tiff", "image/tiff", - "tr", "application/x-troff", - "tsv", "text/tab-separated-values", - "txt", "text/plain", - "ulw", "audio/basic", - "ustar", "application/x-ustar", - "vxml", "application/voicexml+xml", - "xbm", "image/x-xbitmap", - "xht", "application/xhtml+xml", - "xhtml", "application/xhtml+xml", - "xls", "application/vnd.ms-excel", - "xml", "application/xml", - "xpm", "image/x-xpixmap", - "xsl", "application/xml", - "xslt", "application/xslt+xml", - "xul", "application/vnd.mozilla.xul+xml", - "xwd", "image/x-xwindowdump", - "vsd", "application/x-visio", - "wav", "audio/x-wav", - "wbmp", "image/vnd.wap.wbmp", - "wml", "text/vnd.wap.wml", - "wmlc", "application/vnd.wap.wmlc", - "wmls", "text/vnd.wap.wmlscript", - "wmlscriptc", "application/vnd.wap.wmlscriptc", - "wmv", "video/x-ms-wmv", - "wrl", "x-world/x-vrml", - "wspolicy", "application/wspolicy+xml", - "Z", "application/x-compress", - "z", "application/x-compress", - "zip", "application/zip" - }; -} diff --git a/modules/tomcat-lite/test/org/apache/coyote/lite/TomcatLiteCoyoteTest.java b/modules/tomcat-lite/test/org/apache/coyote/lite/TomcatLiteCoyoteTest.java deleted file mode 100644 index 2a8b233a51a1..000000000000 --- a/modules/tomcat-lite/test/org/apache/coyote/lite/TomcatLiteCoyoteTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - */ -package org.apache.coyote.lite; - -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import junit.framework.TestCase; - -import org.apache.tomcat.lite.http.HttpClient; -import org.apache.tomcat.lite.http.HttpChannel; -import org.apache.tomcat.lite.http.HttpConnector; -import org.apache.tomcat.lite.io.BBuffer; - -/** - * Very simple test. - */ -public class TomcatLiteCoyoteTest extends TestCase { - static int port = 8884; - static { - Logger.getLogger("org.apache.catalina.core.StandardService").setLevel(Level.WARNING); - Logger.getLogger("org.apache.catalina.core.StandardEngine").setLevel(Level.WARNING); - Logger.getLogger("org.apache.catalina.startup.ContextConfig").setLevel(Level.WARNING); - } - static Tomcat main = TomcatStandaloneMain.setUp(port); - - public void testSimple() throws IOException { - HttpConnector clientCon = HttpClient.newClient(); - - HttpChannel ch = clientCon.get("localhost", port); - ch.getRequest().setRequestURI("/index.html"); - ch.getRequest().send(); - - BBuffer res = ch.readAll(null, 0); - - assertTrue(res.toString(), - res.toString().indexOf("Apache Tomcat") >= 0); - } - - -} diff --git a/modules/tomcat-lite/test/org/apache/coyote/lite/TomcatStandaloneMain.java b/modules/tomcat-lite/test/org/apache/coyote/lite/TomcatStandaloneMain.java deleted file mode 100644 index 008bee5ba0f1..000000000000 --- a/modules/tomcat-lite/test/org/apache/coyote/lite/TomcatStandaloneMain.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - */ -package org.apache.coyote.lite; - -import javax.servlet.ServletException; - -import org.apache.catalina.LifecycleException; -import org.apache.catalina.connector.Connector; -import org.apache.tomcat.lite.TestMain; - -/** - * Startup tomcat + coyote lite connector. - * No config files used. - * - * @author Costin Manolache - */ -public class TomcatStandaloneMain { - - public static Tomcat setUp(int port) { - try { - Tomcat tomcat = new Tomcat(); - - tomcat.setPort(port); - String base = TestMain.findDir("/output/build"); - tomcat.setBaseDir(base); - // Absolute path - tomcat6 and 7 are different, - // 7 adds webapps. - tomcat.addWebapp("/", base + "/webapps/ROOT"); - - LiteProtocolHandler litePH = setUp(tomcat, port); - - tomcat.start(); - return tomcat; - } catch (LifecycleException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (ServletException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return null; - } - - public static LiteProtocolHandler setUp(Tomcat tomcat, int port) { - Connector connector; - try { - connector = new Connector(LiteProtocolHandler.class.getName()); - tomcat.getService().addConnector(connector); - connector.setPort(port); - tomcat.setConnector(connector); - LiteProtocolHandler ph = - (LiteProtocolHandler) connector.getProtocolHandler(); - return ph; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/TestMain.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/TestMain.java deleted file mode 100644 index 1ceafb4a3434..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/TestMain.java +++ /dev/null @@ -1,313 +0,0 @@ -/* - */ -package org.apache.tomcat.lite; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Constructor; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.http.BaseMapper; -import org.apache.tomcat.lite.http.HttpClient; -import org.apache.tomcat.lite.http.Dispatcher; -import org.apache.tomcat.lite.http.HttpConnector; -import org.apache.tomcat.lite.http.HttpRequest; -import org.apache.tomcat.lite.http.HttpResponse; -import org.apache.tomcat.lite.http.HttpServer; -import org.apache.tomcat.lite.http.HttpChannel.HttpService; -import org.apache.tomcat.lite.http.services.EchoCallback; -import org.apache.tomcat.lite.http.services.SleepCallback; -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.jsse.JsseSslProvider; -import org.apache.tomcat.lite.proxy.HttpProxyService; -import org.apache.tomcat.lite.proxy.StaticContentService; -import org.apache.tomcat.lite.service.IOStatus; - -/** - * Laucher for tomcat-lite standalone, configured with test handlers. - * - * Used in tests - one is running for the entire suite. - * - * @author Costin Manolache - */ -public class TestMain { - - static { - JsseSslProvider.testModeURLConnection(); - } - - static TestMain defaultServer; - - private boolean init = false; - - HttpConnector testClient; - HttpConnector testServer; - HttpConnector testProxy; - HttpConnector sslServer; - HttpProxyService proxy; - - public TestMain() { - init(); - } - - protected void init() { - testClient = HttpClient.newClient(); - } - - /** - * A single instance used for all tests. - */ - public static TestMain shared() { - if (defaultServer == null) { - defaultServer = new TestMain(); - defaultServer.run(); - } - return defaultServer; - } - - public static HttpConnector getTestServer() { - return shared().testServer; - } - - public HttpConnector getClient() { - return shared().testClient; - } - - public static BaseMapper.Context initTestContext(Dispatcher d) throws IOException { - BaseMapper.Context mCtx = d.addContext(null, "", null, null, null, null); - - mCtx.addWrapper("/", new StaticContentService() - .setContentType("text/html") - .setData("Client pool
    " + - "Server pool
    " + - "Proxy pool
    " + - "")); - - mCtx.addWrapper("/favicon.ico", - new StaticContentService().setStatus(404).setData("Not found")); - - mCtx.addWrapper("/hello", new StaticContentService().setData("Hello world")); - mCtx.addWrapper("/2nd", new StaticContentService().setData("Hello world2")); - mCtx.addWrapper("/echo/*", new EchoCallback()); - - mCtx.addWrapper("/sleep/1", new SleepCallback().setData("sleep 1")); - mCtx.addWrapper("/sleep/10", new SleepCallback().sleep(10000).setData( - "sleep 1")); - - mCtx.addWrapper("/chunked/*", new StaticContentService().setData("AAAA") - .chunked()); - mCtx.addWrapper("/helloClose", new HttpService() { - @Override - public void service(HttpRequest httpReq, HttpResponse httpRes) - throws IOException { - httpRes.setHeader("Connection", "close"); - httpRes.getBodyWriter().write("Hello"); - } - }); - return mCtx; - } - - public void initTestCallback(Dispatcher d) throws IOException { - BaseMapper.Context mCtx = initTestContext(d); - mCtx.addWrapper("/proc/cpool/client", new IOStatus(testClient.cpool)); - mCtx.addWrapper("/proc/cpool/proxy", new IOStatus(testProxy.cpool)); - mCtx.addWrapper("/proc/cpool/server", new IOStatus(testServer.cpool)); - } - - public void run() { - try { - startAll(); - // TODO(costin): clean up - // Hook in JMX and debug properties - try { - Class c = Class.forName("org.apache.tomcat.lite.TomcatLiteJmx"); - Constructor constructor = c.getConstructor(TestMain.class); - constructor.newInstance(this); - } catch (Throwable t) { - // ignore - } - } catch (Throwable t) { - t.printStackTrace(); - } - } - - public static String findDir(String dir) { - String path = "."; - for (int i = 0; i < 5; i++) { - File f = new File(path + dir); - if (f.exists()) { - try { - return f.getCanonicalPath(); - } catch (IOException e) { - return f.getAbsolutePath(); - } - } - path = path + "/.."; - } - return null; - } - - public int getServerPort() { - return 8802; - } - - public int getProxyPort() { - return 8903; - } - - public int getSslServerPort() { - return 8443; - } - - static String PRIVATE_KEY = - "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALsz2milZGHliWte61TfMTSwpAdq" + -"9uJkMTqgpSVtwxxOe8kT84QtIzhdAsQYjRz9ZtQn9DYWhJQs/cs/R3wWsjWwgiFHLzGalvsmMYJ3" + -"vBO8VMj762fAWu7GjUApIXcxMJoK4sQUpZKbqTuXpwzVUeeqBcspsIDgOLCo233G7/fBAgMBAAEC" + -"gYAWEaDX4VeaKuMuYzw+/yjf20sbDMMaIVGkZbfSV8Q+nAn/xHhaxq92P5DJ6VMJbd4neKZTkggD" + -"J+KriUQ2Hr7XXd/nM+sllaDWGmUnMYFI4txaNkikMA3ZyE/Xa79eDpTnSst8Nm11vrX9oF/hDNo4" + -"dhbU1krjAwVl/WijzSk4gQJBANvSmsmdjPlzvGNE11Aq3Ffb9/SqAOdE8NevMFeVKtBEKHIe1WlO" + -"ThRyWv3I8bUKTQMNULruSFVghTh6Hkt/CBkCQQDaAuxaXjv2voYozkOviXMpt0X5LZJMQu2gFc2x" + -"6UgBqYP2pNGDdRVWpbxF65PpXcLNKllCss2WB8i8kdeixYHpAkEAnIrzfia7sR2RiCQLLWUIe20D" + -"vHGgqRG4bfCtfYGV9rDDGNoKYq7H/dmeIOML9kA6rbS6zBRK4LoWxSx6DIuPaQJAL2c3USbwTuR6" + -"c2D2IrL2UXnCQz3/c4mR9Z8IDMk2mPXs9bI8xCKvMxnyaBmjHbj/ZHDy26fZP+gNY8MqagAcEQJA" + -"SidPwFV6cO8LCIA43wSVHlKZt4yU5wa9EWfzqVZxj7VSav7431kuxktW/YlwwxO4Pn8hgpPqD+W1" + -"E+Ssocxi8A=="; - - static String CERTIFICATE = "-----BEGIN CERTIFICATE-----\n" + -"MIIC5DCCAk2gAwIBAgIJAMa8ioWQMpEZMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV" + -"BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEChMJbG9jYWxob3N0MRIwEAYDVQQL" + -"Ewlsb2NhbGhvc3QxEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0xMDAyMjYyMzIxNDBa" + -"Fw0xMTAyMjYyMzIxNDBaMFYxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTESMBAG" + -"A1UEChMJbG9jYWxob3N0MRIwEAYDVQQLEwlsb2NhbGhvc3QxEjAQBgNVBAMTCWxv" + -"Y2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuzPaaKVkYeWJa17r" + -"VN8xNLCkB2r24mQxOqClJW3DHE57yRPzhC0jOF0CxBiNHP1m1Cf0NhaElCz9yz9H" + -"fBayNbCCIUcvMZqW+yYxgne8E7xUyPvrZ8Ba7saNQCkhdzEwmgrixBSlkpupO5en" + -"DNVR56oFyymwgOA4sKjbfcbv98ECAwEAAaOBuTCBtjAdBgNVHQ4EFgQUj3OnBK8R" + -"UN2CcmPvfQ1/IBeFwn8wgYYGA1UdIwR/MH2AFI9zpwSvEVDdgnJj730NfyAXhcJ/" + -"oVqkWDBWMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAoTCWxvY2Fs" + -"aG9zdDESMBAGA1UECxMJbG9jYWxob3N0MRIwEAYDVQQDEwlsb2NhbGhvc3SCCQDG" + -"vIqFkDKRGTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAKcJWWZbHRuG" + -"77ir1ETltxNIsAFvuhDD6E68eBwpviWfKhFxiOdD1vmAGqWWDYpmgORBGxFMZxTq" + -"c82iSbM0LseFeHwxAfeNXosSShMFtQzKt2wKZLLQB/Oqrea32m4hU//NP8rNbTux" + -"dcAHeNQEDB5EUUSewAlh+fUE6HB6c8j0\n" + -"-----END CERTIFICATE-----\n\n"; - - protected synchronized void startAll() throws IOException { - if (init) { - System.err.println("2x init ???"); - } else { - init = true; - boolean debug = false; - if (debug) { - System.setProperty("javax.net.debug", "ssl"); - System.setProperty("jsse", "conn_state,alert,engine,record,ssocket,socket,prf"); - Logger.getLogger("SSL").setLevel(Level.FINEST); - testClient.setDebug(true); - testClient.setDebugHttp(true); - } - - proxy = new HttpProxyService() - .withHttpClient(testClient); - testProxy = HttpServer.newServer(getProxyPort()); - - if (debug) { - testProxy.setDebugHttp(true); - testProxy.setDebug(true); - } - - // dispatcher rejects 'http://' - testProxy.setHttpService(proxy); - try { - testProxy.start(); - } catch (IOException e) { - e.printStackTrace(); - } - - testServer = HttpServer.newServer(getServerPort()); - if (debug) { - testServer.setDebugHttp(true); - testServer.setDebug(true); - } - initTestCallback(testServer.getDispatcher()); - try { - testServer.start(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - -// Base64 b64 = new Base64(); -// byte[] keyBytes = b64.decode(PRIVATE_KEY); - - sslServer = HttpServer.newSslServer(getSslServerPort()); - - if (debug) { - sslServer.setDebug(true); - sslServer.setDebugHttp(true); - } - JsseSslProvider sslCon = (JsseSslProvider) sslServer.getSslProvider(); - - sslCon = sslCon - .setKeyRes("org/apache/tomcat/lite/http/genrsa_512.cert", - "org/apache/tomcat/lite/http/genrsa_512.der"); - initTestCallback(sslServer.getDispatcher()); - sslServer.start(); - } - - Runtime.getRuntime().addShutdownHook(new Thread() { - public void run() { - System.err.println("Done"); - } - public void start() { - System.err.println("Done1"); - } - }); - } - - /** - * Blocking get, returns when the body has been read. - */ - public static BBuffer get(String url) throws IOException { - - BBuffer out = BBuffer.allocate(); - - HttpRequest aclient = HttpClient.newClient().request(url); - aclient.send(); - aclient.readAll(out, - //Long.MAX_VALUE);// - 2000000); - aclient.release(); // return connection to pool - return out; - } - - public static BBuffer getUrl(String path) throws IOException { - BBuffer out = BBuffer.allocate(); - getUrl(path, out); - return out; - } - - public static HttpURLConnection getUrl(String path, - BBuffer out) throws IOException { - URL url = new URL(path); - HttpURLConnection connection = - (HttpURLConnection) url.openConnection(); - connection.setReadTimeout(10000); - connection.connect(); - int rc = connection.getResponseCode(); - InputStream is = connection.getInputStream(); - BufferedInputStream bis = new BufferedInputStream(is); - byte[] buf = new byte[2048]; - int rd = 0; - while((rd = bis.read(buf)) > 0) { - out.append(buf, 0, rd); - } - return connection; - } - - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/ClientTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/ClientTest.java deleted file mode 100644 index 66c51fd0474d..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/ClientTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.io.BufferedReader; -import java.io.IOException; - -import org.apache.tomcat.lite.TestMain; - -import junit.framework.TestCase; - -/** - * Examples and tests for Tomcat-lite in client mode. - * - */ -public class ClientTest extends TestCase { - - /** - * All connectors created this way will share a single - * IO thread. Each connector will have its keep-alive - * pool - so it's better to share them. - * - * Since I want to test keep-alive works, I use a static one - */ - static HttpConnector httpCon = HttpClient.newClient(); - - /** - * Start a http server, runs on 8802 - shared by all tests. - * Will use /echo handler. - */ - static HttpConnector testServer = TestMain.getTestServer(); - - - public void testSimpleBlocking() throws IOException { - HttpRequest req = httpCon.request("http://localhost:8802/echo/test1"); - HttpResponse res = req.waitResponse(); - - assertEquals(200, res.getStatus()); - //assertEquals("", res.getHeader("")); - - BufferedReader reader = res.getReader(); - String line1 = reader.readLine(); - assertEquals("REQ HEAD:", line1); - } - - public void testSimpleCallback() throws IOException { - - } - - public void testGetParams() throws IOException { - } - - public void testPostParams() throws IOException { - } - - public void testPostBody() throws IOException { - } - - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/CompressFilterTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/CompressFilterTest.java deleted file mode 100644 index 23666c2ae126..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/CompressFilterTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.util.Random; - -import junit.framework.TestCase; - -import org.apache.tomcat.lite.io.IOBuffer; - -public class CompressFilterTest extends TestCase { - - CompressFilter cf = new CompressFilter(); - - private void check(String clear, String xtra) throws Exception { - IOBuffer in = new IOBuffer(); - IOBuffer out = new IOBuffer(); - - in.append(clear); - in.close(); - - cf.compress(in, out); - -// BBuffer bb = out.copyAll(null); -// String hd = Hex.getHexDump(bb.array(), bb.position(), -// bb.remaining(), true); -// System.err.println(hd); - - if (xtra != null) { - out.append(xtra); - } - in.recycle(); - out.close(); - cf.decompress(out, in); - - assertEquals(in.copyAll(null).toString(), clear); - assertTrue(in.isAppendClosed()); - - if (xtra != null) { - assertEquals(out.copyAll(null).toString(), xtra); - } - } - - public void test1() throws Exception { - check("X1Y2Z3", null); - } - - public void testXtra() throws Exception { - check("X1Y2Z3", "GET /"); - } - - public void testLarge() throws Exception { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < 2 * 1024; i++) { - sb.append("0123456789012345"); - } - check(sb.toString(), null); - } - - public void testLarge10() throws Exception { - for (int i = 0; i < 10; i++) { - testLargeIn(); - cf.recycle(); - } - } - - public void testLargeIn() throws Exception { - StringBuffer sb = new StringBuffer(); - Random r = new Random(); - for (int i = 0; i < 16 * 2 * 1024; i++) { - sb.append(' ' + r.nextInt(32)); - } - check(sb.toString(), null); - } - - - public void testSpdy() throws Exception { - cf.setDictionary(SpdyConnection.SPDY_DICT, SpdyConnection.DICT_ID); - check("connection: close\n", null); - } - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/DispatcherTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/DispatcherTest.java deleted file mode 100644 index 6c90bcaaaf57..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/DispatcherTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import org.apache.tomcat.lite.io.CBuffer; - -import junit.framework.TestCase; - -public class DispatcherTest extends TestCase { - - public void testMapper() throws Exception { - BaseMapper mapper = new BaseMapper(); - - String[] welcomes = new String[2]; - welcomes[0] = "index.html"; - welcomes[1] = "foo.html"; - - mapper.addContext("test1.com", "", "context0", new String[0], null, null); - mapper.addContext("test1.com", "/foo", "context1", new String[0], null, null); - mapper.addContext("test1.com", "/foo/bar", "context2", welcomes, null, null); - mapper.addContext("test1.com", "/foo/bar/bla", "context3", new String[0], null, null); - - mapper.addWrapper("test1.com", "/foo/bar", "/fo/*", "wrapper0"); - mapper.addWrapper("test1.com", "/foo/bar", "/", "wrapper1"); - mapper.addWrapper("test1.com", "/foo/bar", "/blh", "wrapper2"); - mapper.addWrapper("test1.com", "/foo/bar", "*.jsp", "wrapper3"); - mapper.addWrapper("test1.com", "/foo/bar", "/blah/bou/*", "wrapper4"); - mapper.addWrapper("test1.com", "/foo/bar", "/blah/bobou/*", "wrapper5"); - mapper.addWrapper("test1.com", "/foo/bar", "*.htm", "wrapper6"); - - mapper.addContext("asdf.com", "", "context0", new String[0], null, null); - - MappingData mappingData = new MappingData(); - - CBuffer host = CBuffer.newInstance(); - host.set("test1.com"); - - CBuffer uri = CBuffer.newInstance(); - uri.set("/foo/bar/blah/bobou/foo"); - - mapper.map(host, uri, mappingData); - - assertEquals("context2", mappingData.context.toString()); - assertEquals("/foo/bar", mappingData.contextPath.toString()); - } -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpChannelInMemoryTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpChannelInMemoryTest.java deleted file mode 100644 index 59b89cba0b9b..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpChannelInMemoryTest.java +++ /dev/null @@ -1,384 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.io.BufferedReader; -import java.io.IOException; - -import junit.framework.TestCase; - -import org.apache.tomcat.lite.http.HttpChannel.HttpService; -import org.apache.tomcat.lite.http.HttpChannel.RequestCompleted; -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.CBuffer; -import org.apache.tomcat.lite.io.IOBuffer; -import org.apache.tomcat.lite.io.IOChannel; -import org.apache.tomcat.lite.io.IOConnector; -import org.apache.tomcat.lite.io.MemoryIOConnector; -import org.apache.tomcat.lite.io.MemoryIOConnector.MemoryIOChannel; - -// TODO: rename to Http11ConnectionTest -public class HttpChannelInMemoryTest extends TestCase { - /** - * Connection under test - */ - Http11Connection conn; - - /** - * Last http channel created by the connection - */ - volatile HttpChannel http; - - // Input/output for the connection - MemoryIOConnector.MemoryIOChannel net = new MemoryIOChannel(); - - HttpConnector serverConnector = new HttpConnector(null); - - // Callback results for callback tests - boolean hasBody = false; - boolean bodyDone = false; - boolean bodySentDone = false; - boolean headersDone = false; - boolean allDone = false; - - public void setUp() throws IOException { - // Requests will not be serviced - you must manually generate - // the response. - serverConnector.setHttpService(null); - - conn = new Http11Connection(serverConnector) { - protected HttpChannel checkHttpChannel() throws IOException { - return http = super.checkHttpChannel(); - } - }.serverMode(); - conn.setSink(net); - } - - - public void test2Req() throws IOException { - String req = "GET /index.html?q=b&c=d HTTP/1.1\r\n" + - "Host: Foo.com \n" + - "H2:Bar\r\n" + - "H3: Foo \r\n" + - " Bar\r\n" + - "H4: Foo\n" + - " Bar\n" + - "\r\n" + - "HEAD /r2? HTTP/1.1\n" + - "Host: Foo.com\r\n" + - "H3: Foo \r\n" + - " Bar\r\n" + - "H4: Foo\n" + - " Bar\n" + - "\r\n"; - net.getIn().append(req); - - //http = lastServer.get(0); - assertTrue(http.getRequest().method().equals("GET")); - assertTrue(http.getRequest().protocol().equals("HTTP/1.1")); - assertEquals(http.getRequest().getMimeHeaders().size(), 4); - assertEquals(http.getRequest().getMimeHeaders().getHeader("Host").toString(), - "Foo.com"); - assertEquals(http.getRequest().getMimeHeaders().getHeader("H2").toString(), - "Bar"); - - http.getOut().append("Response1"); - http.getOut().close(); - http.startSending(); - http.release(); - - // now second response must be in. - // the connector will create a new http channel - - //http = lastServer.get(1); - - assertTrue(http.getRequest().method().equals("HEAD")); - assertTrue(http.getRequest().protocol().equals("HTTP/1.1")); - assertTrue(http.getRequest().getMimeHeaders().size() == 3); - assertTrue(http.getRequest().getMimeHeaders().getHeader("Host") - .equals("Foo.com")); - } - - public void testHttp11Close() throws IOException { - String req = "GET /index.html?q=b&c=d HTTP/1.1\r\n" + - "Host: Foo.com\n" + - "Connection: close\n" + - "\n"; - net.getIn().append(req); - - assertTrue(http.getRequest().method().equals("GET")); - assertTrue(http.getRequest().protocol().equals("HTTP/1.1")); - - http.getOut().append("Response1"); - http.getOut().close(); - http.startSending(); - http.release(); - - assertTrue(net.out.indexOf("connection:close") > 0); - assertFalse(net.isOpen()); - } - - public void testHttp10Close() throws IOException { - String req = "GET /index.html?q=b&c=d HTTP/1.0\r\n" + - "Host: Foo.com \n" + - "\r\n"; - net.getIn().append(req); - - assertTrue(http.getRequest().method().equals("GET")); - assertTrue(http.getRequest().protocol().equals("HTTP/1.0")); - - http.getOut().append("Response1"); - http.getOut().close(); - http.startSending(); - - assertTrue(net.out.indexOf("connection:close") > 0); - assertFalse(net.isOpen()); - } - - public void testHttp10KA() throws IOException { - String req = "GET /index.html?q=b&c=d HTTP/1.0\r\n" + - "Connection: Keep-Alive\n" + - "Host: Foo.com \n" + - "\r\n"; - net.getIn().append(req); - - assertTrue(http.getRequest().method().equals("GET")); - assertTrue(http.getRequest().protocol().equals("HTTP/1.0")); - - http.getOut().append("Hi"); - http.getOut().close(); - http.startSending(); - - // after request - assertEquals(conn.activeHttp, null); - - assertTrue(net.out.indexOf("connection:keep-alive") > 0); - assertTrue(net.isOpen()); - // inserted since we can calculate the response - assertEquals(http.getResponse().getHeader("Content-Length"), - "2"); - } - - public void testHttp10KANoCL() throws IOException { - String req = "GET /index.html?q=b&c=d HTTP/1.0\r\n" + - "Connection: Keep-Alive\n" + - "Host: Foo.com \n" + - "\r\n"; - net.getIn().append(req); - - assertTrue(http.getRequest().method().equals("GET")); - assertTrue(http.getRequest().protocol().equals("HTTP/1.0")); - - http.getOut().append("Hi"); - http.startSending(); - - http.getOut().append("After"); - http.getOut().close(); - http.startSending(); - - // after request - assertEquals(conn.activeHttp, null); - - assertFalse(net.out.indexOf("connection:keep-alive") > 0); - assertFalse(net.isOpen()); - // inserted since we can calculate the response - assertEquals(http.getResponse().getHeader("Content-Length"), - null); - assertEquals(http.getResponse().getHeader("Transfer-Encoding"), - null); - } - - public void testMultiLineHead() throws IOException { - net.getIn().append("GET / HTTP/1.0\n" + - "Cookie: 1234\n" + - " 456 \n" + - "Connection: Close\n\n"); - net.getIn().close(); - - MultiMap headers = http.getRequest().getMimeHeaders(); - CBuffer cookie = headers.getHeader("Cookie"); - CBuffer conn = headers.getHeader("Connection"); - assertEquals(conn.toString(), "close"); - assertEquals(cookie.toString(), "1234 456"); - - assertEquals(http.conn.headRecvBuf.toString(), - "GET / HTTP/1.0\n" + - "Cookie: 1234 456 \n" + // \n -> trailing space - "Connection: Close\n\n"); - } - - public void testCloseSocket() throws IOException { - net.getIn().append("GET / HTTP/1.1\n" - + "Host: localhost\n" - + "\n"); - assertTrue(((Http11Connection)http.conn).keepAlive()); - - net.getIn().close(); - assertFalse(((Http11Connection)http.conn).keepAlive()); - } - - public void test2ReqByte2Byte() throws IOException { - String req = "GET /index.html?q=b&c=d HTTP/1.1\r\n" + - "Host: Foo.com \n" + - "H2:Bar\r\n" + - "H3: Foo \r\n" + - " Bar\r\n" + - "H4: Foo\n" + - " Bar\n" + - "\r\n" + - "HEAD /r2? HTTP/1.1\n" + - "Host: Foo1.com\n" + - "H3: Foo \r\n" + - " Bar\r\n" + - "\r\n"; - for (int i = 0; i < req.length(); i++) { - net.getIn().append(req.charAt(i)); - } - - assertTrue(http.getRequest().method().equals("GET")); - assertTrue(http.getRequest().protocol().equals("HTTP/1.1")); - assertTrue(http.getRequest().getMimeHeaders().size() == 4); - assertTrue(http.getRequest().getMimeHeaders().getHeader("Host") - .equals("Foo.com")); - - // send a response - http.sendBody.append("Response1"); - http.getOut().close(); - - http.startSending(); // This will trigger a pipelined request - - http.release(); // now second response must be in - - assertTrue(http.getRequest().method().equals("HEAD")); - assertTrue(http.getRequest().protocol().equals("HTTP/1.1")); - assertTrue(http.getRequest().getMimeHeaders().size() == 2); - assertTrue(http.getRequest().getMimeHeaders().getHeader("Host") - .equals("Foo1.com")); - - // send a response - service method will be called - http.sendBody.append("Response2"); - http.getOut().close(); - http.release(); // now second response must be in - - - } - - public void testEndWithoutFlushCallbacks() throws IOException { - - net.getIn().append(POST); - - net.getIn().close(); - http.setCompletedCallback(new RequestCompleted() { - public void handle(HttpChannel data, Object extra) - throws IOException { - allDone = true; - } - }); - - http.sendBody.queue("Hi"); - http.getOut().close(); - http.startSending(); // will call handleEndSend - - assertTrue(allDone); - - } - - public void testCallbacks() throws IOException { - // already accepted - will change - serverConnector.setHttpService(new HttpService() { - public void service(HttpRequest httpReq, HttpResponse httpRes) - throws IOException { - - headersDone = true; - HttpChannel http = httpReq.getHttpChannel(); - - http.setCompletedCallback(new RequestCompleted() { - public void handle(HttpChannel data, Object extra) - throws IOException { - allDone = true; - } - }); - http.setDataReceivedCallback(new IOConnector.DataReceivedCallback() { - @Override - public void handleReceived(IOChannel ch) throws IOException { - if (ch.getIn().isAppendClosed()) { - bodyDone = true; - } - } - }); - http.setDataFlushedCallback(new IOConnector.DataFlushedCallback() { - @Override - public void handleFlushed(IOChannel ch) throws IOException { - if (ch.getOut().isAppendClosed()) { - bodySentDone = true; - } - } - }); - } - }); - - // Inject the request - net.getIn().append("POST / HTTP/1.0\n" + - "Connection: Close\n" + - "Content-Length: 4\n\n" + - "1"); - assertTrue(headersDone); - net.getIn().append("234"); - - net.getIn().close(); - assertTrue(bodyDone); - - - http.sendBody.queue("Hi"); - http.getOut().close(); - http.startSending(); - assertTrue(bodySentDone); - - assertTrue(allDone); - - } - - public static String POST = "POST / HTTP/1.0\n" + - "Connection: Close\n" + - "Content-Length: 4\n\n" + - "1234"; - - public void testClose() throws IOException { - net.getIn().append(POST); - net.getIn().close(); - - IOBuffer receiveBody = http.receiveBody; - IOBuffer appData = receiveBody; - BBuffer res = BBuffer.allocate(1000); - appData.readAll(res); - - assertEquals(res.toString(), "1234"); - assertFalse(((Http11Connection)http.conn).keepAlive()); - - http.sendBody.queue(res); - http.getOut().close(); - http.startSending(); - - assertTrue(net.getOut().isAppendClosed()); - assertTrue(net.out.toString().indexOf("\n1234") > 0); - - } - - public void testReadLine() throws Exception { - net.getIn().append("POST / HTTP/1.0\n" + - "Content-Length: 28\n\n" + - "Line 1\n" + - "Line 2\r\n" + - "Line 3\r" + - "Line 4"); - net.getIn().close(); - - BufferedReader r = http.getRequest().getReader(); - assertEquals("Line 1", r.readLine()); - assertEquals("Line 2", r.readLine()); - assertEquals("Line 3", r.readLine()); - assertEquals("Line 4", r.readLine()); - assertEquals(null, r.readLine()); - - } -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpChannelTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpChannelTest.java deleted file mode 100644 index b49dea2af298..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpChannelTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.io.IOException; - -import junit.framework.TestCase; - -import org.apache.tomcat.lite.io.BBuffer; - -public class HttpChannelTest extends TestCase { - - HttpChannel ch = new HttpChannel().serverMode(true); - Http11Connection con = new Http11Connection(null).serverMode(); - HttpRequest req = ch.getRequest(); - - - BBuffer head = BBuffer.allocate(); - BBuffer line = BBuffer.wrapper(); - BBuffer name = BBuffer.wrapper(); - BBuffer value = BBuffer.wrapper(); - - BBuffer statusB = BBuffer.wrapper(); - BBuffer msgB = BBuffer.wrapper(); - BBuffer methodB = BBuffer.wrapper(); - BBuffer queryB = BBuffer.wrapper(""); - BBuffer requestB = BBuffer.wrapper(); - BBuffer protoB = BBuffer.wrapper(); - - BBuffer l7 = BBuffer.wrapper("GET \n"); - BBuffer l8 = BBuffer.wrapper("GET /\n"); - BBuffer l9 = BBuffer.wrapper("GET /a?b\n"); - BBuffer l10 = BBuffer.wrapper("GET /a?b HTTP/1.0\n"); - BBuffer l11 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b"); - BBuffer l12 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\n"); - - BBuffer f1 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\n\n"); - BBuffer f2 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\r\n\r\n"); - BBuffer f3 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\r\r"); - BBuffer f4 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\r\n\r"); - - public void reqTest(String lineS, String method, String req, - String qry, String proto) throws IOException { - BBuffer line = BBuffer.wrapper(lineS); - queryB.recycle(); - protoB.recycle(); - requestB.recycle(); - methodB.recycle(); - con.parseRequestLine(line, methodB, requestB, queryB, protoB); - assertEquals(proto, protoB.toString()); - assertEquals(req, requestB.toString()); - assertEquals(qry, queryB.toString()); - assertEquals(method, methodB.toString()); - } - - public void testParams() throws IOException { - MultiMap params = processQry("a=b&c=d"); - assertEquals("b", params.getString("a")); - } - - private MultiMap processQry(String qry) throws IOException { - BBuffer head = BBuffer.wrapper("GET /a?" + qry + " HTTP/1.0\n" + - "Host: a\n\n"); - con.parseMessage(ch, head); - MultiMap params = req.getParameters(); - return params; - } - - public void testParseReq() throws IOException { - reqTest("GET / HTTP/1.0", "GET", "/", "", "HTTP/1.0"); - reqTest("GET", "GET", "", "", ""); - reqTest("GET / HTTP/1.0", "GET", "/", "", "HTTP/1.0"); - reqTest("GET / HTTP/1.0", "GET", "/", "", "HTTP/1.0"); - reqTest("GET /?b HTTP/1.0", "GET", "/", "b", "HTTP/1.0"); - reqTest("GET ?a HTTP/1.0", "GET", "", "a", "HTTP/1.0"); - reqTest("GET a HTTP/1.0", "GET", "a", "", "HTTP/1.0"); - reqTest("GET a? HTTP/1.0", "GET", "a", "", "HTTP/1.0"); - } - - public void headTest(String headS, String expName, String expValue, - String expLine, String expRest) throws IOException { - head = BBuffer.wrapper(headS); - head.readLine(line); - con.parseHeader(ch, head, line, name, value); - - assertEquals(expName, name.toString()); - assertEquals(expValue, value.toString()); - - assertEquals(expLine, line.toString()); - assertEquals(expRest, head.toString()); - } - - public void testParseHeader() throws IOException { - headTest("a:b\n", "a", "b", "", ""); - headTest("a :b\n", "a", "b", "", ""); - headTest("a : b\n", "a", "b", "", ""); - headTest("a : b\n", "a", "b", "", ""); - headTest("a : b c \n", "a", "b c", "", ""); - headTest("a : b c\n", "a", "b c", "", ""); - headTest("a : b c\n", "a", "b c", "", ""); - headTest("a : b \n c\n", "a", "b c", "", ""); - headTest("a : b \n c\n", "a", "b c", "", ""); - headTest("a : b \n c\nd:", "a", "b c", "", "d:"); - - } - - public void responseTest(String lineS, String proto, String status, - String msg) throws IOException { - protoB.recycle(); - statusB.recycle(); - msgB.recycle(); - BBuffer line = BBuffer.wrapper(lineS); - con.parseResponseLine(line, - protoB, statusB, msgB); - assertEquals(proto, protoB.toString()); - assertEquals(status, statusB.toString()); - assertEquals(msg, msgB.toString()); - } - - public void testResponse() throws Exception { - responseTest("HTTP/1.1 200 OK", "HTTP/1.1", "200", "OK"); - responseTest("HTTP/1.1 200 OK", "HTTP/1.1", "200", "OK"); - responseTest("HTTP/1.1 200", "HTTP/1.1", "200", ""); - responseTest("HTTP/1.1", "HTTP/1.1", "", ""); - } - - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpsTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpsTest.java deleted file mode 100644 index 8ce9bc9bfcbe..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpsTest.java +++ /dev/null @@ -1,74 +0,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.lite.http; - -import junit.framework.TestCase; - -import org.apache.tomcat.lite.TestMain; -import org.apache.tomcat.lite.io.BBuffer; - -public class HttpsTest extends TestCase { - - static int port = 8443; - - public void testSimpleClient() throws Exception { - final HttpConnector httpClient = TestMain.shared().getClient(); - checkResponse(httpClient); - } - - public void testSimpleServer() throws Exception { - final HttpConnector httpClient = TestMain.shared().getClient(); - BBuffer res = TestMain.getUrl("https://localhost:8443/hello"); - assertTrue(res.toString().indexOf("Hello") >= 0); - } - - - private void checkResponse(HttpConnector httpCon) throws Exception { - HttpRequest ch = httpCon.request("localhost", port).setSecure(true); - - ch.setRequestURI("/hello"); - ch.setProtocol("HTTP/1.0"); // to force close - ch.send(); - BBuffer res = ch.readAll(); - - assertTrue(res.toString().indexOf("Hello") >= 0); - } - - public void testSimpleClient20() throws Exception { - final HttpConnector httpClient = TestMain.shared().getClient(); - for (int i = 0; i < 10; i++) { - checkResponse(httpClient); - } - } - - public void testSimpleRequestGoogle() throws Exception { - for (int i = 0; i < 40; i++) { - final HttpConnector httpClient = TestMain.shared().getClient(); - HttpRequest client = httpClient.request("www.google.com", 443). - setSecure(true); - client.getHttpChannel().setIOTimeout(2000000); - client.setRequestURI("/accounts/ServiceLogin"); - client.send(); - - BBuffer res = client.readAll(); - assertTrue(res.toString().indexOf("Google Accounts") > 0); - } - } - - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/LiveHttp1Test.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/LiveHttp1Test.java deleted file mode 100644 index 4d30843c3fcc..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/LiveHttp1Test.java +++ /dev/null @@ -1,152 +0,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.lite.http; - -import java.io.IOException; - -import junit.framework.TestCase; - -import org.apache.tomcat.lite.TestMain; -import org.apache.tomcat.lite.io.BBuffer; - -public class LiveHttp1Test extends TestCase { - // Proxy tests extend this class, run same tests via proxy on 8903 - protected int clientPort = 8802; - - HttpRequest httpReq; - - BBuffer bodyRecvBuffer = BBuffer.allocate(1024); - - int to = 1000000; - - public void setUp() throws IOException { - // DefaultHttpConnector.get().setDebug(true); - // DefaultHttpConnector.get().setDebugHttp(true); - TestMain.getTestServer(); - - httpReq = HttpClient.newClient().request("localhost", - clientPort); - - bodyRecvBuffer.recycle(); - } - - public void tearDown() throws Exception { - if (httpReq != null) { - httpReq.release(); // async - httpReq = null; - } - } - - public void testSimpleRequest() throws Exception { - httpReq.requestURI().set("/hello"); - - httpReq.send(); - httpReq.readAll(bodyRecvBuffer, to); - assertEquals("Hello world", bodyRecvBuffer.toString()); - } - - public void testSimpleRequestClose() throws Exception { - httpReq.requestURI().set("/hello"); - httpReq.setHeader("Connection", "close"); - - httpReq.send(); - httpReq.readAll(bodyRecvBuffer, to); - assertEquals("Hello world", bodyRecvBuffer.toString()); - } - - public void testPoolGetRelease() throws Exception { - HttpConnector con = HttpClient.newClient(); - con.setMaxHttpPoolSize(10); - HttpChannel httpCh = con.get("localhost", clientPort); - httpCh.release(); - - httpCh = con.get("localhost", clientPort); - httpCh.release(); - - httpCh = con.get("localhost", clientPort); - httpCh.release(); - - } - - public void testSimpleChunkedRequest() throws Exception { - httpReq.requestURI().set("/chunked/foo"); - httpReq.send(); - httpReq.readAll(bodyRecvBuffer, to); - assertTrue(bodyRecvBuffer.toString(), bodyRecvBuffer.toString().indexOf("AAA") >= 0); - } - - // Check waitResponseHead() - public void testRequestHead() throws Exception { - httpReq.requestURI().set("/echo/foo"); - - // Send the request, wait response - httpReq.send(); - - httpReq.readAll(bodyRecvBuffer, to); - assertTrue(bodyRecvBuffer.toString().indexOf("GET /echo/foo") > 0); - } - - public void test10() throws Exception { - for (int i = 0; i < 10; i++) { - testSimpleRequest(); - tearDown(); - setUp(); - - notFound(); - tearDown(); - setUp(); - - testSimpleRequest(); - tearDown(); - setUp(); - } - } - - public void notFound() throws Exception { - httpReq.requestURI().set("/foo"); - httpReq.send(); - httpReq.readAll(bodyRecvBuffer, to); - } - - // compression not implemented - public void testGzipRequest() throws Exception { - httpReq.requestURI().set("/hello"); - httpReq.setHeader("accept-encoding", - "gzip"); - - // Send the request, wait response - httpReq.send(); - // cstate.waitResponseHead(10000); // headers are received - // ByteChunk data = new ByteChunk(1024); - // acstate.serializeResponse(acstate.res, data); - - // System.err.println(bodyRecvBuffer.toString()); - - httpReq.readAll(bodyRecvBuffer, to); - // Done - } - - public void testWrongPort() throws Exception { - httpReq = HttpClient.newClient().request("localhost", 18904); - httpReq.requestURI().set("/hello"); - - httpReq.send(); - - httpReq.readAll(bodyRecvBuffer, to); - assertEquals(0, bodyRecvBuffer.remaining()); - } -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/MultiMapTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/MultiMapTest.java deleted file mode 100644 index 497f275c4213..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/MultiMapTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import org.apache.tomcat.lite.http.MultiMap.Entry; - -import junit.framework.TestCase; - -public class MultiMapTest extends TestCase { - - MultiMap map = new MultiMap(); - MultiMap lmap = new MultiMap().insensitive(); - - public void testAdd() { - map.add("foo", "bar"); - assertEquals("bar", map.get("foo").toString()); - } - - public void testRemove() { - map.add("foo", "bar"); - map.add("foo", "bar"); - map.add("foo1", "bar"); - assertEquals(3, map.count); - map.remove("foo"); - assertEquals(1, map.count); - } - - public void testRemove1() { - map.add("foo", "bar"); - map.add("foo1", "bar"); - map.add("foo", "bar"); - assertEquals(3, map.count); - map.remove("foo"); - assertEquals(1, map.count); - map.remove("foo1"); - assertEquals(0, map.count); - } - - public void testCase() { - lmap.add("foo", "bar1"); - lmap.add("Foo", "bar2"); - lmap.add("a", "bar3"); - lmap.add("B", "bar4"); - assertEquals(4, lmap.count); - assertEquals(3, lmap.map.size()); - - assertEquals("bar3", lmap.getString("a")); - assertEquals("bar3", lmap.getString("A")); - assertEquals("bar1", lmap.getString("Foo")); - Entry entry = lmap.getEntry("FOO"); - assertEquals(2, entry.values.size()); - } - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/SpdyTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/SpdyTest.java deleted file mode 100644 index 500201f3cd67..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/SpdyTest.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.http; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; - -import junit.framework.TestCase; - -import org.apache.tomcat.lite.TestMain; -import org.apache.tomcat.lite.http.HttpConnectionPool.RemoteServer; -import org.apache.tomcat.lite.io.IOBuffer; -import org.apache.tomcat.lite.io.SocketConnector; - -public class SpdyTest extends TestCase { - HttpConnector http11Con = TestMain.shared().getClient(); - - static HttpConnector spdyCon = HttpClient.newClient(); - - static HttpConnector spdyConSsl = HttpClient.newClient(); - - HttpConnector memSpdyCon = new HttpConnector(null); - - public void testClient() throws IOException { - HttpRequest req = - spdyCon.request("http://localhost:8802/echo/test1"); - - // Force SPDY - no negotiation - req.setProtocol("SPDY/1.0"); - - HttpResponse res = req.waitResponse(); - - assertEquals(200, res.getStatus()); - //assertEquals("", res.getHeader("")); - - BufferedReader reader = res.getReader(); - String line1 = reader.readLine(); - //assertEquals("", line1); - } - - public void testSslClient() throws IOException { - - HttpRequest req = - spdyConSsl.request("http://localhost:8443/echo/test1"); - // Enable SSL for the connection. - // TODO: this must be done on the first request, all will be - // encrypted. - req.setSecure(true); - // Force SPDY - no negotiation - req.setProtocol("SPDY/1.0"); - - HttpResponse res = req.waitResponse(); - - assertEquals(200, res.getStatus()); - //assertEquals("", res.getHeader("")); - - res.setReadTimeout(2000); - BufferedReader reader = res.getReader(); - String line1 = reader.readLine(); - //assertEquals("", line1); - } - - - // Initial frame generated by Chrome - public void testParse() throws IOException { - InputStream is = - getClass().getClassLoader().getResourceAsStream("org/apache/tomcat/lite/http/spdyreq0.bin"); - - IOBuffer iob = new IOBuffer(); - iob.append(is); - - SpdyConnection con = new SpdyConnection(memSpdyCon, new RemoteServer()); - - // By default it has a dispatcher buit-in - con.serverMode = true; - - con.dataReceived(iob); - - HttpChannel spdyChannel = con.channels.get(1); - - assertEquals(1, con.lastFrame.version); - assertEquals(1, con.lastFrame.type); - assertEquals(1, con.lastFrame.flags); - - assertEquals(417, con.lastFrame.length); - - // TODO: test req, headers - HttpRequest req = spdyChannel.getRequest(); - assertTrue(req.getHeader("accept").indexOf("application/xml") >= 0); - - } - - // Initial frame generated by Chrome - public void testParseCompressed() throws IOException { - InputStream is = - getClass().getClassLoader().getResourceAsStream("org/apache/tomcat/lite/http/spdyreqCompressed.bin"); - - IOBuffer iob = new IOBuffer(); - iob.append(is); - - SpdyConnection con = new SpdyConnection(memSpdyCon, new RemoteServer()); - - // By default it has a dispatcher buit-in - con.serverMode = true; - - con.dataReceived(iob); - - HttpChannel spdyChannel = con.channels.get(1); - - assertEquals(1, con.lastFrame.version); - assertEquals(1, con.lastFrame.type); - assertEquals(1, con.lastFrame.flags); - - // TODO: test req, headers - HttpRequest req = spdyChannel.getRequest(); - assertTrue(req.getHeader("accept").indexOf("application/xml") >= 0); - - } - - // Does int parsing works ? - public void testLargeInt() throws Exception { - - IOBuffer iob = new IOBuffer(); - iob.append(0x80); - iob.append(0x01); - iob.append(0xFF); - iob.append(0xFF); - - iob.append(0xFF); - iob.append(0xFF); - iob.append(0xFF); - iob.append(0xFF); - - SpdyConnection con = new SpdyConnection(memSpdyCon, new RemoteServer()); - con.dataReceived(iob); - assertEquals(1, con.currentInFrame.version); - assertEquals(0xFFFF, con.currentInFrame.type); - assertEquals(0xFF, con.currentInFrame.flags); - assertEquals(0xFFFFFF, con.currentInFrame.length); - - } - - // Does int parsing works ? - public void testBad() throws Exception { - - IOBuffer iob = new IOBuffer(); - iob.append(0xFF); - iob.append(0xFF); - iob.append(0xFF); - iob.append(0xFF); - - iob.append(0xFF); - iob.append(0xFF); - iob.append(0xFF); - iob.append(0xFF); - - SpdyConnection con = new SpdyConnection(memSpdyCon, new RemoteServer()); - con.dataReceived(iob); - - assertEquals(1, con.streamErrors.get()); - - } - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/genrsa_512.cert b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/genrsa_512.cert deleted file mode 100644 index 8b2235485a3c..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/genrsa_512.cert +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICXzCCAgmgAwIBAgIJAKl2huIxu+mhMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV -BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEChMJbG9jYWxob3N0MRIwEAYDVQQL -Ewlsb2NhbGhvc3QxEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0xMDAyMjgwNTM1NDVa -Fw0xMTAyMjgwNTM1NDVaMFYxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTESMBAG -A1UEChMJbG9jYWxob3N0MRIwEAYDVQQLEwlsb2NhbGhvc3QxEjAQBgNVBAMTCWxv -Y2FsaG9zdDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCkMTUYO8aijGGXIUTMRp3h -NTBudLHDF66MDQxomS+drL1sDGzpsLG1ltZcSPrp2Ak2tDVLd9eDb6VmddgyvE0N -AgMBAAGjgbkwgbYwHQYDVR0OBBYEFPfuRg3nOxppwBPdpOQTbjDbcPbEMIGGBgNV -HSMEfzB9gBT37kYN5zsaacAT3aTkE24w23D2xKFapFgwVjELMAkGA1UEBhMCVVMx -CzAJBgNVBAgTAkNBMRIwEAYDVQQKEwlsb2NhbGhvc3QxEjAQBgNVBAsTCWxvY2Fs -aG9zdDESMBAGA1UEAxMJbG9jYWxob3N0ggkAqXaG4jG76aEwDAYDVR0TBAUwAwEB -/zANBgkqhkiG9w0BAQUFAANBAFqvhtdEd1OKNZ2TbLeFJbvavSZUDd0d/vz+qZgh -L2Oe+CU/82D4lVpf52g4HFMrnEnAiJFuq1SwoNJZzlxk8kU= ------END CERTIFICATE----- diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/genrsa_512.der b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/genrsa_512.der deleted file mode 100644 index 75ef44938cd8..000000000000 Binary files a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/genrsa_512.der and /dev/null differ diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/services/EchoCallback.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/services/EchoCallback.java deleted file mode 100644 index 1c29ec492b41..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/services/EchoCallback.java +++ /dev/null @@ -1,61 +0,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.lite.http.services; - -import java.io.IOException; -import java.util.logging.Logger; - -import org.apache.tomcat.lite.http.Http11Connection; -import org.apache.tomcat.lite.http.HttpChannel; -import org.apache.tomcat.lite.http.HttpRequest; -import org.apache.tomcat.lite.http.HttpResponse; -import org.apache.tomcat.lite.http.HttpChannel.HttpService; -import org.apache.tomcat.lite.io.IOBuffer; - -/** - * Response is plain/text, copy of the received request - */ -public class EchoCallback implements HttpService { - Logger log = Logger.getLogger("coyote.static"); - - String contentType = "text/plain"; - - - public EchoCallback() { - } - - @Override - public void service(HttpRequest req, HttpResponse res) throws IOException { - HttpChannel sproc = req.getHttpChannel(); - res.setStatus(200); - res.setContentType(contentType); - - IOBuffer tmp = new IOBuffer(null); - Http11Connection.serialize(req, tmp); - - sproc.getOut().append("REQ HEAD:\n"); - sproc.getOut().append(tmp.readAll(null)); - IOBuffer reqBuf = sproc.getOut(); - - reqBuf.append("\nCONTENT_LENGTH:") - .append(Long.toString(req.getContentLength())) - .append("\n"); -// -// sproc.release(); - } - - -} \ No newline at end of file diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/services/SleepCallback.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/services/SleepCallback.java deleted file mode 100644 index 12657d1147ac..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/services/SleepCallback.java +++ /dev/null @@ -1,85 +0,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.lite.http.services; - -import java.io.IOException; - -import org.apache.tomcat.lite.http.HttpRequest; -import org.apache.tomcat.lite.http.HttpResponse; -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.proxy.StaticContentService; - -/** - * Test adapters that sleeps, for load test and for encoding. - * REQUIRES THREAD POOL - */ -public class SleepCallback extends StaticContentService { - long t1; - long t2; - long t3; - long t4; - - public SleepCallback() { - } - - public SleepCallback sleep(long t1, long t2, long t3, - long t4) { - this.t1 = t1; - this.t2 = t2; - this.t3 = t3; - this.t4 = t4; - return this; - } - - public SleepCallback sleep(long t1) { - return sleep(t1, t1, t1, t1); - } - - @Override - public void service(HttpRequest httpReq, HttpResponse res) throws IOException { - // TODO: blocking ! needs thread pool ! - try { - - Thread.currentThread().sleep(t1); - res.setStatus(200); - if (!chunked) { - res.setContentLength(mb.remaining() * 2); - } - res.setContentType(contentType); - - res.flush(); - - Thread.currentThread().sleep(t2); - - res.getBody().queue(BBuffer.wrapper(mb, 0, mb.remaining())); - res.flush(); - - //res.action(ActionCode.ACTION_CLIENT_FLUSH, res); - - Thread.currentThread().sleep(t3); - - res.getBody().queue(BBuffer.wrapper(mb, 0, mb.remaining())); - res.flush(); - - Thread.currentThread().sleep(t4); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - -} \ No newline at end of file diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/spdyreq0 b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/spdyreq0 deleted file mode 100644 index 4df3aa94a1e2..000000000000 Binary files a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/spdyreq0 and /dev/null differ diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/spdyreq0.bin b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/spdyreq0.bin deleted file mode 100644 index 4df3aa94a1e2..000000000000 Binary files a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/spdyreq0.bin and /dev/null differ diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/spdyreqCompressed b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/spdyreqCompressed deleted file mode 100644 index 3507ff91c189..000000000000 Binary files a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/spdyreqCompressed and /dev/null differ diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/spdyreqCompressed.bin b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/spdyreqCompressed.bin deleted file mode 100644 index 3507ff91c189..000000000000 Binary files a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/spdyreqCompressed.bin and /dev/null differ diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/BBufferTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/io/BBufferTest.java deleted file mode 100644 index ae02346f92a4..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/BBufferTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import org.apache.tomcat.lite.io.BBuffer; - -import junit.framework.TestCase; - -public class BBufferTest extends TestCase { - BBuffer res = BBuffer.wrapper(""); - - BBuffer l1 = BBuffer.wrapper(""); - BBuffer l1a = BBuffer.wrapper("a"); - - BBuffer l2 = BBuffer.wrapper("\r"); - BBuffer l3 = BBuffer.wrapper("\n"); - BBuffer l4 = BBuffer.wrapper("\r\n"); - BBuffer l5 = BBuffer.wrapper("\r\na"); - BBuffer l5_a = BBuffer.wrapper("\ra"); - BBuffer l5_b = BBuffer.wrapper("\na"); - BBuffer l6 = BBuffer.wrapper("a\n"); - BBuffer l7 = BBuffer.wrapper("GET \n"); - BBuffer l8 = BBuffer.wrapper("GET /\n"); - BBuffer l9 = BBuffer.wrapper("GET /a?b\n"); - BBuffer l10 = BBuffer.wrapper("GET /a?b HTTP/1.0\n"); - BBuffer l11 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b"); - BBuffer l12 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\n"); - - BBuffer f1 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\n\n"); - BBuffer f2 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\r\n\r\n"); - BBuffer f3 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\r\r"); - BBuffer f4 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\r\n\r"); - - BBuffer s1 = BBuffer.wrapper(" \n"); - BBuffer s2 = BBuffer.wrapper(" a"); - BBuffer s3 = BBuffer.wrapper(" "); - BBuffer s4 = BBuffer.wrapper(" a"); - - BBuffer h1 = BBuffer.wrapper("a"); - BBuffer h2 = BBuffer.wrapper("a?b"); - BBuffer h3 = BBuffer.wrapper("a b"); - - public void hashTest(String s) { - assertEquals(s.hashCode(), BBuffer.wrapper(s).hashCode()); - } - - public void testHash() { - hashTest(""); - hashTest("a"); - hashTest("123abc"); - hashTest("123abc\0"); - // Fails for UTF chars - only ascii hashTest("123abc\u12345;"); - } - - public void testReadToSpace() { - assertEquals(3, l8.readToSpace(res)); - assertEquals("GET", res.toString()); - assertEquals(" /\n", l8.toString()); - - assertEquals(0, l1.readToSpace(res)); - assertEquals("", res.toString()); - assertEquals("", l1.toString()); - } - - public void testReadToDelim() { - assertEquals(1, h1.readToDelimOrSpace((byte)'?', res)); - assertEquals("a", res.toString()); - assertEquals("", h1.toString()); - - assertEquals(1, h2.readToDelimOrSpace((byte)'?', res)); - assertEquals("a", res.toString()); - assertEquals("?b", h2.toString()); - - assertEquals(1, h3.readToDelimOrSpace((byte)'?', res)); - assertEquals("a", res.toString()); - assertEquals(" b", h3.toString()); - } - - public void testGet() { - assertEquals(0x20, s1.get(0)); - assertEquals(0x0a, s1.get(1)); - try { - s1.get(2); - } catch(ArrayIndexOutOfBoundsException ex) { - return; - } - fail("Exception"); - } - - public void testSkipSpace() { - assertEquals(1, s1.skipSpace()); - assertEquals("\n", s1.toString()); - - assertEquals(1, s2.skipSpace()); - assertEquals("a", s2.toString()); - - assertEquals(2, s3.skipSpace()); - assertEquals("", s3.toString()); - - assertEquals(3, s4.skipSpace()); - assertEquals("a", s4.toString()); - - assertEquals(0, l1.skipSpace()); - assertEquals("", l1.toString()); - } - - public void testLFLF() { - assertTrue(f1.hasLFLF()); - assertTrue(f2.hasLFLF()); - assertTrue(f3.hasLFLF()); - - assertFalse(f4.hasLFLF()); - assertFalse(l1.hasLFLF()); - assertFalse(l2.hasLFLF()); - assertFalse(l3.hasLFLF()); - - assertFalse(l10.hasLFLF()); - assertFalse(l11.hasLFLF()); - assertFalse(l12.hasLFLF()); - } - - public void testReadLine() { - assertEquals(-1, l1.readLine(res)); - assertEquals("", res.toString()); - assertEquals("", l1.toString()); - - assertEquals(-1, l1a.readLine(res)); - assertEquals("", res.toString()); - assertEquals("a", l1a.toString()); - - assertEquals(0, l2.readLine(res)); - assertEquals("", l2.toString()); - assertEquals("", res.toString()); - assertEquals(0, l3.readLine(res)); - assertEquals("", l3.toString()); - assertEquals("", res.toString()); - assertEquals(0, l4.readLine(res)); - assertEquals("", res.toString()); - - assertEquals(0, l5.readLine(res)); - assertEquals("", res.toString()); - assertEquals("a", l5.toString()); - assertEquals(0, l5_b.readLine(res)); - assertEquals("", res.toString()); - assertEquals("a", l5_b.toString()); - assertEquals(0, l5_a.readLine(res)); - assertEquals("", res.toString()); - assertEquals("a", l5_a.toString()); - - assertEquals(1, l6.readLine(res)); - assertEquals("a", res.toString()); - - assertEquals(4, l7.readLine(res)); - assertEquals("GET ", res.toString()); - assertEquals(5, l8.readLine(res)); - assertEquals("GET /", res.toString()); - - } -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/CBufferTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/io/CBufferTest.java deleted file mode 100644 index db0152c19251..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/CBufferTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import junit.framework.TestCase; - -public class CBufferTest extends TestCase { - - CBuffer ext = CBuffer.newInstance(); - - public void extTest(String path, String exp) { - CBuffer.newInstance().append(path).getExtension(ext, '/', '.'); - assertEquals(exp, ext.toString()); - } - - public void testExt() { - extTest("foo.jsp", "jsp"); - extTest("foo.j", "j"); - extTest("/foo.j", "j"); - extTest("//foo.j", "j"); - extTest(".j", "j"); - extTest(".", ""); - extTest("/abc", ""); - extTest("/abc.", ""); - extTest("/abc/", ""); - extTest("/abc/d", ""); - } - - public void testLastIndexOf() { - - } -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/OneTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/io/OneTest.java deleted file mode 100644 index 74470cd3f074..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/OneTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; - -import org.apache.tomcat.lite.TestMain; -import org.apache.tomcat.lite.http.HttpChannel; -import org.apache.tomcat.lite.io.MemoryIOConnector; -import org.apache.tomcat.lite.io.MemoryIOConnector.MemoryIOChannel; - -import junit.framework.TestCase; - -public class OneTest extends TestCase { - - public void setUp() throws Exception { - TestMain.getTestServer(); - } - - public void tearDown() throws IOException { - } - - - public void testOne() throws Exception { - - } -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/SocksTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/io/SocksTest.java deleted file mode 100644 index a1f9870a7b6b..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/SocksTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.ProxySelector; -import java.net.SocketAddress; -import java.net.URI; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.tomcat.lite.proxy.SocksServer; - - -import junit.framework.TestCase; - -public class SocksTest extends TestCase { - - public void setUp() { -// SocksServer socks = new SocksServer(); -// try { -// socks.initServer(); -// } catch (IOException e1) { -// // TODO Auto-generated catch block -// e1.printStackTrace(); -// } -// -// ProxySelector.setDefault(new ProxySelector() { -// -// @Override -// public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { -// } -// -// @Override -// public List select(URI uri) { -// -// List res = new ArrayList(); -// try { -// res.add(new Proxy(Proxy.Type.SOCKS, -// new InetSocketAddress(InetAddress.getLocalHost(), 1080))); -// } catch (UnknownHostException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } -// return res; -// } -// -// }); - } - - public void testSocks() { - - } -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/UEncoderTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/io/UEncoderTest.java deleted file mode 100644 index f48a61c61cb3..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/UEncoderTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.io; - -import junit.framework.TestCase; - - -public class UEncoderTest extends TestCase { - IOWriter enc=new IOWriter(null); - UrlEncoding dec = new UrlEncoding(); - CBuffer cc = CBuffer.newInstance(); - - /* - * - * Test method for 'org.apache.tomcat.util.buf.UEncoder.encodeURL(String)' - * TODO: find the relevant rfc and apache tests and add more - */ - public void testEncodeURL() { - - String eurl1=encodeURL("test"); - assertEquals("test", eurl1); - - eurl1=encodeURL("/test"); - assertEquals("/test", eurl1); - - // safe ranges - eurl1=encodeURL("test$-_."); - assertEquals("test$-_.", eurl1); - - eurl1=encodeURL("test$-_.!*'(),"); - assertEquals("test$-_.!*'(),", eurl1); - - eurl1=encodeURL("//test"); - assertEquals("//test", eurl1); - } - - public String encodeURL(String uri) { - cc.recycle(); - dec.urlEncode(uri, cc, enc); - return cc.toString(); - } - - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/test.properties b/modules/tomcat-lite/test/org/apache/tomcat/lite/io/test.properties deleted file mode 100644 index 19ee5e4afcf5..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/test.properties +++ /dev/null @@ -1,33 +0,0 @@ -RUN=Log,JMXProxy,Socks - -Log.(class)=org.apache.tomcat.integration.simple.LogConfig -Log.debug=org.apache.tomcat.async.AsyncHttpConnector -Log.debug=Proxy - -JMXProxy.(class)=org.apache.tomcat.integration.simple.JMXProxy -JMXProxy.port=8003 - -Socks.(class)=org.apache.tomcat.async.callbacks.SocksServer -Socks.port=2080 -Socks.idleTimeout=0 - -HttpConnector-TestServer.debug=true -#HttpConnector-TestServer.debugHttp=true -HttpConnector-TestServer.clientKeepAlive=true -HttpConnector-TestServer.serverKeepAlive=true -HttpConnector-TestServer.maxHttpPoolSize=10 - -HttpConnector.debug=true -#HttpConnector.debugHttp=true -HttpConnector.clientKeepAlive=true -HttpConnector.serverKeepAlive=true -HttpConnector.maxHttpPoolSize=10 - -HttpConnector-Proxy.debug=true -#HttpConnector-Proxy.debugHttp=true -HttpConnector-Proxy.clientKeepAlive=true -HttpConnector-Proxy.serverKeepAlive=true -HttpConnector-Proxy.maxHttpPoolSize=10 - - -#IOConnector.debug=true diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/load/LiveHttp5Test.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/load/LiveHttp5Test.java deleted file mode 100644 index 3bcdb74c1352..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/load/LiveHttp5Test.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.load; - -import org.apache.tomcat.lite.http.LiveHttp1Test; - -import junit.framework.TestSuite; - -public class LiveHttp5Test extends LiveHttp1Test { - - /** - * Want to run the same tests few times. - */ - public static TestSuite suite() { - TestSuite s = new TestSuite(); - for (int i = 0; i < 5; i++) { - s.addTestSuite(LiveHttp1Test.class); - } - return s; - } - - public void test100() throws Exception { - for (int i = 0; i < 100; i++) { - testSimpleRequest(); - tearDown(); - setUp(); - - notFound(); - tearDown(); - setUp(); - - testSimpleRequest(); - tearDown(); - setUp(); - } - } - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/load/LiveHttpThreadedTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/load/LiveHttpThreadedTest.java deleted file mode 100644 index 2e8ef071ca21..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/load/LiveHttpThreadedTest.java +++ /dev/null @@ -1,292 +0,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.lite.load; - - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import junit.framework.TestCase; - -import org.apache.tomcat.lite.TestMain; -import org.apache.tomcat.lite.http.HttpClient; -import org.apache.tomcat.lite.http.HttpChannel; -import org.apache.tomcat.lite.http.HttpConnector; -import org.apache.tomcat.lite.http.HttpRequest; -import org.apache.tomcat.lite.http.HttpChannel.RequestCompleted; -import org.apache.tomcat.lite.io.BBuffer; -import org.apache.tomcat.lite.io.SocketConnector; - -/* - Notes on memory use ( from heap dumps ): - - buffers are not yet recycled ( the BBuffers used in channels ) - - - each active connection consumes at least 26k - 2 buffers + head buffer - ( 8k each ) - TODO: could 'peak' in the In buffer and move headRecv to HttpChannel - - - - HttpChannel keeps about 64K ( for the hello world ). - -- res is 25k - -- req is 32k, BufferedIOReader 16k, - - TODO: - - leak in NioThread.active - closed sockets not removed - - need to rate-limit and queue requests - OOM - - timeouts - - seems few responses missing on large async requests (URL works) - */ - -/** - * Long running test - async tests are failing since rate control - * is not implemented ( too many outstanding requests - OOM ), - * it seems there is a bug as well. - */ -public class LiveHttpThreadedTest extends TestCase { - HttpConnector clientCon = TestMain.shared().getClient(); - HttpConnector serverCon = TestMain.shared().getTestServer(); - - HttpConnector spdyClient = - HttpClient.newClient().setCompression(false); - - HttpConnector spdyClientCompress = - HttpClient.newClient(); - - HttpConnector spdyClientCompressSsl = - HttpClient.newClient(); - - ThreadRunner tr; - static boolean dumpHeap = true; - - AtomicInteger ok = new AtomicInteger(); - int reqCnt; - - Map active = new HashMap(); - - public void tearDown() throws IOException { - clientCon.cpool.clear(); - } - - public void test1000Async() throws Exception { -// try { - asyncRequest(10, 100, false, false, clientCon, "AsyncHttp"); -// } finally { -// dumpHeap("heapAsync.bin"); -// } - - } - - public void test10000Async() throws Exception { - asyncRequest(20, 500, false, false, clientCon, "AsyncHttp"); - } - - - public void test1000AsyncSsl() throws Exception { - asyncRequest(20, 50, false, true, clientCon, "AsyncHttpSsl"); - } - - public void test10000AsyncSsl() throws Exception { - asyncRequest(20, 500, false, true, clientCon, "AsyncHttpSsl"); - } - - public void test1000AsyncSpdy() throws Exception { - asyncRequest(10, 100, true, false, spdyClient, "AsyncSpdy"); - } - - public void test10000AsyncSpdy() throws Exception { - asyncRequest(20, 500, true, false, spdyClient, "AsyncSpdy"); - } - - public void test1000AsyncSpdyComp() throws Exception { - asyncRequest(10, 100, true, false, spdyClientCompress, "AsyncSpdyComp"); - } - - public void test10000AsyncSpdyComp() throws Exception { - asyncRequest(20, 500, true, false, spdyClientCompress, "AsyncSpdyComp"); - } - - public void xtest1000AsyncSpdySsl() throws Exception { - asyncRequest(10, 100, true, true, spdyClient, "AsyncSpdySsl"); - } - - public void xtest1000AsyncSpdyCompSsl() throws Exception { - asyncRequest(10, 100, true, true, spdyClientCompress, "AsyncSpdyCompSsl"); - } - - public void xtest10000AsyncSpdyCompSsl() throws Exception { - asyncRequest(20, 500, true, true, spdyClientCompress, "AsyncSpdyCompSsl"); - } - - Object thrlock = new Object(); - Object lock = new Object(); - - public void asyncRequest(final int thr, int perthr, - final boolean spdy, final boolean ssl, - final HttpConnector clientCon, String test) throws Exception { - clientCon.getConnectionPool().clear(); - reqCnt = thr * perthr; - long t0 = System.currentTimeMillis(); - - tr = new ThreadRunner(thr, perthr) { - public void makeRequest(int i) throws Exception { - HttpRequest cstate = clientCon.request("localhost", - ssl ? 8443 : 8802); - synchronized (active) { - active.put(cstate, cstate); - } - if (spdy) { - // Magic way to force spdy - will be replaced with - // a negotiation. - cstate.setProtocol("SPDY/1.0"); - } - if (ssl) { - cstate.setSecure(true); - } - cstate.requestURI().set("/hello"); - cstate.setCompletedCallback(reqCallback); - // no body - cstate.getBody().close(); - - cstate.send(); - - while (active.size() >= thr) { - synchronized(thrlock) { - thrlock.wait(); - } - } - } - }; - tr.run(); - synchronized (lock) { - if (ok.get() < reqCnt) { - lock.wait(reqCnt * 100); - } - } - long time = (System.currentTimeMillis() - t0); - - System.err.println("====== " + test + - " threads: " + thr + ", req: " + - reqCnt + ", sendTime" + tr.time + - ", time: " + time + - ", connections: " + clientCon.getConnectionPool().getSocketCount() + - ", avg: " + (time / reqCnt)); - - assertEquals(reqCnt, ok.get()); - assertEquals(0, tr.errors.get()); - } - - RequestCompleted reqCallback = new RequestCompleted() { - @Override - public void handle(HttpChannel data, Object extraData) - throws IOException { - String out = data.getIn().copyAll(null).toString(); - if (200 != data.getResponse().getStatus()) { - System.err.println("Wrong status"); - tr.errors.incrementAndGet(); - } else if (!"Hello world".equals(out)) { - tr.errors.incrementAndGet(); - System.err.println("bad result " + out); - } - synchronized (active) { - active.remove(data.getRequest()); - } - synchronized (thrlock) { - thrlock.notify(); - } - data.release(); - int okres = ok.incrementAndGet(); - if (okres >= reqCnt) { - synchronized (lock) { - lock.notify(); - } - } - } - }; - - - - public void testURLRequest1000() throws Exception { - urlRequest(10, 100, false, "HttpURLConnection"); - } - - public void xtestURLRequest10000() throws Exception { - urlRequest(20, 500, false, "HttpURLConnection"); - - } - - // I can't seem to get 1000 requests to all complete... - public void xtestURLRequestSsl100() throws Exception { - urlRequest(10, 10, true, "HttpURLConnectionSSL"); - } - - public void xtestURLRequestSsl10000() throws Exception { - urlRequest(20, 500, true, "HttpURLConnectionSSL"); - - } - - /** - * HttpURLConnection client against lite.http server. - */ - public void urlRequest(int thr, int cnt, final boolean ssl, String test) - throws Exception { - long t0 = System.currentTimeMillis(); - - - try { - HttpConnector testServer = TestMain.getTestServer(); - - tr = new ThreadRunner(thr, cnt) { - - public void makeRequest(int i) throws Exception { - try { - BBuffer out = BBuffer.allocate(); - String url = ssl ? "https://localhost:8443/hello" : - "http://localhost:8802/hello"; - HttpURLConnection con = - TestMain.getUrl(url, out); - if (con.getResponseCode() != 200) { - errors.incrementAndGet(); - } - if (!"Hello world".equals(out.toString())) { - errors.incrementAndGet(); - System.err.println("bad result " + out); - } - } catch(Throwable t) { - t.printStackTrace(); - errors.incrementAndGet(); - } - } - }; - tr.run(); - assertEquals(0, tr.errors.get()); - long time = (System.currentTimeMillis() - t0); - - System.err.println("====== " + test + " threads: " + thr + ", req: " + - (thr * cnt) + ", time: " + time + ", avg: " + - (time / (thr * cnt))); - } finally { - //dumpHeap("heapURLReq.bin"); - } - } - - // TODO: move to a servlet - - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/load/MicroTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/load/MicroTest.java deleted file mode 100644 index 4539312f8f95..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/load/MicroTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.load; - -import org.apache.tomcat.lite.http.BaseMapper; -import org.apache.tomcat.lite.http.MappingData; -import org.apache.tomcat.lite.io.CBuffer; - -import junit.framework.TestCase; - -public class MicroTest extends TestCase { - - public void testMapper() throws Exception { - BaseMapper mapper = new BaseMapper(); - - MappingData mappingData = new MappingData(); - CBuffer host = CBuffer.newInstance(); - host.set("test1.com"); - - CBuffer uri = CBuffer.newInstance(); - uri.set("/foo/bar/blah/bobou/foo"); - - String[] welcomes = new String[2]; - welcomes[0] = "index.html"; - welcomes[1] = "foo.html"; - - for (int i = 0; i < 100; i++) { - String hostN = "test" + i + ".com"; - mapper.addContext(hostN, "", "context0", new String[0], null, null); - mapper.addContext(hostN, "/foo", "context1", new String[0], null, null); - mapper.addContext(hostN, "/foo/bar", "context2", welcomes, null, null); - mapper.addContext(hostN, "/foo/bar/bla", "context3", new String[0], null, null); - - mapper.addWrapper(hostN, "/foo/bar", "/fo/*", "wrapper0"); - } - int N = 10000; - for (int i = 0; i < N; i++) { - mappingData.recycle(); - mapper.map(host, uri, mappingData); - } - - long time = System.currentTimeMillis(); - for (int i = 0; i < N; i++) { - mappingData.recycle(); - mapper.map(host, uri, mappingData); - } - // TODO: asserts - //System.out.println("Elapsed:" + (System.currentTimeMillis() - time)); - } -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/load/ThreadRunner.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/load/ThreadRunner.java deleted file mode 100644 index 96fea90fe421..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/load/ThreadRunner.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.load; - -import java.util.concurrent.atomic.AtomicInteger; - -public class ThreadRunner { - int tCount = 10; - int rCount = 100; - Thread[] threads; - int[] ok; - - int sleepTime = 0; - - long time; - protected AtomicInteger errors = new AtomicInteger(); - - public ThreadRunner(int threads, int count) { - tCount = threads; - rCount = count; - this.threads = new Thread[tCount]; - ok = new int[tCount]; - } - - public void run() { - long t0 = System.currentTimeMillis(); - for (int i = 0; i < tCount; i++) { - final int j = i; - threads[i] = new Thread(new Runnable() { - public void run() { - makeRequests(j); - } - }); - threads[i].start(); - } - - int res = 0; - for (int i = 0; i < tCount; i++) { - try { - threads[i].join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - res += ok[i]; - } - long t1 = System.currentTimeMillis(); - time = t1 - t0; - } - - public void makeRequests(int cnt) { - for (int i = 0; i < rCount ; i++) { - try { - //System.err.println("MakeReq " + t + " " + i); - makeRequest(cnt); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - public void makeRequest(int i) throws Exception { - - } -} \ No newline at end of file diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/LiveProxyHttp1Test.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/LiveProxyHttp1Test.java deleted file mode 100644 index 6a1b8e5ed3dd..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/LiveProxyHttp1Test.java +++ /dev/null @@ -1,33 +0,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.lite.proxy; - - -import java.io.IOException; - -import org.apache.tomcat.lite.http.LiveHttp1Test; - - -public class LiveProxyHttp1Test extends LiveHttp1Test { - public void setUp() throws IOException { - // All tests in super, but with client pointing to - // the proxy server, which in turn hits the real server. - clientPort = 8903; - super.setUp(); - } - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/ProxyTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/ProxyTest.java deleted file mode 100644 index 1d21a57ade0f..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/ProxyTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* -n * 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.lite.proxy; - -import java.io.IOException; - -import org.apache.tomcat.lite.TestMain; - -import junit.framework.TestCase; - - -public class ProxyTest extends TestCase { - - String resStr; - - public void setUp() throws Exception { - TestMain.getTestServer(); - } - - public void tearDown() throws IOException { - } - - public void xtestRequestSlowChunked() throws Exception { - resStr = - TestMain.get("http://localhost:8903/sleep/1c").toString(); - assertEquals("sleep 1csleep 1c", resStr); - } - - public void testSingleRequest() throws Exception { - String resStr = - TestMain.get("http://localhost:8903/hello").toString(); - assertEquals("Hello world", resStr); - } - - - public void test2Requests() throws Exception { - String resStr = - TestMain.get("http://localhost:8903/hello").toString(); - assertEquals("Hello world", resStr); - resStr = - TestMain.get("http://localhost:8903/hello?a=b").toString(); - assertEquals("Hello world", resStr); - } - - public void testRequestSimple() throws Exception { - resStr = - TestMain.get("http://localhost:8903/hello").toString(); - assertEquals("Hello world", resStr); - resStr = - TestMain.get("http://localhost:8903/hello").toString(); - assertEquals("Hello world", resStr); - resStr = - TestMain.get("http://localhost:8903/hello").toString(); - assertEquals(resStr, "Hello world"); - - } - - public void testExtAdapter() throws Exception { - String res = - TestMain.get("http://www.apache.org/").toString(); - assertTrue(res.indexOf("Apache") > 0); - - Thread.currentThread().sleep(100); - // second time - are we reusing ? - res = - TestMain.get("http://www.apache.org/").toString(); - - assertTrue(res.indexOf("Apache") > 0); - - } - - public void testStaticAdapter() throws Exception { - - assertEquals("Hello world", - TestMain.get("http://localhost:8802/hello").toString()); - assertEquals("Hello world2", - TestMain.get("http://localhost:8802/2nd").toString()); - - } - - public void testRequestParams() throws Exception { - // qry string - String resStr = - TestMain.get("http://localhost:8903/echo/foo?q=a&b") - .toString(); - assertTrue(resStr, resStr.indexOf("foo?q=a&b") > 0); - } - - - public void testRequestChunked() throws Exception { - // Chunked encoding - String resStr = - TestMain.get("http://localhost:8903/chunked/test") - .toString(); - assertEquals(4, resStr.length()); - assertTrue(resStr.indexOf("AAA") >= 0); - } - - - public void testRequestSlow() throws Exception { - // Slow - String resStr = - TestMain.get("http://localhost:8903/sleep/1").toString(); - assertEquals("sleep 1sleep 1", resStr.toString()); - } -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/SmallProxyTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/SmallProxyTest.java deleted file mode 100644 index 83ac8a974c10..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/SmallProxyTest.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - */ -package org.apache.tomcat.lite.proxy; - -import java.io.IOException; - -import junit.framework.TestCase; - -import org.apache.tomcat.lite.http.HttpChannel; -import org.apache.tomcat.lite.http.HttpConnector; -import org.apache.tomcat.lite.http.HttpConnector.HttpConnection; -import org.apache.tomcat.lite.io.MemoryIOConnector; -import org.apache.tomcat.lite.io.MemoryIOConnector.MemoryIOChannel; - -public class SmallProxyTest extends TestCase { - - MemoryIOConnector memoryServerConnector = - new MemoryIOConnector(); - - MemoryIOConnector memoryClientConnector = - new MemoryIOConnector().withServer(memoryServerConnector); - - - HttpConnector httpCon = new HttpConnector(memoryServerConnector) { - @Override - public HttpChannel get(CharSequence target) throws IOException { - throw new IOException(); - } - public HttpChannel getServer() { - lastServer = new HttpChannel().serverMode(true); - lastServer.setConnector(this); - //lastServer.withIOConnector(memoryServerConnector); - return lastServer; - } - }; - - HttpConnector httpClient = new HttpConnector(memoryClientConnector) { - @Override - public HttpChannel get(CharSequence target) throws IOException { - lastClient = new HttpChannel(); - lastClient.setConnector(this); - return lastClient; - } - public HttpChannel get(String host, int port) throws IOException { - lastClient = new HttpChannel(); - lastClient.setConnector(this); - return lastClient; - } - public HttpChannel getServer() { - throw new RuntimeException(); - } - }; - - HttpChannel lastServer; - HttpChannel lastClient; - - boolean hasBody = false; - boolean bodyDone = false; - boolean bodySentDone = false; - boolean headersDone = false; - boolean allDone = false; - - - //MemoryIOChannel clientNet = new MemoryIOChannel(); - - MemoryIOConnector.MemoryIOChannel net = new MemoryIOChannel(); - HttpChannel http; - - HttpConnection serverConnection; - - public void setUp() throws IOException { - http = httpCon.getServer(); - serverConnection = httpCon.handleAccepted(net); - } - - /** - * More complicated test.. - * @throws IOException - */ - public void testProxy() throws IOException { - httpCon.setHttpService(new HttpProxyService() - .withSelector(memoryClientConnector) - .withHttpClient(httpClient)); - - net.getIn().append("GET http://www.apache.org/ HTTP/1.0\n" + - "Connection: Close\n\n"); - net.getIn().close(); - - // lastClient.rawSendBuffers has the request sent by proxy - lastClient.getNet().getIn() - .append("HTTP/1.0 200 OK\n\nHi\n"); - lastClient.getNet().getIn() - .append("world\n"); - - // TODO: check what the proxy sent - // lastClient.getOut(); - - // will also trigger 'release' - both sides are closed. - lastClient.getNet().getIn().close(); - - // wait response... - // http.sendBody.close(); - String res = net.out.toString(); - assertTrue(res.indexOf("Hi\nworld\n") > 0); - assertTrue(res.indexOf("HTTP/1.0 200 OK") == 0); - assertTrue(res.indexOf("tomcatproxy") > 0); - - } -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/util/UEncoderTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/util/UEncoderTest.java deleted file mode 100644 index 5048e287583a..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/lite/util/UEncoderTest.java +++ /dev/null @@ -1,51 +0,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.lite.util; - -import junit.framework.TestCase; - -public class UEncoderTest extends TestCase { - URLEncoder enc=new URLEncoder(); - - /* - * - * Test method for 'org.apache.tomcat.util.buf.UEncoder.encodeURL(String)' - * TODO: find the relevant rfc and apache tests and add more - */ - public void testEncodeURL() { - - String eurl1=enc.encodeURL("test"); - assertEquals("test", eurl1); - - eurl1=enc.encodeURL("/test"); - assertEquals("/test", eurl1); - - // safe ranges - eurl1=enc.encodeURL("test$-_."); - assertEquals("test$-_.", eurl1); - - eurl1=enc.encodeURL("test$-_.!*'(),"); - assertEquals("test$-_.!*'(),", eurl1); - - eurl1=enc.encodeURL("//test"); - assertEquals("//test", eurl1); - - - } - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/AntProperties.java b/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/AntProperties.java deleted file mode 100644 index b7e7ff3b1234..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/AntProperties.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - */ -package org.apache.tomcat.test.watchdog; - -import java.util.Hashtable; - -/** - * Extracted from IntrospectionHelper - a simple utility class to - * do ant style ${property} replacements on a string, using a map - * holding properties. Also allows a hook for dynamic, on-demand - * properties. - * - * @author Costin Manolache - */ -public class AntProperties { - public static interface PropertySource { - public String getProperty(String key); - } - - /** - * Replace ${NAME} with the property value - */ - public static String replaceProperties(String value, - Hashtable staticProp, PropertySource dynamicProp[]) { - if (value.indexOf("$") < 0) { - return value; - } - StringBuffer sb = new StringBuffer(); - int prev = 0; - // assert value!=nil - int pos; - while ((pos = value.indexOf("$", prev)) >= 0) { - if (pos > 0) { - sb.append(value.substring(prev, pos)); - } - if (pos == (value.length() - 1)) { - sb.append('$'); - prev = pos + 1; - } else if (value.charAt(pos + 1) != '{') { - sb.append('$'); - prev = pos + 1; // XXX - } else { - int endName = value.indexOf('}', pos); - if (endName < 0) { - sb.append(value.substring(pos)); - prev = value.length(); - continue; - } - String n = value.substring(pos + 2, endName); - String v = null; - if (staticProp != null) { - v = (String) staticProp.get(n); - } - if (v == null && dynamicProp != null) { - for (int i = 0; i < dynamicProp.length; i++) { - v = dynamicProp[i].getProperty(n); - if (v != null) { - break; - } - } - } - if (v == null) - v = "${" + n + "}"; - - sb.append(v); - prev = endName + 1; - } - } - if (prev < value.length()) - sb.append(value.substring(prev)); - return sb.toString(); - } - - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/CookieController.java b/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/CookieController.java deleted file mode 100644 index f63bd1a0e4ad..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/CookieController.java +++ /dev/null @@ -1,636 +0,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.test.watchdog; - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.net.URL; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Properties; -import java.util.Vector; - - -/** - * Represents a collection of Cookie instances. - *

    - * Fires events when the cookies have been changed internally. Deals - * with management of cookies in terms of saving and loading them, - * and disabling them. - * - * @author Ramesh.Mandava - */ -public class CookieController { - -// private VetoableChangeSupport vceListeners; - - private static Hashtable cookieJar = new Hashtable(); - - /* public no arg constructor for bean */ - public CookieController() { - } - -///////////////////////////////////////////////////////////// - /** - * Records any cookies which have been sent as part of an HTTP response. - * The connection parameter must be already have been opened, so that - * the response headers are available. It's ok to pass a non-HTTP - * URL connection, or one which does not have any set-cookie headers. - */ - public void recordAnyCookies(Vector rcvVectorOfCookies , URL url ) { - - if ((rcvVectorOfCookies == null) || ( rcvVectorOfCookies.size()== 0) ) { - // no headers here - return; - } - try { - /* - Properties properties = new Properties(); - FileInputStream fin = new FileInputStream("ServerAutoRun.properties"); - properties.load(fin); - - String cookiepolicy = properties.getProperty("cookie.acceptpolicy"); - if (cookiepolicy == null || cookiepolicy.equals("none")) { - return; - } - */ - - - for (int hi = 0; hi 0 && dotsNeeded > 0; dotsNeeded-- ) { - lastChar = domain.lastIndexOf( '.', lastChar-1 ); - } - - if( lastChar > 0 ) - domainOK = true; - } - - if( domainOK ) { - recordCookie(cookie); - - } - } - - - /** - * Record the cookie in the in-memory container of cookies. If there - * is already a cookie which is in the exact same domain with the - * exact same - */ - public void recordCookie(HttpCookie cookie) { - if (!checkIfCookieOK(cookie)) { - return; - } - synchronized (cookieJar) { - - String domain = cookie.getDomain().toLowerCase(); - - Vector cookieList = (Vector)cookieJar.get(domain); - if (cookieList == null) { - cookieList = new Vector(); - } - - addOrReplaceCookie(cookieList, cookie); - cookieJar.put(domain, cookieList); - - } - - } - - public boolean checkIfCookieOK(HttpCookie cookie) { - return true; - } - - /** - * Scans the vector of cookies looking for an exact match with the - * given cookie. Replaces it if there is one, otherwise adds - * one at the end. The vector is presumed to have cookies which all - * have the same domain, so the domain of the cookie is not checked. - *

    - *

    - * If this is called, it is assumed that the cookie jar is exclusively - * held by the current thread. - * - */ - private void addOrReplaceCookie(Vector cookies, - HttpCookie cookie) { - int numCookies = cookies.size(); - - String path = cookie.getPath(); - String name = cookie.getName(); - HttpCookie replaced = null; - int replacedIndex = -1; - - for (int i = 0; i < numCookies; i++) { - HttpCookie existingCookie = (HttpCookie)cookies.elementAt(i); - - String existingPath = existingCookie.getPath(); - if (path.equals(existingPath)) { - String existingName = existingCookie.getName(); - if (name.equals(existingName)) { - // need to replace this one! - replaced = existingCookie; - replacedIndex = i; - break; - } - } - } - - - // Do the replace - if cookie has already expired, remove - // the replaced cookie. - if (replaced != null) { - if (cookie.isSaveableInMemory()) { - cookies.setElementAt(cookie, replacedIndex); - //System.out.println("REPLACED existing cookie with " + cookie); - } else { - cookies.removeElementAt(replacedIndex); - //System.out.println("Removed cookie b/c or expr " + cookie); - } - - } else { // only save the cookie in memory if it is non persistent - // or not expired. - if (cookie.isSaveableInMemory()) { - cookies.addElement(cookie); - //System.out.println("RECORDED new cookie " + cookie); - } - - } - - } - - public String applyRelevantCookies(URL url ) { - - try { - /* - Properties properties = new Properties(); - FileInputStream fin = new FileInputStream("ServerAutoRun.properties"); - properties.load(fin); - // check current accept policy instead enableCookies - String cookiepolicy = properties.getProperty("cookie.acceptpolicy"); - if (cookiepolicy == null || cookiepolicy.equals("none")) { - return null; - } - - */ - - return applyCookiesForHost(url); - - } - catch ( Exception e ) - { - System.out.println("Exception : " +e ); - return null; - } - - - } - - - /** - * Host may be a FQDN, or a partial domain name starting with a dot. - * Adds any cookies which match the host and path to the - * cookie set on the URL connection. - */ - private String applyCookiesForHost(URL url ){ - String cookieString = null; - Vector cookieVector = getAllRelevantCookies(url); - - if (cookieVector != null) { - - for (Enumeration e = cookieVector.elements(); e.hasMoreElements();) { - HttpCookie cookie = (HttpCookie)e.nextElement(); - if( cookieString == null ) { - cookieString = cookie.getNameValue(); - } else { - cookieString = cookieString + "; " + cookie.getNameValue(); - } - } - - /* - - if( cookieString != null ) { - httpConn.setRequestProperty("Cookie", cookieString); - -// System.out.println("Returned cookie string: " + cookieString + " for HOST = " + host); - } - - */ - - - } -// System.out.println("Returned cookie string: " + cookieString + " for HOST = " + host); - return cookieString; - - } - - private Vector getAllRelevantCookies(URL url) { - String host = url.getHost(); - Vector cookieVector = getSubsetRelevantCookies(host, url); - - Vector tempVector; - int index; - - while ((index = host.indexOf('.', 1)) >= 0) { - // trim off everything up to, and including the dot. - host = host.substring(index+1); - - // add onto cookieVector - tempVector = getSubsetRelevantCookies(host,url); - if (tempVector != null ) { - for (Enumeration e = tempVector.elements(); e.hasMoreElements(); ) { - if (cookieVector == null) { - cookieVector = new Vector(2); - } - - cookieVector.addElement(e.nextElement()); - - } - } - } - return cookieVector; - } - - private Vector getSubsetRelevantCookies(String host, URL url) { - - Vector cookieList = (Vector)cookieJar.get(host); - -// System.out.println("getRelevantCookies() .. for host, url " + host +", "+url); - Vector cookiePortList = (Vector)cookieJar.get(host+":"+((url.getPort() == -1) ? 80 : url.getPort())); - if (cookiePortList != null) { - if (cookieList == null) { - cookieList = new Vector(10); - } - Enumeration cookies = cookiePortList.elements(); - while (cookies.hasMoreElements()) { - cookieList.addElement(cookies.nextElement()); - } - } - - - if (cookieList == null) { - return null; - } - - String path = url.getFile(); -// System.out.println(" path is " + path + "; protocol = " + url.getProtocol()); - - - int queryInd = path.indexOf('?'); - if (queryInd > 0) { - // strip off the part following the ? - path = path.substring(0, queryInd); - } - - Enumeration cookies = cookieList.elements(); - Vector cookiesToSend = new Vector(10); - - while (cookies.hasMoreElements()) { - HttpCookie cookie = (HttpCookie)cookies.nextElement(); - - String cookiePath = cookie.getPath(); - - if (path.startsWith(cookiePath)) { - // larrylf: Actually, my documentation (from Netscape) - // says that /foo should - // match /foobar and /foo/bar. Yuck!!! - - if (!cookie.hasExpired()) { - cookiesToSend.addElement(cookie); - } - -/* - We're keeping this piece of commented out code around just in - case we decide to put it back. the spec does specify the above, - but it is so disgusting! - - int cookiePathLen = cookiePath.length(); - - // verify that /foo does not match /foobar by mistake - if ((path.length() == cookiePathLen) - || (path.length() > cookiePathLen && - path.charAt(cookiePathLen) == '/')) { - - // We have a matching cookie! - - if (!cookie.hasExpired()) { - cookiesToSend.addElement(cookie); - } - } -*/ - } - } - - // Now, sort the cookies in most to least specific order - // Yes, its the deaded bubblesort!! Wah Ha-ha-ha-ha.... - // (it should be a small vector, so perf is not an issue...) - if( cookiesToSend.size() > 1 ) { - for( int i = 0; i < cookiesToSend.size()-1; i++ ) { - HttpCookie headC = (HttpCookie)cookiesToSend.elementAt(i); - String head = headC.getPath(); - // This little excercise is a cheap way to get - // '/foo' to read more specfic then '/' - if( !head.endsWith("/") ) { - head = head + "/"; - } - for( int j = i+1; j < cookiesToSend.size(); j++ ) { - HttpCookie scanC = (HttpCookie)cookiesToSend.elementAt(j); - String scan = scanC.getPath(); - if( !scan.endsWith("/") ) { - scan = scan + "/"; - } - - int headCount = 0; - int index = -1; - while( (index=head.indexOf('/', index+1)) != -1 ) { - headCount++; - } - index = -1; - - int scanCount = 0; - while( (index=scan.indexOf('/', index+1)) != -1 ) { - scanCount++; - } - - if( scanCount > headCount ) { - cookiesToSend.setElementAt(headC, j); - cookiesToSend.setElementAt(scanC, i); - headC = scanC; - head = scan; - } - } - } - } - - - return cookiesToSend; - - } - - /* - * Writes cookies out to PrintWriter if they are persistent - * (i.e. have a expr date) - * and haven't expired. Will remove cookies that have expired as well - */ - private void saveCookiesToStream(PrintWriter pw) { - - Enumeration cookieLists = cookieJar.elements(); - - while (cookieLists.hasMoreElements()) { - Vector cookieList = (Vector)cookieLists.nextElement(); - - Enumeration cookies = cookieList.elements(); - - while (cookies.hasMoreElements()) { - HttpCookie cookie = (HttpCookie)cookies.nextElement(); - - if (cookie.getExpirationDate() != null) { - if (cookie.isSaveable()) { - pw.println(cookie); - } else { // the cookie must have expired, - //remove from Vector cookieList - cookieList.removeElement(cookie); - } - - } - } - } - // Must print something to the printwriter in the case that - // the cookieJar has been cleared - otherwise the old cookie - // file will continue to exist. - pw.print(""); - } -///////////////////////////////////////////////////////////// - /* adds cookieList to the existing cookie jar*/ - public void addToCookieJar(HttpCookie[] cookieList) { - - if (cookieList != null) { - for (int i = 0; i < cookieList.length; i++) { - - recordCookie(cookieList[i]); - } - } - - } - - /*adds one cookie to the Cookie Jar */ - public void addToCookieJar(String cookieString, URL docURL) { - recordCookie(new HttpCookie(docURL, cookieString)); - } - - /* loads the cookies from the given filename */ - public void loadCookieJarFromFile(String cookieFileName) { - try { - FileReader fr = new FileReader(cookieFileName); - - BufferedReader in = new BufferedReader(fr); - - try { - String cookieString; - while ((cookieString = in.readLine()) != null) { - HttpCookie cookie = new HttpCookie(cookieString); - // Record the cookie, without notification. We don't - // do a notification for cookies that are read at - // program start-up. - recordCookie(cookie); - } - } finally { - in.close(); - } - - - } catch (IOException e) { - // do nothing; it's not an error not to have persistent cookies - } - - } - - /* saves the cookies to the given file specified by fname */ - public void saveCookieJarToFile(String cookieFileName) { - try { - FileWriter fw = new FileWriter(cookieFileName); - PrintWriter pw = new PrintWriter(fw, false); - - try { - saveCookiesToStream(pw); - } finally { - pw.close(); - } - - } catch (IOException e) { - // REMIND: I18N - System.err.println("Saving cookies failed " + e.getMessage()); - } - } - - /** - * Return an array with all of the cookies represented by this - * jar. This is useful when the bean is shutting down, and the client - * wants to make the cookie jar persist. - */ - public HttpCookie[] getAllCookies() { - - Vector result = new Vector(); - Hashtable jar; - jar = (Hashtable) cookieJar.clone(); - - synchronized (jar) { - - for (Enumeration e = jar.elements(); e.hasMoreElements() ;) { - Vector v = (Vector) e.nextElement(); - for (int i = 0; i < v.size(); i++) { - HttpCookie hc = (HttpCookie) v.elementAt(i); - result.addElement(hc); - - } - - } - } - - HttpCookie[] resultA = new HttpCookie[result.size()]; - for (int i = 0; i < result.size(); i++) { - resultA[i] = (HttpCookie) result.elementAt(i); - } - return resultA; - } - - /* Gets all cookies that applies for the URL */ - public HttpCookie[] getCookiesForURL(URL url) { - - Vector cookieVector = getAllRelevantCookies(url); - - if (cookieVector == null) { - return null; - } - - int i = 0; - HttpCookie[] cookieArr = new HttpCookie[cookieVector.size()]; - - for (Enumeration e = cookieVector.elements(); e.hasMoreElements(); ) { - - cookieArr[i++] = (HttpCookie)e.nextElement(); -// System.out.println("cookieArr["+(i-1)+"] = " +cookieArr[i-1].toString()); - } - - return cookieArr; - } - - /* this will set the property of enableCookies to isDisabled */ - public void setCookieDisable(boolean isDisabled) { - - // Pending visit back this again - try { - Properties properties = new Properties(); - properties.load(new FileInputStream("ServerAutoRun.properties") ); - - - properties.put("enableCookies", isDisabled ? "false" : "true"); - properties.store(new FileOutputStream("ServerAutoRun.properties"),"comments"); - } - catch ( Exception e ) - { - System.out.println("Exception : " + e ); - } - } - - public void discardAllCookies() { - cookieJar.clear(); - - } - - /* - * purges any expired cookies in the Cookie hashtable. - */ - public void purgeExpiredCookies() { - Enumeration cookieLists = cookieJar.elements(); - - while (cookieLists.hasMoreElements()) { - Vector cookieList = (Vector)cookieLists.nextElement(); - - Enumeration cookies = cookieList.elements(); - - while (cookies.hasMoreElements()) { - HttpCookie cookie = (HttpCookie)cookies.nextElement(); - - if (cookie.hasExpired()) { - cookieList.removeElement(cookie); - } - } - } - - } - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/DynamicObject.java b/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/DynamicObject.java deleted file mode 100644 index 6d618858aeaf..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/DynamicObject.java +++ /dev/null @@ -1,385 +0,0 @@ -/* - */ -package org.apache.tomcat.test.watchdog; - -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Refactoring of IntrospectionUtils and modeler dynamic bean. - * - * Unlike IntrospectionUtils, the method informations can be cached. - * Also I hope this class will be simpler to use. - * There is no static cache. - * - * @author Costin Manolache - */ -public class DynamicObject { - // Based on MbeansDescriptorsIntrospectionSource - - private static Logger log = Logger.getLogger(DynamicObject.class.getName()); - - private static Class NO_PARAMS[] = new Class[0]; - - - private static String strArray[] = new String[0]; - - private static Class[] supportedTypes = new Class[] { Boolean.class, - Boolean.TYPE, Byte.class, Byte.TYPE, Character.class, - Character.TYPE, Short.class, Short.TYPE, Integer.class, - Integer.TYPE, Long.class, Long.TYPE, Float.class, Float.TYPE, - Double.class, Double.TYPE, String.class, strArray.getClass(), - BigDecimal.class, BigInteger.class, AtomicInteger.class, - AtomicLong.class, java.io.File.class, }; - - - private Class realClass; - - // Method or Field - private Map getAttMap; - - public DynamicObject(Class beanClass) { - this.realClass = beanClass; - initCache(); - } - - private void initCache() { - Method methods[] = null; - - getAttMap = new HashMap(); - - methods = realClass.getMethods(); - for (int j = 0; j < methods.length; ++j) { - if (ignorable(methods[j])) { - continue; - } - String name = methods[j].getName(); - - Class params[] = methods[j].getParameterTypes(); - - if (name.startsWith("get") && params.length == 0) { - Class ret = methods[j].getReturnType(); - if (!supportedType(ret)) { - if (log.isLoggable(Level.FINE)) - log.fine("Unsupported type " + methods[j]); - continue; - } - name = unCapitalize(name.substring(3)); - - getAttMap.put(name, methods[j]); - } else if (name.startsWith("is") && params.length == 0) { - Class ret = methods[j].getReturnType(); - if (Boolean.TYPE != ret) { - if (log.isLoggable(Level.FINE)) - log.fine("Unsupported type " + methods[j] + " " + ret); - continue; - } - name = unCapitalize(name.substring(2)); - - getAttMap.put(name, methods[j]); - } - } - // non-private AtomicInteger and AtomicLong - stats - Field fields[] = realClass.getFields(); - for (int j = 0; j < fields.length; ++j) { - if (fields[j].getType() == AtomicInteger.class) { - getAttMap.put(fields[j].getName(), fields[j]); - } - } - - } - - public List attributeNames() { - return new ArrayList(getAttMap.keySet()); - } - - - public Object invoke(Object proxy, String method) throws Exception { - Method executeM = null; - Class c = proxy.getClass(); - executeM = c.getMethod(method, NO_PARAMS); - if (executeM == null) { - throw new RuntimeException("No execute in " + proxy.getClass()); - } - return executeM.invoke(proxy, (Object[]) null); - } - - // TODO -// public Object invoke(String method, Object[] params) { -// return null; -// } - - public Object getAttribute(Object o, String att) { - AccessibleObject m = getAttMap.get(att); - if (m instanceof Method) { - try { - return ((Method) m).invoke(o); - } catch (Throwable e) { - log.log(Level.INFO, "Error getting attribute " + realClass + " " - + att, e); - return null; - } - } if (m instanceof Field) { - if (((Field) m).getType() == AtomicInteger.class) { - try { - Object value = ((Field) m).get(o); - return ((AtomicInteger) value).get(); - } catch (Throwable e) { - return null; - } - } else { - return null; - } - } else { - return null; - } - } - - /** - * Set an object-type attribute. - * - * Use setProperty to use a string value and convert it to the - * specific (primitive) type. - */ - public boolean setAttribute(Object proxy, String name, Object value) { - // TODO: use the cache... - String methodName = "set" + capitalize(name); - Method[] methods = proxy.getClass().getMethods(); - for (Method m : methods) { - Class[] paramT = m.getParameterTypes(); - if (methodName.equals(m.getName()) - && paramT.length == 1 - && (value == null || paramT[0].isAssignableFrom(value - .getClass()))) { - try { - m.invoke(proxy, value); - return true; - } catch (IllegalArgumentException e) { - log.severe("Error setting: " + name + " " - + proxy.getClass().getName() + " " + e); - } catch (IllegalAccessException e) { - log.severe("Error setting: " + name + " " - + proxy.getClass().getName() + " " + e); - } catch (InvocationTargetException e) { - log.severe("Error setting: " + name + " " - + proxy.getClass().getName() + " " + e); - } - } - } - return false; - } - - public boolean setProperty(Object proxy, String name, String value) { - // TODO: use the cache... - String setter = "set" + capitalize(name); - - try { - Method methods[] = proxy.getClass().getMethods(); - - Method setPropertyMethod = null; - - // First, the ideal case - a setFoo( String ) method - for (int i = 0; i < methods.length; i++) { - if (ignorable(methods[i])) { - continue; - } - Class paramT[] = methods[i].getParameterTypes(); - if (setter.equals(methods[i].getName()) && paramT.length == 1) { - if ("java.lang.String".equals(paramT[0].getName())) { - methods[i].invoke(proxy, new Object[] { value }); - return true; - } else { - // match - find the type and invoke it - Class paramType = methods[i].getParameterTypes()[0]; - Object params[] = new Object[1]; - params[0] = convert(value, paramType); - if (params[0] != null) { - methods[i].invoke(proxy, params); - return true; - } - } - } - // save "setProperty" for later - if ("setProperty".equals(methods[i].getName()) && - paramT.length == 2 && - paramT[0] == String.class && - paramT[1] == String.class) { - setPropertyMethod = methods[i]; - } - } - - try { - Field field = proxy.getClass().getField(name); - if (field != null) { - Object conv = convert(value, field.getType()); - if (conv != null) { - field.set(proxy, conv); - return true; - } - } - } catch (NoSuchFieldException e) { - // ignore - } - - // Ok, no setXXX found, try a setProperty("name", "value") - if (setPropertyMethod != null) { - Object params[] = new Object[2]; - params[0] = name; - params[1] = value; - setPropertyMethod.invoke(proxy, params); - return true; - } - - } catch (Throwable ex2) { - log.log(Level.WARNING, "IAE " + proxy + " " + name + " " + value, - ex2); - } - return false; - } - - // ----------- Helpers ------------------ - - static Object convert(String object, Class paramType) { - Object result = null; - if ("java.lang.String".equals(paramType.getName())) { - result = object; - } else if ("java.lang.Long".equals(paramType.getName()) - || "long".equals(paramType.getName())) { - try { - result = Long.parseLong(object); - } catch (NumberFormatException ex) { - } - // Try a setFoo ( boolean ) - } else if ("java.lang.Integer".equals(paramType.getName()) - || "int".equals(paramType.getName())) { - try { - result = new Integer(object); - } catch (NumberFormatException ex) { - } - // Try a setFoo ( boolean ) - } else if ("java.lang.Boolean".equals(paramType.getName()) - || "boolean".equals(paramType.getName())) { - result = new Boolean(object); - } else { - log.info("Unknown type " + paramType.getName()); - } - if (result == null) { - throw new IllegalArgumentException("Can't convert argument: " - + object + " to " + paramType ); - } - return result; - } - - /** - * Converts the first character of the given String into lower-case. - * - * @param name - * The string to convert - * @return String - */ - static String unCapitalize(String name) { - if (name == null || name.length() == 0) { - return name; - } - char chars[] = name.toCharArray(); - chars[0] = Character.toLowerCase(chars[0]); - return new String(chars); - } - - /** - * Check if this class is one of the supported types. If the class is - * supported, returns true. Otherwise, returns false. - * - * @param ret - * The class to check - * @return boolean True if class is supported - */ - static boolean supportedType(Class ret) { - for (int i = 0; i < supportedTypes.length; i++) { - if (ret == supportedTypes[i]) { - return true; - } - } - if (isBeanCompatible(ret)) { - return true; - } - return false; - } - - /** - * Check if this class conforms to JavaBeans specifications. If the class is - * conformant, returns true. - * - * @param javaType - * The class to check - * @return boolean True if the class is compatible. - */ - static boolean isBeanCompatible(Class javaType) { - // Must be a non-primitive and non array - if (javaType.isArray() || javaType.isPrimitive()) { - return false; - } - - // Anything in the java or javax package that - // does not have a defined mapping is excluded. - if (javaType.getName().startsWith("java.") - || javaType.getName().startsWith("javax.")) { - return false; - } - - try { - javaType.getConstructor(new Class[] {}); - } catch (java.lang.NoSuchMethodException e) { - return false; - } - - // Make sure superclass is compatible - Class superClass = javaType.getSuperclass(); - if (superClass != null && superClass != java.lang.Object.class - && superClass != java.lang.Exception.class - && superClass != java.lang.Throwable.class) { - if (!isBeanCompatible(superClass)) { - return false; - } - } - return true; - } - - /** - * Reverse of Introspector.decapitalize - */ - static String capitalize(String name) { - if (name == null || name.length() == 0) { - return name; - } - char chars[] = name.toCharArray(); - chars[0] = Character.toUpperCase(chars[0]); - return new String(chars); - } - - private boolean ignorable(Method method) { - if (Modifier.isStatic(method.getModifiers())) - return true; - if (!Modifier.isPublic(method.getModifiers())) { - return true; - } - if (method.getDeclaringClass() == Object.class) - return true; - return false; - } - - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/HttpCookie.java b/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/HttpCookie.java deleted file mode 100644 index 33e21a07ca96..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/HttpCookie.java +++ /dev/null @@ -1,290 +0,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.test.watchdog; - -import java.io.FileInputStream; -import java.io.IOException; -import java.net.URL; -import java.util.Date; -import java.util.Properties; -import java.util.StringTokenizer; - -/** - * An object which represents an HTTP cookie. Can be constructed by - * parsing a string from the set-cookie: header. - * - * Syntax: Set-Cookie: NAME=VALUE; expires=DATE; - * path=PATH; domain=DOMAIN_NAME; secure - * - * All but the first field are optional. - * - * @author Ramesh.Mandava - */ - -public class HttpCookie { - private Date expirationDate = null; - private String nameAndValue; - private String path; - private String domain; - private boolean isSecure = false; - private static boolean defaultSet = true; - private static long defExprTime = 100; - - public HttpCookie(String cookieString) { - /* - System.out.println("Calling default expiration :"); - getDefaultExpiration(); - */ - parseCookieString(cookieString); - } - - // - // Constructor for use by the bean - // - public HttpCookie(Date expirationDate, - String nameAndValue, - String path, - String domain, - boolean isSecure) { - this.expirationDate = expirationDate; - this.nameAndValue = nameAndValue; - this.path = path; - this.domain = domain; - this.isSecure = isSecure; - } - - public HttpCookie(URL url, String cookieString) { - parseCookieString(cookieString); - applyDefaults(url); - } - - /** - * Fills in default values for domain, path, etc. from the URL - * after creation of the cookie. - */ - private void applyDefaults(URL url) { - if (domain == null) { - domain = url.getHost()+":"+((url.getPort() == -1) ? 80 : url.getPort()); - } - - if (path == null) { - path = url.getFile(); - - // larrylf: The documentation for cookies say that the path is - // by default, the path of the document, not the filename of the - // document. This could be read as not including that document - // name itself, just its path (this is how NetScape intrprets it) - // so amputate the document name! - int last = path.lastIndexOf("/"); - if( last > -1 ) { - path = path.substring(0, last); - } - } - } - - - /** - * Parse the given string into its individual components, recording them - * in the member variables of this object. - */ - private void parseCookieString(String cookieString) { - StringTokenizer tokens = new StringTokenizer(cookieString, ";"); - - if (!tokens.hasMoreTokens()) { - // REMIND: make this robust against parse errors - nameAndValue="="; - return; - } - - nameAndValue = tokens.nextToken().trim(); - - while (tokens.hasMoreTokens()) { - String token = tokens.nextToken().trim(); - - if (token.equalsIgnoreCase("secure")) { - isSecure = true; - } else { - int equIndex = token.indexOf("="); - - if (equIndex < 0) { - continue; - // REMIND: malformed cookie - } - - String attr = token.substring(0, equIndex); - String val = token.substring(equIndex+1); - - if (attr.equalsIgnoreCase("path")) { - path = val; - } else if (attr.equalsIgnoreCase("domain")) { - if( val.indexOf(".") == 0 ) { - // spec seems to allow for setting the domain in - // the form 'domain=.eng.sun.com'. We want to - // trim off the leading '.' so we can allow for - // both leading dot and non leading dot forms - // without duplicate storage. - domain = val.substring(1); - } else { - domain = val; - } - } else if (attr.equalsIgnoreCase("expires")) { - expirationDate = parseExpireDate(val); - } else { - // unknown attribute -- do nothing - } - } - } - - // commented the following out, b/c ok to have no expirationDate - // that means that the cookie should last only for that particular - // session. - // if (expirationDate == null) { - // expirationDate = getDefaultExpiration(); - // } - } - - /* Returns the default expiration, which is the current time + default - expiration as specified in the properties file. - This uses reflection to get at the properties file, since Globals is - not in the utils/ directory - */ - private Date getDefaultExpiration() { - if (defaultSet == false) { - Properties props = new Properties(); - - try { - FileInputStream fin = new FileInputStream("ServerAutoRun.properties"); - props.load( fin ); - - System.out.println("Got properties from ServerAutoRun.properties"); - props.list(System.out); - - } catch (IOException ex) { - System.out.println("HttpCookie getDefaultExpiration : ServerAutoRun.properties not found!" + ex); - } - - // defExprTime = props.getProperty("cookies.default.expiration"); - defExprTime = Long.parseLong( props.getProperty("cookies.default.expiration") ); - - } - defaultSet = true; - - return (new Date(System.currentTimeMillis() + defExprTime)); - - } - - //====================================================================== - // - // Accessor functions - // - - - - public String getNameValue() { - return nameAndValue; - } - - /** - * Returns just the name part of the cookie - */ - public String getName() { - - // it probably can't have null value, but doesn't hurt much - // to check. - if (nameAndValue == null) { - return "="; - } - int index = nameAndValue.indexOf("="); - return (index < 0) ? "=" : nameAndValue.substring(0, index); - } - - - /** - * Returns the domain of the cookie as it was presented - */ - public String getDomain() { - // REMIND: add port here if appropriate - return domain; - } - - public String getPath() { - return path; - } - - public Date getExpirationDate() { - return expirationDate; - } - - public boolean hasExpired() { - if(expirationDate == null) { - return false; - } - return (expirationDate.getTime() <= System.currentTimeMillis()); - } - - /** - * Returns true if the cookie has an expiration date (meaning it's - * persistent), and if the date nas not expired; - */ - public boolean isSaveable() { - return (expirationDate != null) - && (expirationDate.getTime() > System.currentTimeMillis()); - } - - public boolean isSaveableInMemory() { - return ((expirationDate == null) || - (expirationDate != null && expirationDate.getTime() > System.currentTimeMillis())); - } - - public boolean isSecure() { - return isSecure; - } - - private Date parseExpireDate(String dateString) { - // format is wdy, DD-Mon-yyyy HH:mm:ss GMT - RfcDateParser parser = new RfcDateParser(dateString); - Date theDate = parser.getDate(); - if (theDate == null) { - // Expire in some intelligent default time - theDate = getDefaultExpiration(); - } - return theDate; - } - - public String toString() { - - String result = (nameAndValue == null) ? "=" : nameAndValue; - if (expirationDate != null) { - result += "; expires=" + expirationDate; - } - - if (path != null) { - result += "; path=" + path; - } - - if (domain != null) { - result += "; domain=" + domain; - } - - if (isSecure) { - result += "; secure"; - } - - return result; - } -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/RfcDateParser.java b/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/RfcDateParser.java deleted file mode 100644 index 2aeebb7f18cc..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/RfcDateParser.java +++ /dev/null @@ -1,103 +0,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.test.watchdog; - -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; - -/** - * A parser for date strings commonly found in http and email headers that - * follow various RFC conventions. Given a date-string, the parser will - * attempt to parse it by trying matches with a set of patterns, returning - * null on failure, a Date object on success. - * - * @author Ramesh.Mandava - */ -public class RfcDateParser { - - private boolean isGMT = false; - - static final String[] standardFormats = { - "EEEE', 'dd-MMM-yy HH:mm:ss z", // RFC 850 (obsoleted by 1036) - "EEEE', 'dd-MMM-yy HH:mm:ss", // ditto but no tz. Happens too often - "EEE', 'dd-MMM-yyyy HH:mm:ss z", // RFC 822/1123 - "EEE', 'dd MMM yyyy HH:mm:ss z", // REMIND what rfc? Apache/1.1 - "EEEE', 'dd MMM yyyy HH:mm:ss z", // REMIND what rfc? Apache/1.1 - "EEE', 'dd MMM yyyy hh:mm:ss z", // REMIND what rfc? Apache/1.1 - "EEEE', 'dd MMM yyyy hh:mm:ss z", // REMIND what rfc? Apache/1.1 - "EEE MMM dd HH:mm:ss z yyyy", // Date's string output format - "EEE MMM dd HH:mm:ss yyyy", // ANSI C asctime format() - "EEE', 'dd-MMM-yy HH:mm:ss", // No time zone 2 digit year RFC 1123 - "EEE', 'dd-MMM-yyyy HH:mm:ss" // No time zone RFC 822/1123 - }; - - /* because there are problems with JDK1.1.6/SimpleDateFormat with - * recognizing GMT, we have to create this workaround with the following - * hardcoded strings */ - static final String[] gmtStandardFormats = { - "EEEE',' dd-MMM-yy HH:mm:ss 'GMT'", // RFC 850 (obsoleted by 1036) - "EEE',' dd-MMM-yyyy HH:mm:ss 'GMT'", // RFC 822/1123 - "EEE',' dd MMM yyyy HH:mm:ss 'GMT'", // REMIND what rfc? Apache/1.1 - "EEEE',' dd MMM yyyy HH:mm:ss 'GMT'", // REMIND what rfc? Apache/1.1 - "EEE',' dd MMM yyyy hh:mm:ss 'GMT'", // REMIND what rfc? Apache/1.1 - "EEEE',' dd MMM yyyy hh:mm:ss 'GMT'", // REMIND what rfc? Apache/1.1 - "EEE MMM dd HH:mm:ss 'GMT' yyyy" // Date's string output format - }; - - String dateString; - - public RfcDateParser(String dateString) { - this.dateString = dateString.trim(); - if (this.dateString.indexOf("GMT") != -1) { - isGMT = true; - } - } - - public Date getDate() { - - int arrayLen = isGMT ? gmtStandardFormats.length : standardFormats.length; - for (int i = 0; i < arrayLen; i++) { - Date d = null; - - if (isGMT) { - d = tryParsing(gmtStandardFormats[i]); - } else { - d = tryParsing(standardFormats[i]); - } - if (d != null) { - return d; - } - - } - - return null; - } - - private Date tryParsing(String format) { - - java.text.SimpleDateFormat df = new java.text.SimpleDateFormat(format, Locale.US); - if (isGMT) { - df.setTimeZone(TimeZone.getTimeZone("GMT")); - } - try { - return df.parse(dateString); - } catch (Exception e) { - return null; - } - } -} /* class RfcDateParser */ diff --git a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogClient.java b/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogClient.java deleted file mode 100644 index ccd2d6fe35c7..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogClient.java +++ /dev/null @@ -1,213 +0,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.test.watchdog; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.StringReader; -import java.util.Properties; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import junit.framework.Test; -import junit.framework.TestResult; -import junit.framework.TestSuite; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.EntityResolver; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -public class WatchdogClient { - - protected String goldenDir; - protected String testMatch; - protected String file; - protected String[] exclude = null; - protected String[] slow = - { - "SingleModelTest" // slow - }; - - protected String targetMatch; - - protected int port; - - Properties props = new Properties(); - - protected void beforeSuite() { - } - - protected void afterSuite(TestResult res) { - } - - public Test getSuite() { - return getSuite(port); - } - - public static class NullResolver implements EntityResolver { - public InputSource resolveEntity (String publicId, - String systemId) - throws SAXException, IOException - { - return new InputSource(new StringReader("")); - } - } - - /** Read XML as DOM. - */ - public static Document readXml(InputStream is) - throws SAXException, IOException, ParserConfigurationException - { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setValidating(false); - dbf.setIgnoringComments(false); - dbf.setIgnoringElementContentWhitespace(true); - DocumentBuilder db = null; - db = dbf.newDocumentBuilder(); - db.setEntityResolver( new NullResolver() ); - Document doc = db.parse(is); - return doc; - } - - /** - * Return a test suite for running a watchdog-like - * test file. - * - * @param base base dir for the watchdog dir - * @param testMatch Prefix of tests to be run - * @return - */ - public Test getSuite(int port) { - TestSuite tests = new WatchdogTests(); - tests.setName(this.getClass().getSimpleName()); - - props.setProperty("port", Integer.toString(port)); - props.setProperty("host", "localhost"); - props.setProperty("wgdir", - goldenDir); - - - try { - Document doc = readXml(new FileInputStream(file)); - Element docE = doc.getDocumentElement(); - NodeList targetsL = docE.getElementsByTagName("target"); - for (int i = 0; i < targetsL.getLength(); i++) { - Element target = (Element) targetsL.item(i); - String targetName = target.getAttribute("name"); - if (targetMatch != null && !targetName.equals(targetMatch)) { - continue; - } - - // Tests are duplicated - //TestSuite targetSuite = new TestSuite(targetName); - - NodeList watchDogL = target.getElementsByTagName("watchdog"); - for (int j = 0; j < watchDogL.getLength(); j++) { - Element watchE = (Element) watchDogL.item(j); - String testName = watchE.getAttribute("testName"); - if (single != null && !testName.equals(single)) { - continue; - } - if (testMatch != null) { - if (!testName.startsWith(testMatch)) { - continue; - } - } - if (exclude != null) { - boolean found = false; - for (String e: exclude) { - if (e.equals(testName)) { - found = true; - break; - } - } - if (found) { - continue; - } - } - testName = testName + "(" + this.getClass().getName() + ")"; - WatchdogTestCase test = new WatchdogTestCase(watchE, props, testName); - tests.addTest(test); - if (single != null) { - singleTest = test; - break; - } - } - } - - } catch (IOException e) { - e.printStackTrace(); - } catch (SAXException e) { - e.printStackTrace(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } - return tests; - } - - // --------- Inner classes ------------- - - protected String getWatchdogdir() { - String path = System.getProperty("watchdog.home"); - if (path != null) { - return path; - } - path = ".."; - for (int i = 0; i < 10; i++) { - File f = new File(path + "/watchdog"); - if (f.exists()) { - return f.getAbsolutePath(); - } - path = path + "/.."; - } - return null; - } - - public class WatchdogTests extends TestSuite { - public void run(TestResult res) { - beforeSuite(); - super.run(res); - afterSuite(res); - } - } - - // Support for running a single test in the suite - - protected String single; - WatchdogTestCase singleTest; - - public int countTestCases() { - return 1; - } - - public void run(TestResult result) { - getSuite(); - if (singleTest != null) { - beforeSuite(); - singleTest.run(result); - afterSuite(result); - } - } - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogHttpClient.java b/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogHttpClient.java deleted file mode 100644 index 0763c4896659..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogHttpClient.java +++ /dev/null @@ -1,411 +0,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.test.watchdog; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; -import java.net.SocketException; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Vector; - - -public class WatchdogHttpClient { - private static final String CRLF = "\r\n"; - private static final int LINE_FEED = 10; - - static int debug = 0; - - public static void dispatch(WatchdogTestImpl client) throws Exception { - HashMap requestHeaders = client.requestHeaders; - String host = client.host; - int port = client.port; - String content = client.content; - String request = client.request; - - // XXX headers are ignored - Socket socket; - try { - socket = new Socket( host, port ); - } catch (IOException ex) { - System.out.println( " Socket Exception: " + ex ); - return; - } - socket.setSoTimeout(10000); - - //socket obtained, rebuild the request. - rebuildRequest(client, client.request, socket); - - InputStream in = new CRBufferedInputStream( socket.getInputStream() ); - - // Write the request - socket.setSoLinger( true, 1000 ); - - OutputStream out = new BufferedOutputStream( - socket.getOutputStream() ); - StringBuffer reqbuf = new StringBuffer( 128 ); - - // set the Host header - client.setHeaderDetails( "Host:" + host + ":" + port, requestHeaders, true ); - - // set the Content-Length header - if ( content != null ) { - client.setHeaderDetails( "Content-Length:" + content.length(), - requestHeaders, true ); - } - - // set the Cookie header - if ( client.testSession != null ) { - client.cookieController = ( CookieController ) client.sessionHash.get( client.testSession ); - - if ( client.cookieController != null ) { - - String releventCookieString = client.cookieController.applyRelevantCookies( client.requestURL ); - - if ( ( releventCookieString != null ) && ( !releventCookieString.trim().equals( "" ) ) ) { - client.setHeaderDetails( "Cookie:" + releventCookieString, requestHeaders, true ); - } - } - } - - if ( debug > 0 ) { - System.out.println( " REQUEST: " + request ); - } - reqbuf.append( client.request ).append( CRLF ); - - // append all request headers - if ( !requestHeaders.isEmpty() ) { - Iterator iter = requestHeaders.keySet().iterator(); - - while ( iter.hasNext() ) { - StringBuffer tmpBuf = new StringBuffer(32); - String headerKey = ( String ) iter.next(); - ArrayList values = (ArrayList) requestHeaders.get( headerKey ); - String[] value = (String[]) values.toArray( new String[ values.size() ] ); - tmpBuf.append( headerKey ).append(": "); - for ( int i = 0; i < value.length; i++ ) { - if ((i + 1) == value.length) { - tmpBuf.append( value[ i ] ); - } else { - tmpBuf.append( value[ i ] ).append(", "); - } - } - if ( debug > 0 ) { - System.out.println( " REQUEST HEADER: " + tmpBuf.toString()); - } - tmpBuf.append( CRLF ); - reqbuf.append(tmpBuf.toString()); - } - } - - /* - - if ( ( testSession != null ) && ( sessionHash.get( testSession ) != null ) ) { - System.out.println("Sending Session Id : " + (String)sessionHash.get( testSession ) ); - pw.println("JSESSIONID:" + (String)sessionHash.get( testSession) ); - } - - */ - - if ( request.indexOf( "HTTP/1." ) > -1 ) { - reqbuf.append( "" ).append( CRLF ); - } - - // append request content - if ( content != null ) { - reqbuf.append( content ); - // XXX no CRLF at the end -see HTTP specs! - } - - byte[] reqbytes = reqbuf.toString().getBytes(); - - try { - // write the request - out.write( reqbytes, 0, reqbytes.length ); - out.flush(); - } catch ( Exception ex1 ) { - System.out.println( " Error writing request " + ex1 ); - if ( debug > 0 ) { - System.out.println( "Message: " + ex1.getMessage() ); - ex1.printStackTrace(); - } - } - - // read the response - try { - - client.responseLine = read( in ); - - if ( debug > 0 ) { - System.out.println( " RESPONSE STATUS-LINE: " + client.responseLine ); - } - - client.headers = parseHeaders( client, in ); - - byte[] result = readBody( in ); - - if ( result != null ) { - client.responseBody = result; - if ( debug > 0 ) { - System.out.println( " RESPONSE BODY:\n" + new String( client.responseBody ) ); - } - } - - } catch ( SocketException ex ) { - System.out.println( " Socket Exception: " + ex ); - } finally { - if ( debug > 0 ) { - System.out.println( " closing socket" ); - } - socket.close(); - socket = null; - } - - } - - /** - * readBody reads the body of the response - * from the InputStream. - * - * @param input an InputStream - * @return a byte[] representation of the response - */ - private static byte[] readBody( InputStream input ) { - StringBuffer sb = new StringBuffer( 255 ); - while ( true ) { - try { - int ch = input.read(); - - if ( ch < 0 ) { - if ( sb.length() == 0 ) { - return ( null ); - } else { - break; - } - } - sb.append( ( char ) ch ); - - } catch ( IOException ex ) { - return null; - } - } - return sb.toString().getBytes(); - } - - - /** - * Read a line from the specified servlet input stream, and strip off - * the trailing carriage return and newline (if any). Return the remaining - * characters that were read as a string.7 - * - * @returns The line that was read, or null if end of file - * was encountered - * - * @exception IOException if an input/output error occurred - */ - private static String read( InputStream input ) throws IOException { - // Read the next line from the input stream - StringBuffer sb = new StringBuffer(); - - while ( true ) { - try { - int ch = input.read(); - // System.out.println("XXX " + (char)ch ); - if ( ch < 0 ) { - if ( sb.length() == 0 ) { - if ( debug > 0 ) - System.out.println( " Error reading line " + ch + " " + sb.toString() ); - return ""; - } else { - break; - } - } else if ( ch == LINE_FEED ) { - break; - } - - sb.append( ( char ) ch ); - } catch ( IOException ex ) { - System.out.println( " Error reading : " + ex ); - debug = 1; - - if ( debug > 0 ) { - System.out.println( "Partial read: " + sb.toString() ); - ex.printStackTrace(); - } - input.close(); - break; - } - } - return sb.toString(); - } - - - // ==================== Code from JSERV !!! ==================== - /** - * Parse the incoming HTTP request headers, and set the corresponding - * request properties. - * - * - * @exception IOException if an input/output error occurs - */ - private static HashMap parseHeaders( WatchdogTestImpl client, InputStream is ) throws IOException { - HashMap headers = new HashMap(); - client.cookieVector = new Vector(); - - while ( true ) { - // Read the next header line - String line = read( is ); - - if ( ( line == null ) || ( line.length() < 1 ) ) { - break; - } - - client.parseHeader( line, headers, false ); - - if ( debug > 0 ) { - System.out.println( " RESPONSE HEADER: " + line ); - } - - } - - if ( client.testSession != null ) { - client.cookieController = ( CookieController ) client.sessionHash.get( client.testSession ); - - if ( client.cookieController != null ) { - client.cookieController.recordAnyCookies( client.cookieVector, client.requestURL ); - } - } - - return headers; - } - - - /** - * Private utility method to 'massage' a request string that - * may or may not have replacement markers for the request parameters. - * - * @param req the request to manipulate - * @param socket local socket. Used to rebuild specified query strings. - * - * @exception Exception if an error occurs - */ - private static void rebuildRequest(WatchdogTestImpl client, String req, Socket socket) throws Exception { - client.request = client.replaceMarkers(req, socket ); - String addressString = client.request.substring( client.request.indexOf( "/" ), client.request.indexOf( "HTTP" ) ).trim(); - - if ( addressString.indexOf( "?" ) > -1 ) { - addressString = addressString.substring( 0, addressString.indexOf( "?" ) ) ; - } - - client.requestURL = new URL( "http", client.host, client.port, addressString ); - } - - - /** - * CRBufferedInputStream is a modified version of - * the java.io.BufferedInputStream class. The fill code is - * the same, but the read is modified in that if a carriage return - * is found in the response stream from the target server, - * it will skip that byte and return the next in the stream. - */ - private static class CRBufferedInputStream extends BufferedInputStream { - private static final int CARRIAGE_RETURN = 13; - - private static final int DEFAULT_BUFFER = 2048; - - /** - * Creates a new CRBufferedInputStream instance. - * - * @param in an InputStream value - */ - public CRBufferedInputStream( InputStream in ) { - super( in, DEFAULT_BUFFER ); - } - - /** - * read reads a single byte value per call. - * If, the byte read, is a carriage return, the next byte - * in the stream in returned instead. - * - * @return an int value - * @exception IOException if an error occurs - */ - public int read() throws IOException { - if ( in == null ) { - throw new IOException ( "Stream closed" ); - } - if ( pos >= count ) { - fill(); - if ( pos >= count ) { - return -1; - } - } - int val = buf[pos++] & 0xff; - if ( val == CARRIAGE_RETURN ) { - if (pos >= count) { - fill(); - if (pos >= count) { - return -1; - } - } - return buf[pos++] & 0xff; - } - return val; - } - - /** - * fill is used to fill the internal - * buffer used by this BufferedInputStream class. - * - * @exception IOException if an error occurs - */ - private void fill() throws IOException { - if (markpos < 0) { - pos = 0; /* no mark: throw away the buffer */ - } else if (pos >= buf.length) {/* no room left in buffer */ - if (markpos > 0) { /* can throw away early part of the buffer */ - int sz = pos - markpos; - System.arraycopy(buf, markpos, buf, 0, sz); - pos = sz; - markpos = 0; - } else if (buf.length >= marklimit) { - markpos = -1; /* buffer got too big, invalidate mark */ - pos = 0; /* drop buffer contents */ - } else { /* grow buffer */ - int nsz = pos * 2; - if (nsz > marklimit) - nsz = marklimit; - byte nbuf[] = new byte[nsz]; - System.arraycopy(buf, 0, nbuf, 0, pos); - buf = nbuf; - } - } - count = pos; - int n = in.read(buf, pos, buf.length - pos); - if (n > 0) { - count = n + pos; - } - } - } - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestCase.java b/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestCase.java deleted file mode 100644 index 344f7254980c..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestCase.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - */ -package org.apache.tomcat.test.watchdog; - -import java.util.Properties; - -import junit.framework.AssertionFailedError; -import junit.framework.Test; -import junit.framework.TestResult; - -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; - -public class WatchdogTestCase implements Test { - String testName; - - Element watchE; - - private Properties props; - - private WatchdogClient wc; - - public WatchdogTestCase() { - - } - - public WatchdogTestCase(Element watchE, Properties props, String testName) { - this.testName = testName; - this.watchE = watchE; - this.props = props; - } - - public int countTestCases() { - return 1; - } - - public String getName() { - return testName == null ? "WatchdogTest" : testName; - } - - public String toString() { - return getName(); - } - - public void testDummy() { - } - - public void run(TestResult res) { - if (watchE == null) { - res.endTest(this); - return; - } - WatchdogTestImpl test = new WatchdogTestImpl(); - NamedNodeMap attrs = watchE.getAttributes(); - - for (int i = 0; i < attrs.getLength(); i++) { - Node n = attrs.item(i); - String name = n.getNodeName(); - String value = n.getNodeValue(); - value = AntProperties.replaceProperties(value, props, null); - try { - new DynamicObject(test.getClass()).setProperty(test, - name, value); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - try { - res.startTest(this); - new DynamicObject(test.getClass()).invoke(test, "execute"); - } catch (Throwable e) { - res.addError(this, e); - // res.stop(); - } - - if (test.passCount == 1) { - res.endTest(this); - return; - } else { - if (test.lastError == null) { - res.addFailure(this, new AssertionFailedError(test.request - + " " + test.description + "\n" + test.resultOut)); - } else { - res.addError(this, test.lastError); - } - } - res.endTest(this); - } - -} diff --git a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestImpl.java b/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestImpl.java deleted file mode 100644 index 75715833ccca..000000000000 --- a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestImpl.java +++ /dev/null @@ -1,1172 +0,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. - */ - -/** - * @Author Costin, Ramesh.Mandava - */ - -package org.apache.tomcat.test.watchdog; - -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.InetAddress; -import java.net.Socket; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.StringTokenizer; -import java.util.Vector; - -import org.apache.tomcat.lite.io.Hex; - -// derived from Jsp - -public class WatchdogTestImpl { - - int failureCount = 0; - - int passCount = 0; - - Throwable lastError; - - boolean hasFailed = false; - - String prefix = "http"; - - String host = "localhost"; - - String localHost = null; - - String localIP = null; - - int port = 8080; - - int debug = 0; - - String description = "No description"; - - String request; - - HashMap requestHeaders = new HashMap(); - - String content; - - // true if task is nested - private boolean nested = false; - - // Expected response - boolean magnitude = true; - - boolean exactMatch = false; - - // expect a response body - boolean expectResponseBody = true; - - // Match the body against a golden file - String goldenFile; - - // Match the body against a string - String responseMatch; - - // the response should include the following headers - HashMap expectHeaders = new HashMap(); - - // Headers that should not be found in response - HashMap unexpectedHeaders = new HashMap(); - - // Match request line - String returnCode = ""; - - String returnCodeMsg = ""; - - // Actual response - String responseLine; - - byte[] responseBody; - - HashMap headers; - - // For Report generation - StringBuffer resultOut = new StringBuffer(); - - boolean firstTask = false; - - boolean lastTask = false; - - String expectedString; - - String actualString; - - String testName; - - String assertion; - - String testStrategy; - - // For Session Tracking - static Hashtable sessionHash; - - static Hashtable cookieHash; - - String testSession; - - Vector cookieVector; - - URL requestURL; - - CookieController cookieController; - - /** - * Creates a new GTest instance. - * - */ - public WatchdogTestImpl() { - } - - /** - * setTestSession adds a CookieController for the value of - * sessionName - * - * @param sessionName - * a String value - */ - public void setTestSession(String sessionName) { - testSession = sessionName; - - if (sessionHash == null) { - sessionHash = new Hashtable(); - } else if (sessionHash.get(sessionName) == null) { - sessionHash.put(sessionName, new CookieController()); - } - } - - /** - * setTestName sets the current test name. - * - * @param tn - * current testname. - */ - public void setTestName(String tn) { - testName = tn; - } - - /** - * setAssertion sets the assertion text for the current test. - * - * @param assertion - * assertion text - */ - public void setAssertion(String assertion) { - this.assertion = assertion; - } - - /** - * setTestStrategy sets the test strategy for the current test. - * - * @param strategy - * test strategy text - */ - public void setTestStrategy(String strategy) { - testStrategy = strategy; - } - - /** - * getTestName returns the current test name. - * - * @return a String value - */ - public String getTestName() { - return testName; - } - - /** - * getAssertion returns the current assertion text. - * - * @return a String value - */ - public String getAssertion() { - return assertion; - } - - /** - * getTestStrategy returns the current test strategy test. - * - * @return a String value - */ - public String getTestStrategy() { - return testStrategy; - } - - /** - * setFirstTask denotes that current task being executed is the - * first task within the list. - * - * @param a - * boolean value - */ - public void setFirstTask(boolean val) { - firstTask = val; - } - - /** - * setLastTask denotes that the current task being executed is - * the last task within the list. - * - * @param a - * boolean value - */ - public void setLastTask(boolean val) { - lastTask = val; - } - - /** - * setPrefix sets the protocol prefix. Defaults to "http" - * - * @param prefix - * Either http or https - */ - public void setPrefix(String prefix) { - this.prefix = prefix; - } - - /** - * setHost sets hostname where the target server is running. - * Defaults to "localhost" - * - * @param h - * a String value - */ - public void setHost(String h) { - this.host = h; - } - - /** - * setPort sets the port that the target server is listening - * on. Defaults to "8080" - * - * @param portS - * a String value - */ - public void setPort(String portS) { - this.port = Integer.valueOf(portS).intValue(); - } - - /** - * setExactMatch determines if a byte-by-byte comparsion is - * made of the server's response and the test's goldenFile, or if a token - * comparison is made. By default, only a token comparison is made - * ("false"). - * - * @param exact - * a String value - */ - public void setExactMatch(String exact) { - exactMatch = Boolean.valueOf(exact).booleanValue(); - } - - /** - * setContent String value upon which the request header - * Content-Length is based upon. - * - * @param s - * a String value - */ - public void setContent(String s) { - this.content = s; - } - - /** - * setDebug enables debug output. By default, this is disabled - * ( value of "0" ). - * - * @param debugS - * a String value - */ - public void setDebug(String debugS) { - debug = Integer.valueOf(debugS).intValue(); - } - - /** - * setMagnitude Expected return value of the test execution. - * Defaults to "true" - * - * @param magnitudeS - * a String value - */ - public void setMagnitude(String magnitudeS) { - magnitude = Boolean.valueOf(magnitudeS).booleanValue(); - } - - /** - * setGoldenFile Sets the goldenfile that will be used to - * validate the server's response. - * - * @param s - * fully qualified path and filename - */ - public void setGoldenFile(String s) { - this.goldenFile = s; - } - - /** - * setExpectResponseBody sets a flag to indicate if a response - * body is expected from the server or not - * - * @param b - * a boolean value - */ - public void setExpectResponseBody(boolean b) { - this.expectResponseBody = b; - } - - /** - * setExpectHeaders Configures GTest to look for the header - * passed in the server's response. - * - * @param s - * a String value in the format of - * : - */ - public void setExpectHeaders(String s) { - this.expectHeaders = new HashMap(); - StringTokenizer tok = new StringTokenizer(s, "|"); - while (tok.hasMoreElements()) { - String header = (String) tok.nextElement(); - setHeaderDetails(header, expectHeaders, false); - } - } - - /** - * setUnexpectedHeaders Configures GTest to look for the header - * passed to validate that it doesn't exist in the server's response. - * - * @param s - * a String value in the format of - * : - */ - public void setUnexpectedHeaders(String s) { - this.unexpectedHeaders = new HashMap(); - setHeaderDetails(s, unexpectedHeaders, false); - } - - public void setNested(String s) { - nested = Boolean.valueOf(s).booleanValue(); - } - - /** - * setResponseMatch Match the passed value in the server's - * response. - * - * @param s - * a String value - */ - public void setResponseMatch(String s) { - this.responseMatch = s; - } - - /** - * setRequest Sets the HTTP/HTTPS request to be sent to the - * target server Ex. GET /servlet_path/val HTTP/1.0 - * - * @param s - * a String value in the form of METHOD PATH - * HTTP_VERSION - */ - public void setRequest(String s) { - this.request = s; - } - - /** - * setReturnCode Sets the expected return code from the - * server's response. - * - * @param code - * a valid HTTP response status code - */ - public void setReturnCode(String code) { - this.returnCode = code; - } - - /** - * Describe setReturnCodeMsg Sets the expected return message - * to be found in the server's response. - * - * @param code - * a valid HTTP resonse status code - * @param message - * a String value - */ - public void setReturnCodeMsg(String message) { - this.returnCodeMsg = message; - } - - /** - * setRequestHeaders Configures the request headers GTest - * should send to the target server. - * - * @param s - * a String value in for format of - * : - */ - public void setRequestHeaders(String s) { - requestHeaders = new HashMap(); - StringTokenizer tok = new StringTokenizer(s, "|"); - while (tok.hasMoreElements()) { - String header = (String) tok.nextElement(); - setHeaderDetails(header, requestHeaders, true); - } - } - - // Inner tests are not used currently, can be reworked - - // /** - // * Add a Task to this container - // * - // * @param Task to add - // */ - // public void addTask(Task task) { - // children.add(task); - // } - - /** - * execute Executes the test. - * - * @exception BuildException - * if an error occurs - */ - public void execute() { - - try { - - if (resultOut != null && !nested) { - resultOut.append("\ntestName: " + testName); - resultOut.append("\nreq: " + request); - resultOut.append("\nassertion: " + assertion); - resultOut.append("\ntestStrategy: " + testStrategy); - } - - WatchdogHttpClient.dispatch(this); - - hasFailed = !checkResponse(magnitude); - - // if ( !children.isEmpty() ) { - // Iterator iter = children.iterator(); - // while (iter.hasNext()) { - // Task task = (Task) iter.next(); - // task.perform(); - // } - // } - - if (!hasFailed && !nested) { - passCount++; - if (resultOut != null) { - resultOut.append("PASS\n"); - } -// System.out.println(" PASSED " + testName + " (" -// + request + ")"); - } else if (hasFailed && !nested) { - failureCount++; - if (resultOut != null) { - resultOut.append("FAIL\n"); - } - System.out.println(" FAILED " + testName + "\n (" - + request + ")\n" + resultOut.toString()); - } - - } catch (Exception ex) { - failureCount++; - System.out.println(" FAIL " + description + " (" + request + ")"); - lastError = ex; - ex.printStackTrace(); - } finally { - if (!nested) { - hasFailed = false; - } - } - } - - /** - * checkResponse Executes various response checking mechanisms - * against the server's response. Checks include: - *

      - *
    • expected headers - *
    • unexpected headers - *
    • return codes and messages in the Status-Line - *
    • response body comparison againt a goldenfile - *
    - * - * @param testCondition - * a boolean value - * @return a boolean value - * @exception Exception - * if an error occurs - */ - private boolean checkResponse(boolean testCondition) throws Exception { - boolean match = false; - - if (responseLine != null && !"".equals(responseLine)) { - // If returnCode doesn't match - if (responseLine.indexOf("HTTP/1.") > -1) { - - if (!returnCode.equals("")) { - boolean resCode = (responseLine.indexOf(returnCode) > -1); - boolean resMsg = (responseLine.indexOf(returnCodeMsg) > -1); - - if (returnCodeMsg.equals("")) { - match = resCode; - } else { - match = (resCode && resMsg); - } - - if (match != testCondition) { - - if (resultOut != null) { - String expectedStatusCode = "" - + returnCode + "\n"; - String expectedReasonPhrase = "" - + returnCodeMsg + ""; - actualString = "" + responseLine - + "\n"; - resultOut.append(expectedStatusCode); - resultOut.append(expectedReasonPhrase); - resultOut.append(actualString); - } - - return false; - } - } - } else { - resultOut.append("\nNo response or invalid response: " - + responseLine + ""); - return false; - } - } else { - resultOut.append("\nNo response from server"); - return false; - } - - /* - * Check for headers the test expects to be in the server's response - */ - - // Duplicate set of response headers - HashMap copiedHeaders = cloneHeaders(headers); - - // used for error reporting - String currentHeaderField = null; - String currentHeaderValue = null; - - if (!expectHeaders.isEmpty()) { - boolean found = false; - String expHeader = null; - - if (!headers.isEmpty()) { - Iterator expectIterator = expectHeaders.keySet().iterator(); - while (expectIterator.hasNext()) { - found = false; - String expFieldName = (String) expectIterator.next(); - currentHeaderField = expFieldName; - ArrayList expectValues = (ArrayList) expectHeaders - .get(expFieldName); - Iterator headersIterator = copiedHeaders.keySet() - .iterator(); - - while (headersIterator.hasNext()) { - String headerFieldName = (String) headersIterator - .next(); - ArrayList headerValues = (ArrayList) copiedHeaders - .get(headerFieldName); - - // compare field names and values in an HTTP 1.x - // compliant fashion - if ((headerFieldName.equalsIgnoreCase(expFieldName))) { - int hSize = headerValues.size(); - int eSize = expectValues.size(); - - // number of expected headers found in server - // response - int numberFound = 0; - - for (int i = 0; i < eSize; i++) { - currentHeaderValue = (String) expectValues - .get(i); - - /* - * Handle the Content-Type header appropriately - * based on the the test is configured to look - * for. - */ - if (currentHeaderField - .equalsIgnoreCase("content-type")) { - String resVal = (String) headerValues - .get(0); - if (currentHeaderValue.indexOf(';') > -1) { - if (currentHeaderValue.equals(resVal)) { - numberFound++; - headerValues.remove(0); - } - } else if (resVal - .indexOf(currentHeaderValue) > -1) { - numberFound++; - headerValues.remove(0); - } - } else if (currentHeaderField - .equalsIgnoreCase("location")) { - String resVal = (String) headerValues - .get(0); - int idx = currentHeaderValue - .indexOf(":80/"); - if (idx > -1) { - String tempValue = currentHeaderValue - .substring(0, idx) - + currentHeaderValue - .substring(idx + 3); - if (currentHeaderValue.equals(resVal) - || tempValue.equals(resVal)) { - numberFound++; - headerValues.remove(0); - } - } else { - if (currentHeaderValue.equals(resVal)) { - numberFound++; - headerValues.remove(0); - } - } - } else if (headerValues - .contains(currentHeaderValue)) { - numberFound++; - headerValues.remove(headerValues - .indexOf(currentHeaderValue)); - } - } - if (numberFound == eSize) { - found = true; - } - } - } - if (!found) { - /* - * Expected headers not found in server response. Break - * the processing loop. - */ - break; - } - } - } - - if (!found) { - StringBuffer actualBuffer = new StringBuffer(128); - if (resultOut != null) { - expectedString = "" - + currentHeaderField + ": " + currentHeaderValue - + "\n"; - } - if (!headers.isEmpty()) { - Iterator iter = headers.keySet().iterator(); - while (iter.hasNext()) { - String headerName = (String) iter.next(); - ArrayList vals = (ArrayList) headers.get(headerName); - String[] val = (String[]) vals.toArray(new String[vals - .size()]); - for (int i = 0; i < val.length; i++) { - if (resultOut != null) { - actualBuffer.append("" - + headerName + ": " + val[i] - + "\n"); - } - } - } - if (resultOut != null) { - resultOut.append(expectedString); - resultOut.append(actualBuffer.toString()); - } - } - return false; - } - } - - /* - * Check to see if we're looking for unexpected headers. If we are, - * compare the values in the unexectedHeaders ArrayList against the - * headers from the server response. if the unexpected header is found, - * then return false. - */ - - if (!unexpectedHeaders.isEmpty()) { - boolean found = false; - String unExpHeader = null; - // Check if we got any unexpected headers - - if (!copiedHeaders.isEmpty()) { - Iterator unexpectedIterator = unexpectedHeaders.keySet() - .iterator(); - while (unexpectedIterator.hasNext()) { - found = false; - String unexpectedFieldName = (String) unexpectedIterator - .next(); - ArrayList unexpectedValues = (ArrayList) unexpectedHeaders - .get(unexpectedFieldName); - Iterator headersIterator = copiedHeaders.keySet() - .iterator(); - - while (headersIterator.hasNext()) { - String headerFieldName = (String) headersIterator - .next(); - ArrayList headerValues = (ArrayList) copiedHeaders - .get(headerFieldName); - - // compare field names and values in an HTTP 1.x - // compliant fashion - if ((headerFieldName - .equalsIgnoreCase(unexpectedFieldName))) { - int hSize = headerValues.size(); - int eSize = unexpectedValues.size(); - int numberFound = 0; - for (int i = 0; i < eSize; i++) { - if (headerValues.contains(unexpectedValues - .get(i))) { - numberFound++; - if (headerValues.indexOf(headerFieldName) >= 0) { - headerValues.remove(headerValues - .indexOf(headerFieldName)); - } - } - } - if (numberFound == eSize) { - found = true; - } - } - } - if (!found) { - /* - * Expected headers not found in server response. Break - * the processing loop. - */ - break; - } - } - } - - if (found) { - resultOut.append("\n Unexpected header received from server: " - + unExpHeader); - return false; - } - } - - if (responseMatch != null) { - // check if we got the string we wanted - if (expectResponseBody && responseBody == null) { - resultOut.append("\n ERROR: got no response, expecting " - + responseMatch); - return false; - } - String responseBodyString = new String(responseBody); - if (responseBodyString.indexOf(responseMatch) < 0) { - resultOut.append("\n ERROR: expecting match on " - + responseMatch); - resultOut.append("\n Received: \n" + responseBodyString); - } - } - - if (!expectResponseBody && responseBody != null) { - resultOut - .append("Received a response body from the server where none was expected"); - return false; - } - - // compare the body - if (goldenFile == null) - return true; - - // Get the expected result from the "golden" file. - byte[] expResult = getExpectedResult(); - String expResultS = (expResult == null) ? "" : new String(expResult); - // Compare the results and set the status - boolean cmp = true; - - if (exactMatch) { - cmp = compare(responseBody, expResult); - } else { - cmp = compareWeak(responseBody, expResult); - } - - if (cmp != testCondition) { - - if (resultOut != null) { - expectedString = "" + new String(expResult) - + "\n"; - actualString = "" - + (responseBody != null ? new String(responseBody) - : "null") + "\n"; - resultOut.append(expectedString); - resultOut.append(actualString); - } - - return false; - } - - return true; - } - - /** - * Replaces any |client.ip| and |client.host| parameter marks with the host - * and IP values of the host upon which Watchdog is running. - * - * @param request - * An HTTP request. - */ - String replaceMarkers(String req, Socket socket) { - - final String CLIENT_IP = "client.ip"; - final String CLIENT_HOME = "client.host"; - - if (localIP == null || localHost == null) { - InetAddress addr = socket.getLocalAddress(); - localHost = addr.getHostName(); - localIP = addr.getHostAddress(); - } - - if (req.indexOf('|') > -1) { - StringTokenizer tok = new StringTokenizer(request, "|"); - StringBuffer sb = new StringBuffer(50); - - while (tok.hasMoreElements()) { - String token = tok.nextToken(); - if (token.equals(CLIENT_IP)) { - sb.append(localIP); - } else if (token.equals(CLIENT_HOME)) { - sb.append(localHost); - } else { - sb.append(token); - } - } - return sb.toString(); - } else { - return req; - } - } - - /** - * getExpectedResult returns a byte array containing the - * content of the configured goldenfile - * - * @return goldenfile as a byte[] - * @exception IOException - * if an error occurs - */ - private byte[] getExpectedResult() throws IOException { - byte[] expResult = { 'N', 'O', ' ', 'G', 'O', 'L', 'D', 'E', 'N', 'F', - 'I', 'L', 'E', ' ', 'F', 'O', 'U', 'N', 'D' }; - - try { - InputStream in = new BufferedInputStream(new FileInputStream( - goldenFile)); - return readBody(in); - } catch (Exception ex) { - System.out.println("Golden file not found: " + goldenFile); - return expResult; - } - } - - /** - * compare compares the two byte arrays passed in to verify - * that the lengths of the arrays are equal, and that the content of the two - * arrays, byte for byte are equal. - * - * @param fromServer - * a byte[] value - * @param fromGoldenFile - * a byte[] value - * @return boolean true if equal, otherwise false - */ - private boolean compare(byte[] fromServer, byte[] fromGoldenFile) { - if (fromServer == null || fromGoldenFile == null) { - return false; - } - - /* - * Check to see that the respose and golden file lengths are equal. If - * they are not, dump the hex and don't bother comparing the bytes. If - * they are equal, iterate through the byte arrays and compare each - * byte. If the bytes don't match, dump the hex representation of the - * server response and the goldenfile and return false. - */ - if (fromServer.length != fromGoldenFile.length) { - StringBuffer sb = new StringBuffer(50); - sb.append(" Response and golden files lengths do not match!\n"); - sb.append(" Server response length: "); - sb.append(fromServer.length); - sb.append("\n Goldenfile length: "); - sb.append(fromGoldenFile.length); - resultOut.append(sb.toString()); - sb = null; - // dump the hex representation of the byte arrays - dumpHex(fromServer, fromGoldenFile); - - return false; - } else { - - int i = 0; - int j = 0; - - while ((i < fromServer.length) && (j < fromGoldenFile.length)) { - if (fromServer[i] != fromGoldenFile[j]) { - resultOut.append("\n Error at position " + (i + 1)); - // dump the hex representation of the byte arrays - dumpHex(fromServer, fromGoldenFile); - - return false; - } - - i++; - j++; - } - } - - return true; - } - - /** - * compareWeak creates new Strings from the passed arrays and - * then uses a StringTokenizer to compare non-whitespace tokens. - * - * @param fromServer - * a byte[] value - * @param fromGoldenFile - * a byte[] value - * @return a boolean value - */ - private boolean compareWeak(byte[] fromServer, byte[] fromGoldenFile) { - if (fromServer == null || fromGoldenFile == null) { - return false; - } - - boolean status = true; - - String server = new String(fromServer); - String golden = new String(fromGoldenFile); - - StringTokenizer st1 = new StringTokenizer(server); - - StringTokenizer st2 = new StringTokenizer(golden); - - while (st1.hasMoreTokens() && st2.hasMoreTokens()) { - String tok1 = st1.nextToken(); - String tok2 = st2.nextToken(); - - if (!tok1.equals(tok2)) { - resultOut.append("\t FAIL*** : Rtok1 = " + tok1 + ", Etok2 = " - + tok2); - status = false; - } - } - - if (st1.hasMoreTokens() || st2.hasMoreTokens()) { - status = false; - } - - if (!status) { - StringBuffer sb = new StringBuffer(255); - sb - .append("ERROR: Server's response and configured goldenfile do not match!\n"); - sb.append("Response received from server:\n"); - sb - .append("---------------------------------------------------------\n"); - sb.append(server); - sb.append("\nContent of Goldenfile:\n"); - sb - .append("---------------------------------------------------------\n"); - sb.append(golden); - sb.append("\n"); - resultOut.append(sb.toString()); - } - return status; - } - - /** - * readBody reads the body of the response from the - * InputStream. - * - * @param input - * an InputStream - * @return a byte[] representation of the response - */ - private byte[] readBody(InputStream input) { - StringBuffer sb = new StringBuffer(255); - while (true) { - try { - int ch = input.read(); - - if (ch < 0) { - if (sb.length() == 0) { - return (null); - } else { - break; - } - } - sb.append((char) ch); - - } catch (IOException ex) { - return null; - } - } - return sb.toString().getBytes(); - } - - /** - * setHeaderDetails Wrapper method for parseHeader. Allows easy - * addition of headers to the specified HashMap - * - * @param line - * a String value - * @param headerMap - * a HashMap value - * @param isRequest - * a boolean indicating if the passed Header HashMap - * is for request headers - */ - void setHeaderDetails(String line, HashMap headerHash, boolean isRequest) { - StringTokenizer stk = new StringTokenizer(line, "##"); - - while (stk.hasMoreElements()) { - String presentHeader = stk.nextToken(); - parseHeader(presentHeader, headerHash, isRequest); - } - } - - /** - * parseHeader parses input headers in format of "key:value" - * The parsed header field-name will be used as a key in the passed HashMap - * object, and the values found will be stored in an ArrayList associated - * with the field-name key. - * - * @param line - * String representation of an HTTP header line. - * @param headers - * aHashMap to store key/value header objects. - * @param isRequest - * set to true if the headers being processed are requestHeaders. - */ - void parseHeader(String line, HashMap headerMap, boolean isRequest) { - // Parse the header name and value - int colon = line.indexOf(":"); - - if (colon < 0) { - resultOut - .append("\n ERROR: Header is in incorrect format: " + line); - return; - } - - String name = line.substring(0, colon).trim(); - String value = line.substring(colon + 1).trim(); - - if ((cookieVector != null) && (name.equalsIgnoreCase("Set-Cookie"))) { - cookieVector.addElement(value); - /* - * if ( ( value.indexOf("JSESSIONID") > -1 ) || - * (value.indexOf("jsessionid") > -1 ) ) { String sessionId= - * value.substring( value.indexOf("=")+1); if ( testSession != null - * ) { sessionHash.put( testSession, sessionId ); } - * System.out.println("Got Session-ID : " + sessionId ); } - */ - } - - // System.out.println("HEADER: " +name + " " + value); - - ArrayList values = (ArrayList) headerMap.get(name); - if (values == null) { - values = new ArrayList(); - } - // HACK - if (value.indexOf(',') > -1 && !isRequest - && !name.equalsIgnoreCase("Date")) { - StringTokenizer st = new StringTokenizer(value, ","); - while (st.hasMoreElements()) { - values.add(st.nextToken()); - } - } else { - values.add(value); - } - - headerMap.put(name, values); - } - - /** - * dumpHex helper method to dump formatted hex output of the - * server response and the goldenfile. - * - * @param serverResponse - * a byte[] value - * @param goldenFile - * a byte[] value - */ - private void dumpHex(byte[] serverResponse, byte[] goldenFile) { - StringBuffer outBuf = new StringBuffer( - (serverResponse.length + goldenFile.length) * 2); - - String fromServerString = Hex.getHexDump(serverResponse, 0, - serverResponse.length, true); - String fromGoldenFileString = Hex.getHexDump(goldenFile, 0, - goldenFile.length, true); - - outBuf - .append(" Hex dump of server response and goldenfile below.\n\n### RESPONSE FROM SERVER ###\n"); - outBuf.append("----------------------------\n"); - outBuf.append(fromServerString); - outBuf.append("\n\n### GOLDEN FILE ###\n"); - outBuf.append("-------------------\n"); - outBuf.append(fromGoldenFileString); - outBuf.append("\n\n### END OF DUMP ###\n"); - - resultOut.append(outBuf.toString()); - - } - - /** - * cloneHeaders returns a "cloned" HashMap of the map passed - * in. - * - * @param map - * a HashMap value - * @return a HashMap value - */ - private HashMap cloneHeaders(HashMap map) { - HashMap dupMap = new HashMap(); - Iterator iter = map.keySet().iterator(); - - while (iter.hasNext()) { - String key = new String((String) iter.next()); - ArrayList origValues = (ArrayList) map.get(key); - ArrayList dupValues = new ArrayList(); - - String[] dupVal = (String[]) origValues - .toArray(new String[origValues.size()]); - for (int i = 0; i < dupVal.length; i++) { - dupValues.add(new String(dupVal[i])); - } - - dupMap.put(key, dupValues); - } - return dupMap; - } - -}