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();
}
/**