All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.kingsoft.services.http.impl.RepeatableInputStreamRequestEntity Maven / Gradle / Ivy

package com.kingsoft.services.http.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.entity.InputStreamEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.kingsoft.services.HttpHeaders;
import com.kingsoft.services.RequestMessage;

public class RepeatableInputStreamRequestEntity extends BasicHttpEntity {

	/** True if the request entity hasn't been written out yet */
	private boolean firstAttempt = true;

	/** The underlying InputStreamEntity being delegated to */
	private InputStreamEntity inputStreamRequestEntity;

	/** The InputStream containing the content to write out */
	private InputStream content;

	private static final Logger log = LoggerFactory
			.getLogger(RepeatableInputStreamRequestEntity.class);

	/**
	 * Record the original exception if we do attempt a retry, so that if the
	 * retry fails, we can report the original exception. Otherwise, we're most
	 * likely masking the real exception with an error about not being able to
	 * reset far enough back in the input stream.
	 */
	private IOException originalException;

	public RepeatableInputStreamRequestEntity(final RequestMessage request) {
		setChunked(false);

		/*
		 * If we don't specify a content length when we instantiate our
		 * InputStreamRequestEntity, then HttpClient will attempt to buffer the
		 * entire stream contents into memory to determine the content length.
		 * 
		 * TODO: It'd be nice to have easier access to content length and
		 * content type from the request, instead of having to look directly
		 * into the headers.
		 */
		long contentLength = -1;
		try {
			String contentLengthString = request.getHeaders().get(
					HttpHeaders.CONTENT_LENGTH);
			if (contentLengthString != null) {
				contentLength = Long.parseLong(contentLengthString);
			} else {
				throw new IllegalStateException(String.format(
						"can not find %s header", HttpHeaders.CONTENT_LENGTH));
			}
		} catch (NumberFormatException nfe) {
			log.error("Unable to parse content length from request.  "
					+ "Buffering contents in memory.");
			throw nfe;
		}

		String contentType = request.getHeaders().get("Content-Type");

		inputStreamRequestEntity = new InputStreamEntity(request.getContent(),
				contentLength);

		inputStreamRequestEntity.setContentType(contentType);
		content = request.getContent();

		setContent(content);
		setContentType(contentType);
		setContentLength(contentLength);
	}

	@Override
	public boolean isChunked() {
		return false;
	}

	/**
	 * Returns true if the underlying InputStream supports marking/reseting or
	 * if the underlying InputStreamRequestEntity is repeatable (i.e. its
	 * content length has been set to
	 * {@link InputStreamRequestEntity#CONTENT_LENGTH_AUTO} and therefore its
	 * entire contents will be buffered in memory and can be repeated).
	 *
	 * @see org.apache.commons.httpclient.methods.RequestEntity#isRepeatable()
	 */
	@Override
	public boolean isRepeatable() {
		return content.markSupported()
				|| inputStreamRequestEntity.isRepeatable();
	}

	/**
	 * Resets the underlying InputStream if this isn't the first attempt to
	 * write out the request, otherwise simply delegates to
	 * InputStreamRequestEntity to write out the data.
	 * 

* If an error is encountered the first time we try to write the request * entity, we remember the original exception, and report that as the root * cause if we continue to encounter errors, rather than masking the * original error. * * @see org.apache.commons.httpclient.methods.RequestEntity#writeRequest(java.io.OutputStream) */ @Override public void writeTo(OutputStream output) throws IOException { try { if (!firstAttempt && isRepeatable()) content.reset(); firstAttempt = false; inputStreamRequestEntity.writeTo(output); } catch (IOException ioe) { if (originalException == null) originalException = ioe; throw originalException; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy