2011-07-13 17:53:17 +00:00
|
|
|
/*******************************************************************************
|
2013-05-28 19:29:24 +00:00
|
|
|
* Copyright (c) 2013 Ziver
|
|
|
|
|
*
|
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.
|
|
|
|
|
******************************************************************************/
|
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.OutputStream;
|
|
|
|
|
import java.io.PrintStream;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This PrintStream is written for HTTP use
|
|
|
|
|
* It has buffer capabilities and cookie management.
|
|
|
|
|
*
|
|
|
|
|
* @author Ziver
|
|
|
|
|
*
|
|
|
|
|
*/
|
2010-01-31 18:10:00 +00:00
|
|
|
public class HttpPrintStream extends PrintStream{
|
|
|
|
|
// Defines the type of message
|
2011-06-24 23:20:59 +00:00
|
|
|
public enum HttpMessageType{
|
2010-01-31 18:10:00 +00:00
|
|
|
REQUEST,
|
|
|
|
|
RESPONSE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This defines the type of message that will be generated
|
2011-06-24 23:20:59 +00:00
|
|
|
private HttpMessageType message_type;
|
2010-01-31 18:10:00 +00:00
|
|
|
// 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;
|
2010-01-31 18:10:00 +00:00
|
|
|
// An Map of all the cookies
|
2011-06-24 23:20:59 +00:00
|
|
|
private HashMap<String, String> cookies;
|
2010-01-31 18:10:00 +00:00
|
|
|
// The buffered header
|
2008-11-14 16:38:36 +00:00
|
|
|
private StringBuffer buffer;
|
2010-01-31 18:10:00 +00:00
|
|
|
// If the header buffering is enabled
|
|
|
|
|
private boolean buffer_enabled;
|
2008-11-14 16:38:36 +00:00
|
|
|
|
2010-01-31 18:10:00 +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 );
|
2010-01-31 18:10:00 +00:00
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 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) {
|
2008-11-14 16:38:36 +00:00
|
|
|
super(out);
|
|
|
|
|
|
2010-01-31 18:10:00 +00:00
|
|
|
this.message_type = type;
|
|
|
|
|
res_status_code = 0;
|
2011-06-24 23:20:59 +00:00
|
|
|
headers = new HashMap<String, String>();
|
|
|
|
|
cookies = new HashMap<String, String>();
|
2008-11-14 16:38:36 +00:00
|
|
|
buffer = new StringBuffer();
|
|
|
|
|
buffer_enabled = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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){
|
|
|
|
|
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
|
|
|
|
|
*
|
2009-02-26 17:10:57 +00:00
|
|
|
* @param key is the name of the cookie
|
|
|
|
|
* @param value is the value of the cookie
|
2008-11-14 16:38:36 +00:00
|
|
|
* @throws Exception Throws exception if the header has already been sent
|
|
|
|
|
*/
|
2010-01-31 18:10:00 +00:00
|
|
|
public void setCookie(String key, String value) throws RuntimeException{
|
2011-06-24 23:20:59 +00:00
|
|
|
if(cookies == null)
|
2010-01-31 18:10:00 +00:00
|
|
|
throw new RuntimeException("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
|
2008-11-14 16:38:36 +00:00
|
|
|
* @throws Exception Throws exception if the header has already been sent
|
|
|
|
|
*/
|
2010-01-31 18:10:00 +00:00
|
|
|
public void setHeader(String key, String value) throws RuntimeException{
|
2011-06-24 23:20:59 +00:00
|
|
|
if(headers == null)
|
2010-01-31 18:10:00 +00:00
|
|
|
throw new RuntimeException("Header already sent!!!");
|
2011-06-24 23:20:59 +00:00
|
|
|
headers.put(key, value);
|
2009-05-17 18:46:05 +00:00
|
|
|
}
|
2010-01-31 18:10:00 +00:00
|
|
|
|
2009-05-17 18:46:05 +00:00
|
|
|
/**
|
2010-01-31 18:10:00 +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
|
2010-01-31 18:10:00 +00:00
|
|
|
* @throws RuntimeException if the header has already been sent or the message type is wrong
|
2009-05-17 18:46:05 +00:00
|
|
|
*/
|
2010-01-31 18:10:00 +00:00
|
|
|
public void setStatusCode(int code) throws RuntimeException{
|
|
|
|
|
if( res_status_code == null )
|
|
|
|
|
throw new RuntimeException("Header already sent!!!");
|
2011-06-24 23:20:59 +00:00
|
|
|
if( message_type != HttpMessageType.RESPONSE )
|
2010-01-31 18:10:00 +00:00
|
|
|
throw new RuntimeException("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 RuntimeException if the header has already been sent or the message type is wrong
|
|
|
|
|
*/
|
|
|
|
|
public void setRequestType(String req_type) throws RuntimeException{
|
|
|
|
|
if( req_type == null )
|
|
|
|
|
throw new RuntimeException("Header already sent!!!");
|
2011-06-24 23:20:59 +00:00
|
|
|
if( message_type != HttpMessageType.REQUEST )
|
2010-01-31 18:10:00 +00:00
|
|
|
throw new RuntimeException("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 RuntimeException if the header has already been sent or the message type is wrong
|
|
|
|
|
*/
|
|
|
|
|
public void setRequestURL(String req_url) throws RuntimeException{
|
|
|
|
|
if( req_url == null )
|
|
|
|
|
throw new RuntimeException("Header already sent!!!");
|
2011-06-24 23:20:59 +00:00
|
|
|
if( message_type != HttpMessageType.REQUEST )
|
2010-01-31 18:10:00 +00:00
|
|
|
throw new RuntimeException("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;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-14 16:38:36 +00:00
|
|
|
/**
|
2009-02-26 17:10:57 +00:00
|
|
|
* Prints with a new line
|
2008-11-14 16:38:36 +00:00
|
|
|
*/
|
|
|
|
|
public void println(String s){
|
|
|
|
|
printOrBuffer(s+"\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2009-04-16 20:51:15 +00:00
|
|
|
* Prints an string
|
2008-11-14 16:38:36 +00:00
|
|
|
*/
|
|
|
|
|
public void print(String s){
|
2009-04-16 20:51:15 +00:00
|
|
|
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
|
|
|
/**
|
|
|
|
|
* prints to all
|
|
|
|
|
*/
|
2009-04-16 20:51:15 +00:00
|
|
|
private void printOrBuffer(String s){
|
2008-11-14 16:38:36 +00:00
|
|
|
if(buffer_enabled){
|
|
|
|
|
buffer.append(s);
|
|
|
|
|
}
|
|
|
|
|
else{
|
2010-01-31 18:10:00 +00:00
|
|
|
if(res_status_code != null){
|
2011-06-24 23:20:59 +00:00
|
|
|
if( message_type==HttpMessageType.REQUEST )
|
|
|
|
|
super.print(req_type+" "+req_url+" HTTP/1.0");
|
2010-01-31 18:10:00 +00:00
|
|
|
else
|
2011-06-24 23:20:59 +00:00
|
|
|
super.print("HTTP/1.0 "+res_status_code+" "+getStatusString(res_status_code));
|
2015-03-23 21:05:51 +00:00
|
|
|
super.print(System.lineSeparator());
|
2010-01-31 18:10:00 +00:00
|
|
|
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()){
|
|
|
|
|
super.print(key+": "+headers.get(key));
|
2015-03-23 21:05:51 +00:00
|
|
|
super.print(System.lineSeparator());
|
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 ){
|
2010-01-31 18:10:00 +00:00
|
|
|
super.print("Cookie: ");
|
2011-06-24 23:20:59 +00:00
|
|
|
for(String key : cookies.keySet()){
|
|
|
|
|
super.print(key+"="+cookies.get(key)+"; ");
|
2010-01-31 18:10:00 +00:00
|
|
|
}
|
2015-03-23 21:05:51 +00:00
|
|
|
super.print(System.lineSeparator());
|
2010-01-31 18:10:00 +00:00
|
|
|
}
|
|
|
|
|
else{
|
2011-06-24 23:20:59 +00:00
|
|
|
for(String key : cookies.keySet()){
|
|
|
|
|
super.print("Set-Cookie: "+key+"="+cookies.get(key)+";");
|
2015-03-23 21:05:51 +00:00
|
|
|
super.print(System.lineSeparator());
|
2010-01-31 18:10:00 +00:00
|
|
|
}
|
|
|
|
|
}
|
2008-11-14 16:38:36 +00:00
|
|
|
}
|
2015-03-23 21:05:51 +00:00
|
|
|
super.print(System.lineSeparator());
|
2011-06-24 23:20:59 +00:00
|
|
|
cookies = null;
|
2008-11-14 16:38:36 +00:00
|
|
|
}
|
|
|
|
|
super.print(s);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2009-02-26 17:10:57 +00:00
|
|
|
* Sends out the buffer and clears it
|
2008-11-14 16:38:36 +00:00
|
|
|
*/
|
|
|
|
|
public void flush(){
|
|
|
|
|
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
|
|
|
super.flush();
|
|
|
|
|
}
|
2009-05-17 18:46:05 +00:00
|
|
|
|
2008-11-14 16:38:36 +00:00
|
|
|
public void close(){
|
|
|
|
|
flush();
|
|
|
|
|
super.close();
|
|
|
|
|
}
|
2009-05-17 18:46:05 +00:00
|
|
|
|
2008-11-14 16:38:36 +00:00
|
|
|
public void println(){ println("");}
|
2009-04-16 20:51:15 +00:00
|
|
|
public void println(boolean x){ println(String.valueOf(x));}
|
|
|
|
|
public void println(char x){ println(String.valueOf(x));}
|
2008-11-14 16:38:36 +00:00
|
|
|
public void println(char[] x){ println(new String(x));}
|
2009-04-16 20:51:15 +00:00
|
|
|
public void println(double x){ println(String.valueOf(x));}
|
|
|
|
|
public void println(float x){ println(String.valueOf(x));}
|
|
|
|
|
public void println(int x){ println(String.valueOf(x));}
|
|
|
|
|
public void println(long x){ println(String.valueOf(x));}
|
|
|
|
|
public void println(Object x){ println(String.valueOf(x));}
|
2009-05-17 18:46:05 +00:00
|
|
|
|
2009-04-16 20:51:15 +00:00
|
|
|
public void print(boolean x){ printOrBuffer(String.valueOf(x));}
|
|
|
|
|
public void print(char x){ printOrBuffer(String.valueOf(x));}
|
2008-11-14 16:38:36 +00:00
|
|
|
public void print(char[] x){ printOrBuffer(new String(x));}
|
2009-04-16 20:51:15 +00:00
|
|
|
public void print(double x){ printOrBuffer(String.valueOf(x));}
|
|
|
|
|
public void print(float x){ printOrBuffer(String.valueOf(x));}
|
|
|
|
|
public void print(int x){ printOrBuffer(String.valueOf(x));}
|
|
|
|
|
public void print(long x){ printOrBuffer(String.valueOf(x));}
|
|
|
|
|
public void print(Object x){ printOrBuffer(String.valueOf(x));}
|
2010-01-31 18:10:00 +00:00
|
|
|
|
2009-05-17 18:46:05 +00:00
|
|
|
/*
|
|
|
|
|
public void write(int b) { print((char)b);}
|
|
|
|
|
public void write(byte buf[], int off, int len){
|
|
|
|
|
print(new String(buf, off, len));}
|
|
|
|
|
*/
|
|
|
|
|
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
|
|
|
}
|