/*
 * Copyright (C) 2009-2010, Google Inc.
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.http.server;

import static javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT;
import static javax.servlet.http.HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE;
import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT_RANGES;
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_LENGTH;
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_RANGE;
import static org.eclipse.jgit.util.HttpSupport.HDR_IF_RANGE;
import static org.eclipse.jgit.util.HttpSupport.HDR_RANGE;

import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.text.MessageFormat;
import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jgit.lib.ObjectId;

/**
 * Dumps a file over HTTP GET (or its information via HEAD).
 * <p>
 * Supports a single byte range requested via {@code Range} HTTP header. This
 * feature supports a dumb client to resume download of a larger object file.
 */
final class FileSender {
	private final File path;

	private final RandomAccessFile source;

	private final long lastModified;

	private final long fileLen;

	private long pos;

	private long end;

	FileSender(final File path) throws FileNotFoundException {
		this.path = path;
		this.source = new RandomAccessFile(path, "r");

		try {
			this.lastModified = path.lastModified();
			this.fileLen = source.getChannel().size();
			this.end = fileLen;
		} catch (IOException e) {
			try {
				source.close();
			} catch (IOException closeError) {
				// Ignore any error closing the stream.
			}

			final FileNotFoundException r;
			r = new FileNotFoundException(MessageFormat.format(HttpServerText.get().cannotGetLengthOf, path));
			r.initCause(e);
			throw r;
		}
	}

	void close() {
		try {
			source.close();
		} catch (IOException e) {
			// Ignore close errors on a read-only stream.
		}
	}

	long getLastModified() {
		return lastModified;
	}

	String getTailChecksum() throws IOException {
		final int n = 20;
		final byte[] buf = new byte[n];
		source.seek(fileLen - n);
		source.readFully(buf, 0, n);
		return ObjectId.fromRaw(buf).getName();
	}

	void serve(final HttpServletRequest req, final HttpServletResponse rsp,
			final boolean sendBody) throws IOException {
		if (!initRangeRequest(req, rsp)) {
			rsp.sendError(SC_REQUESTED_RANGE_NOT_SATISFIABLE);
			return;
		}

		rsp.setHeader(HDR_ACCEPT_RANGES, "bytes");
		rsp.setHeader(HDR_CONTENT_LENGTH, Long.toString(end - pos));

		if (sendBody) {
			final OutputStream out = rsp.getOutputStream();
			try {
				final byte[] buf = new byte[4096];
				source.seek(pos);
				while (pos < end) {
					final int r = (int) Math.min(buf.length, end - pos);
					final int n = source.read(buf, 0, r);
					if (n < 0) {
						throw new EOFException(MessageFormat.format(HttpServerText.get().unexpectedeOFOn, path));
					}
					out.write(buf, 0, n);
					pos += n;
				}
				out.flush();
			} finally {
				out.close();
			}
		}
	}

	private boolean initRangeRequest(final HttpServletRequest req,
			final HttpServletResponse rsp) throws IOException {
		final Enumeration<String> rangeHeaders = getRange(req);
		if (!rangeHeaders.hasMoreElements()) {
			// No range headers, the request is fine.
			return true;
		}

		final String range = rangeHeaders.nextElement();
		if (rangeHeaders.hasMoreElements()) {
			// To simplify the code we support only one range.
			return false;
		}

		final int eq = range.indexOf('=');
		final int dash = range.indexOf('-');
		if (eq < 0 || dash < 0 || !range.startsWith("bytes=")) {
			return false;
		}

		final String ifRange = req.getHeader(HDR_IF_RANGE);
		if (ifRange != null && !getTailChecksum().equals(ifRange)) {
			// If the client asked us to verify the ETag and its not
			// what they expected we need to send the entire content.
			return true;
		}

		try {
			if (eq + 1 == dash) {
				// "bytes=-500" means last 500 bytes
				pos = Long.parseLong(range.substring(dash + 1));
				pos = fileLen - pos;
			} else {
				// "bytes=500-" (position 500 to end)
				// "bytes=500-1000" (position 500 to 1000)
				pos = Long.parseLong(range.substring(eq + 1, dash));
				if (dash < range.length() - 1) {
					end = Long.parseLong(range.substring(dash + 1));
					end++; // range was inclusive, want exclusive
				}
			}
		} catch (NumberFormatException e) {
			// We probably hit here because of a non-digit such as
			// "," appearing at the end of the first range telling
			// us there is a second range following. To simplify
			// the code we support only one range.
			return false;
		}

		if (end > fileLen) {
			end = fileLen;
		}
		if (pos >= end) {
			return false;
		}

		rsp.setStatus(SC_PARTIAL_CONTENT);
		rsp.setHeader(HDR_CONTENT_RANGE, "bytes " + pos + "-" + (end - 1) + "/"
				+ fileLen);
		source.seek(pos);
		return true;
	}

	private static Enumeration<String> getRange(final HttpServletRequest req) {
		return req.getHeaders(HDR_RANGE);
	}
}
