Clean up transport logic in ContentProviderRestoreComponent
This commit is contained in:
parent
a1a8329299
commit
0a978c37e8
1 changed files with 58 additions and 95 deletions
|
@ -17,6 +17,7 @@ import libcore.io.Streams;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
@ -27,8 +28,6 @@ import static com.stevesoltys.backup.transport.component.provider.ContentProvide
|
||||||
import static com.stevesoltys.backup.transport.component.provider.ContentProviderBackupConfiguration.INCREMENTAL_BACKUP_DIRECTORY;
|
import static com.stevesoltys.backup.transport.component.provider.ContentProviderBackupConfiguration.INCREMENTAL_BACKUP_DIRECTORY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Clean this up. Much of it was taken from the LocalTransport implementation.
|
|
||||||
*
|
|
||||||
* @author Steve Soltys
|
* @author Steve Soltys
|
||||||
*/
|
*/
|
||||||
public class ContentProviderRestoreComponent implements RestoreComponent {
|
public class ContentProviderRestoreComponent implements RestoreComponent {
|
||||||
|
@ -55,40 +54,6 @@ public class ContentProviderRestoreComponent implements RestoreComponent {
|
||||||
return TRANSPORT_OK;
|
return TRANSPORT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ParcelFileDescriptor buildFileDescriptor() throws FileNotFoundException {
|
|
||||||
ContentResolver contentResolver = configuration.getContext().getContentResolver();
|
|
||||||
|
|
||||||
return contentResolver.openFileDescriptor(configuration.getUri(), "r");
|
|
||||||
}
|
|
||||||
|
|
||||||
private ZipInputStream buildInputStream(ParcelFileDescriptor inputFileDescriptor) throws FileNotFoundException {
|
|
||||||
FileInputStream fileInputStream = new FileInputStream(inputFileDescriptor.getFileDescriptor());
|
|
||||||
return new ZipInputStream(fileInputStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean containsPackageFile(String fileName) throws IOException, InvalidKeyException,
|
|
||||||
InvalidAlgorithmParameterException {
|
|
||||||
|
|
||||||
ParcelFileDescriptor inputFileDescriptor = buildFileDescriptor();
|
|
||||||
ZipInputStream inputStream = buildInputStream(inputFileDescriptor);
|
|
||||||
|
|
||||||
ZipEntry zipEntry;
|
|
||||||
while ((zipEntry = inputStream.getNextEntry()) != null) {
|
|
||||||
|
|
||||||
if (zipEntry.getName().startsWith(fileName)) {
|
|
||||||
IoUtils.closeQuietly(inputStream);
|
|
||||||
IoUtils.closeQuietly(inputFileDescriptor.getFileDescriptor());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inputStream.closeEntry();
|
|
||||||
}
|
|
||||||
|
|
||||||
IoUtils.closeQuietly(inputStream);
|
|
||||||
IoUtils.closeQuietly(inputFileDescriptor.getFileDescriptor());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RestoreDescription nextRestorePackage() {
|
public RestoreDescription nextRestorePackage() {
|
||||||
Preconditions.checkNotNull(restoreState, "startRestore() not called");
|
Preconditions.checkNotNull(restoreState, "startRestore() not called");
|
||||||
|
@ -117,6 +82,39 @@ public class ContentProviderRestoreComponent implements RestoreComponent {
|
||||||
return RestoreDescription.NO_MORE_PACKAGES;
|
return RestoreDescription.NO_MORE_PACKAGES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean containsPackageFile(String fileName) throws IOException, InvalidKeyException,
|
||||||
|
InvalidAlgorithmParameterException {
|
||||||
|
ParcelFileDescriptor inputFileDescriptor = buildInputFileDescriptor();
|
||||||
|
ZipInputStream inputStream = buildInputStream(inputFileDescriptor);
|
||||||
|
|
||||||
|
Optional<ZipEntry> zipEntry = seekToEntry(inputStream, fileName);
|
||||||
|
IoUtils.closeQuietly(inputFileDescriptor.getFileDescriptor());
|
||||||
|
return zipEntry.isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ParcelFileDescriptor buildInputFileDescriptor() throws FileNotFoundException {
|
||||||
|
ContentResolver contentResolver = configuration.getContext().getContentResolver();
|
||||||
|
return contentResolver.openFileDescriptor(configuration.getUri(), "r");
|
||||||
|
}
|
||||||
|
|
||||||
|
private ZipInputStream buildInputStream(ParcelFileDescriptor inputFileDescriptor) throws FileNotFoundException {
|
||||||
|
FileInputStream fileInputStream = new FileInputStream(inputFileDescriptor.getFileDescriptor());
|
||||||
|
return new ZipInputStream(fileInputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<ZipEntry> seekToEntry(ZipInputStream inputStream, String entryPath) throws IOException {
|
||||||
|
ZipEntry zipEntry;
|
||||||
|
while ((zipEntry = inputStream.getNextEntry()) != null) {
|
||||||
|
|
||||||
|
if (zipEntry.getName().startsWith(entryPath)) {
|
||||||
|
return Optional.of(zipEntry);
|
||||||
|
}
|
||||||
|
inputStream.closeEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRestoreData(ParcelFileDescriptor outputFileDescriptor) {
|
public int getRestoreData(ParcelFileDescriptor outputFileDescriptor) {
|
||||||
Preconditions.checkState(restoreState != null, "startRestore() not called");
|
Preconditions.checkState(restoreState != null, "startRestore() not called");
|
||||||
|
@ -138,25 +136,22 @@ public class ContentProviderRestoreComponent implements RestoreComponent {
|
||||||
|
|
||||||
private int transferIncrementalRestoreData(String packageName, BackupDataOutput backupDataOutput)
|
private int transferIncrementalRestoreData(String packageName, BackupDataOutput backupDataOutput)
|
||||||
throws IOException, InvalidAlgorithmParameterException, InvalidKeyException {
|
throws IOException, InvalidAlgorithmParameterException, InvalidKeyException {
|
||||||
ParcelFileDescriptor inputFileDescriptor = buildFileDescriptor();
|
ParcelFileDescriptor inputFileDescriptor = buildInputFileDescriptor();
|
||||||
ZipInputStream inputStream = buildInputStream(inputFileDescriptor);
|
ZipInputStream inputStream = buildInputStream(inputFileDescriptor);
|
||||||
|
|
||||||
ZipEntry zipEntry;
|
Optional<ZipEntry> zipEntryOptional = seekToEntry(inputStream, INCREMENTAL_BACKUP_DIRECTORY + packageName);
|
||||||
while ((zipEntry = inputStream.getNextEntry()) != null) {
|
while (zipEntryOptional.isPresent()) {
|
||||||
|
String fileName = new File(zipEntryOptional.get().getName()).getName();
|
||||||
if (zipEntry.getName().startsWith(INCREMENTAL_BACKUP_DIRECTORY + packageName)) {
|
|
||||||
String fileName = new File(zipEntry.getName()).getName();
|
|
||||||
String blobKey = new String(Base64.decode(fileName, Base64.DEFAULT));
|
String blobKey = new String(Base64.decode(fileName, Base64.DEFAULT));
|
||||||
|
|
||||||
byte[] backupData = Streams.readFullyNoClose(inputStream);
|
byte[] backupData = Streams.readFullyNoClose(inputStream);
|
||||||
backupDataOutput.writeEntityHeader(blobKey, backupData.length);
|
backupDataOutput.writeEntityHeader(blobKey, backupData.length);
|
||||||
backupDataOutput.writeEntityData(backupData, backupData.length);
|
backupDataOutput.writeEntityData(backupData, backupData.length);
|
||||||
}
|
|
||||||
|
|
||||||
inputStream.closeEntry();
|
inputStream.closeEntry();
|
||||||
|
|
||||||
|
zipEntryOptional = seekToEntry(inputStream, INCREMENTAL_BACKUP_DIRECTORY + packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
IoUtils.closeQuietly(inputStream);
|
|
||||||
IoUtils.closeQuietly(inputFileDescriptor.getFileDescriptor());
|
IoUtils.closeQuietly(inputFileDescriptor.getFileDescriptor());
|
||||||
return TRANSPORT_OK;
|
return TRANSPORT_OK;
|
||||||
}
|
}
|
||||||
|
@ -173,36 +168,13 @@ public class ContentProviderRestoreComponent implements RestoreComponent {
|
||||||
String name = restoreState.getPackages()[restoreState.getPackageIndex()].packageName;
|
String name = restoreState.getPackages()[restoreState.getPackageIndex()].packageName;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
inputFileDescriptor = buildFileDescriptor();
|
inputFileDescriptor = buildInputFileDescriptor();
|
||||||
restoreState.setInputFileDescriptor(inputFileDescriptor);
|
restoreState.setInputFileDescriptor(inputFileDescriptor);
|
||||||
|
|
||||||
inputStream = buildInputStream(inputFileDescriptor);
|
inputStream = buildInputStream(inputFileDescriptor);
|
||||||
restoreState.setInputStream(inputStream);
|
restoreState.setInputStream(inputStream);
|
||||||
|
|
||||||
} catch (FileNotFoundException ex) {
|
if (!seekToEntry(inputStream, FULL_BACKUP_DIRECTORY + name).isPresent()) {
|
||||||
Log.e(TAG, "Unable to read archive for " + name, ex);
|
|
||||||
|
|
||||||
if (inputFileDescriptor != null) {
|
|
||||||
IoUtils.closeQuietly(inputFileDescriptor.getFileDescriptor());
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRANSPORT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
ZipEntry zipEntry;
|
|
||||||
while ((zipEntry = inputStream.getNextEntry()) != null) {
|
|
||||||
|
|
||||||
if (zipEntry.getName().equals(FULL_BACKUP_DIRECTORY + name)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
inputStream.closeEntry();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (zipEntry == null) {
|
|
||||||
IoUtils.closeQuietly(inputStream);
|
|
||||||
IoUtils.closeQuietly(inputFileDescriptor.getFileDescriptor());
|
IoUtils.closeQuietly(inputFileDescriptor.getFileDescriptor());
|
||||||
return TRANSPORT_PACKAGE_REJECTED;
|
return TRANSPORT_PACKAGE_REJECTED;
|
||||||
}
|
}
|
||||||
|
@ -210,8 +182,9 @@ public class ContentProviderRestoreComponent implements RestoreComponent {
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Log.e(TAG, "Unable to read archive for " + name, ex);
|
Log.e(TAG, "Unable to read archive for " + name, ex);
|
||||||
|
|
||||||
IoUtils.closeQuietly(inputStream);
|
if (inputFileDescriptor != null) {
|
||||||
IoUtils.closeQuietly(inputFileDescriptor.getFileDescriptor());
|
IoUtils.closeQuietly(inputFileDescriptor.getFileDescriptor());
|
||||||
|
}
|
||||||
return TRANSPORT_PACKAGE_REJECTED;
|
return TRANSPORT_PACKAGE_REJECTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,12 +201,8 @@ public class ContentProviderRestoreComponent implements RestoreComponent {
|
||||||
try {
|
try {
|
||||||
bytesRead = inputStream.read(buffer);
|
bytesRead = inputStream.read(buffer);
|
||||||
|
|
||||||
if (bytesRead < 0) {
|
if (bytesRead <= 0) {
|
||||||
bytesRead = NO_MORE_DATA;
|
bytesRead = NO_MORE_DATA;
|
||||||
|
|
||||||
} else if (bytesRead == 0) {
|
|
||||||
bytesRead = NO_MORE_DATA;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
outputStream.write(buffer, 0, bytesRead);
|
outputStream.write(buffer, 0, bytesRead);
|
||||||
}
|
}
|
||||||
|
@ -243,21 +212,16 @@ public class ContentProviderRestoreComponent implements RestoreComponent {
|
||||||
return TRANSPORT_ERROR;
|
return TRANSPORT_ERROR;
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
|
||||||
if (bytesRead == NO_MORE_DATA) {
|
if (bytesRead == NO_MORE_DATA) {
|
||||||
|
if (inputFileDescriptor != null) {
|
||||||
IoUtils.closeQuietly(inputFileDescriptor.getFileDescriptor());
|
IoUtils.closeQuietly(inputFileDescriptor.getFileDescriptor());
|
||||||
IoUtils.closeQuietly(inputStream);
|
}
|
||||||
IoUtils.closeQuietly(outputStream);
|
IoUtils.closeQuietly(fileDescriptor.getFileDescriptor());
|
||||||
|
|
||||||
fileDescriptor.close();
|
|
||||||
|
|
||||||
restoreState.setInputFileDescriptor(null);
|
restoreState.setInputFileDescriptor(null);
|
||||||
restoreState.setInputStream(null);
|
restoreState.setInputStream(null);
|
||||||
restoreState.setOutputStream(null);
|
restoreState.setOutputStream(null);
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
|
||||||
Log.e(TAG, "Exception while closing socket for restore: ", ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
|
@ -290,10 +254,9 @@ public class ContentProviderRestoreComponent implements RestoreComponent {
|
||||||
|
|
||||||
private void resetFullRestoreState() {
|
private void resetFullRestoreState() {
|
||||||
Preconditions.checkNotNull(restoreState);
|
Preconditions.checkNotNull(restoreState);
|
||||||
Preconditions.checkState(restoreState.getRestoreType() != TYPE_FULL_STREAM);
|
Preconditions.checkState(restoreState.getRestoreType() == TYPE_FULL_STREAM);
|
||||||
|
|
||||||
IoUtils.closeQuietly(restoreState.getInputFileDescriptor());
|
IoUtils.closeQuietly(restoreState.getInputFileDescriptor());
|
||||||
IoUtils.closeQuietly(restoreState.getInputStream());
|
|
||||||
IoUtils.closeQuietly(restoreState.getOutputStream());
|
IoUtils.closeQuietly(restoreState.getOutputStream());
|
||||||
restoreState = null;
|
restoreState = null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue