1b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey/* 2b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * Copyright (C) 2013 The Android Open Source Project 3b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * 4b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * you may not use this file except in compliance with the License. 6b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * You may obtain a copy of the License at 7b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * 8b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * 10b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * Unless required by applicable law or agreed to in writing, software 11b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * See the License for the specific language governing permissions and 14b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * limitations under the License. 15b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey */ 16b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 17b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeypackage android.support.v4.content; 18b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 19b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeyimport static android.provider.OpenableColumns.DISPLAY_NAME; 20b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeyimport static android.provider.OpenableColumns.SIZE; 21b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 224c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikasimport static org.junit.Assert.assertEquals; 234c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikasimport static org.junit.Assert.fail; 244c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas 25b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeyimport android.content.ContentResolver; 264c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikasimport android.content.Context; 27b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeyimport android.database.Cursor; 28b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeyimport android.net.Uri; 29b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeyimport android.os.Environment; 304c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikasimport android.support.test.InstrumentationRegistry; 31754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport android.support.test.filters.SmallTest; 324c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikasimport android.support.test.runner.AndroidJUnit4; 33b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeyimport android.support.v4.content.FileProvider.SimplePathStrategy; 34b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeyimport android.test.MoreAsserts; 354c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas 364c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikasimport org.junit.Before; 374c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikasimport org.junit.Test; 384c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikasimport org.junit.runner.RunWith; 392cb3bffdfbe47f5657821e5a12da9aab16b85c52Jeff Sharkey 40120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viveretteimport java.io.ByteArrayOutputStream; 41b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeyimport java.io.File; 42b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeyimport java.io.FileNotFoundException; 43b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeyimport java.io.FileOutputStream; 44120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viveretteimport java.io.IOException; 45b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeyimport java.io.InputStream; 46b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkeyimport java.io.OutputStream; 47b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 48b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey/** 49b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey * Tests for {@link FileProvider} 50b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey */ 514c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas@SmallTest 524c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas@RunWith(AndroidJUnit4.class) 534c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikaspublic class FileProviderTest { 54b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey private static final String TEST_AUTHORITY = "moocow"; 55b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 56b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey private static final String TEST_FILE = "file.test"; 57b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey private static final byte[] TEST_DATA = new byte[] { (byte) 0xf0, 0x00, 0x0d }; 58b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey private static final byte[] TEST_DATA_ALT = new byte[] { (byte) 0x33, 0x66 }; 59b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 60b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey private ContentResolver mResolver; 614c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas private Context mContext; 62b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 634c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Before 644c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas public void setup() throws Exception { 654c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas mContext = InstrumentationRegistry.getTargetContext(); 664c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas mResolver = mContext.getContentResolver(); 67b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 68b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 694c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 70b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testStrategyUriSimple() throws Exception { 71b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final SimplePathStrategy strat = new SimplePathStrategy("authority"); 72b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.addRoot("tag", mContext.getFilesDir()); 73b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 74b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey File file = buildPath(mContext.getFilesDir(), "file.test"); 75b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals("content://authority/tag/file.test", 76b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.getUriForFile(file).toString()); 77b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 78b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey file = buildPath(mContext.getFilesDir(), "subdir", "file.test"); 79b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals("content://authority/tag/subdir/file.test", 80b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.getUriForFile(file).toString()); 81b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 82b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey file = buildPath(Environment.getExternalStorageDirectory(), "file.test"); 83b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey try { 84b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.getUriForFile(file); 85b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey fail("somehow got uri for file outside roots?"); 86b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } catch (IllegalArgumentException e) { 87b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 88b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 89b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 904c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 91b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testStrategyUriJumpOutside() throws Exception { 92b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final SimplePathStrategy strat = new SimplePathStrategy("authority"); 93b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.addRoot("tag", mContext.getFilesDir()); 94b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 95b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey File file = buildPath(mContext.getFilesDir(), "..", "file.test"); 96b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey try { 97b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.getUriForFile(file); 98b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey fail("file escaped!"); 99b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } catch (IllegalArgumentException e) { 100b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 101b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 102b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 1034c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 104b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testStrategyUriShortestRoot() throws Exception { 105b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey SimplePathStrategy strat = new SimplePathStrategy("authority"); 106b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.addRoot("tag1", mContext.getFilesDir()); 107b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.addRoot("tag2", new File("/")); 108b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 109b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey File file = buildPath(mContext.getFilesDir(), "file.test"); 110b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals("content://authority/tag1/file.test", 111b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.getUriForFile(file).toString()); 112b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 113b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat = new SimplePathStrategy("authority"); 114b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.addRoot("tag1", new File("/")); 115b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.addRoot("tag2", mContext.getFilesDir()); 116b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 117b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey file = buildPath(mContext.getFilesDir(), "file.test"); 118b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals("content://authority/tag2/file.test", 119b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.getUriForFile(file).toString()); 120b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 121b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 1224c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 123b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testStrategyFileSimple() throws Exception { 124b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final SimplePathStrategy strat = new SimplePathStrategy("authority"); 125b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.addRoot("tag", mContext.getFilesDir()); 126b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 1272002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette File expectedRoot = mContext.getFilesDir().getCanonicalFile(); 1282002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette File file = buildPath(expectedRoot, "file.test"); 129b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(file.getPath(), 130b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.getFileForUri(Uri.parse("content://authority/tag/file.test")).getPath()); 131b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 1322002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette file = buildPath(expectedRoot, "subdir", "file.test"); 133b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(file.getPath(), strat.getFileForUri( 134b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey Uri.parse("content://authority/tag/subdir/file.test")).getPath()); 135b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 136b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 1374c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 138b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testStrategyFileJumpOutside() throws Exception { 139b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final SimplePathStrategy strat = new SimplePathStrategy("authority"); 140b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.addRoot("tag", mContext.getFilesDir()); 141b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 142b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey try { 143b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.getFileForUri(Uri.parse("content://authority/tag/../file.test")); 144b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey fail("file escaped!"); 145b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } catch (SecurityException e) { 146b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 147b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 148b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 1494c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 150b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testStrategyEscaping() throws Exception { 151b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final SimplePathStrategy strat = new SimplePathStrategy("authority"); 152b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.addRoot("t/g", mContext.getFilesDir()); 153b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 1542002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette File expectedRoot = mContext.getFilesDir().getCanonicalFile(); 1552002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette File file = buildPath(expectedRoot, "lol\"wat?foo&bar", "wat.txt"); 156b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final String expected = "content://authority/t%2Fg/lol%22wat%3Ffoo%26bar/wat.txt"; 157b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 158b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(expected, 159b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.getUriForFile(file).toString()); 160b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(file.getPath(), 161b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.getFileForUri(Uri.parse(expected)).getPath()); 162b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 163b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 1644c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 165b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testStrategyExtraParams() throws Exception { 166b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final SimplePathStrategy strat = new SimplePathStrategy("authority"); 167b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.addRoot("tag", mContext.getFilesDir()); 168b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 1692002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette File expectedRoot = mContext.getFilesDir().getCanonicalFile(); 1702002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette File file = buildPath(expectedRoot, "file.txt"); 171b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(file.getPath(), strat.getFileForUri( 172b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey Uri.parse("content://authority/tag/file.txt?extra=foo")).getPath()); 173b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 174b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 1754c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 176b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testStrategyExtraSeparators() throws Exception { 177b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final SimplePathStrategy strat = new SimplePathStrategy("authority"); 178b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.addRoot("tag", mContext.getFilesDir()); 179b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 180b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey // When canonicalized, the path separators are trimmed 181b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey File inFile = new File(mContext.getFilesDir(), "//foo//bar//"); 1822002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette File expectedRoot = mContext.getFilesDir().getCanonicalFile(); 1832002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette File outFile = new File(expectedRoot, "/foo/bar"); 184b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final String expected = "content://authority/tag/foo/bar"; 185b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 186b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(expected, 187b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.getUriForFile(inFile).toString()); 188b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(outFile.getPath(), 189b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey strat.getFileForUri(Uri.parse(expected)).getPath()); 190b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 191b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 1924c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 193b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testQueryProjectionNull() throws Exception { 194b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final File file = new File(mContext.getFilesDir(), TEST_FILE); 195b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final Uri uri = stageFileAndGetUri(file, TEST_DATA); 196b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 197b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey // Verify that null brings out default columns 198b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey Cursor cursor = mResolver.query(uri, null, null, null, null); 199b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey try { 200b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(1, cursor.getCount()); 201b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey cursor.moveToFirst(); 202b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(TEST_FILE, cursor.getString(cursor.getColumnIndex(DISPLAY_NAME))); 203b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(TEST_DATA.length, cursor.getLong(cursor.getColumnIndex(SIZE))); 204b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } finally { 205b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey cursor.close(); 206b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 207b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 208b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 2094c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 210b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testQueryProjectionOrder() throws Exception { 211b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final File file = new File(mContext.getFilesDir(), TEST_FILE); 212b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final Uri uri = stageFileAndGetUri(file, TEST_DATA); 213b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 214b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey // Verify that swapped order works 215b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey Cursor cursor = mResolver.query(uri, new String[] { 216b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey SIZE, DISPLAY_NAME }, null, null, null); 217b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey try { 218b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(1, cursor.getCount()); 219b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey cursor.moveToFirst(); 220b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(TEST_DATA.length, cursor.getLong(0)); 221b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(TEST_FILE, cursor.getString(1)); 222b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } finally { 223b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey cursor.close(); 224b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 225b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 226b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey cursor = mResolver.query(uri, new String[] { 227b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey DISPLAY_NAME, SIZE }, null, null, null); 228b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey try { 229b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(1, cursor.getCount()); 230b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey cursor.moveToFirst(); 231b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(TEST_FILE, cursor.getString(0)); 232b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(TEST_DATA.length, cursor.getLong(1)); 233b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } finally { 234b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey cursor.close(); 235b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 236b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 237b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 2384c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 239b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testQueryExtraColumn() throws Exception { 240b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final File file = new File(mContext.getFilesDir(), TEST_FILE); 241b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final Uri uri = stageFileAndGetUri(file, TEST_DATA); 242b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 243b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey // Verify that extra column doesn't gook things up 244b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey Cursor cursor = mResolver.query(uri, new String[] { 245b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey SIZE, "foobar", DISPLAY_NAME }, null, null, null); 246b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey try { 247b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(1, cursor.getCount()); 248b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey cursor.moveToFirst(); 249b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(TEST_DATA.length, cursor.getLong(0)); 250b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(TEST_FILE, cursor.getString(1)); 251b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } finally { 252b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey cursor.close(); 253b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 254b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 255b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 2564c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 257b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testReadFile() throws Exception { 258b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final File file = new File(mContext.getFilesDir(), TEST_FILE); 259b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final Uri uri = stageFileAndGetUri(file, TEST_DATA); 260b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 261b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertContentsEquals(TEST_DATA, uri); 262b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 263b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 2644c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 265b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testWriteFile() throws Exception { 266b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final File file = new File(mContext.getFilesDir(), TEST_FILE); 267b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final Uri uri = stageFileAndGetUri(file, TEST_DATA); 268b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 269b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertContentsEquals(TEST_DATA, uri); 270b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 271b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final OutputStream out = mResolver.openOutputStream(uri); 272b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey try { 273b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey out.write(TEST_DATA_ALT); 274b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } finally { 275120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette closeQuietly(out); 276b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 277b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 278b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertContentsEquals(TEST_DATA_ALT, uri); 279b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 280b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 2814c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 282b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testWriteMissingFile() throws Exception { 283b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final File file = new File(mContext.getFilesDir(), TEST_FILE); 284b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final Uri uri = stageFileAndGetUri(file, null); 285b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 286b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey try { 287b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertContentsEquals(new byte[0], uri); 288b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey fail("Somehow read missing file?"); 289b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } catch(FileNotFoundException e) { 290b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 291b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 292b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final OutputStream out = mResolver.openOutputStream(uri); 293b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey try { 294b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey out.write(TEST_DATA_ALT); 295b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } finally { 296120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette closeQuietly(out); 297b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 298b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 299b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertContentsEquals(TEST_DATA_ALT, uri); 300b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 301b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 3024c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 303b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testDelete() throws Exception { 304b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final File file = new File(mContext.getFilesDir(), TEST_FILE); 305b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final Uri uri = stageFileAndGetUri(file, TEST_DATA); 306b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 307b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertContentsEquals(TEST_DATA, uri); 308b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 309b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(1, mResolver.delete(uri, null, null)); 310b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals(0, mResolver.delete(uri, null, null)); 311b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 312b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey try { 313b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertContentsEquals(new byte[0], uri); 314b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey fail("Somehow read missing file?"); 315b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } catch(FileNotFoundException e) { 316b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 317b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 318b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 3194c0cac8cbf22f47465eec7a75d723fa0e0ebf1dcAurimas Liutikas @Test 320b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey public void testMetaDataTargets() { 321b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey Uri actual; 322b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 323b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey actual = FileProvider.getUriForFile(mContext, TEST_AUTHORITY, 324b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey new File("/proc/version")); 325b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals("content://moocow/test_root/proc/version", actual.toString()); 326b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 327b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey actual = FileProvider.getUriForFile(mContext, TEST_AUTHORITY, 328b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey new File("/proc/1/mountinfo")); 329b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals("content://moocow/test_init/mountinfo", actual.toString()); 330b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 331b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey actual = FileProvider.getUriForFile(mContext, TEST_AUTHORITY, 332b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey buildPath(mContext.getFilesDir(), "meow")); 333b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals("content://moocow/test_files/meow", actual.toString()); 334b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 335b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey actual = FileProvider.getUriForFile(mContext, TEST_AUTHORITY, 336b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey buildPath(mContext.getFilesDir(), "thumbs", "rawr")); 337b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals("content://moocow/test_thumbs/rawr", actual.toString()); 338b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 339b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey actual = FileProvider.getUriForFile(mContext, TEST_AUTHORITY, 340b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey buildPath(mContext.getCacheDir(), "up", "down")); 341b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals("content://moocow/test_cache/up/down", actual.toString()); 342b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 343b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey actual = FileProvider.getUriForFile(mContext, TEST_AUTHORITY, 344b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey buildPath(Environment.getExternalStorageDirectory(), "Android", "obb", "foobar")); 345b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey assertEquals("content://moocow/test_external/Android/obb/foobar", actual.toString()); 3462002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette 3472002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette File[] externalFilesDirs = ContextCompat.getExternalFilesDirs(mContext, null); 3482002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette actual = FileProvider.getUriForFile(mContext, TEST_AUTHORITY, 3492002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette buildPath(externalFilesDirs[0], "foo", "bar")); 3502002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette assertEquals("content://moocow/test_external_files/foo/bar", actual.toString()); 3512002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette 3522002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette File[] externalCacheDirs = ContextCompat.getExternalCacheDirs(mContext); 3532002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette actual = FileProvider.getUriForFile(mContext, TEST_AUTHORITY, 3542002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette buildPath(externalCacheDirs[0], "foo", "bar")); 3552002bed7d4769fc985b7a8e8b5ba875ffc7e829aAlan Viverette assertEquals("content://moocow/test_external_cache/foo/bar", actual.toString()); 356b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 357b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 358b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey private void assertContentsEquals(byte[] expected, Uri actual) throws Exception { 359b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final InputStream in = mResolver.openInputStream(actual); 360b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey try { 361120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette MoreAsserts.assertEquals(expected, readFully(in)); 362b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } finally { 363120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette closeQuietly(in); 364b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 365b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 366b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 367b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey private Uri stageFileAndGetUri(File file, byte[] data) throws Exception { 368b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey if (data != null) { 369b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey final FileOutputStream out = new FileOutputStream(file); 370b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey try { 371b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey out.write(data); 372b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } finally { 373b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey out.close(); 374b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 375b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } else { 376b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey file.delete(); 377b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 378b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey return FileProvider.getUriForFile(mContext, TEST_AUTHORITY, file); 379b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 380b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey 381b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey private static File buildPath(File base, String... segments) { 382b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey File cur = base; 383b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey for (String segment : segments) { 384b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey if (cur == null) { 385b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey cur = new File(segment); 386b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } else { 387b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey cur = new File(cur, segment); 388b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 389b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 390b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey return cur; 391b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey } 392120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette 393120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette /** 394120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null. 395120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette */ 396120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette private static void closeQuietly(AutoCloseable closeable) { 397120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette if (closeable != null) { 398120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette try { 399120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette closeable.close(); 400120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } catch (RuntimeException rethrown) { 401120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette throw rethrown; 402120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } catch (Exception ignored) { 403120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } 404120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } 405120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } 406120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette 407120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette /** 408120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette * Returns a byte[] containing the remainder of 'in', closing it when done. 409120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette */ 410120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette private static byte[] readFully(InputStream in) throws IOException { 411120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette try { 412120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette return readFullyNoClose(in); 413120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } finally { 414120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette in.close(); 415120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } 416120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } 417120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette 418120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette /** 419120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette * Returns a byte[] containing the remainder of 'in'. 420120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette */ 421120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette private static byte[] readFullyNoClose(InputStream in) throws IOException { 422120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 423120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette byte[] buffer = new byte[1024]; 424120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette int count; 425120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette while ((count = in.read(buffer)) != -1) { 426120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette bytes.write(buffer, 0, count); 427120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } 428120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette return bytes.toByteArray(); 429120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } 430b49cb25e1450ae36d2559e9753c6d5064e530fccJeff Sharkey} 431