hal/src/zutil/net/http/HttpPrintStream.java

318 lines
9.2 KiB
Java
Raw Normal View History

2015-05-27 13:13:19 +00:00
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Ziver Koc
2013-05-28 19:29:24 +00:00
*
2011-07-13 17:53:17 +00:00
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
2013-05-28 19:29:24 +00:00
*
2011-07-13 17:53:17 +00:00
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
2013-05-28 19:29:24 +00:00
*
2011-07-13 17:53:17 +00:00
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
2015-05-27 13:13:19 +00:00
*/
2013-05-28 19:29:24 +00:00
2011-02-15 19:37:35 +00:00
package zutil.net.http;
2008-11-14 16:38:36 +00:00
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
2008-11-14 16:38:36 +00:00
import java.util.HashMap;
/**
* This PrintStream is written for HTTP use
* It has buffer capabilities and cookie management.
*
* @author Ziver
*
*/
public class HttpPrintStream extends OutputStream{
// Defines the type of message
2011-06-24 23:20:59 +00:00
public enum HttpMessageType{
REQUEST,
RESPONSE
}
// The actual output stream
private PrintStream out;
// This defines the type of message that will be generated
2011-06-24 23:20:59 +00:00
private HttpMessageType message_type;
// The status code of the message, ONLY for response
private Integer res_status_code;
// The request type of the message ONLY for request
private String req_type;
// The requesting url ONLY for request
private String req_url;
// An Map of all the header values
2011-06-24 23:20:59 +00:00
private HashMap<String, String> headers;
// An Map of all the cookies
2011-06-24 23:20:59 +00:00
private HashMap<String, String> cookies;
// The buffered header
2008-11-14 16:38:36 +00:00
private StringBuffer buffer;
// If the header buffering is enabled
private boolean buffer_enabled;
2008-11-14 16:38:36 +00:00
/**
* Creates an new instance of HttpPrintStream with
* message type of RESPONSE and buffering disabled.
*
* @param out is the OutputStream to send the message
*/
2008-11-14 16:38:36 +00:00
public HttpPrintStream(OutputStream out) {
2011-06-24 23:20:59 +00:00
this( out, HttpMessageType.RESPONSE );
}
/**
* Creates an new instance of HttpPrintStream with
* message type buffering disabled.
*
* @param out is the OutputStream to send the message
* @param type is the type of message
*/
2011-06-24 23:20:59 +00:00
public HttpPrintStream(OutputStream out, HttpMessageType type) {
this.out = new PrintStream(out);
this.message_type = type;
this.res_status_code = 0;
this.headers = new HashMap<String, String>();
this.cookies = new HashMap<String, String>();
this.buffer = new StringBuffer();
this.buffer_enabled = false;
2008-11-14 16:38:36 +00:00
}
/**
* Enable the buffering capability of the PrintStream.
* Nothing will be sent to the client when buffering
2009-05-17 18:46:05 +00:00
* is enabled until you close or flush the stream.
* This function will flush the stream if buffering is
* disabled.
2008-11-14 16:38:36 +00:00
*
* @param b
*/
public void enableBuffering(boolean b) throws IOException {
2008-11-14 16:38:36 +00:00
buffer_enabled = b;
2009-05-17 18:46:05 +00:00
if(!buffer_enabled) flush();
2008-11-14 16:38:36 +00:00
}
/**
* Adds a cookie that will be sent to the client
*
* @param key is the name of the cookie
* @param value is the value of the cookie
* @throws IOException Throws exception if the header has already been sent
2008-11-14 16:38:36 +00:00
*/
public void setCookie(String key, String value) throws IOException{
2011-06-24 23:20:59 +00:00
if(cookies == null)
throw new IOException("Header already sent!");
2011-06-24 23:20:59 +00:00
cookies.put(key, value);
2008-11-14 16:38:36 +00:00
}
/**
2009-05-17 18:46:05 +00:00
* Adds an header value
2008-11-14 16:38:36 +00:00
*
2009-05-17 18:46:05 +00:00
* @param key is the header name
* @param value is the value of the header
* @throws IOException Throws exception if the header has already been sent
2008-11-14 16:38:36 +00:00
*/
public void setHeader(String key, String value) throws IOException{
2011-06-24 23:20:59 +00:00
if(headers == null)
throw new IOException("Header already sent!");
2011-06-24 23:20:59 +00:00
headers.put(key, value);
2009-05-17 18:46:05 +00:00
}
2009-05-17 18:46:05 +00:00
/**
* Sets the status code of the message, ONLY available in HTTP RESPONSE
2009-05-17 18:46:05 +00:00
*
* @param code the code from 100 up to 599
* @throws IOException if the header has already been sent or the message type is wrong
2009-05-17 18:46:05 +00:00
*/
public void setStatusCode(int code) throws IOException{
if( res_status_code == null )
throw new IOException("Header already sent!");
2011-06-24 23:20:59 +00:00
if( message_type != HttpMessageType.RESPONSE )
throw new IOException("Status Code is only available in HTTP RESPONSE!");
res_status_code = code;
}
/**
* Sets the request type of the message, ONLY available in HTTP REQUEST
*
* @param req_type is the type of the message, e.g. GET, POST...
* @throws IOException if the header has already been sent or the message type is wrong
*/
public void setRequestType(String req_type) throws IOException{
if( req_type == null )
throw new IOException("Header already sent!");
2011-06-24 23:20:59 +00:00
if( message_type != HttpMessageType.REQUEST )
throw new IOException("Request Message Type is only available in HTTP REQUEST!");
this.req_type = req_type;
}
/**
* Sets the requesting URL of the message, ONLY available in HTTP REQUEST
*
* @param req_url is the URL
* @throws IOException if the header has already been sent or the message type is wrong
*/
public void setRequestURL(String req_url) throws IOException{
if( req_url == null )
throw new IOException("Header already sent!");
2011-06-24 23:20:59 +00:00
if( message_type != HttpMessageType.REQUEST )
throw new IOException("Request URL is only available in HTTP REQUEST!");
this.req_url = req_url;
2008-11-14 16:38:36 +00:00
}
2011-06-24 23:20:59 +00:00
protected void setHeaders( HashMap<String,String> map ){
headers = map;
}
protected void setCookies( HashMap<String,String> map ){
cookies = map;
}
/**
* Prints a new line
*/
public void println() throws IOException {
printOrBuffer(System.lineSeparator());
}
2008-11-14 16:38:36 +00:00
/**
* Prints with a new line
2008-11-14 16:38:36 +00:00
*/
public void println(String s) throws IOException {
printOrBuffer(s + System.lineSeparator());
2008-11-14 16:38:36 +00:00
}
/**
* Prints an string
2008-11-14 16:38:36 +00:00
*/
public void print(String s) throws IOException {
printOrBuffer(s);
2008-11-14 16:38:36 +00:00
}
2009-05-17 18:46:05 +00:00
2008-11-14 16:38:36 +00:00
/**
* Will buffer String or directly output headers if needed and then the String
2008-11-14 16:38:36 +00:00
*/
private void printOrBuffer(String s) throws IOException {
2008-11-14 16:38:36 +00:00
if(buffer_enabled){
buffer.append(s);
}
else{
if(res_status_code != null){
2011-06-24 23:20:59 +00:00
if( message_type==HttpMessageType.REQUEST )
out.print(req_type + " " + req_url + " HTTP/1.0");
else
out.print("HTTP/1.0 " + res_status_code + " " + getStatusString(res_status_code));
out.println();
res_status_code = null;
req_type = null;
req_url = null;
2009-05-17 18:46:05 +00:00
}
2011-06-24 23:20:59 +00:00
if(headers != null){
for(String key : headers.keySet()){
out.println(key + ": " + headers.get(key));
2009-05-17 18:46:05 +00:00
}
2011-06-24 23:20:59 +00:00
headers = null;
2009-05-17 18:46:05 +00:00
}
2011-06-24 23:20:59 +00:00
if(cookies != null){
if( !cookies.isEmpty() ){
if( message_type==HttpMessageType.REQUEST ){
out.print("Cookie: ");
for(String key : cookies.keySet()){
out.print(key + "=" + cookies.get(key) + "; ");
}
out.println();
}
else{
for(String key : cookies.keySet()){
out.print("Set-Cookie: " + key + "=" + cookies.get(key) + ";");
out.print(System.lineSeparator());
}
}
2008-11-14 16:38:36 +00:00
}
out.print(System.lineSeparator());
2011-06-24 23:20:59 +00:00
cookies = null;
2008-11-14 16:38:36 +00:00
}
out.print(s);
2008-11-14 16:38:36 +00:00
}
}
/**
* @return if headers has been sent. The setHeader, setStatusCode, setCookie method will throw Exceptions
*/
public boolean isHeaderSent() {
return res_status_code == null && headers == null && cookies == null;
}
2008-11-14 16:38:36 +00:00
/**
* Sends out the buffer and clears it
2008-11-14 16:38:36 +00:00
*/
@Override
public void flush() throws IOException {
flushBuffer();
out.flush();
}
@Override
public void close() throws IOException {
flush();
out.close();
}
protected void flushBuffer() throws IOException {
2008-11-14 16:38:36 +00:00
if(buffer_enabled){
buffer_enabled = false;
printOrBuffer(buffer.toString());
buffer.delete(0, buffer.length());
buffer_enabled = true;
2009-05-17 18:46:05 +00:00
}
2011-06-24 23:20:59 +00:00
else if(res_status_code != null || headers != null || cookies != null){
2009-05-17 18:46:05 +00:00
printOrBuffer("");
}
2008-11-14 16:38:36 +00:00
}
2009-05-17 18:46:05 +00:00
/**
* Will flush all buffers and write binary data to stream
*/
@Override
public void write(int b) throws IOException {
flushBuffer();
out.write(b);
}
/**
* * Will flush all buffers and write binary data to stream
*/
@Override
public void write(byte[] buf, int off, int len) throws IOException {
flushBuffer();
out.write(buf, off, len);
}
private void rawWrite(String s) throws IOException {
out.write(s.getBytes());
}
2009-05-17 18:46:05 +00:00
private String getStatusString(int type){
switch(type){
case 100: return "Continue";
case 200: return "OK";
case 301: return "Moved Permanently";
case 307: return "Temporary Redirect";
case 400: return "Bad Request";
case 401: return "Unauthorized";
case 403: return "Forbidden";
case 404: return "Not Found";
case 500: return "Internal Server Error";
case 501: return "Not Implemented";
default: return "";
}
}
2008-11-14 16:38:36 +00:00
}