Jelajahi Sumber

change: PackageScanner

Mariusz Sieroń 6 tahun lalu
induk
melakukan
731ceb5cb3

+ 8 - 5
assira/src/main/java/net/ranides/assira/collection/query/CQueryBuilder.java

@@ -7,13 +7,12 @@
 
 package net.ranides.assira.collection.query;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
 import java.util.function.Function;
 import java.util.function.Supplier;
 import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
 import net.ranides.assira.functional.CheckedFunction;
 import net.ranides.assira.functional.CheckedSupplier;
 
@@ -114,7 +113,11 @@ public class CQueryBuilder<T> {
     public static <T,P> CQuery<T> fromIterable(P param, Function<? super P, Iterable<T>> source) {
         return fromIterable(() -> source.apply(param));
     }
-    
+
+    public static <T,E extends Exception> CQuery<T> fromSpliterator(CheckedSupplier<Spliterator<T>,E> source) throws E {
+        return fromStream(() -> StreamSupport.stream(source.$get(), false));
+    }
+
     public static <T,E extends Exception> CQuery<T> fromStream(CheckedSupplier<Stream<T>,E> source) throws E {
         return new CQueryAbstract.CQIterable<>(() -> source.$get().iterator());
     }

+ 43 - 40
assira/src/main/java/net/ranides/assira/reflection/util/PackageScanner.java

@@ -8,7 +8,8 @@ package net.ranides.assira.reflection.util;
 
 import net.ranides.assira.collection.iterators.EnumerationUtils;
 import net.ranides.assira.collection.iterators.ForwardSpliterator;
-import net.ranides.assira.collection.iterators.IteratorUtils;
+import net.ranides.assira.collection.query.CQuery;
+import net.ranides.assira.collection.query.CQueryBuilder;
 import net.ranides.assira.generic.ValueUtils;
 import net.ranides.assira.io.ZipReader;
 import net.ranides.assira.io.uri.URIUtils;
@@ -38,14 +39,19 @@ public final class PackageScanner {
     private ClassLoader loader;
 
     private PackageScanner() {
-        /* utility class */
+        // do nothing
     }
 
     public static PackageScanner scanner() {
         return new PackageScanner();
     }
 
-    public PackageScanner root(String root) {
+    public PackageScanner scope(String root) {
+        this.root = StringUtils.replace(root, '.', '/');
+        return this;
+    }
+
+    public PackageScanner directory(String root) {
         this.root = root;
         return this;
     }
@@ -55,15 +61,19 @@ public final class PackageScanner {
         return this;
     }
 
-    public Stream<Class<?>> types() throws IOException {
-        return names().map(toclass(cloader())).filter(Objects::nonNull);
+    public CQuery<Class<?>> types() throws IOException {
+        return names().map(toClass(cloader())).filter(Objects::nonNull);
+    }
+
+    public CQuery<String> names() throws IOException {
+        return files().filter(PackageScanner::isClass).map(PackageScanner::toClassName);
     }
 
-    public Stream<String> names() throws IOException {
+    public CQuery<String> files() throws IOException {
         if(root == null) {
-            return StreamSupport.stream(new PackageSpliterator(), false);
+            return CQueryBuilder.fromSpliterator(() -> new PackageSpliterator());
         } else {
-            return StreamSupport.stream(new PackageSpliterator(root, cloader()), false);
+            return CQueryBuilder.fromSpliterator(() -> new PackageSpliterator(root, cloader()));
         }
     }
 
@@ -72,11 +82,11 @@ public final class PackageScanner {
     }
 
     private static final class PackageSpliterator extends ForwardSpliterator<String> {
-		
+
         private final String nroot;
         private final String croot;
         private final Iterator<String> resources;
-        
+
         private Spliterator<String> current;
 
         public PackageSpliterator() {
@@ -85,19 +95,19 @@ public final class PackageScanner {
             this.resources = Collections.singleton(PackageScanner.class.getProtectionDomain().getCodeSource().getLocation().getPath()+"!").iterator();
             this.current = Collections.<String>emptyList().spliterator();
         }
-		
-		public PackageSpliterator(String root, ClassLoader loader) throws IOException {
-			this.nroot = (root==null)? ":" : (root + ".");
-			this.croot = StringUtils.replace(root, '.', '/');
+
+        public PackageSpliterator(String root, ClassLoader loader) throws IOException {
+            this.nroot = (root==null)? ":" : (root + "/");
+            this.croot = root;
             this.resources = EnumerationUtils.map(loader.getResources(croot), URL::getPath);
             this.current = Collections.<String>emptyList().spliterator();
-		}
+        }
 
-		@Override
-		public boolean tryAdvance(Consumer<? super String> action) {
+        @Override
+        public boolean tryAdvance(Consumer<? super String> action) {
             return current.tryAdvance(action) || tryAdvanceResource(action);
-		}
-        
+        }
+
         private boolean tryAdvanceResource(Consumer<? super String> action) {
             if(!resources.hasNext()) {
                 return false;
@@ -107,7 +117,7 @@ public final class PackageScanner {
             current = file.isDirectory() ? forDirectory(file.toPath()) : forJAR(uri);
             return current.tryAdvance(action);
         }
-        
+
         private Spliterator<String> forJAR(String uri) {
             try {
                 String jar = StringUtils.between(uri, ":", "!");
@@ -119,19 +129,19 @@ public final class PackageScanner {
                 throw ExceptionUtils.rethrow(cause);
             }
         }
-        
+
         private Spliterator<String> forDirectory(Path file) {
             try {
                 return Files
-                    .walk(file)
-                    .filter(PackageScanner::isClass)
-                    .map(s -> nroot + toClassName(file.relativize(s)))
-                    .spliterator();
+                        .walk(file)
+                        .filter(p -> !Files.isDirectory(p))
+                        .map(s ->  StringUtils.replace(nroot + file.relativize(s), '\\','/'))
+                        .spliterator();
             } catch(IOException cause) {
                 throw ExceptionUtils.rethrow(cause);
             }
         }
-        
+
         private final class JARSpliterator extends ForwardSpliterator<String> {
 
             private final JarInputStream istream;
@@ -145,11 +155,8 @@ public final class PackageScanner {
                 try {
                     JarEntry entry;
                     while(null != (entry = istream.getNextJarEntry())) {
-                        String ename = entry.getName();
-                        if( ename.endsWith(".class") && ename.startsWith(croot) ) {
-                            action.accept(toClassName(ename));
-                            return true;
-                        }
+                        action.accept(entry.getName());
+                        return true;
                     }
                     istream.close();
                     return false;
@@ -160,13 +167,13 @@ public final class PackageScanner {
 
         }
 
-	}
+    }
 
-    private static boolean isClass(Path path) {
-        return path.getFileName().toString().endsWith(".class");
+    private static boolean isClass(String path) {
+        return path.endsWith(".class");
     }
     
-    private static Function<String, Class<?>> toclass(ClassLoader loader) {
+    private static Function<String, Class<?>> toClass(ClassLoader loader) {
         return name -> {
             try {
                 return Class.forName(name, false, loader);
@@ -175,11 +182,7 @@ public final class PackageScanner {
             }
         };
     }
-    
-    private static String toClassName(Path path) {
-        return toClassName(path.toString());
-    }
-    
+
     private static String toClassName(String path) {
         String fname = StringUtils.removeSuffix(path, ".class");
         return StringUtils.replace(StringUtils.replace(fname, '/', '.'), '\\', '.');

+ 1 - 1
assira/src/test/java/net/ranides/assira/ContractTesters.java

@@ -37,7 +37,7 @@ public final class ContractTesters {
             try {
                 RUNNER = new TestContractRunner(System.err);
                 
-                PackageScanner.scanner().root("net.ranides.assira").names()
+                PackageScanner.scanner().scope("net.ranides.assira").names()
                     .map(newtester())
                     .filter(o -> o!=null)
                     .forEach(RUNNER::append);

+ 17 - 6
assira/src/test/java/net/ranides/assira/reflection/util/PackageScannerTest.java

@@ -25,9 +25,9 @@ public class PackageScannerTest {
         String ec2 = "net.ranides.assira.reflection.util.PackageScanner";
         String ec3 = "net.ranides.assira.reflection.util.PackageScannerTest";
         
-        assertTrue(PackageScanner.scanner().root(ns1).names().anyMatch(ec1::equals));
-        assertTrue(PackageScanner.scanner().root(ns2).names().anyMatch(ec2::equals));
-        assertTrue(PackageScanner.scanner().root(ns2).names().anyMatch(ec3::equals));
+        assertTrue(PackageScanner.scanner().scope(ns1).names().matchAny(ec1::equals));
+        assertTrue(PackageScanner.scanner().scope(ns2).names().matchAny(ec2::equals));
+        assertTrue(PackageScanner.scanner().scope(ns2).names().matchAny(ec3::equals));
     }
 
     @Test
@@ -39,9 +39,20 @@ public class PackageScannerTest {
         Class<?> ec2 = net.ranides.assira.reflection.util.PackageScanner.class;
         Class<?> ec3 = net.ranides.assira.reflection.util.PackageScannerTest.class;
 
-        assertTrue(PackageScanner.scanner().root(ns1).types().anyMatch(ec1::equals));
-        assertTrue(PackageScanner.scanner().root(ns2).types().anyMatch(ec2::equals));
-        assertTrue(PackageScanner.scanner().root(ns2).types().anyMatch(ec3::equals));
+        assertTrue(PackageScanner.scanner().scope(ns1).types().matchAny(ec1::equals));
+        assertTrue(PackageScanner.scanner().scope(ns2).types().matchAny(ec2::equals));
+        assertTrue(PackageScanner.scanner().scope(ns2).types().matchAny(ec3::equals));
     }
 
+    @Test
+    public void testFileStream() throws IOException {
+        String ns1 = "net/ranides/assira/junit";
+        String ec1 = "net/ranides/assira/junit/LogObserver.class";
+
+        assertTrue(PackageScanner.scanner().directory(ns1).files().matchAny(ec1::equals));
+
+        String ns2 = "reflective";
+        String ec2 = "reflective/constructors-jdk8/4.txt";
+        assertTrue(PackageScanner.scanner().directory(ns2).files().matchAny(ec2::equals));
+    }
 }