package httpRecorder.proxy;

/*
 * Disclaimer:
 * The following source code is sample code created by IBM Corporation.  
 * This sample code is not part of any standard IBM product and is provided 
 * to you solely for the purpose of assisting you in the development of your 
 * applications.  The code is provided 'AS IS', without warranty or condition 
 * of any kind.  IBM shall not be liable for any damages arising out of your 
 * use of the sample code, even if IBM has been advised of the possibility of 
 * such damages.
 */

import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;

/**
 * Abstract class with the common attributes of an HTTP request and response.
 * 
 * Some headers may have extra information:
 * 		<i>content-type</i>: Boolean value indication if the content is text format.
 * 
 * The interval attribute shows the number of miliseconds between the creation
 * of a request and the previous one.
 */

public abstract class HttpElement
{
	public static final String DEFAULT_VERSION = "HTTP/1.1";
	
	private long creationTime;
	private String line;
	private String version;
	private Hashtable headersByName;
	private byte[] body;
	private String fromIpAddress;
	private String toIpAddress;
				
	public HttpElement()
	{
		creationTime = System.currentTimeMillis();
		version = DEFAULT_VERSION;
		headersByName = new Hashtable();
	}

	public void parse(InputStream inputStream)
	throws IOException
	{
		while(true)
		{
			String mainLine = ProxyUtil.readLine(inputStream, ProxyUtil.ENTIRE_LINE);
			if((mainLine == null) || mainLine.equals(HttpProxy.CRLF))
				break;
				
			mainLine = mainLine.trim();
			if(line == null)
				line = mainLine;
			else
				addHeader(new HttpHeader(mainLine));
		}
		
		//if(inputStream.available() > 0)
			setBody(inputStream);
			
		if(line != null)
			parse();
	}
	
	protected abstract void setBody(InputStream inputStream) throws IOException;	
	protected abstract void parse() throws IOException;
	
	protected boolean isValid(HttpHeader header)
	{
		return	(header != null)
				&& (header.getName() != null);
	}
	
	protected void addHeader(HttpHeader header)
	{
		if(isValid(header))
		{
			headersByName.put(header.getName(), header);
			header.setElement(this);
		}		
	}
	
	public long getCreationTime()
	{
		return creationTime;
	}
	
	public String getVersion()
	{
		return version;
	}
	
	protected void setVersion(String version)
	{
		this.version = version;
	}

	protected void setLine(String line)
	{
		this.line = line;
	}
	
	public String getLine()
	{
		return line;
	}

	protected void setFromIpAddress(String ipAddress)
	{
		fromIpAddress = ipAddress;
	}
	
	protected String getFromIpAddress()
	{
		return fromIpAddress;
	}

	protected void setToIpAddress(String ipAddress)
	{
		toIpAddress = ipAddress;
	}
	
	protected String getToIpAddress()
	{
		return toIpAddress;
	}

	public HttpHeader[] getHeaders()
	{
		return (HttpHeader[])headersByName.values().toArray(new HttpHeader[headersByName.values().size()]);
	}
	
	public HttpHeader getHeader(String name)
	{
		return (HttpHeader)headersByName.get(name);
	}
	
	public String getHeaderValue(String name)
	{
		HttpHeader header = getHeader(name);
		if(header == null)
			return null;
			
		return header.getValue();
	}
	
	public int getHeaderIntValue(String name)
	{
		HttpHeader header = getHeader(name);
		if(header != null)
		{
			try
			{
				return Integer.parseInt(header.getValue());
			}
			catch(NumberFormatException nfe)
			{
			}
		}
		
		return -1;
	}
	
	
	protected void setBody(byte[] body)
	{
		this.body = ProxyUtil.trim(body);
	}

	public byte[] getBody()
	{
		return body;
	}
		
	public String toString()
	{
		return toString(0, null);
	}

	public String toString(int identation, String extraAttributes)
	{
		if(extraAttributes == null)
			extraAttributes = "";
		else if(!extraAttributes.startsWith(""))
			extraAttributes = " " + extraAttributes;

		StringBuffer tabs = new StringBuffer();
		for(int i=0; i<identation; i++)
			tabs.append("\t");
			
		StringBuffer request = new StringBuffer();
		request.append(tabs);
		request.append("<").append(xmlTopElement()).append(xmlAttributes());
		request.append(extraAttributes);
		request.append(">");
		HttpHeader[] headersArray = getHeaders();
		for(int i=0; i<headersArray.length; i++)
		{
			request.append("\n").append(tabs).append("\t");
			
			request.append("<header");
			request.append(ProxyUtil.xmlAttribute("name", headersArray[i].getName()));
			request.append(ProxyUtil.xmlAttribute("value", headersArray[i].getValue()));
			request.append("/>");
		}
		
		if(body != null)
		{
			String sBody = new String(body).trim();
			if(!"".equals(sBody))
			{
				request.append("\n").append(tabs).append("\t");
				
				request.append("<body>");
				request.append(ProxyUtil.useValidXMLCharacters(sBody));
				request.append("</body>");
			}
		}

		request.append("\n").append(tabs);
		request.append("</").append(xmlTopElement()).append(">");
		
		return request.toString();
	}
	
	protected abstract String xmlTopElement();
	
	protected StringBuffer xmlAttributes()
	{
		StringBuffer attributes = new StringBuffer();	
		attributes.append(ProxyUtil.xmlAttribute("version", getVersion()));
		attributes.append(ProxyUtil.xmlAttribute("creationTime", new Long(getCreationTime()).toString()));
		attributes.append(ProxyUtil.xmlAttribute("fromIpAddress", getFromIpAddress()));
		attributes.append(ProxyUtil.xmlAttribute("toIpAddress", getToIpAddress()));
		return attributes;
	}		
}
