1 18 19 package sync4j.syncclient.test; 20 21 import java.io.*; 22 import java.security.Principal ; 23 import java.util.Date ; 24 import java.util.Vector ; 25 import java.util.Enumeration ; 26 import java.util.Properties ; 27 28 import sync4j.syncclient.spds.engine.*; 29 import sync4j.syncclient.spds.SyncException; 30 31 import sync4j.framework.tools.Base64; 32 33 34 43 public class FileSystemSyncSource implements SyncSource { 44 45 47 public static final String DATABASE_FILE_NAME 48 = "sync.db" ; 49 public static final String DATABASE_HEADER 50 = "FileSystemSyncSource file database" ; 51 public static final String LOG_NAME 52 = "sync4j.framework.engine" ; 53 54 56 60 private String sourceDirectory = "."; 61 62 public void setSourceDirectory(String sourceDirectory) { 63 this.sourceDirectory = sourceDirectory; 64 } 65 66 public String getSourceDirectory() { 67 return this.sourceDirectory; 68 } 69 70 private String name; 71 public String getName() { 72 return name; 73 } 74 public void setName(String name) { 75 this.name = name; 76 } 77 78 private String type; 79 public String getType() { 80 return this.type; 81 } 82 public void setType(String type) { 83 this.type = type; 84 } 85 86 private boolean encode = false; 87 public boolean isEncode() { 88 return encode; 89 } 90 public void setEncode(boolean encode) { 91 this.encode = encode; 92 } 93 public void setEncode(String encode) { 94 if ("true".equals(encode)) { 95 this.encode = true; 96 } else { 97 this.encode = false; 98 } 99 } 100 101 private String sourceURI; 102 103 106 public String getSourceURI() { 107 return sourceURI; 108 } 109 110 113 public void setSourceURI(String sourceURI) { 114 this.sourceURI = sourceURI; 115 } 116 117 119 120 public FileSystemSyncSource() { 121 } 122 123 public void beginSync(int type) throws SyncException { 125 126 File f = new File(sourceDirectory); 131 if (!f.isDirectory()) { 132 throw new SyncException( 133 "Destination directory (" + sourceDirectory + ") not existing." 134 ); 135 } 136 137 restoreSyncDB(); 138 } 139 140 public void endSync() throws SyncException { 141 } 142 143 public SyncItem[] getAllSyncItems(Principal principal) throws SyncException { 144 return filterSyncItems(principal, null, SyncItemState.UNKNOWN); 145 } 146 147 public SyncItem[] getDeletedSyncItems(Principal principal, 148 Date since ) throws SyncException { 149 return filterSyncItems(principal, since, SyncItemState.DELETED); 150 } 151 152 public SyncItem[] getNewSyncItems(Principal principal, 153 Date since ) throws SyncException { 154 return filterSyncItems(principal, since, SyncItemState.NEW); 155 } 156 157 public SyncItem[] getUpdatedSyncItems(Principal principal, 158 Date since ) throws SyncException { 159 return filterSyncItems(principal, since, SyncItemState.UPDATED); 160 } 161 162 public void removeSyncItem(Principal principal, SyncItem syncItem) throws SyncException { 163 String fileName = syncItem.getKey().getKeyAsString(); 164 165 new File(sourceDirectory, fileName).delete(); 166 167 removeState(principal, fileName); 168 } 169 170 public SyncItem setSyncItem(Principal principal, SyncItem syncItem) 171 throws SyncException { 172 try { 173 String fileName = syncItem.getKey().getKeyAsString(); 174 byte[] fileContent = 175 (byte[])syncItem.getPropertyValue(SyncItem.PROPERTY_BINARY_CONTENT); 176 177 FileOutputStream fos = new FileOutputStream(new File(sourceDirectory, fileName)); 178 if (fileContent != null) { 179 if (encode) { 180 fos.write(Base64.decode(fileContent)); 181 } else { 182 fos.write(fileContent); 183 } 184 } 185 fos.close(); 186 187 setState(principal, fileName, SyncItemState.SYNCHRONIZED); 188 189 SyncItem newSyncItem = 190 new SyncItemImpl(this, fileName, SyncItemState.NEW); 191 192 newSyncItem.setProperties(syncItem.getProperties()); 193 194 return newSyncItem; 195 } catch (IOException e) { 196 throw new SyncException( "Error setting the item " 197 + syncItem 198 , e 199 ); 200 } 201 } 202 203 public void commitSync() { 204 } 205 206 246 protected Properties updateSyncDatabase(Principal principal) { 247 248 Properties syncDatabase = new Properties (); 249 250 try { 251 File fileSyncDatabase = getDatabaseFile(principal); 252 253 if (fileSyncDatabase.exists()) { 257 FileInputStream fis = new FileInputStream(fileSyncDatabase); 258 syncDatabase.load(fis); 259 fis.close(); 260 } 261 262 Vector existingFiles = getExistingFiles(); 266 267 Enumeration databaseFiles = syncDatabase.propertyNames(); 271 272 String state = null, 273 fileName = null; 274 275 long lastModified; 276 277 int n = existingFiles.size(); 278 for (int i=0; i < n; ++i) { 279 fileName = (String )existingFiles.elementAt(i); 280 lastModified = new File(sourceDirectory, fileName).lastModified(); 281 282 state = syncDatabase.getProperty(fileName); 283 284 if (state != null) { 285 if (lastModified > lastModifiedFromStateString(state)) { 289 state = buildStateString(SyncItemState.UPDATED, lastModified); 290 syncDatabase.put(fileName, state); 291 } 292 } else { 293 state = buildStateString(SyncItemState.NEW, lastModified); 297 syncDatabase.put(fileName, state); 298 } 299 } 301 for (; databaseFiles.hasMoreElements();) { 302 fileName = (String )databaseFiles.nextElement(); 303 304 if (!existingFiles.contains(fileName)) { 305 state = buildStateString(SyncItemState.DELETED, System.currentTimeMillis()); 306 syncDatabase.put(fileName, state); 307 } 308 } 310 FileOutputStream fos = new FileOutputStream(fileSyncDatabase); 314 syncDatabase.save(fos, DATABASE_HEADER); 315 fos.close(); 316 } catch (IOException e) { 317 e.printStackTrace(); 318 } 319 320 return syncDatabase; 321 } 322 323 private File getDatabaseFile(Principal principal) { 324 return new File(sourceDirectory + '.' + DATABASE_FILE_NAME); 325 } 326 327 private String buildStateString(char state, long lastModified) { 328 return state + String.valueOf(lastModified); 329 } 330 331 protected long lastModifiedFromStateString(String state) { 332 return Long.parseLong(state.substring(1)); 333 } 334 335 protected char stateFromStateString(String state) { 336 if ((state == null) || (state.length() == 0)) return SyncItemState.UNKNOWN; 337 338 return state.charAt(0); 339 } 340 341 private Vector getExistingFiles() throws IOException { 342 Vector ret = new Vector (); 343 344 String [] files = new File(sourceDirectory).list(); 345 346 if (files != null) { 347 for (int i = 0; i<files.length; ++i) { 348 if (!files[i].endsWith('.' + DATABASE_FILE_NAME)) { 349 ret.addElement(files[i]); 350 } 351 } } 353 354 return ret; 355 } 356 357 protected void setState(Principal principal, String file, char state) { 358 try { 359 Properties syncDatabase = new Properties (); 360 361 File fileSyncDatabase = getDatabaseFile(principal); 362 363 if (fileSyncDatabase.exists()) { 367 FileInputStream fis = new FileInputStream(fileSyncDatabase); 368 syncDatabase.load(fis); 369 fis.close(); 370 } 371 372 syncDatabase.put(file, buildStateString(state, System.currentTimeMillis())); 373 374 FileOutputStream fos = new FileOutputStream(fileSyncDatabase); 375 syncDatabase.save(fos, DATABASE_HEADER); 376 fos.close(); 377 } catch (IOException e) { 378 e.printStackTrace(); 379 } 380 } 381 382 private void removeState(Principal principal, String file) { 383 try { 384 File fileSyncDatabase = getDatabaseFile(principal); 385 386 if (!fileSyncDatabase.exists()) return; 387 388 Properties syncDatabase = new Properties (); 389 390 394 FileInputStream fis = new FileInputStream(fileSyncDatabase); 395 syncDatabase.load(fis); 396 fis.close(); 397 398 syncDatabase.remove(file); 399 400 FileOutputStream fos = new FileOutputStream(fileSyncDatabase); 401 syncDatabase.save(fos, DATABASE_HEADER); 402 fos.close(); 403 } catch (IOException e) { 404 e.printStackTrace(); 405 } 406 } 407 408 422 protected SyncItem[] filterSyncItems(Principal principal, 423 Date since , 424 char state ) 425 throws SyncException { 426 Properties syncDatabase = updateSyncDatabase(principal); 427 428 Vector syncItems = new Vector (); 429 430 long fileTimestamp, 431 sinceTimestamp = (since == null) ? -1 : since.getTime(); 432 433 SyncItem syncItem = null; 434 String fileName = null; 435 String stateString = null; 436 char fileState ; 437 for (Enumeration e = syncDatabase.keys(); e.hasMoreElements(); ) { 438 fileName = (String )e.nextElement(); 439 stateString = (String )syncDatabase.get(fileName); 440 fileState = stateFromStateString(stateString); 441 if ((state == SyncItemState.UNKNOWN) || (fileState == state)) { 442 fileTimestamp = lastModifiedFromStateString(stateString); 443 if (fileTimestamp > sinceTimestamp ) { 444 syncItem = new SyncItemImpl(this, fileName, fileState); 445 if (encode){ 446 syncItem.setProperty( 447 new SyncItemProperty(SyncItem.PROPERTY_BINARY_CONTENT , 448 Base64.encode(readFileContent(fileName))) 449 ); 450 } else { 451 syncItem.setProperty( 452 new SyncItemProperty(SyncItem.PROPERTY_BINARY_CONTENT, 453 readFileContent(fileName) ) 454 ); 455 } 456 syncItems.addElement(syncItem); 457 } 458 } 459 } 461 SyncItem[] ret = new SyncItem[syncItems.size()]; 462 for (int i=0; i<ret.length; ++i) { 463 ret[i] = (SyncItem)syncItems.elementAt(i); 464 } 465 466 return ret; 467 } 468 469 476 protected byte[] readFileContent(String fileName) { 477 byte buf[] = null; 478 479 try { 480 File file = new File(sourceDirectory, fileName); 481 482 if (!file.exists()) return new byte[0]; 483 484 buf = new byte[(int)file.length()]; 485 486 FileInputStream fis = new FileInputStream(file); 487 fis.read(buf); 488 fis.close(); 489 } catch (IOException e) { 490 buf = new byte[0]; 491 e.printStackTrace(); 492 } 493 494 return buf; 495 } 496 497 500 private void restoreSyncDB() throws SyncException { 501 502 Properties syncDatabase = new Properties (); 503 504 String state = null; 505 String fileName = null; 506 507 try { 508 509 File fileSyncDatabase = getDatabaseFile(null); 510 511 if (fileSyncDatabase.exists()) { 515 FileInputStream fis = new FileInputStream(fileSyncDatabase); 516 syncDatabase.load(fis); 517 fis.close(); 518 } 519 520 Enumeration databaseFiles = syncDatabase.propertyNames(); 524 525 for (; databaseFiles.hasMoreElements();) { 526 fileName = (String )databaseFiles.nextElement(); 527 528 state = syncDatabase.getProperty(fileName); 529 530 if (stateFromStateString(state) == SyncItemState.DELETED) { 531 syncDatabase.remove(fileName); 532 } 533 } 535 536 FileOutputStream fos = new FileOutputStream(fileSyncDatabase); 540 syncDatabase.save(fos, DATABASE_HEADER); 541 fos.close(); 542 } catch (IOException e) { 543 throw new SyncException( "Error reading sync database: " 544 + e.getMessage()); 545 } 546 } 547 } | Popular Tags |