KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > sync4j > exchange > engine > source > ExchangeSyncSource


1 /**
2  * Copyright (C) 2003-2005 Funambol
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18
19 package sync4j.exchange.engine.source;
20
21 import java.io.Serializable JavaDoc;
22 import java.security.Principal JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Date JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.logging.Logger JavaDoc;
28 import java.util.logging.Level JavaDoc;
29 import java.util.TimeZone JavaDoc;
30
31 import sync4j.framework.core.AlertCode;
32 import sync4j.framework.logging.Sync4jLogger;
33 import sync4j.framework.engine.SyncItemImpl;
34 import sync4j.framework.engine.SyncItem;
35 import sync4j.framework.engine.SyncItemKey;
36 import sync4j.framework.engine.SyncProperty;
37 import sync4j.framework.engine.SyncItemState;
38 import sync4j.framework.engine.source.SyncSource;
39 import sync4j.framework.engine.source.SyncSourceException;
40 import sync4j.framework.engine.source.AbstractSyncSource;
41 import sync4j.framework.server.Sync4jDevice;
42 import sync4j.framework.server.store.PersistentStore;
43 import sync4j.framework.server.store.PersistentStoreException;
44
45 import sync4j.exchange.items.common.model.Item;
46 import sync4j.exchange.items.common.manager.ItemManager;
47 import sync4j.exchange.DataAccessException;
48
49 import sync4j.framework.security.Sync4jPrincipal;
50
51 import sync4j.server.config.Configuration;
52
53 /**
54  *
55  * This class implements common methods of
56  * <pre>
57  * ExchangeCalendarSyncSource
58  * ExchangeContactSyncSource
59  * ExchangeNoteSyncSource
60  * ExchangeTaskSyncSource
61  * </pre>
62  *
63  * @author Fabio Maggi @ Funambol
64  *
65  * version $Id: ExchangeSyncSource.java,v 1.14 2005/06/22 12:21:17 nichele Exp $
66  */

67 public abstract class ExchangeSyncSource
68 extends AbstractSyncSource
69 implements SyncSource, Serializable JavaDoc {
70
71     // --------------------------------------------------------------- Constants
72

73     protected static final String JavaDoc ITEM_ADD = "A" ;
74     protected static final String JavaDoc ITEM_REMOVE = "D" ;
75     protected static final String JavaDoc ITEM_UPDATE = "U" ;
76
77     protected static final String JavaDoc ITEM_ADD_ERROR = "AE" ;
78     protected static final String JavaDoc ITEM_REMOVE_ERROR = "DE" ;
79     protected static final String JavaDoc ITEM_UPDATE_ERROR = "UE" ;
80
81     protected static final String JavaDoc TYPE_VCARD = "text/x-vcard" ;
82     protected static final String JavaDoc TYPE_ICAL = "text/x-vcalendar" ;
83
84     // -------------------------------------------------------------- Private data
85

86     private Item[] localItems = null ;
87     private Item[] exchangeItems = null ;
88
89     private String JavaDoc[] newItemIds = null ;
90     private String JavaDoc[] deleteItemIds = null ;
91     private String JavaDoc[] updateItemIds = null ;
92
93     private HashMap JavaDoc changedItems = null ;
94
95     protected String JavaDoc deviceTimeZoneDescr = null ;
96     protected TimeZone JavaDoc deviceTimeZone = null ;
97
98     protected String JavaDoc deviceCharset = null ;
99
100     protected Logger JavaDoc log = null ;
101
102     // -------------------------------------------------------------- Properties
103

104      /**
105       * Property exchange folder
106       */

107      protected String JavaDoc exchangeFolder;
108
109      /** Getter for property exchange folder.
110       * @return Value of property exchange folder.
111       *
112       */

113      public String JavaDoc getExchangeFolder() {
114          return exchangeFolder;
115      }
116
117      /** Setter for property exchange folder.
118       * @param exchangeFolder New value of property exchange folder.
119       *
120       */

121      public void setExchangeFolder(String JavaDoc exchangeFolder) {
122          this.exchangeFolder = exchangeFolder;
123      }
124
125     /**
126      * Property ExchangeServer host
127      */

128     private String JavaDoc host;
129
130     /** Getter for property exchangeServerHost.
131      * @return Value of property exchangeServerHost.
132      *
133      */

134     public String JavaDoc getHost() {
135         return host;
136     }
137
138     /** Setter for property exchangeServerHost.
139      * @param host New value of property exchangeServerHost.
140      *
141      */

142     public void setHost(String JavaDoc host) {
143         this.host = host;
144     }
145
146     /**
147      * Property ExchangeServer port
148      */

149     private int port = 80;
150
151     /** Getter for property exchangeServerPort.
152      * @return Value of property exchangeServerPort.
153      *
154      */

155     public int getPort() {
156         return port;
157     }
158
159     /** Setter for property exchangeServerPort.
160      * @param port New value of property exchangeServerPort.
161      *
162      */

163     public void setPort(int port) {
164         this.port = port;
165     }
166
167     /**
168      * Should the content be encoded?
169      */

170     private boolean encode = false;
171
172     /** Getter for property encode.
173      * @return Value of property encode.
174      *
175      */

176     public boolean isEncode() {
177         return encode;
178     }
179
180     /** Setter for property encode.
181      * @param encode New value of property encode.
182      *
183      */

184     public void setEncode(boolean encode) {
185         this.encode = encode;
186     }
187
188     /**
189      * Property schedule
190      */

191     private String JavaDoc schedule;
192
193     /** Getter for property schedule.
194      * @return Value of property schedule.
195      *
196      */

197     public String JavaDoc getSchedule() {
198         return schedule;
199     }
200
201     /** Setter for property schedule.
202      * @param schedule New value of property schedule.
203      *
204      */

205     public void setSchedule(String JavaDoc schedule) {
206         this.schedule = schedule;
207     }
208
209     /**
210      * Property scheduleEnabled
211      */

212     private boolean scheduleEnabled;
213
214     /** Getter for property scheduleEnabled.
215      * @return Value of property scheduleEnabled.
216      *
217      */

218     public boolean isSchedulEnablede() {
219         return scheduleEnabled;
220     }
221
222     /** Setter for property schedule.
223      * @param scheduleEnabled New value of property schedule.
224      *
225      */

226     public void setScheduleEnabled(boolean scheduleEnabled) {
227         this.scheduleEnabled = scheduleEnabled;
228     }
229
230     /** Getter for property newItemIds.
231      * @return Value of property newItemIds.
232      *
233      */

234     public String JavaDoc[] getNewItemIds() {
235         return this.newItemIds;
236     }
237
238     /** Getter for property updateItemIds.
239      * @return Value of property updateItemIds.
240      *
241      */

242     public String JavaDoc[] getUpdateItemIds() {
243         return this.updateItemIds;
244     }
245
246     /** Getter for property deleteItemIds.
247      * @return Value of property deleteItemIds.
248      *
249      */

250     public String JavaDoc[] getDeleteItemIds() {
251         return this.deleteItemIds;
252     }
253
254     // ---------------------------------------------------------- Public Methods
255

256     /**
257      * @see SyncSource
258      */

259     public void beginSync(Principal JavaDoc principal, int syncMode)
260     throws SyncSourceException {
261
262         String JavaDoc principalId = null ;
263         String JavaDoc username = null ;
264         String JavaDoc credentials = null ;
265
266         ItemManager im = null ;
267
268         log = Sync4jLogger.getLogger("source");
269
270         changedItems = new HashMap JavaDoc();
271
272         principalId = ((Sync4jPrincipal) principal).getId() ;
273         username = ((Sync4jPrincipal) principal).getUsername() ;
274         credentials = ((Sync4jPrincipal) principal).getEncodedCredentials() ;
275
276         try {
277             String JavaDoc deviceId = ((Sync4jPrincipal)principal).getDeviceId();
278             Sync4jDevice device = getDevice (deviceId) ;
279             String JavaDoc timezone = device.getTimeZone ( ) ;
280             if (device.getConvertDate ()) {
281                 if (timezone != null && timezone.length() > 0) {
282                     deviceTimeZoneDescr = timezone;
283                     deviceTimeZone = TimeZone.getTimeZone(deviceTimeZoneDescr);
284                 }
285             }
286
287             deviceCharset = device.getCharset();
288         } catch (Exception JavaDoc e) {
289             throw new SyncSourceException(e.getMessage());
290         }
291
292
293         try {
294
295             im = new ItemManager (this.host ,
296                                    this.port);
297
298             if ((syncMode != AlertCode.SLOW) &&
299                 (syncMode != AlertCode.REFRESH_FROM_SERVER)) {
300
301                 this.exchangeItems = im.getExchangeItems (username ,
302                                                             credentials ,
303                                                             this.exchangeFolder ) ;
304
305                 this.localItems = im.getLocalItems (this.sourceURI,
306                                                     principalId) ;
307
308                 this.newItemIds = findNewItemIds () ;
309                 this.updateItemIds = findUpdateItemIds () ;
310                 this.deleteItemIds = findDeleteItemIds () ;
311
312             }
313
314             if (log.isLoggable(Level.SEVERE)) {
315                 log.severe("Exchange SyncSource " + sourceURI + " - begineSync");
316             }
317
318         } catch (DataAccessException e) {
319             throw new SyncSourceException("Error accessing items: " +
320                                            e.getMessage(), e);
321         }
322
323
324     }
325
326     /**
327      * @see SyncSource
328      */

329     public void endSync(Principal JavaDoc principal)
330     throws SyncSourceException {
331
332         ItemManager im = null ;
333
334         Item [] exchItems = null ;
335         String JavaDoc id = null ;
336
337         String JavaDoc principalId = null ;
338         String JavaDoc username = null ;
339         String JavaDoc credentials = null ;
340
341         principalId = ((Sync4jPrincipal) principal).getId() ;
342         username = ((Sync4jPrincipal) principal).getUsername() ;
343         credentials = ((Sync4jPrincipal) principal).getEncodedCredentials() ;
344
345         try {
346
347             im = new ItemManager (this.host ,
348                                    this.port );
349
350             //
351
// to do: optimize the performance,
352
// by read only update / add items
353
// to setting lastModified
354
// with addItems[exist], deleteItems[exist],
355
// updateItems[implements] array
356
//
357
exchItems = im.getExchangeItems (username ,
358                                                credentials ,
359                                                this.exchangeFolder ) ;
360
361             im.updateLocalItems (exchItems ,
362                                  this.sourceURI ,
363                                  principalId);
364
365             if (log.isLoggable(Level.SEVERE)) {
366                 log.severe("Exchange SyncSource " + sourceURI + " - endSync");
367                 log.severe("Items changed: " + changedItems.size());
368
369                 Iterator JavaDoc i = changedItems.keySet().iterator();
370
371                 while(i.hasNext()) {
372
373                     id = (String JavaDoc) i.next();
374
375                     log.severe("Item id: " + id +
376                                " Status: " + changedItems.get(id));
377                 }
378
379             }
380
381         } catch (DataAccessException e) {
382             throw new SyncSourceException("Error updating items:" +
383                                           e.getMessage(), e);
384         }
385
386     }
387
388     // ---------------------------------------------------------- Private Methods
389

390     /**
391      * Create new items id array
392      *
393      * @return new items id array
394      */

395     private String JavaDoc[] findNewItemIds () {
396
397         ArrayList JavaDoc newRows = null ;
398         String JavaDoc[] ids = null ;
399         Item exchangeItem = null ;
400
401         int count = 0 ;
402
403         newRows = new ArrayList JavaDoc();
404
405         for (int i = 0, l = this.exchangeItems.length; i < l; i++) {
406
407             exchangeItem = this.exchangeItems[i];
408
409             if (!this.isItemInArray(this.localItems, exchangeItem)) {
410                 newRows.add(exchangeItem.getId());
411                 count++;
412             }
413
414         }
415
416         return (String JavaDoc[])newRows.toArray(new String JavaDoc[count]) ;
417
418     }
419
420     /**
421      * Create deleted items id array
422      *
423      * @return deleted items id array
424      */

425     private String JavaDoc[] findDeleteItemIds () {
426
427         ArrayList JavaDoc deleteRows = null ;
428         String JavaDoc[] ids = null ;
429         Item localItem = null ;
430
431         int count = 0;
432
433         deleteRows = new ArrayList JavaDoc();
434
435         for (int i=0, l = this.localItems.length; i < l; i++) {
436
437            localItem = localItems[i];
438
439            if (!this.isItemInArray(this.exchangeItems, localItem)) {
440                deleteRows.add(localItem.getId());
441                count++;
442            }
443
444         }
445
446         return (String JavaDoc[])deleteRows.toArray(new String JavaDoc[count]) ;
447
448     }
449
450     /**
451      * Create updated items id array
452      *
453      * @return updated items id array
454      */

455     private String JavaDoc[] findUpdateItemIds () {
456
457         ArrayList JavaDoc updateRows = null ;
458         String JavaDoc[] ids = null ;
459
460         Item exchangeItem = null ;
461         Item localItem = null ;
462
463         Date JavaDoc excItemLastModified = null ;
464         Date JavaDoc localItemLastModified = null ;
465
466         String JavaDoc excItemLastModifiedStr = null;
467         String JavaDoc localItemLastModifiedStr = null ;
468
469         int count = 0 ;
470
471         updateRows = new ArrayList JavaDoc();
472
473         for (int i = 0, l = this.exchangeItems.length; i < l; i++) {
474
475             exchangeItem = this.exchangeItems[i] ;
476             localItem = this.getItemById(this.localItems,
477                                               exchangeItem.getId()) ;
478
479             if (localItem != null) {
480
481                  excItemLastModified = exchangeItem.getLastModified () ;
482                  localItemLastModified = localItem.getLastModified () ;
483
484                  //
485
// because java.util.Date no save millisecond
486
// string rappresention of date is in HH:mm:ss
487
//
488
excItemLastModifiedStr = String.valueOf(excItemLastModified) ;
489                  localItemLastModifiedStr = String.valueOf(localItemLastModified) ;
490
491                  if (!excItemLastModifiedStr.equals(localItemLastModifiedStr)) {
492
493                     updateRows.add(exchangeItem.getId());
494                     count++;
495
496                  }
497
498              }
499
500         }
501
502         return (String JavaDoc[])updateRows.toArray(new String JavaDoc[count]) ;
503
504     }
505
506     /**
507      * Return href (webdav resource name) of item
508      *
509      * @param id id of item to find
510      * @return href (webdav resource name) of find item,
511      * or <p>null</p> if item not found
512      */

513     protected String JavaDoc getHref(String JavaDoc id) {
514
515         Item exchangeItem = null ;
516         String JavaDoc href = null ;
517
518         //
519
// in case of slow sync no exchange item load
520
//
521
if (exchangeItems != null) {
522
523             for (int i=0, l = exchangeItems.length; i < l; i++) {
524
525                 exchangeItem = exchangeItems[i];
526
527                 if (exchangeItem.getId().equals(id)) {
528
529                     href = exchangeItem.getHref();
530                     break;
531                 }
532
533              }
534
535          }
536
537          return href;
538
539     }
540
541
542     /**
543      * Add item to mapp operations status array
544      *
545      * @param id id of item to add
546      * @param status status of item to add
547      *
548      */

549     protected void toChangedItems (String JavaDoc id, String JavaDoc status) {
550         changedItems.put(id, status);
551     }
552
553     // ---------------------------------------------------------- Private Methods
554

555     /**
556      * get Item by id
557      *
558      * @param items array
559      * @param id
560      * @return <p>item</p> if find
561      * <p>null</p> if not find
562      **/

563     private Item getItemById(Item[] items,
564                              String JavaDoc id) {
565
566         Item item = null;
567         Item sequenceItem = null;
568
569         for (int i = 0, l = items.length; i < l; i++) {
570
571             sequenceItem = items[i];
572
573             if (sequenceItem.getId().equals(id)) {
574                 item = sequenceItem;
575                 break;
576             }
577
578         }
579
580         return item;
581
582     }
583
584     /**
585      *
586      * check if item id is included
587      * in ids from array of items
588      *
589      * @param items items array
590      * @param id id to find
591      * @return <p>true</p> if is included
592      * <p>false</p> if is not included
593      **/

594     private boolean isIdInArray(Item[] items,
595                                 String JavaDoc id) {
596
597         boolean isFind = false;
598
599         for (int i = 0, l = items.length; i < l; i++) {
600
601             if (items[i].getId().equals(id)) {
602                 isFind = true;
603                 break;
604             }
605
606         }
607
608         return isFind;
609
610     }
611
612     /**
613      *
614      * check if item is included
615      * in array of items
616      *
617      * @param items items array
618      * @param item item to find
619      * @return <p>true</p> if is included
620      * <p>false</p> if is not included
621      **/

622     private boolean isItemInArray(Item[] items,
623                                   Item item) {
624
625         return isIdInArray(items, item.getId());
626
627     }
628
629
630     /**
631      * Return the device with the given deviceId
632      * @param deviceId String
633      * @return Sync4jDevice
634      * @throws PersistentStoreException
635      */

636     private Sync4jDevice getDevice(String JavaDoc deviceId) throws PersistentStoreException {
637         Sync4jDevice device = new Sync4jDevice(deviceId);
638         PersistentStore store = Configuration.getConfiguration().getStore();
639         store.read(device);
640         return device;
641     }
642
643
644 }
645
Popular Tags