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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org