You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ia...@apache.org on 2014/01/09 20:07:20 UTC
git commit: Android: Refactor File API
Updated Branches:
refs/heads/dev e7f83cb7d -> eaeb59812
Android: Refactor File API
Also gets content file copying working
Promote Filesystem interface to base class
Remove duplicated code; push to Filesystem class
Stream file output where possible between methods
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/eaeb5981
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/tree/eaeb5981
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/diff/eaeb5981
Branch: refs/heads/dev
Commit: eaeb598124c01176c1c9191910b5761e56c00904
Parents: e7f83cb
Author: Ian Clelland <ic...@chromium.org>
Authored: Wed Jan 8 13:24:50 2014 -0500
Committer: Ian Clelland <ic...@chromium.org>
Committed: Thu Jan 9 14:03:38 2014 -0500
----------------------------------------------------------------------
src/android/ContentFilesystem.java | 148 +++++++++++++++++----------
src/android/FileUtils.java | 34 +++++--
src/android/Filesystem.java | 167 +++++++++++++++++++++++++++----
src/android/LocalFilesystem.java | 143 +++++++-------------------
src/android/LocalFilesystemURL.java | 7 +-
src/android/ReadFileCallback.java | 7 --
6 files changed, 308 insertions(+), 198 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/eaeb5981/src/android/ContentFilesystem.java
----------------------------------------------------------------------
diff --git a/src/android/ContentFilesystem.java b/src/android/ContentFilesystem.java
index 03a1939..535a2fe 100644
--- a/src/android/ContentFilesystem.java
+++ b/src/android/ContentFilesystem.java
@@ -1,26 +1,30 @@
package org.apache.cordova.file;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.InputStream;
+import java.io.OutputStream;
import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaResourceApi;
+import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.ContentResolver;
import android.database.Cursor;
+import android.net.Uri;
import android.provider.MediaStore;
-public class ContentFilesystem implements Filesystem {
+public class ContentFilesystem extends Filesystem {
private CordovaInterface cordova;
+ private CordovaResourceApi resourceApi;
- public ContentFilesystem(CordovaInterface cordova) {
+ public ContentFilesystem(CordovaInterface cordova, CordovaWebView webView) {
this.cordova = cordova;
+ this.resourceApi = new CordovaResourceApi(webView.getContext(), webView.pluginManager);
}
@Override
@@ -41,23 +45,37 @@ public class ContentFilesystem implements Filesystem {
throw new IOException();
}
try {
- JSONObject entry = new JSONObject();
- entry.put("isFile", fp.isFile());
- entry.put("isDirectory", fp.isDirectory());
- entry.put("name", fp.getName());
- entry.put("fullPath", "file://" + fp.getAbsolutePath());
- // The file system can't be specified, as it would lead to an infinite loop.
- entry.put("filesystem", FileUtils.APPLICATION);
- return entry;
+ return makeEntryForPath(inputURL.fullPath, inputURL.filesystemType, fp.isDirectory());
} catch (JSONException e) {
throw new IOException();
}
}
-
- @Override
+
+ @Override
public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
- String fileName, JSONObject options, boolean directory) throws IOException {
- throw new IOException("Cannot create content url");
+ String fileName, JSONObject options, boolean directory) throws IOException, TypeMismatchException, JSONException {
+ if (options != null) {
+ if (options.optBoolean("create")) {
+ throw new IOException("Cannot create content url");
+ }
+ }
+ LocalFilesystemURL requestedURL = new LocalFilesystemURL(Uri.withAppendedPath(inputURL.URL, fileName));
+ File fp = new File(this.filesystemPathForURL(requestedURL));
+ if (!fp.exists()) {
+ throw new FileNotFoundException("path does not exist");
+ }
+ if (directory) {
+ if (fp.isFile()) {
+ throw new TypeMismatchException("path doesn't exist or is file");
+ }
+ } else {
+ if (fp.isDirectory()) {
+ throw new TypeMismatchException("path doesn't exist or is directory");
+ }
+ }
+ // Return the directory
+ return makeEntryForPath(requestedURL.fullPath, requestedURL.filesystemType, directory);
+
}
@Override
@@ -93,55 +111,72 @@ public class ContentFilesystem implements Filesystem {
@Override
public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public JSONObject getParentForLocalURL(LocalFilesystemURL inputURL)
- throws IOException {
- LocalFilesystemURL newURL = new LocalFilesystemURL(inputURL.URL);
-
- if (!("".equals(inputURL.fullPath) || "/".equals(inputURL.fullPath))) {
- int end = inputURL.fullPath.endsWith("/") ? 1 : 0;
- int lastPathStartsAt = inputURL.fullPath.lastIndexOf('/', inputURL.fullPath.length()-end)+1;
- newURL.fullPath = newURL.fullPath.substring(0,lastPathStartsAt);
- }
- return getEntryForLocalURL(newURL);
+ String path = filesystemPathForURL(inputURL);
+ if (path == null) {
+ throw new FileNotFoundException();
+ }
+ File file = new File(path);
+ JSONObject metadata = new JSONObject();
+ try {
+ metadata.put("size", file.length());
+ metadata.put("type", resourceApi.getMimeType(inputURL.URL));
+ metadata.put("name", file.getName());
+ metadata.put("fullPath", inputURL.fullPath);
+ metadata.put("lastModifiedDate", file.lastModified());
+ } catch (JSONException e) {
+ return null;
+ }
+ return metadata;
}
@Override
public JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
Filesystem srcFs, LocalFilesystemURL srcURL, boolean move)
- throws IOException, InvalidModificationException, JSONException,
- NoModificationAllowedException, FileExistsException {
- // TODO Auto-generated method stub
- return null;
+ throws IOException, InvalidModificationException, JSONException,
+ NoModificationAllowedException, FileExistsException {
+ if (LocalFilesystem.class.isInstance(srcFs)) {
+ /* Same FS, we can shortcut with CordovaResourceApi operations */
+ // Figure out where we should be copying to
+ final LocalFilesystemURL destinationURL = makeDestinationURL(newName, srcURL, destURL);
+
+ OutputStream os = resourceApi.openOutputStream(destURL.URL);
+ CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(srcURL.URL);
+ if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
+ throw new NoModificationAllowedException("Cannot move file at source URL");
+ }
+ try {
+ resourceApi.copyResource(ofrr, os);
+ } catch (IOException e) {
+ throw new IOException("Cannot read file at source URL");
+ }
+ if (move) {
+ srcFs.removeFileAtLocalURL(srcURL);
+ }
+ return makeEntryForURL(destinationURL, false);
+ } else {
+ // Need to copy the hard way
+ return super.copyFileToURL(destURL, newName, srcFs, srcURL, move);
+ }
}
+
@Override
- public void readFileAtURL(LocalFilesystemURL inputURL, int start, int end,
+ public void readFileAtURL(LocalFilesystemURL inputURL, long start, long end,
ReadFileCallback readFileCallback) throws IOException {
- int numBytesToRead = end - start;
- byte[] bytes = new byte[numBytesToRead];
- String contentType;
-
- File file = new File(this.filesystemPathForURL(inputURL));
- contentType = FileHelper.getMimeTypeForExtension(file.getAbsolutePath());
-
- InputStream inputStream = new FileInputStream(file);
- int numBytesRead = 0;
+ CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(inputURL.URL);
+ if (end < 0) {
+ end = ofrr.length;
+ }
+ long numBytesToRead = end - start;
try {
if (start > 0) {
- inputStream.skip(start);
- }
- while (numBytesToRead > 0 && (numBytesRead = inputStream.read(bytes, numBytesRead, numBytesToRead)) >= 0) {
- numBytesToRead -= numBytesRead;
+ ofrr.inputStream.skip(start);
}
+ LimitedInputStream inputStream = new LimitedInputStream(ofrr.inputStream, numBytesToRead);
+ readFileCallback.handleData(inputStream, ofrr.mimeType);
} finally {
- inputStream.close();
+ ofrr.inputStream.close();
}
- readFileCallback.handleData(bytes, contentType);
}
@Override
@@ -178,7 +213,7 @@ public class ContentFilesystem implements Filesystem {
@Override
public LocalFilesystemURL URLforFilesystemPath(String path) {
- // TODO Auto-generated method stub
+ // Returns null as we don't support reverse mapping back to content:// URLs
return null;
}
@@ -188,4 +223,11 @@ public class ContentFilesystem implements Filesystem {
File file = new File(path);
return file.exists();
}
-}
+
+ @Override
+ OutputStream getOutputStreamForURL(LocalFilesystemURL inputURL)
+ throws IOException {
+ OutputStream os = resourceApi.openOutputStream(inputURL.URL);
+ return os;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/eaeb5981/src/android/FileUtils.java
----------------------------------------------------------------------
diff --git a/src/android/FileUtils.java b/src/android/FileUtils.java
index 20a2700..d1c1b59 100644
--- a/src/android/FileUtils.java
+++ b/src/android/FileUtils.java
@@ -20,7 +20,6 @@ package org.apache.cordova.file;
import android.net.Uri;
import android.os.Environment;
-import android.provider.MediaStore;
import android.util.Base64;
import android.util.Log;
@@ -34,9 +33,11 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URLDecoder;
import java.util.ArrayList;
@@ -68,6 +69,7 @@ public class FileUtils extends CordovaPlugin {
public static int PERSISTENT = 1;
public static int RESOURCE = 2;
public static int APPLICATION = 3;
+ public static int CONTENT = 4;
// This field exists only to support getEntry, below, which has been deprecated
private static FileUtils filePlugin;
@@ -99,8 +101,9 @@ public class FileUtils extends CordovaPlugin {
fp.mkdirs();
this.filesystems.add(new LocalFilesystem(cordova, "temporary", tempRoot));
this.filesystems.add(new LocalFilesystem(cordova, "persistent", persistentRoot));
- this.filesystems.add(null);
- this.filesystems.add(new ContentFilesystem(cordova));
+ this.filesystems.add(null); // Hold for 'resource' FS
+ this.filesystems.add(null); // Hold for 'application' FS
+ this.filesystems.add(new ContentFilesystem(cordova, webView));
// Initialize static plugin reference for deprecated getEntry method
if (filePlugin == null) {
@@ -764,22 +767,35 @@ public class FileUtils extends CordovaPlugin {
throw new MalformedURLException("No installed handlers for this URL");
}
- fs.readFileAtURL(inputURL, start, end, new ReadFileCallback() {
- public void handleData(byte[] bytes, String contentType) {
+ fs.readFileAtURL(inputURL, start, end, new Filesystem.ReadFileCallback() {
+ public void handleData(InputStream inputStream, String contentType) {
try {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ final int BUFFER_SIZE = 8192;
+ byte[] buffer = new byte[BUFFER_SIZE];
+
+ for (;;) {
+ int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
+
+ if (bytesRead <= 0) {
+ break;
+ }
+ os.write(buffer, 0, bytesRead);
+ }
+
PluginResult result;
switch (resultType) {
case PluginResult.MESSAGE_TYPE_STRING:
- result = new PluginResult(PluginResult.Status.OK, new String(bytes, encoding));
+ result = new PluginResult(PluginResult.Status.OK, os.toString(encoding));
break;
case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
- result = new PluginResult(PluginResult.Status.OK, bytes);
+ result = new PluginResult(PluginResult.Status.OK, os.toByteArray());
break;
case PluginResult.MESSAGE_TYPE_BINARYSTRING:
- result = new PluginResult(PluginResult.Status.OK, bytes, true);
+ result = new PluginResult(PluginResult.Status.OK, os.toByteArray(), true);
break;
default: // Base64.
- byte[] base64 = Base64.encode(bytes, Base64.NO_WRAP);
+ byte[] base64 = Base64.encode(os.toByteArray(), Base64.NO_WRAP);
String s = "data:" + contentType + ";base64," + new String(base64, "US-ASCII");
result = new PluginResult(PluginResult.Status.OK, s);
}
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/eaeb5981/src/android/Filesystem.java
----------------------------------------------------------------------
diff --git a/src/android/Filesystem.java b/src/android/Filesystem.java
index ba2c7bd..1f869c9 100644
--- a/src/android/Filesystem.java
+++ b/src/android/Filesystem.java
@@ -1,47 +1,174 @@
package org.apache.cordova.file;
import java.io.FileNotFoundException;
+import java.io.FilterInputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
-import org.apache.cordova.CordovaInterface;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-public interface Filesystem {
+public abstract class Filesystem {
- JSONObject getEntryForLocalURL(LocalFilesystemURL inputURL) throws IOException;
+ public interface ReadFileCallback {
+ public void handleData(InputStream inputStream, String contentType) throws IOException;
+ }
- JSONObject getFileForLocalURL(LocalFilesystemURL inputURL, String fileName,
- JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException;
+ public static JSONObject makeEntryForPath(String path, int fsType, Boolean isDir)
+ throws JSONException {
+ JSONObject entry = new JSONObject();
- boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException, NoModificationAllowedException;
+ int end = path.endsWith("/") ? 1 : 0;
+ String[] parts = path.substring(0,path.length()-end).split("/");
+ String name = parts[parts.length-1];
+ entry.put("isFile", !isDir);
+ entry.put("isDirectory", isDir);
+ entry.put("name", name);
+ entry.put("fullPath", path);
+ // The file system can't be specified, as it would lead to an infinite loop,
+ // but the filesystem type can
+ entry.put("filesystem", fsType);
- boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException, NoModificationAllowedException;
+ return entry;
- JSONArray readEntriesAtLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException;
+ }
- JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException;
+ public static JSONObject makeEntryForURL(LocalFilesystemURL inputURL, Boolean isDir) throws JSONException {
+ return makeEntryForPath(inputURL.fullPath, inputURL.filesystemType, isDir);
+ }
- JSONObject getParentForLocalURL(LocalFilesystemURL inputURL) throws IOException;
+ abstract JSONObject getEntryForLocalURL(LocalFilesystemURL inputURL) throws IOException;
- JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
- Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException;
+ abstract JSONObject getFileForLocalURL(LocalFilesystemURL inputURL, String fileName,
+ JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException;
- void readFileAtURL(LocalFilesystemURL inputURL, int start, int end,
+ abstract boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException, NoModificationAllowedException;
+
+ abstract boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException, NoModificationAllowedException;
+
+ abstract JSONArray readEntriesAtLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException;
+
+ abstract JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException;
+
+ public JSONObject getParentForLocalURL(LocalFilesystemURL inputURL) throws IOException {
+ LocalFilesystemURL newURL = new LocalFilesystemURL(inputURL.URL);
+
+ if (!("".equals(inputURL.fullPath) || "/".equals(inputURL.fullPath))) {
+ int end = inputURL.fullPath.endsWith("/") ? 1 : 0;
+ int lastPathStartsAt = inputURL.fullPath.lastIndexOf('/', inputURL.fullPath.length()-end)+1;
+ newURL.fullPath = newURL.fullPath.substring(0,lastPathStartsAt);
+ }
+ return getEntryForLocalURL(newURL);
+ }
+
+ protected LocalFilesystemURL makeDestinationURL(String newName, LocalFilesystemURL srcURL, LocalFilesystemURL destURL) {
+ // I know this looks weird but it is to work around a JSON bug.
+ if ("null".equals(newName) || "".equals(newName)) {
+ newName = srcURL.URL.getLastPathSegment();;
+ }
+
+ String newDest = destURL.URL.toString();
+ if (newDest.endsWith("/")) {
+ newDest = newDest + newName;
+ } else {
+ newDest = newDest + "/" + newName;
+ }
+ return new LocalFilesystemURL(newDest);
+ }
+
+ /* Read a source URL (possibly from a different filesystem, srcFs,) and copy it to
+ * the destination URL on this filesystem, optionally with a new filename.
+ * If move is true, then this method should either perform an atomic move operation
+ * or remove the source file when finished.
+ */
+ JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
+ Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException {
+ // This is "the hard way" -- transfer data between arbitrary filesystem urls/
+ // Gets an input stream from src, and writes its contents to an output stream
+ // from dest.
+
+ // First, check to see that we can do it
+ if (!move || srcFs.canRemoveFileAtLocalURL(srcURL)) {
+ final LocalFilesystemURL destination = makeDestinationURL(newName, srcURL, destURL);
+ srcFs.readFileAtURL(srcURL, 0, -1, new ReadFileCallback() {
+ public void handleData(InputStream inputStream, String contentType) throws IOException {
+ if (inputStream != null) {
+ //write data to file
+ OutputStream os = getOutputStreamForURL(destination);
+ final int BUFFER_SIZE = 8192;
+ byte[] buffer = new byte[BUFFER_SIZE];
+
+ for (;;) {
+ int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
+
+ if (bytesRead <= 0) {
+ break;
+ }
+ os.write(buffer, 0, bytesRead);
+ }
+ os.close();
+ } else {
+ throw new IOException("Cannot read file at source URL");
+ }
+ }
+ });
+ if (move) {
+ // Delete original
+ srcFs.removeFileAtLocalURL(srcURL);
+ }
+ return makeEntryForURL(destination, false);
+ } else {
+ throw new NoModificationAllowedException("Cannot move file at source URL");
+ }
+ }
+
+ abstract OutputStream getOutputStreamForURL(LocalFilesystemURL inputURL) throws IOException;
+
+ abstract void readFileAtURL(LocalFilesystemURL inputURL, long start, long end,
ReadFileCallback readFileCallback) throws IOException;
- long writeToFileAtURL(LocalFilesystemURL inputURL, String data, int offset,
+ abstract long writeToFileAtURL(LocalFilesystemURL inputURL, String data, int offset,
boolean isBinary) throws NoModificationAllowedException, IOException;
- long truncateFileAtURL(LocalFilesystemURL inputURL, long size)
+ abstract long truncateFileAtURL(LocalFilesystemURL inputURL, long size)
throws IOException, NoModificationAllowedException;
// This method should return null if filesystem urls cannot be mapped to paths
- String filesystemPathForURL(LocalFilesystemURL url);
-
- LocalFilesystemURL URLforFilesystemPath(String path);
-
- boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL);
+ abstract String filesystemPathForURL(LocalFilesystemURL url);
+
+ abstract LocalFilesystemURL URLforFilesystemPath(String path);
+
+ abstract boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL);
+
+ protected class LimitedInputStream extends FilterInputStream {
+ long numBytesToRead;
+ public LimitedInputStream(InputStream in, long numBytesToRead) {
+ super(in);
+ this.numBytesToRead = numBytesToRead;
+ }
+ @Override
+ public int read() throws IOException {
+ if (numBytesToRead <= 0) {
+ return -1;
+ }
+ numBytesToRead--;
+ return in.read();
+ }
+ @Override
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+ if (numBytesToRead <= 0) {
+ return -1;
+ }
+ int bytesToRead = byteCount;
+ if (byteCount > numBytesToRead) {
+ bytesToRead = (int)numBytesToRead; // Cast okay; long is less than int here.
+ }
+ int numBytesRead = in.read(buffer, byteOffset, bytesToRead);
+ numBytesToRead -= numBytesRead;
+ return numBytesRead;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/eaeb5981/src/android/LocalFilesystem.java
----------------------------------------------------------------------
diff --git a/src/android/LocalFilesystem.java b/src/android/LocalFilesystem.java
index 6c16e45..f0d919f 100644
--- a/src/android/LocalFilesystem.java
+++ b/src/android/LocalFilesystem.java
@@ -7,6 +7,7 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
@@ -18,7 +19,7 @@ import org.json.JSONObject;
import android.util.Base64;
import android.net.Uri;
-public class LocalFilesystem implements Filesystem {
+public class LocalFilesystem extends Filesystem {
private String name;
private String fsRoot;
@@ -55,24 +56,6 @@ public class LocalFilesystem implements Filesystem {
return null;
}
- public static JSONObject makeEntryForPath(String path, int fsType, Boolean isDir) throws JSONException {
- JSONObject entry = new JSONObject();
-
- int end = path.endsWith("/") ? 1 : 0;
- String[] parts = path.substring(0,path.length()-end).split("/");
- String name = parts[parts.length-1];
- entry.put("isFile", !isDir);
- entry.put("isDirectory", isDir);
- entry.put("name", name);
- entry.put("fullPath", path);
- // The file system can't be specified, as it would lead to an infinite loop,
- // but the filesystem type can
- entry.put("filesystem", fsType);
-
- return entry;
-
- }
-
public JSONObject makeEntryForFile(File file, int fsType) throws JSONException {
String path = this.fullPathForFilesystemPath(file.getAbsolutePath());
if (path != null) {
@@ -240,18 +223,6 @@ public class LocalFilesystem implements Filesystem {
return metadata;
}
- @Override
- public JSONObject getParentForLocalURL(LocalFilesystemURL inputURL) throws IOException {
- LocalFilesystemURL newURL = new LocalFilesystemURL(inputURL.URL);
-
- if (!("".equals(inputURL.fullPath) || "/".equals(inputURL.fullPath))) {
- int end = inputURL.fullPath.endsWith("/") ? 1 : 0;
- int lastPathStartsAt = inputURL.fullPath.lastIndexOf('/', inputURL.fullPath.length()-end)+1;
- newURL.fullPath = newURL.fullPath.substring(0,lastPathStartsAt);
- }
- return getEntryForLocalURL(newURL);
- }
-
/**
* 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.
@@ -272,31 +243,6 @@ public class LocalFilesystem implements Filesystem {
return false;
}
-
- /**
- * Creates the destination File object based on name passed in
- *
- * @param newName for the file directory to be called, if null use existing file name
- * @param fp represents the source file
- * @param destination represents the destination file
- * @return a File object that represents the destination
- */
- private File createDestination(String newName, String oldName, File destination) {
- File destFile = null;
-
- // I know this looks weird but it is to work around a JSON bug.
- if ("null".equals(newName) || "".equals(newName)) {
- newName = null;
- }
-
- if (newName != null) {
- destFile = new File(destination.getAbsolutePath() + File.separator + newName);
- } else {
- destFile = new File(destination.getAbsolutePath() + File.separator + oldName);
- }
- return destFile;
- }
-
/**
* Copy a file
*
@@ -473,92 +419,71 @@ public class LocalFilesystem implements Filesystem {
throw new FileNotFoundException("The source does not exist");
}
- // Figure out where we should be copying to
- String originalName = srcURL.URL.getLastPathSegment();
- final File destination = createDestination(newName, originalName, destinationDir);
-
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 = this.filesystemPathForURL(srcURL);
- File source = new File(srcFilesystemPath);
+ File sourceFile = new File(srcFilesystemPath);
+ String destFilesystemPath = this.filesystemPathForURL(destinationURL);
+ File destinationFile = new File(destFilesystemPath);
- if (!source.exists()) {
+ 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 (source.getAbsolutePath().equals(destination.getAbsolutePath())) {
+ if (sourceFile.getAbsolutePath().equals(destinationFile.getAbsolutePath())) {
throw new InvalidModificationException("Can't copy a file onto itself");
}
- if (source.isDirectory()) {
+ if (sourceFile.isDirectory()) {
if (move) {
- return moveDirectory(source, destination, destURL.filesystemType);
+ return moveDirectory(sourceFile, destinationFile, destURL.filesystemType);
} else {
- return copyDirectory(source, destination, destURL.filesystemType);
+ return copyDirectory(sourceFile, destinationFile, destURL.filesystemType);
}
} else {
if (move) {
- return moveFile(source, destination, destURL.filesystemType);
+ return moveFile(sourceFile, destinationFile, destURL.filesystemType);
} else {
- return copyFile(source, destination, destURL.filesystemType);
+ return copyFile(sourceFile, destinationFile, destURL.filesystemType);
}
}
} else {
// Need to copy the hard way
- // First, check to see that we can do it
- if (!move || srcFs.canRemoveFileAtLocalURL(srcURL)) {
- srcFs.readFileAtURL(srcURL, 0, -1, new ReadFileCallback() {
- public void handleData(byte[] data, String contentType) throws IOException {
- if (data != null) {
- //write data to file
- FileOutputStream os = new FileOutputStream(destination);
- os.write(data);
- os.close();
- } else {
- throw new IOException("Cannot read file at source URL");
- }
- }
- });
- if (move) {
- // Delete original
- srcFs.removeFileAtLocalURL(srcURL);
- }
- return makeEntryForFile(destination, destURL.filesystemType);
- } else {
- throw new NoModificationAllowedException("Cannot move file at source URL");
- }
+ return super.copyFileToURL(destURL, newName, srcFs, srcURL, move);
}
}
@Override
- public void readFileAtURL(LocalFilesystemURL inputURL, int start, int end,
+ public void readFileAtURL(LocalFilesystemURL inputURL, long start, long end,
ReadFileCallback readFileCallback) throws IOException {
- int numBytesToRead = end - start;
- byte[] bytes = new byte[numBytesToRead];
- String contentType;
-
File file = new File(this.filesystemPathForURL(inputURL));
- contentType = FileHelper.getMimeTypeForExtension(file.getAbsolutePath());
+ String contentType = FileHelper.getMimeTypeForExtension(file.getAbsolutePath());
- InputStream inputStream = new FileInputStream(file);
- int numBytesRead = 0;
+ if (end < 0) {
+ end = file.length();
+ }
+ long numBytesToRead = end - start;
+
+ InputStream rawInputStream = new FileInputStream(file);
try {
if (start > 0) {
- inputStream.skip(start);
- }
- while (numBytesToRead > 0 && (numBytesRead = inputStream.read(bytes, numBytesRead, numBytesToRead)) >= 0) {
- numBytesToRead -= numBytesRead;
+ rawInputStream.skip(start);
}
+ LimitedInputStream inputStream = new LimitedInputStream(rawInputStream, numBytesToRead);
+ readFileCallback.handleData(inputStream, contentType);
} finally {
- inputStream.close();
+ rawInputStream.close();
}
- readFileCallback.handleData(bytes, contentType);
}
-
+
@Override
public long writeToFileAtURL(LocalFilesystemURL inputURL, String data,
int offset, boolean isBinary) throws IOException, NoModificationAllowedException {
@@ -630,4 +555,12 @@ public class LocalFilesystem implements Filesystem {
return file.exists();
}
+ @Override
+ OutputStream getOutputStreamForURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
+ String path = filesystemPathForURL(inputURL);
+ File file = new File(path);
+ FileOutputStream os = new FileOutputStream(file);
+ return os;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/eaeb5981/src/android/LocalFilesystemURL.java
----------------------------------------------------------------------
diff --git a/src/android/LocalFilesystemURL.java b/src/android/LocalFilesystemURL.java
index 0dc547e..1065382 100644
--- a/src/android/LocalFilesystemURL.java
+++ b/src/android/LocalFilesystemURL.java
@@ -24,8 +24,8 @@ public class LocalFilesystemURL {
if (fsType == FileUtils.PERSISTENT) {
return URL.getPath().substring(11);
}
- if (fsType == FileUtils.APPLICATION) {
- return URL.getPath();
+ if (fsType == FileUtils.CONTENT) {
+ return '/' + URL.getHost() + URL.getPath();
}
return null;
}
@@ -41,7 +41,7 @@ public class LocalFilesystemURL {
}
}
} else if ("content".equals(URL.getScheme())) {
- return FileUtils.APPLICATION;
+ return FileUtils.CONTENT;
}
return -1;
}
@@ -50,5 +50,4 @@ public class LocalFilesystemURL {
this(Uri.parse(strURL));
}
-
}
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/eaeb5981/src/android/ReadFileCallback.java
----------------------------------------------------------------------
diff --git a/src/android/ReadFileCallback.java b/src/android/ReadFileCallback.java
deleted file mode 100644
index b8ba02d..0000000
--- a/src/android/ReadFileCallback.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.apache.cordova.file;
-
-import java.io.IOException;
-
-public interface ReadFileCallback {
- public void handleData(byte[] data, String contentType) throws IOException;
-}