package org.apache.taverna.robundle.fs; /* * 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. */ import java.io.IOException; import java.net.URI; import java.nio.file.ClosedFileSystemException; import java.nio.file.FileStore; import java.nio.file.FileSystem; import java.nio.file.Path; import java.nio.file.PathMatcher; import java.nio.file.Paths; import java.nio.file.WatchService; import java.nio.file.attribute.UserPrincipalLookupService; import java.util.Collections; import java.util.Iterator; import java.util.Set; public class BundleFileSystem extends FileSystem { protected final URI baseURI; private FileSystem origFS; private final String separator; private final Path source; protected BundleFileSystem(FileSystem origFS, URI baseURI) { if (origFS == null || baseURI == null) { throw new NullPointerException(); } this.origFS = origFS; this.baseURI = baseURI; this.separator = origFS.getSeparator(); this.source = findSource(); } @Override public void close() throws IOException { if (origFS == null) { return; } origFS.close(); // De-reference the original ZIP file system so it can be // garbage collected origFS = null; } protected Path findSource() { Path zipRoot = getRootDirectory().getZipPath(); URI uri = zipRoot.toUri(); String schemeSpecific; if (provider().getJarDoubleEscaping()) { schemeSpecific = uri.getSchemeSpecificPart(); } else { // http://dev.mygrid.org.uk/issues/browse/T3-954 schemeSpecific = uri.getRawSchemeSpecificPart(); } if (!schemeSpecific.endsWith("!/")) { // sanity check throw new IllegalStateException("Can't parse JAR URI: " + uri); } URI zip = URI.create(schemeSpecific.substring(0, schemeSpecific.length() - 2)); return Paths.get(zip); // Look up our path } public URI getBaseURI() { return baseURI; } protected BundleFileStore getFileStore() { // We assume there's only one file store, as is true for ZipProvider return new BundleFileStore(this, getOrigFS().getFileStores().iterator() .next()); } @Override public Iterable<FileStore> getFileStores() { return Collections.<FileStore> singleton(getFileStore()); } /** * Thread-safe ClosedFileSystemException test * * @return */ protected FileSystem getOrigFS() { FileSystem orig = origFS; if (orig == null || !orig.isOpen()) { throw new ClosedFileSystemException(); } return orig; } @Override public Path getPath(String first, String... more) { Path zipPath = getOrigFS().getPath(first, more); return wrap(zipPath); } @Override public PathMatcher getPathMatcher(String syntaxAndPattern) { final PathMatcher zipMatcher = getOrigFS().getPathMatcher( syntaxAndPattern); return new PathMatcher() { @Override public boolean matches(Path path) { return zipMatcher.matches(unwrap(path)); } }; } @Override public Iterable<Path> getRootDirectories() { return Collections.<Path> singleton(getRootDirectory()); } public BundlePath getRootDirectory() { return wrap(getOrigFS().getRootDirectories().iterator().next()); } @Override public String getSeparator() { return separator; } public Path getSource() { return source; } @Override public UserPrincipalLookupService getUserPrincipalLookupService() { throw new UnsupportedOperationException(); } @Override public boolean isOpen() { if (origFS == null) { return false; } return origFS.isOpen(); } @Override public boolean isReadOnly() { return getOrigFS().isReadOnly(); } @Override public WatchService newWatchService() throws IOException { throw new UnsupportedOperationException(); } @Override public BundleFileSystemProvider provider() { return BundleFileSystemProvider.getInstance(); } @Override public Set<String> supportedFileAttributeViews() { if (origFS == null) { throw new ClosedFileSystemException(); } return origFS.supportedFileAttributeViews(); } protected Path unwrap(Path bundlePath) { if (!(bundlePath instanceof BundlePath)) { // assume it's already unwrapped for some reason (for instance being // null) return bundlePath; } return ((BundlePath) bundlePath).getZipPath(); } protected BundlePath wrap(Path zipPath) { if (zipPath == null) { return null; } if (zipPath instanceof BundlePath) { throw new IllegalArgumentException("Did not expect BundlePath: " + zipPath); } return new BundlePath(this, zipPath); } protected Iterator<Path> wrapIterator(final Iterator<Path> iterator) { return new Iterator<Path>() { @Override public boolean hasNext() { return iterator.hasNext(); } @Override public Path next() { return wrap(iterator.next()); } @Override public void remove() { iterator.remove(); } }; } }