Search in sources :

Example 1 with ZipIterator

use of com.laytonsmith.PureUtilities.ZipIterator in project CommandHelper by EngineHub.

the class ClassDiscovery method discover.

/**
 * Does the class discovery for this particular URL. This should only be called by doDiscovery. Other internal
 * methods should call doDiscovery, which handles looking through the dirtyURLs.
 */
private synchronized void discover(URL rootLocation) {
    long start = System.currentTimeMillis();
    if (debug) {
        StreamUtils.GetSystemOut().println("Beginning discovery of " + rootLocation);
    }
    try {
        // If the ClassDiscoveryCache is set, just use this.
        if (classDiscoveryCache != null) {
            ClassDiscoveryURLCache cduc = classDiscoveryCache.getURLCache(rootLocation);
            preCaches.put(rootLocation, cduc);
        }
        String url;
        try {
            url = URLDecoder.decode(rootLocation.toString(), "UTF-8");
        } catch (UnsupportedEncodingException ex) {
            // apparently this should never happen, but we have to catch it anyway
            url = null;
        }
        if (url == null) {
            url = GetClassContainer(ClassDiscovery.class).toString();
        }
        final File rootLocationFile;
        if (!classCache.containsKey(rootLocation)) {
            classCache.put(rootLocation, Collections.synchronizedSet(new HashSet<>()));
        } else {
            classCache.get(rootLocation).clear();
        }
        final Set<ClassMirror<?>> mirrors = classCache.get(rootLocation);
        if (preCaches.containsKey(rootLocation)) {
            if (debug) {
                StreamUtils.GetSystemOut().println("Precache already contains this URL, so using it");
            }
            // No need, already got a cache for this url
            mirrors.addAll(preCaches.get(rootLocation).getClasses());
            return;
        }
        if (debug) {
            StreamUtils.GetSystemOut().println("Precache does not contain data for this URL, so scanning now.");
        }
        url = url.replaceFirst("^jar:", "");
        if (url.endsWith("!/")) {
            url = StringUtils.replaceLast(url, "!/", "");
        }
        if (url.startsWith("file:") && !url.endsWith(".jar")) {
            final AtomicInteger id = new AtomicInteger(0);
            // ExecutorService service = Executors.newFixedThreadPool(10, new ThreadFactory() {
            // @Override
            // public Thread newThread(Runnable r) {
            // return new Thread(r, "ClassDiscovery-Async-" + id.incrementAndGet());
            // }
            // });
            // Remove file: from the front
            String root = url.substring(5);
            rootLocationFile = new File(root);
            List<File> fileList = new ArrayList<>();
            descend(new File(root), fileList);
            // to all of them. We have to first remove the "front" part
            for (File f : fileList) {
                String file = f.toString();
                if (!file.matches(".*\\$(?:\\d)*\\.class") && file.endsWith(".class")) {
                    InputStream stream = null;
                    try {
                        stream = FileUtil.readAsStream(new File(rootLocationFile, f.getAbsolutePath().replaceFirst(Pattern.quote(new File(root).getAbsolutePath() + File.separator), "")));
                        ClassReader reader = new ClassReader(stream);
                        ClassMirrorVisitor mirrorVisitor = new ClassMirrorVisitor();
                        reader.accept(mirrorVisitor, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG);
                        mirrors.add(mirrorVisitor.getMirror(new URL(url)));
                    } catch (IOException ex) {
                        Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
                    } finally {
                        if (stream != null) {
                            try {
                                stream.close();
                            } catch (IOException ex) {
                                Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }
            }
        // service.shutdown();
        // try {
        // //Doesn't look like 0 is an option, so we'll just wait a day.
        // service.awaitTermination(1, TimeUnit.DAYS);
        // } catch (InterruptedException ex) {
        // Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
        // }
        } else if (url.startsWith("file:") && url.endsWith(".jar")) {
            // We are running from a jar
            url = url.replaceFirst("file:", "");
            rootLocationFile = new File(url);
            ZipIterator zi = new ZipIterator(rootLocationFile);
            try {
                zi.iterate(new ZipIterator.ZipIteratorCallback() {

                    @Override
                    public void handle(String filename, InputStream in) {
                        if (!filename.matches(".*\\$(?:\\d)*\\.class") && filename.endsWith(".class")) {
                            try {
                                ClassReader reader = new ClassReader(in);
                                ClassMirrorVisitor mirrorVisitor = new ClassMirrorVisitor();
                                reader.accept(mirrorVisitor, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG);
                                mirrors.add(mirrorVisitor.getMirror(rootLocationFile.toURI().toURL()));
                            } catch (IOException ex) {
                                Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }, progressIterator);
            } catch (IOException ex) {
                Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            throw new RuntimeException("Unknown url type: " + rootLocation);
        }
    } catch (RuntimeException e) {
        e.printStackTrace(System.err);
    } finally {
        if (debug) {
            StreamUtils.GetSystemOut().println("Scans finished for " + rootLocation + ", taking " + (System.currentTimeMillis() - start) + " ms.");
        }
    }
}
Also used : ZipIterator(com.laytonsmith.PureUtilities.ZipIterator) InputStream(java.io.InputStream) ArrayList(java.util.ArrayList) UnsupportedEncodingException(java.io.UnsupportedEncodingException) ClassMirrorVisitor(com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.ClassMirrorVisitor) IOException(java.io.IOException) ClassMirror(com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.ClassMirror) URL(java.net.URL) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ClassReader(org.objectweb.asm.ClassReader) File(java.io.File) HashSet(java.util.HashSet)

Aggregations

ClassMirror (com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.ClassMirror)1 ClassMirrorVisitor (com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.ClassMirrorVisitor)1 ZipIterator (com.laytonsmith.PureUtilities.ZipIterator)1 File (java.io.File)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 URL (java.net.URL)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 ClassReader (org.objectweb.asm.ClassReader)1