package com.occamlab.te.util;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URLConnection;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Class of utilities for URL Connections, Java 7 (JDK 1.7.0) and later.
*
* @author Paul Daisey (Image Matters LLC)
*
*/
public class URLConnectionUtils {
private static final Logger LOGR = Logger
.getLogger(URLConnectionUtils.class.getName());
static {
try {
System.setProperty("sun.net.http.errorstream.enableBuffering",
"true");
System.setProperty("sun.net.http.errorstream.timeout", "600");
} catch (Exception e) {
LOGR.warning("Failed to enable buffering of error stream.\n"
+ e.getMessage());
e.fillInStackTrace();
e.printStackTrace(System.err);
}
}
/**
* Get an input stream from a URL connection. In case of an IOException, get
* the ErrorStream instead, if it is available. This makes it possible to
* obtain an ows:ExceptionReport when the server returns HTTP code 400 Bad
* Request.
*
* This method depends upon features of class
* sun.net.www.protocol.http.HttpURLConnection introduced in Java version 7
* (JDK 1.7.0). From its Javadoc:
*
* System properties related to error stream handling:
*
* sun.net.http.errorstream.enableBuffering = <boolean>
*
* With the above system property set to true (default is false), when the
* response code is >=400, the HTTP handler will try to buffer the response
* body (up to a certain amount and within a time limit). Thus freeing up
* the underlying socket connection for reuse. The rationale behind this is
* that usually when the server responds with a >=400 error (client error or
* server error, such as 404 file not found), the server will send a small
* response body to explain who to contact and what to do to recover. With
* this property set to true, even if the application doesn't call
* getErrorStream(), read the response body, and then call close(), the
* underlying socket connection can still be kept-alive and reused. The
* following two system properties provide further control to the error
* stream buffering behaviour.
*
* sun.net.http.errorstream.timeout = <int> the timeout (in millisec)
* waiting the error stream to be buffered; default is 300 ms
*
* sun.net.http.errorstream.bufferSize = <int> the size (in bytes) to use
* for the buffering the error stream; default is 4k
*
* @return InputStream from URLConnection if available, or the error stream
* if the connection failed but the server sent useful data, or
* null.
*/
public static InputStream getInputStream(URLConnection uc)
throws IOException {
InputStream is = null;
try {
is = uc.getInputStream();
} catch (IOException ioe) {
if (LOGR.isLoggable(Level.FINE)) {
String msg = String
.format("Failed to resolve URL %s.\nTrying error stream...\n %s",
uc.getURL(), ioe.getMessage());
LOGR.fine(msg);
}
if (HttpURLConnection.class.isInstance(uc)) {
HttpURLConnection huc = (HttpURLConnection) uc;
is = huc.getErrorStream();
}
}
return is;
}
}