2 * vCardObjectStore.java
4 * Created on December 13, 2006, 10:44 PM
6 * To change this template, choose Tools | Template Manager
7 * and open the template in the editor.
10 package net
.bionicmessage
.objects
;
13 import java
.io
.FileInputStream
;
14 import java
.io
.IOException
;
15 import java
.util
.ArrayList
;
16 import java
.util
.Hashtable
;
17 import java
.util
.Properties
;
18 import java
.util
.logging
.FileHandler
;
19 import java
.util
.logging
.Level
;
20 import java
.util
.logging
.Logger
;
22 import net
.bionicmessage
.groupdav
.GroupDAVObject
;
23 import net
.bionicmessage
.groupdav
.groupDAV
;
24 import net
.bionicmessage
.utils
.HTMLFormatter
;
26 import com
.funambol
.foundation
.pdi
.contact
.*;
27 import com
.funambol
.foundation
.pdi
.parser
.VcardParser
;
28 import java
.io
.StringWriter
;
29 import java
.io
.ByteArrayInputStream
;
30 import java
.io
.PrintWriter
;
31 import java
.util
.List
;
36 public class vCardObjectStore
{
37 groupDAV client
= null;
38 public static int OPTION_SSL
= 1; /* Are we using SSL? */
39 public static int OPTION_I_AM_AN_EXPERT
= 128; /* Allows the user to do dangerous things,
40 * such as changing the URL the store points to
42 public static int OPTION_PURGE
= 64; /* Purge the store contents, i.e for Funambol
44 public static int OPTION_TODO
= 32;
45 public static int OPTION_NEWHANDLER
= 16;
46 /** Retrieve password from store config file */
47 public static int OPTION_STOREDPASS
= 8;
49 boolean sslmode
= false;
50 boolean expertmode
= false;
51 boolean purgemode
= false;
52 boolean todomode
= false;
53 boolean newhandler
= false;
54 ObjectTracking obtrack
= null;
55 String obtrackdir
= "";
56 Properties props
= null;
58 /* Queues for reports */
59 ArrayList addedToStore
= new ArrayList();
60 ArrayList updatedInStore
= new ArrayList();
61 ArrayList deletedFromStore
= new ArrayList();
62 ArrayList untouched
= new ArrayList();
63 ArrayList addedToServer
= new ArrayList();
64 ArrayList updatedOnServer
= new ArrayList();
65 ArrayList deletedFromServer
= new ArrayList();
67 Hashtable objCache
= new Hashtable();
69 Logger log
= Logger
.getLogger("groupdav.vcardobjectstore");
70 FileHandler fh
= null;
71 /** Creates a new instance of vCardObjectStore */
72 public vCardObjectStore(String storedir
, int options
) {
73 int ssltest
= options
& OPTION_SSL
;
74 if (ssltest
== OPTION_SSL
) {
77 int experttest
= options
& OPTION_I_AM_AN_EXPERT
;
78 if (experttest
== OPTION_I_AM_AN_EXPERT
) {
81 int purgetest
= options
& OPTION_PURGE
;
82 if (purgetest
== OPTION_PURGE
) {
85 int todotest
= options
& OPTION_TODO
;
86 if (todotest
== OPTION_TODO
) {
89 int newtest
= options
& OPTION_NEWHANDLER
;
90 if (newtest
== OPTION_NEWHANDLER
) {
93 obtrackdir
= storedir
+File
.separatorChar
+"obtrack"+File
.separatorChar
;
95 File obtrackdirf
= new File(obtrackdir
);
96 String
[] files
= obtrackdirf
.list();
97 if (obtrackdirf
.exists() && files
.length
> 0) {
98 for (int i
= 0; i
< files
.length
; i
++) {
99 String string
= files
[i
];
100 File toDelete
= new File(obtrackdir
+File
.separatorChar
+string
);
101 boolean deleted
= toDelete
.delete();
102 System
.out
.println("Delete " + toDelete
.getAbsolutePath() + "..."+deleted
);
105 obtrackdirf
.delete();
107 obtrack
= new ObjectTracking(obtrackdir
);
108 props
= new Properties();
109 propfile
= new File(storedir
+File
.separatorChar
+"vcardstoreprops");
110 if (propfile
.exists()) {
112 FileInputStream propstream
= new FileInputStream(propfile
);
113 props
.load(propstream
);
114 } catch (IOException ex
) {
115 ex
.printStackTrace();
119 long curTime
= new java
.util
.Date().getTime();
120 HTMLFormatter hf
= new HTMLFormatter();
121 fh
= new FileHandler(storedir
+ File
.separatorChar
+ "storelog-"+curTime
+".html");
124 fh
.setLevel(Level
.ALL
);
125 log
.setLevel(Level
.ALL
);
126 } catch (SecurityException ex
) {
127 ex
.printStackTrace();
128 } catch (IOException ex
) {
129 ex
.printStackTrace();
133 public void setServer(String url
) {
134 if (props
.getProperty("groupdav.server") == null || expertmode
) {
135 props
.setProperty("groupdav.server",url
);
138 public void setStore(String storeurl
) {
139 if (!storeurl
.substring(storeurl
.length()).equals("/")) {
140 storeurl
= storeurl
+ "/";
142 if(props
.getProperty("groupdav.store") == null || expertmode
) {
143 props
.setProperty("groupdav.store",storeurl
);
146 public void connect_Base64(String b64cache
) throws Exception
{
147 client
= new groupDAV(props
.getProperty("groupdav.server"),b64cache
);
150 public void connect_plain(String user
, String pass
) throws Exception
{
151 client
= new groupDAV(props
.getProperty("groupdav.server"),user
,pass
);
154 public void connect_storedpass() throws Exception
{
155 client
= new groupDAV(props
.getProperty("groupdav.server"),
156 props
.getProperty("groupdav.user"),
157 props
.getProperty("groupdav.pass"));
162 private void afterConnect() throws Exception
{
163 client
.setLogger(log
);
165 public Hashtable
getStores() {
166 return client
.getURLLocs();
168 private String
addFromServerToStore(String url
) throws Exception
{
169 return addFromServerToStore(url
,addedToStore
);
171 /* Store->Server side */
172 private String
addFromServerToStore(String url
,List toAdd
) throws Exception
{
173 GroupDAVObject obj
= client
.getObject(url
);
174 Contact ct
= constructContactObject(obj
.getContent());
175 String uid
= ct
.getUid();
176 objCache
.put(uid
,ct
);
177 Name name
= ct
.getName();
178 String n
= name
.getDisplayName().getPropertyValueAsString();
179 if (name
.getDisplayName().getPropertyValueAsString() == null) {
182 obtrack
.createObject(uid
,url
,obj
.getEtag(),
183 n
.trim(),obj
.getContent(),0,0);
187 private void updateObjectFromServer(String uid
) throws Exception
{
188 GroupDAVObject obj
= client
.getObject(obtrack
.getObjectURL(uid
));
189 Contact ct
= constructContactObject(obj
.getContent());
190 Name name
= ct
.getName();
191 objCache
.put(uid
,ct
);
192 obtrack
.updateEtag(uid
,obj
.getEtag());
193 obtrack
.updateObject(uid
,obj
.getContent());
194 obtrack
.updateName(uid
,name
.getDisplayName().getPropertyValueAsString().trim());
195 updatedInStore
.add(uid
);
197 private void deleteFromStore(String uid
) throws Exception
{
198 obtrack
.deleteObject(uid
);
199 deletedFromStore
.add(uid
);
201 /* -> End store/server side */
202 /* Client->Store->Server side */
203 /** Adds an object to the server.
204 * @param uid The UID of the object to add
205 * @param name Name of the object to be added
206 * @param contents The ical2 data of the object
207 * @param dtstart The DTSTART of the object in Unix time
208 * @param dtend The DTEND of the object in Unix time
209 * @return -1 if error, 0 if added, 1 if replaced,2 if merged.
211 public String
addObject(String uid
,
213 String contents
) throws Exception
{
214 if (contents
.indexOf("\nUID:") == -1) {
215 int endLoc
= contents
.indexOf("END:VCARD");
216 StringBuffer sb
= new StringBuffer();
217 sb
.append(contents
.substring(0, endLoc
));
221 sb
.append(contents
.substring(endLoc
));
222 contents
= sb
.toString();
225 /* Post to the server first so we don't have objects in the store
226 * which the server does not want */
227 GroupDAVObject gbo
= client
.postObject(props
.getProperty("groupdav.store"),uid
,contents
);
228 addFromServerToStore(gbo
.getLocation());
232 * Replace a pre-existing object in the store with a new one.
233 * @param uid The UID of the object to replace
234 * @param name If the object's name has changed, the store will be updated with the new name
236 * If name is null, the name will not be modified.
237 * @param contents Contents of the object replacing the object
238 * @param dtstart The start time of the object. If dtstart and dtend are 0, dates will not be changed
239 * @param dtend The end time of the object. If dtstart and dtend are 0, dates will not be changed
241 public int replaceObject(String uid
,
243 String contents
) throws Exception
{
244 String oldetag
= obtrack
.getObjectEtag(uid
);
245 GroupDAVObject gbo
= client
.modifyObject(obtrack
.getObjectURL(uid
),contents
,oldetag
);
246 updatedOnServer
.add(uid
);
247 obtrack
.updateObject(uid
,contents
);
248 obtrack
.updateEtag(uid
,gbo
.getEtag());
250 obtrack
.updateName(uid
,name
);
254 public int mergeObject(String newuid
, String contents1
, String contents2
)
258 public void deleteObject(String uid
) throws Exception
{
259 String oldetag
= obtrack
.getObjectEtag(uid
);
260 GroupDAVObject gbo
= client
.deleteObject(obtrack
.getObjectURL(uid
),oldetag
);
261 obtrack
.deleteObject(uid
);
262 deletedFromServer
.add(uid
);
264 public Contact
getObjectFromStore(String uid
) throws Exception
{
265 if (objCache
.get(uid
) != null) {
266 log
.fine("Object " + uid
+ "has been retrieved from store");
267 Contact ct
= (Contact
)objCache
.get(uid
);
270 if (!obtrack
.doesObjectExist(uid
)) {
271 throw new Exception("We do not have an object for " + uid
);
273 log
.fine("We are constructing an object for " + uid
);
274 return constructContactObject(obtrack
.getObjectContents(uid
));
281 * @throws java.lang.Exception
282 * @return The UID of the object
284 private Contact
constructContactObject(String content
) throws Exception
{
285 // Fix junk from KAddressBook
286 String ct
= content
.replace("::", ":");
287 ByteArrayInputStream bis
= new ByteArrayInputStream(ct
.getBytes());
288 VcardParser vcp
= new VcardParser(bis
,null,null);
291 public void startSync() throws Exception
{
292 log
.info("Sync started....");
294 List objects
= client
.listObjects(props
.getProperty("groupdav.store"));
295 Map etags
= client
.getEtags();
296 for (int i
= 0; i
< objects
.size(); i
++) {
297 String url
= (String
)objects
.get(i
);
298 // Do we have the object?
299 boolean haveurl
= obtrack
.doesURLExist(url
);
301 String stuid
= obtrack
.findObjectByURL(url
);
302 String stetag
= obtrack
.getObjectEtag(stuid
);
303 String getag
= (String
)etags
.get(url
);
304 if (!stetag
.equals(getag
)) {
305 updateObjectFromServer(stuid
);
307 untouched
.add(stuid
);
309 log
.fine("We have the URL: " + url
);
312 addFromServerToStore(url
);
313 } catch (Exception ex
) {
314 log
.throwing(this.getClass().getName(),"startSync",ex
);
316 log
.fine("We added the URL: " + url
);
320 ArrayList URLarray
= obtrack
.getURLList();
321 for (int i
= 0; i
< URLarray
.size(); i
++) {
322 String url
= (String
)URLarray
.get(i
);
323 if (null == etags
.get(url
)) {
324 log
.fine("Deleted on server: " + url
);
325 deleteFromStore(obtrack
.findObjectByURL(url
));
330 public ArrayList
getUnModifiedUIDS() {
333 public ArrayList
getAddedToServerUIDS() {
334 return addedToServer
;
336 public ArrayList
getAddedToStoreUIDS() {
339 public ArrayList
getDeletedFromServerUIDS() {
340 return deletedFromServer
;
342 public ArrayList
getDeletedFromStoreUIDS() {
343 return deletedFromStore
;
345 public ArrayList
getUpdatedInStoreUIDS() {
346 return updatedInStore
;
348 public ArrayList
getUpdatedOnServerUIDS() {
349 return updatedOnServer
;
351 public void printDebugReport() throws Exception
{
352 StringWriter sw
= new StringWriter();
353 PrintWriter lw
= new PrintWriter(sw
);
354 ArrayList uids
= obtrack
.getUIDList();
355 for (int i
= 0; i
< uids
.size(); i
++) {
356 String uid
= (String
)uids
.get(i
);
357 String url
= obtrack
.getObjectURL(uid
);
359 throw new Exception("URL for "+uid
+ " is null");
361 String etag
= obtrack
.getObjectEtag(uid
);
362 String name
= obtrack
.getObjectName(uid
);
363 String data
= obtrack
.getObjectContents(uid
);
367 dtstart
= obtrack
.getDtStartForUid(uid
);
368 dtend
= obtrack
.getDtEndFromUid(uid
);
370 lw
.println("----------");
371 lw
.println("UID:"+uid
);
372 lw
.println("URL:"+url
);
373 lw
.println("ETAG:"+etag
);
374 lw
.println("NAME:"+name
);
376 lw
.println("DTSTART:"+dtstart
);
377 lw
.println("DTEND:"+dtend
);
379 lw
.println("DATA FOLLOWS:");
381 lw
.println("----------");
383 lw
.println("Objects added to store: ");
384 for (int i
= 0; i
< addedToStore
.size(); i
++) {
385 String uid
= (String
)addedToStore
.get(i
);
386 lw
.println("A: "+uid
);
388 lw
.println("Objects updated from server: ");
389 for (int i
= 0; i
< updatedInStore
.size(); i
++) {
390 String uid
= (String
)updatedInStore
.get(i
);
391 lw
.println("U: "+uid
);
393 lw
.println("Objects deleted from store: ");
394 for (int i
= 0; i
< deletedFromStore
.size(); i
++) {
395 String uid
= (String
)deletedFromStore
.get(i
);
396 lw
.println("D: "+uid
);
398 lw
.println("Objects added to the server: ");
399 for (int i
= 0; i
< addedToServer
.size(); i
++) {
400 String uid
= (String
)addedToServer
.get(i
);
401 lw
.println("SA: "+uid
);
403 lw
.println("Objects merged to server: ");
404 for (int i
= 0; i
< updatedOnServer
.size(); i
++) {
405 String uid
= (String
)updatedOnServer
.get(i
);
406 lw
.println("SM: "+uid
);
408 lw
.println("Objects deleted from server: ");
409 for (int i
= 0; i
< deletedFromServer
.size(); i
++) {
410 String uid
= (String
)deletedFromServer
.get(i
);
411 lw
.println("SD: "+uid
);
415 log
.info(sw
.toString());
417 public void close() throws Exception
{
421 public String
searchUids(String name
) throws Exception
{
422 // Find potential names
423 ArrayList
<String
> potentialNames
= obtrack
.findObjectsByName(name
);
424 for (int i
= 0; i
< potentialNames
.size(); i
++) {
425 String id
= potentialNames
.get(i
);
426 // Do we have a match?
427 boolean match
= obtrack
.doesUidMatchTimes(id
, 0,0);
433 public static void main(String args
[]) {
434 String storeloc
= "";
435 if (args
.length
> 0 && args
[0] != null) {
438 storeloc
= System
.getProperty("user.home") + System
.getProperty("file.separator") + "vcardobjectstoretest";
440 vCardObjectStore vco
= new vCardObjectStore(storeloc
,
441 vCardObjectStore
.OPTION_STOREDPASS
+ ICalendarObjectStore
.OPTION_TODO
);
444 vco
.connect_storedpass();
446 vco
.printDebugReport();
447 } catch (Exception ex
) {
448 ex
.printStackTrace();