diff options
Diffstat (limited to 'simple/simple-http/src/main/java/org/simpleframework/http/core/RequestCollector.java')
-rw-r--r-- | simple/simple-http/src/main/java/org/simpleframework/http/core/RequestCollector.java | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/simple/simple-http/src/main/java/org/simpleframework/http/core/RequestCollector.java b/simple/simple-http/src/main/java/org/simpleframework/http/core/RequestCollector.java new file mode 100644 index 0000000..027318d --- /dev/null +++ b/simple/simple-http/src/main/java/org/simpleframework/http/core/RequestCollector.java @@ -0,0 +1,184 @@ +/* + * RequestCollector.java October 2002 + * + * Copyright (C) 2002, Niall Gallagher <niallg@users.sf.net> + * + * 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. + */ + +package org.simpleframework.http.core; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static org.simpleframework.http.core.ContainerEvent.REQUEST_READY; +import static org.simpleframework.transport.TransportEvent.READ_WAIT; + +import java.io.IOException; +import java.nio.channels.SocketChannel; + +import org.simpleframework.common.buffer.Allocator; +import org.simpleframework.http.message.Body; +import org.simpleframework.http.message.EntityConsumer; +import org.simpleframework.http.message.Header; +import org.simpleframework.transport.Channel; +import org.simpleframework.transport.ByteCursor; +import org.simpleframework.transport.trace.Trace; + +/** + * The <code>RequestCollector</code> object is used to collect all of + * the data used to form a request entity. This will collect the data + * fragment by fragment from the underlying transport. When all of + * the data is consumed and the entity is created and then it is sent + * to the <code>Selector</code> object for processing. If the request + * has completed the next request can be collected from the + * underlying transport using a new collector object. + * + * @author Niall Gallagher + */ +class RequestCollector implements Collector { + + /** + * This is used to consume the request entity from the channel. + */ + private final EntityConsumer entity; + + /** + * This is the cursor used to read and reset the data. + */ + private final ByteCursor cursor; + + /** + * This is the channel used to acquire the underlying data. + */ + private final Channel channel; + + /** + * This is the trace used to listen for various collect events. + */ + private final Trace trace; + + /** + * This represents the time the request collection began at. + */ + private final Timer timer; + + /** + * The <code>RequestCollector</code> object used to collect the data + * from the underlying transport. In order to collect a body this + * must be given an <code>Allocator</code> which is used to create + * an internal buffer to store the consumed body. + * + * @param allocator this is the allocator used to buffer data + * @param tracker this is the tracker used to create sessions + * @param channel this is the channel used to read the data + */ + public RequestCollector(Allocator allocator, Channel channel) { + this.entity = new EntityConsumer(allocator, channel); + this.timer = new Timer(MILLISECONDS); + this.cursor = channel.getCursor(); + this.trace = channel.getTrace(); + this.channel = channel; + } + + /** + * This is used to collect the data from a <code>Channel</code> + * which is used to compose the entity. If at any stage there + * are no ready bytes on the socket the controller provided can + * be used to queue the collector until such time as the socket + * is ready to read. Also, should the entity have completed reading + * all required content it is handed to the controller as ready, + * which processes the entity as a new client HTTP request. + * + * @param controller this is the controller used to queue this + */ + public void collect(Controller controller) throws IOException { + while(cursor.isReady()) { + if(entity.isFinished()) { + break; + } else { + timer.set(); + entity.consume(cursor); + } + } + if(cursor.isOpen()) { + if(entity.isFinished()) { + trace.trace(REQUEST_READY); + controller.ready(this); + } else { + trace.trace(READ_WAIT); + controller.select(this); + } + } + } + + /** + * This is the time in milliseconds when the request was first + * read from the underlying channel. The time represented here + * represents the time collection of this request began. This + * does not necessarily represent the time the bytes arrived on + * the receive buffers as some data may have been buffered. + * + * @return this represents the time the request was ready at + */ + public long getTime() { + return timer.get(); + } + + /** + * This provides the HTTP request header for the entity. This is + * always populated and provides the details sent by the client + * such as the target URI and the query if specified. Also this + * can be used to determine the method and protocol version used. + * + * @return the header provided by the HTTP request message + */ + public Header getHeader() { + return entity.getHeader(); + } + + /** + * This is used to acquire the body for this HTTP entity. This + * will return a body which can be used to read the content of + * the message, also if the request is multipart upload then all + * of the parts are provided as <code>Part</code> objects. Each + * part can then be read as an individual message. + * + * @return the body provided by the HTTP request message + */ + public Body getBody() { + return entity.getBody(); + } + + /** + * This provides the connected channel for the client. This is + * used to send and receive bytes to and from an transport layer. + * Each channel provided with an entity contains an attribute + * map which contains information about the connection. + * + * @return the connected channel for this HTTP entity + */ + public Channel getChannel() { + return channel; + } + + /** + * This returns the socket channel that is used by the collector + * to read content from. This is a selectable socket, in that + * it can be registered with a Java NIO selector. This ensures + * that the system can be notified when the socket is ready. + * + * @return the socket channel used by this collector object + */ + public SocketChannel getSocket() { + return channel.getSocket(); + } +}
\ No newline at end of file |