cleaned up file handling

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/persistance/FileBackend.java           | 138 
src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java |   3 
src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java |  17 
3 files changed, 87 insertions(+), 71 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/persistance/FileBackend.java 🔗

@@ -1,6 +1,7 @@
 package eu.siacs.conversations.persistance;
 
 import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -42,8 +43,7 @@ public class FileBackend {
 
 	private static int IMAGE_SIZE = 1920;
 
-	private SimpleDateFormat imageDateFormat = new SimpleDateFormat(
-			"yyyyMMdd_HHmmssSSS", Locale.US);
+	private final SimpleDateFormat imageDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US);
 
 	private XmppConnectionService mXmppConnectionService;
 
@@ -110,9 +110,7 @@ public class FileBackend {
 				scalledW = size;
 				scalledH = (int) (h / ((double) w / size));
 			}
-			Bitmap scalledBitmap = Bitmap.createScaledBitmap(originalBitmap,
-					scalledW, scalledH, true);
-			return scalledBitmap;
+			return Bitmap.createScaledBitmap(originalBitmap, scalledW, scalledH, true);
 		} else {
 			return originalBitmap;
 		}
@@ -148,31 +146,34 @@ public class FileBackend {
 	}
 
 	public DownloadableFile copyFileToPrivateStorage(Message message, Uri uri) throws FileCopyException {
+		Log.d(Config.LOGTAG, "copy " + uri.toString() + " to private storage");
+		String mime = mXmppConnectionService.getContentResolver().getType(uri);
+		String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mime);
+		message.setRelativeFilePath(message.getUuid() + "." + extension);
+		DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message);
+		file.getParentFile().mkdirs();
+		OutputStream os = null;
+		InputStream is = null;
 		try {
-			Log.d(Config.LOGTAG, "copy " + uri.toString() + " to private storage");
-			String mime = mXmppConnectionService.getContentResolver().getType(uri);
-			String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mime);
-			message.setRelativeFilePath(message.getUuid() + "." + extension);
-			DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message);
-			file.getParentFile().mkdirs();
-			file.createNewFile();
-			OutputStream os = new FileOutputStream(file);
-			InputStream is = mXmppConnectionService.getContentResolver().openInputStream(uri);
+			if (!file.createNewFile()) {
+				throw new FileCopyException(R.string.error_io_exception);
+			}
+			os = new FileOutputStream(file);
+			is = mXmppConnectionService.getContentResolver().openInputStream(uri);
 			byte[] buffer = new byte[1024];
-            int length;
-            while ((length = is.read(buffer)) > 0) {
+			int length;
+			while ((length = is.read(buffer)) > 0) {
 				os.write(buffer, 0, length);
-            }
+			}
 			os.flush();
-			os.close();
-			is.close();
-			Log.d(Config.LOGTAG, "output file name " + mXmppConnectionService.getFileBackend().getFile(message));
-			return file;
-		} catch (FileNotFoundException e) {
-			throw new FileCopyException(R.string.error_file_not_found);
 		} catch (IOException e) {
 			throw new FileCopyException(R.string.error_io_exception);
+		} finally {
+			close(os);
+			close(is);
 		}
+		Log.d(Config.LOGTAG, "output file name " + mXmppConnectionService.getFileBackend().getFile(message));
+		return file;
 	}
 
 	public DownloadableFile copyImageToPrivateStorage(Message message, Uri image)
@@ -182,40 +183,41 @@ public class FileBackend {
 
 	private DownloadableFile copyImageToPrivateStorage(Message message,
 			Uri image, int sampleSize) throws FileCopyException {
+		DownloadableFile file = getFile(message);
+		file.getParentFile().mkdirs();
+		InputStream is = null;
+		OutputStream os = null;
 		try {
-			InputStream is = mXmppConnectionService.getContentResolver()
-					.openInputStream(image);
-			DownloadableFile file = getFile(message);
-			file.getParentFile().mkdirs();
-			file.createNewFile();
+			if (!file.createNewFile()) {
+				throw new FileCopyException(R.string.error_io_exception);
+			}
+			is = mXmppConnectionService.getContentResolver().openInputStream(image);
+			os = new FileOutputStream(file);
+
 			Bitmap originalBitmap;
 			BitmapFactory.Options options = new BitmapFactory.Options();
 			int inSampleSize = (int) Math.pow(2, sampleSize);
-			Log.d(Config.LOGTAG, "reading bitmap with sample size "
-					+ inSampleSize);
+			Log.d(Config.LOGTAG, "reading bitmap with sample size " + inSampleSize);
 			options.inSampleSize = inSampleSize;
 			originalBitmap = BitmapFactory.decodeStream(is, null, options);
 			is.close();
 			if (originalBitmap == null) {
 				throw new FileCopyException(R.string.error_not_an_image_file);
 			}
-			Bitmap scalledBitmap = resize(originalBitmap, IMAGE_SIZE);
-			originalBitmap = null;
+			Bitmap scaledBitmap = resize(originalBitmap, IMAGE_SIZE);
 			int rotation = getRotation(image);
 			if (rotation > 0) {
-				scalledBitmap = rotate(scalledBitmap, rotation);
+				scaledBitmap = rotate(scaledBitmap, rotation);
 			}
-			OutputStream os = new FileOutputStream(file);
-			boolean success = scalledBitmap.compress(
-					Bitmap.CompressFormat.WEBP, 75, os);
+
+			boolean success = scaledBitmap.compress(Bitmap.CompressFormat.WEBP, 75, os);
 			if (!success) {
 				throw new FileCopyException(R.string.error_compressing_image);
 			}
 			os.flush();
-			os.close();
 			long size = file.getSize();
-			int width = scalledBitmap.getWidth();
-			int height = scalledBitmap.getHeight();
+			int width = scaledBitmap.getWidth();
+			int height = scaledBitmap.getHeight();
 			message.setBody(Long.toString(size) + ',' + width + ',' + height);
 			return file;
 		} catch (FileNotFoundException e) {
@@ -223,8 +225,7 @@ public class FileBackend {
 		} catch (IOException e) {
 			throw new FileCopyException(R.string.error_io_exception);
 		} catch (SecurityException e) {
-			throw new FileCopyException(
-					R.string.error_security_exception_during_image_copy);
+			throw new FileCopyException(R.string.error_security_exception_during_image_copy);
 		} catch (OutOfMemoryError e) {
 			++sampleSize;
 			if (sampleSize <= 3) {
@@ -232,23 +233,24 @@ public class FileBackend {
 			} else {
 				throw new FileCopyException(R.string.error_out_of_memory);
 			}
+		} finally {
+			close(os);
+			close(is);
 		}
 	}
 
 	private int getRotation(Uri image) {
+		InputStream is = null;
 		try {
-			InputStream is = mXmppConnectionService.getContentResolver()
-					.openInputStream(image);
+			is = mXmppConnectionService.getContentResolver().openInputStream(image);
 			return ExifHelper.getOrientation(is);
 		} catch (FileNotFoundException e) {
 			return 0;
+		} finally {
+			close(is);
 		}
 	}
 
-	public Bitmap getImageFromMessage(Message message) {
-		return BitmapFactory.decodeFile(getFile(message).getAbsolutePath());
-	}
-
 	public Bitmap getThumbnail(Message message, int size, boolean cacheOnly)
 			throws FileNotFoundException {
 		Bitmap thumbnail = mXmppConnectionService.getBitmapCache().get(
@@ -257,8 +259,7 @@ public class FileBackend {
 			File file = getFile(message);
 			BitmapFactory.Options options = new BitmapFactory.Options();
 			options.inSampleSize = calcSampleSize(file, size);
-			Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(),
-					options);
+			Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(),options);
 			if (fullsize == null) {
 				throw new FileNotFoundException();
 			}
@@ -271,13 +272,11 @@ public class FileBackend {
 
 	public Uri getTakePhotoUri() {
 		StringBuilder pathBuilder = new StringBuilder();
-		pathBuilder.append(Environment
-				.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
+		pathBuilder.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
 		pathBuilder.append('/');
 		pathBuilder.append("Camera");
 		pathBuilder.append('/');
-		pathBuilder.append("IMG_" + this.imageDateFormat.format(new Date())
-				+ ".jpg");
+		pathBuilder.append("IMG_" + this.imageDateFormat.format(new Date()) + ".jpg");
 		Uri uri = Uri.parse("file://" + pathBuilder.toString());
 		File file = new File(uri.toString());
 		file.getParentFile().mkdirs();
@@ -325,13 +324,13 @@ public class FileBackend {
 			String filename = getAvatarPath(avatar.getFilename());
 			file = new File(filename + ".tmp");
 			file.getParentFile().mkdirs();
+			OutputStream os = null;
 			try {
 				file.createNewFile();
-				FileOutputStream mFileOutputStream = new FileOutputStream(file);
+				os = new FileOutputStream(file);
 				MessageDigest digest = MessageDigest.getInstance("SHA-1");
 				digest.reset();
-				DigestOutputStream mDigestOutputStream = new DigestOutputStream(
-						mFileOutputStream, digest);
+				DigestOutputStream mDigestOutputStream = new DigestOutputStream(os, digest);
 				mDigestOutputStream.write(avatar.getImageAsBytes());
 				mDigestOutputStream.flush();
 				mDigestOutputStream.close();
@@ -349,6 +348,8 @@ public class FileBackend {
 				return false;
 			} catch (NoSuchAlgorithmException e) {
 				return false;
+			} finally {
+				close(os);
 			}
 		}
 		avatar.size = file.length();
@@ -356,8 +357,7 @@ public class FileBackend {
 	}
 
 	public String getAvatarPath(String avatar) {
-		return mXmppConnectionService.getFilesDir().getAbsolutePath()
-				+ "/avatars/" + avatar;
+		return mXmppConnectionService.getFilesDir().getAbsolutePath()+ "/avatars/" + avatar;
 	}
 
 	public Uri getAvatarUri(String avatar) {
@@ -368,10 +368,11 @@ public class FileBackend {
 		if (image == null) {
 			return null;
 		}
+		InputStream is = null;
 		try {
 			BitmapFactory.Options options = new BitmapFactory.Options();
 			options.inSampleSize = calcSampleSize(image, size);
-			InputStream is = mXmppConnectionService.getContentResolver().openInputStream(image);
+			is = mXmppConnectionService.getContentResolver().openInputStream(image);
 			Bitmap input = BitmapFactory.decodeStream(is, null, options);
 			if (input == null) {
 				return null;
@@ -384,6 +385,8 @@ public class FileBackend {
 			}
 		} catch (FileNotFoundException e) {
 			return null;
+		} finally {
+			close(is);
 		}
 	}
 
@@ -391,10 +394,11 @@ public class FileBackend {
 		if (image == null) {
 			return null;
 		}
+		InputStream is = null;
 		try {
 			BitmapFactory.Options options = new BitmapFactory.Options();
 			options.inSampleSize = calcSampleSize(image,Math.max(newHeight, newWidth));
-			InputStream is = mXmppConnectionService.getContentResolver().openInputStream(image);
+			is = mXmppConnectionService.getContentResolver().openInputStream(image);
 			Bitmap source = BitmapFactory.decodeStream(is, null, options);
 
 			int sourceWidth = source.getWidth();
@@ -414,8 +418,11 @@ public class FileBackend {
 			return dest;
 		} catch (FileNotFoundException e) {
 			return null;
+		} catch (IOException e) {
+			return null;
+		} finally {
+			close(is);
 		}
-
 	}
 
 	public Bitmap cropCenterSquare(Bitmap input, int size) {
@@ -522,4 +529,13 @@ public class FileBackend {
 	public boolean isFileAvailable(Message message) {
 		return getFile(message).exists();
 	}
+
+	public static void close(Closeable stream) {
+		if (stream != null) {
+			try {
+				stream.close();
+			} catch (IOException e) {
+			}
+		}
+	}
 }

src/main/java/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java 🔗

@@ -11,6 +11,7 @@ import android.util.Base64;
 
 import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.entities.DownloadableFile;
+import eu.siacs.conversations.persistance.FileBackend;
 import eu.siacs.conversations.utils.CryptoHelper;
 import eu.siacs.conversations.xml.Element;
 import eu.siacs.conversations.xmpp.OnIqPacketReceived;
@@ -172,6 +173,7 @@ public class JingleInbandTransport extends JingleTransport {
 				connection.updateProgress((int) ((((double) (this.fileSize - this.remainingSize)) / this.fileSize) * 100));
 			}
 		} catch (IOException e) {
+			FileBackend.close(fileInputStream);
 			this.onFileTransmissionStatusChanged.onFileTransferAborted();
 		}
 	}
@@ -198,6 +200,7 @@ public class JingleInbandTransport extends JingleTransport {
 				connection.updateProgress((int) ((((double) (this.fileSize - this.remainingSize)) / this.fileSize) * 100));
 			}
 		} catch (IOException e) {
+			FileBackend.close(fileOutputStream);
 			this.onFileTransmissionStatusChanged.onFileTransferAborted();
 		}
 	}

src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java 🔗

@@ -11,6 +11,7 @@ import java.security.NoSuchAlgorithmException;
 import java.util.Arrays;
 
 import eu.siacs.conversations.entities.DownloadableFile;
+import eu.siacs.conversations.persistance.FileBackend;
 import eu.siacs.conversations.utils.CryptoHelper;
 
 public class JingleSocks5Transport extends JingleTransport {
@@ -126,25 +127,19 @@ public class JingleSocks5Transport extends JingleTransport {
 				} catch (NoSuchAlgorithmException e) {
 					callback.onFileTransferAborted();
 				} finally {
-					try {
-						if (fileInputStream != null) {
-							fileInputStream.close();
-						}
-					} catch (IOException e) {
-						callback.onFileTransferAborted();
-					}
+					FileBackend.close(fileInputStream);
 				}
 			}
 		}).start();
 
 	}
 
-	public void receive(final DownloadableFile file,
-			final OnFileTransmissionStatusChanged callback) {
+	public void receive(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) {
 		new Thread(new Runnable() {
 
 			@Override
 			public void run() {
+				OutputStream fileOutputStream = null;
 				try {
 					MessageDigest digest = MessageDigest.getInstance("SHA-1");
 					digest.reset();
@@ -152,7 +147,7 @@ public class JingleSocks5Transport extends JingleTransport {
 					socket.setSoTimeout(30000);
 					file.getParentFile().mkdirs();
 					file.createNewFile();
-					OutputStream fileOutputStream = file.createOutputStream();
+					fileOutputStream = file.createOutputStream();
 					if (fileOutputStream == null) {
 						callback.onFileTransferAborted();
 						return;
@@ -183,6 +178,8 @@ public class JingleSocks5Transport extends JingleTransport {
 					callback.onFileTransferAborted();
 				} catch (NoSuchAlgorithmException e) {
 					callback.onFileTransferAborted();
+				} finally {
+					FileBackend.close(fileOutputStream);
 				}
 			}
 		}).start();