summaryrefslogtreecommitdiffstats
path: root/simple/simple-http/src/main/java/org/simpleframework/http/core/RequestCollector.java
diff options
context:
space:
mode:
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.java184
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