Hi All,
Hope all is well!
Have been experiencing some interesting behaviour with the source resolver
today, and in particular the java.net.HttpURLConnection implementation.
Have a look at this code:
URL url = new URL("http://localhost:8080/something/somewhere/");
URLConnection conn = url.openConnection();
HttpURLConnection c = (HttpURLConnection) conn;
System.out.println("1." + c.getInputStream());
System.out.println("2." + c.getLastModified());
System.out.println("3." + c.getContentType());
System.out.println("4." + c.getResponseCode());
Assuming that the URL points to a valid server, but a bogus path - then the
following code raises a FileNotFoundException. However, if you move the
call to getInputStream() to be after getResponseCode() then no exception is
raised and and you'll receive a valid InputStream containing the error
page from the server.
This behaviour currently causes the SourceResolver to return server error
pages as valid data when resolving a particular URI. From what I can tell,
other than examine the content returned, there's currently no easy way to
tell whether the SourceResolver resolved the document correctly or not.
I've attached a patch that examines the return code of the
HttpURLConnection and throws a SourceException if the code is not within
the valid range of 200-206 as defined by the HTTP RFC.
This fixes the problem, but prevents people from parsing error pages as
Source objects (if anyone did that before?). Perhaps someone could take a
look at the patch as maybe there's a better solution? Any ideas? If not
let me know, and I'll apply the patch attached.
Cheers,
Marcus
--
.....
,,$$$$$$$$$, Marcus Crafter
;$' '$$$$: Computer Systems Engineer
$: $$$$: ManageSoft GmbH
$ o_)$$$: 82-84 Mainzer Landstrasse
;$, _/\ &&:' 60327 Frankfurt Germany
' /( &&&
\_&&&&'
&&&&.
&&&&&&&:
Index: src/java/org/apache/excalibur/source/impl/URLSource.java
===================================================================
RCS file:
/home/cvs/avalon-excalibur/sourceresolve/src/java/org/apache/excalibur/source/impl/URLSource.java,v
retrieving revision 1.24
diff -u -r1.24 URLSource.java
--- src/java/org/apache/excalibur/source/impl/URLSource.java 4 Apr 2003 16:36:51
-0000 1.24
+++ src/java/org/apache/excalibur/source/impl/URLSource.java 27 Jun 2003 16:33:57
-0000
@@ -54,8 +54,10 @@
*/
package org.apache.excalibur.source.impl;
+import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
@@ -278,9 +280,77 @@
return input;
}
}
+ if (m_connection instanceof HttpURLConnection) {
+ validateConnection((HttpURLConnection)m_connection);
+ }
input = m_connection.getInputStream();
m_connection = null; // make sure a new m_connection is created next time
return input;
+ }
+
+ /**
+ * Method which ascertains whether a given [EMAIL PROTECTED] HttpURLConnection} is
+ * able to return valid data or not.
+ *
+ * <p>Valid return codes from HTTP servers are defined
+ * <a
href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2">here</a>
+ * to be in the range 200-206 (inclusive)</p>
+ *
+ * <p>This method checks that the given connection object has a return code
+ * within this range, and if not, raises a [EMAIL PROTECTED] SourceException}
with the return
+ * code and any data sent by the server</p>
+ *
+ * @param conn a [EMAIL PROTECTED] HttpURLConnection} instance
+ * @throws SourceException if the request did not succeed
+ * @exception IOException if an error occurs
+ */
+ private void validateConnection(final HttpURLConnection conn)
+ throws SourceException, IOException {
+ final int responseCode = conn.getResponseCode();
+ final int[] SUCCESS_CODES =
+ {
+ HttpURLConnection.HTTP_OK,
+ HttpURLConnection.HTTP_CREATED,
+ HttpURLConnection.HTTP_ACCEPTED,
+ HttpURLConnection.HTTP_NOT_AUTHORITATIVE,
+ HttpURLConnection.HTTP_NO_CONTENT,
+ HttpURLConnection.HTTP_RESET,
+ HttpURLConnection.HTTP_PARTIAL,
+ };
+
+ for (int i = 0; i < SUCCESS_CODES.length; ++i) {
+ if (responseCode == SUCCESS_CODES[i])
+ return;
+ }
+
+ // response from the server was not successful, return an error to the caller
+ final String responseText = readString(conn.getInputStream());
+
+ throw new SourceException(
+ "Request for " + conn.getURL() + " was unsuccessful " +
+ "(" + responseCode + ")" + ", response from server:\n" + responseText
+ );
+ }
+
+ /**
+ * Helper method to read an [EMAIL PROTECTED] InputStream} into a [EMAIL
PROTECTED] String}.
+ *
+ * @param stream input [EMAIL PROTECTED] InputStream}
+ * @return a contents in the [EMAIL PROTECTED] InputStream} as a [EMAIL
PROTECTED] String}
+ * @exception IOException if an error occurs
+ */
+ private String readString(final InputStream stream) throws IOException {
+ final BufferedReader is =
+ new BufferedReader(new InputStreamReader(stream));
+ String line;
+ StringBuffer resp = new StringBuffer();
+
+ while ((line = is.readLine()) != null) {
+ resp.append(line);
+ resp.append('\n');
+ }
+
+ return resp.toString();
}
private static boolean checkedURLClass = false;
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]