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

org.xsocket.connection.http.ResponseHeader Maven / Gradle / Ivy

There is a newer version: 2.0-beta-1
Show newest version
/*
 *  Copyright (c) xsocket.org, 2006 - 2008. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
 * The latest copy of this software may be found on http://www.xsocket.org/
 */
package org.xsocket.connection.http;

import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.logging.Logger;

import org.xsocket.DataConverter;
import org.xsocket.IDataSink;
import org.xsocket.connection.INonBlockingConnection;



/**
 * http response header representation
 *
 * @author [email protected]
 */
public final class ResponseHeader extends AbstractMessageHeader  {
	
	private static final Logger LOG = Logger.getLogger(ResponseHeader.class.getName());
	
	
	private ByteBuffer[] rawHeader = null;
	
	private int statusCode = 0;
	private String reason = null; 
	private String protocol = null;

	private boolean isRedirectedResponse = false;
	
	
	// performance optimization
	private String server = null;

	
	/**
	 * constructor 
	 * 
	 * @param statusCode  the status code
	 */
	public ResponseHeader(int statusCode) {
		this(statusCode, null, getReason(statusCode));
	}

	
	/**
	 * constructor 
	 * 
	 * @param contentType  the content type 
	 */
	public ResponseHeader(String contentType) {
		this(200, contentType);
	}

	

	/**
	 * constructor 
	 * 
	 * @param statusCode   the status code 
	 * @param contentType  the content type
	 */
	public ResponseHeader(int statusCode, String contentType) {
		this(statusCode, contentType, getReason(statusCode));
	}

	
	/**
	 * constructor 
	 * 
	 * @param statusCode   the status code
	 * @param contentType  the content type
	 * @param reason       the reason
	 */
	public ResponseHeader(int statusCode, String contentType, String reason) {
		this("HTTP/1.1", statusCode, contentType, reason);
	}
	

	/**
	 * constructor 
	 * 
	 * @param protocol      the protocol
	 * @param statusCode    the status code 
	 * @param contentType   the content type
	 * @param reason        the reason
	 */
	ResponseHeader(String protocol, int statusCode, String contentType, String reason) {
		this.protocol = protocol;
		this.statusCode = statusCode;
		this.reason = reason;
		
		if (contentType != null) {
			setContentType(contentType);
		}
	}

	
	private ResponseHeader(ByteBuffer[] rawHeader) throws IOException {
		this.rawHeader = rawHeader;
		
		String header = DataConverter.toString(rawHeader, "ISO-8859-1");
		String[] headerlines = header.split("\r\n");
		
		// unfolding lines if necessary
		headerlines = unfoldingHeaderlines(headerlines);

		
		for (String line : headerlines) {
			
			if (line.length() == 0) {
				LOG.warning("got m response header with empty line:\r\n" + header);
				continue;
			}
			
			
			// read first line
			if (protocol == null) {
				int pos1 = line.indexOf(" ");
				protocol = line.substring(0, pos1);
				
				int pos2 = line.indexOf(" ", pos1 + 1);
				statusCode = Integer.parseInt(line.substring(pos1 + 1, pos2));
				
				if ((pos2 + 1) < line.length()) {
					reason = line.substring(pos2 + 1, line.length());
				} else {
					reason = "HTTP/1.0";
				}
			
			// read the remaining
			} else {
				addHeaderLineSilence(line);
			}
		}
	}
	 

	/**
	 * copy the headers 
	 * 
	 * @param otherHeader         the other response header
	 * @param upperExcludenames   the header names to exclude
	 */
	public void copyHeaderFrom(ResponseHeader otherHeader, String... upperExcludenames) {
		super.copyHeaderFrom(otherHeader, upperExcludenames);
	}
	
	
	/**
	 * sets the is redirected flag
	 * 
	 * @param isRedirectedResponse the redirected flag
	 */
	void setRedirectedResponse(boolean isRedirectedResponse) {
		this.isRedirectedResponse = isRedirectedResponse;
	}
	
	
	/**
	 * gets the is redirected flag
	 * 
	 * @return isRedirectedResponse the redirected flag
	 */	
	boolean isRedirectedResponse() {
		return isRedirectedResponse;
	}

	
	
	/**
	 * returns the status 
	 * 
	 * @return the status 
	 */
	public int getStatus() {
		return statusCode;
	}
	
	
	/**
	 * returns the reason
	 * 
	 * @return the reason 
	 */
	public String getReason() {
		return reason;
	}
	
	
	/**
	 * returns the protocol 
	 * 
	 * @return the protocol
	 */
	public String getProtocol() {
		return protocol;
	}
	

	/**
	 * sets the server header 
	 * 
	 * @param server  the server header 
	 */
	public void setServer(String server) {
		setHeader(SERVER, server);
	}
	
	
	/**
	 * gets the server header 
	 * 
	 * @return the server header
	 */
	public String getServer() {
		return server;
	}
	
	
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	void onHeaderAdded(String upperHeadername, String headervalue) {
		super.onHeaderAdded(upperHeadername, headervalue);
		
		if (upperHeadername.equals("SERVER")) {
			server = headervalue;
		}
	}


	/**
	 * {@inheritDoc}
	 */
	@Override
	void onHeaderRemoved(String upperHeadername) {
		super.onHeaderRemoved(upperHeadername);
		
		if (upperHeadername.equals("SERVER")) {
			server = null;
		}
	}
	
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		
		sb.append(protocol + " " + statusCode + " " + reason + "\r\n");
		sb.append(printHeaders());
			
		// write blank line
		sb.append("\r\n");
		return sb.toString();
	}
	
	
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final int writeTo(IDataSink dataSink) throws IOException {

		if (!isHeadersModified() && (rawHeader != null)) {			
			int written = (int) dataSink.write(rawHeader);
			written += dataSink.write("\r\n\r\n"); 
			rawHeader = null; // necessary, because byte buffers pointer will be modified by writing
		    return written;
		    
		} else {
			return dataSink.write(toString());
		}
	}
	
	
	/**
	 * read the response header from the given connection
	 *  
	 * @param connection    the tcp connection
	 * @param maxLength     max length to read 
	 * @return the response header 
	 * 
	 * @throws BufferUnderflowException  if not enough data is available
	 * @throws IOException if some other error occurs 
	 */
	public static ResponseHeader readFrom(INonBlockingConnection connection, int maxLength) throws BufferUnderflowException, IOException {
		ByteBuffer[] rawHeader = connection.readByteBufferByDelimiter("\r\n\r\n", "US-ASCII", maxLength);
		return new ResponseHeader(rawHeader);
	}



	private static String getReason(int statusCode) {
		switch (statusCode) {
		case 200:
			return "OK";

		case 404:
			return "Not found";
			
		case 504:
			return "Gateway Timeout";
			
		default:
			return " ";
		}

	}
}	




© 2015 - 2025 Weber Informatics LLC | Privacy Policy