1 18 19 package sync4j.syncclient.test; 20 21 import java.io.*; 22 import java.security.Principal ; 23 24 import java.util.Date ; 25 import java.util.HashMap ; 26 import java.util.Vector ; 27 import java.util.Enumeration ; 28 import java.util.Properties ; 29 30 import sync4j.syncclient.common.SourceUtils; 31 32 import sync4j.syncclient.spds.engine.*; 33 import sync4j.syncclient.spds.SyncException; 34 35 import sync4j.framework.tools.Base64; 36 import sync4j.framework.tools.IOTools; 37 38 39 48 public class SIFSyncSource implements SyncSource { 49 50 52 public static final String DATABASE_FILE_NAME 53 = "sync.db" ; 54 public static final String DATABASE_HEADER 55 = "FileSystemSyncSource file database" ; 56 public static final String LOG_NAME 57 = "sync4j.framework.engine" ; 58 59 61 65 private String sourceDirectory = "."; 66 67 public void setSourceDirectory(String sourceDirectory) { 68 this.sourceDirectory = sourceDirectory; 69 } 70 71 public String getSourceDirectory() { 72 return this.sourceDirectory; 73 } 74 75 private String name; 76 77 public String getName() { 78 return name; 79 } 80 81 public void setName(String name) { 82 this.name = name; 83 } 84 85 private String type; 86 87 public String getType() { 88 return this.type; 89 } 90 91 public void setType(String type) { 92 this.type = type; 93 } 94 95 private boolean encode = false; 96 97 public boolean isEncode() { 98 return encode; 99 } 100 101 public void setEncode(boolean encode) { 102 this.encode = encode; 103 } 104 105 public void setEncode(String encode) { 106 107 if ("true".equals(encode)) { 108 this.encode = true ; 109 } else { 110 this.encode = false ; 111 } 112 } 113 114 private String sourceURI; 115 116 119 public String getSourceURI() { 120 return sourceURI; 121 } 122 123 126 public void setSourceURI(String sourceURI) { 127 this.sourceURI = sourceURI; 128 } 129 130 132 133 public SIFSyncSource() { 134 } 135 136 138 public void beginSync(int type) throws SyncException { 139 restoreSyncDB (); 140 } 141 142 143 public void endSync() throws SyncException { 144 } 145 146 147 public SyncItem[] getAllSyncItems(Principal principal) throws SyncException { 148 return filterSyncItems(principal, null, SyncItemState.UNKNOWN); 149 } 150 151 152 public SyncItem[] getDeletedSyncItems(Principal principal, 153 Date since ) throws SyncException { 154 return filterSyncItems(principal, since, SyncItemState.DELETED); 155 156 } 157 158 159 public SyncItem[] getNewSyncItems(Principal principal, 160 Date since ) throws SyncException { 161 return filterSyncItems(principal, since, SyncItemState.NEW); 162 163 } 164 165 public SyncItem[] getUpdatedSyncItems(Principal principal, 166 Date since ) throws SyncException { 167 return filterSyncItems(principal, since, SyncItemState.UPDATED); 168 169 } 170 171 public void removeSyncItem(Principal principal, SyncItem syncItem) throws SyncException { 172 String fileName = syncItem.getKey().getKeyAsString(); 173 174 new File(sourceDirectory, fileName).delete(); 175 176 removeState(principal, fileName); 177 } 178 179 182 183 public SyncItem setSyncItem(Principal principal, SyncItem syncItem) 184 throws SyncException { 185 186 try { 187 String fileName = syncItem.getKey().getKeyAsString(); 188 byte[] fileContent = 189 (byte[])syncItem.getPropertyValue(SyncItem.PROPERTY_BINARY_CONTENT); 190 191 if (fileContent == null) { 192 fileContent = new byte[0]; 193 } 194 195 HashMap hashMap = null; 196 HashMap hashMapFromFile = null; 197 198 File f = new File (sourceDirectory, fileName); 199 200 if (encode && fileContent.length > 0) { 201 202 203 if (f.exists()) { 204 hashMapFromFile = SourceUtils. 205 xmlToHashMap(IOTools.readFileString(f)); 206 207 hashMap = SourceUtils.xmlToHashMap 208 (new String (Base64.decode(fileContent))); 209 210 hashMapFromFile.putAll(hashMap); 211 212 IOTools.writeFile( 213 SourceUtils.hashMapToXml(hashMapFromFile), f); 214 215 216 } 217 else { 218 219 hashMapFromFile = new HashMap (); 220 221 hashMap = SourceUtils.xmlToHashMap 222 (new String (Base64.decode(fileContent))); 223 224 hashMapFromFile.putAll(hashMap); 225 226 IOTools.writeFile( 227 SourceUtils.hashMapToXml(hashMapFromFile), f); 228 } 229 230 } else { 231 232 if (f.exists()) { 233 234 hashMapFromFile = SourceUtils. 235 xmlToHashMap(IOTools.readFileString(f)); 236 237 hashMap = SourceUtils. 238 xmlToHashMap(new String (fileContent)); 239 240 hashMapFromFile.putAll(hashMap); 241 242 IOTools.writeFile( 243 SourceUtils.hashMapToXml(hashMapFromFile), f); 244 245 } else { 246 247 hashMapFromFile = new HashMap (); 248 249 hashMap = SourceUtils. 250 xmlToHashMap(new String (fileContent)); 251 252 hashMapFromFile.putAll(hashMap); 253 254 IOTools.writeFile( 255 SourceUtils.hashMapToXml(hashMapFromFile), f); 256 257 } 258 259 } 260 261 Date t = (Date ) syncItem.getPropertyValue(SyncItem.PROPERTY_TIMESTAMP); 262 263 f.setLastModified(t.getTime()); 264 265 setState(principal, fileName, SyncItemState.SYNCHRONIZED); 266 267 SyncItem newSyncItem = 268 new SyncItemImpl(this, fileName, SyncItemState.NEW); 269 270 newSyncItem.setProperties(syncItem.getProperties()); 271 272 return newSyncItem; 273 } catch (IOException e) { 274 throw new SyncException( "Error setting the item " 275 + syncItem 276 , e 277 ); 278 } 279 catch (Exception e) { 280 throw new SyncException( "Error setting the hashmap in item " 281 + syncItem 282 , e 283 ); 284 } 285 } 286 287 public void commitSync() { 288 } 289 290 330 private Properties updateSyncDatabase(Principal principal) { 331 332 Properties syncDatabase = new Properties (); 333 334 try { 335 File fileSyncDatabase = getDatabaseFile(principal); 336 337 if (fileSyncDatabase.exists()) { 341 FileInputStream fis = new FileInputStream(fileSyncDatabase); 342 syncDatabase.load(fis); 343 fis.close(); 344 } 345 346 Vector existingFiles = getExistingFiles(); 350 351 Enumeration databaseFiles = syncDatabase.propertyNames(); 355 356 String state = null, 357 fileName = null; 358 359 long lastModified; 360 361 int n = existingFiles.size(); 362 for (int i=0; i < n; ++i) { 363 fileName = (String )existingFiles.elementAt(i); 364 lastModified = new File(sourceDirectory, fileName).lastModified(); 365 366 state = syncDatabase.getProperty(fileName); 367 368 if (state != null) { 369 if (lastModified > lastModifiedFromStateString(state)) { 373 state = buildStateString(SyncItemState.UPDATED, lastModified); 374 syncDatabase.put(fileName, state); 375 } 376 } else { 377 state = buildStateString(SyncItemState.NEW, lastModified); 381 syncDatabase.put(fileName, state); 382 } 383 } 385 for (; databaseFiles.hasMoreElements();) { 386 fileName = (String )databaseFiles.nextElement(); 387 388 if (!existingFiles.contains(fileName)) { 389 state = buildStateString(SyncItemState.DELETED, System.currentTimeMillis()); 390 syncDatabase.put(fileName, state); 391 } 392 } 394 FileOutputStream fos = new FileOutputStream(fileSyncDatabase); 398 syncDatabase.save(fos, DATABASE_HEADER); 399 fos.close(); 400 } catch (IOException e) { 401 e.printStackTrace(); 402 } 403 404 return syncDatabase; 405 } 406 407 private File getDatabaseFile(Principal principal) { 408 return new File(sourceDirectory + '.' + DATABASE_FILE_NAME); 409 } 410 411 private String buildStateString(char state, long lastModified) { 412 return state + String.valueOf(lastModified); 413 } 414 415 private long lastModifiedFromStateString(String state) { 416 return Long.parseLong(state.substring(1)); 417 } 418 419 private char stateFromStateString(String state) { 420 if ((state == null) || (state.length() == 0)) return SyncItemState.UNKNOWN; 421 422 return state.charAt(0); 423 } 424 425 private Vector getExistingFiles() throws IOException { 426 Vector ret = new Vector (); 427 428 String [] files = new File(sourceDirectory).list(); 429 430 if (files != null) { 431 for (int i = 0; i<files.length; ++i) { 432 if (!files[i].endsWith('.' + DATABASE_FILE_NAME)) { 433 ret.addElement(files[i]); 434 } 435 } } 437 438 return ret; 439 } 440 441 private void setState(Principal principal, String file, char state) { 442 try { 443 Properties syncDatabase = new Properties (); 444 445 File fileSyncDatabase = getDatabaseFile(principal); 446 447 if (fileSyncDatabase.exists()) { 451 FileInputStream fis = new FileInputStream(fileSyncDatabase); 452 syncDatabase.load(fis); 453 fis.close(); 454 } 455 456 syncDatabase.put(file, buildStateString(state, System.currentTimeMillis())); 457 458 FileOutputStream fos = new FileOutputStream(fileSyncDatabase); 459 syncDatabase.save(fos, DATABASE_HEADER); 460 fos.close(); 461 } catch (IOException e) { 462 e.printStackTrace(); 463 } 464 } 465 466 private void removeState(Principal principal, String file) { 467 try { 468 File fileSyncDatabase = getDatabaseFile(principal); 469 470 if (!fileSyncDatabase.exists()) return; 471 472 Properties syncDatabase = new Properties (); 473 474 478 FileInputStream fis = new FileInputStream(fileSyncDatabase); 479 syncDatabase.load(fis); 480 fis.close(); 481 482 syncDatabase.remove(file); 483 484 FileOutputStream fos = new FileOutputStream(fileSyncDatabase); 485 syncDatabase.save(fos, DATABASE_HEADER); 486 fos.close(); 487 } catch (IOException e) { 488 e.printStackTrace(); 489 } 490 } 491 492 506 private SyncItem[] filterSyncItems(Principal principal, 507 Date since , 508 char state ) { 509 Properties syncDatabase = updateSyncDatabase(principal); 510 511 Vector syncItems = new Vector (); 512 513 long fileTimestamp, 514 sinceTimestamp = (since == null) ? -1 : since.getTime(); 515 516 SyncItem syncItem = null; 517 String fileName = null; 518 String stateString = null; 519 char fileState ; 520 for (Enumeration e = syncDatabase.keys(); e.hasMoreElements(); ) { 521 fileName = (String )e.nextElement(); 522 stateString = (String )syncDatabase.get(fileName); 523 fileState = stateFromStateString(stateString); 524 if ((state == SyncItemState.UNKNOWN) || (fileState == state)) { 525 fileTimestamp = lastModifiedFromStateString(stateString); 526 if (fileTimestamp > sinceTimestamp ) { 527 syncItem = new SyncItemImpl(this, fileName, fileState); 528 if (encode){ 529 syncItem.setProperty( 530 new SyncItemProperty(SyncItem.PROPERTY_BINARY_CONTENT , 531 Base64.encode(readFileContent(fileName))) 532 ); 533 } else { 534 syncItem.setProperty( 535 new SyncItemProperty(SyncItem.PROPERTY_BINARY_CONTENT, 536 readFileContent(fileName) ) 537 ); 538 } 539 syncItems.addElement(syncItem); 540 } 541 } 542 } 544 SyncItem[] ret = new SyncItem[syncItems.size()]; 545 for (int i=0; i<ret.length; ++i) { 546 ret[i] = (SyncItem)syncItems.elementAt(i); 547 } 548 549 return ret; 550 } 551 552 559 private byte[] readFileContent(String fileName) { 560 byte buf[] = null; 561 562 try { 563 File file = new File(sourceDirectory, fileName); 564 565 if (!file.exists()) return new byte[0]; 566 567 buf = new byte[(int)file.length()]; 568 569 FileInputStream fis = new FileInputStream(file); 570 fis.read(buf); 571 fis.close(); 572 } catch (IOException e) { 573 buf = new byte[0]; 574 e.printStackTrace(); 575 } 576 577 return buf; 578 } 579 580 583 private void restoreSyncDB () { 584 585 Properties syncDatabase = new Properties (); 586 587 String state = null; 588 String fileName = null; 589 590 try { 591 592 File fileSyncDatabase = getDatabaseFile(null); 593 594 if (fileSyncDatabase.exists()) { 598 FileInputStream fis = new FileInputStream(fileSyncDatabase); 599 syncDatabase.load(fis); 600 fis.close(); 601 } 602 603 Enumeration databaseFiles = syncDatabase.propertyNames(); 607 608 for (; databaseFiles.hasMoreElements();) { 609 fileName = (String )databaseFiles.nextElement(); 610 611 state = syncDatabase.getProperty(fileName); 612 613 if (stateFromStateString(state) == SyncItemState.DELETED) { 614 syncDatabase.remove(fileName); 615 } 616 } 618 619 FileOutputStream fos = new FileOutputStream(fileSyncDatabase); 623 syncDatabase.save(fos, DATABASE_HEADER); 624 fos.close(); 625 } catch (IOException e) { 626 e.printStackTrace(); 627 } 628 629 } 630 631 632 } 633 | Popular Tags |