Merge pull request #14583 from nextcloud/tryResources

Use of Try-With-Resources
This commit is contained in:
Andy Scherzinger 2025-06-12 11:02:25 +02:00 committed by GitHub
commit fa83d67bfa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 138 additions and 237 deletions

View File

@ -963,20 +963,12 @@ public final class ThumbnailsCacheManager {
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px, px);
}
} else if (Type.VIDEO == type) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) {
retriever.setDataSource(file.getAbsolutePath());
thumbnail = retriever.getFrameAtTime(-1);
} catch (Exception ex) {
// can't create a bitmap
Log_OC.w(TAG, "Failed to create bitmap from video " + file.getAbsolutePath());
} finally {
try {
retriever.release();
} catch (RuntimeException | IOException ex) {
// Ignore failure at this point.
Log_OC.w(TAG, "Failed release MediaMetadataRetriever for " + file.getAbsolutePath());
}
}
if (thumbnail != null) {

View File

@ -953,15 +953,11 @@ public class UploadFileOperation extends SyncOperation {
File temporalFile = null;
File originalFile = new File(mOriginalStoragePath);
File expectedFile = null;
FileLock fileLock = null;
FileChannel channel = null;
long size;
try {
// check conditions
result = checkConditions(originalFile);
if (result != null) {
return result;
}
@ -983,107 +979,121 @@ public class UploadFileOperation extends SyncOperation {
// Get the last modification date of the file from the file system
long lastModifiedTimestamp = originalFile.lastModified() / 1000;
final Long creationTimestamp = FileUtil.getCreationTimestamp(originalFile);
try {
channel = new RandomAccessFile(mFile.getStoragePath(), "rw").getChannel();
fileLock = channel.tryLock();
} catch (FileNotFoundException e) {
// this basically means that the file is on SD card
// try to copy file to temporary dir if it doesn't exist
String temporalPath = FileStorageUtils.getInternalTemporalPath(user.getAccountName(), mContext) +
mFile.getRemotePath();
mFile.setStoragePath(temporalPath);
temporalFile = new File(temporalPath);
// Initialize channel and fileLock in try-with-resources
try (
FileChannel channel = new RandomAccessFile(mFile.getStoragePath(), "rw").getChannel();
FileLock fileLock = channel.tryLock()
) {
if (fileLock == null) {
// Handle the case when the file lock cannot be acquired
String temporalPath = FileStorageUtils.getInternalTemporalPath(user.getAccountName(), mContext) + mFile.getRemotePath();
mFile.setStoragePath(temporalPath);
temporalFile = new File(temporalPath);
Files.deleteIfExists(Paths.get(temporalPath));
result = copy(originalFile, temporalFile);
Files.deleteIfExists(Paths.get(temporalPath));
result = copy(originalFile, temporalFile);
if (result.isSuccess()) {
if (temporalFile.length() == originalFile.length()) {
channel = new RandomAccessFile(temporalFile.getAbsolutePath(), "rw").getChannel();
fileLock = channel.tryLock();
if (result.isSuccess()) {
if (temporalFile.length() == originalFile.length()) {
// Acquire lock on temporary file
try (FileChannel tempChannel = new RandomAccessFile(temporalFile.getAbsolutePath(), "rw").getChannel();
FileLock tempFileLock = tempChannel.tryLock()) {
if (tempFileLock != null) {
// Use the temporary channel for the upload
size = tempChannel.size();
updateSize(size);
// Perform the upload operation
if (size > ChunkedFileUploadRemoteOperation.CHUNK_SIZE_MOBILE) {
boolean onWifiConnection = connectivityService.getConnectivity().isWifi();
mUploadOperation = new ChunkedFileUploadRemoteOperation(
mFile.getStoragePath(),
mFile.getRemotePath(),
mFile.getMimeType(),
mFile.getEtagInConflict(),
lastModifiedTimestamp,
creationTimestamp,
onWifiConnection,
mDisableRetries
);
} else {
mUploadOperation = new UploadFileRemoteOperation(
mFile.getStoragePath(),
mFile.getRemotePath(),
mFile.getMimeType(),
mFile.getEtagInConflict(),
lastModifiedTimestamp,
creationTimestamp,
mDisableRetries
);
}
if (result.isSuccess() && mUploadOperation != null) {
result = mUploadOperation.execute(client);
if (!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_PRECONDITION_FAILED) {
result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
}
}
} else {
result = new RemoteOperationResult(ResultCode.LOCK_FAILED);
}
}
} else {
result = new RemoteOperationResult(ResultCode.LOCK_FAILED);
}
}
} else {
size = channel.size();
updateSize(size);
// Perform the upload operation
if (size > ChunkedFileUploadRemoteOperation.CHUNK_SIZE_MOBILE) {
boolean onWifiConnection = connectivityService.getConnectivity().isWifi();
mUploadOperation = new ChunkedFileUploadRemoteOperation(
mFile.getStoragePath(),
mFile.getRemotePath(),
mFile.getMimeType(),
mFile.getEtagInConflict(),
lastModifiedTimestamp,
creationTimestamp,
onWifiConnection,
mDisableRetries
);
} else {
result = new RemoteOperationResult(ResultCode.LOCK_FAILED);
mUploadOperation = new UploadFileRemoteOperation(
mFile.getStoragePath(),
mFile.getRemotePath(),
mFile.getMimeType(),
mFile.getEtagInConflict(),
lastModifiedTimestamp,
creationTimestamp,
mDisableRetries
);
}
if (result.isSuccess() && mUploadOperation != null) {
result = mUploadOperation.execute(client);
if (!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_PRECONDITION_FAILED) {
result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
}
}
}
} catch (FileNotFoundException e) {
Log_OC.d(TAG, mOriginalStoragePath + " not exists anymore");
result = new RemoteOperationResult(ResultCode.LOCAL_FILE_NOT_FOUND);
} catch (OverlappingFileLockException e) {
Log_OC.d(TAG, "Overlapping file lock exception");
result = new RemoteOperationResult(ResultCode.LOCK_FAILED);
} catch (Exception e) {
result = new RemoteOperationResult(e);
}
try {
size = channel.size();
} catch (Exception e1) {
size = new File(mFile.getStoragePath()).length();
}
updateSize(size);
// perform the upload
if (size > ChunkedFileUploadRemoteOperation.CHUNK_SIZE_MOBILE) {
boolean onWifiConnection = connectivityService.getConnectivity().isWifi();
mUploadOperation = new ChunkedFileUploadRemoteOperation(mFile.getStoragePath(),
mFile.getRemotePath(),
mFile.getMimeType(),
mFile.getEtagInConflict(),
lastModifiedTimestamp,
creationTimestamp,
onWifiConnection,
mDisableRetries);
} else {
mUploadOperation = new UploadFileRemoteOperation(mFile.getStoragePath(),
mFile.getRemotePath(),
mFile.getMimeType(),
mFile.getEtagInConflict(),
lastModifiedTimestamp,
creationTimestamp,
mDisableRetries);
}
for (OnDatatransferProgressListener mDataTransferListener : mDataTransferListeners) {
mUploadOperation.addDataTransferProgressListener(mDataTransferListener);
}
if (mCancellationRequested.get()) {
throw new OperationCancelledException();
}
if (result.isSuccess() && mUploadOperation != null) {
result = mUploadOperation.execute(client);
/// move local temporal file or original file to its corresponding
// location in the Nextcloud local folder
if (!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_PRECONDITION_FAILED) {
result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
}
}
} catch (FileNotFoundException e) {
Log_OC.d(TAG, mOriginalStoragePath + " not exists anymore");
result = new RemoteOperationResult(ResultCode.LOCAL_FILE_NOT_FOUND);
} catch (OverlappingFileLockException e) {
Log_OC.d(TAG, "Overlapping file lock exception");
result = new RemoteOperationResult(ResultCode.LOCK_FAILED);
} catch (Exception e) {
result = new RemoteOperationResult(e);
} finally {
// Finalize cleanup
mUploadStarted.set(false);
if (fileLock != null) {
try {
fileLock.release();
} catch (IOException e) {
Log_OC.e(TAG, "Failed to unlock file with path " + mOriginalStoragePath);
}
}
if (channel != null) {
try {
channel.close();
} catch (IOException e) {
Log_OC.w(TAG, "Failed to close file channel");
}
}
if (temporalFile != null && !originalFile.equals(temporalFile)) {
temporalFile.delete();
}
@ -1093,6 +1103,8 @@ public class UploadFileOperation extends SyncOperation {
}
logResult(result, mOriginalStoragePath, mRemotePath);
} catch (Exception e) {
result = new RemoteOperationResult(e);
}
if (result.isSuccess()) {
@ -1101,7 +1113,7 @@ public class UploadFileOperation extends SyncOperation {
getStorageManager().saveConflict(mFile, mFile.getEtagInConflict());
}
// delete temporal file
// Delete temporal file
if (temporalFile != null && temporalFile.exists() && !temporalFile.delete()) {
Log_OC.e(TAG, "Could not delete temporal file " + temporalFile.getAbsolutePath());
}
@ -1109,6 +1121,7 @@ public class UploadFileOperation extends SyncOperation {
return result;
}
private void updateSize(long size) {
OCUpload ocUpload = uploadsStorageManager.getUploadById(getOCUploadId());
if (ocUpload != null) {
@ -1532,22 +1545,16 @@ public class UploadFileOperation extends SyncOperation {
if (!sourceFile.renameTo(targetFile)) {
// try to copy and then delete
targetFile.createNewFile();
FileChannel inChannel = new FileInputStream(sourceFile).getChannel();
FileChannel outChannel = new FileOutputStream(targetFile).getChannel();
try {
try (
FileChannel inChannel = new FileInputStream(sourceFile).getChannel();
FileChannel outChannel = new FileOutputStream(targetFile).getChannel()
) {
inChannel.transferTo(0, inChannel.size(), outChannel);
sourceFile.delete();
} catch (Exception e) {
mFile.setStoragePath(""); // forget the local file
// by now, treat this as a success; the file was uploaded
// the best option could be show a warning message
} finally {
if (inChannel != null) {
inChannel.close();
}
if (outChannel != null) {
outChannel.close();
}
}
}

View File

@ -117,9 +117,6 @@ public class CopyAndUploadContentUrisTask extends AsyncTask<Object, Void, Result
protected ResultCode doInBackground(Object[] params) {
ResultCode result = ResultCode.UNKNOWN_ERROR;
InputStream inputStream = null;
FileOutputStream outputStream = null;
String fullTempPath = null;
Uri currentUri = null;
@ -137,11 +134,7 @@ public class CopyAndUploadContentUrisTask extends AsyncTask<Object, Void, Result
currentRemotePath = remotePaths[i];
long lastModified = 0;
try (Cursor cursor = leakedContentResolver.query(currentUri,
null,
null,
null,
null)) {
try (Cursor cursor = leakedContentResolver.query(currentUri, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
// this check prevents a crash when last modification time is not available on certain phones
int columnIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_LAST_MODIFIED);
@ -152,42 +145,37 @@ public class CopyAndUploadContentUrisTask extends AsyncTask<Object, Void, Result
}
fullTempPath = FileStorageUtils.getTemporalPath(user.getAccountName()) + currentRemotePath;
inputStream = leakedContentResolver.openInputStream(currentUri);
File cacheFile = new File(fullTempPath);
File tempDir = cacheFile.getParentFile();
if (!tempDir.exists()) {
tempDir.mkdirs();
}
cacheFile.createNewFile();
outputStream = new FileOutputStream(fullTempPath);
byte[] buffer = new byte[4096];
int count;
while ((count = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, count);
}
if (lastModified != 0) {
try {
if (!cacheFile.setLastModified(lastModified)) {
Log_OC.w(TAG, "Could not change mtime of cacheFile");
}
} catch (SecurityException e) {
Log_OC.e(TAG, "Not enough permissions to change mtime of cacheFile", e);
} catch (IllegalArgumentException e) {
Log_OC.e(TAG, "Could not change mtime of cacheFile, mtime is negativ: "+lastModified, e);
try (InputStream inputStream = leakedContentResolver.openInputStream(currentUri);
FileOutputStream outputStream = new FileOutputStream(fullTempPath)) {
byte[] buffer = new byte[4096];
int count;
while ((count = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, count);
}
if (lastModified != 0) {
try {
if (!cacheFile.setLastModified(lastModified)) {
Log_OC.w(TAG, "Could not change mtime of cacheFile");
}
} catch (SecurityException e) {
Log_OC.e(TAG, "Not enough permissions to change mtime of cacheFile", e);
} catch (IllegalArgumentException e) {
Log_OC.e(TAG, "Could not change mtime of cacheFile, mtime is negativ: " + lastModified, e);
}
}
requestUpload(user, fullTempPath, currentRemotePath, behaviour);
fullTempPath = null;
}
requestUpload(
user,
fullTempPath,
currentRemotePath,
behaviour
);
fullTempPath = null;
}
result = ResultCode.OK;
} catch (ArrayIndexOutOfBoundsException e) {
@ -206,7 +194,7 @@ public class CopyAndUploadContentUrisTask extends AsyncTask<Object, Void, Result
} catch (Exception e) {
Log_OC.e(TAG, "Exception while copying " + currentUri + " to temporary file", e);
result = ResultCode.LOCAL_STORAGE_NOT_COPIED;
result = ResultCode.LOCAL_STORAGE_NOT_COPIED;
// clean
if (fullTempPath != null) {
@ -216,22 +204,6 @@ public class CopyAndUploadContentUrisTask extends AsyncTask<Object, Void, Result
}
}
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) {
Log_OC.w(TAG, "Ignoring exception of inputStream closure");
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (Exception e) {
Log_OC.w(TAG, "Ignoring exception of outStream closure");
}
}
}
return result;

View File

@ -1,68 +0,0 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2018 Andy Scherzinger <info@andy-scherzinger.de>
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.decoration;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.view.View;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.RecyclerView;
/**
* DividerItemDecoration based on {@link DividerItemDecoration} adding a 72dp left padding.
*/
public class SimpleListItemDividerDecoration extends DividerItemDecoration {
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
private final Rect bounds = new Rect();
private Drawable divider;
private int leftPadding;
/**
* Default divider will be used
*/
public SimpleListItemDividerDecoration(Context context) {
super(context, DividerItemDecoration.VERTICAL);
final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS);
divider = styledAttributes.getDrawable(0);
leftPadding = Math.round(72 * (context.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
styledAttributes.recycle();
}
@Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
canvas.save();
final int right;
//noinspection AndroidLintNewApi - NewApi lint fails to handle overrides.
if (parent.getClipToPadding()) {
right = parent.getWidth() - parent.getPaddingRight();
canvas.clipRect(leftPadding, parent.getPaddingTop(), right,
parent.getHeight() - parent.getPaddingBottom());
} else {
right = parent.getWidth();
}
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
parent.getDecoratedBoundsWithMargins(child, bounds);
final int bottom = bounds.bottom + Math.round(child.getTranslationY());
final int top = bottom - 1;
if (divider != null) {
divider.setBounds(leftPadding, top, right, bottom);
divider.draw(canvas);
}
}
canvas.restore();
}
}

View File

@ -113,11 +113,9 @@ public class AndroidCalendar {
private static boolean missing(ContentResolver resolver, Uri uri) {
// Determine if a provider is missing
ContentProviderClient provider = resolver.acquireContentProviderClient(uri);
if (provider != null) {
provider.release();
try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) {
return provider == null;
}
return provider == null;
}
@Override