/* * Reader.java February 2001 * * Copyright (C) 2001, 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 java.nio.channels.SocketChannel; import org.simpleframework.transport.Channel; import org.simpleframework.transport.reactor.Operation; /** * The <code>Reader</code> object is used to read the bytes to form a request * entity. In order to execute a read operation the socket must be read ready. * This is determined using the socket object, which is registered with a * selector. If at any point the reading results in an error the operation is * canceled and the collector is closed, which shuts down the connection. * * @author Niall Gallagher * * @see org.simpleframework.transport.reactor.Reactor */ class Reader implements Operation { /** * This is the selector used to process the collection events. */ private final Selector source; /** * This is the collector used to consume the entity bytes. */ private final Collector task; /** * This is the channel object associated with the collector. */ private final Channel channel; /** * Constructor for the <code>Reader</code> object. This requires a selector * and a collector object in order to consume the data from the connected * socket which forms a HTTP request entity. * * @param source * the selector object used to process events * @param task * this is the task used to collect the entity */ public Reader(Selector source, Collector task) { this.channel = task.getChannel(); this.source = source; this.task = task; } /** * This is the <code>SocketChannel</code> used to determine if the * connection has some bytes that can be read. If it contains any data then * that data is read from and is used to compose the request entity, which * consists of a HTTP header and body. * * @return this returns the socket for the connected pipeline */ @Override public SocketChannel getChannel() { return this.task.getSocket(); } /** * This <code>run</code> method is used to collect the bytes from the * connected channel. If a sufficient amount of data is read from the socket * to form a HTTP entity then the collector uses the <code>Selector</code> * object to dispatch the request. This is sequence of events that occur for * each transaction. */ @Override public void run() { try { this.task.collect(this.source); } catch (Throwable e) { this.cancel(); } } /** * This is used to cancel the operation if it has timed out. If the retry is * waiting too long to read content from the socket then the retry is * canceled and the underlying transport is closed. This helps to clean up * occupied resources. */ @Override public void cancel() { try { this.channel.close(); } catch (Throwable e) { return; } } }