@ -49,7 +49,6 @@
package de.anomic.http ;
package de.anomic.http ;
import java.io.ByteArrayInputStream ;
import java.io.ByteArrayOutputStream ;
import java.io.ByteArrayOutputStream ;
import java.io.File ;
import java.io.File ;
import java.io.FileOutputStream ;
import java.io.FileOutputStream ;
@ -82,10 +81,11 @@ import org.apache.commons.pool.impl.GenericObjectPool;
import de.anomic.server.serverByteBuffer ;
import de.anomic.server.serverByteBuffer ;
import de.anomic.server.serverCodings ;
import de.anomic.server.serverCodings ;
import de.anomic.server.serverCore ;
import de.anomic.server.serverCore ;
import de.anomic.server.serverLog ;
import de.anomic.server.serverObjects ;
import de.anomic.server.serverObjects ;
import de.anomic.server.logging.serverLog ;
import de.anomic.server.serverCore.Session ;
import de.anomic.server.serverCore.Session ;
public final class httpc {
public final class httpc {
// statics
// statics
@ -126,6 +126,8 @@ public final class httpc {
java . security . Security . setProperty ( "networkaddress.cache.negative.ttl" , "0" ) ;
java . security . Security . setProperty ( "networkaddress.cache.negative.ttl" , "0" ) ;
}
}
/ * *
/ * *
* A Object Pool containing all pooled httpc - objects .
* A Object Pool containing all pooled httpc - objects .
* @see httpcPool
* @see httpcPool
@ -164,6 +166,11 @@ public final class httpc {
* /
* /
final serverByteBuffer readLineBuffer = new serverByteBuffer ( ) ;
final serverByteBuffer readLineBuffer = new serverByteBuffer ( ) ;
public String toString ( ) {
return ( this . savedRemoteHost = = null ) ? "Disconnected" : "Connected to " + this . savedRemoteHost +
( ( this . remoteProxyUse ) ? " via " + this . host : "" ) ;
}
public static httpc getInstance (
public static httpc getInstance (
String server ,
String server ,
int port ,
int port ,
@ -371,9 +378,10 @@ public final class httpc {
// header information
// header information
public httpHeader responseHeader = null ;
public httpHeader responseHeader = null ;
public String httpVer = "HTTP/0.9" ;
public String status ; // the success/failure response string starting with status-code
public String status ; // the success/failure response string starting with status-code
private boolean gzip ; // for gunzipping on-the-fly
private boolean gzip ; // for gunzipping on-the-fly
private long gzipLength ; // zipped-length of the response
private String encoding ;
public response ( boolean zipped ) throws IOException {
public response ( boolean zipped ) throws IOException {
@ -390,7 +398,7 @@ public final class httpc {
}
}
// reads in the http header, right now, right here
// reads in the http header, right now, right here
byte [ ] b = serverCore . receive ( clientInput , readLineBuffer , t imeout, t erminalMaxLength, false ) ;
byte [ ] b = serverCore . receive ( clientInput , readLineBuffer , t erminalMaxLength, false ) ;
if ( b = = null ) {
if ( b = = null ) {
// the server has meanwhile disconnected
// the server has meanwhile disconnected
status = "503 server has closed connection" ;
status = "503 server has closed connection" ;
@ -402,9 +410,12 @@ public final class httpc {
if ( p < 0 ) {
if ( p < 0 ) {
status = "500 status line parse error" ;
status = "500 status line parse error" ;
// flush in anything that comes without parsing
// flush in anything that comes without parsing
while ( ( b = serverCore . receive ( clientInput , readLineBuffer , t imeout, t erminalMaxLength, false ) ). length ! = 0 ) { }
while ( ( b != null ) & & ( b . length ! = 0 ) ) b = serverCore . receive ( clientInput , readLineBuffer , t erminalMaxLength, false ) ;
return ; // in bad mood
return ; // in bad mood
}
}
// the http version reported by the server
this . httpVer = buffer . substring ( 0 , p ) ;
// we have a status
// we have a status
status = buffer . substring ( p + 1 ) . trim ( ) ; // the status code plus reason-phrase
status = buffer . substring ( p + 1 ) . trim ( ) ; // the status code plus reason-phrase
@ -412,13 +423,13 @@ public final class httpc {
if ( status . startsWith ( "400" ) ) {
if ( status . startsWith ( "400" ) ) {
// bad request
// bad request
// flush in anything that comes without parsing
// flush in anything that comes without parsing
while ( ( b = serverCore . receive ( clientInput , readLineBuffer , t imeout, t erminalMaxLength, false ) ) . length ! = 0 ) { }
while ( ( b = serverCore . receive ( clientInput , readLineBuffer , t erminalMaxLength, false ) ) . length ! = 0 ) { }
return ; // in bad mood
return ; // in bad mood
}
}
// at this point we should have a valid response. read in the header properties
// at this point we should have a valid response. read in the header properties
String key = "" ;
String key = "" ;
while ( ( b = serverCore . receive ( clientInput , readLineBuffer , t imeout, t erminalMaxLength, false ) ) ! = null ) {
while ( ( b = serverCore . receive ( clientInput , readLineBuffer , t erminalMaxLength, false ) ) ! = null ) {
if ( b . length = = 0 ) break ;
if ( b . length = = 0 ) break ;
buffer = new String ( b ) ;
buffer = new String ( b ) ;
//System.out.println("#H#" + buffer); // debug
//System.out.println("#H#" + buffer); // debug
@ -446,18 +457,17 @@ public final class httpc {
gzip = ( ( zipped ) & & ( responseHeader . gzip ( ) ) ) ;
gzip = ( ( zipped ) & & ( responseHeader . gzip ( ) ) ) ;
if ( gzip ) {
if ( gzip ) {
// change attributes in case of gzip decoding
gzipLength = responseHeader . contentLength ( ) ;
responseHeader . remove ( "CONTENT-ENCODING" ) ; // we fake that we don't have encoding, since what comes out does not have gzip and we also don't know what was encoded
responseHeader . remove ( "CONTENT-ENCODING" ) ; // we fake that we don't have encoding, since what comes out does not have gzip and we also don't know what was encoded
responseHeader . remove ( "CONTENT-LENGTH" ) ; // we cannot use the length during gunzippig yet; still we can hope that it works
responseHeader . remove ( "CONTENT-LENGTH" ) ; // we cannot use the length during gunzippig yet; still we can hope that it works
} else {
}
gzipLength = - 1 ;
}
}
//System.out.println("###incoming header: " + responseHeader.toString());
public String toString ( ) {
StringBuffer toStringBuffer = new StringBuffer ( ) ;
// the body must be read separately by the get/writeContent methods
toStringBuffer . append ( ( this . status = = null ) ? "Status: Unknown" : "Status: " + this . status )
//System.out.println("## connection is " + ((socket.isClosed()) ? "closed" : "open") + ".");
. append ( " | Headers: " )
. append ( ( this . responseHeader = = null ) ? "none" : this . responseHeader . toString ( ) ) ;
return toStringBuffer . toString ( ) ;
}
}
public boolean success ( ) {
public boolean success ( ) {
@ -498,69 +508,42 @@ public final class httpc {
long len = 0 ;
long len = 0 ;
// find out length
// find out length
long length = responseHeader . contentLength ( ) ;
long length = this . responseHeader . contentLength ( ) ;
// using the proper intput stream
InputStream dis = ( this . gzip ) ? ( InputStream ) new GZIPInputStream ( clientInput ) : ( InputStream ) clientInput ;
// we have three methods of reading: length-based, length-based gzip and connection-close-based
// we have three methods of reading: length-based, length-based gzip and connection-close-based
try {
if ( length > 0 ) {
if ( length > 0 ) {
// we read exactly 'length' bytes
// we read exactly 'length' bytes
try {
while ( ( len < length ) & & ( ( l = dis . read ( buffer ) ) > = 0 ) ) {
while ( ( len < length ) & & ( ( l = clientInput . read ( buffer ) ) > = 0 ) ) {
if ( procOS ! = null ) procOS . write ( buffer , 0 , l ) ;
if ( procOS ! = null ) procOS . write ( buffer , 0 , l ) ;
if ( bufferOS ! = null ) bufferOS . write ( buffer , 0 , l ) ;
if ( bufferOS ! = null ) bufferOS . write ( buffer , 0 , l ) ;
len + = l ;
len + = l ;
}
}
} catch ( java . net . SocketException e ) {
// this is an error:
throw new IOException ( "Socket exception: " + e . getMessage ( ) ) ;
} catch ( java . net . SocketTimeoutException e ) {
// this is an error:
throw new IOException ( "Socket time-out: " + e . getMessage ( ) ) ;
}
} else if ( ( gzip ) & & ( gzipLength > 0 ) & & ( gzipLength < 100000 ) ) {
//System.out.println("PERFORMING NEW GZIP-LENGTH-BASED HTTPC: gzipLength=" + gzipLength); // DEBUG
// we read exactly 'gzipLength' bytes; first copy into buffer:
ByteArrayOutputStream baos = new ByteArrayOutputStream ( ) ;
while ( ( len < gzipLength ) & & ( ( l = clientInput . read ( buffer ) ) > = 0 ) ) {
baos . write ( buffer , 0 , l ) ;
len + = l ;
}
baos . flush ( ) ;
// now uncompress
InputStream dis = new GZIPInputStream ( new ByteArrayInputStream ( baos . toByteArray ( ) ) ) ;
try {
while ( ( l = dis . read ( buffer ) ) > 0 ) {
if ( procOS ! = null ) procOS . write ( buffer , 0 , l ) ;
if ( bufferOS ! = null ) bufferOS . write ( buffer , 0 , l ) ;
len + = l ;
}
} catch ( java . net . SocketException e ) {
// this is an error:
throw new IOException ( "Socket exception: " + e . getMessage ( ) ) ;
} catch ( java . net . SocketTimeoutException e ) {
// this is an error:
throw new IOException ( "Socket time-out: " + e . getMessage ( ) ) ;
}
baos . close ( ) ; baos = null ;
} else {
} else {
// no content-length was given, thus we read until the connection closes
// no content-length was given, thus we read until the connection closes
InputStream dis = ( gzip ) ? ( InputStream ) new GZIPInputStream ( clientInput ) : ( InputStream ) clientInput ;
try {
while ( ( l = dis . read ( buffer , 0 , buffer . length ) ) > = 0 ) {
while ( ( l = dis . read ( buffer , 0 , buffer . length ) ) > = 0 ) {
if ( procOS ! = null ) procOS . write ( buffer , 0 , l ) ;
if ( procOS ! = null ) procOS . write ( buffer , 0 , l ) ;
if ( bufferOS ! = null ) bufferOS . write ( buffer , 0 , l ) ;
if ( bufferOS ! = null ) bufferOS . write ( buffer , 0 , l ) ;
}
}
}
} catch ( java . net . SocketException e ) {
} catch ( java . net . SocketException e ) {
// this is not an error: it's ok, we waited for that
throw new IOException ( "Socket exception: " + e . getMessage ( ) ) ;
} catch ( java . net . SocketTimeoutException e ) {
} catch ( java . net . SocketTimeoutException e ) {
// the same here; should be ok.
throw new IOException ( "Socket time-out: " + e . getMessage ( ) ) ;
}
} finally {
}
// close the streams
// close the streams
if ( procOS ! = null ) procOS . flush ( ) ;
if ( procOS ! = null ) {
if ( procOS instanceof httpChunkedOutputStream )
( ( httpChunkedOutputStream ) procOS ) . finish ( ) ;
procOS . flush ( ) ;
}
if ( bufferOS ! = null ) bufferOS . flush ( ) ;
if ( bufferOS ! = null ) bufferOS . flush ( ) ;
buffer = null ;
buffer = null ;
}
}
}
public void print ( ) {
public void print ( ) {
serverLog . logInfo ( "HTTPC" , "RESPONSE: status=" + status + ", header=" + responseHeader . toString ( ) ) ;
serverLog . logInfo ( "HTTPC" , "RESPONSE: status=" + status + ", header=" + responseHeader . toString ( ) ) ;
@ -659,7 +642,6 @@ public final class httpc {
//System.out.println("***HEADER for path " + path + ": PROXY TO SERVER = " + header.toString()); // DEBUG
//System.out.println("***HEADER for path " + path + ": PROXY TO SERVER = " + header.toString()); // DEBUG
Iterator i = header . keySet ( ) . iterator ( ) ;
Iterator i = header . keySet ( ) . iterator ( ) ;
String key ;
String key ;
String value ;
int count ;
int count ;
char tag ;
char tag ;
while ( i . hasNext ( ) ) {
while ( i . hasNext ( ) ) {
@ -668,35 +650,28 @@ public final class httpc {
if ( ( tag ! = '*' ) & & ( tag ! = '#' ) ) {
if ( ( tag ! = '*' ) & & ( tag ! = '#' ) ) {
count = header . keyCount ( key ) ;
count = header . keyCount ( key ) ;
for ( int j = 0 ; j < count ; j + + ) {
for ( int j = 0 ; j < count ; j + + ) {
serverCore . send ( clientOutput, key + ": " + ( ( String ) header . getSingle ( key , j ) ) . trim ( ) ) ;
serverCore . send ( this . clientOutput, key + ": " + ( ( String ) header . getSingle ( key , j ) ) . trim ( ) ) ;
}
}
//System.out.println("#" + key + ": " + value);
//System.out.println("#" + key + ": " + value);
}
}
}
}
// send terminating line
// send terminating line
serverCore . send ( clientOutput, "" ) ;
serverCore . send ( this . clientOutput, "" ) ;
clientOutput. flush ( ) ;
this . clientOutput. flush ( ) ;
// this is the place where www.stern.de refuses to answer ..???
// this is the place where www.stern.de refuses to answer ..???
}
}
private boolean shallTransportZipped ( String path ) {
return ( ! ( ( path . endsWith ( ".gz" ) ) | | ( path . endsWith ( ".tgz" ) ) | |
( path . endsWith ( ".jpg" ) ) | | ( path . endsWith ( ".jpeg" ) ) | |
( path . endsWith ( ".gif" ) ) | ( path . endsWith ( ".zip" ) ) ) ) ;
}
public response GET ( String path , httpHeader requestHeader ) throws IOException {
public response GET ( String path , httpHeader requestHeader ) throws IOException {
//serverLog.logDebug("HTTPC", handle + " requested GET '" + path + "', time = " + (System.currentTimeMillis() - handle));
//serverLog.logDebug("HTTPC", handle + " requested GET '" + path + "', time = " + (System.currentTimeMillis() - handle));
try {
try {
boolean zipped = shallTransportZipped( path ) ;
boolean zipped = httpd . shallTransportZipped ( path ) ;
send ( httpHeader . METHOD_GET , path , requestHeader , zipped ) ;
send ( httpHeader . METHOD_GET , path , requestHeader , zipped ) ;
response r = new response ( zipped ) ;
response r = new response ( zipped ) ;
//serverLog.logDebug("HTTPC", handle + " returned GET '" + path + "', time = " + (System.currentTimeMillis() - handle));
//serverLog.logDebug("HTTPC", handle + " returned GET '" + path + "', time = " + (System.currentTimeMillis() - handle));
return r ;
return r ;
} catch ( Socket Exception e ) {
} catch ( Exception e ) {
throw new IOException ( e . getMessage ( ) ) ;
throw new IOException ( e . getMessage ( ) ) ;
}
}
}
}