Implemented SkyDriveFileStorage including transactional write

This commit is contained in:
Philipp Crocoll 2013-11-04 22:26:21 +01:00
parent 17bfc0c975
commit 684312b412
6 changed files with 540 additions and 299 deletions

View File

@ -13,4 +13,5 @@ proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.
# Project target. # Project target.
target=android-17 target=android-17
android.library=true android.library=true
android.library.reference.1=../../../../../../../AppData/Local/Android/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib android.library.reference.1=..\\..\\..\\..\\..\\..\\..\\AppData\\Local\\Android\\android-sdk\\extras\\google\\google_play_services\\libproject\\google-play-services_lib
android.library.reference.2=../../../../LiveSDK-for-Android/src

View File

@ -1,36 +1,45 @@
package keepass2android.javafilestorage; package keepass2android.javafilestorage;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import keepass2android.javafilestorage.JavaFileStorageBase.InvalidPathException; import keepass2android.javafilestorage.JavaFileStorageBase.InvalidPathException;
import keepass2android.javafilestorage.skydrive.SkyDriveException;
import keepass2android.javafilestorage.skydrive.SkyDriveFile;
import keepass2android.javafilestorage.skydrive.SkyDriveFolder;
import keepass2android.javafilestorage.skydrive.SkyDriveObject;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import com.google.api.services.drive.model.File;
import com.microsoft.live.LiveAuthClient; import com.microsoft.live.LiveAuthClient;
import com.microsoft.live.LiveAuthException; import com.microsoft.live.LiveAuthException;
import com.microsoft.live.LiveAuthListener; import com.microsoft.live.LiveAuthListener;
import com.microsoft.live.LiveConnectClient; import com.microsoft.live.LiveConnectClient;
import com.microsoft.live.LiveConnectSession; import com.microsoft.live.LiveConnectSession;
import com.microsoft.live.LiveDownloadOperation;
import com.microsoft.live.LiveOperation; import com.microsoft.live.LiveOperation;
import com.microsoft.live.LiveOperationException; import com.microsoft.live.LiveOperationException;
import com.microsoft.live.LiveStatus; import com.microsoft.live.LiveStatus;
import com.microsoft.live.OverwriteOption;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
public class SkyDriveFileStorage extends JavaFileStorageBase { public class SkyDriveFileStorage extends JavaFileStorageBase {
private LiveAuthClient mAuthClient; private LiveAuthClient mAuthClient;
@ -43,10 +52,10 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
private HashMap<String /* id */, SkyDriveObject> mFolderCache = new HashMap<String, SkyDriveObject>(); private HashMap<String /* id */, SkyDriveObject> mFolderCache = new HashMap<String, SkyDriveObject>();
public static final String[] SCOPES = { public static final String[] SCOPES = { "wl.signin", "wl.skydrive_update", };
"wl.signin",
"wl.skydrive_update", // see http://stackoverflow.com/questions/17997688/howto-to-parse-skydrive-api-date-in-java
}; SimpleDateFormat SKYDRIVE_DATEFORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.ENGLISH);
public final class JsonKeys { public final class JsonKeys {
public static final String CODE = "code"; public static final String CODE = "code";
@ -81,60 +90,58 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
} }
} }
class SkyDrivePath {
class SkyDrivePath
{
String mPath; String mPath;
public SkyDrivePath() public SkyDrivePath() {
{
} }
public SkyDrivePath(String path) throws UnsupportedEncodingException, FileNotFoundException, InvalidPathException, LiveOperationException, SkyDriveException public SkyDrivePath(String path) throws UnsupportedEncodingException,
{ FileNotFoundException, InvalidPathException,
LiveOperationException, SkyDriveException {
setPath(path); setPath(path);
} }
public SkyDrivePath(String parentPath, JSONObject fileToAppend) throws UnsupportedEncodingException, FileNotFoundException, IOException, InvalidPathException, JSONException, LiveOperationException, SkyDriveException public SkyDrivePath(String parentPath, JSONObject fileToAppend)
{ throws UnsupportedEncodingException, FileNotFoundException,
IOException, InvalidPathException, JSONException,
LiveOperationException, SkyDriveException {
setPath(parentPath); setPath(parentPath);
if ((!mPath.endsWith("/")) && (!mPath.equals(""))) if ((!mPath.endsWith("/")) && (!mPath.equals("")))
mPath = mPath + "/"; mPath = mPath + "/";
mPath += encode(fileToAppend.getString("name"))+NAME_ID_SEP+encode(fileToAppend.getString("id")); mPath += encode(fileToAppend.getString("name")) + NAME_ID_SEP
+ encode(fileToAppend.getString("id"));
} }
public void setPath(String path) throws UnsupportedEncodingException, InvalidPathException, FileNotFoundException, LiveOperationException, SkyDriveException { public void setPath(String path) throws UnsupportedEncodingException,
InvalidPathException, FileNotFoundException,
LiveOperationException, SkyDriveException {
setPathWithoutVerify(path); setPathWithoutVerify(path);
verifyWithRetry(); verifyWithRetry();
} }
private void verifyWithRetry() throws FileNotFoundException,
private void verifyWithRetry() throws FileNotFoundException, LiveOperationException, SkyDriveException, UnsupportedEncodingException { LiveOperationException, SkyDriveException,
try UnsupportedEncodingException {
{ try {
verify(); verify();
} } catch (FileNotFoundException e) {
catch (FileNotFoundException e)
{
initializeFoldersCache(); initializeFoldersCache();
verify(); verify();
} }
} }
public void setPathWithoutVerify(String path)
public void setPathWithoutVerify(String path) throws UnsupportedEncodingException, InvalidPathException throws UnsupportedEncodingException, InvalidPathException {
{
mPath = path.substring(getProtocolPrefix().length()); mPath = path.substring(getProtocolPrefix().length());
// Log.d(TAG, " mAccount=" + mAccount); // Log.d(TAG, " mAccount=" + mAccount);
// Log.d(TAG, " mAccountLocalPath=" + mAccountLocalPath); // Log.d(TAG, " mAccountLocalPath=" + mAccountLocalPath);
} }
// make sure the path exists // make sure the path exists
private void verify() throws FileNotFoundException, UnsupportedEncodingException { private void verify() throws FileNotFoundException,
UnsupportedEncodingException {
if (mPath.equals("")) if (mPath.equals(""))
return; return;
@ -143,38 +150,43 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
String parentId = mRootFolderId; String parentId = mRootFolderId;
for (int i=0;i<parts.length;i++) for (int i = 0; i < parts.length; i++) {
{
String part = parts[i]; String part = parts[i];
// Log.d(TAG, "parsing part " + part); // Log.d(TAG, "parsing part " + part);
int indexOfSeparator = part.lastIndexOf(NAME_ID_SEP); int indexOfSeparator = part.lastIndexOf(NAME_ID_SEP);
if (indexOfSeparator < 0) if (indexOfSeparator < 0)
throw new FileNotFoundException("invalid path " + mPath); throw new FileNotFoundException("invalid path " + mPath);
String id = decode(part.substring(indexOfSeparator+NAME_ID_SEP.length())); String id = decode(part.substring(indexOfSeparator
+ NAME_ID_SEP.length()));
String name = decode(part.substring(0, indexOfSeparator)); String name = decode(part.substring(0, indexOfSeparator));
// Log.d(TAG, " name=" + name); // Log.d(TAG, " name=" + name);
SkyDriveObject thisFolder = mFolderCache.get(id); SkyDriveObject thisFolder = mFolderCache.get(id);
if (thisFolder == null) if (thisFolder == null) {
{
thisFolder = tryAddFileToCache(this); thisFolder = tryAddFileToCache(this);
// check if it's still null // check if it's still null
if (thisFolder == null) if (thisFolder == null)
throw new FileNotFoundException("couldn't find id " + id + " being part of "+ mPath+" in SkyDrive "); throw new FileNotFoundException("couldn't find id "
+ id + " being part of " + mPath
+ " in SkyDrive ");
} }
if (thisFolder.getParentId().equals(parentId) == false) if (thisFolder.getParentId().equals(parentId) == false)
throw new FileNotFoundException("couldn't find parent id " + parentId + " as parent of "+thisFolder.getName() +" in "+ mPath+" in SkyDrive"); throw new FileNotFoundException("couldn't find parent id "
+ parentId + " as parent of "
+ thisFolder.getName() + " in " + mPath
+ " in SkyDrive");
if (thisFolder.getName().equals(name) == false) if (thisFolder.getName().equals(name) == false)
throw new FileNotFoundException("Name of "+id+" changed from "+name+" to "+thisFolder.getName() +" in "+ mPath+" in SkyDrive " ); throw new FileNotFoundException("Name of " + id
+ " changed from " + name + " to "
+ thisFolder.getName() + " in " + mPath
+ " in SkyDrive ");
parentId = id; parentId = id;
} }
} }
public String getDisplayName() {
public String getDisplayName()
{
// skydrive:// // skydrive://
String displayName = getProtocolPrefix(); String displayName = getProtocolPrefix();
@ -183,13 +195,11 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
String[] parts = mPath.split("/"); String[] parts = mPath.split("/");
for (int i=0;i<parts.length;i++) for (int i = 0; i < parts.length; i++) {
{
String part = parts[i]; String part = parts[i];
// Log.d(TAG, "parsing part " + part); // Log.d(TAG, "parsing part " + part);
int indexOfSeparator = part.lastIndexOf(NAME_ID_SEP); int indexOfSeparator = part.lastIndexOf(NAME_ID_SEP);
if (indexOfSeparator < 0) if (indexOfSeparator < 0) {
{
// seems invalid, but we're very generous here // seems invalid, but we're very generous here
displayName += "/" + part; displayName += "/" + part;
continue; continue;
@ -205,18 +215,21 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
return displayName; return displayName;
} }
public String getSkyDriveId() throws InvalidPathException,
public String getSkyDriveId() throws InvalidPathException, UnsupportedEncodingException { UnsupportedEncodingException {
String pathWithoutTrailingSlash = mPath; String pathWithoutTrailingSlash = mPath;
if (pathWithoutTrailingSlash.endsWith("/")) if (pathWithoutTrailingSlash.endsWith("/"))
pathWithoutTrailingSlash = pathWithoutTrailingSlash.substring(0,pathWithoutTrailingSlash.length()-1); pathWithoutTrailingSlash = pathWithoutTrailingSlash.substring(
if (pathWithoutTrailingSlash.equals("")) 0, pathWithoutTrailingSlash.length() - 1);
{ if (pathWithoutTrailingSlash.equals("")) {
return mRootFolderId; return mRootFolderId;
} }
String lastPart = pathWithoutTrailingSlash.substring(pathWithoutTrailingSlash.lastIndexOf(NAME_ID_SEP)+NAME_ID_SEP.length()); String lastPart = pathWithoutTrailingSlash
.substring(pathWithoutTrailingSlash
.lastIndexOf(NAME_ID_SEP) + NAME_ID_SEP.length());
if (lastPart.contains("/")) if (lastPart.contains("/"))
throw new InvalidPathException("error extracting SkyDriveId from "+mPath); throw new InvalidPathException(
"error extracting SkyDriveId from " + mPath);
return decode(lastPart); return decode(lastPart);
} }
@ -224,58 +237,126 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
return getProtocolPrefix() + mPath; return getProtocolPrefix() + mPath;
} }
public SkyDrivePath getParentPath() throws UnsupportedEncodingException, FileNotFoundException, InvalidPathException, LiveOperationException, SkyDriveException {
String pathWithoutTrailingSlash = mPath;
if (pathWithoutTrailingSlash.endsWith("/"))
pathWithoutTrailingSlash = pathWithoutTrailingSlash.substring(
0, pathWithoutTrailingSlash.length() - 1);
if (pathWithoutTrailingSlash.equals(""))
{
return null;
}
int indexOfLastSlash = pathWithoutTrailingSlash.lastIndexOf("/");
if (indexOfLastSlash == -1)
{
return new SkyDrivePath(getProtocolPrefix());
}
String parentPath = pathWithoutTrailingSlash.substring(0, indexOfLastSlash);
return new SkyDrivePath(getProtocolPrefix()+parentPath);
}
public String getFilename() throws InvalidPathException {
String pathWithoutTrailingSlash = mPath;
if (pathWithoutTrailingSlash.endsWith("/"))
pathWithoutTrailingSlash = pathWithoutTrailingSlash.substring(
0, pathWithoutTrailingSlash.length() - 1);
String[] parts = mPath.split("/");
String lastPart = parts[parts.length-1];
int indexOfSeparator = lastPart.lastIndexOf(NAME_ID_SEP);
if (indexOfSeparator < 0) {
throw new InvalidPathException("cannot extract filename from " + mPath);
}
String name = lastPart.substring(0, indexOfSeparator);
try {
name = decode(name);
} catch (UnsupportedEncodingException e) {
// ignore
}
return name;
}
}; };
public SkyDriveFileStorage(String clientId, Context appContext) {
public SkyDriveFileStorage(String clientId, Context appContext)
{
mAuthClient = new LiveAuthClient(appContext, clientId); mAuthClient = new LiveAuthClient(appContext, clientId);
} }
void login(final FileStorageSetupActivity activity) void login(final FileStorageSetupActivity activity) {
{ mAuthClient.login((Activity) activity, Arrays.asList(SCOPES),
mAuthClient.login((Activity)activity,
Arrays.asList(SCOPES),
new LiveAuthListener() { new LiveAuthListener() {
@Override @Override
public void onAuthComplete(LiveStatus status, public void onAuthComplete(LiveStatus status,
LiveConnectSession session, LiveConnectSession session, Object userState) {
Object userState) {
if (status == LiveStatus.CONNECTED) { if (status == LiveStatus.CONNECTED) {
try initialize(activity, session);
{
initializeSession(session);
finishActivityWithSuccess(activity);
}
catch (Exception e)
{
finishWithError((Activity)activity, e);
}
} else { } else {
finishWithError((Activity)activity, new Exception("Error connecting to SkdDrive. Status is "+status)); finishWithError((Activity) activity, new Exception(
"Error connecting to SkdDrive. Status is "
+ status));
} }
} }
@Override @Override
public void onAuthError(LiveAuthException exception, Object userState) { public void onAuthError(LiveAuthException exception,
Object userState) {
finishWithError((Activity) activity, exception); finishWithError((Activity) activity, exception);
} }
}); });
} }
private void initializeSession(LiveConnectSession session) throws LiveOperationException, SkyDriveException { private void initialize(final FileStorageSetupActivity setupAct,
LiveConnectSession session) {
mSession = session; mSession = session;
mConnectClient = new LiveConnectClient(session); mConnectClient = new LiveConnectClient(session);
final Activity activity = (Activity)setupAct;
AsyncTask<Object, Void, AsyncTaskResult<String> > task = new AsyncTask<Object, Void, AsyncTaskResult<String>>()
{
@Override
protected AsyncTaskResult<String> doInBackground(Object... arg0) {
try {
initializeFoldersCache(); initializeFoldersCache();
if (setupAct.getProcessName().equals(PROCESS_NAME_SELECTFILE))
setupAct.getState().putString(EXTRA_PATH, getProtocolPrefix());
return new AsyncTaskResult<String>("ok");
} catch ( Exception anyError) {
return new AsyncTaskResult<String>(anyError);
}
}
@Override
protected void onPostExecute(AsyncTaskResult<String> result) {
Exception error = result.getError();
if (error != null ) {
finishWithError(activity, error);
} else if ( isCancelled()) {
activity.setResult(Activity.RESULT_CANCELED);
activity.finish();
} else {
//all right!
finishActivityWithSuccess(setupAct);
}
}
};
task.execute(new Object[]{});
} }
private void initializeFoldersCache() throws LiveOperationException, SkyDriveException {
private void initializeFoldersCache() throws LiveOperationException,
SkyDriveException, FileNotFoundException {
//use alias for now (overwritten later):
mRootFolderId = "me/skydrive"; mRootFolderId = "me/skydrive";
LiveOperation operation = mConnectClient.get(mRootFolderId + "/files"); LiveOperation operation = mConnectClient.get(mRootFolderId + "/files");
@ -287,44 +368,64 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
JSONArray data = result.optJSONArray(JsonKeys.DATA); JSONArray data = result.optJSONArray(JsonKeys.DATA);
for (int i = 0; i < data.length(); i++) { for (int i = 0; i < data.length(); i++) {
SkyDriveObject skyDriveObj = SkyDriveObject.create(data.optJSONObject(i)); SkyDriveObject skyDriveObj = SkyDriveObject.create(data
.optJSONObject(i));
if (skyDriveObj == null) if (skyDriveObj == null)
continue; // ignored type continue; // ignored type
Log.d(TAG, "adding "+skyDriveObj.getName()+" to cache with id " + skyDriveObj.getId()+" in "+skyDriveObj.getParentId());
mFolderCache.put(skyDriveObj.getId(), skyDriveObj); mFolderCache.put(skyDriveObj.getId(), skyDriveObj);
mRootFolderId = skyDriveObj.getParentId();
}
//check if we received anything. If not: query the root folder directly
if (data.length() == 0)
{
operation = mConnectClient.get(mRootFolderId);
result = operation.getResult();
checkResult(result);
mRootFolderId = SkyDriveObject.create(result).getId();
} }
} }
private void checkResult(JSONObject result) throws SkyDriveException { private void checkResult(JSONObject result) throws SkyDriveException, FileNotFoundException {
if (result.has(JsonKeys.ERROR)) { if (result.has(JsonKeys.ERROR)) {
JSONObject error = result.optJSONObject(JsonKeys.ERROR); JSONObject error = result.optJSONObject(JsonKeys.ERROR);
String message = error.optString(JsonKeys.MESSAGE); String message = error.optString(JsonKeys.MESSAGE);
String code = error.optString(JsonKeys.CODE); String code = error.optString(JsonKeys.CODE);
Log.d(TAG, "Code: "+code);
if ("resource_not_found".equals(code))
throw new FileNotFoundException(message);
else
throw new SkyDriveException(message, code); throw new SkyDriveException(message, code);
} }
} }
private SkyDriveObject tryAddFileToCache(SkyDrivePath skyDrivePath) { private SkyDriveObject tryAddFileToCache(SkyDrivePath skyDrivePath) {
try try {
{ SkyDriveObject obj = getSkyDriveObject(skyDrivePath);
LiveOperation operation = mConnectClient.get(skyDrivePath.getSkyDriveId()); if (obj != null) {
JSONObject result = operation.getResult();
checkResult(result);
SkyDriveObject obj = SkyDriveObject.create(result);
if (obj != null)
{
mFolderCache.put(obj.getId(), obj); mFolderCache.put(obj.getId(), obj);
} }
return obj; return obj;
} } catch (Exception e) {
catch (Exception e)
{
return null; return null;
} }
} }
private SkyDriveObject getSkyDriveObject(SkyDrivePath skyDrivePath)
throws LiveOperationException, InvalidPathException,
UnsupportedEncodingException, SkyDriveException, FileNotFoundException {
LiveOperation operation = mConnectClient.get(skyDrivePath
.getSkyDriveId());
JSONObject result = operation.getResult();
checkResult(result);
SkyDriveObject obj = SkyDriveObject.create(result);
return obj;
}
@Override @Override
public boolean requiresSetup(String path) { public boolean requiresSetup(String path) {
// always go through the setup process: // always go through the setup process:
@ -335,14 +436,17 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
public void startSelectFile(FileStorageSetupInitiatorActivity activity, public void startSelectFile(FileStorageSetupInitiatorActivity activity,
boolean isForSave, int requestCode) { boolean isForSave, int requestCode) {
((JavaFileStorage.FileStorageSetupInitiatorActivity)(activity)).startSelectFileProcess(getProtocolId()+"://", isForSave, requestCode); ((JavaFileStorage.FileStorageSetupInitiatorActivity) (activity))
.startSelectFileProcess(getProtocolId() + "://", isForSave,
requestCode);
} }
@Override @Override
public void prepareFileUsage(FileStorageSetupInitiatorActivity activity, public void prepareFileUsage(FileStorageSetupInitiatorActivity activity,
String path, int requestCode) { String path, int requestCode) {
((JavaFileStorage.FileStorageSetupInitiatorActivity)(activity)).startFileUsageProcess(path, requestCode); ((JavaFileStorage.FileStorageSetupInitiatorActivity) (activity))
.startFileUsageProcess(path, requestCode);
} }
@ -356,60 +460,124 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
return ""; return "";
/* /*
SkyDrivePath skydrivePath = new SkyDrivePath(); * SkyDrivePath skydrivePath = new SkyDrivePath(); try {
try { * skydrivePath.setPathWithoutVerify(path); } catch (Exception e) {
skydrivePath.setPathWithoutVerify(path); * e.printStackTrace(); return path; } return
} catch (Exception e) { * skydrivePath.getDisplayName();
e.printStackTrace(); */
return path;
}
return skydrivePath.getDisplayName();*/
} }
@Override @Override
public boolean checkForFileChangeFast(String path, public boolean checkForFileChangeFast(String path,
String previousFileVersion) throws Exception { String previousFileVersion) throws Exception {
// TODO Auto-generated method stub
String currentVersion = getCurrentFileVersionFast(path);
if (currentVersion == null)
return false; return false;
return currentVersion.equals(previousFileVersion) == false;
} }
@Override @Override
public String getCurrentFileVersionFast(String path) { public String getCurrentFileVersionFast(String path) {
// TODO Auto-generated method stub try
{
SkyDrivePath drivePath = new SkyDrivePath(path);
SkyDriveObject obj = getSkyDriveObject(drivePath);
if (obj == null)
return null; return null;
return obj.getUpdatedTime();
}
catch (Exception e)
{
Log.w(TAG,"Error getting file version:");
e.printStackTrace();
return null;
}
} }
@Override @Override
public InputStream openFileForRead(String path) throws Exception { public InputStream openFileForRead(String path) throws Exception {
// TODO Auto-generated method stub try
return null; {
LiveDownloadOperation op = mConnectClient.download(new SkyDrivePath(path).getSkyDriveId()+"/content");
return op.getStream();
}
catch (Exception e)
{
throw convertException(e);
}
} }
@Override @Override
public void uploadFile(String path, byte[] data, boolean writeTransactional) public void uploadFile(String path, byte[] data, boolean writeTransactional)
throws Exception { throws Exception {
// TODO Auto-generated method stub
try
{
SkyDrivePath driveTargetPath = new SkyDrivePath(path);
SkyDrivePath driveUploadPath = driveTargetPath;
SkyDrivePath driveTempPath = null;
ByteArrayInputStream bis = new ByteArrayInputStream(data);
//if writeTransactional, upload the file to a temp destination.
//this is a somewhat ugly way because it requires two uploads, but renaming/copying doesn't work
//nicely in SkyDrive, and SkyDrive doesn't provide file histories by itself, so we need to make sure
//no file gets corrupt if upload is canceled.
if (writeTransactional)
{
LiveOperation uploadOp = uploadFile(driveUploadPath.getParentPath(), driveUploadPath.getFilename()+".tmp", bis);
driveTempPath = new SkyDrivePath(driveUploadPath.getParentPath().getFullPath(), uploadOp.getResult());
//recreate ByteArrayInputStream for use in uploadFile below
bis = new ByteArrayInputStream(data);
}
//upload the file
uploadFile(driveUploadPath.getParentPath(), driveUploadPath.getFilename(), bis);
if (writeTransactional)
{
//delete old file
mConnectClient.delete(driveTempPath.getSkyDriveId());
// don't check result. If delete fails -> not a big deal
}
}
catch (Exception e)
{
throw convertException(e);
}
}
private LiveOperation uploadFile(SkyDrivePath parentPath, String filename, ByteArrayInputStream bis)
throws LiveOperationException, InvalidPathException,
UnsupportedEncodingException, FileNotFoundException,
SkyDriveException {
LiveOperation op = mConnectClient.upload(parentPath.getSkyDriveId(), filename, bis, OverwriteOption.Overwrite);
checkResult(op.getResult());
return op;
} }
@Override @Override
public String createFolder(String parentPath, String newDirName) public String createFolder(String parentPath, String newDirName)
throws Exception { throws Exception {
try try {
{
SkyDrivePath skyDriveParentPath = new SkyDrivePath(parentPath); SkyDrivePath skyDriveParentPath = new SkyDrivePath(parentPath);
String parentId = skyDriveParentPath.getSkyDriveId();
JSONObject newFolder = new JSONObject(); JSONObject newFolder = new JSONObject();
newFolder.put("name", newDirName); newFolder.put("name", newDirName);
newFolder.put("description", "folder");
LiveOperation operation = mConnectClient.put(skyDriveParentPath.getSkyDriveId(), newFolder); LiveOperation operation = mConnectClient.post(
parentId, newFolder);
JSONObject result = operation.getResult(); JSONObject result = operation.getResult();
checkResult(result); checkResult(result);
return new SkyDrivePath(parentPath, result).getFullPath(); return new SkyDrivePath(parentPath, result).getFullPath();
} } catch (Exception e) {
catch(Exception e)
{
throw convertException(e); throw convertException(e);
} }
@ -427,25 +595,108 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
@Override @Override
public String createFilePath(String parentPath, String newFileName) public String createFilePath(String parentPath, String newFileName)
throws Exception { throws Exception {
// TODO Auto-generated method stub try {
return null; SkyDrivePath skyDriveParentPath = new SkyDrivePath(parentPath);
LiveOperation op = uploadFile(skyDriveParentPath, newFileName, new ByteArrayInputStream(new byte[0]));
checkResult(op.getResult());
return new SkyDrivePath(parentPath, op.getResult()).getFullPath();
} catch (Exception e) {
throw convertException(e);
}
} }
@Override @Override
public List<FileEntry> listFiles(String parentPath) throws Exception { public List<FileEntry> listFiles(String parentPath) throws Exception {
// TODO Auto-generated method stub
return null; try
{
SkyDrivePath parentDrivePath = new SkyDrivePath(parentPath);
LiveOperation operation = mConnectClient.get(parentDrivePath.getSkyDriveId() + "/files");
JSONObject result = operation.getResult();
checkResult(result);
JSONArray data = result.optJSONArray(JsonKeys.DATA);
List<FileEntry> resultList = new ArrayList<FileEntry>(data.length());
for (int i = 0; i < data.length(); i++) {
SkyDriveObject skyDriveObj = SkyDriveObject.create(data
.optJSONObject(i));
if (skyDriveObj == null)
continue; // ignored type
Log.d(TAG, "listing "+skyDriveObj.getName()+" with id " + skyDriveObj.getId()+" in "+skyDriveObj.getParentId());
resultList.add(convertToFileEntry(parentDrivePath, skyDriveObj));
}
return resultList;
}
catch (Exception e)
{
throw convertException(e);
}
}
private FileEntry convertToFileEntry(SkyDrivePath parentPath, SkyDriveObject skyDriveObj) throws UnsupportedEncodingException, FileNotFoundException, IOException, InvalidPathException, JSONException, LiveOperationException, SkyDriveException {
FileEntry res = new FileEntry();
res.canRead = true;
res.canWrite = true;
res.displayName = skyDriveObj.getName();
res.isDirectory = SkyDriveFolder.class.isAssignableFrom(skyDriveObj.getClass());
try
{
res.lastModifiedTime = SKYDRIVE_DATEFORMATTER.parse(skyDriveObj.getUpdatedTime()).getTime();
}
catch (Exception e)
{
Log.w(TAG, "Cannot parse time " + skyDriveObj.getUpdatedTime());
res.lastModifiedTime = -1;
}
if (parentPath == null) //this is the case if we're listing the parent path itself
res.path = getProtocolPrefix();
else
res.path = new SkyDrivePath(parentPath.getFullPath(), skyDriveObj.toJson()).getFullPath();
Log.d(TAG, "path: "+res.path);
if (SkyDriveFile.class.isAssignableFrom(skyDriveObj.getClass()))
{
res.sizeInBytes = ((SkyDriveFile)skyDriveObj).getSize();
}
return res;
} }
@Override @Override
public FileEntry getFileEntry(String filename) throws Exception { public FileEntry getFileEntry(String filename) throws Exception {
// TODO Auto-generated method stub try
return null; {
SkyDrivePath drivePath = new SkyDrivePath(filename);
Log.d(TAG, "getFileEntry for "+ filename +" = "+drivePath.getFullPath());
Log.d(TAG, " parent is "+drivePath.getParentPath());
return convertToFileEntry(drivePath.getParentPath(),getSkyDriveObject(drivePath));
}
catch (Exception e)
{
throw convertException(e);
}
} }
@Override @Override
public void delete(String path) throws Exception { public void delete(String path) throws Exception {
// TODO Auto-generated method stub try
{
SkyDrivePath drivePath = new SkyDrivePath(path);
LiveOperation op = mConnectClient.delete(drivePath.getSkyDriveId());
checkResult(op.getResult());
}
catch (Exception e)
{
throw convertException(e);
}
} }
@ -453,17 +704,14 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
public void onCreate(FileStorageSetupActivity activity, public void onCreate(FileStorageSetupActivity activity,
Bundle savedInstanceState) { Bundle savedInstanceState) {
} }
@Override @Override
public void onResume(FileStorageSetupActivity activity) { public void onResume(FileStorageSetupActivity activity) {
} }
private void finishWithError(final Activity activity, private void finishWithError(final Activity activity, Exception error) {
Exception error) {
Log.e("KP2AJ", "Exception: " + error.toString()); Log.e("KP2AJ", "Exception: " + error.toString());
error.printStackTrace(); error.printStackTrace();
@ -473,13 +721,13 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
activity.finish(); activity.finish();
}; };
private void finishActivityWithSuccess(
private void finishActivityWithSuccess(FileStorageSetupActivity setupActivity) { FileStorageSetupActivity setupActivity) {
Log.d("KP2AJ", "Success with authenticating!"); Log.d("KP2AJ", "Success with authenticating!");
Activity activity = (Activity) setupActivity; Activity activity = (Activity) setupActivity;
if (setupActivity.getProcessName().equals(PROCESS_NAME_FILE_USAGE_SETUP)) if (setupActivity.getProcessName()
{ .equals(PROCESS_NAME_FILE_USAGE_SETUP)) {
Intent data = new Intent(); Intent data = new Intent();
data.putExtra(EXTRA_IS_FOR_SAVE, setupActivity.isForSave()); data.putExtra(EXTRA_IS_FOR_SAVE, setupActivity.isForSave());
data.putExtra(EXTRA_PATH, setupActivity.getPath()); data.putExtra(EXTRA_PATH, setupActivity.getPath());
@ -487,8 +735,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
activity.finish(); activity.finish();
return; return;
} }
if (setupActivity.getProcessName().equals(PROCESS_NAME_SELECTFILE)) if (setupActivity.getProcessName().equals(PROCESS_NAME_SELECTFILE)) {
{
Intent data = new Intent(); Intent data = new Intent();
String path = setupActivity.getState().getString(EXTRA_PATH); String path = setupActivity.getState().getString(EXTRA_PATH);
@ -501,33 +748,24 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
Log.w("KP2AJ", "Unknown process: " + setupActivity.getProcessName()); Log.w("KP2AJ", "Unknown process: " + setupActivity.getProcessName());
} }
@Override @Override
public void onStart(final FileStorageSetupActivity activity) { public void onStart(final FileStorageSetupActivity activity) {
mAuthClient.initialize(Arrays.asList(SCOPES), new LiveAuthListener() { mAuthClient.initialize(Arrays.asList(SCOPES), new LiveAuthListener() {
@Override @Override
public void onAuthError(LiveAuthException exception, Object userState) { public void onAuthError(LiveAuthException exception,
Object userState) {
finishWithError(((Activity) activity), exception); finishWithError(((Activity) activity), exception);
} }
@Override @Override
public void onAuthComplete(LiveStatus status, public void onAuthComplete(LiveStatus status,
LiveConnectSession session, LiveConnectSession session, Object userState) {
Object userState) {
if (status == LiveStatus.CONNECTED) { if (status == LiveStatus.CONNECTED) {
try initialize(activity, session);
{
initializeSession(session);
finishActivityWithSuccess(activity);
}
catch (Exception e)
{
finishWithError((Activity)activity, e);
}
} else { } else {
login(activity); login(activity);
} }

View File

@ -1,4 +1,4 @@
package keepass2android.javafilestorage; package keepass2android.javafilestorage.skydrive;
public class SkyDriveException extends Exception { public class SkyDriveException extends Exception {

View File

@ -1,4 +1,5 @@
package keepass2android.javafilestorage; package keepass2android.javafilestorage.skydrive;
import org.json.JSONObject; import org.json.JSONObject;

View File

@ -1,4 +1,4 @@
package keepass2android.javafilestorage; package keepass2android.javafilestorage.skydrive;
import org.json.JSONObject; import org.json.JSONObject;

View File

@ -1,4 +1,5 @@
package keepass2android.javafilestorage; package keepass2android.javafilestorage.skydrive;
import org.json.JSONObject; import org.json.JSONObject;