xlawrence    2005/01/31 16:52:43 CET

  Modified files:
    syncClient/src/java/org/jahia/suite/calendar/syncClients 
                                                             
ICalendarSyncSource.java 
                                                             SyncClient.java 
  Added files:
    syncClient/src/java/org/jahia/suite/calendar/syncClients 
                                                             FileMapping.java 
  Log:
  Improved change detection algorithm. Now based on a mapping file.
  
  Revision  Changes    Path
  1.1       +239 -0    
uwcal_JSR168/syncClient/src/java/org/jahia/suite/calendar/syncClients/FileMapping.java
 (new)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/uwcal_JSR168/syncClient/src/java/org/jahia/suite/calendar/syncClients/FileMapping.java?rev=1.1&content-type=text/plain
  1.4       +20 -14    
uwcal_JSR168/syncClient/src/java/org/jahia/suite/calendar/syncClients/ICalendarSyncSource.java
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/uwcal_JSR168/syncClient/src/java/org/jahia/suite/calendar/syncClients/ICalendarSyncSource.java.diff?r1=1.3&r2=1.4&f=h
  1.5       +73 -52    
uwcal_JSR168/syncClient/src/java/org/jahia/suite/calendar/syncClients/SyncClient.java
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/uwcal_JSR168/syncClient/src/java/org/jahia/suite/calendar/syncClients/SyncClient.java.diff?r1=1.4&r2=1.5&f=h
  
  
  
  Index: FileMapping.java
  ====================================================================
  /*
   *                                   ____.
   *                       __/\ ______|    |__/\.     _______
   *            __   .____|    |       \   |    +----+       \
   *    _______|  /--|    |    |    -   \  _    |    :    -   \_________
   *   \\______: :---|    :    :           |    :    |         \________>
   *           |__\---\_____________:______:    :____|____:_____\
   *                                      /_____|
   *
   *              . . . i n   j a h i a   w e   t r u s t . . .
   *
   *
   *
   * ----- BEGIN LICENSE BLOCK -----
   * Version: JCSL 1.0
   *
   * The contents of this file are subject to the Jahia Community Source License
   * 1.0 or later (the "License"); you may not use this file except in
   * compliance with the License. You may obtain a copy of the License at
   * http://www.jahia.org/license
   *
   * Software distributed under the License is distributed on an "AS IS" basis,
   * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   * for the rights, obligations and limitations governing use of the contents
   * of the file. The Original and Upgraded Code is the Jahia CMS and Portal
   * Server. The developer of the Original and Upgraded Code is JAHIA Ltd. JAHIA
   * Ltd. owns the copyrights in the portions it created. All Rights Reserved.
   *
   * The Shared Modifications are Jahia View Helper.
   *
   * The Developer of the Shared Modifications is Jahia Solution S�rl.
   * Portions created by the Initial Developer are Copyright (C) 2002 by the
   * Initial Developer. All Rights Reserved.
   *
   * ----- END LICENSE BLOCK -----
   */
  
  package org.jahia.suite.calendar.syncClients;
  
  import java.util.Properties;
  import java.util.Iterator;
  import java.util.Vector;
  import java.util.Collection;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.IOException;
  
  import org.apache.log4j.Logger;
  
  /**
   *
   * @author Xavier Lawrence
   */
  public class FileMapping {
      
      // log4j logger
      static Logger log = Logger.getLogger(FileMapping.class);
      
      public static final String MAPPING_FILE = "mapping.db";
      public static final String FILE_HEADER = "SyncItem mapping file";
      
      // Position in File to FileName
      private Properties mapping;    
      
      // FileName to Content
      private Properties syncItems;
      
      private Vector processedFiles;
      
      private String dbDirectoryName;
      
      private static FileMapping currentMapping; 
       
      /** Creates a new instance of FileMapping */
      public FileMapping(String dbDirectoryName) {
          this.dbDirectoryName = dbDirectoryName;
      }
      
      /**
       *
       */
      public static FileMapping getCurrentMapping() {
          return currentMapping;
      }
      
      /**
       *
       */
      public void load() {
          try {
              mapping = new Properties();
              syncItems = new Properties();
              processedFiles = new Vector();
              loadSyncItemFiles();
              loadMapping();
              currentMapping = this;
              
          } catch (IOException e) {
              log.fatal(e.getMessage());
              e.printStackTrace();
              System.exit(-1);
          }
      }
      
      /**
       *
       */
      public String getMapping(String item) {
          Iterator ite = syncItems.keySet().iterator();
          
          while (ite.hasNext()) {
              String key = (String)ite.next();
              String value = syncItems.getProperty(key);
              
              if (item.trim().equals(value.trim())) {
                  log.debug("Found mapped item: "+key);
                  return key;
              }
          }
          return null;
      }
          
      /**
       *
       */
      public void removeMapping (int key) {
          mapping.remove(Integer.toString(key));
      }
      
      /**
       *
       */
      public boolean processed(String fileName) {
          return processedFiles.contains(fileName);
      }
      
      /**
       *
       */
      public Iterator keys() {
          return mapping.keySet().iterator();
      }
      
      /**
       *
       */
      public Collection values() {
          return mapping.values();
      }
      
      /**
       *
       */
      public String getMappedFile(int position) {
          return mapping.getProperty(Integer.toString(position));        
      }
      
      /**
       *
       */
      public int getFilePosition(String fileName) {
          Iterator ite = mapping.keySet().iterator();
          
          while (ite.hasNext()) {
              String key = (String)ite.next();
              String value = mapping.getProperty(key);
              
              if (fileName.equals(value)) {
                  return Integer.parseInt(key);
              }
          }
          return -1;
      }
      
      /**
       *
       */
      public int size() {
          return mapping.size();
      }
      
      /**
       *
       */
      public void updateMapping(int key, String value) {
          mapping.setProperty(Integer.toString(key), value);
          processedFiles.addElement(value);
      }
      
      /**
       *
       */
      public void loadMapping() throws IOException {
          File mappingFile = new File(dbDirectoryName + '.' +
                  MAPPING_FILE);
          // Reads the existing mapping
          if (mappingFile.exists()) {
              FileInputStream fis = new FileInputStream(mappingFile);
              mapping.load(fis);
              fis.close();
              log.debug("Mapping loaded: "+mapping+ "\nFrom file: 
"+mappingFile);
          }
      }
      
      /**
       *
       */
      public void saveMapping() throws IOException {
          File mappingFile = new File(dbDirectoryName + '.' +
                  MAPPING_FILE);
          
          FileOutputStream fos = new FileOutputStream(mappingFile);
          mapping.store(fos, FILE_HEADER);
          fos.flush();
          fos.close();
      }
      
      /**
       *
       */
      private void loadSyncItemFiles() throws IOException {
          // get all the syncITem files
          File[] syncItemFiles = new File(dbDirectoryName).listFiles();
          
          if (syncItemFiles == null || syncItemFiles.length == 0) return;
          
          for (int i=0; i<syncItemFiles.length; i++) {
              byte[] buf = new byte[(int)syncItemFiles[i].length()];
              
              FileInputStream fis = new FileInputStream(syncItemFiles[i]);
              fis.read(buf);
              fis.close();
              
              syncItems.setProperty(syncItemFiles[i].getName(), new 
String(buf));
              log.debug("Loaded File: "+syncItemFiles[i].getName());
          }        
      }
  }
  
  
  
  Index: ICalendarSyncSource.java
  ===================================================================
  RCS file: 
/home/cvs/repository/uwcal_JSR168/syncClient/src/java/org/jahia/suite/calendar/syncClients/ICalendarSyncSource.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ICalendarSyncSource.java  25 Jan 2005 13:04:06 -0000      1.3
  +++ ICalendarSyncSource.java  31 Jan 2005 15:52:42 -0000      1.4
  @@ -78,7 +78,7 @@
       private String type;
       private String sourceURI;
       
  -    private Properties syncDatabase;
  +    private Properties syncDatabase;    
       
       /**
        * Creates a new instance of ICalendarSyncSource
  @@ -245,12 +245,15 @@
           String fileName = syncItem.getKey().getKeyAsString();
           
           new File(sourceDirectory, fileName).delete();
  +               
  +        syncDatabase.remove(fileName);
           
  -//        Date t =
  -//                
(Date)syncItem.getPropertyValue(SyncItem.PROPERTY_TIMESTAMP);
  -//        
  -//        syncDatabase.setProperty(fileName, 
buildStateString(SyncItemState.DELETED, 
  -//        t.getTime()));
  +        FileMapping mapping = FileMapping.getCurrentMapping();
  +        
  +        for (int i = mapping.getFilePosition(fileName); i<mapping.size(); 
i++) {
  +            mapping.updateMapping(i, mapping.getMappedFile(i+1));
  +        }
  +        mapping.removeMapping(mapping.size());
       }
       
       /**
  @@ -417,7 +420,7 @@
        * 5.    End For each
        * </pre>
        * <p>
  -     * At the end of the process, the updated database is saved and than 
returned.
  +     * At the end of the process, the updated database is saved and then 
returned.
        *
        * @return the updated databse. In case of error, an error message is 
traced
        *         and an empty Properties object is returned.
  @@ -467,14 +470,16 @@
               // Some items have been deleted by the client
               
               ite = syncDatabase.keySet().iterator();
  +            FileMapping mapping = FileMapping.getCurrentMapping();
               
  -            while (ite.hasNext()) {
  -                int keyValue = Integer.parseInt((String)ite.next());
  -                if (keyValue > existingFiles.size()) {
  +            while (ite.hasNext()) {            
  +                String keyValue = (String)ite.next();                
  +                
  +                if (!mapping.values().contains(keyValue)) {
                       log.debug("Item: "+keyValue+": DELETED");
                       state = buildStateString(SyncItemState.DELETED,
                               System.currentTimeMillis());
  -                    syncDatabase.setProperty(new 
Integer(keyValue).toString(), state);
  +                    syncDatabase.setProperty(keyValue, state);
                   }
               }
           }
  @@ -489,9 +494,7 @@
           FileOutputStream fos = new FileOutputStream(fileSyncDatabase);
           syncDatabase.store(fos, DATABASE_HEADER);
           fos.flush();
  -        fos.close();
  -        
  -        
  +        fos.close();     
       }
       
       /**
  @@ -580,6 +583,9 @@
           return Integer.toString(nextFileId);
       }
       
  +    /**
  +     *
  +     */
       private boolean fileExists(int fileName) {
           return new File(sourceDirectory, 
Integer.toString(fileName)).exists();
       }
  
  
  
  Index: SyncClient.java
  ===================================================================
  RCS file: 
/home/cvs/repository/uwcal_JSR168/syncClient/src/java/org/jahia/suite/calendar/syncClients/SyncClient.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SyncClient.java   24 Jan 2005 13:37:56 -0000      1.4
  +++ SyncClient.java   31 Jan 2005 15:52:43 -0000      1.5
  @@ -48,12 +48,10 @@
   import java.io.File;
   import java.io.FileInputStream;
   import java.io.FileOutputStream;
  -import java.io.OutputStreamWriter;
  -import java.io.InputStreamReader;
   import java.io.IOException;
   import java.io.FileNotFoundException;
   
  -import java.util.Properties;
  +import java.util.Iterator;
   
   import org.apache.log4j.Logger;
   
  @@ -73,6 +71,7 @@
       
       private SyncClientFrame syncClientGUI;
       private CalendarFileManager calManager;
  +    private FileMapping mapping;
       
       // log4j logger
       static Logger log = Logger.getLogger(SyncClient.class);
  @@ -92,43 +91,51 @@
        * @throws IOException If something goes wrong during the storing of the 
file
        * @throws FileNotFoundException If the file does not exist
        */
  -    protected void generateSyncItemFile(File file, String content)
  -    throws IOException, FileNotFoundException {      
  -        
  -        content = new String(content.getBytes());
  -        
  -        // new file for a new item
  -        if (!file.exists()) {
  -            file.createNewFile();
  +    protected void generateSyncItemFile(int filePosition, String 
dbDirectoryName,
  +            String content) 
  +    throws IOException, FileNotFoundException {       
  +        
  +        String fileName = mapping.getMapping(content);
  +        File file = null;
  +        
  +        // UNCHANGED ITEM
  +        if (fileName != null) {
  +            log.debug("Content has not changed for item at position: "+
  +                    filePosition+ ". Kept in file: "+fileName);
  +            mapping.updateMapping(filePosition, fileName);
  +            return;
               
  -            // existing file for existing item
           } else {
  -            FileInputStream fin = new FileInputStream(file);
  -            InputStreamReader d = new InputStreamReader(fin);
  -            char[] buf = new char[(int)file.length()];
  -            d.read(buf);
  -            d.close();
  -            String currentContent = new String(buf).trim();
  -            currentContent = new String(currentContent.getBytes());
  -            
  -            // If the content has not changed between 2 syncs...
  -            if (currentContent.equals(content)) {
  -                // ... do nothing
  -                log.debug("Content has not changed for item: 
"+file.getName());
  -                return;
  +            
  +            fileName = mapping.getMappedFile(filePosition);
  +            
  +            // ADDED ITEM
  +            if (fileName == null) {
  +                
  +                int index = 1;
  +                file = new File(dbDirectoryName +"/"+ index);
                   
  +                while (file.exists()) {
  +                    index++;
  +                    file = new File(dbDirectoryName +"/"+ index);
  +                }
  +                fileName = file.getName();
  +                log.debug("ADDED: filePos="+filePosition+ ". File: 
"+fileName);
  +            
  +            // MODIFIED ITEM
               } else {
  -                log.debug(currentContent.length()+"-"+content.length());
  +                file = new File(dbDirectoryName +"/"+ fileName);
                   file.delete();
  -                file.createNewFile();
  -            }
  +                log.debug("MODIFIED: filePos="+filePosition+ ". File: 
"+fileName);
  +            }           
           }
  -        
  +
           FileOutputStream fout = new FileOutputStream(file);
  -        OutputStreamWriter o = new OutputStreamWriter(fout);
  -        o.write(content);
  -        o.flush();
  -        o.close();
  +        fout.write(content.getBytes());
  +        fout.flush();
  +        fout.close();
  +        
  +        mapping.updateMapping(filePosition, fileName);
       }
       
       /**
  @@ -149,23 +156,28 @@
       private void updateICSFile(File[] files, String fileName, String 
       dbDir) throws FileNotFoundException, IOException, 
       ValidationException, ParserException {
  -        String[] contents = new String[files.length];
  -        // file name
  -        int j=0;
  +        String[] contents = new String[files.length];       
  +        
           for (int i=0; i<files.length; i++) {
  -            File f = new File(dbDir + "/" + j);
  -            if (!f.exists()) {
  -                i--;
  -                j++;
  -                continue;
  +            
  +            String tmpFileName = files[i].getName();            
  +            int filePosition = mapping.getFilePosition(tmpFileName);
  +                             
  +            // NEW file returned from the server
  +            if (filePosition == -1) {
  +                filePosition = mapping.size() + 1;
  +                mapping.updateMapping(filePosition, tmpFileName);
               }
  +            
  +            File f = new File(dbDir + "/" + tmpFileName);
  +            
               FileInputStream fis = new FileInputStream(f);
  -            InputStreamReader d = new InputStreamReader(fis);
  -            char[] content = new char[(int)f.length()];
  -            d.read(content);
  -            contents[i] = new String(content);
  +            byte[] content = new byte[(int)f.length()];
  +            fis.read(content);
  +            contents[filePosition-1] = new String(content);
  +            log.debug("Set content at position: "+ filePosition +". For 
file: "+
  +                    tmpFileName);
               fis.close();
  -            j++;
           }
           calManager.writeCalendarItems(fileName, contents);
       }
  @@ -181,7 +193,7 @@
        * @throws ValidationException If the iCalendar file is not valid (cf. 
RFC-2445)
        */
       public void sync(String fileName) throws FileNotFoundException, 
IOException,
  -    SyncException, DMException, ParserException, ValidationException {
  +    SyncException, DMException, ParserException, ValidationException {       
 
           
           File dbDir = new File(DB_DIRECTORY);
           if (!dbDir.exists()) {
  @@ -199,6 +211,9 @@
           final String dbDirectoryName = new String(DB_DIRECTORY + 
userValues[1] +
           userValues[3]);
           
  +        mapping = new FileMapping(dbDirectoryName);
  +        mapping.load();
  +        
           final File dir = new File(dbDirectoryName);
           // create the db directory if it does not exist        
           dir.mkdir();
  @@ -206,8 +221,7 @@
           // Generate all Sync Item files        
           for (int i=0; i<items.length; i++) {
               if (i==0 && withOutCalProps) continue;  // Ignore the cal 
properties
  -            File f = new File(dbDirectoryName +"/"+ i);
  -            generateSyncItemFile(f, items[i].trim());
  +            generateSyncItemFile(i, dbDirectoryName, items[i]);
           }
           
           File[] files = dir.listFiles();
  @@ -226,12 +240,18 @@
           if (files.length > itemNB) {
               // There are more files in the directory than sync items
               // -> delete unecessary files <-
  -            for (int i = itemNB; i<files.length; i++) {
  -                File f = new File(dir, Integer.toString(i+1));
  +            for (int i = itemNB; i<files.length; i++) {               
  +                mapping.removeMapping(i+1);               
  +            }
  +            
  +            for (int i=0; i<files.length; i++) {
  +                File f = files[i];
  +                if (mapping.processed(f.getName())) continue;
  +                
                   log.debug("Deleted File: "+ f.getName());
                   f.delete();
               }
  -        }
  +        }    
           
           syncClientGUI.log("Sync data ready. Synchronizing...");
                   
  @@ -282,6 +302,7 @@
           } else {
               syncClientGUI.log("WARNING: No data returned");
           }
  +        mapping.saveMapping();
       }
       
       /**
  

Reply via email to