diff --git a/jdk/make/sun/net/FILES_java.gmk b/jdk/make/sun/net/FILES_java.gmk index 1ab771a37f1..3d729947667 100644 --- a/jdk/make/sun/net/FILES_java.gmk +++ b/jdk/make/sun/net/FILES_java.gmk @@ -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 \ diff --git a/jdk/src/share/classes/sun/net/www/http/HttpCapture.java b/jdk/src/share/classes/sun/net/www/http/HttpCapture.java new file mode 100644 index 00000000000..873c0dcc398 --- /dev/null +++ b/jdk/src/share/classes/sun/net/www/http/HttpCapture.java @@ -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 patterns = null; + private static volatile ArrayList capFiles = null; + + private static synchronized void init() { + initialized = true; + String rulesFile = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + 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(); + capFiles = new ArrayList(); + } + 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; + } +} diff --git a/jdk/src/share/classes/sun/net/www/http/HttpCaptureInputStream.java b/jdk/src/share/classes/sun/net/www/http/HttpCaptureInputStream.java new file mode 100644 index 00000000000..fd1320295a5 --- /dev/null +++ b/jdk/src/share/classes/sun/net/www/http/HttpCaptureInputStream.java @@ -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; + } +} diff --git a/jdk/src/share/classes/sun/net/www/http/HttpCaptureOutputStream.java b/jdk/src/share/classes/sun/net/www/http/HttpCaptureOutputStream.java new file mode 100644 index 00000000000..e2718ee6d27 --- /dev/null +++ b/jdk/src/share/classes/sun/net/www/http/HttpCaptureOutputStream.java @@ -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(); + } +} diff --git a/jdk/src/share/classes/sun/net/www/http/HttpClient.java b/jdk/src/share/classes/sun/net/www/http/HttpClient.java index b0e4cc37385..f170ff1cca0 100644 --- a/jdk/src/share/classes/sun/net/www/http/HttpClient.java +++ b/jdk/src/share/classes/sun/net/www/http/HttpClient.java @@ -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() { - 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; } diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java b/jdk/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java new file mode 100644 index 00000000000..0163d42eda0 --- /dev/null +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java @@ -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(); + } + +} diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index aacab5f238d..5e28654b950 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -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() { 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 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> 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> 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