/*
 * Paraselene
 * Copyright (c) 2009, 2010  Akira Terasaki
 * このファイルは同梱されているLicense.txtに定めた条件に同意できる場合にのみ
 * 利用可能です。
 */
package paraselene.supervisor;

import paraselene.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import java.util.zip.*;

class NullForward extends Forward {
	void Action( Supervisor sp, HttpServletResponse res ) throws Exception {
	}
}

interface CacheAjax {
	void writeTo( HttpServletResponse res ) throws IOException;
}

class CacheWriter extends PrintWriter implements CacheAjax {
	private CharArrayWriter	caw;
	private String	charset;
	private String	ctype;

	CacheWriter( Page p, String mime, RequestParameter param, SessionData data ){
		super( new CharArrayWriter() );
		caw = (CharArrayWriter)out;
		charset = p.getCharset();
		ctype = mime;
	}

	public void writeTo( HttpServletResponse res ) throws IOException {
		res.setContentLength( caw.toString().getBytes( charset ).length );
		writeTo( res, res.getWriter() );
	}

	void writeTo( HttpServletResponse res, PrintWriter w ) throws IOException {
		res.setContentType( ctype );
		caw.writeTo( w );
		w.flush();
	}
}

class CacheBin implements CacheAjax {
	private boolean gzip;
	private byte[]	buf = new byte[1024 * 64];
	private int	size;
	private String	ctype;

	CacheBin( String mime, boolean gzip_f ) {
		ctype = mime;
		gzip = gzip_f;
	}

	private OutputStream getOutpuStream( HttpServletResponse res ) throws IOException {
		if ( gzip ) {
			return new GZIPOutputStream( res.getOutputStream() );
		}
		return new BufferedOutputStream( res.getOutputStream() );
	}

	private void flush( OutputStream out ) throws IOException {
		if ( out instanceof GZIPOutputStream ) {
			((GZIPOutputStream)out).finish();
		}
		out.flush();
	}

	private void write_once( RequestParameter param, SessionData data, HttpServletResponse res ) throws IOException {
		if ( !gzip )	res.setContentLength( size );
		OutputStream	out = getOutpuStream( res );
		out.write( buf, 0, size );
		flush( out );
		byte[]	tmp = new byte[size];
		for ( int i = 0; i < size; i++ ) {
			tmp[i] = buf[i];
		}
		buf = tmp;
	}

	void write( Downloadable dl, RequestParameter param, SessionData data, HttpServletResponse res ) throws IOException, Page.PageException {
		BufferedInputStream	in = new BufferedInputStream( dl.getInputStream() );
		try {
			size = in.read( buf );
			if ( size < buf.length ) {
				write_once( param, data, res );
				return;
			}
			OutputStream	out = getOutpuStream( res );
			while( true ) {
				out.write( buf, 0, size );
				if ( size < buf.length )	break;
				size = in.read( buf );
				if ( size <= 0 )	break;
			}
			flush( out );
		}
		finally {
			if ( in != null )	in.close();
		}
	}

	public void writeTo( HttpServletResponse res ) throws IOException {
		if ( gzip )	res.addHeader( "Content-Encoding", "gzip" );
		res.setContentType( ctype );
		res.setContentLength( size );
		OutputStream	out = getOutpuStream( res );
		out.write( buf, 0, size );
		flush( out );
		res.flushBuffer();
		out.close();
	}
}

