You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by jb...@apache.org on 2015/03/17 06:46:48 UTC

svn commit: r1667176 - in /tomcat/sandbox/niofs: src/META-INF/ src/META-INF/services/ src/META-INF/services/java.nio.file.spi.FileSystemProvider src/niofs/ArchiveFileSystemProvider.java tst/niofs/ClassLoaderTest.java

Author: jboynes
Date: Tue Mar 17 05:46:48 2015
New Revision: 1667176

URL: http://svn.apache.org/r1667176
Log:
NIOFS URI support and tests with URLClassLoader

Added:
    tomcat/sandbox/niofs/src/META-INF/
    tomcat/sandbox/niofs/src/META-INF/services/
    tomcat/sandbox/niofs/src/META-INF/services/java.nio.file.spi.FileSystemProvider
    tomcat/sandbox/niofs/tst/niofs/ClassLoaderTest.java   (with props)
Modified:
    tomcat/sandbox/niofs/src/niofs/ArchiveFileSystemProvider.java

Added: tomcat/sandbox/niofs/src/META-INF/services/java.nio.file.spi.FileSystemProvider
URL: http://svn.apache.org/viewvc/tomcat/sandbox/niofs/src/META-INF/services/java.nio.file.spi.FileSystemProvider?rev=1667176&view=auto
==============================================================================
--- tomcat/sandbox/niofs/src/META-INF/services/java.nio.file.spi.FileSystemProvider (added)
+++ tomcat/sandbox/niofs/src/META-INF/services/java.nio.file.spi.FileSystemProvider Tue Mar 17 05:46:48 2015
@@ -0,0 +1,17 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+niofs.ArchiveFileSystemProvider

Modified: tomcat/sandbox/niofs/src/niofs/ArchiveFileSystemProvider.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/niofs/src/niofs/ArchiveFileSystemProvider.java?rev=1667176&r1=1667175&r2=1667176&view=diff
==============================================================================
--- tomcat/sandbox/niofs/src/niofs/ArchiveFileSystemProvider.java (original)
+++ tomcat/sandbox/niofs/src/niofs/ArchiveFileSystemProvider.java Tue Mar 17 05:46:48 2015
@@ -21,6 +21,7 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.nio.ByteBuffer;
 import java.nio.channels.NonWritableChannelException;
 import java.nio.channels.SeekableByteChannel;
@@ -29,6 +30,7 @@ import java.nio.file.CopyOption;
 import java.nio.file.DirectoryStream;
 import java.nio.file.FileStore;
 import java.nio.file.FileSystem;
+import java.nio.file.FileSystemNotFoundException;
 import java.nio.file.Files;
 import java.nio.file.LinkOption;
 import java.nio.file.NoSuchFileException;
@@ -36,6 +38,7 @@ import java.nio.file.NotDirectoryExcepti
 import java.nio.file.OpenOption;
 import java.nio.file.Path;
 import java.nio.file.PathMatcher;
+import java.nio.file.Paths;
 import java.nio.file.ProviderMismatchException;
 import java.nio.file.ReadOnlyFileSystemException;
 import java.nio.file.StandardOpenOption;
@@ -55,37 +58,61 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
+import static java.net.URLEncoder.encode;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 /**
  * A provider for read-only filesystems based on an underlying archive file in ZIP format.
  */
 public class ArchiveFileSystemProvider extends FileSystemProvider {
+    private static final String UTF8 = UTF_8.toString();
+
+    private final Map<String, ArchiveFileSystem> fileSystems = new ConcurrentHashMap<>();
 
     @Override
     public String getScheme() {
         return "archive";
     }
 
-    // TODO: We will need to support URIs in order to support converting paths to URLs.
     @Override
-    public FileSystem newFileSystem(URI uri, Map<String, ?> env) throws IOException {
-        throw new UnsupportedOperationException();
+    public ArchiveFileSystem newFileSystem(URI uri, Map<String, ?> env) throws IOException {
+        String name = uri.getAuthority();
+        ArchiveFileSystem fileSystem = fileSystems.get(name);
+        if (fileSystem == null) {
+            fileSystem = newFileSystem(Paths.get(URI.create(name)), env);
+            fileSystems.put(name, fileSystem);
+        }
+        return fileSystem;
     }
 
     @Override
-    public FileSystem getFileSystem(URI uri) {
-        throw new UnsupportedOperationException();
+    public ArchiveFileSystem getFileSystem(URI uri) {
+        ArchiveFileSystem fileSystem = fileSystems.get(uri.getAuthority());
+        if (fileSystem == null) {
+            throw new FileSystemNotFoundException();
+        }
+        return fileSystem;
     }
 
     @Override
     public Path getPath(URI uri) {
-        throw new UnsupportedOperationException();
+        if (!getScheme().equals(uri.getScheme())) {
+            throw new ProviderMismatchException(uri.toString());
+        }
+        String name = uri.getAuthority();
+        FileSystem fileSystem = fileSystems.get(name);
+        if (fileSystem == null) {
+            throw new FileSystemNotFoundException(name);
+        }
+        return fileSystem.getPath(uri.getPath());
     }
 
     @Override
-    public FileSystem newFileSystem(Path path, Map<String, ?> env) throws IOException {
+    public ArchiveFileSystem newFileSystem(Path path, Map<String, ?> env) throws IOException {
         return new ArchiveFileSystem(path, env);
     }
 
@@ -233,10 +260,16 @@ public class ArchiveFileSystemProvider e
      *
      */
     class ArchiveFileSystem extends FileSystem {
-        private volatile boolean open = true;
+        private final URI baseURI;
         private final Map<Path, DirectoryNode> directory;
+        private volatile boolean open = true;
 
         public ArchiveFileSystem(Path path, Map<String, ?> env) throws IOException {
+            try {
+                baseURI = new URI(getScheme() + "://" + encode(path.toUri().toString(), UTF8));
+            } catch (URISyntaxException e) {
+                throw new IllegalArgumentException(e);
+            }
             directory = createIndex(path);
         }
 
@@ -365,6 +398,9 @@ public class ArchiveFileSystemProvider e
                 @Override
                 public int read(ByteBuffer dst) throws IOException {
                     int size = Math.min(dst.remaining(), node.data.length - position);
+                    if (size == 0) {
+                        return -1;
+                    }
                     dst.put(node.data, position, size);
                     position += size;
                     return size;
@@ -454,7 +490,7 @@ public class ArchiveFileSystemProvider e
                 } else {
                     StringBuilder builder = new StringBuilder(first);
                     for (String s : more) {
-                        builder.append(s);
+                        builder.append(getSeparator()).append(s);
                     }
                     path = builder.toString();
                 }
@@ -564,7 +600,7 @@ public class ArchiveFileSystemProvider e
 
             @Override
             public URI toUri() {
-                throw new UnsupportedOperationException();
+                return baseURI.resolve(path);
             }
 
             @Override

Added: tomcat/sandbox/niofs/tst/niofs/ClassLoaderTest.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/niofs/tst/niofs/ClassLoaderTest.java?rev=1667176&view=auto
==============================================================================
--- tomcat/sandbox/niofs/tst/niofs/ClassLoaderTest.java (added)
+++ tomcat/sandbox/niofs/tst/niofs/ClassLoaderTest.java Tue Mar 17 05:46:48 2015
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package niofs;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.net.URLStreamHandlerFactory;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static java.net.URLEncoder.encode;
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ */
+public class ClassLoaderTest {
+    @BeforeClass
+    public static void initURLHandler() {
+        // Need this to even construct URLs.
+        URLStreamHandlerFactory factory = protocol -> {
+            switch (protocol) {
+                case "archive":
+                    return new URLStreamHandler() {
+                        @Override
+                        protected URLConnection openConnection(URL u) throws IOException {
+                            URI archive = URI.create("archive://" + u.getHost());
+                            FileSystem fileSystem = FileSystems.getFileSystem(archive);
+                            Path path = fileSystem.getPath(u.getPath());
+                            return new URLConnection(u) {
+                                @Override
+                                public void connect() throws IOException {
+                                }
+
+                                @Override
+                                public InputStream getInputStream() throws IOException {
+                                    return Files.newInputStream(path);
+                                }
+                            };
+                        }
+                    };
+                default:
+                    return null;
+            }
+        };
+        URL.setURLStreamHandlerFactory(factory);
+    }
+
+    private ClassLoader classLoader;
+
+    @Before
+    public void initClassLoader() throws IOException {
+        ArchiveFileSystemProvider provider = new ArchiveFileSystemProvider();
+        Path war = FileSystems.getDefault().getPath("greenhouse-1.0.0.BUILD-SNAPSHOT.war");
+        URI warURI = URI.create(provider.getScheme() + "://" + encode(war.toUri().toString(), "UTF8"));
+        FileSystem fileSystem = FileSystems.newFileSystem(warURI, Collections.emptyMap());
+        URL[] urls = Files.list(fileSystem.getPath(fileSystem.getSeparator() + "WEB-INF", "lib"))
+                .filter(path -> path.getFileName().toString().matches(".*\\.(zip|jar)$"))
+                .map(path -> {
+                    try {
+                        return URI.create(provider.getScheme() + "://" + encode(path.toUri().toString(), "UTF8"));
+                    } catch (UnsupportedEncodingException e) {
+                        throw new IllegalStateException(e);
+                    }
+                })
+                .peek(uri -> {
+                    try {
+                        FileSystems.newFileSystem(uri, Collections.emptyMap());
+                    } catch (IOException e) {
+                        throw new IllegalStateException(e);
+                    }
+                })
+                .map(uri -> {
+                    try {
+                        return new URL(uri.toString() + '/');
+                    } catch (IOException e) {
+                        throw new IllegalStateException(e);
+                    }
+                })
+                .toArray(URL[]::new);
+        classLoader = new URLClassLoader(urls);
+    }
+
+    @Test
+    public void testLoadable() throws ClassNotFoundException {
+        Class<?> inject = classLoader.loadClass("javax.inject.Inject");
+        assertEquals("Inject", inject.getSimpleName());
+    }
+
+    @Test
+    public void loadAllResources() throws IOException {
+        // Read all the paths in we are meant to open;
+        Set<String> paths;
+        try (BufferedReader reader = new BufferedReader(new FileReader("urls.log"))) {
+            paths = reader.lines()
+                    .map(line -> line.split(" ")[1])
+                    .collect(Collectors.toSet());
+        }
+        long time = -System.nanoTime();
+        Set<?> urls = paths.stream()
+                .map(classLoader::getResource)
+                .collect(Collectors.toSet());
+        time += System.nanoTime();
+        System.out.printf("Found %d resources in %dms\n", urls.size(), time / 1000000);
+        assertEquals(paths.size(), urls.size());
+    }
+}

Propchange: tomcat/sandbox/niofs/tst/niofs/ClassLoaderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native



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