protected int addItem(SyncItem item) throws SyncException {
    if (Log.isLoggable(Log.DEBUG)) {
      Log.debug(TAG_LOG, "addItem");
    }
    JSONSyncItem jsonSyncItem = (JSONSyncItem) item;
    try {
      String fullName = getFileFullName(jsonSyncItem.getContentName());

      FileAdapter tgtFile = new FileAdapter(fullName);
      if (tgtFile.exists()) {
        // This is the case where the client and the server have a file
        // with the very same name but different content. In this case
        // we rename the destination file
        fullName = createUniqueFileName(fullName);
        if (Log.isLoggable(Log.INFO)) {
          Log.info(TAG_LOG, "Changing target file name to avoid clashing " + fullName);
        }
      }
      tgtFile.close();

      item.setKey(fullName);
      if (Log.isLoggable(Log.DEBUG)) {
        Log.debug(TAG_LOG, "key set to:" + fullName);
      }
      // This is a new file, rename the temp file
      String sourceFileName = createTempFileName(jsonSyncItem.getContentName());
      renameTempFile(sourceFileName, fullName);

      super.addItem(item);
      return SyncSource.SUCCESS_STATUS;
    } catch (IOException ioe) {
      Log.error(TAG_LOG, "Cannot rename temporary file", ioe);
      throw new SyncException(SyncException.CLIENT_ERROR, "Cannot rename temporary file");
    }
  }
 private String createUniqueFileName(String origFileName) throws IOException {
   // Search for the extension
   int lastPeriodIdx = origFileName.lastIndexOf('.');
   String prefix = "";
   String suffix = "";
   if (lastPeriodIdx == -1) {
     prefix = origFileName;
   } else {
     prefix = origFileName.substring(0, lastPeriodIdx);
     if (lastPeriodIdx < origFileName.length() - 1) {
       suffix = origFileName.substring(lastPeriodIdx + 1);
     }
   }
   // Search for a possible file name
   for (int i = 0; i < 1000; ++i) {
     StringBuffer n = new StringBuffer();
     n.append(prefix).append("-").append(i).append(".").append(suffix);
     String newName = n.toString();
     FileAdapter f = new FileAdapter(newName);
     try {
       if (!f.exists()) {
         return newName;
       }
     } finally {
       f.close();
     }
   }
   return origFileName;
 }
 protected void renameTempFile(String tempFileName, String fullName) throws IOException {
   // Move the file from the temporary directory to the final one
   if (Log.isLoggable(Log.DEBUG)) {
     Log.debug(TAG_LOG, "Renaming " + tempFileName + " to " + fullName);
   }
   FileAdapter tempFile = new FileAdapter(tempFileName);
   tempFile.rename(fullName);
 }
 public long getLastModified() {
   try {
     FileAdapter file = new FileAdapter(fileName);
     long lastModified = file.lastModified();
     file.close();
     return lastModified;
   } catch (IOException ex) {
     Log.error(TAG_LOG, "Failed to get file last modification time", ex);
     return -1;
   }
 }
 public long getObjectSize() {
   try {
     FileAdapter file = new FileAdapter(fileName);
     long size = file.getSize();
     file.close();
     return size;
   } catch (IOException ex) {
     Log.error(TAG_LOG, "Failed to read file size", ex);
     return 0;
   }
 }
  protected OutputStream getDownloadOutputStream(
      String name, long size, boolean isUpdate, boolean isThumbnail, boolean append)
      throws IOException {

    String tempFileName = createTempFileName(name);
    if (Log.isLoggable(Log.TRACE)) {
      Log.trace(TAG_LOG, "getDownloadOutputStream: " + tempFileName);
    }

    FileAdapter file = createTempFile(tempFileName);
    OutputStream os = file.openOutputStream(append);
    file.close();
    return os;
  }
 public boolean exists(String luid) {
   FileAdapter fa = null;
   try {
     fa = new FileAdapter(luid);
     return fa.exists();
   } catch (Throwable t) {
     return false;
   } finally {
     if (fa != null) {
       try {
         fa.close();
       } catch (Exception ex) {
       }
     }
   }
 }
  /**
   * Checks if file must be filtered out
   *
   * @param key full path of the file to check
   */
  public boolean filterOutgoingItem(String key) {
    boolean filterOutItem = super.filterOutgoingItem(key);
    if (filterOutItem) return filterOutItem;

    // As long as there's no reason to filter out this file, variable reason
    // will remain null:
    String reason = null; // if it gets a value, the item is not OK
    FileAdapter file = null;
    try {
      // Filter hidden files
      file = new FileAdapter(key);
      if (file.isHidden()) {
        reason = "it is hidden";
      } else {
        // Filter files according to standard media sync criteria
        if (isOutsideSizeOrDateRange(file.getSize(), file.lastModified())) {
          reason = "it is too large or too old";
        }
      }
    } catch (IOException ex) {
      Log.error(TAG_LOG, "Cannot check file: " + key, ex);
    } finally {
      if (file != null) {
        try {
          file.close();
        } catch (Exception ex) {
        }
      }
    }
    // Filter by extension
    if (reason == null && extensions != null && extensions.length > 0) {
      if (!isSupportedExtension(key, extensions)) {
        reason = "its extension is not accepted";
      }
    }
    if (reason != null) {
      if (Log.isLoggable(Log.INFO)) {
        Log.info(TAG_LOG, "Filtering file " + key + " because " + reason);
      }
      return true;
    } else {
      return false;
    }
  }
 protected int updateItem(SyncItem item) throws SyncException {
   if (Log.isLoggable(Log.DEBUG)) {
     Log.debug(TAG_LOG, "updateItem");
   }
   JSONSyncItem jsonSyncItem = (JSONSyncItem) item;
   try {
     String fullName = getFileFullName(jsonSyncItem.getContentName());
     item.setKey(fullName);
     if (Log.isLoggable(Log.DEBUG)) {
       Log.debug(TAG_LOG, "key set to:" + fullName);
     }
     if (jsonSyncItem.isItemKeyUpdated()) {
       // Update the tracker of the renamed item
       // Must be done before renaming the file since the rename
       // event will be notified to the tracker itself
       getTracker()
           .removeItem(new SyncItem(jsonSyncItem.getOldKey(), null, SyncItem.STATE_DELETED, null));
       getTracker()
           .removeItem(new SyncItem(jsonSyncItem.getKey(), null, SyncItem.STATE_NEW, null));
     }
     if (jsonSyncItem.isItemContentUpdated()) {
       // The new content has been downloaded into a temporary file
       String sourceFileName = createTempFileName(jsonSyncItem.getContentName());
       renameTempFile(sourceFileName, fullName);
       if (jsonSyncItem.isItemKeyUpdated()) {
         // We shall remove the old file
         String oldFileName = jsonSyncItem.getOldKey();
         FileAdapter fa = new FileAdapter(oldFileName);
         fa.delete();
       }
     } else if (jsonSyncItem.isItemKeyUpdated()) {
       // This is just a rename
       String sourceFileName = jsonSyncItem.getOldKey();
       renameTempFile(sourceFileName, fullName);
     }
     super.updateItem(item);
     return SyncSource.SUCCESS_STATUS;
   } catch (IOException ioe) {
     Log.error(TAG_LOG, "Cannot rename temporary file", ioe);
     throw new SyncException(SyncException.CLIENT_ERROR, "Cannot rename temporary file");
   }
 }
  protected Enumeration getAllItemsKeys() throws SyncException {
    if (Log.isLoggable(Log.TRACE)) {
      Log.trace(TAG_LOG, "getAllItemsKeys");
    }
    totalItemsCount = 0;
    // Scan the briefcase directory and return all keys
    try {
      if (Log.isLoggable(Log.TRACE)) {
        Log.trace(TAG_LOG, "directory: " + directory);
      }
      FileAdapter dir = new FileAdapter(directory, true);
      Enumeration files = dir.list(false, false /* Filters hidden files */);
      dir.close();
      // We use the full file name as key, so we need to scan all the
      // items and prepend the directory
      Vector keys = new Vector();

      while (files.hasMoreElements()) {
        String file = (String) files.nextElement();
        // We better filter by extension right here, so we have the
        // proper number of items to be returned
        if (isSupportedExtension(file, extensions)) {
          String fullName = getFileFullName(file);
          keys.addElement(fullName);
          totalItemsCount++;
        }
      }

      Enumeration result = keys.elements();
      if (itemsSorter != null) {
        if (Log.isLoggable(Log.DEBUG)) {
          Log.debug(TAG_LOG, "Sorting all items keys");
        }
        result = itemsSorter.sort(result, syncMode);
      }
      return result;
    } catch (Exception e) {
      Log.error(TAG_LOG, "Cannot get list of files", e);
      throw new SyncException(SyncException.CLIENT_ERROR, e.toString());
    }
  }
  public long getPartiallyReceivedItemSize(String luid) {

    FileAdapter fa = null;
    try {
      String tempFileName = createTempFileName(getFileNameFromKey(luid));
      fa = new FileAdapter(tempFileName);
      if (!fa.exists()) {
        return -1;
      }
      return fa.getSize();
    } catch (Exception e) {
      return -1;
    } finally {
      if (fa != null) {
        try {
          fa.close();
        } catch (Exception ex) {
        }
      }
    }
  }
 /**
  * Delete an item from the local store.
  *
  * @param key the item key
  * @throws SyncException if the operation fails for any reason
  */
 public int deleteItem(String key) throws SyncException {
   if (Log.isLoggable(Log.INFO)) {
     Log.info(TAG_LOG, "Deleting item " + key);
   }
   FileAdapter fa = null;
   try {
     fa = new FileAdapter(key);
     if (fa.exists()) {
       fa.delete();
     }
     return SyncSource.SUCCESS_STATUS;
   } catch (Exception e) {
     Log.error(TAG_LOG, "Cannot delete item", e);
     return SyncSource.ERROR_STATUS;
   } finally {
     if (fa != null) {
       try {
         fa.close();
       } catch (IOException ex) {
       }
     }
   }
 }
  /**
   * Twin detection implementation
   *
   * @param item
   * @return the twin sync item, whose key is the LUID
   */
  public SyncItem findTwin(SyncItem item) {

    if (item instanceof JSONSyncItem) {

      JSONFileObject json = ((JSONSyncItem) item).getJSONFileObject();
      String fileName = json.getName();
      String fullName = getFileFullName(fileName);

      // Does this existing in our directory?
      if (Log.isLoggable(Log.DEBUG)) {
        Log.debug(TAG_LOG, "Checking for twin for: " + fileName);
      }
      FileAdapter fa = null;
      try {
        fa = new FileAdapter(fullName);
        if (fa.exists() && fa.getSize() == json.getSize()) {
          if (Log.isLoggable(Log.DEBUG)) {
            Log.debug(TAG_LOG, "Twin found");
          }
          item.setKey(fullName);
          return item;
        }
      } catch (Throwable t) {
        Log.error(TAG_LOG, "Cannot check for twins", t);
      } finally {
        if (fa != null) {
          try {
            fa.close();
          } catch (IOException ioe) {
          }
        }
      }
    }
    // No twin found
    return null;
  }
 protected void deleteAllItems() {
   if (Log.isLoggable(Log.TRACE)) {
     Log.trace(TAG_LOG, "removeAllItems");
   }
   // Scan the briefcase directory and return all keys
   try {
     FileAdapter dir = new FileAdapter(directory);
     Enumeration files = dir.list(false);
     dir.close();
     // We use the full file name as key, so we need to scan all the
     // items and prepend the directory
     while (files.hasMoreElements()) {
       String fileName = (String) files.nextElement();
       String fullName = getFileFullName(fileName);
       FileAdapter file = new FileAdapter(fullName);
       file.delete();
       file.close();
     }
     // at the end, empty the tracker
     tracker.reset();
   } catch (Exception e) {
     throw new SyncException(SyncException.CLIENT_ERROR, e.toString());
   }
 }
  protected SyncItem getItemContent(SyncItem item) throws SyncException {
    FileAdapter file = null;
    try {
      String fileFullName = item.getKey();
      String fileName = getFileNameFromKey(fileFullName);
      file = new FileAdapter(fileFullName);

      long size = file.getSize();
      long modified = file.lastModified();

      JSONFileObject jsonFileObject = new JSONFileObject();
      jsonFileObject.setName(fileName);
      jsonFileObject.setSize(size);
      jsonFileObject.setCreationdate(modified);
      jsonFileObject.setLastModifiedDate(modified);
      jsonFileObject.setMimetype(getContentTypeFromFileName(fileName));

      FileSyncItem syncItem =
          new FileSyncItem(
              fileFullName,
              item.getKey(),
              getConfig().getType(),
              item.getState(),
              item.getParent(),
              jsonFileObject);

      // Set the item old key to handle renames
      if (getTracker() instanceof CacheTrackerWithRenames) {
        CacheTrackerWithRenames tracker = (CacheTrackerWithRenames) getTracker();
        if (tracker.isRenamedItem(item.getKey())) {
          String oldKey = tracker.getRenamedFileName(item.getKey());
          if (Log.isLoggable(Log.DEBUG)) {
            Log.debug(TAG_LOG, "Setting item old key: " + oldKey);
          }
          syncItem.setOldKey(oldKey);
          if (oldKey != null) {
            syncItem.setItemKeyUpdated(true);
          }
        } else {
          syncItem.setOldKey(null);
          syncItem.setItemKeyUpdated(false);
        }
      }

      // Check if the sync item content has been updated.
      if (getTracker() instanceof CacheTrackerWithRenames) {
        CacheTrackerWithRenames tracker = (CacheTrackerWithRenames) getTracker();
        if (tracker.isRenamedItem(item.getKey())) {
          boolean itemUpdated =
              tracker.isRenamedItemUpdated(syncItem.getOldKey(), syncItem.getKey());
          if (Log.isLoggable(Log.DEBUG)) {
            Log.debug(TAG_LOG, "Setting item content updated: " + itemUpdated);
          }
          syncItem.setItemContentUpdated(itemUpdated);
        }
      }
      return syncItem;
    } catch (Exception e) {
      throw new SyncException(
          SyncException.CLIENT_ERROR, "Cannot create SyncItem: " + e.toString());
    } finally {
      try {
        if (file != null) {
          file.close();
        }
      } catch (IOException ex) {
      }
    }
  }
 public OutputStream getOutputStream() throws IOException {
   FileAdapter file = new FileAdapter(fileName);
   OutputStream os = file.openOutputStream();
   file.close();
   return os;
 }
 public InputStream getInputStream() throws IOException {
   FileAdapter file = new FileAdapter(fileName);
   InputStream is = file.openInputStream();
   file.close();
   return is;
 }