Re: [OpenMap Users] BinaryFile and JNLPClassLoader issue

From: Carsten Ø. Madsen <com_at_navicon.dk>
Date: Thu, 17 Jun 2010 13:35:56 +0200

Hello Tore

I'm working on it ;>

Don may have added some of the following to the trunk of svn?

I would be very interested in hearing about any problems with the patch
below as it seems to have fixed the problems we have seen with loading
shape files embedded in jar files under JNLP (1.6.20).

I have patched StreamInputReader with:

     /**
      * Read from the file
      *
      * _at_param b
      * The byte array to read into
      * _at_param off
      * the first array position to read into
      * _at_param len
      * the number of bytes to read
      * _at_return the number of bytes read
      * _at_exception IOException
      * Any IO errors encountered in reading from the file
      */
     public int read(byte b[], int off, int len) throws IOException {

         int gotsofar = 0;
         while (gotsofar < len) {
             int read = inputStream.read(b, off + gotsofar, len -
gotsofar);
             if (read == -1) {
                 if (gotsofar > 0) {
                     // Hit the EOF in the middle of the loop.
                     count(gotsofar); // BUG FIX HERE !!!
                     return gotsofar;
                 } else {
                     return read;
                 }
             } else {
                 gotsofar += read;
             }
         }

         count(gotsofar);
         return gotsofar;
     }

And BinaryFile with:

     public BinaryFile(String name) throws IOException {
         boolean showDebug = false;
         if (Debug.debugging("binaryfile")) {
             showDebug = true;
         }

         if (showDebug) {
             Debug.output("BinaryFile: trying to figure out how to handle "
                     + name);
         }

         try {
             File file = null;
             URL url = null;

             if (!Environment.isApplet()) {
                 file = new File(name);
             }

             if (file != null && file.exists()) {
                 // If the string represents a file, then we want to
                 // use the RandomAccessFile aspect of the BinaryFile.
                 setInputReader(new FileInputReader(file));
             } else {
                 // COM PATCH START
                 // see JNLP deploy tip here
                 //
http://java.sun.com/javase/6/docs/technotes/guides/jweb/deployment_advice.html#ClassLoader_and_Resources

                 final InputStream resourceStream = Thread.currentThread()
                         
.getContextClassLoader().getResourceAsStream(name);
                 if (resourceStream != null) {
                     if (showDebug) {
                         Debug.output("BinaryFile: loading " + name
                                 + " via getResourceAsStream");
                     }
                     final String urlName = name;
                     setInputReader(new StreamInputReader() {
                         {
                             this.name = urlName;
                             this.inputStream = resourceStream;
                         }

                         _at_Override
                         protected void reopen() throws IOException {
                             super.reopen();
                             inputStream = Thread.currentThread()
                                     .getContextClassLoader()
                                     .getResourceAsStream(name);
                         }
                     });
                 } else { // COM PATCH END
                     // url = ClassLoader.getSystemResource(name);
                     url = Thread.currentThread().getContextClassLoader()
                             .getResource(name);

                     // OK, now we want to look around for the file, in the
                     // classpaths, and as a resource. It may be a file in
                     // a classpath, available for direct access.
                     if (url != null) {

                         String newname = url.getFile();
                         if (showDebug) {
                             Debug.output("BinaryFile: looking for " +
newname);
                         }

                         if (!Environment.isApplet()) {
                             file = new File(newname);
                         }

                         if (file != null && file.exists()) {
                             // It's still a file, available directly.
                             // Access it with the RandomAccessFile
                             setInputReader(new FileInputReader(file));
                         } else {
                             // Need to get it as a resource. Needs
                             // special handling if it's coming in a jar
                             // file. Jar file references have a "!" in
                             // them
                             if (!setJarInputReader(newname)) {
                                 if (showDebug) {
                                     Debug.output(" trying as url: " +
url);
                                 }
                                 setInputReader(new URLInputReader(url));
                             }

                         }

                     } else if (Environment.isApplet()) {
                         if (showDebug) {
                             Debug.output(" As applet, checking
codebase...");
                         }
                         // Look in the codebase for applets...
                         URL[] cba = new URL[1];
                         cba[0] = Environment.getApplet().getCodeBase();

                         URLClassLoader ucl =
URLClassLoader.newInstance(cba);
                         url = ucl.getResource(name);

                         if (url != null) {
                             setInputReader(new URLInputReader(url));
                         }
                     }
                 }
                 // It's not in the classpath, so try it as a URL.
                 if (inputReader == null) {

                     if (showDebug) {
                         Debug.output(" lastly, trying as URL: " + name);
                     }
                     try {
                         setInputReader(new URLInputReader(new URL(name)));
                     } catch (java.security.AccessControlException ace) {
                         Debug.output("BinaryFile: " + name
                                 + " couldn't be accessed.");
                         throw new IOException(
                                 "AccessControlException trying to fetch "
                                         + name + " as a URL");
                     }
                 }

             }

             if (inputReader == null) {
                 throw new FileNotFoundException("BinaryFile can't find: "
                         + name);
             }

             classCount++;
             openCount++;

         } catch (IOException ioe) {
             throw ioe;
         }
     }

BR
Carsten

On 06/17/2010 01:22 PM, Tore Halset wrote:
> Hello.
>
> I am seeing this as well. Have you found a solution to this problem?
>
> - Tore.
>
> On Jun 8, 2010, at 14:20 , Carsten Ø. Madsen wrote:
>
>
>> Hello
>>
>> I have an issue using the BinaryFile class to load shape files in signed jar files under JNLP. Most of the time it works but sometimes I get a JNLP security warning about mixing signed and unsigned code (see [1]).
>>
>> The BinaryFile class does:
>>
>> url = Thread.currentThread()
>> .getContextClassLoader()
>> .getResource(name);
>>
>> and it then tries to decompose the url to read the contents. However [2] says that the correct way to access a resource under JNLP is to use getResourceAsStream:
>>
>> "Access the ClassLoader being used with:
>> ClassLoader cl = Thread.getCurrent().getContextClassLoader();
>>
>>
>> ClassLoader.getResource() returns a URL, but any code that assumes the URL is a JarURL to a FileURL, and then tries to decompose that FileURL to find the underlying file path will fail. The correct way to access resources is to use getResourceAsStream() which will return the correct content whatever type of ClassLoader is used to access the resource. If the resource is already cached, the contents of the resource will be returned from the cache directly, so there won't be extra network connections to the resource itself."
>> So should BinaryFile have a check to see of the class loader is a JNLP loader and then use getResourceAsStream?
>> I'm guessing that the BinaryFile fails (provokes security warning) when getResource returns something that is cached.
>> [1] http://java.sun.com/javase/6/docs/technotes/guides/jweb/mixed_code.html
>>
>> [2] http://java.sun.com/javase/6/docs/technotes/guides/jweb/deployment_advice.html#ClassLoader_and_Resources
>>
>> BR
>> Carsten
>>
>>
>>
>>
> --
> [To unsubscribe to this list send an email to "majdart_at_bbn.com"
> with the following text in the BODY of the message "unsubscribe openmap-users"]
>

--
[To unsubscribe to this list send an email to "majdart_at_bbn.com"
with the following text in the BODY of the message "unsubscribe openmap-users"]
Received on Thu Jun 17 2010 - 07:36:27 EDT

This archive was generated by hypermail 2.3.0 : Tue Mar 28 2017 - 23:25:09 EDT