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]