2005-06-18 03:48:11 +02:00
// httpc.java
2005-04-07 21:19:42 +02:00
// -------------------------------------
// (C) by Michael Peter Christen; mc@anomic.de
// first published on http://www.anomic.de
// Frankfurt, Germany, 2004
// last major change: 26.02.2004
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Using this software in any meaning (reading, learning, copying, compiling,
// running) means that you agree that the Author(s) is (are) not responsible
// for cost, loss of data or any harm that may be caused directly or indirectly
// by usage of this softare or this documentation. The usage of this software
// is on your own risk. The installation and usage (starting/running) of this
// software may allow other people or application to access your computer and
// any attached devices and is highly dependent on the configuration of the
// software which must be done by the user of the software; the author(s) is
// (are) also not responsible for proper configuration and usage of the
// software, even if provoked by documentation provided together with
// the software.
//
// Any changes to this file according to the GPL as documented in the file
// gpl.txt aside this file in the shipment you received can be done to the
// lines that follows this copyright notice here, but changes must not be
// done inside the copyright notive above. A re-distribution must contain
// the intact and unchanged copyright notice.
// Contributions and changes to the program code must be marked as such.
package de.anomic.http ;
2005-05-05 07:32:19 +02:00
import java.io.File ;
import java.io.FileOutputStream ;
import java.io.IOException ;
import java.io.InputStream ;
import java.io.OutputStream ;
import java.io.PushbackInputStream ;
2006-09-18 12:12:11 +02:00
import java.io.Writer ;
2005-05-05 07:32:19 +02:00
import java.net.InetAddress ;
2005-08-19 08:47:34 +02:00
import java.net.InetSocketAddress ;
2005-05-05 07:32:19 +02:00
import java.net.MalformedURLException ;
import java.net.Socket ;
import java.net.SocketException ;
import java.net.UnknownHostException ;
import java.text.SimpleDateFormat ;
2005-07-07 15:58:54 +02:00
import java.util.ArrayList ;
2006-06-02 21:09:48 +02:00
import java.util.Collections ;
2005-05-05 07:32:19 +02:00
import java.util.Date ;
import java.util.Enumeration ;
import java.util.GregorianCalendar ;
import java.util.HashMap ;
2005-11-07 11:57:54 +01:00
import java.util.HashSet ;
2005-05-05 07:32:19 +02:00
import java.util.Iterator ;
2005-11-07 11:57:54 +01:00
import java.util.LinkedList ;
2006-06-02 21:09:48 +02:00
import java.util.List ;
2005-05-05 07:32:19 +02:00
import java.util.Locale ;
2006-06-02 21:09:48 +02:00
import java.util.Map ;
import java.util.Set ;
2005-05-05 07:32:19 +02:00
import java.util.TimeZone ;
import java.util.zip.GZIPInputStream ;
2005-09-22 12:30:55 +02:00
import java.util.zip.GZIPOutputStream ;
2005-04-19 08:55:57 +02:00
2005-11-03 16:28:37 +01:00
import javax.net.ssl.HostnameVerifier ;
import javax.net.ssl.HttpsURLConnection ;
import javax.net.ssl.SSLContext ;
2005-05-05 07:32:19 +02:00
import javax.net.ssl.SSLSocketFactory ;
2005-11-03 16:28:37 +01:00
import javax.net.ssl.TrustManager ;
import javax.net.ssl.X509TrustManager ;
2005-04-07 21:19:42 +02:00
2006-09-30 00:27:20 +02:00
import org.apache.commons.pool.impl.GenericObjectPool ;
2006-01-04 01:39:00 +01:00
import de.anomic.kelondro.kelondroBase64Order ;
2006-06-12 14:14:11 +02:00
import de.anomic.kelondro.kelondroMScoreCluster ;
2006-09-30 00:27:20 +02:00
import de.anomic.net.URL ;
2005-05-05 07:32:19 +02:00
import de.anomic.server.serverByteBuffer ;
import de.anomic.server.serverCore ;
2006-09-18 12:12:11 +02:00
import de.anomic.server.serverFileUtils ;
2005-05-05 07:32:19 +02:00
import de.anomic.server.serverObjects ;
2005-06-09 11:56:41 +02:00
import de.anomic.server.logging.serverLog ;
2006-10-02 11:59:20 +02:00
import de.anomic.tools.nxTools ;
2005-05-05 07:32:19 +02:00
2005-08-07 17:16:33 +02:00
/ * *
2005-08-07 18:27:38 +02:00
* This class implements an http client . While http access is built - in in java
* libraries , it is still necessary to implement the network interface since
* otherwise there is no access to the HTTP / 1 . 0 / HTTP / 1 . 1 header information
* that comes along each connection .
* FIXME : Add some information about the usage of the threadpool .
2005-08-07 17:16:33 +02:00
* /
2005-04-19 08:55:57 +02:00
public final class httpc {
2005-08-07 17:16:33 +02:00
2005-09-22 12:30:55 +02:00
// some constants
/ * *
* Specifies that the httpc is allowed to use gzip content encoding for
* http post requests
2005-10-05 12:45:33 +02:00
* @see # POST ( String , httpHeader , serverObjects , HashMap )
2005-09-22 12:30:55 +02:00
* /
public static final String GZIP_POST_BODY = " GZIP_POST_BODY " ;
2005-04-07 21:19:42 +02:00
// statics
private static final String vDATE = " 20040602 " ;
2006-02-18 11:27:56 +01:00
public static String userAgent ;
2005-04-07 21:19:42 +02:00
private static final int terminalMaxLength = 30000 ;
2005-12-07 14:26:27 +01:00
private static final TimeZone GMTTimeZone = TimeZone . getTimeZone ( " GMT " ) ;
2005-08-07 18:27:38 +02:00
/ * *
* This string is initialized on loading of this class and contains
* information about the current OS .
* /
public static String systemOST ;
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
// --- The GMT standard date format used in the HTTP protocol
2005-12-07 14:26:27 +01:00
private static final SimpleDateFormat HTTPGMTFormatter = new SimpleDateFormat ( " EEE, dd MMM yyyy HH:mm:ss zzz " , Locale . US ) ;
static {
HTTPGMTFormatter . setTimeZone ( GMTTimeZone ) ;
}
2005-10-09 06:43:07 +02:00
static final HashMap reverseMappingCache = new HashMap ( ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
// the dns cache
2006-06-02 21:09:48 +02:00
private static final Map nameCacheHit = Collections . synchronizedMap ( new HashMap ( ) ) ; // a not-synchronized map resulted in deadlocks
2006-11-27 16:27:43 +01:00
private static final Set nameCacheMiss = Collections . synchronizedSet ( new HashSet ( ) ) ;
private static final kelondroMScoreCluster nameCacheHitAges = new kelondroMScoreCluster ( ) ;
private static final kelondroMScoreCluster nameCacheMissAges = new kelondroMScoreCluster ( ) ;
2006-06-12 14:14:11 +02:00
private static final long startTime = System . currentTimeMillis ( ) ;
2006-11-27 16:53:42 +01:00
private static final int maxNameCacheHitAge = 24 * 60 * 60 ; // 24 hours in minutes
private static final int maxNameCacheMissAge = 24 * 60 * 60 ; // 24 hours in minutes
2006-11-27 16:27:43 +01:00
private static final int maxNameCacheHitSize = 3000 ;
private static final int maxNameCacheMissSize = 3000 ;
2006-06-02 21:09:48 +02:00
public static final List nameCacheNoCachingPatterns = Collections . synchronizedList ( new LinkedList ( ) ) ;
private static final Set nameCacheNoCachingList = Collections . synchronizedSet ( new HashSet ( ) ) ;
2006-11-27 16:27:43 +01:00
2005-06-18 03:48:11 +02:00
/ * *
* A Object Pool containing all pooled httpc - objects .
* @see httpcPool
* /
private static final httpcPool theHttpcPool ;
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
// class variables
private Socket socket = null ; // client socket for commands
2005-07-07 23:00:11 +02:00
private Thread socketOwner = null ;
2006-05-10 18:01:14 +02:00
private String adressed_host = null ;
private int adressed_port = 80 ;
private String target_virtual_host = null ;
2005-12-05 01:17:12 +01:00
2005-04-07 21:19:42 +02:00
// output and input streams for client control connection
2005-07-07 15:58:54 +02:00
PushbackInputStream clientInput = null ;
2005-06-18 03:48:11 +02:00
private OutputStream clientOutput = null ;
2005-10-23 14:35:48 +02:00
private httpdByteCountInputStream clientInputByteCount = null ;
private httpdByteCountOutputStream clientOutputByteCount = null ;
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
private boolean remoteProxyUse = false ;
2005-10-22 15:28:04 +02:00
private httpRemoteProxyConfig remoteProxyConfig = null ;
2005-10-09 06:43:07 +02:00
String requestPath = null ;
2005-07-04 13:09:48 +02:00
private boolean allowContentEncoding = true ;
2005-09-05 12:34:34 +02:00
public static boolean yacyDebugMode = false ;
2005-12-22 02:01:46 +01:00
2005-04-20 09:39:40 +02:00
/ * *
* Indicates if the current object was removed from pool because the maximum limit
* was exceeded .
* /
2005-04-19 12:42:48 +02:00
boolean removedFromPool = false ;
2005-08-07 17:16:33 +02:00
2005-12-22 02:01:46 +01:00
static SSLSocketFactory theSSLSockFactory = null ;
2005-04-19 08:55:57 +02:00
static {
2005-12-22 02:01:46 +01:00
// set time-out of InetAddress.getByName cache ttl
java . security . Security . setProperty ( " networkaddress.cache.ttl " , " 60 " ) ;
java . security . Security . setProperty ( " networkaddress.cache.negative.ttl " , " 0 " ) ;
// Configuring the httpc object pool
2005-04-19 08:55:57 +02:00
// implementation of session thread pool
GenericObjectPool . Config config = new GenericObjectPool . Config ( ) ;
2005-08-07 17:16:33 +02:00
2005-04-19 08:55:57 +02:00
// The maximum number of active connections that can be allocated from pool at the same time,
// 0 for no limit
config . maxActive = 150 ;
2005-08-07 17:16:33 +02:00
2005-04-19 08:55:57 +02:00
// The maximum number of idle connections connections in the pool
2005-06-18 03:48:11 +02:00
// 0 = no limit.
2005-04-19 08:55:57 +02:00
config . maxIdle = 75 ;
2005-06-18 03:48:11 +02:00
config . minIdle = 10 ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
config . whenExhaustedAction = GenericObjectPool . WHEN_EXHAUSTED_BLOCK ;
config . minEvictableIdleTimeMillis = 30000 ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
theHttpcPool = new httpcPool ( new httpcFactory ( ) , config ) ;
2005-12-22 02:01:46 +01:00
// initializing a dummy trustManager to enable https connections
2005-11-03 16:28:37 +01:00
// Create a trust manager that does not validate certificate chains
TrustManager [ ] trustAllCerts = new TrustManager [ ] { new X509TrustManager ( ) {
public java . security . cert . X509Certificate [ ] getAcceptedIssuers ( ) {
return null ;
}
public void checkClientTrusted (
java . security . cert . X509Certificate [ ] certs , String authType ) {
}
public void checkServerTrusted (
java . security . cert . X509Certificate [ ] certs , String authType ) {
}
} } ;
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext . getInstance ( " SSL " ) ;
// Create empty HostnameVerifier
HostnameVerifier hv = new HostnameVerifier ( ) {
public boolean verify ( String urlHostName , javax . net . ssl . SSLSession session ) {
// logger.info("Warning: URL Host: "+urlHostName+"
// vs."+session.getPeerHost());
return true ;
}
} ;
sc . init ( null , trustAllCerts , new java . security . SecureRandom ( ) ) ;
HttpsURLConnection . setDefaultSSLSocketFactory ( theSSLSockFactory = sc . getSocketFactory ( ) ) ;
HttpsURLConnection . setDefaultHostnameVerifier ( hv ) ;
} catch ( Exception e ) {
}
2005-12-22 02:01:46 +01:00
// provide system information for client identification
String loc = System . getProperty ( " user.timezone " , " nowhere " ) ;
int p = loc . indexOf ( " / " ) ;
if ( p > 0 ) loc = loc . substring ( 0 , p ) ;
loc = loc + " / " + System . getProperty ( " user.language " , " dumb " ) ;
systemOST =
System . getProperty ( " os.arch " , " no-os-arch " ) + " " +
System . getProperty ( " os.name " , " no-os-name " ) + " " +
System . getProperty ( " os.version " , " no-os-version " ) + " ; " +
" java " + System . getProperty ( " java.version " , " no-java-version " ) + " ; " + loc ;
userAgent = " yacy (www.yacy.net; v " + vDATE + " ; " + systemOST + " ) " ;
2005-11-03 16:28:37 +01:00
}
2005-12-22 02:01:46 +01:00
2005-04-20 09:39:40 +02:00
/ * *
* A reusable readline buffer
* @see serverByteBuffer
* /
2005-06-17 03:26:51 +02:00
final serverByteBuffer readLineBuffer = new serverByteBuffer ( 100 ) ;
2005-08-07 17:16:33 +02:00
2005-10-05 12:45:33 +02:00
private static final HashMap openSocketLookupTable = new HashMap ( ) ;
2005-08-07 17:16:33 +02:00
2005-08-07 18:27:38 +02:00
/ * *
* Convert the status of this class into an String object to output it .
* /
2005-06-09 11:56:41 +02:00
public String toString ( ) {
2006-05-10 18:01:14 +02:00
return ( this . adressed_host = = null ) ? " Disconnected " : " Connected to " + this . adressed_host +
( ( this . remoteProxyUse ) ? " via " + adressed_host : " " ) ;
2005-06-09 11:56:41 +02:00
}
2005-08-07 17:16:33 +02:00
2005-08-07 18:27:38 +02:00
/ * *
* This method gets a new httpc instance from the object pool and
* initializes it with the given parameters . Use this method if you have to
* use a proxy to access the pages .
*
* @param server
* @param port
* @param timeout
* @param ssl
* @param remoteProxyHost
* @param remoteProxyPort
* @throws IOException
* @see httpc # init
* /
2005-04-20 09:39:40 +02:00
public static httpc getInstance (
2005-06-18 03:48:11 +02:00
String server ,
2006-05-10 18:01:14 +02:00
String vhost ,
2005-06-18 03:48:11 +02:00
int port ,
int timeout ,
2005-04-20 09:39:40 +02:00
boolean ssl ,
2005-10-23 14:35:48 +02:00
httpRemoteProxyConfig remoteProxyConfig ,
String incomingByteCountAccounting ,
String outgoingByteCountAccounting
2005-06-18 03:48:11 +02:00
) throws IOException {
2005-08-07 17:16:33 +02:00
2005-04-19 12:42:48 +02:00
httpc newHttpc ;
2005-04-19 08:55:57 +02:00
try {
// fetching a new httpc from the object pool
2005-06-18 03:48:11 +02:00
newHttpc = ( httpc ) httpc . theHttpcPool . borrowObject ( ) ;
2005-04-19 08:55:57 +02:00
} catch ( Exception e ) {
throw new IOException ( " Unable to initialize a new httpc. " + e . getMessage ( ) ) ;
2005-06-18 03:48:11 +02:00
}
2005-08-07 17:16:33 +02:00
2005-04-19 12:42:48 +02:00
// initialize it
2005-08-09 11:07:19 +02:00
try {
2005-10-22 15:28:04 +02:00
newHttpc . init (
server ,
2006-05-10 18:01:14 +02:00
vhost ,
2005-10-22 15:28:04 +02:00
port ,
timeout ,
ssl ,
2005-10-23 14:35:48 +02:00
remoteProxyConfig ,
incomingByteCountAccounting ,
outgoingByteCountAccounting
2005-10-22 15:28:04 +02:00
) ;
2005-08-09 11:07:19 +02:00
} catch ( IOException e ) {
try { httpc . theHttpcPool . returnObject ( newHttpc ) ; } catch ( Exception e1 ) { }
throw e ;
}
2005-04-19 12:42:48 +02:00
return newHttpc ;
2005-04-19 08:55:57 +02:00
}
2005-10-23 14:35:48 +02:00
public static httpc getInstance (
String server ,
2006-05-10 18:01:14 +02:00
String vhost ,
2005-10-23 14:35:48 +02:00
int port ,
int timeout ,
boolean ssl ,
httpRemoteProxyConfig remoteProxyConfig
) throws IOException {
2006-10-19 12:10:53 +02:00
if ( remoteProxyConfig = = null ) throw new NullPointerException ( " Proxy object must not be null. " ) ;
2006-05-10 18:01:14 +02:00
return getInstance ( server , vhost , port , timeout , ssl , remoteProxyConfig , null , null ) ;
2005-10-23 14:35:48 +02:00
}
2005-08-07 17:16:33 +02:00
2005-10-23 14:35:48 +02:00
public static httpc getInstance (
String server ,
2006-05-10 18:01:14 +02:00
String vhost ,
2005-10-23 14:35:48 +02:00
int port ,
int timeout ,
boolean ssl
) throws IOException {
2006-05-10 18:01:14 +02:00
return getInstance ( server , vhost , port , timeout , ssl , null , null ) ;
2005-10-23 14:35:48 +02:00
}
2005-08-07 18:27:38 +02:00
/ * *
* This method gets a new httpc instance from the object pool and
* initializes it with the given parameters .
*
* @param server
* @param port
* @param timeout
* @param ssl
* @throws IOException
* @see httpc # init
* /
2005-10-23 14:35:48 +02:00
public static httpc getInstance (
String server ,
2006-05-10 18:01:14 +02:00
String vhost ,
2005-10-23 14:35:48 +02:00
int port ,
int timeout ,
boolean ssl ,
String incomingByteCountAccounting ,
String outgoingByteCountAccounting
) throws IOException {
2005-08-07 17:16:33 +02:00
2005-04-21 12:31:40 +02:00
httpc newHttpc = null ;
2005-04-26 12:38:35 +02:00
// fetching a new httpc from the object pool
2005-04-19 08:55:57 +02:00
try {
2005-04-21 12:31:40 +02:00
newHttpc = ( httpc ) httpc . theHttpcPool . borrowObject ( ) ;
2005-08-07 17:16:33 +02:00
2005-04-19 08:55:57 +02:00
} catch ( Exception e ) {
2005-05-13 10:30:30 +02:00
throw new IOException ( " Unable to fetch a new httpc from pool. " + e . getMessage ( ) ) ;
2005-06-18 03:48:11 +02:00
}
2005-08-07 17:16:33 +02:00
2005-04-21 12:31:40 +02:00
// initialize it
2005-04-26 12:38:35 +02:00
try {
2006-05-10 18:01:14 +02:00
newHttpc . init ( server , vhost , port , timeout , ssl , incomingByteCountAccounting , outgoingByteCountAccounting ) ;
2005-04-26 12:38:35 +02:00
} catch ( IOException e ) {
try { httpc . theHttpcPool . returnObject ( newHttpc ) ; } catch ( Exception e1 ) { }
throw e ;
}
2005-04-21 12:31:40 +02:00
return newHttpc ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
}
2005-08-07 17:16:33 +02:00
2005-08-07 18:27:38 +02:00
/ * *
* Put back a used instance into the instance pool of httpc .
*
* @param theHttpc The instance of httpc which should be returned to the pool
* /
2005-04-19 08:55:57 +02:00
public static void returnInstance ( httpc theHttpc ) {
try {
theHttpc . reset ( ) ;
httpc . theHttpcPool . returnObject ( theHttpc ) ;
} catch ( Exception e ) {
2005-06-18 03:48:11 +02:00
// we could ignore this error
2005-04-26 12:38:35 +02:00
}
2005-04-19 08:55:57 +02:00
}
2005-08-07 17:16:33 +02:00
2005-08-07 18:27:38 +02:00
/ * *
* Sets wether the content is allowed to be unzipped while getting ?
* FIXME : The name of this method seems misleading , if I read the usage of
* this method correctly ?
*
* @param status true , if the content is allowed to be decoded on the fly ?
* /
2005-07-04 13:09:48 +02:00
public void setAllowContentEncoding ( boolean status ) {
this . allowContentEncoding = status ;
}
2005-08-07 17:16:33 +02:00
2005-08-07 18:27:38 +02:00
/ * *
* Check wether the connection of this instance is closed .
*
* @return true if the connection is no longer open .
* /
2005-06-23 13:00:26 +02:00
public boolean isClosed ( ) {
if ( this . socket = = null ) return true ;
2005-10-09 06:43:07 +02:00
return ( ! this . socket . isConnected ( ) ) | | ( this . socket . isClosed ( ) ) ;
2005-06-23 13:00:26 +02:00
}
2005-08-07 17:16:33 +02:00
2005-08-07 18:27:38 +02:00
/ * *
* Does an DNS - Check to resolve a hostname to an IP .
*
* @param host Hostname of the host in demand .
* @return String with the ip . null , if the host could not be resolved .
* /
2005-11-07 11:57:54 +01:00
public static InetAddress dnsResolve ( String host ) {
if ( ( host = = null ) | | ( host . length ( ) = = 0 ) ) return null ;
2006-11-06 03:05:39 +01:00
host = host . toLowerCase ( ) . trim ( ) ;
2005-11-07 11:57:54 +01:00
// trying to resolve host by doing a name cache lookup
InetAddress ip = ( InetAddress ) nameCacheHit . get ( host ) ;
2005-04-07 21:19:42 +02:00
if ( ip ! = null ) return ip ;
2005-11-07 11:57:54 +01:00
2006-11-27 16:27:43 +01:00
if ( nameCacheMiss . contains ( host ) ) return null ;
try {
2005-11-07 11:57:54 +01:00
boolean doCaching = true ;
ip = InetAddress . getByName ( host ) ;
if (
( ip = = null ) | |
( ip . isLoopbackAddress ( ) ) | |
( nameCacheNoCachingList . contains ( ip . getHostName ( ) ) )
) {
doCaching = false ;
} else {
Iterator noCachingPatternIter = nameCacheNoCachingPatterns . iterator ( ) ;
while ( noCachingPatternIter . hasNext ( ) ) {
String nextPattern = ( String ) noCachingPatternIter . next ( ) ;
if ( ip . getHostName ( ) . matches ( nextPattern ) ) {
// disallow dns caching for this host
nameCacheNoCachingList . add ( ip . getHostName ( ) ) ;
doCaching = false ;
break ;
}
}
2005-04-07 21:19:42 +02:00
}
2005-11-07 11:57:54 +01:00
2006-06-12 14:14:11 +02:00
if ( doCaching ) {
2006-11-06 03:05:39 +01:00
// remove old entries
2006-11-27 16:53:42 +01:00
flushHitNameCache ( ) ;
2006-11-06 03:05:39 +01:00
// add new entries
2006-06-12 14:14:11 +02:00
synchronized ( nameCacheHit ) {
nameCacheHit . put ( ip . getHostName ( ) , ip ) ;
2006-11-27 16:27:43 +01:00
nameCacheHitAges . setScore ( ip . getHostName ( ) , intTime ( System . currentTimeMillis ( ) ) ) ;
2006-06-12 14:14:11 +02:00
}
}
2005-11-07 11:57:54 +01:00
return ip ;
2005-04-07 21:19:42 +02:00
} catch ( UnknownHostException e ) {
2006-11-27 16:53:42 +01:00
// remove old entries
flushMissNameCache ( ) ;
// add new entries
2006-11-27 16:27:43 +01:00
nameCacheMiss . add ( host ) ;
nameCacheMissAges . setScore ( host , intTime ( System . currentTimeMillis ( ) ) ) ;
2005-04-07 21:19:42 +02:00
}
return null ;
}
2005-08-07 17:16:33 +02:00
2005-11-07 11:57:54 +01:00
// /**
// * Checks wether an hostname already is in the DNS-cache.
// * FIXME: This method should use dnsResolve, as the code is 90% identical?
// *
// * @param host Searched for hostname.
// * @return true, if the hostname already is in the cache.
// */
// public static boolean dnsFetch(String host) {
// if ((nameCacheHit.get(host) != null) /*|| (nameCacheMiss.contains(host)) */) return false;
// try {
// String ip = InetAddress.getByName(host).getHostAddress();
// if ((ip != null) && (!(ip.equals("127.0.0.1"))) && (!(ip.equals("localhost")))) {
// nameCacheHit.put(host, ip);
// return true;
// }
// return false;
// } catch (UnknownHostException e) {
// //nameCacheMiss.add(host);
// return false;
// }
// }
2005-06-18 03:48:11 +02:00
2006-06-12 14:14:11 +02:00
/ * *
* Returns the number of entries in the nameCacheHit map
*
* @return int The number of entries in the nameCacheHit map
* /
public static int nameCacheHitSize ( ) {
return nameCacheHit . size ( ) ;
}
2006-11-27 16:27:43 +01:00
public static int nameCacheMissSize ( ) {
return nameCacheMiss . size ( ) ;
}
2006-06-12 14:14:11 +02:00
/ * *
* Returns the number of entries in the nameCacheNoCachingList list
*
* @return int The number of entries in the nameCacheNoCachingList list
* /
public static int nameCacheNoCachingListSize ( ) {
return nameCacheNoCachingList . size ( ) ;
}
/ * *
* Converts the time to a non negative int
*
* @param longTime Time in miliseconds since 01 / 01 / 1970 00 : 00 GMT
* @return int seconds since startTime
* /
private static int intTime ( long longTime ) {
return ( int ) Math . max ( 0 , ( ( longTime - startTime ) / 1000 ) ) ;
}
/ * *
2006-11-27 16:53:42 +01:00
* Removes old entries from the dns hit cache
2006-06-12 14:14:11 +02:00
* /
2006-11-27 16:53:42 +01:00
public static void flushHitNameCache ( ) {
int cutofftime = intTime ( System . currentTimeMillis ( ) ) - maxNameCacheHitAge ;
2006-06-12 14:14:11 +02:00
int size ;
String k ;
synchronized ( nameCacheHit ) {
2006-11-27 16:27:43 +01:00
size = nameCacheHitAges . size ( ) ;
2006-06-12 14:14:11 +02:00
while ( ( size > 0 ) & &
2006-11-27 16:27:43 +01:00
( size > maxNameCacheHitSize ) | | ( nameCacheHitAges . getMinScore ( ) < cutofftime ) ) {
k = ( String ) nameCacheHitAges . getMinObject ( ) ;
2006-06-12 14:14:11 +02:00
nameCacheHit . remove ( k ) ;
2006-11-27 16:27:43 +01:00
nameCacheHitAges . deleteScore ( k ) ;
2006-06-12 14:14:11 +02:00
size - - ; // size = nameCacheAges.size();
}
}
2006-11-27 16:53:42 +01:00
}
/ * *
* Removes old entries from the dns miss cache
* /
public static void flushMissNameCache ( ) {
int cutofftime = intTime ( System . currentTimeMillis ( ) ) - maxNameCacheMissAge ;
int size ;
String k ;
2007-03-12 10:06:57 +01:00
synchronized ( nameCacheMissAges ) {
2006-11-27 16:27:43 +01:00
size = nameCacheMissAges . size ( ) ;
while ( ( size > 0 ) & &
( size > maxNameCacheMissSize ) | | ( nameCacheMissAges . getMinScore ( ) < cutofftime ) ) {
k = ( String ) nameCacheMissAges . getMinObject ( ) ;
nameCacheMiss . remove ( k ) ;
nameCacheMissAges . deleteScore ( k ) ;
size - - ; // size = nameCacheAges.size();
}
}
2006-06-12 14:14:11 +02:00
}
2005-08-07 18:27:38 +02:00
/ * *
* Returns the given date in an HTTP - usable format .
2007-03-16 14:52:48 +01:00
* ( according to RFC822 )
2005-08-07 18:27:38 +02:00
*
* @param date The Date - Object to be converted .
* @return String with the date .
* /
2005-06-18 03:48:11 +02:00
public static String dateString ( Date date ) {
2005-12-07 00:51:29 +01:00
if ( date = = null ) return " " ;
2006-10-19 09:48:13 +02:00
/ *
* This synchronized is needed because SimpleDateFormat
* is not thread - safe .
* See : http : //bugs.sun.com/bugdatabase/view_bug.do?bug_id=6231579
* /
synchronized ( HTTPGMTFormatter ) {
return HTTPGMTFormatter . format ( date ) ;
}
2005-06-18 03:48:11 +02:00
}
2005-08-07 17:16:33 +02:00
2005-08-07 18:27:38 +02:00
/ * *
* Returns the current date as Date - Object .
*
* @return Date - object with the current time .
* /
2005-06-18 03:48:11 +02:00
public static Date nowDate ( ) {
return new GregorianCalendar ( GMTTimeZone ) . getTime ( ) ;
2005-04-19 08:55:57 +02:00
}
2005-08-07 17:16:33 +02:00
2005-08-07 18:27:38 +02:00
/ * *
* Initialize the httpc - instance with the given data . This method is used ,
* if you have to use a proxy to access the pages . This just calls init
* without proxy information and adds the proxy information .
*
* @param remoteProxyHost
* @param remoteProxyPort
* @throws IOException
* /
2005-10-22 15:28:04 +02:00
void init (
String server ,
2006-05-10 18:01:14 +02:00
String vhost ,
2005-10-22 15:28:04 +02:00
int port ,
int timeout ,
boolean ssl ,
2005-10-23 14:35:48 +02:00
httpRemoteProxyConfig theRemoteProxyConfig ,
String incomingByteCountAccounting ,
String outgoingByteCountAccounting
) throws IOException {
2005-09-07 11:54:11 +02:00
if ( port = = - 1 ) {
port = ( ssl ) ? 443 : 80 ;
}
2005-10-22 15:28:04 +02:00
String remoteProxyHost = theRemoteProxyConfig . getProxyHost ( ) ;
int remoteProxyPort = theRemoteProxyConfig . getProxyPort ( ) ;
2006-05-10 18:01:14 +02:00
this . init ( remoteProxyHost , vhost , remoteProxyPort , timeout , ssl , incomingByteCountAccounting , outgoingByteCountAccounting ) ;
2005-10-22 15:28:04 +02:00
2005-06-18 03:48:11 +02:00
this . remoteProxyUse = true ;
2006-05-10 18:01:14 +02:00
this . adressed_host = server ;
this . adressed_port = port ;
this . target_virtual_host = vhost ;
2005-10-22 15:28:04 +02:00
this . remoteProxyConfig = theRemoteProxyConfig ;
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-08-07 18:27:38 +02:00
/ * *
* Initialize the https - instance with the given data . Opens the sockets to
* the remote server and creats input and output streams .
*
* @param server Hostname of the server to connect to .
* @param port On which port should we connect .
* @param timeout How long do we wait for answers ?
* @param ssl Wether we should use SSL .
* @throws IOException
* /
2005-10-23 14:35:48 +02:00
void init (
2006-05-10 18:01:14 +02:00
String server ,
String vhost ,
2005-10-23 14:35:48 +02:00
int port ,
int timeout ,
boolean ssl ,
String incomingByteCountAccounting ,
String outgoingByteCountAccounting
) throws IOException {
2005-04-07 21:19:42 +02:00
//serverLog.logDebug("HTTPC", handle + " initialized");
2005-05-23 12:10:51 +02:00
this . remoteProxyUse = false ;
2005-12-05 01:17:12 +01:00
//this.timeout = timeout;
2005-08-07 17:16:33 +02:00
2005-05-23 12:10:51 +02:00
try {
2005-09-07 11:54:11 +02:00
if ( port = = - 1 ) {
port = ( ssl ) ? 443 : 80 ;
}
2006-05-10 18:01:14 +02:00
this . adressed_host = server ;
this . adressed_port = port ;
this . target_virtual_host = vhost ;
2006-09-04 13:23:57 +02:00
2005-08-19 08:47:34 +02:00
// creating a socket
2005-11-03 16:28:37 +01:00
this . socket = ( ssl )
? theSSLSockFactory . createSocket ( )
: new Socket ( ) ;
2005-08-19 08:47:34 +02:00
// creating a socket address
2006-09-04 13:23:57 +02:00
InetSocketAddress address = null ;
if ( ! this . remoteProxyUse ) {
// only try to resolve the address if we are not using a proxy
InetAddress hostip = dnsResolve ( server ) ;
if ( hostip = = null ) throw new UnknownHostException ( server ) ;
address = new InetSocketAddress ( hostip , port ) ;
} else {
address = new InetSocketAddress ( server , port ) ;
}
2005-08-07 17:16:33 +02:00
2005-08-19 10:23:12 +02:00
// trying to establish a connection to the address
2005-08-19 08:47:34 +02:00
this . socket . connect ( address , timeout ) ;
2005-07-07 15:58:54 +02:00
// registering the socket
2005-08-19 08:47:34 +02:00
this . socketOwner = this . registerOpenSocket ( this . socket ) ;
2005-08-07 17:16:33 +02:00
2005-07-07 15:58:54 +02:00
// setting socket timeout and keep alive behaviour
2005-08-19 08:47:34 +02:00
this . socket . setSoTimeout ( timeout ) ; // waiting time for read
//socket.setSoLinger(true, timeout);
this . socket . setKeepAlive ( true ) ; //
2005-08-07 17:16:33 +02:00
2005-10-23 14:35:48 +02:00
if ( incomingByteCountAccounting ! = null ) {
this . clientInputByteCount = new httpdByteCountInputStream ( this . socket . getInputStream ( ) , incomingByteCountAccounting ) ;
}
2007-03-16 14:52:48 +01:00
if ( outgoingByteCountAccounting ! = null ) {
this . clientOutputByteCount = new httpdByteCountOutputStream ( this . socket . getOutputStream ( ) , outgoingByteCountAccounting ) ;
}
2005-10-23 14:35:48 +02:00
2005-07-07 15:58:54 +02:00
// getting input and output streams
2005-10-23 14:35:48 +02:00
this . clientInput = new PushbackInputStream ( ( this . clientInputByteCount ! = null ) ?
this . clientInputByteCount :
this . socket . getInputStream ( ) ) ;
2005-08-19 08:47:34 +02:00
this . clientOutput = this . socket . getOutputStream ( ) ;
2005-10-23 14:35:48 +02:00
2005-05-23 12:10:51 +02:00
// if we reached this point, we should have a connection
} catch ( UnknownHostException e ) {
2005-07-07 15:58:54 +02:00
if ( this . socket ! = null ) {
2005-08-19 08:47:34 +02:00
httpc . unregisterOpenSocket ( this . socket , this . socketOwner ) ;
2005-07-07 15:58:54 +02:00
}
this . socket = null ;
2005-07-07 23:00:11 +02:00
this . socketOwner = null ;
2005-05-23 12:10:51 +02:00
throw new IOException ( " unknown host: " + server ) ;
2005-08-02 18:03:35 +02:00
}
2005-10-23 14:35:48 +02:00
}
public long getInputStreamByteCount ( ) {
return ( this . clientInputByteCount = = null ) ? 0 : this . clientInputByteCount . getCount ( ) ;
}
public long getOutputStreamByteCount ( ) {
return ( this . clientOutputByteCount = = null ) ? 0 : this . clientOutputByteCount . getCount ( ) ;
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-08-07 18:27:38 +02:00
/ * *
* This method resets an httpc - instance , so that it can be used for the next
* connection . This is called before the instance is put back to the pool .
* All streams and sockets are closed and set to null .
* /
2005-06-18 03:48:11 +02:00
void reset ( ) {
if ( this . clientInput ! = null ) {
try { this . clientInput . close ( ) ; } catch ( Exception e ) { }
this . clientInput = null ;
}
if ( this . clientOutput ! = null ) {
try { this . clientOutput . close ( ) ; } catch ( Exception e ) { }
this . clientOutput = null ;
}
if ( this . socket ! = null ) {
try { this . socket . close ( ) ; } catch ( Exception e ) { }
2005-10-09 06:43:07 +02:00
httpc . unregisterOpenSocket ( this . socket , this . socketOwner ) ;
2005-06-18 03:48:11 +02:00
this . socket = null ;
2005-07-07 23:00:11 +02:00
this . socketOwner = null ;
2005-06-18 03:48:11 +02:00
}
2005-10-23 14:35:48 +02:00
if ( this . clientInputByteCount ! = null ) {
2005-12-07 00:51:29 +01:00
this . clientInputByteCount . finish ( ) ;
2005-10-23 14:35:48 +02:00
this . clientInputByteCount = null ;
}
if ( this . clientOutputByteCount ! = null ) {
2005-12-07 00:51:29 +01:00
this . clientOutputByteCount . finish ( ) ;
2005-10-23 14:35:48 +02:00
this . clientOutputByteCount = null ;
}
2005-08-07 17:16:33 +02:00
2006-05-10 18:01:14 +02:00
this . adressed_host = null ;
this . target_virtual_host = null ;
2005-12-05 01:17:12 +01:00
//this.timeout = 0;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
this . remoteProxyUse = false ;
2005-10-22 15:28:04 +02:00
this . remoteProxyConfig = null ;
2005-06-18 03:48:11 +02:00
this . requestPath = null ;
2005-08-07 17:16:33 +02:00
2005-07-04 13:09:48 +02:00
this . allowContentEncoding = true ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
// shrink readlinebuffer if it is to large
this . readLineBuffer . reset ( 80 ) ;
2005-04-07 21:19:42 +02:00
}
2005-08-07 18:27:38 +02:00
/ * *
* Just calls reset to close all connections .
* /
2005-06-18 03:48:11 +02:00
public void close ( ) {
reset ( ) ;
2005-04-07 21:19:42 +02:00
}
2005-08-07 18:27:38 +02:00
/ * *
* If this instance is garbage - collected we check if the object was returned
* to the pool . if not , we invalidate the object from the pool .
*
* @see httpcPool # invalidateObject
* /
2005-06-18 03:48:11 +02:00
protected void finalize ( ) throws Throwable {
if ( ! ( this . removedFromPool ) ) {
System . err . println ( " Httpc object was not returned to object pool. " ) ;
httpc . theHttpcPool . invalidateObject ( this ) ;
}
this . reset ( ) ;
2005-04-07 21:19:42 +02:00
}
2005-08-10 23:50:17 +02:00
/ * *
* This method invokes a call to the given server .
*
* @param method Which method should be called ? GET , POST , HEAD or CONNECT
* @param path String with the path on the server to be get .
* @param header The prefilled header ( if available ) from the calling
* browser .
* @param zipped Is encoded content ( gzip ) allowed or not ?
* @throws IOException
* /
2005-04-07 21:19:42 +02:00
private void send ( String method , String path , httpHeader header , boolean zipped ) throws IOException {
2005-06-09 11:56:41 +02:00
// scheduled request through request-response objects/threads
2005-08-07 17:16:33 +02:00
2005-06-09 11:56:41 +02:00
// check and correct path
if ( ( path = = null ) | | ( path . length ( ) = = 0 ) ) path = " / " ;
2005-08-07 17:16:33 +02:00
2005-06-09 11:56:41 +02:00
// for debuggug:
2005-10-09 06:43:07 +02:00
this . requestPath = path ;
2005-08-07 17:16:33 +02:00
2005-06-09 11:56:41 +02:00
// prepare header
if ( header = = null ) header = new httpHeader ( ) ;
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
// set some standard values
2005-05-13 11:14:12 +02:00
if ( ! ( header . containsKey ( httpHeader . ACCEPT ) ) )
header . put ( httpHeader . ACCEPT , " text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 " ) ;
if ( ! ( header . containsKey ( httpHeader . ACCEPT_CHARSET ) ) )
header . put ( httpHeader . ACCEPT_CHARSET , " ISO-8859-1,utf-8;q=0.7,*;q=0.7 " ) ;
if ( ! ( header . containsKey ( httpHeader . ACCEPT_LANGUAGE ) ) )
header . put ( httpHeader . ACCEPT_LANGUAGE , " en-us,en;q=0.5 " ) ;
if ( ! ( header . containsKey ( httpHeader . KEEP_ALIVE ) ) )
header . put ( httpHeader . KEEP_ALIVE , " 300 " ) ;
2005-08-07 17:16:33 +02:00
2005-06-09 11:56:41 +02:00
// set user agent. The user agent is only set if the value does not yet exists.
// this gives callers the opportunity, to change the user agent themselves, and
// it will not be changed.
if ( ! ( header . containsKey ( httpHeader . USER_AGENT ) ) ) header . put ( httpHeader . USER_AGENT , userAgent ) ;
2005-08-07 17:16:33 +02:00
2005-06-09 11:56:41 +02:00
// set the host attribute. This is in particular necessary, if we contact another proxy
// the host is mandatory, if we use HTTP/1.1
if ( ! ( header . containsKey ( httpHeader . HOST ) ) ) {
2006-05-10 18:01:14 +02:00
if ( this . remoteProxyUse ) {
header . put ( httpHeader . HOST , this . adressed_host ) ;
} else {
header . put ( httpHeader . HOST , this . target_virtual_host ) ;
}
2005-06-09 11:56:41 +02:00
}
2005-10-22 15:28:04 +02:00
if ( this . remoteProxyUse ) {
String remoteProxyUser = this . remoteProxyConfig . getProxyUser ( ) ;
String remoteProxyPwd = this . remoteProxyConfig . getProxyPwd ( ) ;
if ( ( remoteProxyUser ! = null ) & & ( remoteProxyUser . length ( ) > 0 ) ) {
2006-01-04 01:39:00 +01:00
header . put ( httpHeader . PROXY_AUTHORIZATION , " Basic " + kelondroBase64Order . standardCoder . encodeString ( remoteProxyUser + " : " + remoteProxyPwd ) ) ;
2005-10-22 15:28:04 +02:00
}
}
2005-08-07 17:16:33 +02:00
2005-06-09 11:56:41 +02:00
if ( ! ( header . containsKey ( httpHeader . CONNECTION ) ) ) {
header . put ( httpHeader . CONNECTION , " close " ) ;
}
2006-01-25 19:54:46 +01:00
2005-06-09 11:56:41 +02:00
// stimulate zipping or not
// we can unzip, and we will return it always as unzipped, unless not wanted
if ( header . containsKey ( httpHeader . ACCEPT_ENCODING ) ) {
String encoding = ( String ) header . get ( httpHeader . ACCEPT_ENCODING ) ;
if ( zipped ) {
if ( encoding . indexOf ( " gzip " ) < 0 ) {
// add the gzip encoding
//System.out.println("!!! adding gzip encoding");
header . put ( httpHeader . ACCEPT_ENCODING , " gzip,deflate " + ( ( encoding . length ( ) = = 0 ) ? " " : ( " ; " + encoding ) ) ) ;
}
} else {
int pos = encoding . indexOf ( " gzip " ) ;
if ( pos > = 0 ) {
// remove the gzip encoding
//System.out.println("!!! removing gzip encoding");
header . put ( httpHeader . ACCEPT_ENCODING , encoding . substring ( 0 , pos ) + encoding . substring ( pos + 4 ) ) ;
}
}
} else {
if ( zipped ) header . put ( httpHeader . ACCEPT_ENCODING , " gzip,deflate " ) ;
}
2005-08-07 17:16:33 +02:00
2005-06-09 11:56:41 +02:00
//header = new httpHeader(); header.put("Host", this.host); // debug
2005-08-07 17:16:33 +02:00
2005-06-09 11:56:41 +02:00
// send request
if ( ( this . remoteProxyUse ) & & ( ! ( method . equals ( httpHeader . METHOD_CONNECT ) ) ) )
2006-05-10 18:01:14 +02:00
path = ( ( this . adressed_port = = 443 ) ? " https:// " : " http:// " ) + this . adressed_host + " : " + this . adressed_port + path ;
2005-10-09 06:43:07 +02:00
serverCore . send ( this . clientOutput , method + " " + path + " HTTP/1.0 " ) ; // if set to HTTP/1.1, servers give time-outs?
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
// send header
2005-06-09 11:56:41 +02:00
//System.out.println("***HEADER for path " + path + ": PROXY TO SERVER = " + header.toString()); // DEBUG
Iterator i = header . keySet ( ) . iterator ( ) ;
String key ;
int count ;
2005-04-30 03:22:46 +02:00
char tag ;
2005-06-09 11:56:41 +02:00
while ( i . hasNext ( ) ) {
key = ( String ) i . next ( ) ;
2005-04-30 03:22:46 +02:00
tag = key . charAt ( 0 ) ;
if ( ( tag ! = '*' ) & & ( tag ! = '#' ) ) {
count = header . keyCount ( key ) ;
for ( int j = 0 ; j < count ; j + + ) {
2005-06-09 11:56:41 +02:00
serverCore . send ( this . clientOutput , key + " : " + ( ( String ) header . getSingle ( key , j ) ) . trim ( ) ) ;
2005-04-30 03:22:46 +02:00
}
//System.out.println("#" + key + ": " + value);
2005-06-09 11:56:41 +02:00
}
}
2005-08-07 17:16:33 +02:00
2005-06-09 11:56:41 +02:00
// send terminating line
serverCore . send ( this . clientOutput , " " ) ;
this . clientOutput . flush ( ) ;
2005-08-07 17:16:33 +02:00
2005-06-09 11:56:41 +02:00
// this is the place where www.stern.de refuses to answer ..???
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-08-10 23:50:17 +02:00
/ * *
* This method GETs a page from the server .
*
* @param path The path to the page which should be GET .
* @param requestHeader Prefilled httpHeader .
2007-02-26 13:56:50 +01:00
* @return Instance of response with the content .
2005-08-10 23:50:17 +02:00
* @throws IOException
* /
2005-04-07 21:19:42 +02:00
public response GET ( String path , httpHeader requestHeader ) throws IOException {
//serverLog.logDebug("HTTPC", handle + " requested GET '" + path + "', time = " + (System.currentTimeMillis() - handle));
2005-06-09 11:56:41 +02:00
try {
2005-07-04 13:25:25 +02:00
boolean zipped = ( ! this . allowContentEncoding ) ? false : httpd . shallTransportZipped ( path ) ;
2005-06-09 11:56:41 +02:00
send ( httpHeader . METHOD_GET , path , requestHeader , zipped ) ;
response r = new response ( zipped ) ;
2005-04-07 21:19:42 +02:00
//serverLog.logDebug("HTTPC", handle + " returned GET '" + path + "', time = " + (System.currentTimeMillis() - handle));
return r ;
2005-06-09 11:56:41 +02:00
} catch ( Exception e ) {
2007-03-08 17:15:40 +01:00
if ( e . getMessage ( ) . indexOf ( " heap space " ) > 0 ) {
e . printStackTrace ( ) ;
}
2005-06-09 11:56:41 +02:00
throw new IOException ( e . getMessage ( ) ) ;
}
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-08-10 23:50:17 +02:00
/ * *
* This method gets only the header of a page .
*
* @param path The path to the page whose header should be get .
* @param requestHeader Prefilled httpHeader .
2007-02-26 13:56:50 +01:00
* @return Instance of response with the content .
2005-08-10 23:50:17 +02:00
* @throws IOException
* /
2005-04-07 21:19:42 +02:00
public response HEAD ( String path , httpHeader requestHeader ) throws IOException {
2005-06-18 03:48:11 +02:00
try {
send ( httpHeader . METHOD_HEAD , path , requestHeader , false ) ;
return new response ( false ) ;
// in this case the caller should not read the response body,
// since there is none...
} catch ( SocketException e ) {
throw new IOException ( e . getMessage ( ) ) ;
}
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-08-10 23:50:17 +02:00
/ * *
* This method POSTs some data to a page .
*
* @param path The path to the page which the post is sent to .
* @param requestHeader Prefilled httpHeader .
* @param ins InputStream with the data to be posted to the server .
2007-02-26 13:56:50 +01:00
* @return Instance of response with the content .
2005-08-10 23:50:17 +02:00
* @throws IOException
* /
2005-04-07 21:19:42 +02:00
public response POST ( String path , httpHeader requestHeader , InputStream ins ) throws IOException {
2005-06-18 03:48:11 +02:00
try {
send ( httpHeader . METHOD_POST , path , requestHeader , false ) ;
// if there is a body to the call, we would have a CONTENT-LENGTH tag in the requestHeader
String cl = ( String ) requestHeader . get ( httpHeader . CONTENT_LENGTH ) ;
2005-04-07 21:19:42 +02:00
int len , c ;
byte [ ] buffer = new byte [ 512 ] ;
2005-06-18 03:48:11 +02:00
if ( cl ! = null ) {
len = Integer . parseInt ( cl ) ;
// transfer len bytes from ins to the server
while ( ( len > 0 ) & & ( ( c = ins . read ( buffer ) ) > = 0 ) ) {
2005-10-09 06:43:07 +02:00
this . clientOutput . write ( buffer , 0 , c ) ;
2005-04-07 21:19:42 +02:00
len - = c ;
}
2005-06-18 03:48:11 +02:00
} else {
2005-04-07 21:19:42 +02:00
len = 0 ;
2005-06-18 03:48:11 +02:00
while ( ( c = ins . read ( buffer ) ) > = 0 ) {
2005-10-09 06:43:07 +02:00
this . clientOutput . write ( buffer , 0 , c ) ;
2005-04-07 21:19:42 +02:00
len + = c ;
}
2005-10-22 15:28:04 +02:00
// TODO: we can not set the header here. This ist too late
2005-08-03 04:02:39 +02:00
requestHeader . put ( httpHeader . CONTENT_LENGTH , Integer . toString ( len ) ) ;
2005-04-07 21:19:42 +02:00
}
2005-10-09 06:43:07 +02:00
this . clientOutput . flush ( ) ;
2005-06-18 03:48:11 +02:00
return new response ( false ) ;
} catch ( SocketException e ) {
throw new IOException ( e . getMessage ( ) ) ;
}
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-08-10 23:50:17 +02:00
/ * *
* Call the server with the CONNECT - method .
2005-12-06 22:21:14 +01:00
* This is used to establish https - connections through a https - proxy
2005-08-10 23:50:17 +02:00
*
* @param host To which host should a connection be made ?
* @param port Which port should be connected ?
* @param requestHeader prefilled httpHeader .
* @return Instance of response with the content .
* /
2005-12-06 22:21:14 +01:00
public response CONNECT ( String remotehost , int remoteport , httpHeader requestHeader ) throws IOException {
2005-06-18 03:48:11 +02:00
try {
2005-12-06 22:21:14 +01:00
send ( httpHeader . METHOD_CONNECT , remotehost + " : " + remoteport , requestHeader , false ) ;
2005-06-18 03:48:11 +02:00
return new response ( false ) ;
} catch ( SocketException e ) {
throw new IOException ( e . getMessage ( ) ) ;
}
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-08-10 23:50:17 +02:00
/ * *
* This method sends several files at once via a POST request . Only those
* files in the Hashtable files are written whose names are contained in
* args .
*
* @param path The path to the page which the post is sent to .
* @param requestHeader Prefilled httpHeader .
* @param args serverObjects with the names of the files to send .
2005-10-05 12:45:33 +02:00
* @param files HashMap with the names of the files as key and the content
2005-08-10 23:50:17 +02:00
* of the files as value .
* @return Instance of response with the content .
* @throws IOException
* /
2005-10-05 12:45:33 +02:00
public response POST ( String path , httpHeader requestHeader , serverObjects args , HashMap files ) throws IOException {
2005-06-18 03:48:11 +02:00
// make shure, the header has a boundary information like
// CONTENT-TYPE=multipart/form-data; boundary=----------0xKhTmLbOuNdArY
if ( requestHeader = = null ) requestHeader = new httpHeader ( ) ;
String boundary = ( String ) requestHeader . get ( httpHeader . CONTENT_TYPE ) ;
if ( boundary = = null ) {
// create a boundary
boundary = " multipart/form-data; boundary=---------- " + java . lang . System . currentTimeMillis ( ) ;
requestHeader . put ( httpHeader . CONTENT_TYPE , boundary ) ;
}
// extract the boundary string
int pos = boundary . toUpperCase ( ) . indexOf ( " BOUNDARY= " ) ;
if ( pos < 0 ) {
// again, create a boundary
boundary = " multipart/form-data; boundary=---------- " + java . lang . System . currentTimeMillis ( ) ;
requestHeader . put ( httpHeader . CONTENT_TYPE , boundary ) ;
pos = boundary . indexOf ( " boundary= " ) ;
}
boundary = " -- " + boundary . substring ( pos + " boundary= " . length ( ) ) ;
2005-08-07 17:16:33 +02:00
2005-09-22 12:30:55 +02:00
boolean zipContent = args . containsKey ( GZIP_POST_BODY ) ;
2005-09-23 01:05:34 +02:00
args . remove ( GZIP_POST_BODY ) ;
2005-09-22 12:30:55 +02:00
OutputStream out ;
GZIPOutputStream zippedOut ;
2005-10-05 12:45:33 +02:00
serverByteBuffer buf = new serverByteBuffer ( ) ;
2005-09-22 12:30:55 +02:00
if ( zipContent ) {
zippedOut = new GZIPOutputStream ( buf ) ;
out = zippedOut ;
} else {
out = buf ;
}
2005-06-18 03:48:11 +02:00
// in contrast to GET and HEAD, this method also transports a message body
// the body consists of repeated boundaries and values in between
if ( args . size ( ) ! = 0 ) {
// we have values for the POST, start with one boundary
String key , value ;
Enumeration e = args . keys ( ) ;
while ( e . hasMoreElements ( ) ) {
// start with a boundary
2006-09-13 17:47:56 +02:00
out . write ( boundary . getBytes ( " UTF-8 " ) ) ;
2005-09-22 12:30:55 +02:00
out . write ( serverCore . crlf ) ;
2005-04-07 21:19:42 +02:00
// write value
2005-06-18 03:48:11 +02:00
key = ( String ) e . nextElement ( ) ;
2005-10-05 12:45:33 +02:00
value = args . get ( key , " " ) ;
2005-06-18 03:48:11 +02:00
if ( ( files ! = null ) & & ( files . containsKey ( key ) ) ) {
// we are about to write a file
2006-09-13 17:47:56 +02:00
out . write ( ( " Content-Disposition: form-data; name= " + '"' + key + '"' + " ; filename= " + '"' + value + '"' ) . getBytes ( " UTF-8 " ) ) ;
2005-09-22 12:30:55 +02:00
out . write ( serverCore . crlf ) ;
out . write ( serverCore . crlf ) ;
out . write ( ( byte [ ] ) files . get ( key ) ) ;
out . write ( serverCore . crlf ) ;
2005-06-18 03:48:11 +02:00
} else {
// write a single value
2006-09-13 17:47:56 +02:00
out . write ( ( " Content-Disposition: form-data; name= " + '"' + key + '"' ) . getBytes ( " UTF-8 " ) ) ;
2005-09-22 12:30:55 +02:00
out . write ( serverCore . crlf ) ;
out . write ( serverCore . crlf ) ;
2006-09-13 17:47:56 +02:00
out . write ( value . getBytes ( " UTF-8 " ) ) ;
2005-09-22 12:30:55 +02:00
out . write ( serverCore . crlf ) ;
2005-04-07 21:19:42 +02:00
}
2005-06-18 03:48:11 +02:00
}
// finish with a boundary
2006-09-13 17:47:56 +02:00
out . write ( boundary . getBytes ( " UTF-8 " ) ) ;
2005-09-22 12:30:55 +02:00
out . write ( serverCore . crlf ) ;
2005-06-18 03:48:11 +02:00
}
2005-04-07 21:19:42 +02:00
// create body array
2005-09-22 12:30:55 +02:00
out . close ( ) ;
2005-04-07 21:19:42 +02:00
byte [ ] body = buf . toByteArray ( ) ;
2005-10-05 12:45:33 +02:00
buf = null ; out = null ;
2005-04-07 21:19:42 +02:00
//System.out.println("DEBUG: PUT BODY=" + new String(body));
2005-09-22 12:30:55 +02:00
if ( zipContent ) {
requestHeader . put ( httpHeader . CONTENT_ENCODING , " gzip " ) ;
2005-10-22 15:28:04 +02:00
//TODO: should we also set the content length here?
2005-09-22 12:30:55 +02:00
} else {
// size of that body
requestHeader . put ( httpHeader . CONTENT_LENGTH , Integer . toString ( body . length ) ) ;
}
2005-10-22 15:28:04 +02:00
2005-06-18 03:48:11 +02:00
// send the header
send ( httpHeader . METHOD_POST , path , requestHeader , false ) ;
2005-10-22 15:28:04 +02:00
2005-06-18 03:48:11 +02:00
// send the body
2005-10-09 06:43:07 +02:00
serverCore . send ( this . clientOutput , body ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
return new response ( false ) ;
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
/ *
DEBUG : PUT BODY = - - - - - - - - - - - - 1090358578442
Content - Disposition : form - data ; name = " youare "
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
Ty2F86ekSWM5
- - - - - - - - - - - - 1090358578442
Content - Disposition : form - data ; name = " key "
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
6EkPPOl7
- - - - - - - - - - - - 1090358578442
Content - Disposition : form - data ; name = " iam "
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
HnTvzwV7SCJR
- - - - - - - - - - - - 1090358578442
Content - Disposition : form - data ; name = " process "
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
permission
- - - - - - - - - - - - 1090358578442
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
* /
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
/ *
- - - - - - - - - - - - 0xKhTmLbOuNdArY
Content - Disposition : form - data ; name = " file1 " ; filename = " dir.gif "
Content - Type : image / gif
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
GIF89
- - - - - - - - - - - - 0xKhTmLbOuNdArY
Content - Disposition : form - data ; name = " file2 " ; filename = " "
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
- - - - - - - - - - - - 0xKhTmLbOuNdArY
Content - Disposition : form - data ; name = " upload "
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
do upload
- - - - - - - - - - - - 0xKhTmLbOuNdArY - -
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
# # # # # # Listing Properties # # # # # #
# METHOD = POST
# # # Header Values :
# EXT = html
# HTTP = HTTP / 1 . 1
# ACCEPT - ENCODING = gzip , deflate ; q = 1 . 0 , identity ; q = 0 . 5 , * ; q = 0
# HOST = localhost : 8080
# PATH = / testcgi / doit . html
# CONTENT - LENGTH = 474
# CONTENT - TYPE = multipart / form - data ; boundary = - - - - - - - - - - 0xKhTmLbOuNdArY
# ARGC = 0
# CONNECTION = close
# USER - AGENT = Mozilla / 5 . 0 ( Macintosh ; U ; PPC Mac OS X ; de - de ) AppleWebKit / 103u ( KHTML , like Gecko ) Safari / 100 . 1
# # # Call Properties :
# # # # # # End OfList # # # # # #
2005-06-18 03:48:11 +02:00
* /
2005-08-07 17:16:33 +02:00
2005-10-22 15:28:04 +02:00
public static byte [ ] singleGET (
2006-05-10 18:01:14 +02:00
String realhost ,
String virtualhost ,
2005-10-22 15:28:04 +02:00
int port ,
String path ,
int timeout ,
String user ,
String password ,
boolean ssl ,
httpRemoteProxyConfig theRemoteProxyConfig ,
httpHeader requestHeader
) throws IOException {
2005-06-18 03:48:11 +02:00
if ( requestHeader = = null ) requestHeader = new httpHeader ( ) ;
2005-10-22 15:28:04 +02:00
// setting host authorization header
2005-06-18 03:48:11 +02:00
if ( ( user ! = null ) & & ( password ! = null ) & & ( user . length ( ) ! = 0 ) ) {
2006-01-04 01:39:00 +01:00
requestHeader . put ( httpHeader . AUTHORIZATION , kelondroBase64Order . standardCoder . encodeString ( user + " : " + password ) ) ;
2005-06-18 03:48:11 +02:00
}
2005-08-07 17:16:33 +02:00
2005-04-19 08:55:57 +02:00
httpc con = null ;
2005-06-18 03:48:11 +02:00
try {
2005-10-22 15:28:04 +02:00
if ( ( theRemoteProxyConfig = = null ) | | ( ! theRemoteProxyConfig . useProxy ( ) ) ) {
2006-05-10 18:01:14 +02:00
con = httpc . getInstance ( realhost , virtualhost , port , timeout , ssl ) ;
2005-06-18 03:48:11 +02:00
} else {
2006-05-10 18:01:14 +02:00
con = httpc . getInstance ( realhost , virtualhost , port , timeout , ssl , theRemoteProxyConfig ) ;
2005-04-19 08:55:57 +02:00
}
2005-08-07 17:16:33 +02:00
2006-01-25 14:25:48 +01:00
httpc . response res = con . GET ( path , requestHeader ) ;
2005-06-18 03:48:11 +02:00
if ( res . status . startsWith ( " 2 " ) ) {
2005-10-05 12:45:33 +02:00
return res . writeContent ( ) ;
2005-06-18 03:48:11 +02:00
}
2005-10-09 06:43:07 +02:00
return res . status . getBytes ( ) ;
2005-04-19 08:55:57 +02:00
} catch ( Exception e ) {
throw new IOException ( e . getMessage ( ) ) ;
} finally {
if ( con ! = null ) httpc . returnInstance ( con ) ;
}
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-10-22 15:28:04 +02:00
public static byte [ ] singleGET (
2006-05-10 18:01:14 +02:00
URL u ,
String vhost ,
2005-10-22 15:28:04 +02:00
int timeout ,
String user ,
String password ,
httpRemoteProxyConfig theRemoteProxyConfig
) throws IOException {
2005-06-18 03:48:11 +02:00
int port = u . getPort ( ) ;
2005-04-07 21:19:42 +02:00
boolean ssl = u . getProtocol ( ) . equals ( " https " ) ;
2005-06-18 03:48:11 +02:00
if ( port < 0 ) port = ( ssl ) ? 443 : 80 ;
String path = u . getPath ( ) ;
String query = u . getQuery ( ) ;
if ( ( query ! = null ) & & ( query . length ( ) > 0 ) ) path = path + " ? " + query ;
2006-05-10 18:01:14 +02:00
return singleGET ( u . getHost ( ) , vhost , port , path , timeout , user , password , ssl , theRemoteProxyConfig , null ) ;
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
/ *
public static byte [ ] singleGET ( String url , int timeout ) throws IOException {
2005-06-18 03:48:11 +02:00
try {
return singleGET ( new URL ( url ) , timeout , null , null , null , 0 ) ;
} catch ( MalformedURLException e ) {
throw new IOException ( " Malformed URL: " + e . getMessage ( ) ) ;
}
2005-04-07 21:19:42 +02:00
}
2005-06-18 03:48:11 +02:00
* /
2005-08-07 17:16:33 +02:00
2005-10-22 15:28:04 +02:00
public static byte [ ] singlePOST (
2006-05-10 18:01:14 +02:00
String realhost ,
String virtualhost ,
2005-10-22 15:28:04 +02:00
int port ,
String path ,
int timeout ,
String user ,
String password ,
boolean ssl ,
httpRemoteProxyConfig theRemoteProxyConfig ,
httpHeader requestHeader ,
2005-11-11 00:48:20 +01:00
serverObjects props ,
HashMap files
2005-10-22 15:28:04 +02:00
) throws IOException {
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
if ( requestHeader = = null ) requestHeader = new httpHeader ( ) ;
if ( ( user ! = null ) & & ( password ! = null ) & & ( user . length ( ) ! = 0 ) ) {
2006-01-04 01:39:00 +01:00
requestHeader . put ( httpHeader . AUTHORIZATION , kelondroBase64Order . standardCoder . encodeString ( user + " : " + password ) ) ;
2005-06-18 03:48:11 +02:00
}
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
httpc con = null ;
2005-04-19 08:55:57 +02:00
try {
2005-10-22 15:28:04 +02:00
if ( ( theRemoteProxyConfig = = null ) | | ( ! theRemoteProxyConfig . useProxy ( ) ) ) {
2006-05-10 18:01:14 +02:00
con = httpc . getInstance ( realhost , virtualhost , port , timeout , ssl ) ;
2005-10-22 15:28:04 +02:00
} else {
2006-05-10 18:01:14 +02:00
con = httpc . getInstance ( realhost , virtualhost , port , timeout , ssl , theRemoteProxyConfig ) ;
2005-10-22 15:28:04 +02:00
}
2005-11-11 00:48:20 +01:00
httpc . response res = con . POST ( path , requestHeader , props , files ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
//System.out.println("response=" + res.toString());
if ( res . status . startsWith ( " 2 " ) ) {
2005-10-05 12:45:33 +02:00
return res . writeContent ( ) ;
2005-06-18 03:48:11 +02:00
}
2005-10-09 06:43:07 +02:00
return res . status . getBytes ( ) ;
2005-04-19 08:55:57 +02:00
} catch ( Exception e ) {
throw new IOException ( e . getMessage ( ) ) ;
} finally {
if ( con ! = null ) httpc . returnInstance ( con ) ;
}
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-10-22 15:28:04 +02:00
public static byte [ ] singlePOST (
URL u ,
2006-05-10 18:01:14 +02:00
String vhost ,
2005-10-22 15:28:04 +02:00
int timeout ,
String user ,
String password ,
httpRemoteProxyConfig theRemoteProxyConfig ,
2005-11-11 00:48:20 +01:00
serverObjects props ,
HashMap files
2005-10-22 15:28:04 +02:00
) throws IOException {
2005-06-18 03:48:11 +02:00
int port = u . getPort ( ) ;
2005-04-07 21:19:42 +02:00
boolean ssl = u . getProtocol ( ) . equals ( " https " ) ;
if ( port < 0 ) port = ( ssl ) ? 443 : 80 ;
2005-06-18 03:48:11 +02:00
String path = u . getPath ( ) ;
String query = u . getQuery ( ) ;
if ( ( query ! = null ) & & ( query . length ( ) > 0 ) ) path = path + " ? " + query ;
2005-10-22 15:28:04 +02:00
return singlePOST (
2006-05-10 18:01:14 +02:00
u . getHost ( ) ,
vhost ,
2005-10-22 15:28:04 +02:00
port ,
path ,
timeout ,
user ,
password ,
ssl ,
theRemoteProxyConfig ,
null ,
2005-11-11 00:48:20 +01:00
props ,
files
2005-10-22 15:28:04 +02:00
) ;
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-10-22 15:28:04 +02:00
public static byte [ ] singlePOST (
String url ,
int timeout ,
serverObjects props
) throws IOException {
2005-06-18 03:48:11 +02:00
try {
2006-05-09 15:11:00 +02:00
URL u = new URL ( url ) ;
2005-10-22 15:28:04 +02:00
return singlePOST (
2006-05-09 15:11:00 +02:00
u ,
u . getHost ( ) ,
2005-10-22 15:28:04 +02:00
timeout ,
null ,
null ,
null ,
2005-11-11 00:48:20 +01:00
props ,
null
2005-10-22 15:28:04 +02:00
) ;
2005-06-18 03:48:11 +02:00
} catch ( MalformedURLException e ) {
throw new IOException ( " Malformed URL: " + e . getMessage ( ) ) ;
}
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2006-10-02 11:59:20 +02:00
public static byte [ ] wget (
2006-05-09 15:11:00 +02:00
URL url ,
2006-05-10 18:01:14 +02:00
String vhost ,
2005-10-22 15:28:04 +02:00
int timeout ,
String user ,
String password ,
httpRemoteProxyConfig theRemoteProxyConfig
) throws IOException {
2006-05-10 18:01:14 +02:00
return wget ( url , vhost , timeout , user , password , theRemoteProxyConfig , null ) ;
2005-10-23 12:35:05 +02:00
}
2006-05-09 15:11:00 +02:00
2006-10-02 11:59:20 +02:00
public static byte [ ] wget ( URL url ) throws IOException {
2006-11-12 01:28:10 +01:00
return wget ( url , url . getHost ( ) , 10000 , null , null , null , null ) ;
2005-12-29 18:45:50 +01:00
}
2005-10-23 12:35:05 +02:00
2006-10-02 11:59:20 +02:00
public static byte [ ] wget (
2006-05-09 15:11:00 +02:00
URL url ,
2006-05-10 18:01:14 +02:00
String vhost ,
2005-10-23 12:35:05 +02:00
int timeout ,
String user ,
String password ,
httpRemoteProxyConfig theRemoteProxyConfig ,
httpHeader requestHeader
) throws IOException {
int port = url . getPort ( ) ;
boolean ssl = url . getProtocol ( ) . equals ( " https " ) ;
if ( port < 0 ) port = ( ssl ) ? 443 : 80 ;
String path = url . getPath ( ) ;
String query = url . getQuery ( ) ;
if ( ( query ! = null ) & & ( query . length ( ) > 0 ) ) path = path + " ? " + query ;
2005-06-18 03:48:11 +02:00
// splitting of the byte array into lines
2005-10-22 15:28:04 +02:00
byte [ ] a = singleGET (
2006-05-10 18:01:14 +02:00
url . getHost ( ) ,
vhost ,
2005-10-23 12:35:05 +02:00
port ,
path ,
2005-10-22 15:28:04 +02:00
timeout ,
user ,
password ,
2005-10-23 12:35:05 +02:00
ssl ,
theRemoteProxyConfig ,
requestHeader
2005-10-22 15:28:04 +02:00
) ;
2005-04-07 21:19:42 +02:00
if ( a = = null ) return null ;
2005-12-06 11:41:19 +01:00
// support of gzipped data (requested by roland)
2006-10-19 12:10:53 +02:00
a = serverFileUtils . uncompressGZipArray ( a ) ;
// return result
2006-10-02 11:59:20 +02:00
return a ;
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-10-22 15:28:04 +02:00
public static httpHeader whead (
2006-05-10 18:01:14 +02:00
URL url ,
String vhost ,
2005-10-22 15:28:04 +02:00
int timeout ,
String user ,
String password ,
httpRemoteProxyConfig theRemoteProxyConfig
2005-10-23 12:35:05 +02:00
) throws IOException {
2006-05-10 18:01:14 +02:00
return whead ( url , vhost , timeout , user , password , theRemoteProxyConfig , null ) ;
2005-10-23 12:35:05 +02:00
}
public static httpHeader whead (
2006-05-10 18:01:14 +02:00
URL url ,
String vhost ,
2005-10-23 12:35:05 +02:00
int timeout ,
String user ,
String password ,
httpRemoteProxyConfig theRemoteProxyConfig ,
httpHeader requestHeader
2005-10-22 15:28:04 +02:00
) throws IOException {
2005-04-19 08:55:57 +02:00
// generate request header
2005-10-23 12:35:05 +02:00
if ( requestHeader = = null ) requestHeader = new httpHeader ( ) ;
2005-06-18 03:48:11 +02:00
if ( ( user ! = null ) & & ( password ! = null ) & & ( user . length ( ) ! = 0 ) ) {
2006-01-04 01:39:00 +01:00
requestHeader . put ( httpHeader . AUTHORIZATION , kelondroBase64Order . standardCoder . encodeString ( user + " : " + password ) ) ;
2005-06-18 03:48:11 +02:00
}
2005-04-07 21:19:42 +02:00
// parse query
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
int port = url . getPort ( ) ;
boolean ssl = url . getProtocol ( ) . equals ( " https " ) ;
2005-06-18 03:48:11 +02:00
if ( port < 0 ) port = ( ssl ) ? 443 : 80 ;
String path = url . getPath ( ) ;
String query = url . getQuery ( ) ;
if ( ( query ! = null ) & & ( query . length ( ) > 0 ) ) path = path + " ? " + query ;
2006-05-10 18:01:14 +02:00
String realhost = url . getHost ( ) ;
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
// start connection
2005-04-19 08:55:57 +02:00
httpc con = null ;
2005-06-18 03:48:11 +02:00
try {
2005-10-22 15:28:04 +02:00
if ( ( theRemoteProxyConfig = = null ) | | ( ! theRemoteProxyConfig . useProxy ( ) ) )
2006-05-10 18:01:14 +02:00
con = httpc . getInstance ( realhost , vhost , port , timeout , ssl ) ;
else con = httpc . getInstance ( realhost , vhost , port , timeout , ssl , theRemoteProxyConfig ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
httpc . response res = con . HEAD ( path , requestHeader ) ;
if ( res . status . startsWith ( " 2 " ) ) {
// success
return res . responseHeader ;
}
2005-10-09 06:43:07 +02:00
// fail
return res . responseHeader ;
2005-04-19 08:55:57 +02:00
} catch ( Exception e ) {
throw new IOException ( e . getMessage ( ) ) ;
} finally {
if ( con ! = null ) httpc . returnInstance ( con ) ;
}
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2006-12-01 12:01:56 +01:00
public static byte [ ] wput (
2006-05-09 15:11:00 +02:00
URL url ,
2006-05-10 18:01:14 +02:00
String vhost ,
2005-10-22 15:28:04 +02:00
int timeout ,
String user ,
String password ,
httpRemoteProxyConfig theRemoteProxyConfig ,
2005-11-11 00:48:20 +01:00
serverObjects props ,
HashMap files
2005-10-22 15:28:04 +02:00
) throws IOException {
2005-06-18 03:48:11 +02:00
// splitting of the byte array into lines
2005-10-22 15:28:04 +02:00
byte [ ] a = singlePOST (
2006-05-09 15:11:00 +02:00
url ,
2006-05-10 18:01:14 +02:00
vhost ,
2005-10-22 15:28:04 +02:00
timeout ,
user ,
password ,
theRemoteProxyConfig ,
2005-11-11 00:48:20 +01:00
props ,
files
2005-10-22 15:28:04 +02:00
) ;
2006-12-01 12:01:56 +01:00
if ( a = = null ) return null ;
// support of gzipped data
a = serverFileUtils . uncompressGZipArray ( a ) ;
// return result
return a ;
2005-06-18 03:48:11 +02:00
//System.out.println("wput-out=" + new String(a));
2006-12-01 12:01:56 +01:00
//return nxTools.strings(a);
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
public static void main ( String [ ] args ) {
2005-06-18 03:48:11 +02:00
System . out . println ( " ANOMIC.DE HTTP CLIENT v " + vDATE ) ;
String url = args [ 0 ] ;
if ( ! ( url . toUpperCase ( ) . startsWith ( " HTTP:// " ) ) ) url = " http:// " + url ;
2005-10-05 12:45:33 +02:00
ArrayList text = new ArrayList ( ) ;
2005-06-18 03:48:11 +02:00
if ( args . length = = 4 ) {
2005-04-07 21:19:42 +02:00
int timeout = Integer . parseInt ( args [ 1 ] ) ;
String proxyHost = args [ 2 ] ;
int proxyPort = Integer . parseInt ( args [ 3 ] ) ;
2005-10-22 15:28:04 +02:00
httpRemoteProxyConfig theRemoteProxyConfig = httpRemoteProxyConfig . init ( proxyHost , proxyPort ) ;
2005-04-07 21:19:42 +02:00
try {
2006-05-09 15:11:00 +02:00
URL u = new URL ( url ) ;
2006-10-02 11:59:20 +02:00
text = nxTools . strings ( wget ( u , u . getHost ( ) , timeout , null , null , theRemoteProxyConfig ) ) ;
2005-04-07 21:19:42 +02:00
} catch ( MalformedURLException e ) {
System . out . println ( " The url ' " + url + " ' is wrong. " ) ;
} catch ( IOException e ) {
System . out . println ( " Error loading url ' " + url + " ': " + e . getMessage ( ) ) ;
}
2005-06-18 03:48:11 +02:00
} / * else {
serverObjects post = new serverObjects ( ) ;
int p ;
for ( int i = 1 ; i < args . length ; i + + ) {
p = args [ i ] . indexOf ( " = " ) ;
if ( p > 0 ) post . put ( args [ i ] . substring ( 0 , p ) , args [ i ] . substring ( p + 1 ) ) ;
}
text = wput ( url , post ) ;
} * /
2005-10-05 12:45:33 +02:00
Iterator i = text . listIterator ( ) ;
while ( i . hasNext ( ) ) System . out . println ( ( String ) i . next ( ) ) ;
2005-04-07 21:19:42 +02:00
}
2005-08-07 17:16:33 +02:00
2005-07-07 15:58:54 +02:00
/ * *
* To register an open socket .
2005-08-07 17:16:33 +02:00
* This adds the socket to the list of open sockets where the current thread
2005-08-10 23:50:17 +02:00
* is the owner .
2005-07-07 15:58:54 +02:00
* @param openedSocket the socket that should be registered
2005-08-07 17:16:33 +02:00
* @return the id of the current thread
2005-07-07 15:58:54 +02:00
* /
2005-07-07 23:00:11 +02:00
private Thread registerOpenSocket ( Socket openedSocket ) {
Thread currentThread = Thread . currentThread ( ) ;
2005-07-07 15:58:54 +02:00
synchronized ( openSocketLookupTable ) {
ArrayList openSockets = null ;
2005-07-07 23:00:11 +02:00
if ( openSocketLookupTable . containsKey ( currentThread ) ) {
openSockets = ( ArrayList ) openSocketLookupTable . get ( currentThread ) ;
2005-07-07 15:58:54 +02:00
} else {
openSockets = new ArrayList ( 1 ) ;
2005-07-07 23:00:11 +02:00
openSocketLookupTable . put ( currentThread , openSockets ) ;
2005-07-07 15:58:54 +02:00
}
synchronized ( openSockets ) {
openSockets . add ( openedSocket ) ;
}
2005-07-07 23:00:11 +02:00
return currentThread ;
2005-08-07 17:16:33 +02:00
}
2005-07-07 15:58:54 +02:00
}
2005-08-07 17:16:33 +02:00
2005-07-07 15:58:54 +02:00
/ * *
* Closing all sockets that were opened in the context of the thread
2005-08-07 17:16:33 +02:00
* with the given thread id
2005-07-07 15:58:54 +02:00
* @param threadId
* /
2005-07-07 23:00:11 +02:00
public static int closeOpenSockets ( Thread thread ) {
2005-08-07 17:16:33 +02:00
// getting all still opened sockets
2005-07-07 23:00:11 +02:00
ArrayList openSockets = ( ArrayList ) httpc . getRegisteredOpenSockets ( thread ) . clone ( ) ;
2005-07-07 15:58:54 +02:00
int closedSocketCount = 0 ;
2005-08-07 17:16:33 +02:00
2005-07-07 23:00:11 +02:00
// looping through the list of sockets and close each one
for ( int socketCount = 0 ; socketCount < openSockets . size ( ) ; socketCount + + ) {
Socket openSocket = ( Socket ) openSockets . get ( 0 ) ;
try {
// closing the socket
if ( ! openSocket . isClosed ( ) ) {
openSocket . close ( ) ;
closedSocketCount + + ;
}
// unregistering the socket
httpc . unregisterOpenSocket ( openSocket , thread ) ;
} catch ( Exception ex ) { }
2005-07-07 15:58:54 +02:00
}
2005-08-07 17:16:33 +02:00
2005-07-07 15:58:54 +02:00
return closedSocketCount ;
}
2005-08-07 17:16:33 +02:00
2005-07-07 15:58:54 +02:00
/ * *
2005-08-07 17:16:33 +02:00
* Unregistering the socket .
2005-07-07 15:58:54 +02:00
* The socket will be removed from the list of sockets where the thread with the
* given thread id is the owner .
* @param closedSocket the socket that should be unregistered
* @param threadId the id of the owner thread
* /
2005-07-07 23:00:11 +02:00
public static void unregisterOpenSocket ( Socket closedSocket , Thread thread ) {
2005-07-07 15:58:54 +02:00
synchronized ( openSocketLookupTable ) {
ArrayList openSockets = null ;
2005-07-07 23:00:11 +02:00
if ( openSocketLookupTable . containsKey ( thread ) ) {
openSockets = ( ArrayList ) openSocketLookupTable . get ( thread ) ;
2005-07-07 15:58:54 +02:00
synchronized ( openSockets ) {
openSockets . remove ( closedSocket ) ;
if ( openSockets . size ( ) = = 0 ) {
2005-07-07 23:00:11 +02:00
openSocketLookupTable . remove ( thread ) ;
2005-07-07 15:58:54 +02:00
}
}
}
2005-08-07 17:16:33 +02:00
}
2005-07-07 15:58:54 +02:00
}
2005-08-07 17:16:33 +02:00
2005-07-07 15:58:54 +02:00
/ * *
* Getting a list of open sockets where the current thread is
2005-08-07 17:16:33 +02:00
* the owner
2005-07-07 15:58:54 +02:00
* @return the list of open sockets
* /
public static ArrayList getRegisteredOpenSockets ( ) {
2005-07-07 23:00:11 +02:00
Thread currentThread = Thread . currentThread ( ) ;
2005-08-07 17:16:33 +02:00
return getRegisteredOpenSockets ( currentThread ) ;
2005-07-07 15:58:54 +02:00
}
2005-08-07 17:16:33 +02:00
2005-07-07 15:58:54 +02:00
/ * *
* Getting a list of open sockets where the thread with the given
* thread id is the owner
* @param threadId the thread id of the owner thread
* @return the list of open sockets
* /
2005-07-07 23:00:11 +02:00
public static ArrayList getRegisteredOpenSockets ( Thread thread ) {
2005-07-07 15:58:54 +02:00
synchronized ( openSocketLookupTable ) {
ArrayList openSockets = null ;
2005-07-07 23:00:11 +02:00
if ( openSocketLookupTable . containsKey ( thread ) ) {
openSockets = ( ArrayList ) openSocketLookupTable . get ( thread ) ;
2005-07-07 15:58:54 +02:00
} else {
openSockets = new ArrayList ( 0 ) ;
}
return openSockets ;
2005-08-07 17:16:33 +02:00
}
}
2005-12-06 22:21:14 +01:00
2006-09-18 12:12:11 +02:00
// /**
// * This method outputs the input stream to either an output socket or an
// * file or both. If the length of the input stream is given in the
// * header, exactly that lenght is written. Otherwise the stream is
// * written, till it is closed. If this instance is zipped, stream the
// * input stream through gzip to unzip it on the fly.
// *
// * @param procOS OutputStream where the stream is to be written. If null
// * no write happens.
// * @param bufferOS OutputStream where the stream is to be written too.
// * If null no write happens.
// * @param clientInput InputStream where the content is to be read from.
// * @throws IOException
// */
// private static void writeContentX(InputStream clientInput, boolean usegzip, long length, OutputStream procOS, OutputStream bufferOS) throws IOException {
// // we write length bytes, but if length == -1 (or < 0) then we
// // write until the input stream closes
// // procOS == null -> no write to procOS
// // file == null -> no write to file
// // If the Content-Encoding is gzip, we gunzip on-the-fly
// // and change the Content-Encoding and Content-Length attributes in the header
// byte[] buffer = new byte[2048];
// int l;
// long len = 0;
//
// // using the proper intput stream
// InputStream dis = (usegzip) ? (InputStream) new GZIPInputStream(clientInput) : (InputStream) clientInput;
//
// // we have three methods of reading: length-based, length-based gzip and connection-close-based
// try {
// if (length > 0) {
// // we read exactly 'length' bytes
// while ((len < length) && ((l = dis.read(buffer)) >= 0)) {
// if (procOS != null) procOS.write(buffer, 0, l);
// if (bufferOS != null) bufferOS.write(buffer, 0, l);
// len += l;
// }
// } else {
// // no content-length was given, thus we read until the connection closes
// while ((l = dis.read(buffer, 0, buffer.length)) >= 0) {
// if (procOS != null) procOS.write(buffer, 0, l);
// if (bufferOS != null) bufferOS.write(buffer, 0, l);
// }
// }
// } catch (java.net.SocketException e) {
// throw new IOException("Socket exception: " + e.getMessage());
// } catch (java.net.SocketTimeoutException e) {
// throw new IOException("Socket time-out: " + e.getMessage());
// } finally {
// // close the streams
// if (procOS != null) {
// if (procOS instanceof httpChunkedOutputStream)
// ((httpChunkedOutputStream)procOS).finish();
// procOS.flush();
// }
// if (bufferOS != null) bufferOS.flush();
// buffer = null;
// }
// }
2005-12-06 22:21:14 +01:00
2005-08-07 17:16:33 +02:00
2005-08-10 23:50:17 +02:00
/ * *
* Inner Class to get the response of an http - request and parse it .
* /
public final class response {
// Response-Header = Date | Pragma | Allow | Content-Encoding | Content-Length | Content-Type |
// Expires | Last-Modified | HTTP-header
/ *
Status - Line = HTTP - Version SP Status - Code SP Reason - Phrase CRLF
1xx : Informational - Not used , but reserved for future use
2xx : Success - The action was successfully received , understood , and accepted .
3xx : Redirection - Further action must be taken in order to complete the request
4xx : Client Error - The request contains bad syntax or cannot be fulfilled
5xx : Server Error - The server failed to fulfill an apparently valid request
* /
// header information
public httpHeader responseHeader = null ;
public String httpVer = " HTTP/0.9 " ;
public String status ; // the success/failure response string starting with status-code
2005-09-05 10:01:54 +02:00
public int statusCode = 503 ;
public String statusText = " internal error " ;
2005-08-10 23:50:17 +02:00
private boolean gzip ; // for gunzipping on-the-fly
2006-09-09 17:06:49 +02:00
private long gzippedLength = - 1 ; // reported content length if content-encoding is set
2005-12-05 01:17:12 +01:00
2005-08-10 23:50:17 +02:00
/ * *
* Constructor for this class . Reads in the content for the given outer
* instance and parses it .
*
* @param zipped true , if the content of this response is gzipped .
* @throws IOException
* /
public response ( boolean zipped ) throws IOException {
// lets start with worst-case attributes as set-up
2005-10-09 06:43:07 +02:00
this . responseHeader = new httpHeader ( reverseMappingCache ) ;
this . statusCode = 503 ;
this . statusText = " internal httpc error " ;
this . status = Integer . toString ( this . statusCode ) + " " + this . statusText ;
this . gzip = false ;
2005-08-10 23:50:17 +02:00
// check connection status
2005-10-09 06:43:07 +02:00
if ( httpc . this . clientInput = = null ) {
2005-08-10 23:50:17 +02:00
// the server has meanwhile disconnected
2005-10-09 06:43:07 +02:00
this . statusCode = 503 ;
this . statusText = " lost connection to server " ;
this . status = Integer . toString ( this . statusCode ) + " " + this . statusText ;
2005-08-10 23:50:17 +02:00
return ; // in bad mood
}
// reads in the http header, right now, right here
2005-10-09 06:43:07 +02:00
byte [ ] b = serverCore . receive ( httpc . this . clientInput , httpc . this . readLineBuffer , terminalMaxLength , false ) ;
2005-08-10 23:50:17 +02:00
if ( b = = null ) {
// the server has meanwhile disconnected
2005-10-09 06:43:07 +02:00
this . statusCode = 503 ;
this . statusText = " server has closed connection " ;
this . status = Integer . toString ( this . statusCode ) + " " + this . statusText ;
2005-08-10 23:50:17 +02:00
return ; // in bad mood
}
2005-09-05 10:01:54 +02:00
2005-09-20 23:49:47 +02:00
// parsing the response status line
String buffer = new String ( b ) ;
Object [ ] responseInfo = httpHeader . parseResponseLine ( buffer ) ;
this . httpVer = ( String ) responseInfo [ 0 ] ;
this . statusCode = ( ( Integer ) responseInfo [ 1 ] ) . intValue ( ) ;
this . statusText = ( String ) responseInfo [ 2 ] ;
this . status = this . statusCode + " " + this . statusText ;
2005-09-05 10:01:54 +02:00
2005-09-20 23:49:47 +02:00
if ( ( this . statusCode = = 500 ) & & ( this . statusText . equals ( " status line parse error " ) ) ) {
// flush in anything that comes without parsing
2005-10-09 06:43:07 +02:00
while ( ( b ! = null ) & & ( b . length ! = 0 ) ) b = serverCore . receive ( httpc . this . clientInput , httpc . this . readLineBuffer , terminalMaxLength , false ) ;
2005-09-20 23:49:47 +02:00
return ; // in bad mood
2005-09-05 10:01:54 +02:00
}
2005-09-20 23:49:47 +02:00
2005-08-10 23:50:17 +02:00
// check validity
2005-09-20 23:49:47 +02:00
if ( this . statusCode = = 400 ) {
2005-08-10 23:50:17 +02:00
// bad request
// flush in anything that comes without parsing
2005-10-09 06:43:07 +02:00
while ( ( b = serverCore . receive ( httpc . this . clientInput , httpc . this . readLineBuffer , terminalMaxLength , false ) ) . length ! = 0 ) { }
2005-08-10 23:50:17 +02:00
return ; // in bad mood
}
// at this point we should have a valid response. read in the header properties
String key = " " ;
2005-10-09 06:43:07 +02:00
while ( ( b = serverCore . receive ( httpc . this . clientInput , httpc . this . readLineBuffer , terminalMaxLength , false ) ) ! = null ) {
2005-08-10 23:50:17 +02:00
if ( b . length = = 0 ) break ;
buffer = new String ( b ) ;
2006-02-08 19:48:38 +01:00
buffer = buffer . trim ( ) ;
2005-08-10 23:50:17 +02:00
//System.out.println("#H#" + buffer); // debug
if ( buffer . charAt ( 0 ) < = 32 ) {
// use old entry
if ( key . length ( ) = = 0 ) throw new IOException ( " header corrupted - input error " ) ;
// attach new line
2005-10-09 06:43:07 +02:00
if ( ! ( this . responseHeader . containsKey ( key ) ) ) throw new IOException ( " header corrupted - internal error " ) ;
this . responseHeader . put ( key , ( String ) this . responseHeader . get ( key ) + " " + buffer . trim ( ) ) ;
2005-08-10 23:50:17 +02:00
} else {
// create new entry
2005-09-20 23:49:47 +02:00
int p = buffer . indexOf ( " : " ) ;
2005-08-10 23:50:17 +02:00
if ( p > 0 ) {
2005-10-09 06:43:07 +02:00
this . responseHeader . add ( buffer . substring ( 0 , p ) . trim ( ) , buffer . substring ( p + 1 ) . trim ( ) ) ;
2005-08-10 23:50:17 +02:00
} else {
2006-05-10 18:01:14 +02:00
serverLog . logSevere ( " HTTPC " , " RESPONSE PARSE ERROR: HOST=' " + httpc . this . adressed_host + " ', PATH=' " + httpc . this . requestPath + " ', STATUS=' " + this . status + " ' " ) ;
2005-08-30 23:32:59 +02:00
serverLog . logSevere ( " HTTPC " , " ..............BUFFER: " + buffer ) ;
2006-03-07 20:38:10 +01:00
throw new IOException ( this . status ) ;
2005-08-10 23:50:17 +02:00
}
}
}
// finished with reading header
// we will now manipulate the header if the content is gzip encoded, because
// reading the content with "writeContent" will gunzip on-the-fly
2005-10-09 06:43:07 +02:00
this . gzip = ( ( zipped ) & & ( this . responseHeader . gzip ( ) ) ) ;
2005-08-10 23:50:17 +02:00
2005-10-09 06:43:07 +02:00
if ( this . gzip ) {
2006-09-09 17:06:49 +02:00
if ( this . responseHeader . containsKey ( httpHeader . CONTENT_LENGTH ) ) {
this . gzippedLength = this . responseHeader . contentLength ( ) ;
}
2005-10-09 06:43:07 +02:00
this . responseHeader . remove ( httpHeader . 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
this . responseHeader . remove ( httpHeader . CONTENT_LENGTH ) ; // we cannot use the length during gunzippig yet; still we can hope that it works
2005-08-10 23:50:17 +02:00
}
}
2006-09-09 17:06:49 +02:00
public long getGzippedLength ( ) {
return this . gzippedLength ;
}
public boolean isGzipped ( ) {
return this . gzip ;
}
2005-08-10 23:50:17 +02:00
/ * *
* Converts an instance of this class into a readable string .
*
* @return String with some information about this instance .
* /
public String toString ( ) {
StringBuffer toStringBuffer = new StringBuffer ( ) ;
toStringBuffer . append ( ( this . status = = null ) ? " Status: Unknown " : " Status: " + this . status )
. append ( " | Headers: " )
. append ( ( this . responseHeader = = null ) ? " none " : this . responseHeader . toString ( ) ) ;
2007-02-06 17:26:56 +01:00
return new String ( toStringBuffer ) ;
2005-08-10 23:50:17 +02:00
}
/ * *
* Returns wether this request was successful or not . Stati beginning
* with 2 or 3 are considered successful .
*
2006-04-18 13:37:03 +02:00
* @return True , if the request was successful .
2005-08-10 23:50:17 +02:00
* /
public boolean success ( ) {
2005-10-09 06:43:07 +02:00
return ( ( this . status . charAt ( 0 ) = = '2' ) | | ( this . status . charAt ( 0 ) = = '3' ) ) ;
2005-08-10 23:50:17 +02:00
}
2006-09-18 12:12:11 +02:00
/ * *
2007-02-26 13:56:50 +01:00
* If the response was encoded using < code > Content - Encoding : gzip < / code >
2006-09-18 12:12:11 +02:00
* a { @link GZIPInputStream } is returned . If the < code > Content - Length < / code > header was set ,
* a { @link httpContentLengthInputStream } is returned which returns < code > - 1 < / code > if the end of the
* response body was reached .
*
2007-02-26 13:56:50 +01:00
* @return a { @link InputStream } to read the response body
2006-09-18 12:12:11 +02:00
* @throws IOException
* /
public InputStream getContentInputStream ( ) throws IOException {
if ( this . gzip ) {
// use a gzip input stream for Content-Encoding: gzip
return new GZIPInputStream ( httpc . this . clientInput ) ;
} else if ( this . responseHeader . contentLength ( ) ! = - 1 ) {
// use a httpContentLengthInputStream to read until the end of the response body is reached
return new httpContentLengthInputStream ( httpc . this . clientInput , this . responseHeader . contentLength ( ) ) ;
}
// no Content-Lenght was set. In this case we can read until EOF
return httpc . this . clientInput ;
}
2005-08-10 23:50:17 +02:00
/ * *
2007-02-26 13:56:50 +01:00
* This method just outputs the found content into an byte - array and
2005-08-10 23:50:17 +02:00
* returns it .
*
2007-02-26 13:56:50 +01:00
* @return the found content
2005-08-10 23:50:17 +02:00
* @throws IOException
* /
public byte [ ] writeContent ( ) throws IOException {
2006-09-18 12:12:11 +02:00
// int contentLength = (int) this.responseHeader.contentLength();
// serverByteBuffer sbb = new serverByteBuffer((contentLength==-1)?8192:contentLength);
// writeContentX(httpc.this.clientInput, this.gzip, this.responseHeader.contentLength(), null, sbb);
// return sbb.getBytes();
return serverFileUtils . read ( this . getContentInputStream ( ) ) ;
2005-08-10 23:50:17 +02:00
}
2006-10-03 13:05:48 +02:00
2005-08-10 23:50:17 +02:00
/ * *
* This method outputs the found content into an byte - array and
* additionally outputs it to procOS .
*
* @param procOS
2007-02-26 13:56:50 +01:00
* @return the found content
2005-08-10 23:50:17 +02:00
* @throws IOException
* /
2006-10-03 13:05:48 +02:00
public byte [ ] writeContent ( Object procOS , boolean returnByteArray ) throws IOException {
serverByteBuffer sbb = null ;
if ( returnByteArray ) {
int contentLength = ( int ) this . responseHeader . contentLength ( ) ;
sbb = new serverByteBuffer ( ( contentLength = = - 1 ) ? 8192 : contentLength ) ;
}
2006-09-18 12:12:11 +02:00
if ( procOS instanceof OutputStream ) {
//writeContentX(httpc.this.clientInput, this.gzip, this.responseHeader.contentLength(), procOS, sbb);
serverFileUtils . writeX ( this . getContentInputStream ( ) , ( OutputStream ) procOS , sbb ) ;
} else if ( procOS instanceof Writer ) {
String charSet = this . responseHeader . getCharacterEncoding ( ) ;
2006-09-18 13:39:06 +02:00
if ( charSet = = null ) charSet = httpHeader . DEFAULT_CHARSET ;
2006-09-18 12:12:11 +02:00
serverFileUtils . writeX ( this . getContentInputStream ( ) , charSet , ( Writer ) procOS , sbb , charSet ) ;
} else {
throw new IllegalArgumentException ( " Invalid procOS object type ' " + procOS . getClass ( ) . getName ( ) + " ' " ) ;
}
2006-10-03 13:05:48 +02:00
return ( sbb = = null ) ? null : sbb . getBytes ( ) ;
2006-09-18 12:12:11 +02:00
}
2005-08-10 23:50:17 +02:00
/ * *
* This method writes the input stream to either another output stream
* or a file or both .
*
* @param procOS
* @param file
* @throws IOException
* /
2006-09-18 12:12:11 +02:00
public void writeContent ( Object procOS , File file ) throws IOException {
2005-08-10 23:50:17 +02:00
// this writes the input stream to either another output stream or
// a file or both.
FileOutputStream bufferOS = null ;
try {
if ( file ! = null ) bufferOS = new FileOutputStream ( file ) ;
2006-09-18 12:12:11 +02:00
if ( procOS instanceof OutputStream ) {
serverFileUtils . writeX ( this . getContentInputStream ( ) , ( OutputStream ) procOS , bufferOS ) ;
//writeContentX(httpc.this.clientInput, this.gzip, this.responseHeader.contentLength(), procOS, bufferOS);
} else if ( procOS instanceof Writer ) {
String charSet = this . responseHeader . getCharacterEncoding ( ) ;
2006-09-18 13:39:06 +02:00
if ( charSet = = null ) charSet = httpHeader . DEFAULT_CHARSET ;
2006-09-18 12:12:11 +02:00
serverFileUtils . writeX ( this . getContentInputStream ( ) , charSet , ( Writer ) procOS , bufferOS , charSet ) ;
} else {
throw new IllegalArgumentException ( " Invalid procOS object type ' " + procOS . getClass ( ) . getName ( ) + " ' " ) ;
}
2005-08-10 23:50:17 +02:00
} finally {
if ( bufferOS ! = null ) {
bufferOS . close ( ) ;
if ( file . length ( ) = = 0 ) file . delete ( ) ;
}
}
}
2005-12-06 22:21:14 +01:00
2005-08-10 23:50:17 +02:00
/ * *
* This method outputs a logline to the serverlog with the current
* status of this instance .
* /
public void print ( ) {
2005-10-09 06:43:07 +02:00
serverLog . logInfo ( " HTTPC " , " RESPONSE: status= " + this . status + " , header= " + this . responseHeader . toString ( ) ) ;
2005-08-10 23:50:17 +02:00
}
}
2005-04-07 21:19:42 +02:00
}
/ *
import java.net.* ;
import java.io.* ;
import javax.net.ssl.* ;
import javax.security.cert.X509Certificate ;
import java.security.KeyStore ;
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
//The application can be modified to connect to a server outside
//the firewall by following SSLSocketClientWithTunneling.java.
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
public class SSLSocketClientWithClientAuth {
2005-08-07 17:16:33 +02:00
2005-04-07 21:19:42 +02:00
public static void main ( String [ ] args ) throws Exception {
2005-06-18 03:48:11 +02:00
String host = null ;
int port = - 1 ;
String path = null ;
for ( int i = 0 ; i < args . length ; i + + )
System . out . println ( args [ i ] ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
if ( args . length < 3 ) {
System . out . println (
" USAGE: java SSLSocketClientWithClientAuth " +
" host port requestedfilepath " ) ;
System . exit ( - 1 ) ;
}
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
try {
host = args [ 0 ] ;
port = Integer . parseInt ( args [ 1 ] ) ;
path = args [ 2 ] ;
} catch ( IllegalArgumentException e ) {
System . out . println ( " USAGE: java SSLSocketClientWithClientAuth " +
" host port requestedfilepath " ) ;
System . exit ( - 1 ) ;
}
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
try {
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
SSLSocketFactory factory = null ;
try {
SSLContext ctx ;
KeyManagerFactory kmf ;
KeyStore ks ;
char [ ] passphrase = " passphrase " . toCharArray ( ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
ctx = SSLContext . getInstance ( " TLS " ) ;
kmf = KeyManagerFactory . getInstance ( " SunX509 " ) ;
ks = KeyStore . getInstance ( " JKS " ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
ks . load ( new FileInputStream ( " testkeys " ) , passphrase ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
kmf . init ( ks , passphrase ) ;
ctx . init ( kmf . getKeyManagers ( ) , null , null ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
factory = ctx . getSocketFactory ( ) ;
} catch ( Exception e ) {
throw new IOException ( e . getMessage ( ) ) ;
}
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
SSLSocket socket = ( SSLSocket ) factory . createSocket ( host , port ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
socket . startHandshake ( ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
PrintWriter out = new PrintWriter (
new BufferedWriter (
new OutputStreamWriter (
socket . getOutputStream ( ) ) ) ) ;
out . println ( " GET " + path + " HTTP/1.1 " ) ;
out . println ( ) ;
out . flush ( ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
if ( out . checkError ( ) )
System . out . println (
" SSLSocketClient: java.io.PrintWriter error " ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
BufferedReader in = new BufferedReader (
new InputStreamReader (
socket . getInputStream ( ) ) ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
String inputLine ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
while ( ( inputLine = in . readLine ( ) ) ! = null )
System . out . println ( inputLine ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
in . close ( ) ;
out . close ( ) ;
socket . close ( ) ;
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
} catch ( Exception e ) {
e . printStackTrace ( ) ;
}
2005-04-07 21:19:42 +02:00
}
}
2005-06-18 03:48:11 +02:00
* /
2005-04-19 08:55:57 +02:00
final class httpcFactory implements org . apache . commons . pool . PoolableObjectFactory {
2005-08-07 17:16:33 +02:00
2005-04-19 08:55:57 +02:00
public httpcFactory ( ) {
2005-06-18 03:48:11 +02:00
super ( ) ;
2005-04-19 08:55:57 +02:00
}
2005-08-07 17:16:33 +02:00
2005-04-19 08:55:57 +02:00
/ * *
* @see org . apache . commons . pool . PoolableObjectFactory # makeObject ( )
* /
public Object makeObject ( ) throws Exception {
return new httpc ( ) ;
2005-06-18 03:48:11 +02:00
}
2005-08-07 17:16:33 +02:00
2005-06-18 03:48:11 +02:00
/ * *
2005-04-19 08:55:57 +02:00
* @see org . apache . commons . pool . PoolableObjectFactory # destroyObject ( java . lang . Object )
* /
public void destroyObject ( Object obj ) {
2005-12-06 11:41:19 +01:00
assert ( obj instanceof httpc ) : " Invalid object type added to pool. " ;
2005-04-19 08:55:57 +02:00
if ( obj instanceof httpc ) {
httpc theHttpc = ( httpc ) obj ;
2005-08-07 17:16:33 +02:00
2005-04-19 12:42:48 +02:00
theHttpc . removedFromPool = true ;
2005-04-19 08:55:57 +02:00
}
}
2005-08-07 17:16:33 +02:00
2005-04-19 08:55:57 +02:00
/ * *
* @see org . apache . commons . pool . PoolableObjectFactory # validateObject ( java . lang . Object )
* /
public boolean validateObject ( Object obj ) {
2005-12-06 11:41:19 +01:00
assert ( obj instanceof httpc ) : " Invalid object type in pool. " ;
2005-04-19 08:55:57 +02:00
return true ;
}
2005-08-07 17:16:33 +02:00
2005-04-19 08:55:57 +02:00
/ * *
2005-06-18 03:48:11 +02:00
* @param obj
*
2005-04-19 08:55:57 +02:00
* /
public void activateObject ( Object obj ) {
//log.debug(" activateObject...");
}
2005-08-07 17:16:33 +02:00
2005-04-19 08:55:57 +02:00
/ * *
2005-06-18 03:48:11 +02:00
* @param obj
*
2005-04-19 08:55:57 +02:00
* /
2005-06-18 03:48:11 +02:00
public void passivateObject ( Object obj ) {
2005-12-06 11:41:19 +01:00
assert ( obj instanceof httpc ) : " Invalid object type returned to pool. " ;
2005-04-19 08:55:57 +02:00
}
2005-06-18 03:48:11 +02:00
}
2005-04-19 08:55:57 +02:00
final class httpcPool extends GenericObjectPool {
/ * *
* First constructor .
* @param objFactory
2005-06-18 03:48:11 +02:00
* /
2005-04-19 08:55:57 +02:00
public httpcPool ( httpcFactory objFactory ) {
super ( objFactory ) ;
this . setMaxIdle ( 75 ) ; // Maximum idle threads.
this . setMaxActive ( 150 ) ; // Maximum active threads.
this . setMinEvictableIdleTimeMillis ( 30000 ) ; //Evictor runs every 30 secs.
//this.setMaxWait(1000); // Wait 1 second till a thread is available
}
2005-08-07 17:16:33 +02:00
2005-04-19 08:55:57 +02:00
public httpcPool ( httpcFactory objFactory ,
2005-06-18 03:48:11 +02:00
GenericObjectPool . Config config ) {
2005-04-19 08:55:57 +02:00
super ( objFactory , config ) ;
}
2005-08-07 17:16:33 +02:00
2005-04-19 08:55:57 +02:00
/ * *
* @see org . apache . commons . pool . impl . GenericObjectPool # borrowObject ( )
* /
public Object borrowObject ( ) throws Exception {
2005-06-18 03:48:11 +02:00
return super . borrowObject ( ) ;
2005-04-19 08:55:57 +02:00
}
2005-08-07 17:16:33 +02:00
2005-04-19 08:55:57 +02:00
/ * *
* @see org . apache . commons . pool . impl . GenericObjectPool # returnObject ( java . lang . Object )
* /
public void returnObject ( Object obj ) throws Exception {
super . returnObject ( obj ) ;
2005-06-18 03:48:11 +02:00
}
}