avalon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Marcus Crafter <craft...@managesoft.com>
Subject Re: [PATCH] SourceResolver strangeness ?
Date Mon, 30 Jun 2003 10:35:42 GMT
Hi All,

So the plot thickens - under JDK 1.4.1 the behaviour is as expected:

java version "1.3.1":

2. code is 0
3. code is text/html; charset=iso-8859-1
4. code is 404
1. code is sun.net.www.http.KeepAliveStream@2e000d

java version "1.4.1_03":

2. code is 0
3. code is text/html; charset=iso-8859-1
4. code is 404
Exception in thread "main" java.io.FileNotFoundException:
http://localhost/broken/something/somewhere/
 at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:713)
 at sun.net.www.protocol.http.HttpURLConnection.getHeaderField(HttpURLConnection.java:1178)
 at java.net.HttpURLConnection.getHeaderFieldDate(HttpURLConnection.java:309)

So, something's changed inbetween JDK versions.

I'll make some updates to the patch to take this into account.

Cheers,

Marcus

On Fri, Jun 27, 2003 at 06:53:01PM +0200, Marcus Crafter wrote:
> 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 {@link 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 {@link SourceException} with the return
> +     * code and any data sent by the server</p>
> +     *
> +     * @param conn a {@link 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 {@link InputStream} into a {@link String}.
> +     *
> +     * @param stream input {@link InputStream}
> +     * @return a contents in the {@link InputStream} as a {@link 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: dev-unsubscribe@avalon.apache.org
> For additional commands, e-mail: dev-help@avalon.apache.org

-- 
        .....
     ,,$$$$$$$$$,      Marcus Crafter
    ;$'      '$$$$:    Computer Systems Engineer
    $:         $$$$:   ManageSoft GmbH
     $       o_)$$$:   82-84 Mainzer Landstrasse
     ;$,    _/\ &&:'   60327 Frankfurt Germany
       '     /( &&&
           \_&&&&'
          &&&&.
    &&&&&&&:

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Mime
View raw message