Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.jruby.util;
  
  import java.io.Closeable;
 import java.net.URL;
 import java.util.List;
 import java.util.Map;
 
 import static org.jruby.util.URLUtil.getPath;
 
 // From Stas Garifulin's CompoundJarURLStreamHandler. http://jira.codehaus.org/browse/JRUBY-3299
 public class CompoundJarURLStreamHandler extends URLStreamHandler {
 
     public static final String PROTOCOL = "compoundjar";
 
     private static final CompoundJarURLStreamHandler instance = new CompoundJarURLStreamHandler();
 
     public static URL createUrl(URL baseList<Stringpaththrows MalformedURLException {
         return createUrl(basepath.toArray(new String[0]));
     }
 
     public static URL createUrl(URL baseString... paththrows MalformedURLException {
         StringBuilder pathBuilder = new StringBuilder();
 
         if (base.getProtocol().equals("jar")) {
             pathBuilder.append(getPath(base));
         } else {
             pathBuilder.append(base.toExternalForm());
         }
 
         for (String entry : path) {
             pathBuilder.append("!");
 
             if (!entry.startsWith("/")) {
                 pathBuilder.append("/");
             }
 
             pathBuilder.append(entry);
         }
 
         return new URL(null, -1, pathBuilder.toString(), );
     }
 
     static class CompoundJarURLConnection extends URLConnection {
 
         private final URL baseJarUrl;
 
         private final String[] path;
 
         private static final Map<StringMap<Stringbyte[]>> cache = new ConcurrentHashMap<StringMap<Stringbyte[]>>(16, 0.75f, 4);
 
         CompoundJarURLConnection(URL urlthrows MalformedURLException {
             super(url);
             String spec = getPath(url);
              = spec.split("\\!\\/");
              = new URL([0]);
         }
 
         @Override
         public void connect() throws IOException {
              = true;
         }
 
         private InputStream openEntryWithCache(String[] pathInputStream currentStreamint currentDepththrows IOException {
             final String localPath = path[currentDepth];
 
             // short-circuit files directly on the filesystem, which JarFile can handle
             if (currentDepth == 1 && path[0].indexOf('!') == -1 && path[0].startsWith("file:")) {
                 // it's a top-level jar, just open with JarFile
                 JarFile jarFile = new JarFile(path[0].substring(5));
                 JarEntry entry = jarFile.getJarEntry(localPath);
                 if (entry != null) {
                     return returnOrRecurse(pathjarFile.getInputStream(entry), currentDepth);
                 }
                 return null;
             }
 
             // build path for cache lookup
             StringBuilder pathToHereBuffer = new StringBuilder();
             for (int i = 0; i < currentDepthi++) {
                 if (i > 0) pathToHereBuffer.append("!/");
                 pathToHereBuffer.append(path[i]);
             }
             String pathToHere = pathToHereBuffer.toString();
 
             // check for already-read cached jar contents
             Map<Stringbyte[]> contents = .get(pathToHere);
             if (contents == null) {
                // not found, cache jar contents
                .put(pathToHerecontents = new ConcurrentHashMap<Stringbyte[]>(16, 0.75f, 2));
                cacheJarFrom(currentStreamcontents);
            }
            // now go to cache to find bytes for this elements
            byte[] bytes = contents.get(localPath);
            if (bytes != null) {
                return returnOrRecurse(pathnew ByteArrayInputStream(bytes), currentDepth);
            }
            return null;
        }
        private void cacheJarFrom(InputStream currentStreamMap<Stringbyte[]> contentsthrows IOException {
            JarInputStream currentJar = new JarInputStream(currentStream);
            for (JarEntry entry = currentJar.getNextJarEntry(); entry != nullentry = currentJar.getNextJarEntry()) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] bytes = new byte[1024];
                int size;
                while ((size = currentJar.read(bytes, 0, 1024)) != -1) {
                    baos.write(bytes, 0, size);
                }
                bytes = baos.toByteArray();
                contents.put(entry.getName(), bytes);
            }
        }
        private InputStream returnOrRecurse(String[] pathInputStream nextStreamint currentDepththrows IOException {
            if (currentDepth + 1 < path.length) {
                // we're not all the way down, open the inner jar and go deeper
                return openEntryWithCache(pathnextStreamcurrentDepth + 1);
            } else {
                // we've got it; return an array reading the bytes
                return nextStream;
            }
        }
        private static void close(Closeable resource) {
            if (resource != null) {
                try {
                    resource.close();
                } catch (IOException ignore) {
                }
            }
        }
        @Override
        public InputStream getInputStream() throws IOException {
            InputStream result;
            InputStream baseInputStream = .openStream();
            if (. > 1) {
                try {
                    result = openEntryWithCache(baseInputStream, 1);
                } catch (IOException ex) {
                    close(baseInputStream);
                    throw ex;
                } catch (RuntimeException ex) {
                    close(baseInputStream);
                    throw ex;
                }
            } else {
                result = baseInputStream;
            }
            if (result == null) {
                throw new FileNotFoundException(.toExternalForm());
            }
            return result;
        }
    }
    @Override
    protected URLConnection openConnection(URL urlthrows IOException {
        return new CompoundJarURLConnection(url);
    }
New to GrepCode? Check out our FAQ X