1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2009 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.provider; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.ContentProvider; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.ContentValues; 21476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Linimport android.content.Context; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.database.Cursor; 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.database.MatrixCursor; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.net.Uri; 25ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Linimport android.os.AsyncTask; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.Binder; 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.ParcelFileDescriptor; 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.provider.MediaStore.Images.ImageColumns; 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.util.Log; 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 316f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.app.GalleryApp; 32ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Linimport com.android.gallery3d.common.AsyncTaskUtil; 336f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.common.Utils; 346f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.data.DataManager; 356f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.data.MediaItem; 366f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.data.MediaObject; 376f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.data.Path; 386f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.picasasource.PicasaSource; 396f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.util.GalleryUtils; 406f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.FileNotFoundException; 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.IOException; 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class GalleryProvider extends ContentProvider { 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "GalleryProvider"; 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 47cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen public static final String AUTHORITY = "com.android.gallery3d.provider"; 48cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen public static final Uri BASE_URI = Uri.parse("content://" + AUTHORITY); 496f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin 506f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin public static interface PicasaColumns { 516f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin public static final String USER_ACCOUNT = "user_account"; 526f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin public static final String PICASA_ID = "picasa_id"; 536f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin } 546f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin 55cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen private static final String[] SUPPORTED_PICASA_COLUMNS = { 566f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin PicasaColumns.USER_ACCOUNT, 576f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin PicasaColumns.PICASA_ID, 58cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen ImageColumns.DISPLAY_NAME, 59cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen ImageColumns.SIZE, 60cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen ImageColumns.MIME_TYPE, 61cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen ImageColumns.DATE_TAKEN, 62cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen ImageColumns.LATITUDE, 63cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen ImageColumns.LONGITUDE, 64cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen ImageColumns.ORIENTATION}; 65cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private DataManager mDataManager; 67476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin private static Uri sBaseUri; 68476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin 69476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin public static String getAuthority(Context context) { 70476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin return context.getPackageName() + ".provider"; 71476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin } 72476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin 73476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin public static Uri getUriFor(Context context, Path path) { 74476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin if (sBaseUri == null) { 75476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin sBaseUri = Uri.parse("content://" + context.getPackageName() + ".provider"); 76476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin } 77476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin return sBaseUri.buildUpon() 78476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin .appendEncodedPath(path.toString().substring(1)) // ignore the leading '/' 79476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin .build(); 80476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin } 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int delete(Uri uri, String selection, String[] selectionArgs) { 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new UnsupportedOperationException(); 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // TODO: consider concurrent access 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public String getType(Uri uri) { 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long token = Binder.clearCallingIdentity(); 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Path path = Path.fromString(uri.getPath()); 93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaItem item = (MediaItem) mDataManager.getMediaObject(path); 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return item != null ? item.getMimeType() : null; 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } finally { 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Binder.restoreCallingIdentity(token); 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public Uri insert(Uri uri, ContentValues values) { 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new UnsupportedOperationException(); 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean onCreate() { 107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GalleryApp app = (GalleryApp) getContext().getApplicationContext(); 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mDataManager = app.getDataManager(); 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return true; 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // TODO: consider concurrent access 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public Cursor query(Uri uri, String[] projection, 115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String selection, String[] selectionArgs, String sortOrder) { 116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long token = Binder.clearCallingIdentity(); 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Path path = Path.fromString(uri.getPath()); 119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaObject object = mDataManager.getMediaObject(path); 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (object == null) { 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, "cannot find: " + uri); 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (PicasaSource.isPicasaImage(object)) { 125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return queryPicasaItem(object, 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin projection, selection, selectionArgs, sortOrder); 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } finally { 131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Binder.restoreCallingIdentity(token); 132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Cursor queryPicasaItem(MediaObject image, String[] projection, 136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String selection, String[] selectionArgs, String sortOrder) { 137cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen if (projection == null) projection = SUPPORTED_PICASA_COLUMNS; 138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Object[] columnValues = new Object[projection.length]; 139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin double latitude = PicasaSource.getLatitude(image); 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin double longitude = PicasaSource.getLongitude(image); 141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin boolean isValidLatlong = GalleryUtils.isValidLocation(latitude, longitude); 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0, n = projection.length; i < n; ++i) { 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String column = projection[i]; 1456f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin if (PicasaColumns.USER_ACCOUNT.equals(column)) { 1466f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin columnValues[i] = PicasaSource.getUserAccount(getContext(), image); 1476f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin } else if (PicasaColumns.PICASA_ID.equals(column)) { 1486f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin columnValues[i] = PicasaSource.getPicasaId(image); 1496f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin } else if (ImageColumns.DISPLAY_NAME.equals(column)) { 150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin columnValues[i] = PicasaSource.getImageTitle(image); 151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else if (ImageColumns.SIZE.equals(column)){ 152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin columnValues[i] = PicasaSource.getImageSize(image); 153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else if (ImageColumns.MIME_TYPE.equals(column)) { 154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin columnValues[i] = PicasaSource.getContentType(image); 155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else if (ImageColumns.DATE_TAKEN.equals(column)) { 156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin columnValues[i] = PicasaSource.getDateTaken(image); 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else if (ImageColumns.LATITUDE.equals(column)) { 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin columnValues[i] = isValidLatlong ? latitude : null; 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else if (ImageColumns.LONGITUDE.equals(column)) { 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin columnValues[i] = isValidLatlong ? longitude : null; 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else if (ImageColumns.ORIENTATION.equals(column)) { 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin columnValues[i] = PicasaSource.getRotation(image); 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, "unsupported column: " + column); 165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MatrixCursor cursor = new MatrixCursor(projection); 168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin cursor.addRow(columnValues); 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return cursor; 170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public ParcelFileDescriptor openFile(Uri uri, String mode) 174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throws FileNotFoundException { 175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long token = Binder.clearCallingIdentity(); 176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mode.contains("w")) { 178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new FileNotFoundException("cannot open file for write"); 179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Path path = Path.fromString(uri.getPath()); 181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaObject object = mDataManager.getMediaObject(path); 182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (object == null) { 183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new FileNotFoundException(uri.toString()); 184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (PicasaSource.isPicasaImage(object)) { 186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return PicasaSource.openFile(getContext(), object, mode); 187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new FileNotFoundException("unspported type: " + object); 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } finally { 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Binder.restoreCallingIdentity(token); 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new UnsupportedOperationException(); 198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 200ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin private static interface PipeDataWriter<T> { 201ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin void writeDataToPipe(ParcelFileDescriptor output, T args); 202ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin } 203ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin 204ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin // Modified from ContentProvider.openPipeHelper. We are target at API LEVEL 10. 205ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin // But openPipeHelper is available in API LEVEL 11. 206ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin private static <T> ParcelFileDescriptor openPipeHelper( 207ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin final T args, final PipeDataWriter<T> func) throws FileNotFoundException { 208ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin try { 209ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); 210ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() { 211ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin @Override 212ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin protected Object doInBackground(Object... params) { 213ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin try { 214ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin func.writeDataToPipe(pipe[1], args); 215ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin return null; 216ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin } finally { 217ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin Utils.closeSilently(pipe[1]); 218ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin } 219ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin } 220ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin }; 221ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin AsyncTaskUtil.executeInParallel(task, (Object[]) null); 222ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin return pipe[0]; 223ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin } catch (IOException e) { 224ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin throw new FileNotFoundException("failure making pipe"); 225ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin } 226ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin } 227ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin 228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 229