6811297: Add more logging to HTTP protocol handler

Added extra logging to HttpURLConnection and HttpClient. Added a capture tool.

Reviewed-by: chegar
This commit is contained in:
Jean-Christophe Collet 2009-06-25 18:56:30 +02:00
parent b9554f42b8
commit 1ece67558e
7 changed files with 551 additions and 97 deletions

View File

@ -66,6 +66,9 @@ FILES_java = \
sun/net/www/protocol/file/Handler.java \
sun/net/www/protocol/file/FileURLConnection.java \
sun/net/www/http/HttpClient.java \
sun/net/www/http/HttpCapture.java \
sun/net/www/http/HttpCaptureInputStream.java \
sun/net/www/http/HttpCaptureOutputStream.java \
sun/net/www/http/PosterOutputStream.java \
sun/net/www/http/ChunkedInputStream.java \
sun/net/www/http/ChunkedOutputStream.java \
@ -75,6 +78,7 @@ FILES_java = \
sun/net/www/http/Hurryable.java \
sun/net/www/protocol/http/Handler.java \
sun/net/www/protocol/http/HttpURLConnection.java \
sun/net/www/protocol/http/HttpLogFormatter.java \
sun/net/www/protocol/http/HttpAuthenticator.java \
sun/net/www/protocol/http/AuthenticationHeader.java \
sun/net/www/protocol/http/AuthenticationInfo.java \

View File

@ -0,0 +1,171 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.net.www.http;
import java.io.*;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.net.NetProperties;
import java.util.regex.*;
/**
* Main class of the HTTP traffic capture tool.
* Captures are triggered by the sun.net.http.captureRules system property.
* If set, it should point to a file containing the capture rules.
* Format for the file is simple:
* - 1 rule per line
* - Lines starting with a # are considered comments and ignored
* - a rule is a pair of a regular expression and file pattern, separated by a comma
* - The regular expression is applied to URLs, if it matches, the traffic for
* that URL will be captured in the associated file.
* - if the file name contains a '%d', then that sequence will be replaced by a
* unique random number for each URL. This allow for multi-threaded captures
* of URLs matching the same pattern.
* - Rules are checked in sequence, in the same order as in the file, until a
* match is found or the end of the list is reached.
*
* Examples of rules:
* www\.sun\.com , sun%d.log
* yahoo\.com\/.*asf , yahoo.log
*
* @author jccollet
*/
public class HttpCapture {
private File file = null;
private boolean incoming = true;
private BufferedWriter out = null;
private static boolean initialized = false;
private static volatile ArrayList<Pattern> patterns = null;
private static volatile ArrayList<String> capFiles = null;
private static synchronized void init() {
initialized = true;
String rulesFile = java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<String>() {
public String run() {
return NetProperties.get("sun.net.http.captureRules");
}
});
if (rulesFile != null && !rulesFile.isEmpty()) {
BufferedReader in;
try {
in = new BufferedReader(new FileReader(rulesFile));
} catch (FileNotFoundException ex) {
return;
}
try {
String line = in.readLine();
while (line != null) {
line = line.trim();
if (!line.startsWith("#")) {
// skip line if it's a comment
String[] s = line.split(",");
if (s.length == 2) {
if (patterns == null) {
patterns = new ArrayList<Pattern>();
capFiles = new ArrayList<String>();
}
patterns.add(Pattern.compile(s[0].trim()));
capFiles.add(s[1].trim());
}
}
line = in.readLine();
}
} catch (IOException ioe) {
} finally {
try {
in.close();
} catch (IOException ex) {
}
}
}
}
private static synchronized boolean isInitialized() {
return initialized;
}
private HttpCapture(File f, java.net.URL url) {
file = f;
try {
out = new BufferedWriter(new FileWriter(file, true));
out.write("URL: " + url + "\n");
} catch (IOException ex) {
Logger.getLogger(HttpCapture.class.getName()).log(Level.SEVERE, null, ex);
}
}
public synchronized void sent(int c) throws IOException {
if (incoming) {
out.write("\n------>\n");
incoming = false;
out.flush();
}
out.write(c);
}
public synchronized void received(int c) throws IOException {
if (!incoming) {
out.write("\n<------\n");
incoming = true;
out.flush();
}
out.write(c);
}
public synchronized void flush() throws IOException {
out.flush();
}
public static HttpCapture getCapture(java.net.URL url) {
if (!isInitialized()) {
init();
}
if (patterns == null || patterns.isEmpty()) {
return null;
}
String s = url.toString();
for (int i = 0; i < patterns.size(); i++) {
Pattern p = patterns.get(i);
if (p.matcher(s).find()) {
String f = capFiles.get(i);
File fi;
if (f.indexOf("%d") >= 0) {
java.util.Random rand = new java.util.Random();
do {
String f2 = f.replace("%d", Integer.toString(rand.nextInt()));
fi = new File(f2);
} while (fi.exists());
} else {
fi = new File(f);
}
return new HttpCapture(fi, url);
}
}
return null;
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.net.www.http;
import java.io.*;
/**
* A Simple FilterInputStream subclass to capture HTTP traffic.
* Every byte read is also passed to the HttpCapture class.
*
* @author jccollet
*/
public class HttpCaptureInputStream extends FilterInputStream {
private HttpCapture capture = null;
public HttpCaptureInputStream(InputStream in, HttpCapture cap) {
super(in);
capture = cap;
}
@Override
public int read() throws IOException {
int i = super.read();
capture.received(i);
return i;
}
@Override
public void close() throws IOException {
try {
capture.flush();
} catch (IOException iOException) {
}
super.close();
}
@Override
public int read(byte[] b) throws IOException {
int ret = super.read(b);
for (int i = 0; i < ret; i++) {
capture.received(b[i]);
}
return ret;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int ret = super.read(b, off, len);
for (int i = 0; i < ret; i++) {
capture.received(b[off+i]);
}
return ret;
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.net.www.http;
import java.io.*;
/**
* A Simple FilterOutputStream subclass to capture HTTP traffic.
* Every byte written is also passed to the HttpCapture class.
*
* @author jccollet
*/
public class HttpCaptureOutputStream extends FilterOutputStream {
private HttpCapture capture = null;
public HttpCaptureOutputStream(OutputStream out, HttpCapture cap) {
super(out);
capture = cap;
}
@Override
public void write(int b) throws IOException {
capture.sent(b);
out.write(b);
}
@Override
public void write(byte[] ba) throws IOException {
for (byte b : ba) {
capture.sent(b);
}
out.write(ba);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
for (int i = off; i < len; i++) {
capture.sent(b[i]);
}
out.write(b, off, len);
}
@Override
public void flush() throws IOException {
try {
capture.flush();
} catch (IOException iOException) {
}
super.flush();
}
}

View File

@ -27,6 +27,9 @@ package sun.net.www.http;
import java.io.*;
import java.net.*;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.net.NetworkClient;
import sun.net.ProgressSource;
import sun.net.www.MessageHeader;
@ -34,7 +37,6 @@ import sun.net.www.HeaderParser;
import sun.net.www.MeteredStream;
import sun.net.www.ParseUtil;
import sun.net.www.protocol.http.HttpURLConnection;
import sun.misc.RegexpPool;
/**
* @author Herb Jellinek
@ -64,6 +66,10 @@ public class HttpClient extends NetworkClient {
/** Default port number for http daemons. REMIND: make these private */
static final int httpPortNumber = 80;
// Use same logger as HttpURLConnection since we want to combine both event
// streams into one single HTTP log
private static Logger logger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
/** return default port number (subclasses may override) */
protected int getDefaultPort () { return httpPortNumber; }
@ -75,30 +81,6 @@ public class HttpClient extends NetworkClient {
return -1;
}
/* The following three data members are left in for binary */
/* backwards-compatibility. Unfortunately, HotJava sets them directly */
/* when it wants to change the settings. The new design has us not */
/* cache these, so this is unnecessary, but eliminating the data members */
/* would break HJB 1.1 under JDK 1.2. */
/* */
/* These data members are not used, and their values are meaningless. */
/* REMIND: Take them out for JDK 2.0! */
/**
* @deprecated
*/
// public static String proxyHost = null;
/**
* @deprecated
*/
// public static int proxyPort = 80;
/* instance-specific proxy fields override the static fields if set.
* Used by FTP. These are set to the true proxy host/port if
* usingProxy is true.
*/
// private String instProxy = null;
// private int instProxyPort = -1;
/* All proxying (generic as well as instance-specific) may be
* disabled through use of this flag
*/
@ -141,6 +123,9 @@ public class HttpClient extends NetworkClient {
/* if set, the client will be reused and must not be put in cache */
public boolean reuse = false;
// Traffic capture tool, if configured. See HttpCapture class for info
private HttpCapture capture = null;
/**
* A NOP method kept for backwards binary compatibility
* @deprecated -- system properties are no longer cached.
@ -226,6 +211,7 @@ public class HttpClient extends NetworkClient {
}
});
capture = HttpCapture.getCapture(url);
openServer();
}
@ -300,8 +286,10 @@ public class HttpClient extends NetworkClient {
// KeepAliveTimeout will get reset. We simply close the connection.
// This should be fine as it is very rare that a connection
// to the same host will not use the same proxy.
ret.inCache = false;
ret.closeServer();
synchronized(ret) {
ret.inCache = false;
ret.closeServer();
}
ret = null;
}
}
@ -369,7 +357,7 @@ public class HttpClient extends NetworkClient {
kac.put(url, null, this);
}
protected boolean isInKeepAliveCache() {
protected synchronized boolean isInKeepAliveCache() {
return inCache;
}
@ -389,11 +377,16 @@ public class HttpClient extends NetworkClient {
* method parseHTTP(). That's why this method is overidden from the
* superclass.
*/
@Override
public void openServer(String server, int port) throws IOException {
serverSocket = doConnect(server, port);
try {
OutputStream out = serverSocket.getOutputStream();
if (capture != null) {
out = new HttpCaptureOutputStream(out, capture);
}
serverOutput = new PrintStream(
new BufferedOutputStream(serverSocket.getOutputStream()),
new BufferedOutputStream(out),
false, encoding);
} catch (UnsupportedEncodingException e) {
throw new InternalError(encoding+" encoding not found");
@ -412,7 +405,7 @@ public class HttpClient extends NetworkClient {
/*
* Returns true if this httpclient is from cache
*/
public boolean isCachedConnection() {
public synchronized boolean isCachedConnection() {
return cachedHttpClient;
}
@ -457,26 +450,6 @@ public class HttpClient extends NetworkClient {
super.openServer(proxyHost, proxyPort);
}
/*
* call super.openServer in a privileged block
*/
private synchronized void privilegedSuperOpenServer(final String proxyHost,
final int proxyPort)
throws IOException
{
try {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction<Void>() {
public Void run() throws IOException {
superOpenServer(proxyHost, proxyPort);
return null;
}
});
} catch (java.security.PrivilegedActionException pae) {
throw (IOException) pae.getException();
}
}
/*
*/
protected synchronized void openServer() throws IOException {
@ -490,8 +463,6 @@ public class HttpClient extends NetworkClient {
return;
}
String urlHost = url.getHost().toLowerCase();
if (url.getProtocol().equals("http") ||
url.getProtocol().equals("https") ) {
@ -595,6 +566,9 @@ public class HttpClient extends NetworkClient {
try {
serverInput = serverSocket.getInputStream();
if (capture != null) {
serverInput = new HttpCaptureInputStream(serverInput, capture);
}
serverInput = new BufferedInputStream(serverInput);
return (parseHTTPHeader(responses, pi, httpuc));
} catch (SocketTimeoutException stex) {
@ -686,7 +660,7 @@ public class HttpClient extends NetworkClient {
if (keep == null) {
keep = responses.findValue("Connection");
}
if (keep != null && keep.toLowerCase().equals("keep-alive")) {
if (keep != null && keep.toLowerCase(Locale.US).equals("keep-alive")) {
/* some servers, notably Apache1.1, send something like:
* "Keep-Alive: timeout=15, max=1" which we should respect.
*/
@ -767,10 +741,7 @@ public class HttpClient extends NetworkClient {
* the HTTP method and response code indicate there will be
* no entity body to parse.
*/
String te = null;
try {
te = responses.findValue("Transfer-Encoding");
} catch (Exception e) {}
String te = responses.findValue("Transfer-Encoding");
if (te != null && te.equalsIgnoreCase("chunked")) {
serverInput = new ChunkedInputStream(serverInput, this, responses);
@ -794,10 +765,14 @@ public class HttpClient extends NetworkClient {
* 2. "Not-Modified" or "No-Content" responses - RFC 2616 states that
* 204 or 304 response must not include a message body.
*/
try {
cl = Long.parseLong(responses.findValue("content-length"));
} catch (Exception e) {}
String cls = responses.findValue("content-length");
if (cls != null) {
try {
cl = Long.parseLong(cls);
} catch (NumberFormatException e) {
cl = -1;
}
}
String requestLine = requests.getKey(0);
if ((requestLine != null &&
@ -835,6 +810,9 @@ public class HttpClient extends NetworkClient {
if (isKeepingAlive()) {
// Wrap KeepAliveStream if keep alive is enabled.
if (logger.isLoggable(Level.FINEST)) {
logger.finest("KeepAlive stream used: " + url);
}
serverInput = new KeepAliveStream(serverInput, pi, cl, this);
failedOnce = false;
}

View File

@ -0,0 +1,130 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.net.www.protocol.http;
import java.util.logging.LogRecord;
import java.util.regex.*;
/**
* A Formatter to make the HTTP logs a bit more palatable to the developer
* looking at them. The idea is to present the HTTP events in such a way that
* commands and headers are easily spotted (i.e. on separate lines).
* @author jccollet
*/
public class HttpLogFormatter extends java.util.logging.SimpleFormatter {
// Pattern for MessageHeader data. Mostly pairs within curly brackets
private static volatile Pattern pattern = null;
// Pattern for Cookies
private static volatile Pattern cpattern = null;
public HttpLogFormatter() {
if (pattern == null) {
pattern = Pattern.compile("\\{[^\\}]*\\}");
cpattern = Pattern.compile("[^,\\] ]{2,}");
}
}
@Override
public String format(LogRecord record) {
if (!"sun.net.www.protocol.http.HttpURLConnection".equalsIgnoreCase(record.getSourceClassName())
&& !"sun.net.www.http.HttpClient".equalsIgnoreCase(record.getSourceClassName())) {
// Don't change format for stuff that doesn't concern us
return super.format(record);
}
String src = record.getMessage();
StringBuilder buf = new StringBuilder("HTTP: ");
if (src.startsWith("sun.net.www.MessageHeader@")) {
// MessageHeader logs are composed of pairs within curly brackets
// Let's extract them to make it more readable. That way we get one
// header pair (name, value) per line. A lot easier to read.
Matcher match = pattern.matcher(src);
while (match.find()) {
int i = match.start();
int j = match.end();
String s = src.substring(i + 1, j - 1);
if (s.startsWith("null: ")) {
s = s.substring(6);
}
if (s.endsWith(": null")) {
s = s.substring(0, s.length() - 6);
}
buf.append("\t").append(s).append("\n");
}
} else if (src.startsWith("Cookies retrieved: {")) {
// This comes from the Cookie handler, let's clean up the format a bit
String s = src.substring(20);
buf.append("Cookies from handler:\n");
while (s.length() >= 7) {
if (s.startsWith("Cookie=[")) {
String s2 = s.substring(8);
int c = s2.indexOf("Cookie2=[");
if (c > 0) {
s2 = s2.substring(0, c-1);
s = s2.substring(c);
} else {
s = "";
}
if (s2.length() < 4) {
continue;
}
Matcher m = cpattern.matcher(s2);
while (m.find()) {
int i = m.start();
int j = m.end();
if (i >= 0) {
String cookie = s2.substring(i + 1, j > 0 ? j - 1 : s2.length() - 1);
buf.append("\t").append(cookie).append("\n");
}
}
}
if (s.startsWith("Cookie2=[")) {
String s2 = s.substring(9);
int c = s2.indexOf("Cookie=[");
if (c > 0) {
s2 = s2.substring(0, c-1);
s = s2.substring(c);
} else {
s = "";
}
Matcher m = cpattern.matcher(s2);
while (m.find()) {
int i = m.start();
int j = m.end();
if (i >= 0) {
String cookie = s2.substring(i+1, j > 0 ? j-1 : s2.length() - 1);
buf.append("\t").append(cookie).append("\n");
}
}
}
}
} else {
// Anything else we let as is.
buf.append(src).append("\n");
}
return buf.toString();
}
}

View File

@ -237,7 +237,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
/* try auth without calling Authenticator */
private boolean tryTransparentNTLMServer = NTLMAuthentication.supportsTransparentAuth();
private boolean tryTransparentNTLMProxy = NTLMAuthentication.supportsTransparentAuth();
Object authObj;
/* Set if the user is manually setting the Authorization or Proxy-Authorization headers */
boolean isUserServerAuth;
@ -303,9 +302,16 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
return java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<PasswordAuthentication>() {
public PasswordAuthentication run() {
return Authenticator.requestPasswordAuthentication(
if (logger.isLoggable(Level.FINEST)) {
logger.finest("Requesting Authentication: host =" + host + " url = " + url);
}
PasswordAuthentication pass = Authenticator.requestPasswordAuthentication(
host, addr, port, protocol,
prompt, scheme, url, authType);
if (pass != null && logger.isLoggable(Level.FINEST)) {
logger.finest("Authentication returned: " + pass.toString());
}
return pass;
}
});
}
@ -458,7 +464,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
setRequests=true;
}
if(logger.isLoggable(Level.FINEST)) {
if (logger.isLoggable(Level.FINE)) {
logger.fine(requests.toString());
}
http.writeRequests(requests, poster);
@ -602,7 +608,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
{
boolean redir;
int redirects = 0;
InputStream in = null;
InputStream in;
do {
if (c instanceof HttpURLConnection) {
@ -715,6 +721,12 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
&& !(cachedResponse instanceof SecureCacheResponse)) {
cachedResponse = null;
}
if (logger.isLoggable(Level.FINEST)) {
logger.finest("Cache Request for " + uri + " / " + getRequestMethod());
if (cachedResponse != null) {
logger.finest("From cache: "+cachedResponse.toString());
}
}
if (cachedResponse != null) {
cachedHeaders = mapToMessageHeader(cachedResponse.getHeaders());
cachedInputStream = cachedResponse.getBody();
@ -750,10 +762,13 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
return ProxySelector.getDefault();
}
});
Proxy p = null;
if (sel != null) {
URI uri = sun.net.www.ParseUtil.toURI(url);
if (logger.isLoggable(Level.FINEST)) {
logger.finest("ProxySelector Request for " + uri);
}
Iterator<Proxy> it = sel.select(uri).iterator();
Proxy p;
while (it.hasNext()) {
p = it.next();
try {
@ -766,6 +781,11 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
http = getNewHttpClient(url, p, connectTimeout, false);
http.setReadTimeout(readTimeout);
}
if (logger.isLoggable(Level.FINEST)) {
if (p != null) {
logger.finest("Proxy used: " + p.toString());
}
}
break;
} catch (IOException ioex) {
if (p != Proxy.NO_PROXY) {
@ -993,10 +1013,16 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
URI uri = ParseUtil.toURI(url);
if (uri != null) {
if (logger.isLoggable(Level.FINEST)) {
logger.finest("CookieHandler request for " + uri);
}
Map<String, List<String>> cookies
= cookieHandler.get(
uri, requests.getHeaders(EXCLUDE_HEADERS));
if (!cookies.isEmpty()) {
if (logger.isLoggable(Level.FINEST)) {
logger.finest("Cookies retrieved: " + cookies.toString());
}
for (Map.Entry<String, List<String>> entry :
cookies.entrySet()) {
String key = entry.getKey();
@ -1126,7 +1152,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
writeRequests();
}
http.parseHTTP(responses, pi, this);
if(logger.isLoggable(Level.FINEST)) {
if (logger.isLoggable(Level.FINE)) {
logger.fine(responses.toString());
}
inputStream = http.getInputStream();
@ -1193,7 +1219,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
disconnectInternal ();
throw new IOException ("Authentication failure");
}
authObj = null;
doingNTLMp2ndStage = false;
continue;
}
@ -1270,7 +1295,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
throw new IOException ("Authentication failure");
}
doingNTLM2ndStage = false;
authObj = null;
setCookieHeader();
continue;
}
@ -1571,7 +1595,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
http.parseHTTP(responses, null, this);
/* Log the response to the CONNECT */
logger.fine(responses.toString());
if (logger.isLoggable(Level.FINE)) {
logger.fine(responses.toString());
}
statusLine = responses.getValue(0);
StringTokenizer st = new StringTokenizer(statusLine);
@ -1617,12 +1643,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
reset ();
if (!proxyAuthentication.setHeaders(this,
authhdr.headerParser(), raw)) {
proxyHost = http.getProxyHostUsed();
proxyPort = http.getProxyPortUsed();
disconnectInternal();
throw new IOException ("Authentication failure");
}
authObj = null;
doingNTLMp2ndStage = false;
continue;
}
@ -1699,7 +1722,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
setPreemptiveProxyAuthentication(requests);
/* Log the CONNECT request */
logger.fine(requests.toString());
if (logger.isLoggable(Level.FINE)) {
logger.fine(requests.toString());
}
http.writeRequests(requests, null);
// remove CONNECT header
@ -1842,6 +1867,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
}
}
}
if (logger.isLoggable(Level.FINER)) {
logger.finer("Proxy Authentication for " + authhdr.toString() +" returned " + ret.toString());
}
return ret;
}
@ -1896,21 +1924,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
}
if (ret == null) {
if (schemeID == NegotiateAuthentication.KERBEROS_AUTH) {
URL url1;
try {
url1 = new URL (url, "/"); /* truncate the path */
} catch (Exception e) {
url1 = url;
}
ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos"));
}
if (schemeID == NegotiateAuthentication.NEGOTIATE_AUTH) {
URL url1;
try {
url1 = new URL (url, "/"); /* truncate the path */
} catch (Exception e) {
url1 = url;
}
ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate"));
}
if (schemeID == BasicAuthentication.BASIC_AUTH) {
@ -1981,6 +1997,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
}
}
}
if (logger.isLoggable(Level.FINER)) {
logger.finer("Server Authentication for " + authhdr.toString() +" returned " + ret.toString());
}
return ret;
}
@ -2054,6 +2073,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
if (streaming()) {
throw new HttpRetryException (RETRY_MSG3, stat, loc);
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("Redirected from " + url + " to " + locUrl);
}
// clear out old response headers!!!!
responses = new MessageHeader();
@ -2158,11 +2180,17 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
/* raw stream, which will block on read, so only read
* the expected number of bytes, probably 0
*/
int cl = 0, n=0;
try {
cl = Integer.parseInt (responses.findValue ("Content-Length"));
} catch (Exception e) {}
for (int i=0; i<cl; ) {
long cl = 0;
int n = 0;
String cls = responses.findValue ("Content-Length");
if (cls != null) {
try {
cl = Long.parseLong (cls);
} catch (NumberFormatException e) {
cl = 0;
}
}
for (long i=0; i<cl; ) {
if ((n = is.read (cdata)) == -1) {
break;
} else {
@ -2509,12 +2537,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
return readTimeout < 0 ? 0 : readTimeout;
}
@Override
protected void finalize() {
// this should do nothing. The stream finalizer will close
// the fd
}
String getMethod() {
return method;
}