/*
* Copyright (c) 2012 Denis Solonenko.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
package ru.orangesoftware.financisto2.export.dropbox;
import android.content.Context;
import android.util.Log;
import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.android.AndroidAuthSession;
import com.dropbox.client2.session.AccessTokenPair;
import com.dropbox.client2.session.AppKeyPair;
import com.dropbox.client2.session.Session;
import org.androidannotations.annotations.AfterInject;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EBean;
import ru.orangesoftware.financisto2.R;
import ru.orangesoftware.financisto2.backup.DatabaseExport;
import ru.orangesoftware.financisto2.backup.DatabaseImport;
import ru.orangesoftware.financisto2.bus.GreenRobotBus;
import ru.orangesoftware.financisto2.db.CategoryRepository;
import ru.orangesoftware.financisto2.db.DatabaseAdapter;
import ru.orangesoftware.financisto2.export.ImportExportException;
import ru.orangesoftware.financisto2.export.drive.DoDriveBackup;
import ru.orangesoftware.financisto2.utils.MyPreferences;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;
@EBean(scope = EBean.Scope.Singleton)
public class Dropbox {
public static final String APP_KEY = "INSERT_APP_KEY_HERE";
public static final String APP_SECRET = "INSERT_APP_SECRET_HERE";
public static final Session.AccessType ACCESS_TYPE = Session.AccessType.APP_FOLDER;
private final Context context;
private final DropboxAPI<AndroidAuthSession> dropboxApi;
@Bean
GreenRobotBus bus;
@Bean
DatabaseAdapter db;
@Bean
CategoryRepository categoryRepository;
private boolean startedAuth = false;
public Dropbox(Context context) {
this.context = context;
this.dropboxApi = createApi();
}
@AfterInject
public void init() {
bus.register(this);
}
public void startAuth() {
startedAuth = true;
dropboxApi.getSession().startOAuth2Authentication(context);
}
public void completeAuth() {
try {
if (startedAuth && dropboxApi.getSession().authenticationSuccessful()) {
try {
dropboxApi.getSession().finishAuthentication();
String token = dropboxApi.getSession().getOAuth2AccessToken();
MyPreferences.storeDropboxToken(context, token);
} catch (IllegalStateException e) {
Log.i("Financisto", "Error authenticating Dropbox", e);
}
}
} finally {
startedAuth = false;
}
}
public void deAuth() {
MyPreferences.removeDropboxKeys(context);
dropboxApi.getSession().unlink();
}
private DropboxAPI<AndroidAuthSession> createApi() {
AppKeyPair appKeys = new AppKeyPair(APP_KEY, APP_SECRET);
AndroidAuthSession session = new AndroidAuthSession(appKeys, ACCESS_TYPE);
return new DropboxAPI<AndroidAuthSession>(session);
}
public boolean authSession() {
String token = MyPreferences.getDropboxToken(context);
if (token != null) {
dropboxApi.getSession().setOAuth2AccessToken(token);
return dropboxApi.getSession().isLinked();
}
return false;
}
public void uploadFile(File file) throws Exception {
InputStream is = new FileInputStream(file);
uploadStream(file.getName(), is, file.length());
}
public void uploadStream(String fileName, InputStream is, long length) throws Exception {
try {
if (authSession()) {
try {
DropboxAPI.Entry newEntry = dropboxApi.putFile(fileName, is, length, null, null);
Log.i("Financisto", "Dropbox: The uploaded file's rev is: " + newEntry.rev);
} catch (Exception e) {
Log.e("Financisto", "Dropbox: Something wrong", e);
throw new ImportExportException(context.getString(R.string.dropbox_error), e);
}
} else {
throw new ImportExportException(context.getString(R.string.dropbox_auth_error));
}
} finally {
is.close();
}
}
public List<String> listFiles() throws Exception {
if (authSession()) {
try {
List<String> files = new ArrayList<String>();
List<DropboxAPI.Entry> entries = dropboxApi.search("/", ".backup", 1000, false);
for (DropboxAPI.Entry entry : entries) {
if (entry.fileName() != null) {
files.add(entry.fileName());
}
}
Collections.sort(files, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s2.compareTo(s1);
}
});
return files;
} catch (Exception e) {
Log.e("Financisto", "Dropbox: Something wrong", e);
throw new ImportExportException(context.getString(R.string.dropbox_error), e);
}
} else {
throw new ImportExportException(context.getString(R.string.dropbox_auth_error));
}
}
public InputStream getFileAsStream(String backupFile) throws Exception {
if (authSession()) {
try {
return dropboxApi.getFileStream("/" + backupFile, null);
} catch (Exception e) {
Log.e("Financisto", "Dropbox: Something wrong", e);
throw new ImportExportException(context.getString(R.string.dropbox_error), e);
}
} else {
throw new ImportExportException(context.getString(R.string.dropbox_auth_error));
}
}
public void onEventBackgroundThread(DoDropboxBackup event) {
DatabaseExport export = new DatabaseExport(context, db.db(), true);
try {
String fileName = export.generateFilename();
byte[] backupBytes = export.generateBackupBytes();
InputStream is = new ByteArrayInputStream(backupBytes);
uploadStream(fileName, is, backupBytes.length);
handleSuccess(fileName);
} catch (Exception e) {
handleError(e);
}
}
public void onEventBackgroundThread(DoDropboxListFiles event) {
try {
List<String> files = listFiles();
bus.post(new DropboxFileList(files));
} catch (Exception e) {
handleError(e);
}
}
public void onEventBackgroundThread(DoDropboxRestore event) {
try {
DatabaseImport.createFromDropboxBackup(context, db, categoryRepository, this, event.backupFile).importDatabase();
bus.post(new DropboxRestoreSuccess());
} catch (Exception e) {
handleError(e);
}
}
private void handleSuccess(String fileName) {
bus.post(new DropboxBackupSuccess(fileName));
}
private void handleError(Exception e) {
bus.post(new DropboxBackupError(e));
}
}