diff options
23 files changed, 644 insertions, 71 deletions
diff --git a/jack/src/com/android/jack/backend/jayce/JayceFileImporter.java b/jack/src/com/android/jack/backend/jayce/JayceFileImporter.java index 5683d55..4c14ae6 100644 --- a/jack/src/com/android/jack/backend/jayce/JayceFileImporter.java +++ b/jack/src/com/android/jack/backend/jayce/JayceFileImporter.java @@ -40,9 +40,7 @@ import com.android.sched.util.codec.VariableName; import com.android.sched.util.config.HasKeyId; import com.android.sched.util.config.ThreadConfig; import com.android.sched.util.config.id.PropertyId; -import com.android.sched.util.location.FileLocation; import com.android.sched.util.location.Location; -import com.android.sched.util.location.ZipLocation; import com.android.sched.util.log.Event; import com.android.sched.util.log.LoggerFactory; import com.android.sched.util.log.Tracer; @@ -127,7 +125,7 @@ public class JayceFileImporter { Iterator<InputVFile> jayceFileIt = jackLibrary.iterator(FileType.JAYCE); while (jayceFileIt.hasNext()) { InputVFile jayceFile = jayceFileIt.next(); - String name = getNameFromInputVFile(jackLibrary, jayceFile, FileType.JAYCE); + String name = jayceFile.getPathFromRoot().getPathAsString('/'); try { addImportedTypes(session, name, jackLibrary); } catch (JLookupException e) { @@ -144,7 +142,7 @@ public class JayceFileImporter { Iterator<InputVFile> rscFileIt = jackLibrary.iterator(FileType.RSC); while (rscFileIt.hasNext()) { InputVFile rscFile = rscFileIt.next(); - String name = getNameFromInputVFile(jackLibrary, rscFile, FileType.RSC); + String name = rscFile.getPathFromRoot().getPathAsString('/'); try { addImportedResource(rscFile, session, name); } catch (ResourceImportConflictException e) { @@ -158,28 +156,6 @@ public class JayceFileImporter { } } - // TODO(jack-team): remove this hack - @Nonnull - private String getNameFromInputVFile(@Nonnull InputJackLibrary jackLibrary, - @Nonnull InputVFile jayceFile, @Nonnull FileType fileType) { - Location loc = jayceFile.getLocation(); - String name; - if (loc instanceof ZipLocation) { - name = ((ZipLocation) jayceFile.getLocation()).getEntryName(); - if (jackLibrary.getMajorVersion() != 0) { - name = name.substring( - fileType.buildDirVPath(VPath.ROOT).split().iterator().next().length() + 1); - } - } else { - name = ((FileLocation) jayceFile.getLocation()).getPath(); - if (jackLibrary.getMajorVersion() != 0) { - String prefix = fileType.buildDirVPath(VPath.ROOT).split().iterator().next() + '/'; - name = name.substring(name.lastIndexOf(prefix) + prefix.length()); - } - } - return name; - } - private void addImportedTypes(@Nonnull JSession session, @Nonnull String path, @Nonnull InputLibrary intendedInputLibrary) throws TypeImportConflictException, JTypeLookupException { diff --git a/jack/src/com/android/jack/shrob/obfuscation/resource/RefinedVFile.java b/jack/src/com/android/jack/shrob/obfuscation/resource/RefinedVFile.java index deedb67..b8d81b5 100644 --- a/jack/src/com/android/jack/shrob/obfuscation/resource/RefinedVFile.java +++ b/jack/src/com/android/jack/shrob/obfuscation/resource/RefinedVFile.java @@ -21,6 +21,7 @@ import com.android.sched.util.file.WrongPermissionException; import com.android.sched.util.location.Location; import com.android.sched.vfs.AbstractVElement; import com.android.sched.vfs.InputVFile; +import com.android.sched.vfs.VPath; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -277,4 +278,10 @@ public class RefinedVFile extends AbstractVElement implements InputVFile { public void delete() throws CannotDeleteFileException { file.delete(); } + + @Override + @Nonnull + public VPath getPathFromRoot() { + return file.getPathFromRoot(); + } } diff --git a/sched/src/com/android/sched/vfs/BaseVFS.java b/sched/src/com/android/sched/vfs/BaseVFS.java index eb42576..354cc98 100644 --- a/sched/src/com/android/sched/vfs/BaseVFS.java +++ b/sched/src/com/android/sched/vfs/BaseVFS.java @@ -79,6 +79,12 @@ abstract class BaseVFS<DIR extends BaseVDir, FILE extends BaseVFile> implements abstract boolean isEmpty(@Nonnull DIR dir); + @Nonnull + abstract VPath getPathFromDir(@Nonnull DIR parent, @Nonnull FILE file); + + @Nonnull + abstract VPath getPathFromRoot(@Nonnull FILE file); + // // Location related // diff --git a/sched/src/com/android/sched/vfs/BaseVFile.java b/sched/src/com/android/sched/vfs/BaseVFile.java index 3520eb6..c231341 100644 --- a/sched/src/com/android/sched/vfs/BaseVFile.java +++ b/sched/src/com/android/sched/vfs/BaseVFile.java @@ -75,4 +75,10 @@ abstract class BaseVFile extends BaseVElement implements VFile { public void delete() throws CannotDeleteFileException { vfs.delete(this); } + + @Override + @Nonnull + public VPath getPathFromRoot() { + return vfs.getPathFromRoot(this); + } } diff --git a/sched/src/com/android/sched/vfs/CachedDirectFS.java b/sched/src/com/android/sched/vfs/CachedDirectFS.java index 83512be..ce1f605 100644 --- a/sched/src/com/android/sched/vfs/CachedDirectFS.java +++ b/sched/src/com/android/sched/vfs/CachedDirectFS.java @@ -111,6 +111,11 @@ public class CachedDirectFS extends BaseVFS<CachedParentVDir, CachedParentVFile> public Collection<? extends BaseVElement> list() { return vfs.list(this); } + + @CheckForNull + public CachedParentVDir getParent() { + return parent; + } } static class CachedParentVFile extends ParentVFile { @@ -405,4 +410,29 @@ public class CachedDirectFS extends BaseVFS<CachedParentVDir, CachedParentVFile> private File getNativeFile(@Nonnull VPath path, @Nonnull String name) { return new File(new File(dir.getFile(), path.getPathAsString(File.separatorChar)), name); } + + @Override + @Nonnull + VPath getPathFromDir(@Nonnull CachedParentVDir parent, @Nonnull CachedParentVFile file) { + StringBuffer path = getPathFromDirInternal(parent, (CachedParentVDir) file.getParent()) + .append(file.getName()); + return new VPath(path.toString(), '/'); + } + + @Nonnull + private static StringBuffer getPathFromDirInternal(@Nonnull CachedParentVDir baseDir, + @Nonnull CachedParentVDir currentDir) { + if (baseDir == currentDir) { + return new StringBuffer(); + } + CachedParentVDir currentParent = currentDir.getParent(); + assert currentParent != null; + return getPathFromDirInternal(baseDir, currentParent).append(currentDir.getName()).append('/'); + } + + @Override + @Nonnull + public VPath getPathFromRoot(@Nonnull CachedParentVFile file) { + return getPathFromDir(root, file); + } } diff --git a/sched/src/com/android/sched/vfs/CaseInsensitiveFS.java b/sched/src/com/android/sched/vfs/CaseInsensitiveFS.java index 1807333..78ce7b2 100644 --- a/sched/src/com/android/sched/vfs/CaseInsensitiveFS.java +++ b/sched/src/com/android/sched/vfs/CaseInsensitiveFS.java @@ -118,6 +118,43 @@ public class CaseInsensitiveFS extends BaseVFS<CaseInsensitiveVDir, CaseInsensit return VPath.ROOT; } } + + @Override + @Nonnull + public BaseVFile getVFile(@Nonnull String name) throws NoSuchFileException, + NotFileException { + return vfs.getVFile(this, name); + } + + @Override + @Nonnull + public BaseVDir getVDir(@Nonnull String name) throws NotDirectoryException, + NoSuchFileException { + return vfs.getVDir(this, name); + } + + @Override + @Nonnull + public BaseVFile createVFile(@Nonnull String name) throws CannotCreateFileException { + return vfs.createVFile(this, name); + } + + @Override + @Nonnull + public BaseVDir createVDir(@Nonnull String name) throws CannotCreateFileException { + return vfs.createVDir(this, name); + } + + @Override + @Nonnull + public Collection<? extends BaseVElement> list() { + return vfs.list(this); + } + + @CheckForNull + public VDir getParent() { + return parent; + } } static class CaseInsensitiveVFile extends ParentVFile { @@ -143,8 +180,10 @@ public class CaseInsensitiveFS extends BaseVFS<CaseInsensitiveVDir, CaseInsensit @Override public void delete() throws CannotDeleteFileException { - super.delete(); - // we need to remove the VFile from the parent dir's map + vfs.delete(this); + } + + public void deleteFromCache() { ((InMemoryVDir) parent).internalDelete(name); } } @@ -340,35 +379,74 @@ public class CaseInsensitiveFS extends BaseVFS<CaseInsensitiveVDir, CaseInsensit @Override @Nonnull - CaseInsensitiveVDir getVDir(@Nonnull CaseInsensitiveVDir parent, @Nonnull String name) { - throw new UnsupportedOperationException(); + CaseInsensitiveVDir getVDir(@Nonnull CaseInsensitiveVDir parent, @Nonnull String name) + throws NotDirectoryException, NoSuchFileException { + BaseVElement element = parent.getFromCache(name); + if (element != null) { + if (element.isVDir()) { + return (CaseInsensitiveVDir) element; + } else { + throw new NotDirectoryException(getVDirLocation(parent, name)); + } + } else { + throw new NoSuchFileException(getVDirLocation(parent, name)); + } } @Override @Nonnull - CaseInsensitiveVFile getVFile(@Nonnull CaseInsensitiveVDir parent, @Nonnull String name) { - throw new UnsupportedOperationException(); + CaseInsensitiveVFile getVFile(@Nonnull CaseInsensitiveVDir parent, @Nonnull String name) + throws NotFileException, NoSuchFileException { + BaseVElement element = parent.getFromCache(name); + if (element != null) { + if (!element.isVDir()) { + return (CaseInsensitiveVFile) element; + } else { + throw new NotFileException(getVFileLocation(parent, name)); + } + } else { + throw new NoSuchFileException(getVFileLocation(parent, name)); + } } @Override @Nonnull - CaseInsensitiveVDir createVDir(@Nonnull CaseInsensitiveVDir parent, @Nonnull String name) { + synchronized CaseInsensitiveVDir createVDir(@Nonnull CaseInsensitiveVDir parent, + @Nonnull String name) throws CannotCreateFileException { assert !isClosed(); - return new CaseInsensitiveVDir(this, parent, name); + try { + return getVDir(parent, name); + + } catch (NoSuchFileException e) { + CaseInsensitiveVDir dir = new CaseInsensitiveVDir(this, parent, name); + parent.putInCache(name, dir); + return dir; + } catch (NotDirectoryException e) { + throw new CannotCreateFileException(getVDirLocation(parent, name)); + } } @Override @Nonnull - CaseInsensitiveVFile createVFile(@Nonnull CaseInsensitiveVDir parent, @Nonnull String name) - throws CannotCreateFileException { + synchronized CaseInsensitiveVFile createVFile(@Nonnull CaseInsensitiveVDir parent, + @Nonnull String name) throws CannotCreateFileException { assert !isClosed(); - CaseInsensitiveVFile original = new CaseInsensitiveVFile(this, parent, name); - BaseVFile encoded = vfs.getRootDir().createVFile(encode(original.getPath())); - original.setEncodedFile(encoded); + try { + return getVFile(parent, name); + + } catch (NoSuchFileException e) { + + CaseInsensitiveVFile original = new CaseInsensitiveVFile(this, parent, name); + BaseVFile encoded = vfs.getRootDir().createVFile(encode(original.getPath())); + original.setEncodedFile(encoded); + parent.putInCache(name, original); - return original; + return original; + } catch (NotFileException e) { + throw new CannotCreateFileException(getVFileLocation(parent, name)); + } } @Override @@ -379,6 +457,7 @@ public class CaseInsensitiveFS extends BaseVFS<CaseInsensitiveVDir, CaseInsensit try { BaseVFile encoded = vfs.getRootDir().getVFile(encode(file.getPath())); vfs.delete(encoded); + file.deleteFromCache(); } catch (NotDirectoryException e) { throw new CannotDeleteFileException(file); } catch (NotFileException e) { @@ -391,12 +470,12 @@ public class CaseInsensitiveFS extends BaseVFS<CaseInsensitiveVDir, CaseInsensit @Override @Nonnull Collection<? extends BaseVElement> list(@Nonnull CaseInsensitiveVDir dir) { - throw new UnsupportedOperationException(); + return dir.getAllFromCache(); } @Override boolean isEmpty(@Nonnull CaseInsensitiveVDir dir) { - throw new UnsupportedOperationException(); + return list(dir).isEmpty(); } // @@ -495,4 +574,29 @@ public class CaseInsensitiveFS extends BaseVFS<CaseInsensitiveVDir, CaseInsensit return array; } + + @Override + @Nonnull + VPath getPathFromDir(@Nonnull CaseInsensitiveVDir parent, @Nonnull CaseInsensitiveVFile file) { + StringBuffer path = getPathFromDirInternal(parent, (CaseInsensitiveVDir) file.getParent()) + .append(file.getName()); + return new VPath(path.toString(), '/'); + } + + @Nonnull + private StringBuffer getPathFromDirInternal(@Nonnull CaseInsensitiveVDir baseDir, + @Nonnull CaseInsensitiveVDir currentDir) { + if (baseDir == currentDir) { + return new StringBuffer(); + } + CaseInsensitiveVDir currentParent = (CaseInsensitiveVDir) currentDir.getParent(); + assert currentParent != null; + return getPathFromDirInternal(baseDir, currentParent).append(currentDir.getName()).append('/'); + } + + @Override + @Nonnull + VPath getPathFromRoot(@Nonnull CaseInsensitiveVFile file) { + return getPathFromDir(root, file); + } } diff --git a/sched/src/com/android/sched/vfs/DeflateFS.java b/sched/src/com/android/sched/vfs/DeflateFS.java index 0179b70..f805c2e 100644 --- a/sched/src/com/android/sched/vfs/DeflateFS.java +++ b/sched/src/com/android/sched/vfs/DeflateFS.java @@ -198,4 +198,16 @@ public class DeflateFS extends BaseVFS<BaseVDir, BaseVFile> implements VFS{ Location getVDirLocation(@Nonnull BaseVDir parent, @Nonnull VPath path) { return vfs.getVDirLocation(parent, path); } + + @Override + @Nonnull + VPath getPathFromDir(@Nonnull BaseVDir parent, @Nonnull BaseVFile file) { + return vfs.getPathFromDir(parent, file); + } + + @Override + @Nonnull + VPath getPathFromRoot(@Nonnull BaseVFile file) { + return vfs.getPathFromRoot(file); + } } diff --git a/sched/src/com/android/sched/vfs/DirectFS.java b/sched/src/com/android/sched/vfs/DirectFS.java index b280a40..4495439 100644 --- a/sched/src/com/android/sched/vfs/DirectFS.java +++ b/sched/src/com/android/sched/vfs/DirectFS.java @@ -299,4 +299,29 @@ public class DirectFS extends BaseVFS<ParentVDir, ParentVFile> implements VFS { private File getNativeFile(@Nonnull VPath path, @Nonnull String name) { return new File(new File(dir.getFile(), path.getPathAsString(File.separatorChar)), name); } + + @Override + @Nonnull + VPath getPathFromDir(@Nonnull ParentVDir parent, @Nonnull ParentVFile file) { + StringBuffer path = + getPathFromDirInternal(parent, (ParentVDir) file.getParent()).append(file.getName()); + return new VPath(path.toString(), '/'); + } + + @Nonnull + private static StringBuffer getPathFromDirInternal(@Nonnull ParentVDir baseDir, + @Nonnull ParentVDir currentDir) { + if (baseDir == currentDir) { + return new StringBuffer(); + } + ParentVDir currentParent = (ParentVDir) currentDir.getParent(); + assert currentParent != null; + return getPathFromDirInternal(baseDir, currentParent).append(currentDir.getName()).append('/'); + } + + @Override + @Nonnull + public VPath getPathFromRoot(@Nonnull ParentVFile file) { + return getPathFromDir(root, file); + } } diff --git a/sched/src/com/android/sched/vfs/GenericInputOutputVFile.java b/sched/src/com/android/sched/vfs/GenericInputOutputVFile.java index ec73117..b17adbc 100644 --- a/sched/src/com/android/sched/vfs/GenericInputOutputVFile.java +++ b/sched/src/com/android/sched/vfs/GenericInputOutputVFile.java @@ -82,4 +82,10 @@ public class GenericInputOutputVFile implements InputOutputVFile { public String getDigest() { return file.getDigest(); } + + @Override + @Nonnull + public VPath getPathFromRoot() { + return file.getPathFromRoot(); + } }
\ No newline at end of file diff --git a/sched/src/com/android/sched/vfs/GenericInputVFS.java b/sched/src/com/android/sched/vfs/GenericInputVFS.java index e1e29c6..c34835d 100644 --- a/sched/src/com/android/sched/vfs/GenericInputVFS.java +++ b/sched/src/com/android/sched/vfs/GenericInputVFS.java @@ -62,4 +62,10 @@ public class GenericInputVFS extends AbstractVFS implements InputVFS { public String getDigest() { return vfs.getDigest(); } + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Nonnull + public VPath getPathFromRoot(@Nonnull InputVFile file) { + return ((BaseVFS) vfs).getPathFromRoot((BaseVFile) ((GenericInputVFile) file).getVFile()); + } } diff --git a/sched/src/com/android/sched/vfs/GenericInputVFile.java b/sched/src/com/android/sched/vfs/GenericInputVFile.java index b203dbc..74ea3aa 100644 --- a/sched/src/com/android/sched/vfs/GenericInputVFile.java +++ b/sched/src/com/android/sched/vfs/GenericInputVFile.java @@ -68,4 +68,15 @@ public class GenericInputVFile implements InputVFile { public String getDigest() { return file.getDigest(); } + + @Override + @Nonnull + public VPath getPathFromRoot() { + return file.getPathFromRoot(); + } + + @Nonnull + VFile getVFile() { + return file; + } }
\ No newline at end of file diff --git a/sched/src/com/android/sched/vfs/InputVFile.java b/sched/src/com/android/sched/vfs/InputVFile.java index 55eed90..cc494ed 100644 --- a/sched/src/com/android/sched/vfs/InputVFile.java +++ b/sched/src/com/android/sched/vfs/InputVFile.java @@ -18,10 +18,14 @@ package com.android.sched.vfs; import com.android.sched.util.file.CannotDeleteFileException; +import javax.annotation.Nonnull; + /** * Virtual file to read from. */ public interface InputVFile extends InputVElement, InputStreamProvider { void delete() throws CannotDeleteFileException; + @Nonnull + VPath getPathFromRoot(); } diff --git a/sched/src/com/android/sched/vfs/MessageDigestFS.java b/sched/src/com/android/sched/vfs/MessageDigestFS.java index 123d607..25f1b84 100644 --- a/sched/src/com/android/sched/vfs/MessageDigestFS.java +++ b/sched/src/com/android/sched/vfs/MessageDigestFS.java @@ -385,7 +385,7 @@ public class MessageDigestFS extends BaseVFS<MessageDigestVDir, MessageDigestVFi @Override boolean isEmpty(@Nonnull MessageDigestVDir dir) { - return vfs.isEmpty(dir); + return vfs.isEmpty(dir.getWrappedDir()); } @Override @@ -437,30 +437,42 @@ public class MessageDigestFS extends BaseVFS<MessageDigestVDir, MessageDigestVFi @Override @Nonnull Location getVFileLocation(@Nonnull MessageDigestVDir parent, @Nonnull String name) { - return vfs.getVFileLocation(parent, name); + return vfs.getVFileLocation(parent.getWrappedDir(), name); } @Override @Nonnull Location getVFileLocation(@Nonnull MessageDigestVDir parent, @Nonnull VPath path) { - return vfs.getVFileLocation(parent, path); + return vfs.getVFileLocation(parent.getWrappedDir(), path); } @Override @Nonnull Location getVDirLocation(@Nonnull MessageDigestVDir dir) { - return vfs.getVDirLocation(dir); + return vfs.getVDirLocation(dir.getWrappedDir()); } @Override @Nonnull Location getVDirLocation(@Nonnull MessageDigestVDir parent, @Nonnull String name) { - return vfs.getVDirLocation(parent, name); + return vfs.getVDirLocation(parent.getWrappedDir(), name); } @Override @Nonnull Location getVDirLocation(@Nonnull MessageDigestVDir parent, @Nonnull VPath path) { - return vfs.getVDirLocation(parent, path); + return vfs.getVDirLocation(parent.getWrappedDir(), path); + } + + @Override + @Nonnull + VPath getPathFromDir(@Nonnull MessageDigestVDir parent, @Nonnull MessageDigestVFile file) { + return vfs.getPathFromDir(parent.getWrappedDir(), file.getWrappedFile()); + } + + @Override + @Nonnull + VPath getPathFromRoot(@Nonnull MessageDigestVFile file) { + return vfs.getPathFromRoot(file.getWrappedFile()); } } diff --git a/sched/src/com/android/sched/vfs/MessageDigestInputVFS.java b/sched/src/com/android/sched/vfs/MessageDigestInputVFS.java index 6a3bfc9..bc06970 100644 --- a/sched/src/com/android/sched/vfs/MessageDigestInputVFS.java +++ b/sched/src/com/android/sched/vfs/MessageDigestInputVFS.java @@ -101,6 +101,13 @@ public class MessageDigestInputVFS extends MessageDigestVFS implements InputVFS // This implementation is obsolete anyway throw new UnsupportedOperationException(); } + + @Override + @Nonnull + public VPath getPathFromRoot() { + // This implementation is obsolete anyway + throw new UnsupportedOperationException(); + } } /** diff --git a/sched/src/com/android/sched/vfs/ParentVDir.java b/sched/src/com/android/sched/vfs/ParentVDir.java index 1345f56..2e50eb2 100644 --- a/sched/src/com/android/sched/vfs/ParentVDir.java +++ b/sched/src/com/android/sched/vfs/ParentVDir.java @@ -46,4 +46,9 @@ public class ParentVDir extends BaseVDir { return VPath.ROOT; } } + + @CheckForNull + VDir getParent() { + return parent; + } }
\ No newline at end of file diff --git a/sched/src/com/android/sched/vfs/ParentVFile.java b/sched/src/com/android/sched/vfs/ParentVFile.java index d26f7df..5432fa0 100644 --- a/sched/src/com/android/sched/vfs/ParentVFile.java +++ b/sched/src/com/android/sched/vfs/ParentVFile.java @@ -36,4 +36,9 @@ public class ParentVFile extends BaseVFile { public VPath getPath() { return parent.getPath().clone().appendPath(new VPath(name, '/')); } + + @Nonnull + VDir getParent() { + return parent; + } }
\ No newline at end of file diff --git a/sched/src/com/android/sched/vfs/PrefixedFS.java b/sched/src/com/android/sched/vfs/PrefixedFS.java index af1c14b..cc63ea4 100644 --- a/sched/src/com/android/sched/vfs/PrefixedFS.java +++ b/sched/src/com/android/sched/vfs/PrefixedFS.java @@ -52,7 +52,7 @@ public class PrefixedFS extends BaseVFS<BaseVDir, BaseVFile> implements VFS { } catch (NoSuchFileException e) { rootDir = this.vfs.getRootDir().createVDir(prefix); } - this.rootDir = rootDir; + this.rootDir = changeVFS(rootDir); } @Override @@ -99,35 +99,39 @@ public class PrefixedFS extends BaseVFS<BaseVDir, BaseVFile> implements VFS { @Override @Nonnull Collection<? extends BaseVElement> list(@Nonnull BaseVDir dir) { - return vfs.list(dir); + Collection<? extends BaseVElement> elements = vfs.list(dir); + for (BaseVElement element : elements) { + element.changeVFS(this); + } + return elements; } @Override @Nonnull BaseVFile createVFile(@Nonnull BaseVDir parent, @Nonnull String name) throws CannotCreateFileException { - return vfs.createVFile(parent, name); + return changeVFS(vfs.createVFile(parent, name)); } @Override @Nonnull BaseVDir createVDir(@Nonnull BaseVDir parent, @Nonnull String name) throws CannotCreateFileException { - return vfs.createVDir(parent, name); + return changeVFS(vfs.createVDir(parent, name)); } @Override @Nonnull BaseVDir getVDir(@Nonnull BaseVDir parent, @Nonnull String name) throws NotDirectoryException, NoSuchFileException { - return vfs.getVDir(parent, name); + return changeVFS(vfs.getVDir(parent, name)); } @Override @Nonnull BaseVFile getVFile(@Nonnull BaseVDir parent, @Nonnull String name) throws NotFileException, NoSuchFileException { - return vfs.getVFile(parent, name); + return changeVFS(vfs.getVFile(parent, name)); } @@ -188,4 +192,28 @@ public class PrefixedFS extends BaseVFS<BaseVDir, BaseVFile> implements VFS { Location getVDirLocation(@Nonnull BaseVDir parent, @Nonnull VPath path) { return vfs.getVDirLocation(parent, path); } + + @Override + @Nonnull + VPath getPathFromDir(@Nonnull BaseVDir parent, @Nonnull BaseVFile file) { + return vfs.getPathFromDir(parent, file); + } + + @Override + @Nonnull + VPath getPathFromRoot(@Nonnull BaseVFile file) { + return vfs.getPathFromDir(rootDir, file); + } + + @Nonnull + private BaseVDir changeVFS(@Nonnull BaseVDir dir) { + dir.changeVFS(this); + return dir; + } + + @Nonnull + private BaseVFile changeVFS(@Nonnull BaseVFile file) { + file.changeVFS(this); + return file; + } } diff --git a/sched/src/com/android/sched/vfs/ReadWriteZipFS.java b/sched/src/com/android/sched/vfs/ReadWriteZipFS.java index 2bebec0..0ada64d 100644 --- a/sched/src/com/android/sched/vfs/ReadWriteZipFS.java +++ b/sched/src/com/android/sched/vfs/ReadWriteZipFS.java @@ -206,4 +206,16 @@ public class ReadWriteZipFS extends BaseVFS<BaseVDir, BaseVFile> implements VFS public void setWorkVFS(@Nonnull VFS workVFS) { vfs.setWorkVFS(workVFS); } + + @Override + @Nonnull + VPath getPathFromDir(@Nonnull BaseVDir parent, @Nonnull BaseVFile file) { + return vfs.getPathFromDir(parent, file); + } + + @Override + @Nonnull + VPath getPathFromRoot(@Nonnull BaseVFile file) { + return getPathFromDir(getRootDir(), file); + } } diff --git a/sched/src/com/android/sched/vfs/ReadZipFS.java b/sched/src/com/android/sched/vfs/ReadZipFS.java index 0c15f4a..60badad 100644 --- a/sched/src/com/android/sched/vfs/ReadZipFS.java +++ b/sched/src/com/android/sched/vfs/ReadZipFS.java @@ -19,7 +19,11 @@ package com.android.sched.vfs; import com.google.common.base.Splitter; import com.android.sched.util.file.CannotCreateFileException; +import com.android.sched.util.file.CannotDeleteFileException; import com.android.sched.util.file.InputZipFile; +import com.android.sched.util.file.NoSuchFileException; +import com.android.sched.util.file.NotDirectoryException; +import com.android.sched.util.file.NotFileException; import com.android.sched.util.location.Location; import com.android.sched.util.location.ZipLocation; import com.android.sched.vfs.ReadZipFS.ZipVDir; @@ -66,6 +70,38 @@ public class ReadZipFS extends BaseVFS<ZipVDir, ZipVFile> implements VFS { public VPath getPath() { return new VPath(zipEntry.getName(), '/'); } + + @Override + @Nonnull + public BaseVFile getVFile(@Nonnull String name) throws NoSuchFileException, + NotFileException { + return vfs.getVFile(this, name); + } + + @Override + @Nonnull + public BaseVDir getVDir(@Nonnull String name) throws NotDirectoryException, + NoSuchFileException { + return vfs.getVDir(this, name); + } + + @Override + @Nonnull + public BaseVFile createVFile(@Nonnull String name) throws CannotCreateFileException { + return vfs.createVFile(this, name); + } + + @Override + @Nonnull + public BaseVDir createVDir(@Nonnull String name) throws CannotCreateFileException { + return vfs.createVDir(this, name); + } + + @Override + @Nonnull + public Collection<? extends BaseVElement> list() { + return vfs.list(this); + } } static class ZipVFile extends BaseVFile { @@ -90,6 +126,11 @@ public class ReadZipFS extends BaseVFS<ZipVDir, ZipVFile> implements VFS { public VPath getPath() { return new VPath(zipEntry.getName(), '/'); } + + @Override + public void delete() throws CannotDeleteFileException { + vfs.delete(this); + } } @Nonnull @@ -169,30 +210,70 @@ public class ReadZipFS extends BaseVFS<ZipVDir, ZipVFile> implements VFS { @Override @Nonnull - ZipVDir getVDir(@Nonnull ZipVDir parent, @Nonnull String name) { - throw new UnsupportedOperationException(); + ZipVDir getVDir(@Nonnull ZipVDir parent, @Nonnull String name) throws NotDirectoryException, + NoSuchFileException { + BaseVElement element = parent.getFromCache(name); + if (element != null) { + if (element.isVDir()) { + return (ZipVDir) element; + } else { + throw new NotDirectoryException(getVDirLocation(parent, name)); + } + } else { + throw new NoSuchFileException(getVDirLocation(parent, name)); + } } @Override @Nonnull - ZipVFile getVFile(@Nonnull ZipVDir parent, @Nonnull String name) { - throw new UnsupportedOperationException(); + ZipVFile getVFile(@Nonnull ZipVDir parent, @Nonnull String name) throws NotFileException, + NoSuchFileException { + BaseVElement element = parent.getFromCache(name); + if (element != null) { + if (!element.isVDir()) { + return (ZipVFile) element; + } else { + throw new NotFileException(getVFileLocation(parent, name)); + } + } else { + throw new NoSuchFileException(getVFileLocation(parent, name)); + } } @Override @Nonnull - ZipVDir createVDir(@Nonnull ZipVDir parent, @Nonnull String name) { + synchronized ZipVDir createVDir(@Nonnull ZipVDir parent, @Nonnull String name) + throws CannotCreateFileException { assert !isClosed(); - return new ZipVDir(this, new ZipEntry(parent.getZipEntry().getName() + name + '/'), name); + try { + return getVDir(parent, name); + } catch (NoSuchFileException e) { + ZipVDir vDir = + new ZipVDir(this, new ZipEntry(parent.getZipEntry().getName() + name + '/'), name); + parent.putInCache(name, vDir); + return vDir; + } catch (NotDirectoryException e) { + throw new CannotCreateFileException(getVDirLocation(parent, name)); + } } @Override @Nonnull - ZipVFile createVFile(@Nonnull ZipVDir parent, @Nonnull String name) { + synchronized ZipVFile createVFile(@Nonnull ZipVDir parent, @Nonnull String name) + throws CannotCreateFileException { assert !isClosed(); - return new ZipVFile(this, zipFile.getEntry(parent.getZipEntry().getName() + name), name); + try { + return getVFile(parent, name); + } catch (NoSuchFileException e) { + ZipVFile vFile = + new ZipVFile(this, zipFile.getEntry(parent.getZipEntry().getName() + name), name); + parent.putInCache(name, vFile); + return vFile; + } catch (NotFileException e) { + throw new CannotCreateFileException(getVFileLocation(parent, name)); + } } @Override @@ -204,12 +285,12 @@ public class ReadZipFS extends BaseVFS<ZipVDir, ZipVFile> implements VFS { @Override @Nonnull Collection<? extends BaseVElement> list(@Nonnull ZipVDir dir) { - return dir.list(); + return dir.getAllFromCache(); } @Override boolean isEmpty(@Nonnull ZipVDir dir) { - return dir.list().isEmpty(); + return list(dir).isEmpty(); } // @@ -298,4 +379,20 @@ public class ReadZipFS extends BaseVFS<ZipVDir, ZipVFile> implements VFS { throw new AssertionError(e); } } + + @Override + @Nonnull + VPath getPathFromDir(@Nonnull ZipVDir parent, @Nonnull ZipVFile file) { + String fileEntryPath = file.getZipEntry().getName(); + String parentEntryPath = parent.getZipEntry().getName(); + assert fileEntryPath.startsWith(parentEntryPath); + String newPath = fileEntryPath.substring(parentEntryPath.length()); + return new VPath(newPath, '/'); + } + + @Override + @Nonnull + VPath getPathFromRoot(@Nonnull ZipVFile file) { + return getPathFromDir(root, file); + } } diff --git a/sched/src/com/android/sched/vfs/VFSToVFSWrapper.java b/sched/src/com/android/sched/vfs/VFSToVFSWrapper.java index 322fa48..0a79757 100644 --- a/sched/src/com/android/sched/vfs/VFSToVFSWrapper.java +++ b/sched/src/com/android/sched/vfs/VFSToVFSWrapper.java @@ -258,4 +258,17 @@ public class VFSToVFSWrapper extends BaseVFS<BaseVDir, BaseVFile> implements VFS public void setWorkVFS(@Nonnull VFS temporaryVFS) { workVFS = (BaseVFS<BaseVDir, BaseVFile>) temporaryVFS; } + + @Override + @Nonnull + VPath getPathFromDir(@Nonnull BaseVDir parent, @Nonnull BaseVFile file) { + return workVFS.getPathFromDir(parent, file); + } + + @Override + @Nonnull + VPath getPathFromRoot(@Nonnull BaseVFile file) { + return workVFS.getPathFromRoot(file); + } + } diff --git a/sched/src/com/android/sched/vfs/VFile.java b/sched/src/com/android/sched/vfs/VFile.java index 46df79f..75553e5 100644 --- a/sched/src/com/android/sched/vfs/VFile.java +++ b/sched/src/com/android/sched/vfs/VFile.java @@ -32,4 +32,6 @@ public interface VFile extends VElement, InputStreamProvider, OutputStreamProvid String getDigest(); void delete() throws CannotDeleteFileException; + @Nonnull + VPath getPathFromRoot(); } diff --git a/sched/src/com/android/sched/vfs/WriteZipFS.java b/sched/src/com/android/sched/vfs/WriteZipFS.java index dc5845b..8135220 100644 --- a/sched/src/com/android/sched/vfs/WriteZipFS.java +++ b/sched/src/com/android/sched/vfs/WriteZipFS.java @@ -331,4 +331,20 @@ public class WriteZipFS extends BaseVFS<ZipVDir, ZipVFile> implements VFS { } } } + + @Override + @Nonnull + VPath getPathFromDir(@Nonnull ZipVDir parent, @Nonnull ZipVFile file) { + String fileEntryPath = file.getZipEntry().getName(); + String parentEntryPath = parent.getZipEntry().getName(); + assert fileEntryPath.contains(parentEntryPath); + String newPath = fileEntryPath.substring(fileEntryPath.indexOf(parentEntryPath)); + return new VPath(newPath, '/'); + } + + @Override + @Nonnull + VPath getPathFromRoot(@Nonnull ZipVFile file) { + return getPathFromDir(root, file); + } } diff --git a/sched/tests/com/android/sched/vfs/VFSTest.java b/sched/tests/com/android/sched/vfs/VFSTest.java index 9315dc5..45a4b04 100644 --- a/sched/tests/com/android/sched/vfs/VFSTest.java +++ b/sched/tests/com/android/sched/vfs/VFSTest.java @@ -54,6 +54,7 @@ import java.security.Provider; import java.security.Security; import java.util.Collection; +import javax.annotation.CheckForNull; import javax.annotation.Nonnull; public class VFSTest { @@ -461,7 +462,7 @@ public class VFSTest { } @Test - public void testPrefixFS() + public void testPrefixedFSWithDirectFS() throws NotDirectoryException, CannotCreateFileException, WrongPermissionException, @@ -509,6 +510,164 @@ public class VFSTest { } @Test + public void testPrefixedFSWithZip() + throws NotDirectoryException, + CannotCreateFileException, + WrongPermissionException, + CannotSetPermissionException, + NoSuchFileException, + FileAlreadyExistsException, + IOException { + String prefix = "stuff"; + File file = null; + InputOutputVFS ioVFS1 = null; + InputOutputVFS ioVFS2 = null; + try { + file = File.createTempFile("vfs", ".zip"); + String path = file.getAbsolutePath(); + + WriteZipFS writeZipFS = new WriteZipFS( + new OutputZipFile(path, null, Existence.MAY_EXIST, ChangePermission.NOCHANGE)); + + ioVFS1 = new GenericInputOutputVFS(new PrefixedFS(writeZipFS, new VPath(prefix, '/'))); + + testOutputVFS(ioVFS1); + ioVFS1.close(); + writeZipFS.close(); + + ReadZipFS readZipFS = new ReadZipFS( + new InputZipFile(path, null, Existence.MUST_EXIST, ChangePermission.NOCHANGE)); + + ioVFS2 = new GenericInputOutputVFS(new PrefixedFS(readZipFS, new VPath(prefix, '/'))); + testInputVFS(ioVFS2); + checkZipLocations(ioVFS2, prefix); + + readZipFS.close(); + + } finally { + if (ioVFS1 != null) { + ioVFS1.close(); + } + if (ioVFS2 != null) { + ioVFS2.close(); + } + if (file != null) { + Assert.assertTrue(file.delete()); + } + } + } + + @Test + public void testPrefixedFSWithCaseInsensitiveFS() + throws NotDirectoryException, + CannotCreateFileException, + WrongPermissionException, + CannotSetPermissionException, + NoSuchFileException, + FileAlreadyExistsException, + IOException { + File file = null; + InputOutputVFS ioVFS1 = null; + InputOutputVFS ioVFS2 = null; + try { + file = File.createTempFile("vfs", "dir"); + String path = file.getAbsolutePath(); + Assert.assertTrue(file.delete()); + + CaseInsensitiveFS ciFS = new CaseInsensitiveFS(new DirectFS(new Directory(path, null, + Existence.NOT_EXIST, Permission.WRITE, ChangePermission.NOCHANGE), + Permission.READ | Permission.WRITE)); + + ioVFS1 = new GenericInputOutputVFS(new PrefixedFS(ciFS, new VPath("stuff", '/'))); + + testOutputVFS(ioVFS1); + testInputVFS(ioVFS1); + ciFS.close(); + ioVFS1.close(); + + CaseInsensitiveFS ciFS2 = new CaseInsensitiveFS(new DirectFS(new Directory(path, null, + Existence.MUST_EXIST, Permission.WRITE, ChangePermission.NOCHANGE), + Permission.READ | Permission.WRITE)); + + ioVFS2 = new GenericInputOutputVFS(new PrefixedFS(ciFS2, new VPath("stuff", '/'))); + testInputVFS(ioVFS2); + ciFS2.close(); + + } finally { + if (ioVFS1 != null) { + ioVFS1.close(); + } + if (ioVFS2 != null) { + ioVFS2.close(); + } + if (file != null) { + FileUtils.deleteDir(file); + } + } + } + + @Test + public void testMessageDigestFSWithPrefixedFSAndCaseInsensitiveFS() + throws NotDirectoryException, + CannotCreateFileException, + WrongPermissionException, + CannotSetPermissionException, + NoSuchFileException, + FileAlreadyExistsException, + IOException { + File file = null; + InputOutputVFS ioVFS1 = null; + InputOutputVFS ioVFS2 = null; + try { + file = File.createTempFile("vfs", "dir"); + String path = file.getAbsolutePath(); + Assert.assertTrue(file.delete()); + + Provider.Service sha1 = null; + for (Provider provider : Security.getProviders()) { + for (Provider.Service service : provider.getServices()) { + if (service.getType().equals("MessageDigest") && service.getAlgorithm().equals("SHA")) { + sha1 = service; + } + } + } + Assert.assertNotNull(sha1); + + CaseInsensitiveFS ciFS = + new CaseInsensitiveFS(new MessageDigestFS(new CachedDirectFS(new Directory(path, null, + Existence.NOT_EXIST, Permission.WRITE, ChangePermission.NOCHANGE), + Permission.READ | Permission.WRITE), new MessageDigestFactory(sha1))); + + ioVFS1 = new GenericInputOutputVFS(new PrefixedFS(ciFS, new VPath("stuff", '/'))); + + testOutputVFS(ioVFS1); + testInputVFS(ioVFS1); + ciFS.close(); + ioVFS1.close(); + + CaseInsensitiveFS ciFS2 = + new CaseInsensitiveFS(new MessageDigestFS(new CachedDirectFS(new Directory(path, null, + Existence.MUST_EXIST, Permission.WRITE, ChangePermission.NOCHANGE), + Permission.READ | Permission.WRITE), new MessageDigestFactory(sha1))); + + ioVFS2 = new GenericInputOutputVFS(new PrefixedFS(ciFS2, new VPath("stuff", '/'))); + testInputVFS(ioVFS2); + ciFS2.close(); + + } finally { + if (ioVFS1 != null) { + ioVFS1.close(); + } + if (ioVFS2 != null) { + ioVFS2.close(); + } + if (file != null) { + FileUtils.deleteDir(file); + } + } + } + + @Test public void testWriteZipVFS() throws NotDirectoryException, CannotCreateFileException, @@ -586,6 +745,7 @@ public class VFSTest { NoSuchFileException, IOException { InputVFile file1 = inputVFS.getRootInputVDir().getInputVFile(new VPath("file1", '/')); Assert.assertEquals("file1", readFromFile(file1)); + Assert.assertTrue(file1.getPathFromRoot().equals(new VPath("file1", '/'))); InputVDir dirA = inputVFS.getRootInputVDir().getInputVDir(new VPath("dirA", '/')); Collection<? extends InputVElement> dirAElements = dirA.list(); @@ -597,15 +757,19 @@ public class VFSTest { InputVFile fileAAB1 = inputVFS.getRootInputVDir().getInputVFile(new VPath("dirA/dirAA/dirAAB/fileAAB1", '/')); Assert.assertEquals("dirA/dirAA/dirAAB/fileAAB1", readFromFile(fileAAB1)); + Assert.assertTrue( + fileAAB1.getPathFromRoot().equals(new VPath("dirA/dirAA/dirAAB/fileAAB1", '/'))); InputVDir dirB = inputVFS.getRootInputVDir().getInputVDir(new VPath("dirB", '/')); InputVDir dirBA = dirB.getInputVDir(new VPath("dirBA", '/')); InputVFile fileBA1 = dirBA.getInputVFile(new VPath("fileBA1", '/')); Assert.assertEquals("dirB/dirBA/fileBA1", readFromFile(fileBA1)); + Assert.assertTrue(fileBA1.getPathFromRoot().equals(new VPath("dirB/dirBA/fileBA1", '/'))); InputVDir dirBB = inputVFS.getRootInputVDir().getInputVDir(new VPath("dirB/dirBB", '/')); InputVFile fileBB1 = dirBB.getInputVFile(new VPath("fileBB1", '/')); Assert.assertEquals("dirB/dirBB/fileBB1", readFromFile(fileBB1)); + Assert.assertTrue(fileBB1.getPathFromRoot().equals(new VPath("dirB/dirBB/fileBB1", '/'))); } @Test @@ -724,21 +888,40 @@ public class VFSTest { dirBBPath.getPathAsString(File.separatorChar))); } - private void checkZipLocations(@Nonnull InputVFS inputVFS) throws NotFileOrDirectoryException, - NoSuchFileException { + private void checkZipLocations(@Nonnull InputVFS inputVFS, @CheckForNull String prefix) + throws NotFileOrDirectoryException, NoSuchFileException { VPath fileAAB1Path = new VPath("dirA/dirAA/dirAAB/fileAAB1", '/'); InputVFile fileAAB1 = inputVFS.getRootInputVDir().getInputVFile(fileAAB1Path); ZipLocation fileAAB1Location = (ZipLocation) fileAAB1.getLocation(); Assert.assertTrue(fileAAB1Location.getDescription().contains(".zip")); - Assert.assertTrue(fileAAB1Location.getDescription().contains("entry '" + ZipUtils.ZIP_SEPARATOR - + fileAAB1Path.getPathAsString(ZipUtils.ZIP_SEPARATOR) + '\'')); + String fileAAB1EntryName = getEntryName(fileAAB1Path, prefix, false); + Assert.assertTrue(fileAAB1Location.getDescription().contains(fileAAB1EntryName)); VPath dirBBPath = new VPath("dirB/dirBB", '/'); InputVDir dirBB = inputVFS.getRootInputVDir().getInputVDir(dirBBPath); ZipLocation dirBBLocation = (ZipLocation) dirBB.getLocation(); Assert.assertTrue(dirBBLocation.getDescription().contains(".zip")); - Assert.assertTrue(dirBBLocation.getDescription().contains("entry '" + ZipUtils.ZIP_SEPARATOR - + dirBBPath.getPathAsString(ZipUtils.ZIP_SEPARATOR) + ZipUtils.ZIP_SEPARATOR + '\'')); + String dirBBEntryName = getEntryName(dirBBPath, prefix, true); + Assert.assertTrue(dirBBLocation.getDescription().contains(dirBBEntryName)); + } + private void checkZipLocations(@Nonnull InputVFS inputVFS) + throws NotFileOrDirectoryException, NoSuchFileException { + checkZipLocations(inputVFS, null); + } + + private String getEntryName(@Nonnull VPath path, @CheckForNull String prefix, boolean isDir) { + StringBuffer entryName = new StringBuffer("entry '"); + if (prefix != null) { + entryName.append(ZipUtils.ZIP_SEPARATOR); + entryName.append(prefix); + } + entryName.append(ZipUtils.ZIP_SEPARATOR); + entryName.append(path.getPathAsString(ZipUtils.ZIP_SEPARATOR)); + if (isDir) { + entryName.append(ZipUtils.ZIP_SEPARATOR); + } + entryName.append('\''); + return entryName.toString(); } private void checkUnicity(@Nonnull VFS vfs) throws NotDirectoryException, NoSuchFileException, |