1 18 19 package sync4j.exchange.engine.source; 20 21 import java.io.ByteArrayInputStream ; 22 import java.io.Serializable ; 23 import java.security.Principal ; 24 import java.sql.Timestamp ; 25 import java.util.ArrayList ; 26 import java.util.Date ; 27 import java.util.logging.Logger ; 28 import java.util.logging.Level ; 29 30 import sync4j.exchange.xml.XmlParser; 31 32 import sync4j.foundation.pdi.converter.*; 33 import sync4j.foundation.pdi.parser.*; 34 35 import sync4j.framework.logging.Sync4jLogger; 36 import sync4j.framework.engine.SyncItemImpl; 37 import sync4j.framework.engine.SyncItem; 38 import sync4j.framework.engine.SyncItemKey; 39 import sync4j.framework.engine.SyncProperty; 40 import sync4j.framework.engine.SyncItemState; 41 import sync4j.framework.engine.source.SyncSource; 42 import sync4j.framework.engine.source.SyncSourceException; 43 import sync4j.framework.engine.source.AbstractSyncSource; 44 import sync4j.framework.security.Sync4jPrincipal; 45 import sync4j.framework.server.store.NotFoundException; 46 import sync4j.framework.tools.Base64; 47 48 import sync4j.exchange.items.contact.model.Contact; 49 import sync4j.exchange.items.contact.manager.ContactManager; 50 import sync4j.exchange.items.contact.ContactParseException; 51 import sync4j.exchange.DataAccessException; 52 53 60 public class ExchangeContactSyncSource 61 extends ExchangeSyncSource 62 implements SyncSource, Serializable { 63 64 66 private static final String EXCHANGE_HREF_EXTENSION = ".eml"; 67 68 70 private ContactManager cm = null ; 71 72 74 public ExchangeContactSyncSource() { 75 } 76 77 79 82 public SyncItem setSyncItem(Principal principal, SyncItem syncItem) 83 throws SyncSourceException { 84 85 if (log.isLoggable(Level.FINEST)) { 86 log.finest("setSyncItem - source: " + sourceURI); 87 } 88 89 Contact contact = null ; 90 Contact newContact = null ; 91 92 String itemKey = null ; 93 String href = null ; 94 String content = null ; 95 96 String username = null ; 97 String credentials = null ; 98 99 boolean isAddContact = false ; 100 101 try { 102 103 username = ((Sync4jPrincipal)principal).getUsername() ; 104 credentials = ((Sync4jPrincipal)principal).getEncodedCredentials() ; 105 106 itemKey = syncItem.getKey().getKeyAsString(); 107 108 href = getHref(itemKey); 112 113 if (href == null) { 114 href = String.valueOf(System.currentTimeMillis()) + 119 EXCHANGE_HREF_EXTENSION; 120 isAddContact = true; 121 } 122 123 124 if (log.isLoggable(Level.FINEST)) { 125 if (!isAddContact) { 126 log.finest(itemKey + " already exists: updating"); 127 } else { 128 log.finest(itemKey + " is new: adding"); 129 } 130 } 131 132 contact = getContactFromSyncItem(syncItem); 133 contact.setHref(href); 134 135 cm = getContactManager(); 136 137 newContact = cm.setContact (contact , 138 username , 139 credentials , 140 exchangeFolder); 141 142 if (isAddContact) { 143 toChangedItems(newContact.getId(), ITEM_ADD); 144 } else { 145 toChangedItems(newContact.getId(), ITEM_UPDATE); 146 } 147 148 syncItem = getSyncItem(newContact); 149 150 return syncItem; 151 152 } catch (DataAccessException e) { 153 154 if (newContact != null) { 155 if (isAddContact) { 156 toChangedItems(newContact.getId(), ITEM_ADD_ERROR); 157 } else { 158 toChangedItems(newContact.getId(), ITEM_UPDATE_ERROR); 159 } 160 } 161 162 throw new SyncSourceException("Error setting the item " 163 + syncItem 164 , e 165 ); 166 } 167 } 168 169 172 public SyncItem[] setSyncItems(Principal principal, SyncItem[] syncItems) 173 throws SyncSourceException { 174 175 ArrayList syncItemsInError = new ArrayList (); 176 ArrayList ret = new ArrayList (); 177 178 for (int i = 0, l = syncItems.length; i < l; ++i) { 179 try { 180 ret.add(setSyncItem(principal, syncItems[i])); 181 } catch (SyncSourceException e) { 182 syncItemsInError.add(syncItems[i]); 183 } 184 } 186 if (syncItemsInError.size() > 0) { 187 throw new SyncSourceException("Error setting the following items: " 188 + syncItemsInError.toString() 189 ); 190 } 191 192 if (log.isLoggable(Level.SEVERE)) { 193 log.severe("Exchange SyncSource " + 194 sourceURI + 195 " - set syncItems"); 196 } 197 198 return (SyncItem[])ret.toArray(new SyncItem[] {}); 199 200 } 201 202 205 public SyncItem getSyncItemFromId(Principal principal, 206 SyncItemKey syncItemKey) 207 throws SyncSourceException{ 208 209 SyncItem[] syncItems = 210 getSyncItemsFromIds(principal, new SyncItemKey[] {syncItemKey}); 211 212 if ((syncItems == null) || (syncItems.length == 0)) { 213 return null; 214 } 215 216 return syncItems[0]; 217 218 } 219 220 223 public SyncItem[] getSyncItemsFromIds(Principal principal, 224 SyncItemKey[] syncItemKeys) 225 throws SyncSourceException { 226 227 ArrayList syncItems = null ; 228 Contact contact = null ; 229 230 String username = null ; 231 String credentials = null ; 232 233 String id = null ; 234 235 username = ((Sync4jPrincipal) principal).getUsername() ; 236 credentials = ((Sync4jPrincipal) principal).getEncodedCredentials() ; 237 238 syncItems = new ArrayList (); 239 240 int l = syncItemKeys.length; 241 242 for (int i = 0; ((syncItemKeys != null) && (i < l)); ++i) { 243 244 id = syncItemKeys[i].getKeyAsString(); 245 246 try { 247 cm = getContactManager(); 248 contact = cm.getContactById(username , 249 credentials , 250 id , 251 exchangeFolder); 252 } catch (DataAccessException e) { 253 254 Throwable previous = e.getCause(); 255 256 if (previous instanceof NotFoundException) { 257 258 Logger log = Sync4jLogger.getLogger("source"); 259 if (log.isLoggable(Level.SEVERE)) { 260 log.severe("Contact not found while reading Exchange database: " + e.getMessage()); 261 } 262 Logger.getLogger(LOG_NAME).throwing(getClass().getName(), "readExchangeDatabase", e); 263 } else{ 264 throw new SyncSourceException("Error reading items", e); 265 } 266 } 267 268 269 if (contact != null) { 270 contact.setStatus(SyncItemState.NEW); 271 syncItems.add(getSyncItem(contact)); 272 } 273 274 } 275 276 if (log.isLoggable(Level.SEVERE)) { 277 log.severe("Exchange SyncSource " + 278 sourceURI + 279 " - getting syncItems" ); 280 } 281 282 return (SyncItem[]) syncItems.toArray(new SyncItem[syncItems.size()]); 283 284 } 285 286 289 public SyncItemKey[] getNewSyncItemKeys(Principal principal, 290 Timestamp since ) 291 throws SyncSourceException { 292 return null; 293 } 294 295 298 public SyncItem[] getNewSyncItems(Principal principal, 299 Timestamp since) 300 throws SyncSourceException { 301 302 String ids[] = null; 303 304 ids = this.getNewItemIds(); 305 306 if (log.isLoggable(Level.FINEST)) { 307 log.severe("Exchange SyncSource " + 308 sourceURI + 309 " - getting new syncItems" ); 310 } 311 312 if(ids == null || !(ids.length > 0)) { 313 return new SyncItem[0]; 314 } 315 316 return filterSyncItems(principal, ids, SyncItemState.NEW); 317 318 } 319 320 323 public SyncItemKey[] getDeletedSyncItemKeys(Principal principal, 324 Timestamp since ) 325 throws SyncSourceException { 326 return null; 327 } 328 329 332 public SyncItem[] getDeletedSyncItems(Principal principal, 333 Timestamp since ) 334 throws SyncSourceException { 335 336 String [] ids = null ; 337 SyncItem[] syncItems = null ; 338 339 ids = this.getDeleteItemIds(); 340 341 int l = ids.length; 342 343 syncItems = new SyncItem[l]; 344 345 for (int i = 0; i < l; i++) { 346 347 syncItems[i] = new SyncItemImpl(this, ids[i], SyncItemState.DELETED); 348 } 349 350 if (log.isLoggable(Level.FINEST)) { 351 log.severe("Exchange SyncSource " + 352 sourceURI + 353 " - getting deleted syncItems" ); 354 } 355 356 return syncItems; 357 } 358 359 362 public SyncItem[] getUpdatedSyncItems(Principal principal, 363 Timestamp since) 364 throws SyncSourceException { 365 366 SyncItem[] items = null; 367 368 String [] ids = null ; 369 370 ids = this.getUpdateItemIds(); 371 372 if (log.isLoggable(Level.FINEST)) { 373 log.severe("Exchange SyncSource " + 374 sourceURI + 375 " - getting updated syncItems" ); 376 } 377 378 if(ids == null || !(ids.length > 0)) { 379 return new SyncItem[0]; 380 } 381 382 items = filterSyncItems(principal, ids, SyncItemState.UPDATED); 383 384 return items; 385 } 386 387 388 public SyncItemKey[] getUpdatedSyncItemKeys(Principal principal, 389 Timestamp since) 390 throws SyncSourceException { 391 return null; 392 } 393 394 397 public void removeSyncItem(Principal principal, SyncItem syncItem) 398 throws SyncSourceException { 399 400 Contact contact = null ; 401 402 String username = null ; 403 String credentials = null ; 404 405 String id = null ; 406 String href = null ; 407 408 id = syncItem.getKey().getKeyAsString(); 409 410 username = ((Sync4jPrincipal) principal).getUsername() ; 411 credentials = ((Sync4jPrincipal) principal).getEncodedCredentials() ; 412 413 href = getHref(id); 414 415 try { 416 if (href != null) { 417 contact = new Contact(id) ; 418 contact.setHref(href) ; 419 this.cm.removeContact(contact , 420 username , 421 credentials , 422 exchangeFolder) ; 423 toChangedItems(contact.getId(), ITEM_REMOVE) ; 424 } else { 425 toChangedItems(contact.getId(), ITEM_REMOVE_ERROR) ; 426 } 427 } catch (DataAccessException e) { 428 toChangedItems(contact.getId(), ITEM_REMOVE_ERROR) ; 429 throw new SyncSourceException("Error reading items", e); 430 } 431 432 } 433 434 437 public void removeSyncItems(Principal principal, SyncItem[] syncItems) 438 throws SyncSourceException { 439 440 ArrayList syncItemsInError = new ArrayList (); 441 442 for (int i=0, l = syncItems.length; i < l; ++i) { 443 try { 444 removeSyncItem(principal, syncItems[i]); 445 } catch (SyncSourceException e) { 446 syncItemsInError.add(syncItems[i]); 447 } 448 } 450 if (syncItemsInError.size() > 0) { 451 throw new SyncSourceException("Error deleting the following items: " 452 + syncItemsInError.toString() 453 ); 454 } 455 456 if (log.isLoggable(Level.SEVERE)) { 457 log.severe("Exchange SyncSource " + 458 sourceURI + 459 " - removing syncItems" ); 460 } 461 462 } 463 464 467 public SyncItem[] getAllSyncItems(Principal principal) 468 throws SyncSourceException { 469 470 if (log.isLoggable(Level.SEVERE)) { 471 log.severe("Exchange SyncSource " + 472 sourceURI + 473 " - getting all syncItems" ); 474 } 475 476 return filterSyncItems(principal, SyncItemState.NEW); 477 } 478 479 482 public SyncItem getSyncItemFromTwin(Principal principal, SyncItem syncItem) 483 throws SyncSourceException { 484 485 String username = ((Sync4jPrincipal) principal).getUsername() ; 486 String credentials = ((Sync4jPrincipal) principal).getEncodedCredentials() ; 487 SyncItem syncTwin = null; 488 try { 489 this.cm = getContactManager(); 490 Contact contact = getContactFromSyncItem(syncItem); 491 Contact twin = cm.getContactTwin(contact , 492 username , 493 credentials , 494 exchangeFolder ); 495 496 if (twin != null) { 497 syncTwin = getSyncItem(twin); 498 } 499 500 } catch (DataAccessException ex) { 501 throw new SyncSourceException("Error getting twin", ex); 502 } 503 504 return syncTwin; 505 } 506 507 510 public SyncItem[] getSyncItemsFromTwins(Principal principal, 511 SyncItem[] syncItems) 512 throws SyncSourceException { 513 514 ArrayList items = new ArrayList (); 515 516 for (int i = 0, l = syncItems.length; i < l; ++i){ 517 items.add(getSyncItemFromTwin(principal, syncItems[i])); 518 } 519 520 return (SyncItem[])items.toArray(new SyncItem[items.size()]); 521 522 } 523 524 526 527 private Contact getContact(String id , 528 String content , 529 Timestamp t ) 530 throws SyncSourceException { 531 532 Contact c = new Contact(id); 533 534 c.setLastUpdate(t) ; 535 536 if (content != null && content.length() > 0) { 537 538 if (this.isEncode()) { 539 content = new String (Base64.decode(content)); 540 } 541 542 if (TYPE_VCARD.equals(getType())) { 543 vcard2Contact(content, c); 544 } else { 545 sifc2Contact(content, c); 546 } 547 } 548 549 return c; 550 551 } 552 553 554 567 private SyncItem[] filterSyncItems(Principal principal , 568 String [] ids , 569 char state) 570 throws SyncSourceException { 571 572 Contact[] contacts = null ; 573 574 String username = null ; 575 String credentials = null ; 576 577 username = ((Sync4jPrincipal) principal).getUsername() ; 578 credentials = ((Sync4jPrincipal) principal).getEncodedCredentials() ; 579 580 try { 581 582 cm = getContactManager(); 583 584 contacts = cm.getContacts (username , 585 credentials , 586 ids , 587 exchangeFolder) ; 588 } catch (DataAccessException e) { 589 throw new SyncSourceException("Error reading contacts: " + 590 e.getMessage(), e); 591 } 592 593 return getSyncItems(contacts, state); 594 595 } 596 597 598 610 private SyncItem[] filterSyncItems(Principal principal , 611 char state) 612 throws SyncSourceException { 613 614 Contact[] contacts = null ; 615 616 String username = null ; 617 String credentials = null ; 618 619 username = ((Sync4jPrincipal) principal).getUsername() ; 620 credentials = ((Sync4jPrincipal) principal).getEncodedCredentials() ; 621 622 try { 623 624 cm = getContactManager(); 625 626 contacts = cm.getAllContacts (username , 627 credentials , 628 exchangeFolder ) ; 629 } catch (DataAccessException e) { 630 throw new SyncSourceException("Error reading contacts: " + 631 e.getMessage(), e); 632 } 633 634 return getSyncItems(contacts, state); 635 636 } 637 638 646 private SyncItem[] getSyncItems(Contact[] contacts, 647 char state) 648 throws SyncSourceException { 649 650 SyncItem[] syncItems = null; 651 652 int l = contacts.length; 653 654 syncItems = new SyncItem [l]; 655 656 for (int i=0; i < l; i++) { 657 contacts [i].setStatus(state) ; 658 syncItems[i] = getSyncItem(contacts[i]) ; 659 } 660 661 return syncItems; 662 663 } 664 665 672 private SyncItem getSyncItem(Contact contact) 673 throws SyncSourceException { 674 675 SyncItem syncItem = null; 676 String content = null; 677 678 syncItem = new SyncItemImpl(this , 679 contact.getId() , 680 contact.getStatus() ); 681 682 if (TYPE_VCARD.equals(getType())) { 683 content = contact2vcard(contact); 684 } else { 685 content = contact2sifc(contact); 686 } 687 688 if (isEncode()) { 689 syncItem.setProperty( 690 new SyncProperty(SyncItem.PROPERTY_BINARY_CONTENT, 691 Base64.encode((content).getBytes()) 692 )); 693 694 syncItem.setProperty( 695 new SyncProperty(SyncItem.PROPERTY_FORMAT,"b64") 696 ); 697 698 } else { 699 syncItem.setProperty( 700 new SyncProperty(SyncItem.PROPERTY_BINARY_CONTENT, 701 (content).getBytes()) 702 ); 703 } 704 705 return syncItem; 706 707 } 708 709 718 private String contact2vcard(Contact c) 719 throws SyncSourceException { 720 try { 721 return new ContactToVcard(deviceTimeZone, deviceCharset).convert(c); 722 } catch (ConverterException e) { 723 throw new SyncSourceException( "Conversion error for item " 724 + c.getId() 725 + ": " 726 + e.getMessage() 727 , e 728 ); 729 } 730 } 731 732 741 private String contact2sifc(Contact c) 742 throws SyncSourceException { 743 try { 744 return new ContactToXML(deviceTimeZone, deviceCharset).convert(c); 745 } catch (ConverterException e) { 746 throw new SyncSourceException( "Convertion error for item " 747 + c.getId() 748 + ": " 749 + e.getMessage() 750 , e 751 ); 752 } 753 } 754 755 764 private void vcard2Contact (String content, Contact c) 765 throws SyncSourceException { 766 767 if ((content == null) || (content.length()==0)) { 771 return; 772 } 773 774 ByteArrayInputStream is = null ; 775 VcardParser parser = null ; 776 777 sync4j.foundation.pdi.contact.Contact contact = null ; 778 779 try { 780 781 786 content = content.replaceAll("=\r\n","\r\n "); 787 788 is = new ByteArrayInputStream (content.getBytes()); 789 790 792 parser = new VcardParser(is, deviceTimeZoneDescr, deviceCharset); 793 794 parser.setLogger(log); 795 796 contact = (sync4j.foundation.pdi.contact.Contact)parser.vCard(); 797 798 c.setUid(contact.getUid()); 802 c.setTimezone(contact.getTimezone()); 803 c.setNotes(contact.getNotes()); 804 c.setRevision(contact.getRevision()); 805 c.setName(contact.getName()); 806 c.setBusinessDetail(contact.getBusinessDetail()); 807 c.setPersonalDetail(contact.getPersonalDetail()); 808 c.setLanguages(contact.getLanguages()); 809 c.setCategories(contact.getCategories()); 810 c.setFolder(contact.getFolder()); 811 c.setSubject(contact.getSubject()); 812 c.setMileage(contact.getMileage()); 813 814 c.setSensitivity(contact.getSensitivity()); 815 c.setImportance(contact.getImportance()); 816 817 } catch (Exception e) { 818 e.printStackTrace(); 819 throw new SyncSourceException( "Convertion error for item " 820 + c.getId() 821 + ": " 822 + e.getMessage() 823 , e 824 ); 825 } finally { 826 if (is != null) try { is.close(); } catch (Exception e) {} 827 } 828 } 829 830 839 private void sifc2Contact (String content, Contact c) 840 throws SyncSourceException { 841 if ((content == null) || (content.length()==0)) { 845 return; 846 } 847 848 849 ByteArrayInputStream is = null ; 850 XMLContactParser parser = null ; 851 852 sync4j.foundation.pdi.contact.Contact contact = null ; 853 854 try { 855 is = new ByteArrayInputStream (content.getBytes()); 856 857 859 parser = new XMLContactParser(is); 860 861 contact = (sync4j.foundation.pdi.contact.Contact)parser.parse(); 862 863 c.setUid(contact.getUid()); 867 c.setTimezone(contact.getTimezone()); 868 c.setNotes(contact.getNotes()); 869 c.setRevision(contact.getRevision()); 870 c.setName(contact.getName()); 871 c.setBusinessDetail(contact.getBusinessDetail()); 872 c.setPersonalDetail(contact.getPersonalDetail()); 873 c.setLanguages(contact.getLanguages()); 874 c.setCategories(contact.getCategories()); 875 c.setFolder(contact.getFolder()); 876 c.setSubject(contact.getSubject()); 877 c.setMileage(contact.getMileage()); 878 c.setSensitivity(contact.getSensitivity()); 879 c.setImportance(contact.getImportance()); 880 881 } catch (Exception e) { 882 throw new SyncSourceException( "Parsing error for item " 883 + c.getId() 884 + ": " 885 + e.getMessage() 886 , e 887 ); 888 } finally { 889 if (is != null) try { is.close(); } catch (Exception e) {} 890 } 891 } 892 893 900 private ContactManager getContactManager() 901 throws DataAccessException { 902 903 if (this.cm == null) { 904 this.cm = new ContactManager(this.getHost() , 905 this.getPort()); 906 } 907 908 return this.cm; 909 910 } 911 912 918 private Contact getContactFromSyncItem(SyncItem syncItem) 919 throws SyncSourceException { 920 921 Contact contact = null; 922 String itemKey = syncItem.getKey().getKeyAsString(); 923 924 byte[] itemContent = 925 (byte[])syncItem.getPropertyValue( 926 SyncItem.PROPERTY_BINARY_CONTENT); 927 928 if (itemContent == null) { 929 itemContent = new byte[0]; 930 } 931 932 String content = new String (itemContent); 933 934 Timestamp t = 935 (Timestamp ) syncItem.getPropertyValue(SyncItem.PROPERTY_TIMESTAMP); 936 937 contact = getContact(itemKey, content, t); 938 939 return contact; 940 } 941 942 } 943 | Popular Tags |