You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ag...@apache.org on 2015/03/11 16:35:22 UTC
[11/13] cordova-plugin-file git commit: CB-6428 android: Add support
for directory copies from assets -> filesystem
CB-6428 android: Add support for directory copies from assets -> filesystem
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/commit/072acc73
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/tree/072acc73
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/diff/072acc73
Branch: refs/heads/master
Commit: 072acc733182c4736421e1a516706844e37747e0
Parents: 7051ad3
Author: Andrew Grieve <ag...@chromium.org>
Authored: Tue Mar 10 22:43:14 2015 -0400
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Wed Mar 11 11:35:08 2015 -0400
----------------------------------------------------------------------
src/android/AssetFilesystem.java | 2 +-
src/android/Filesystem.java | 7 +-
src/android/LocalFilesystem.java | 279 ++++++++++------------------------
tests/tests.js | 34 +++++
4 files changed, 119 insertions(+), 203 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/072acc73/src/android/AssetFilesystem.java
----------------------------------------------------------------------
diff --git a/src/android/AssetFilesystem.java b/src/android/AssetFilesystem.java
index 40968e0..c1c0d6f 100644
--- a/src/android/AssetFilesystem.java
+++ b/src/android/AssetFilesystem.java
@@ -211,7 +211,7 @@ public class AssetFilesystem extends Filesystem {
}
@Override
- boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException, NoModificationAllowedException {
+ boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws NoModificationAllowedException {
throw new NoModificationAllowedException("Assets are read-only");
}
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/072acc73/src/android/Filesystem.java
----------------------------------------------------------------------
diff --git a/src/android/Filesystem.java b/src/android/Filesystem.java
index 309c0b8..45047c8 100644
--- a/src/android/Filesystem.java
+++ b/src/android/Filesystem.java
@@ -198,7 +198,7 @@ public abstract class Filesystem {
return getEntryForLocalURL(LocalFilesystemURL.parse(parentUri));
}
- protected LocalFilesystemURL makeDestinationURL(String newName, LocalFilesystemURL srcURL, LocalFilesystemURL destURL) {
+ protected LocalFilesystemURL makeDestinationURL(String newName, LocalFilesystemURL srcURL, LocalFilesystemURL destURL, boolean isDirectory) {
// I know this looks weird but it is to work around a JSON bug.
if ("null".equals(newName) || "".equals(newName)) {
newName = srcURL.uri.getLastPathSegment();;
@@ -210,6 +210,9 @@ public abstract class Filesystem {
} else {
newDest = newDest + "/" + newName;
}
+ if (isDirectory) {
+ newDest += '/';
+ }
return LocalFilesystemURL.parse(newDest);
}
@@ -224,7 +227,7 @@ public abstract class Filesystem {
if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
throw new NoModificationAllowedException("Cannot move file at source URL");
}
- final LocalFilesystemURL destination = makeDestinationURL(newName, srcURL, destURL);
+ final LocalFilesystemURL destination = makeDestinationURL(newName, srcURL, destURL, srcURL.isDirectory);
Uri srcNativeUri = srcFs.toNativeUri(srcURL);
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/072acc73/src/android/LocalFilesystem.java
----------------------------------------------------------------------
diff --git a/src/android/LocalFilesystem.java b/src/android/LocalFilesystem.java
index 93ba2b0..cc0ff57 100644
--- a/src/android/LocalFilesystem.java
+++ b/src/android/LocalFilesystem.java
@@ -20,17 +20,12 @@ package org.apache.cordova.file;
import java.io.ByteArrayInputStream;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
-import java.util.ArrayList;
-import java.util.Arrays;
-
import org.apache.cordova.CordovaResourceApi;
-import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -263,182 +258,72 @@ public class LocalFilesystem extends Filesystem {
return metadata;
}
- /**
- * Check to see if the user attempted to copy an entry into its parent without changing its name,
- * or attempted to copy a directory into a directory that it contains directly or indirectly.
- */
- private boolean isCopyOnItself(String src, String dest) {
-
- // This weird test is to determine if we are copying or moving a directory into itself.
- // Copy /sdcard/myDir to /sdcard/myDir-backup is okay but
- // Copy /sdcard/myDir to /sdcard/myDir/backup should throw an INVALID_MODIFICATION_ERR
- return dest.equals(src) || dest.startsWith(src + File.separator);
- }
-
- /**
- * Copy a file
- *
- * @param srcFile file to be copied
- * @param destFile destination to be copied to
- * @return a FileEntry object
- * @throws IOException
- * @throws InvalidModificationException
- * @throws JSONException
- */
- private JSONObject copyFile(File srcFile, File destFile) throws IOException, InvalidModificationException, JSONException {
- // Renaming a file to an existing directory should fail
- if (destFile.exists() && destFile.isDirectory()) {
- throw new InvalidModificationException("Can't rename a file to a directory");
+ private void copyFile(Filesystem srcFs, LocalFilesystemURL srcURL, File destFile, boolean move) throws IOException, InvalidModificationException, NoModificationAllowedException {
+ if (move) {
+ String realSrcPath = srcFs.filesystemPathForURL(srcURL);
+ if (realSrcPath != null) {
+ File srcFile = new File(realSrcPath);
+ if (srcFile.renameTo(destFile)) {
+ return;
+ }
+ // Trying to rename the file failed. Possibly because we moved across file system on the device.
+ }
}
- copyAction(srcFile, destFile);
-
- return makeEntryForFile(destFile);
- }
-
- /**
- * Moved this code into it's own method so moveTo could use it when the move is across file systems
- */
- private void copyAction(File srcFile, File destFile)
- throws FileNotFoundException, IOException {
- FileInputStream istream = new FileInputStream(srcFile);
- FileOutputStream ostream = new FileOutputStream(destFile);
- FileChannel input = istream.getChannel();
- FileChannel output = ostream.getChannel();
+ CordovaResourceApi.OpenForReadResult offr = resourceApi.openForRead(srcFs.toNativeUri(srcURL));
+ resourceApi.copyResource(offr, new FileOutputStream(destFile));
- try {
- input.transferTo(0, input.size(), output);
- } finally {
- istream.close();
- ostream.close();
- input.close();
- output.close();
+ if (move) {
+ srcFs.removeFileAtLocalURL(srcURL);
}
}
- /**
- * Copy a directory
- *
- * @param srcDir directory to be copied
- * @param destinationDir destination to be copied to
- * @return a DirectoryEntry object
- * @throws JSONException
- * @throws IOException
- * @throws NoModificationAllowedException
- * @throws InvalidModificationException
- */
- private JSONObject copyDirectory(File srcDir, File destinationDir) throws JSONException, IOException, NoModificationAllowedException, InvalidModificationException {
- // Renaming a file to an existing directory should fail
- if (destinationDir.exists() && destinationDir.isFile()) {
- throw new InvalidModificationException("Can't rename a file to a directory");
- }
-
- // Check to make sure we are not copying the directory into itself
- if (isCopyOnItself(srcDir.getAbsolutePath(), destinationDir.getAbsolutePath())) {
- throw new InvalidModificationException("Can't copy itself into itself");
+ private void copyDirectory(Filesystem srcFs, LocalFilesystemURL srcURL, File dstDir, boolean move) throws IOException, NoModificationAllowedException, InvalidModificationException, FileExistsException {
+ if (move) {
+ String realSrcPath = srcFs.filesystemPathForURL(srcURL);
+ if (realSrcPath != null) {
+ File srcDir = new File(realSrcPath);
+ // If the destination directory already exists and is empty then delete it. This is according to spec.
+ if (dstDir.exists()) {
+ if (dstDir.list().length > 0) {
+ throw new InvalidModificationException("directory is not empty");
+ }
+ dstDir.delete();
+ }
+ // Try to rename the directory
+ if (srcDir.renameTo(dstDir)) {
+ return;
+ }
+ // Trying to rename the file failed. Possibly because we moved across file system on the device.
+ }
}
- // See if the destination directory exists. If not create it.
- if (!destinationDir.exists()) {
- if (!destinationDir.mkdir()) {
+ if (dstDir.exists()) {
+ if (dstDir.list().length > 0) {
+ throw new InvalidModificationException("directory is not empty");
+ }
+ } else {
+ if (!dstDir.mkdir()) {
// If we can't create the directory then fail
throw new NoModificationAllowedException("Couldn't create the destination directory");
}
}
-
- for (File file : srcDir.listFiles()) {
- File destination = new File(destinationDir.getAbsoluteFile() + File.separator + file.getName());
- if (file.isDirectory()) {
- copyDirectory(file, destination);
+ LocalFilesystemURL[] children = srcFs.listChildren(srcURL);
+ for (LocalFilesystemURL childLocalUrl : children) {
+ File target = new File(dstDir, new File(childLocalUrl.path).getName());
+ if (childLocalUrl.isDirectory) {
+ copyDirectory(srcFs, childLocalUrl, target, false);
} else {
- copyFile(file, destination);
+ copyFile(srcFs, childLocalUrl, target, false);
}
}
- return makeEntryForFile(destinationDir);
- }
-
- /**
- * Move a file
- *
- * @param srcFile file to be copied
- * @param destFile destination to be copied to
- * @return a FileEntry object
- * @throws IOException
- * @throws InvalidModificationException
- * @throws JSONException
- */
- private JSONObject moveFile(File srcFile, File destFile) throws IOException, JSONException, InvalidModificationException {
- // Renaming a file to an existing directory should fail
- if (destFile.exists() && destFile.isDirectory()) {
- throw new InvalidModificationException("Can't rename a file to a directory");
- }
-
- // Try to rename the file
- if (!srcFile.renameTo(destFile)) {
- // Trying to rename the file failed. Possibly because we moved across file system on the device.
- // Now we have to do things the hard way
- // 1) Copy all the old file
- // 2) delete the src file
- copyAction(srcFile, destFile);
- if (destFile.exists()) {
- srcFile.delete();
- } else {
- throw new IOException("moved failed");
- }
+ if (move) {
+ srcFs.recursiveRemoveFileAtLocalURL(srcURL);
}
-
- return makeEntryForFile(destFile);
}
- /**
- * Move a directory
- *
- * @param srcDir directory to be copied
- * @param destinationDir destination to be copied to
- * @return a DirectoryEntry object
- * @throws JSONException
- * @throws IOException
- * @throws InvalidModificationException
- * @throws NoModificationAllowedException
- * @throws FileExistsException
- */
- private JSONObject moveDirectory(File srcDir, File destinationDir) throws IOException, JSONException, InvalidModificationException, NoModificationAllowedException, FileExistsException {
- // Renaming a file to an existing directory should fail
- if (destinationDir.exists() && destinationDir.isFile()) {
- throw new InvalidModificationException("Can't rename a file to a directory");
- }
-
- // Check to make sure we are not copying the directory into itself
- if (isCopyOnItself(srcDir.getAbsolutePath(), destinationDir.getAbsolutePath())) {
- throw new InvalidModificationException("Can't move itself into itself");
- }
-
- // If the destination directory already exists and is empty then delete it. This is according to spec.
- if (destinationDir.exists()) {
- if (destinationDir.list().length > 0) {
- throw new InvalidModificationException("directory is not empty");
- }
- }
-
- // Try to rename the directory
- if (!srcDir.renameTo(destinationDir)) {
- // Trying to rename the directory failed. Possibly because we moved across file system on the device.
- // Now we have to do things the hard way
- // 1) Copy all the old files
- // 2) delete the src directory
- copyDirectory(srcDir, destinationDir);
- if (destinationDir.exists()) {
- removeDirRecursively(srcDir);
- } else {
- throw new IOException("moved failed");
- }
- }
-
- return makeEntryForFile(destinationDir);
- }
-
@Override
public JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException {
@@ -451,45 +336,39 @@ public class LocalFilesystem extends Filesystem {
throw new FileNotFoundException("The source does not exist");
}
- if (LocalFilesystem.class.isInstance(srcFs)) {
- /* Same FS, we can shortcut with NSFileManager operations */
-
- // Figure out where we should be copying to
- final LocalFilesystemURL destinationURL = makeDestinationURL(newName, srcURL, destURL);
-
- String srcFilesystemPath = srcFs.filesystemPathForURL(srcURL);
- File sourceFile = new File(srcFilesystemPath);
- String destFilesystemPath = this.filesystemPathForURL(destinationURL);
- File destinationFile = new File(destFilesystemPath);
-
- if (!sourceFile.exists()) {
- // The file/directory we are copying doesn't exist so we should fail.
- throw new FileNotFoundException("The source does not exist");
- }
-
- // Check to see if source and destination are the same file
- if (sourceFile.getAbsolutePath().equals(destinationFile.getAbsolutePath())) {
- throw new InvalidModificationException("Can't copy a file onto itself");
- }
-
- if (sourceFile.isDirectory()) {
- if (move) {
- return moveDirectory(sourceFile, destinationFile);
- } else {
- return copyDirectory(sourceFile, destinationFile);
- }
- } else {
- if (move) {
- return moveFile(sourceFile, destinationFile);
- } else {
- return copyFile(sourceFile, destinationFile);
- }
- }
-
- } else {
- // Need to copy the hard way
- return super.copyFileToURL(destURL, newName, srcFs, srcURL, move);
- }
+ // Figure out where we should be copying to
+ final LocalFilesystemURL destinationURL = makeDestinationURL(newName, srcURL, destURL, srcURL.isDirectory);
+
+ Uri dstNativeUri = toNativeUri(destinationURL);
+ Uri srcNativeUri = srcFs.toNativeUri(srcURL);
+ // Check to see if source and destination are the same file
+ if (dstNativeUri.equals(srcNativeUri)) {
+ throw new InvalidModificationException("Can't copy onto itself");
+ }
+
+ if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
+ throw new InvalidModificationException("Source URL is read-only (cannot move)");
+ }
+
+ File destFile = new File(dstNativeUri.getPath());
+ if (destFile.exists()) {
+ if (!srcURL.isDirectory && destFile.isDirectory()) {
+ throw new InvalidModificationException("Can't copy/move a file to an existing directory");
+ } else if (srcURL.isDirectory && destFile.isFile()) {
+ throw new InvalidModificationException("Can't copy/move a directory to an existing file");
+ }
+ }
+
+ if (srcURL.isDirectory) {
+ // E.g. Copy /sdcard/myDir to /sdcard/myDir/backup
+ if (dstNativeUri.toString().startsWith(srcNativeUri.toString() + '/')) {
+ throw new InvalidModificationException("Can't copy directory into itself");
+ }
+ copyDirectory(srcFs, srcURL, destFile, move);
+ } else {
+ copyFile(srcFs, srcURL, destFile, move);
+ }
+ return makeEntryForURL(destinationURL);
}
@Override
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/072acc73/tests/tests.js
----------------------------------------------------------------------
diff --git a/tests/tests.js b/tests/tests.js
index 5735af1..239a0d3 100644
--- a/tests/tests.js
+++ b/tests/tests.js
@@ -3480,6 +3480,40 @@ exports.defineAutoTests = function () {
}, transfer);
});
});
+ it("file.spec.144 copyTo: asset directory", function (done) {
+ var srcUrl = 'file:///android_asset/www/plugins/org.apache.cordova.file';
+ var dstDir = "entry.copy.dstDir";
+ var dstPath = joinURL(root.fullPath, dstDir);
+ // create a new directory entry to kick off it
+ deleteEntry(dstDir, function () {
+ resolveLocalFileSystemURL(srcUrl, function(directory) {
+ directory.copyTo(root, dstDir, function (directory) {
+ expect(directory).toBeDefined();
+ expect(directory.isFile).toBe(false);
+ expect(directory.isDirectory).toBe(true);
+ expect(directory.fullPath).toCanonicallyMatch(dstPath);
+ expect(directory.name).toCanonicallyMatch(dstDir);
+ root.getDirectory(dstDir, {
+ create : false
+ }, function (dirEntry) {
+ expect(dirEntry).toBeDefined();
+ expect(dirEntry.isFile).toBe(false);
+ expect(dirEntry.isDirectory).toBe(true);
+ expect(dirEntry.fullPath).toCanonicallyMatch(dstPath);
+ expect(dirEntry.name).toCanonicallyMatch(dstDir);
+ dirEntry.getFile('www/File.js', {
+ create : false
+ }, function (fileEntry) {
+ expect(fileEntry).toBeDefined();
+ expect(fileEntry.isFile).toBe(true);
+ // cleanup
+ deleteEntry(dstDir, done);
+ }, failed.bind(null, done, 'dirEntry.getFile - Error getting subfile'));
+ }, failed.bind(null, done, 'root.getDirectory - Error getting copied directory'));
+ }, failed.bind(null, done, 'directory.copyTo - Error copying directory'));
+ }, failed.bind(null, done, 'resolving src dir'));
+ }, failed.bind(null, done, 'deleteEntry - Error removing directory : ' + dstDir));
+ });
}
});
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org