From 43bf47ea7b44fc06d62eaef715eede581a9b0682 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Wed, 10 Jul 2013 15:11:23 -0400 Subject: [PATCH] [CB-3384] Add a length getter for UriResolver. Change from interface -> abstract class. Thinking here is that we can maintain compatibility going forward with a base class as opposed to interface by having new methods on it have default implementations. (cherry picked from commit 990d91360d64324ba332e821fe512d712d7d5521) --- .../src/org/apache/cordova/UriResolver.java | 41 ++++++----- .../src/org/apache/cordova/UriResolvers.java | 68 ++++++++++++++++--- 2 files changed, 82 insertions(+), 27 deletions(-) diff --git a/framework/src/org/apache/cordova/UriResolver.java b/framework/src/org/apache/cordova/UriResolver.java index 8341b189..b3bfa4d4 100644 --- a/framework/src/org/apache/cordova/UriResolver.java +++ b/framework/src/org/apache/cordova/UriResolver.java @@ -23,40 +23,47 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import android.net.Uri; - /* * Interface for a class that can resolve URIs. * See CordovaUriResolver for an example. */ -public interface UriResolver { +public abstract class UriResolver { /** * Returns the InputStream for the resource. * Throws an exception if it cannot be read. * Never returns null. */ - InputStream getInputStream() throws IOException; + public abstract InputStream getInputStream() throws IOException; + + /** + * Returns the MIME type of the resource. + * Returns null if the MIME type cannot be determined (e.g. content: that doesn't exist). + */ + public abstract String getMimeType(); + + /** Returns whether the resource is writable. */ + public abstract boolean isWritable(); + + /** + * Returns a File that points to the resource, or null if the resource + * is not on the local file system. + */ + public abstract File getLocalFile(); /** * Returns the OutputStream for the resource. * Throws an exception if it cannot be written to. * Never returns null. */ - OutputStream getOutputStream() throws IOException; + public OutputStream getOutputStream() throws IOException { + throw new IOException("Writing is not suppported"); + } - /** - * Returns the MIME type of the resource. - * Returns null if the MIME type cannot be determined (e.g. content: that doesn't exist). - */ - String getMimeType(); - - /** Returns whether the resource is writable. */ - boolean isWritable(); - /** - * Returns a File that points to the resource, or null if the resource - * is not on the local file system. + * Returns the length of the input stream, or -1 if it is not computable. */ - File getLocalFile(); + public long computeLength() throws IOException { + return -1; + } } diff --git a/framework/src/org/apache/cordova/UriResolvers.java b/framework/src/org/apache/cordova/UriResolvers.java index dcb50016..294fc6bf 100644 --- a/framework/src/org/apache/cordova/UriResolvers.java +++ b/framework/src/org/apache/cordova/UriResolvers.java @@ -44,19 +44,38 @@ public final class UriResolvers { private UriResolvers() {} - private static final class FileUriResolver implements UriResolver { + private static long computeSizeFromResolver(UriResolver resolver) throws IOException { + InputStream inputStream = resolver.getInputStream(); + if (inputStream instanceof FileInputStream) { + return ((FileInputStream)inputStream).getChannel().size(); + } + if (inputStream instanceof ByteArrayInputStream) { + return ((ByteArrayInputStream)inputStream).available(); + } + return -1; + } + + private static final class FileUriResolver extends UriResolver { private final File localFile; private String mimeType; + private FileInputStream cachedInputStream; FileUriResolver(Uri uri) { localFile = new File(uri.getPath()); } public InputStream getInputStream() throws IOException { - return new FileInputStream(localFile); + if (cachedInputStream == null) { + cachedInputStream = new FileInputStream(localFile); + } + return cachedInputStream; } public OutputStream getOutputStream() throws FileNotFoundException { + File parent = localFile.getParentFile(); + if (parent != null) { + localFile.getParentFile().mkdirs(); + } return new FileOutputStream(localFile); } @@ -80,12 +99,17 @@ public final class UriResolvers { public File getLocalFile() { return localFile; } + + public long computeLength() throws IOException { + return localFile.length(); + } } - private static final class AssetUriResolver implements UriResolver { + private static final class AssetUriResolver extends UriResolver { private final AssetManager assetManager; private final String assetPath; private String mimeType; + private InputStream cachedInputStream; AssetUriResolver(Uri uri, AssetManager assetManager) { this.assetManager = assetManager; @@ -93,7 +117,10 @@ public final class UriResolvers { } public InputStream getInputStream() throws IOException { - return assetManager.open(assetPath); + if (cachedInputStream == null) { + cachedInputStream = assetManager.open(assetPath); + } + return cachedInputStream; } public OutputStream getOutputStream() throws FileNotFoundException { @@ -114,12 +141,17 @@ public final class UriResolvers { public File getLocalFile() { return null; } + + public long computeLength() throws IOException { + return computeSizeFromResolver(this); + } } - private static final class ContentUriResolver implements UriResolver { + private static final class ContentUriResolver extends UriResolver { private final Uri uri; private final ContentResolver contentResolver; private String mimeType; + private InputStream cachedInputStream; ContentUriResolver(Uri uri, ContentResolver contentResolver) { this.uri = uri; @@ -127,7 +159,10 @@ public final class UriResolvers { } public InputStream getInputStream() throws IOException { - return contentResolver.openInputStream(uri); + if (cachedInputStream == null) { + cachedInputStream = contentResolver.openInputStream(uri); + } + return cachedInputStream; } public OutputStream getOutputStream() throws FileNotFoundException { @@ -148,9 +183,13 @@ public final class UriResolvers { public File getLocalFile() { return null; } + + public long computeLength() throws IOException { + return computeSizeFromResolver(this); + } } - private static final class ErrorUriResolver implements UriResolver { + private static final class ErrorUriResolver extends UriResolver { final String errorMsg; ErrorUriResolver(String errorMsg) { @@ -178,7 +217,7 @@ public final class UriResolvers { } } - private static final class ReadOnlyResolver implements UriResolver { + private static final class ReadOnlyResolver extends UriResolver { private InputStream inputStream; private String mimeType; @@ -206,9 +245,13 @@ public final class UriResolvers { public InputStream getInputStream() throws IOException { return inputStream; } + + public long computeLength() throws IOException { + return computeSizeFromResolver(this); + } } - private static final class ThreadCheckingResolver implements UriResolver { + private static final class ThreadCheckingResolver extends UriResolver { final UriResolver delegate; ThreadCheckingResolver(UriResolver delegate) { @@ -250,6 +293,11 @@ public final class UriResolvers { checkThread(); return delegate.getInputStream(); } + + public long computeLength() throws IOException { + checkThread(); + return delegate.computeLength(); + } } public static UriResolver createInline(Uri uri, String response, String mimeType) { @@ -290,4 +338,4 @@ public final class UriResolvers { } return new ThreadCheckingResolver(resolver); } -} \ No newline at end of file +}