/** * Returns the parent of the given file system path. * * @param path a file system path. * @return The parent file system path. * @throws URISyntaxException */ static @Nullable FsPath parent(FsPath path) throws URISyntaxException { FsMountPoint mp = path.getMountPoint(); FsEntryName en = path.getEntryName(); if (en.isRoot()) { if (null == mp) return null; path = mp.getPath(); if (null != path) return parent(path); URI mpu = mp.toUri(); URI pu = mpu.resolve(DOT_DOT_URI); if (mpu.getRawPath().length() <= pu.getRawPath().length()) return null; return new FsPath(pu); } else { URI pu = en.toUri().resolve(DOT_URI); en = new FsEntryName(pu, CANONICALIZE); return new FsPath(mp, en); } } }
@SuppressWarnings("LeakingThisInConstructor") private TFile( final FsMountPoint mountPoint, final TArchiveDetector detector) { super(mountPoint.toHierarchicalUri()); this.file = new File(super.getPath()); this.detector = detector; final FsPath mpp = mountPoint.getPath(); if (null == mpp) { assert !mountPoint.toUri().isOpaque(); this.enclArchive = null; this.enclEntryName = null; this.innerArchive = null; } else { assert mountPoint.toUri().isOpaque(); if (mpp.toUri().isOpaque()) { this.enclArchive = new TFile(mpp.getMountPoint(), detector); this.enclEntryName = mpp.getEntryName(); } else { this.enclArchive = null; this.enclEntryName = null; } this.innerArchive = this; this.controller = getController(mountPoint); } assert invariants(); }
final FsPath mpp = mp.getPath(); final FsEntryName en;
@Test public void testSpaces() { for (final String[] params : new String[][] { { "foo:bar:baz:/%20!/%20/%20!/%20/%20", " ", " / ", " / ", }, { "foo:bar:baz:/%20a%20!/%20b%20!/%20c%20", " a ", " b ", " c ", }, }) { FsPath path = FsPath.create(URI.create(params[0])); for (int i = params.length; 0 < --i; ) { assertThat(path.getEntryName().getPath(), equalTo(params[i])); path = path.getMountPoint().getPath(); } } }
@Test public void testResolve() { for (final String[] params : new String[][] { { "foo:bar:/baz?plonk!/", "", "baz", "foo:bar:/baz?plonk!/" }, { "foo:bar:/bäz?bööm!/", "bäng?plönk", "bäz/bäng?plönk", "foo:bar:/bäz?bööm!/bäng?plönk" }, { "foo:bar:/baz!/", "bang?boom", "baz/bang?boom", "foo:bar:/baz!/bang?boom" }, { "foo:bar:/baz!/", "bang", "baz/bang", "foo:bar:/baz!/bang" }, { "foo:bar:/baz!/", "", "baz", "foo:bar:/baz!/" }, { "foo:bar:/baz?plonk!/", "bang?boom", "baz/bang?boom", "foo:bar:/baz?plonk!/bang?boom" }, { "foo:bar:/baz?plonk!/", "bang", "baz/bang", "foo:bar:/baz?plonk!/bang" }, { "foo:/bar/", "baz?bang", null, "foo:/bar/baz?bang" }, { "foo:/bar/", "baz", null, "foo:/bar/baz" }, { "foo:/bar/", "", null, "foo:/bar/" }, { "foo:/bar/", "baz", null, "foo:/bar/baz" }, }) { final FsMountPoint mountPoint = FsMountPoint.create(URI.create(params[0])); final FsEntryName entryName = FsEntryName.create(URI.create(params[1])); final FsEntryName parentEntryName = null == params[2] ? null : FsEntryName.create(URI.create(params[2])); final FsPath path = FsPath.create(URI.create(params[3])); if (null != parentEntryName) assertThat(mountPoint.getPath().resolve(entryName).getEntryName(), equalTo(parentEntryName)); assertThat(mountPoint.resolve(entryName), equalTo(path)); assertThat(mountPoint.resolve(entryName).toUri().isAbsolute(), is(true)); } }
@Test @SuppressWarnings("ResultOfObjectAllocationIgnored") public void testConstructorWithMountPoint() { for (final String[] params : new String[][] { { "foo:/bar/" }, }) { final FsMountPoint mountPoint = FsMountPoint.create(URI.create(params[0])); final FsModel model = newModel(mountPoint, null); assertThat(model.getMountPoint(), sameInstance(mountPoint)); assertThat(model.getMountPoint().getPath(), nullValue()); assertThat(model.getParent(), nullValue()); assertThat(model.isMounted(), is(false)); } }
final FsMountPoint mountPoint = FsMountPoint.create(uri); assertThat(mountPoint.toUri(), sameInstance(uri)); assertThat(mountPoint.getPath(), nullValue()); assertThat(mountPoint.toString(), equalTo(mountPoint.toUri().toString())); assertThat(mountPoint, equalTo(FsMountPoint.create(mountPoint.toUri()))); assertThat(mountPoint.getPath(), equalTo(path)); assertThat(mountPoint.toString(), equalTo(mountPoint.toUri().toString())); assertThat(FsMountPoint.create(mountPoint.toUri()), equalTo(mountPoint)); assertThat(FsMountPoint.create(URI.create(mountPoint.toUri().getScheme() + ":" + mountPoint.getPath() + "!/")), equalTo(mountPoint)); assertThat(FsMountPoint.create(mountPoint.getScheme(), mountPoint.getPath()), equalTo(mountPoint)); assertThat(FsMountPoint.create(mountPoint.toUri()), equalTo(mountPoint)); assertThat(FsMountPoint.create(mountPoint.toUri()).hashCode(), equalTo(mountPoint.hashCode()));
assertThat(model.getMountPoint().getPath().resolve(entryName).getEntryName(), equalTo(parentEntryName)); assertThat(model.getMountPoint().resolve(entryName), equalTo(path)); assertThat(model.isMounted(), is(false));
@Override public FsEntry getEntry(final FsEntryName name) throws IOException { try { return delegate.getEntry(name); } catch (final ControlFlowException ex) { if (!name.isRoot() || null == findKeyException(ex)) throw ex; Entry entry = getParent().getEntry( getModel() .getMountPoint() .getPath() .resolve(name) .getEntryName()); // We're not holding any locks, so it's possible that someone else // has concurrently modified the parent file system. if (null == entry) return null; // The entry is inaccessible for some reason. // This may be because the cipher key is not available. // Now mask the entry as a special file. while (entry instanceof FsCovariantEntry<?>) entry = ((FsCovariantEntry<?>) entry).getEntry(); final FsCovariantEntry<FsArchiveEntry> special = new FsCovariantEntry<FsArchiveEntry>(ROOT_PATH); special.put(SPECIAL, driver.newEntry(ROOT_PATH, SPECIAL, entry)); return special; } }