private static String folderContains(String filename, String folderID) {

    // Returns the ID of a specified filename in a folder or null if it does not exist

    File child = null;
    ChildList children = null;
    try {
      children = service.children().list(folderID).execute();
      for (ChildReference element : children.getItems()) {
        child = service.files().get(element.getId()).execute();
        if (child.getTitle().equals(filename)) {
          break;
        }
      }
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      // System.out.println("children: "+children.toPrettyString());
      // System.out.println("child: "+child.toPrettyString());
    }

    if (child != null && child.getTitle().equals(filename)) {
      return child.getId();
    }

    return null;
  }
Beispiel #2
0
  /**
   * Insert new Google Drive files in the local database.
   *
   * @param driveFiles Collection of Google Drive files to insert.
   */
  private void insertNewDriveFiles(Collection<File> driveFiles) {
    Uri uri = getNotesUri(mAccount.name);

    Log.d(TAG, "Inserting new Drive files: " + driveFiles.size());

    for (File driveFile : driveFiles) {
      if (driveFile != null) {
        ContentValues values = new ContentValues();
        values.put(NotePad.Notes.COLUMN_NAME_ACCOUNT, mAccount.name);
        values.put(NotePad.Notes.COLUMN_NAME_FILE_ID, driveFile.getId());
        values.put(NotePad.Notes.COLUMN_NAME_TITLE, driveFile.getTitle());
        values.put(NotePad.Notes.COLUMN_NAME_NOTE, getFileContent(driveFile));
        values.put(NotePad.Notes.COLUMN_NAME_CREATE_DATE, driveFile.getCreatedDate().getValue());
        values.put(
            NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE, driveFile.getModifiedDate().getValue());
        try {
          mProvider.insert(uri, values);
        } catch (RemoteException e) {
          e.printStackTrace();
        }
      }
    }

    mContext.getContentResolver().notifyChange(uri, null, false);
  }
  private static String determineParent(String email, String workflow) {
    String root = "0B7Jfx3RRVE5YenZEY1N5cE5pRms";
    String parentFolder = null;

    String level = root;
    String parent = root;
    boolean lowest = false;

    // Checks for user
    level = folderContains(email, level);
    if (level != null) {

      DateFormat today = new SimpleDateFormat("E, MM/dd/yyyy");
      Date now = new Date();
      String nowStr = today.format(now);

      // Checks for today's date
      parent = level;
      level = folderContains(nowStr, level);
      if (level != null) {

        // Checks for a workflowID folder
        parent = level;
        level = folderContains(workflow, level);
        // System.out.println("level: "+level);
        if (level != null) {

          // Finds the highest folder number; add 1 and creates it.
          try {
            File child = null;
            int lastRun = 0;
            int tmp = lastRun;
            ChildList children = service.children().list(level).execute();
            for (ChildReference element : children.getItems()) {
              child = service.files().get(element.getId()).execute();
              try {
                tmp = Integer.parseInt(child.getTitle());
                if (tmp > lastRun) {
                  lastRun = tmp;
                }
              } catch (NumberFormatException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              }
            }
            lastRun += 1;
            String next = new Integer(lastRun).toString();
            // System.out.println("level: "+level);
            // System.out.println("next: "+next);
            parentFolder = createFolderWithParentAndTitle(level, next);

          } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

          } finally {
            lowest = true;
          }

        } else {
          parentFolder = createFolderWithParentAndTitle(parent, workflow);
        }
      } else {
        parentFolder = createFolderWithParentAndTitle(parent, nowStr);
      }
    } else {
      parentFolder = createFolderWithParentAndTitle(parent, email);
    }

    try {
      File file = service.files().get(parentFolder).execute();
      service.permissions().insert(file.getId(), perm).execute();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    if (!lowest) parentFolder = determineParent(email, workflow);

    return parentFolder;
  }
Beispiel #4
0
  /**
   * Merge a local file with a Google Drive File.
   *
   * <p>The last modification is used to check which file to sync from. Then, the md5 checksum of
   * the file is used to check whether or not the file's content should be sync'ed.
   *
   * @param localFileUri Local file URI to save local changes against.
   * @param localFile Local file cursor to retrieve data from.
   * @param driveFile Google Drive file.
   */
  private void mergeFiles(Uri localFileUri, Cursor localFile, File driveFile) {
    long localFileModificationDate = localFile.getLong(COLUMN_INDEX_MODIFICATION_DATE);

    Log.d(
        TAG,
        "Modification dates: "
            + localFileModificationDate
            + " - "
            + driveFile.getModifiedDate().getValue());
    if (localFileModificationDate > driveFile.getModifiedDate().getValue()) {
      try {
        if (localFile.getShort(COLUMN_INDEX_DELETED) != 0) {
          Log.d(TAG, "  > Deleting Drive file.");
          mService.files().delete(driveFile.getId()).execute();
          mProvider.delete(localFileUri, null, null);
        } else {
          String localNote = localFile.getString(COLUMN_INDEX_NOTE);
          File updatedFile = null;

          // Update drive file.
          Log.d(TAG, "  > Updating Drive file.");
          driveFile.setTitle(localFile.getString(COLUMN_INDEX_TITLE));

          if (md5(localNote) != driveFile.getMd5Checksum()) {
            // Update both content and metadata.
            ByteArrayContent content = ByteArrayContent.fromString(TEXT_PLAIN, localNote);
            updatedFile = mService.files().update(driveFile.getId(), driveFile, content).execute();
          } else {
            // Only update the metadata.
            updatedFile = mService.files().update(driveFile.getId(), driveFile).execute();
          }

          ContentValues values = new ContentValues();
          values.put(
              NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE,
              updatedFile.getModifiedDate().getValue());
          mProvider.update(localFileUri, values, null, null);
        }
      } catch (IOException e) {
        e.printStackTrace();
      } catch (RemoteException e) {
        e.printStackTrace();
      }
    } else if (localFileModificationDate < driveFile.getModifiedDate().getValue()) {
      // Update local file.
      Log.d(TAG, "  > Updating local file.");
      ContentValues values = new ContentValues();
      values.put(NotePad.Notes.COLUMN_NAME_TITLE, driveFile.getTitle());
      values.put(
          NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE, driveFile.getModifiedDate().getValue());
      // Only download the content if it has changed.
      if (md5(localFile.getString(COLUMN_INDEX_NOTE)) != driveFile.getMd5Checksum()) {
        values.put(NotePad.Notes.COLUMN_NAME_NOTE, getFileContent(driveFile));
      }
      try {
        mProvider.update(localFileUri, values, null, null);
      } catch (RemoteException e) {
        e.printStackTrace();
      }
    }
  }
  private void synchronize(ChangeRecord record) throws IOException {
    try {
      switch (record.getOperation()) {
        case LOCAL_INSERT:
          {
            // Get remote id for the parent folder
            File local = DriveUtils.absolutePath(record.getLocalFile());
            String remoteParent =
                stub.storage().localToRemote().get(DriveUtils.relativePath(local.getParentFile()));
            if (!StringUtils.isEmpty(remoteParent)
                && !stub.storage().localToRemote().containsKey(record.getLocalFile())) {
              // Ignore insert request that doesn't have a parent or
              // already have a mapping.
              // The insert operation will be accomplished by the topmost
              // folder
              String remoteId = stub.transmit().upload(remoteParent, local);
              record.setRemoteFileId(remoteId);
            }
            break;
          }
        case LOCAL_DELETE:
          {
            if (!StringUtils.isEmpty(record.getRemoteFileId())) {
              stub.transmit().delete(record.getRemoteFileId());
            } else {
              logger.warn(
                  "Local deletion has no remote reference, make sure the storage is correct.");
            }
            break;
          }
        case LOCAL_CHANGE:
          {
            if (!StringUtils.isEmpty(record.getRemoteFileId())) {
              File local = DriveUtils.absolutePath(record.getLocalFile());
              stub.transmit().update(record.getRemoteFileId(), local);
            } else {
              logger.warn(
                  "Local change has no remote reference, make sure the storage is correct.");
              logger.warn("Trying to insert the new record");
              // Modify it to a local insert
              record.setOperation(Operation.LOCAL_INSERT);
              synchronize(record);
            }
            break;
          }
        case LOCAL_RENAME:
          {
            if (!StringUtils.isEmpty(record.getRemoteFileId())) {
              stub.transmit().rename(record.getRemoteFileId(), (String) record.getContext()[0]);
            } else {
              logger.warn(
                  "Local rename has no remote reference, make sure the storage is correct.");
              logger.warn("Trying to insert the new record");
              // Modify it to be a local insert
              record.setOperation(Operation.LOCAL_INSERT);
              synchronize(record);
            }
            break;
          }
        case REMOTE_INSERT:
          {
            if (stub.storage().remoteToLocal().containsKey(record.getRemoteFileId())) {
              // This file/folder already had been created
              break;
            }
            com.google.api.services.drive.model.File file = record.getContext(0);

            // Depth search of parent that has a local root
            List<ParentReference> path = new ArrayList<ParentReference>();
            File local = pathToLocal(record.getRemoteFileId(), path);
            if (null == local) {
              // Check whether this file is trashed
              if (file.getLabels().getTrashed()) {
                return;
              }
              if (file.getShared()) {
                return;
              } else {
                throw new IllegalArgumentException("Non-trash file has no known parent");
              }
            }
            File parent = local;
            for (ParentReference node : path) {
              stub.transmit().download(node.getId(), parent);
              parent = DriveUtils.absolutePath(stub.storage().remoteToLocal().get(node.getId()));
            }
            stub.transmit().download(record.getRemoteFileId(), parent);
            record.setLocalFile(stub.storage().remoteToLocal().get(record.getRemoteFileId()));
            if (StringUtils.isEmpty(record.getLocalFile())) {
              break;
            }
            break;
          }
        case REMOTE_DELETE:
          {
            if (StringUtils.isEmpty(record.getLocalFile())) {
              // No local file, remote file should be a trashed one.
              if (logger.isDebugEnabled()) {
                logger.debug(
                    "No corresponding local file for deletion. Remote file may be trashed");
              }
              break;
            }
            File localFile = DriveUtils.absolutePath(record.getLocalFile());
            String localParent = DriveUtils.relativePath(localFile.getParentFile());
            // Preserve the original context
            record.setContext(new Object[] {record.getContext(0), localParent});
            deleteLocalFile(localFile);
            if (localFile.exists()) {
              if (logger.isDebugEnabled()) {
                logger.debug(
                    MessageFormat.format(
                        "Failed to delete file {0}. File may have been deleted.",
                        record.getLocalFile()));
              }
            }
            stub.storage().localToRemote().remove(record.getLocalFile());
            stub.storage().remoteToLocal().remove(record.getRemoteFileId());
            break;
          }
        case REMOTE_CHANGE:
          {
            File local = DriveUtils.absolutePath(record.getLocalFile());
            File localParent = local.getParentFile();
            com.google.api.services.drive.model.File remote = record.getContext(0);

            if (!remote.getTitle().equals(local.getName())) {
              local.delete();
              stub.storage().localToRemote().remove(record.getLocalFile());
              stub.storage().remoteToLocal().remove(record.getRemoteFileId());
            }
            stub.transmit().download(record.getRemoteFileId(), localParent);
            break;
          }
        case REMOTE_RENAME:
          {
            File local = DriveUtils.absolutePath(record.getLocalFile());
            com.google.api.services.drive.model.File remote = record.getContext(0);
            String remoteName = remote.getTitle();
            File newName =
                new File(local.getParentFile().getAbsolutePath() + File.separator + remoteName);
            String relNewName = DriveUtils.relativePath(newName);
            record.setContext(new Object[] {record.getContext()[0], relNewName});
            local.renameTo(newName);
            stub.storage()
                .remoteToLocal()
                .put(record.getRemoteFileId(), DriveUtils.relativePath(newName));
            stub.storage().localToRemote().remove(DriveUtils.relativePath(local));
            stub.storage()
                .localToRemote()
                .put(DriveUtils.relativePath(newName), record.getRemoteFileId());
            break;
          }
      }
    } catch (Exception e) {
      logger.warn(MessageFormat.format("Exception on Change {0}. Retry later", record), e);
      FailedRecord fr = new FailedRecord(record);
      if (e instanceof GoogleJsonResponseException) {
        GoogleJsonResponseException gjre = (GoogleJsonResponseException) e;
        fr.setError(String.valueOf(gjre.getDetails().getCode()));
      } else {
        fr.setError(e.getMessage());
      }
      stub.storage().failedLog().add(fr);
    }
  }
  private void syncNotes(final String syncAccountName, final String accessToken) {
    final Drive drive = getDriveService(syncAccountName, accessToken);
    ContentResolver cr = getContentResolver();
    try {
      // loop over saved files and add any new notes to drive
      Cursor savedNotes =
          cr.query(NotesProvider.CONTENT_URI, NotesSyncQuery.PROJECTION, null, null, null);
      if (savedNotes.moveToFirst()) {
        do {
          final String driveId = savedNotes.getString(NotesSyncQuery.DRIVE_ID);
          if (TextUtils.isEmpty(driveId)) {
            // exists locally but not in drive Ð upload it
            File newNote = new File();
            newNote.setTitle(savedNotes.getString(NotesSyncQuery.TITLE));
            newNote.setMimeType(NOTE_MIME_TYPE);

            File inserted =
                drive
                    .files()
                    .insert(
                        newNote,
                        ByteArrayContent.fromString(
                            NOTE_MIME_TYPE, savedNotes.getString(NotesSyncQuery.BODY)))
                    .execute();

            // save the drive id to the db
            ContentValues cv = new ContentValues();
            cv.put(NotesProvider.KEY_DRIVE_ID, inserted.getId());
            Uri noteUri =
                ContentUris.withAppendedId(
                    NotesProvider.CONTENT_URI, savedNotes.getLong(NotesSyncQuery.ID));
            cr.update(noteUri, cv, null, null);
          } else {
            // TODO compare timestamps etc.
          }
        } while (savedNotes.moveToNext());
      }

      // loop over all files in drive and see if any need to be
      // synced locally
      FileList driveFilesList = drive.files().list().execute();
      for (File remote : driveFilesList.getItems()) {
        if (remote.getLabels().getTrashed()) {
          // skip deleted files
          continue;
        }
        final String where = NotesProvider.KEY_DRIVE_ID + "=?";
        final String[] arguments = new String[] {remote.getId()};
        Cursor c =
            cr.query(
                NotesProvider.CONTENT_URI, NotesDownloadQuery.PROJECTION, where, arguments, null);
        if (c.getCount() == 0) {
          // exists in drive but not locally Ð download it
          final String title = remote.getTitle();
          final String body = getFileContents(drive, remote.getDownloadUrl());
          final ContentValues cv = new ContentValues();
          cv.put(NotesProvider.KEY_TITLE, title);
          cv.put(NotesProvider.KEY_BODY, body);
          cv.put(NotesProvider.KEY_DRIVE_ID, remote.getId());
          cv.put(NotesProvider.KEY_LAST_MODIFIED, remote.getModifiedDate().getValue());
          cr.insert(NotesProvider.CONTENT_URI, cv);
        } else {
          // TODO compare timestamps etc.
        }
      }

    } catch (IOException e) {
      // FIXME error handling
      Log.e(getClass().getSimpleName(), "Drive esplode", e);
    }
  }