1 18 package sync4j.server.engine; 19 20 import java.security.Principal ; 21 import java.sql.Timestamp ; 22 import java.util.*; 23 import java.util.logging.Level ; 24 import java.util.logging.Logger ; 25 26 import org.apache.commons.collections.ListUtils; 27 28 import sync4j.framework.core.Add; 29 import sync4j.framework.core.ModificationCommand; 30 import sync4j.framework.core.StatusCode; 31 import sync4j.framework.engine.*; 32 import sync4j.framework.engine.Util; 33 import sync4j.framework.engine.source.MemorySyncSource; 34 import sync4j.framework.engine.source.ObjectSizeMismatchException; 35 import sync4j.framework.engine.source.SyncSource; 36 import sync4j.framework.engine.source.SyncSourceException; 37 38 86 public class Sync4jStrategy implements SyncStrategy, java.io.Serializable { 87 88 90 public static String LOG_NAME = "sync4j.framework.engine"; 91 92 private transient static Logger log = Logger.getLogger(LOG_NAME); 93 94 96 99 private transient SyncSource[] sources = null; 100 public SyncSource[] getSources(){ return sources; } 101 102 public void setSources(SyncSource[] sources){ this.sources = sources; } 103 104 107 public String getName(){ return name; } 108 109 private String name; 110 public void setName(String name){ this.name = name; } 111 112 114 private HashMap newBAll; 132 private HashMap updatedBAll; 133 private HashMap deletedBAll; 134 135 137 public Sync4jStrategy() { 138 newBAll = new HashMap(); 139 updatedBAll = new HashMap(); 140 deletedBAll = new HashMap(); 141 } 142 143 public Sync4jStrategy(SyncSource[] syncSources) { 144 this(); 145 sources = syncSources; 146 } 147 148 150 171 public SyncOperation[] prepareSlowSync(SyncSource[] sources , 172 Principal principal, 173 Timestamp nextSync , 174 boolean last ) 175 throws SyncException { 176 177 if (sources != null) { 178 this.sources = sources; 179 } 180 181 SyncItem[] Am, Bm; 182 List syncOperations = new ArrayList(); 183 184 Logger log = Logger.getLogger(LOG_NAME); 185 186 if (log.isLoggable(Level.INFO)) { 187 log.info( "Preparing slow synchronization of source '" 188 + sources[1].getSourceURI() 189 + "' for " 190 + principal 191 + " ..." 192 ); 193 if (last) { 194 log.info("Last call"); 195 } else { 196 log.info("Not the last call"); 197 } 198 } 199 200 Am = sources[1].getUpdatedSyncItems(principal, null); 204 Bm = sources[0].getAllSyncItems(principal); 205 206 if (Am == null) { 210 Am = new SyncItem[0]; 211 } 212 213 if (Bm == null) { 214 Bm = new SyncItem[0]; 215 } 216 217 ArrayList newlyMappedItems = new ArrayList(); 224 fixMappedItems(newlyMappedItems, Am, sources[0], principal); 225 226 EngineHelper.resetState(Am); 230 EngineHelper.resetState(Bm); 231 232 for (int i=0; i<Am.length; ++i) { 233 if (!Am[i].isMapped()) { 234 syncOperations.add(checkSyncOperation(principal, nextSync, Am[i], null)); 235 } 236 } 237 238 Iterator j = newlyMappedItems.iterator(); 239 while (j.hasNext()) { 240 SyncItemMapping m = (SyncItemMapping)j.next(); 241 m.getSyncItemA().setState(SyncItemState.SYNCHRONIZED); 242 m.getSyncItemB().setState(SyncItemState.SYNCHRONIZED); 243 syncOperations.add(checkSyncOperation(principal, nextSync, m.getSyncItemA(), m.getSyncItemB())); 244 } 245 246 if (last) { 251 EngineHelper.resetState(Am); 258 259 List all = new ArrayList(Arrays.asList(sources[1].getAllSyncItems(principal))); 260 all.addAll(Arrays.asList(Am)); 261 262 for (int i=0; i<Bm.length; ++i) { 263 if (!(all.contains(Bm[i]))) { 264 syncOperations.add(checkSyncOperation(principal, nextSync, null, Bm[i])); 265 } 266 } 267 } 268 269 if (log.isLoggable(Level.FINEST)) { 270 log.finest("operations: " + syncOperations); 271 } 272 273 if (log.isLoggable(Level.INFO)) { 274 log.info("Preparation completed."); 275 } 276 277 return (SyncOperation[])syncOperations.toArray(new SyncOperationImpl[] {}); 278 } 279 280 299 public SyncOperation[] prepareFastSync(SyncSource[] sources , 300 Principal principal, 301 Timestamp lastSync , 302 Timestamp nextSync , 303 boolean last ) 304 throws SyncException { 305 if (sources != null) { 306 this.sources = sources; 307 } 308 309 311 List Am , Bm , AmBm , AAmBm , AmBBm ; 317 ArrayList syncOperations = null; 318 319 SyncItem[] newA = null, newB = null, 320 updatedA = null, updatedB = null, 321 deletedA = null, deletedB = null; 322 323 if (log.isLoggable(Level.INFO)) { 324 log.info( "Preparing fast synchronization of source '" 325 + sources[1].getSourceURI() 326 + "' for " 327 + principal 328 + " since " 329 + lastSync 330 + "..." 331 ); 332 333 if (last) { 334 log.info("Last call"); 335 } else { 336 log.info("Not the last call"); 337 } 338 } 339 340 342 newA = sources[1].getNewSyncItems (principal, lastSync); 347 updatedA = sources[1].getUpdatedSyncItems (principal, lastSync); 348 deletedA = sources[1].getDeletedSyncItems (principal, lastSync); 349 350 if (log.isLoggable(Level.FINEST)) { 351 log.finest("newA: " + Util.arrayToString(newA)); 352 log.finest("updatedA: " + Util.arrayToString(updatedA)); 353 log.finest("deletedA: " + Util.arrayToString(deletedA)); 354 } 355 356 String uri = sources[0].getSourceURI(); 357 if (newBAll.get(uri) == null) { 358 if (log.isLoggable(Level.FINEST)) { 359 log.finest("Detecting server changes..."); 360 } 361 newB = sources[0].getNewSyncItems (principal, lastSync); 362 updatedB = sources[0].getUpdatedSyncItems (principal, lastSync); 363 deletedB = sources[0].getDeletedSyncItems (principal, lastSync); 364 365 if (newB == null) { 369 newB = new SyncItemImpl[0]; 370 } 371 if (updatedB == null) { 372 updatedB = new SyncItemImpl[0]; 373 } 374 if (deletedB == null) { 375 deletedB = new SyncItemImpl[0]; 376 } 377 378 if (log.isLoggable(Level.FINEST)) { 379 log.finest("newB: " + Util.arrayToString(newB)); 380 log.finest("updatedB: " + Util.arrayToString(updatedB)); 381 log.finest("deletedB: " + Util.arrayToString(deletedB)); 382 } 383 384 newBAll .put(uri, newB); 385 updatedBAll.put(uri, updatedB); 386 deletedBAll.put(uri, deletedB); 387 } else { 388 newB = (SyncItem[])newBAll .get(uri); 389 updatedB = (SyncItem[])updatedBAll.get(uri); 390 deletedB = (SyncItem[])deletedBAll.get(uri); 391 } 392 393 ArrayList newlyMappedItems = new ArrayList(); 400 401 fixMappedItems(newlyMappedItems, newA, sources[0], principal); 402 fixMappedItems(newlyMappedItems, updatedA, sources[0], principal); 403 fixMappedItems(newlyMappedItems, deletedA, sources[0], principal); 404 405 if (log.isLoggable(Level.FINEST)) { 406 log.finest("Newly mapped items: " + newlyMappedItems); 407 } 408 409 Am = new ArrayList(); Bm = new ArrayList(); 410 Am.addAll(Arrays.asList(newA )); 411 Am.addAll(Arrays.asList(updatedA )); 412 Am.addAll(Arrays.asList(deletedA )); 413 Bm.addAll(Arrays.asList(newB )); 414 Bm.addAll(Arrays.asList(updatedB )); 415 Bm.addAll(Arrays.asList(deletedB )); 416 417 if (log.isLoggable(Level.FINEST)) { 418 log.finest("Am: " + Am); 419 log.finest("Bm: " + Bm); 420 log.finest("Am-Bm: " + ListUtils.subtract(Am, Bm)); 421 log.finest("Bm-Am: " + ListUtils.subtract(Bm, Am)); 422 } 423 424 AmBm = EngineHelper.intersect(Am, Bm); 430 AmBBm = EngineHelper.buildAmBBm(ListUtils.subtract(Am, Bm), sources[0], principal); 431 432 AAmBm = new ArrayList(); 433 if (last) { 434 newA = ((MemorySyncSource)sources[1]).getAllNewSyncItems (principal, lastSync); 439 updatedA = ((MemorySyncSource)sources[1]).getAllUpdatedSyncItems (principal, lastSync); 440 deletedA = ((MemorySyncSource)sources[1]).getAllDeletedSyncItems (principal, lastSync); 441 442 AAmBm = EngineHelper.buildAAmBm(ListUtils.subtract(Bm, Am), sources[1], principal); 443 } else { 444 Bm.clear(); 445 } 446 447 if (log.isLoggable(Level.FINEST)) { 448 log.finest("AmBm: " + AmBm ); 449 log.finest("AmBBm: " + AmBBm); 450 log.finest("AAmBm: " + AAmBm); 451 } 452 453 syncOperations = 457 checkSyncOperations(principal, nextSync, Am, Bm, AmBm, AmBBm, AAmBm); 458 459 if (log.isLoggable(Level.FINEST)) { 460 log.finest("operations: " + syncOperations); 461 } 462 463 if (log.isLoggable(Level.INFO)) { 464 log.info("Preparation completed."); 465 } 466 467 return (SyncOperation[])syncOperations.toArray(new SyncOperationImpl[] {}); 468 } 469 470 475 public SyncOperationStatus[] sync(SyncOperation[] syncOperations) { 476 Logger log = Logger.getLogger(LOG_NAME); 477 478 if (log.isLoggable(Level.INFO)) { 479 log.info("Synchronizing..."); 480 } 481 482 if ((syncOperations == null) || (syncOperations.length == 0)) { 483 return new SyncOperationStatus[0]; 484 } 485 486 ArrayList status = new ArrayList(); 487 488 SyncOperationStatus[] operationStatus = null; 489 for(int i=0; i<syncOperations.length; ++i) { 490 if (log.isLoggable(Level.FINEST)) { 491 log.finest("Executing " + syncOperations[i]); 492 } 493 494 operationStatus = execSyncOperation((SyncOperationImpl)syncOperations[i]); 499 500 for (int j=0; j<operationStatus.length; ++j) { 501 status.add(operationStatus[j]); 502 } } 505 if (log.isLoggable(Level.FINEST)) { 506 log.finest("status: " + status); 507 } 508 509 return (SyncOperationStatus[])status.toArray(new SyncOperationStatus[0]); 510 } 511 512 517 public void endSync() throws SyncException { 518 Logger log = Logger.getLogger(LOG_NAME); 519 520 if (log.isLoggable(Level.INFO)) { 521 log.info("Synchronization completed."); 522 } 523 } 524 525 527 542 protected ArrayList checkSyncOperations(Principal principal, 543 Timestamp nextSync , 544 List Am , 545 List Bm , 546 List AmBm , 547 List AmBBm , 548 List AAmBm ) { 549 SyncItemMapping mapping = null; 550 SyncItem syncItemA = null, syncItemB = null; 551 552 ArrayList all = new ArrayList(); 553 ArrayList operations = new ArrayList(); 554 555 557 all.addAll(AmBm ); 558 all.addAll(AmBBm); 559 all.addAll(AAmBm); 560 561 Iterator i = all.iterator(); 565 while (i.hasNext()) { 566 mapping = (SyncItemMapping)i.next(); 567 568 syncItemA = mapping.getSyncItemA(); 569 syncItemB = mapping.getSyncItemB(); 570 571 operations.add( 572 checkSyncOperation( 573 principal, 574 nextSync , 575 syncItemA, 576 syncItemB 577 ) 578 ); 579 Am.remove(syncItemA); 580 Bm.remove(syncItemB); 581 } 582 583 i = Am.iterator(); 587 while (i.hasNext()) { 588 syncItemA = (SyncItem)i.next(); 589 590 operations.add(checkSyncOperation(principal, nextSync, syncItemA, null)); 591 } 593 i = Bm.iterator(); 597 while (i.hasNext()) { 598 syncItemB = (SyncItem)i.next(); 599 600 operations.add(checkSyncOperation(principal, nextSync, null, syncItemB)); 601 } 603 return operations; 604 } 605 606 616 protected SyncOperation checkSyncOperation(Principal principal, 617 Timestamp nextSync , 618 SyncItem syncItemA, 619 SyncItem syncItemB) { 620 if (log.isLoggable(Level.FINEST)) { 621 log.finest( "check: syncItemA: " 622 + syncItemA 623 + " syncItemB: " 624 + syncItemB 625 ); 626 } 627 628 if (syncItemA == null) { 629 syncItemA = SyncItemImpl.getNotExistingSyncItem(null); 630 } 631 if (syncItemB == null) { 632 syncItemB = SyncItemImpl.getNotExistingSyncItem(null); 633 } 634 635 switch (syncItemA.getState()) { 636 case SyncItemState.NEW: 640 switch (syncItemB.getState()) { 641 case SyncItemState.NEW: 642 return new SyncConflict(syncItemA, syncItemB, 643 String.valueOf(SyncItemState.NEW) + 644 String.valueOf(SyncItemState.NEW) ); 645 case SyncItemState.UPDATED: 646 return new SyncConflict(syncItemA, syncItemB, 647 String.valueOf(SyncItemState.NEW) + 648 String.valueOf(SyncItemState.UPDATED) ); 649 case SyncItemState.DELETED: 650 return new SyncConflict(syncItemA, syncItemB, 651 String.valueOf(SyncItemState.NEW) + 652 String.valueOf(SyncItemState.DELETED) ); 653 case SyncItemState.SYNCHRONIZED: 654 return new SyncConflict(syncItemA, syncItemB, 655 String.valueOf(SyncItemState.NEW) + 656 String.valueOf(SyncItemState.SYNCHRONIZED) ); 657 case SyncItemState.NOT_EXISTING: 658 syncItemA.setPropertyValue(syncItemB.PROPERTY_TIMESTAMP, nextSync); 659 return new SyncOperationImpl(principal, syncItemA, syncItemB, SyncOperation.NEW, false, true); 660 } 662 case SyncItemState.DELETED: 666 switch (syncItemB.getState()) { 667 case SyncItemState.NEW: 668 return new SyncConflict(syncItemA, syncItemB, 669 String.valueOf(SyncItemState.DELETED) + 670 String.valueOf(SyncItemState.NEW) ); 671 case SyncItemState.UPDATED: 672 syncItemB.setState(SyncItemState.NEW); 673 return new SyncConflict(syncItemA, syncItemB, 674 String.valueOf(SyncItemState.DELETED) + 675 String.valueOf(SyncItemState.NEW) ); 676 case SyncItemState.SYNCHRONIZED: 677 return new SyncOperationImpl(principal, syncItemA, syncItemB, SyncOperation.DELETE, false, true); 678 679 case SyncItemState.DELETED: 680 case SyncItemState.NOT_EXISTING: 681 return new SyncOperationImpl(principal, syncItemB, syncItemA, SyncOperation.NOP, false, false); 682 } 684 case SyncItemState.UPDATED: 688 switch (syncItemB.getState()) { 689 case SyncItemState.NEW: 690 return new SyncConflict(syncItemA, syncItemB, 691 String.valueOf(SyncItemState.UPDATED) + 692 String.valueOf(SyncItemState.NEW) ); 693 case SyncItemState.UPDATED: 694 return new SyncConflict(syncItemA, syncItemB, 695 String.valueOf(SyncItemState.UPDATED) + 696 String.valueOf(SyncItemState.UPDATED) ); 697 case SyncItemState.DELETED: 698 return new SyncConflict(syncItemA, syncItemB, 699 String.valueOf(SyncItemState.UPDATED) + 700 String.valueOf(SyncItemState.DELETED) ); 701 case SyncItemState.SYNCHRONIZED: 702 syncItemA.setPropertyValue(syncItemB.PROPERTY_TIMESTAMP, nextSync); 703 return new SyncOperationImpl(principal, syncItemA, syncItemB, SyncOperation.UPDATE, false, true); 704 case SyncItemState.NOT_EXISTING: 705 syncItemA.setPropertyValue(syncItemB.PROPERTY_TIMESTAMP, nextSync); 706 return new SyncOperationImpl(principal, syncItemA, syncItemB, SyncOperation.NEW, false, true); 707 } 709 case SyncItemState.SYNCHRONIZED: 713 switch (syncItemB.getState()) { 714 case SyncItemState.NEW: 715 return new SyncConflict(syncItemA, syncItemB, 716 String.valueOf(SyncItemState.SYNCHRONIZED) + 717 String.valueOf(SyncItemState.NEW) ); 718 case SyncItemState.UPDATED: 719 return new SyncOperationImpl(principal, syncItemA, syncItemB, SyncOperation.UPDATE, true, false); 720 case SyncItemState.DELETED: 721 return new SyncOperationImpl(principal, syncItemA, syncItemB, SyncOperation.DELETE, true, false); 722 case SyncItemState.SYNCHRONIZED: 723 return new SyncOperationImpl(principal, syncItemA, syncItemB, SyncOperation.NOP, false, false); 724 case SyncItemState.NOT_EXISTING: 725 return new SyncOperationImpl(principal, syncItemA, syncItemB, SyncOperation.NEW, false, true); 726 } 728 case SyncItemState.NOT_EXISTING: 732 switch (syncItemB.getState()) { 733 case SyncItemState.NEW: 734 case SyncItemState.UPDATED: 735 return new SyncOperationImpl(principal, syncItemA, syncItemB, SyncOperation.NEW, true, false); 736 case SyncItemState.SYNCHRONIZED: 737 return new SyncOperationImpl(principal, syncItemA, syncItemB, SyncOperation.NEW, true, false); 738 case SyncItemState.NOT_EXISTING: 739 case SyncItemState.DELETED: 740 return new SyncOperationImpl(principal, syncItemA, syncItemB, SyncOperation.NOP, false, false); 741 } 743 case SyncItemState.PARTIAL: 747 switch (syncItemB.getState()) { 748 case SyncItemState.NEW: 749 return new SyncConflict(syncItemA, syncItemB, 750 String.valueOf(SyncItemState.UPDATED) + 751 String.valueOf(SyncItemState.NEW) ); 752 case SyncItemState.UPDATED: 753 return new SyncConflict(syncItemA, syncItemB, 754 String.valueOf(SyncItemState.UPDATED) + 755 String.valueOf(SyncItemState.UPDATED) ); 756 case SyncItemState.DELETED: 757 return new SyncConflict(syncItemA, syncItemB, 758 String.valueOf(SyncItemState.UPDATED) + 759 String.valueOf(SyncItemState.DELETED) ); 760 case SyncItemState.SYNCHRONIZED: 761 return new SyncOperationImpl(principal, syncItemA, null, SyncOperation.ACCEPT_CHUNK, false, true); 762 case SyncItemState.NOT_EXISTING: 763 return new SyncOperationImpl(principal, syncItemA, null, SyncOperation.ACCEPT_CHUNK, false, true); 764 } 766 case SyncItemState.CONFLICT: 771 return new SyncConflict(syncItemA, syncItemB, "CX"); 772 } 774 return new SyncOperationImpl(principal, syncItemA, syncItemB, SyncOperation.NOP, false, false); 775 } 776 777 790 protected SyncOperationStatus[] execSyncOperation(SyncOperationImpl operation) { 791 SyncItem syncItemA = operation.getSyncItemA(), 792 syncItemB = operation.getSyncItemB(); 793 794 Principal owner = operation.getOwner(); 795 SyncOperationStatus[] status = null; 796 ModificationCommand cmd = null; 797 798 int size = 0, s = 0; 799 800 switch (operation.getOperation()) { 801 case SyncOperation.NEW: 802 status = new SyncOperationStatus[1]; 803 if (operation.isAOperation()) { 804 cmd = (ModificationCommand)syncItemA.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND); 805 try { 806 syncItemA = sources[1].setSyncItem(owner, syncItemB); 807 operation.setSyncItemA(syncItemA); 808 status[0] = new Sync4jOperationStatusOK(operation, sources[1], cmd, StatusCode.ITEM_ADDED); 809 } catch (SyncException e) { 810 log.severe("Error executing sync operation: " + e.getMessage()); 811 log.throwing(getClass().getName(), "execSyncOperation", e); 812 status[0] = new Sync4jOperationStatusError(operation, sources[1], cmd, e); 813 operation.setAOperation(false); 814 operation.setBOperation(false); 815 } 816 } else if (operation.isBOperation()) { 817 cmd = (ModificationCommand)syncItemA.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND); 818 syncItemB.setProperty(syncItemA.getProperty(SyncItem.PROPERTY_TIMESTAMP)); try { 821 checkSize(syncItemA); 822 syncItemB = sources[0].setSyncItem(owner, syncItemA); 823 operation.setSyncItemB(syncItemB); 824 status[0] = new Sync4jOperationStatusOK(operation, sources[1], cmd, StatusCode.ITEM_ADDED); 825 } catch (ObjectSizeMismatchException e) { 826 log.info(e.getMessage()); 827 status[0] = new Sync4jOperationStatusError(operation, sources[0], cmd, e); 828 operation.setAOperation(false); 829 operation.setBOperation(false); 830 } catch (SyncException e) { 831 log.severe("Error executing sync operation: " + e.getMessage()); 832 log.throwing(getClass().getName(), "execSyncOperation", e); 833 status[0] = new Sync4jOperationStatusError(operation, sources[0], cmd, e); 834 operation.setAOperation(false); 835 operation.setBOperation(false); 836 } 837 } 838 break; 839 840 case SyncOperation.UPDATE: 841 status = new SyncOperationStatus[1]; 842 if (operation.isAOperation()) { 843 cmd = (ModificationCommand)syncItemA.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND); 844 try { 845 syncItemA = sources[1].setSyncItem(owner, syncItemB); 846 operation.setSyncItemA(syncItemA); 847 status[0] = new Sync4jOperationStatusOK(operation, sources[1], cmd); 848 } catch (SyncException e) { 849 log.severe("Error executing sync operation: " + e.getMessage()); 850 log.throwing(getClass().getName(), "execSyncOperation", e); 851 status[0] = new Sync4jOperationStatusError(operation, sources[1], cmd, e); 852 operation.setAOperation(false); 853 operation.setBOperation(false); 854 } 855 } else if (operation.isBOperation()) { 856 cmd = (ModificationCommand)syncItemA.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND); 857 syncItemB.setProperty(syncItemA.getProperty(SyncItem.PROPERTY_TIMESTAMP)); try { 860 checkSize(syncItemA); 861 syncItemB = sources[0].setSyncItem(owner, syncItemA); 862 operation.setSyncItemB(syncItemB); 863 status[0] = new Sync4jOperationStatusOK(operation, sources[0], cmd); 864 } catch (ObjectSizeMismatchException e) { 865 log.info(e.getMessage()); 866 status[0] = new Sync4jOperationStatusError(operation, sources[0], cmd, e); 867 operation.setAOperation(false); 868 operation.setBOperation(false); 869 } catch (SyncException e) { 870 log.severe("Error executing sync operation: " + e.getMessage()); 871 log.throwing(getClass().getName(), "execSyncOperation", e); 872 status[0] = new Sync4jOperationStatusError(operation, sources[0], cmd, e); 873 operation.setAOperation(false); 874 operation.setBOperation(false); 875 } 876 } 877 break; 878 879 case SyncOperation.DELETE: 880 size = 1; 886 if (operation.isAOperation() && operation.isBOperation()) { 887 size = 2; 888 } 889 status = new SyncOperationStatus[size]; 890 891 s = 0; 892 if (operation.isBOperation()) { 893 cmd = (ModificationCommand)syncItemA.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND); 894 syncItemB.setProperty(syncItemA.getProperty(SyncItem.PROPERTY_TIMESTAMP)); try { 898 sources[0].removeSyncItem(owner, syncItemB); 899 status[s++] = new Sync4jOperationStatusOK(operation, sources[0], cmd); 900 } catch (SyncException e) { 901 log.severe("Error executing sync operation: " + e.getMessage()); 902 log.throwing(getClass().getName(), "execSyncOperation", e); 903 status[s++] = new Sync4jOperationStatusError(operation, sources[0], cmd, e); 904 operation.setAOperation(false); 905 operation.setBOperation(false); 906 } 907 } 908 if (operation.isAOperation()) { 909 cmd = (ModificationCommand)syncItemA.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND); 910 911 try { 912 sources[1].removeSyncItem(owner, syncItemA); 913 status[s++] = new Sync4jOperationStatusOK(operation, sources[1], cmd); 914 } catch (SyncException e) { 915 log.severe("Error executing sync operation: " + e.getMessage()); 916 log.throwing(getClass().getName(), "execSyncOperation", e); 917 status[s++] = new Sync4jOperationStatusError(operation, sources[1], cmd, e); 918 operation.setAOperation(false); 919 operation.setBOperation(false); 920 } 921 } 922 break; 923 924 case SyncOperation.NOP: 925 s = 0; 937 if (operation.isAOperation()) ++size; 938 if (operation.isBOperation()) ++size; 939 940 status = new SyncOperationStatus[size]; 941 942 if (operation.isBOperation()) { 943 cmd = (ModificationCommand)syncItemA.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND); 944 status[s++] = new Sync4jOperationStatusOK(operation, sources[0], cmd); 945 } 946 947 if (operation.isAOperation()) { 948 cmd = (ModificationCommand)syncItemA.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND); 949 status[s++] = new Sync4jOperationStatusOK(operation, sources[1], cmd); 950 } 951 952 if (!operation.isAOperation() && !operation.isBOperation()) { 953 char stateItemA = syncItemA.getState(); 954 char stateItemB = syncItemB.getState(); 955 956 switch (stateItemA) { 957 case SyncItemState.SYNCHRONIZED: 958 if (stateItemB == SyncItemState.SYNCHRONIZED) { 959 status = new SyncOperationStatus[1]; 960 cmd = (ModificationCommand)syncItemA.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND); 961 962 if (cmd instanceof Add) { 963 status[0] = new Sync4jOperationStatusOK(operation, sources[1], cmd, StatusCode.ITEM_ADDED); 964 } else { 965 status[0] = new Sync4jOperationStatusOK(operation, sources[1], cmd); 966 } 967 break; 968 } 969 case SyncItemState.NOT_EXISTING: 970 if (stateItemB == SyncItemState.DELETED) { 971 try { 975 cmd = (ModificationCommand)syncItemB.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND); 976 syncItemA = sources[1].setSyncItem(owner, syncItemB); 977 operation.setSyncItemA(syncItemA); 978 979 status = new SyncOperationStatus[1]; 980 status[0] = new Sync4jOperationStatusOK( 981 operation, 982 sources[1], 983 cmd, 984 StatusCode.ITEM_NOT_DELETED 985 ); 986 break; 987 } catch (SyncException e) { 988 log.severe("Error executing sync operation: " + e.getMessage()); 989 log.throwing(getClass().getName(), "execSyncOperation", e); 990 status[0] = new Sync4jOperationStatusError(operation, sources[1], cmd, e); 991 operation.setAOperation(false); 992 operation.setBOperation(false); 993 } 994 } 995 case SyncItemState.DELETED: 996 if (stateItemB == SyncItemState.DELETED) { 997 status = new SyncOperationStatus[1]; 998 cmd = (ModificationCommand)syncItemB.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND); 999 status[0] = new Sync4jOperationStatusOK(operation, sources[1], cmd); 1000 break; 1001 } 1002 } 1003 } 1004 1005 break; 1006 1007 case SyncOperation.ACCEPT_CHUNK: 1008 status = new SyncOperationStatus[1]; 1009 cmd = (ModificationCommand)syncItemA.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND); 1010 status[0] = new Sync4jOperationStatusOK( 1011 operation, sources[0], cmd, StatusCode.CHUNKED_ITEM_ACCEPTED 1012 ); 1013 break; 1014 1015 case SyncOperation.CONFLICT: 1016 try { 1020 status = new SyncOperationStatus[1]; 1021 SyncConflict sc = (SyncConflict)operation; 1022 cmd = (ModificationCommand)syncItemA.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND); 1023 1024 SyncItem resolvingItem = null; 1029 if (sc.getType().equals(sc.STATE_CONFLICT_NONE)) { 1030 resolvingItem = new SyncItemImpl(syncItemA.getSyncSource(), syncItemA.getMappedKey()); 1031 resolvingItem.setProperties(syncItemA.getProperties()); 1032 sources[1].removeSyncItem(owner, resolvingItem); 1033 } else if (sc.getType().equals(sc.STATE_NEW_NEW)) { 1034 resolvingItem = new SyncItemImpl( 1039 syncItemB.getSyncSource(), 1040 syncItemB.getKey().getKeyAsString(), 1041 syncItemB.getKey().getKeyAsString(), 1042 SyncItemState.UNKNOWN 1043 ); 1044 resolvingItem.setProperties(syncItemB.getProperties()); 1045 1046 syncItemA = sources[1].setSyncItem(owner, resolvingItem); 1047 operation.setSyncItemA(syncItemA); 1048 } else { 1049 SyncItemKey luid = syncItemA.getMappedKey(); 1050 if (luid == null) { 1051 throw new SyncException( "Item A with key " 1052 + syncItemA.getKey() 1053 + " should have a mapping, but the mapped key is null" 1054 ); 1055 } 1056 resolvingItem = new SyncItemImpl( 1057 syncItemB.getSyncSource(), 1058 syncItemA.getMappedKey().getKeyAsString() 1059 ); 1060 resolvingItem.setProperties(syncItemB.getProperties()); 1061 1062 syncItemA = sources[1].setSyncItem(owner, resolvingItem); 1063 operation.setSyncItemA(syncItemA); 1064 } 1065 operation.setAOperation(true); 1066 1067 if (syncItemA.getState() == SyncItemState.NEW && 1068 syncItemB.getState() == SyncItemState.SYNCHRONIZED 1069 ) { 1070 status[0] = new Sync4jOperationStatusConflict( 1075 operation, 1076 sources[1], 1077 cmd, 1078 StatusCode.ALREADY_EXISTS 1079 ); 1080 break; 1081 } 1082 status[0] = new Sync4jOperationStatusConflict( 1086 operation, 1087 sources[1], 1088 cmd, 1089 StatusCode.CONFLICT_RESOLVED_WITH_SERVER_DATA 1090 ); 1091 } catch (SyncException e) { 1092 log.severe("Error executing sync operation: " + e.getMessage()); 1093 log.throwing(getClass().getName(), "execSyncOperation", e); 1094 status[0] = new Sync4jOperationStatusError(operation, sources[1], cmd, e); 1095 operation.setAOperation(false); 1096 operation.setBOperation(false); 1097 } 1098 1099 break; 1100 } 1102 return status; 1103 } 1104 1105 1107 1120 private void fixMappedItems(Collection newlyMappedItems, 1121 SyncItem[] syncItems , 1122 SyncSource source , 1123 Principal principal ) { 1124 SyncItem itemB = null; 1125 1126 for (int i = 0; ((syncItems != null) && (i<syncItems.length)); ++i) { 1127 itemB = null; 1128 if (!syncItems[i].isMapped() && (SyncItemState.PARTIAL != syncItems[i].getState())) { 1129 try { 1130 itemB = source.getSyncItemFromTwin(principal, syncItems[i]); 1131 } catch (SyncSourceException e) { 1132 String msg = "Error retrieving the twin item of " 1133 + syncItems[i].getKey() 1134 + " from source " 1135 + source 1136 + ": " 1137 + e.getMessage(); 1138 log.severe(msg); 1139 log.throwing(getClass().getName(), "fixSyncMapping", e); 1140 } 1141 if (itemB != null) { 1142 if (log.isLoggable(Level.FINEST)) { 1143 log.finest( "Hey, client item " 1144 + syncItems[i].getKey().getKeyAsString() 1145 + " is the same of server item " 1146 + itemB.getKey().getKeyAsString() 1147 + '!' 1148 ); 1149 } 1150 SyncItemMapping mapping = new SyncItemMapping(itemB.getKey()); 1151 mapping.setMapping(syncItems[i], itemB); 1152 if (newlyMappedItems != null) { 1153 newlyMappedItems.add(mapping); 1154 } 1155 syncItems[i] = SyncItemHelper.newMappedSyncItem(itemB.getKey(), syncItems[i]); 1156 } 1157 } 1158 } } 1160 1161 1172 private void checkSize(SyncItem item) 1173 throws ObjectSizeMismatchException { 1174 Long size = (Long )item.getPropertyValue(item.PROPERTY_SIZE); 1175 1176 if (size == null) { 1177 return; 1178 } 1179 1180 byte[] data = (byte[])item.getPropertyValue(item.PROPERTY_BINARY_CONTENT); 1181 1182 if (data.length != size.intValue()) { 1183 throw new ObjectSizeMismatchException("The size of the received object does not match the given size"); 1184 } 1185 } 1186} 1187 1188 | Popular Tags |