KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > sync4j > server > store > EnginePersistentStore


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.server.store;
20
21 import java.util.ArrayList JavaDoc;
22
23 import java.sql.*;
24
25 import sync4j.server.engine.Sync4jSource;
26
27 import sync4j.framework.tools.DBTools;
28 import sync4j.framework.tools.Base64;
29 import sync4j.framework.engine.dm.DeviceDMState;
30 import sync4j.framework.server.store.*;
31 import sync4j.framework.server.Sync4jDevice;
32 import sync4j.framework.security.Sync4jPrincipal;
33
34 /**
35  * This is the store for information regarding the Sync4j engine such as users,
36  * principals, ecc. Currently it persistes the following classes:
37  *
38  * <ul>
39  * <li>sync4j.framework.security.Sync4jPrincipal</li>
40  * </ul>
41  *
42  *
43  * @author Stefano Fornari @ Funambol
44  *
45  * @version $Id: EnginePersistentStore.java,v 1.1 2005/05/16 17:32:57 nichele Exp $
46  *
47  */

48 public class EnginePersistentStore
49 extends BasePersistentStore
50 implements PersistentStore, java.io.Serializable JavaDoc {
51
52     // --------------------------------------------------------------- Constants
53

54     private static final String JavaDoc OPT_INSERT = "INSERT";
55
56     public static final byte SQL_INSERT_PRINCIPAL = 0;
57     public static final byte SQL_GET_PRINCIPAL = 1;
58     public static final byte SQL_SELECT_PRINCIPAL = 2;
59     public static final byte SQL_UPDATE_PRINCIPAL = 3;
60     public static final byte SQL_SELECT_ALL_PRINCIPALS = 4;
61     public static final byte SQL_INSERT_SOURCE = 5;
62     public static final byte SQL_GET_SOURCE = 6;
63     public static final byte SQL_UPDATE_SOURCE = 7;
64     public static final byte SQL_SELECT_ALL_SOURCES = 8;
65     public static final byte SQL_SELECT_ALL_DEVICES = 9;
66     public static final byte SQL_GET_DEVICE = 10;
67     public static final byte SQL_INSERT_DEVICE = 11;
68     public static final byte SQL_UPDATE_DEVICE = 12;
69     public static final byte SQL_DELETE_DEVICE = 13;
70     public static final byte SQL_DELETE_DEVICE_PRINCIPAL = 14;
71     public static final byte SQL_DELETE_PRINCIPAL = 15;
72     public static final byte SQL_DELETE_CLIENT_MAPPING = 16;
73     public static final byte SQL_DELETE_LAST_SYNC = 17;
74     public static final byte SQL_GET_COUNTER = 18;
75     public static final byte SQL_UPDATE_COUNTER = 19;
76     public static final byte SQL_DELETE_SOURCE = 20;
77     public static final byte SQL_INSERT_SYNCSOURCE = 21;
78     public static final byte SQL_UPDATE_SYNCSOURCE = 22;
79     public static final byte SQL_DELETE_SOURCE_CLIENT_MAPPING = 23;
80     public static final byte SQL_DELETE_SOURCE_LAST_SYNC = 24;
81     public static final byte SQL_COUNT_DEVICES = 25;
82     public static final byte SQL_COUNT_PRINCIPALS = 26;
83     public static final byte SQL_GET_DEVICE_DM_STATE = 27;
84     public static final byte SQL_UPDATE_DEVICE_DM_STATE = 28;
85     public static final byte SQL_INSERT_DEVICE_DM_STATE = 29;
86     public static final byte SQL_DELETE_DEVICE_DM_STATE = 30;
87     public static final byte SQL_SELECT_ALL_DM_STATE = 31;
88
89     public static final String JavaDoc NS_PRINCIPAL = "principal";
90     public static final String JavaDoc NS_DEVICE = "device" ;
91     public static final String JavaDoc NS_DM_STATE = "dmstate" ;
92
93     // -------------------------------------------------------------- Properties
94

95     private String JavaDoc[] sql = null;
96
97     public void setSql(String JavaDoc[] sql) {
98         this.sql = sql;
99     }
100
101     public String JavaDoc[] getSql() {
102         return this.sql;
103     }
104
105     // ------------------------------------------------------------ Private data
106
private static final String JavaDoc SEARCH_COUNT_DEVICES = "SCD";
107     private static final String JavaDoc SEARCH_COUNT_PRINCIPALS = "SCP";
108
109     // ------------------------------------------------------------ Constructors
110

111     // ---------------------------------------------------------- Public methods
112

113     public boolean delete(Object JavaDoc o)
114     throws PersistentStoreException {
115         if (o instanceof Sync4jDevice) {
116             deleteDevice((Sync4jDevice) o);
117             return true;
118         } else if (o instanceof Sync4jPrincipal) {
119             deletePrincipal((Sync4jPrincipal) o);
120             return true;
121         } else if (o instanceof Sync4jSource) {
122             deleteSource((Sync4jSource) o);
123             return true;
124         } else if (o instanceof DeviceDMState) {
125             deleteDeviceDMState((DeviceDMState) o);
126             return true;
127         }
128
129         return false;
130     }
131
132     public boolean store(String JavaDoc id, Object JavaDoc o, String JavaDoc operation) throws PersistentStoreException {
133         if (o instanceof Sync4jSource) {
134             if (operation.equals(OPT_INSERT)) {
135                 insertSyncSource(id, (Sync4jSource)o);
136             } else {
137                 updateSyncSource(id, (Sync4jSource)o);
138             }
139             return true;
140         }
141
142         return false;
143     }
144
145     public boolean store(Object JavaDoc o)
146     throws PersistentStoreException {
147         if (o instanceof Sync4jPrincipal) {
148             storePrincipal((Sync4jPrincipal)o);
149             return true;
150         } else if (o instanceof Sync4jSource) {
151             storeSource((Sync4jSource)o);
152             return true;
153         } else if (o instanceof Sync4jDevice) {
154             storeDevice((Sync4jDevice)o);
155             return true;
156         } else if (o instanceof DeviceDMState) {
157             storeDeviceDMState((DeviceDMState)o);
158             return true;
159         }
160
161         return false;
162     }
163
164     public boolean read(Object JavaDoc o)
165     throws PersistentStoreException {
166         if (o instanceof Sync4jPrincipal) {
167             readPrincipal((Sync4jPrincipal) o);
168             return true;
169         } else if (o instanceof Sync4jSource) {
170             readSource((Sync4jSource) o);
171             return true;
172         } else if (o instanceof Sync4jDevice) {
173             readDevice((Sync4jDevice) o);
174             return true;
175         } else if (o instanceof DeviceDMState) {
176             readDeviceDMState((DeviceDMState)o);
177             return true;
178         }
179
180         return false;
181     }
182
183     public Object JavaDoc[] read(Class JavaDoc objClass) throws PersistentStoreException {
184         if (objClass.equals(Sync4jSource.class)) {
185             return readAllSources();
186         }
187
188         return null;
189     }
190
191     /**
192      * Read all informations
193      * @param object whichever object Sync
194      * @param clause condition where for select
195      *
196      * @return Object[] array of object
197      */

198     public Object JavaDoc[] read(Object JavaDoc o, Clause clause) throws PersistentStoreException {
199         if (o instanceof Sync4jPrincipal) {
200             return readAllPrincipals(clause);
201         } else if (o instanceof Sync4jDevice) {
202             return readAllDevices(clause);
203         } else if (o instanceof String JavaDoc) {
204             if (o.equals(SEARCH_COUNT_DEVICES)) {
205                 return readCountDevices(clause);
206             } else if (o.equals(SEARCH_COUNT_PRINCIPALS)) {
207                 return readCountPrincipals(clause);
208             }
209         } else if (o instanceof Sync4jSource) {
210             return readSource((Sync4jSource)o, clause);
211         } else if (o instanceof DeviceDMState) {
212             return readDeviceDMState(clause);
213         }
214
215         return null;
216     }
217
218     // --------------------------------------------------------- Private methods
219

220
221     // -------------------------------------------------------------------------
222
// Sync4jPricipal
223
// -------------------------------------------------------------------------
224

225     private void storePrincipal(Sync4jPrincipal p)
226     throws PersistentStoreException {
227         Connection conn = null;
228         PreparedStatement stmt = null;
229         ResultSet rs = null;
230         int n = 0;
231
232         try {
233             conn = dataSource.getConnection();
234
235             if (p.getId() != null && !p.getId().equals("")) {
236
237                 stmt = conn.prepareStatement(sql[SQL_UPDATE_PRINCIPAL]);
238
239                 stmt.setString(1, p.getUsername());
240                 stmt.setString(2, p.getDeviceId());
241                 stmt.setString(3, p.getId() );
242
243                 n = stmt.executeUpdate();
244
245                 stmt.close();
246             } else {
247                 //check if the principal already exist: verify username-deviceid
248

249                 stmt = conn.prepareStatement(sql[SQL_SELECT_PRINCIPAL]);
250
251                 stmt.setString(1, p.getUsername());
252                 stmt.setString(2, p.getDeviceId());
253
254                 rs = stmt.executeQuery();
255
256                 if (rs.next() == false) {
257
258                     n = 0;
259
260                 } else {
261
262                     n = 1;
263
264                     p.setId (rs.getString(1));
265                     p.setUsername (rs.getString(2));
266                     p.setDeviceId (rs.getString(3));
267                     p.setEmail (rs.getString(4));
268                     p.setFirstName(rs.getString(5));
269                     p.setLastName (rs.getString(6));
270                 }
271
272                 stmt.close();
273                 rs.close();
274             }
275
276             if (n == 0) {
277                 //
278
// The first time!!!
279
//
280

281                 int principalId = this.readCounter(NS_PRINCIPAL);
282                 p.setId("" + principalId);
283
284                 stmt = conn.prepareStatement(sql[SQL_INSERT_PRINCIPAL]);
285
286                 stmt.setString(1, p.getId() );
287                 stmt.setString(2, p.getUsername());
288                 stmt.setString(3, p.getDeviceId());
289
290                 stmt.executeUpdate();
291             }
292         } catch (SQLException e) {
293             throw new PersistentStoreException("Error storing principal " + p, e);
294         } finally {
295             DBTools.close(conn, stmt, rs);
296         }
297     }
298
299     /**
300      * Read the principal from the data store. If <i>getId()</i> returns null,
301      * it tries to read the principal from username/device, otherwise throws id
302      * is used for the lookup.
303      *
304      * @throws PersistentException in case of error reading the data store
305      */

306     private void readPrincipal(Sync4jPrincipal p)
307     throws PersistentStoreException {
308         Connection conn = null;
309         PreparedStatement stmt = null;
310         ResultSet rs = null;
311
312         try {
313             conn = dataSource.getConnection();
314
315             if (p.getId() == null) {
316
317                 stmt = conn.prepareStatement(sql[SQL_SELECT_PRINCIPAL]);
318
319                 stmt.setString(1, p.getUsername());
320                 stmt.setString(2, p.getDeviceId());
321             } else {
322
323                 stmt = conn.prepareStatement(sql[SQL_GET_PRINCIPAL]);
324
325                 stmt.setString(1, p.getId());
326             }
327
328             rs = stmt.executeQuery();
329
330             if (rs.next() == false) {
331                 throw new NotFoundException("Principal not found for "
332                 + p.toString()
333                 );
334             }
335
336             p.setId (rs.getString(1));
337             p.setUsername (rs.getString(2));
338             p.setDeviceId (rs.getString(3));
339             p.setEmail (rs.getString(4));
340             p.setFirstName(rs.getString(5));
341             p.setLastName (rs.getString(6));
342         } catch (SQLException e) {
343             throw new PersistentStoreException("Error reading principal " + p, e);
344         } finally {
345             DBTools.close(conn, stmt, rs);
346         }
347     }
348
349     /**
350      * Read all principals
351      *
352      * @return an array with the principals (empty if no objects are found)
353      *
354      * @throws PersistentException in case of error reading the data store
355      */

356     private Object JavaDoc[] readAllPrincipals(Clause clause)
357     throws PersistentStoreException {
358         Connection conn = null;
359         PreparedStatement stmt = null;
360         ResultSet rs = null;
361
362         ArrayList JavaDoc ret = new ArrayList JavaDoc();
363
364         try {
365             conn = dataSource.getConnection();
366
367             PreparedWhere where = clause.getPreparedWhere();
368
369             String JavaDoc query = sql[SQL_SELECT_ALL_PRINCIPALS];
370             if (where.sql.length() > 0){
371                 query += " where " + where.sql;
372             }
373
374             stmt = conn.prepareStatement(query);
375
376             for (int i=0; i<where.parameters.length; ++i) {
377                 stmt.setObject(i+1, where.parameters[i]);
378             }
379
380             rs = stmt.executeQuery();
381
382             while (rs.next()) {
383                 ret.add(
384                     new Sync4jPrincipal(
385                         rs.getString(1),
386                         rs.getString(2),
387                         rs.getString(3)
388                     )
389                 );
390             }
391
392             return ret.toArray(new Sync4jPrincipal[ret.size()]);
393         } catch (SQLException e) {
394             throw new PersistentStoreException("Error reading principals", e);
395         } finally {
396             DBTools.close(conn, stmt, rs);
397         }
398     }
399
400
401     /**
402      * Delete the principal from the data store.
403      *
404      * @param p the principal
405      *
406      * @throws PersistentException in case of error reading the data store
407      */

408     private void deletePrincipal(Sync4jPrincipal p)
409     throws PersistentStoreException {
410         Connection conn = null;
411         PreparedStatement stmt = null;
412
413         try {
414             conn = dataSource.getConnection();
415
416             stmt = conn.prepareStatement(sql[SQL_DELETE_CLIENT_MAPPING]);
417
418             stmt.setString(1, p.getId());
419
420             stmt.executeUpdate();
421
422             stmt.close();
423             stmt = conn.prepareStatement(sql[SQL_DELETE_LAST_SYNC]);
424
425             stmt.setString(1, p.getId());
426
427             stmt.executeUpdate();
428
429             stmt.close();
430             stmt = conn.prepareStatement(sql[SQL_DELETE_PRINCIPAL]);
431
432             stmt.setString(1, p.getId());
433
434             stmt.executeUpdate();
435
436
437         } catch (SQLException e) {
438             throw new PersistentStoreException("Error deleting the principal " + p, e);
439         } finally {
440             DBTools.close(conn, stmt, null);
441         }
442     }
443
444     /**
445      * Select the number of principals that satisfy the conditions specified in input
446      *
447      * @return int number of principals
448      */

449     public Object JavaDoc[] readCountPrincipals(Clause clause) throws PersistentStoreException {
450         Connection conn = null;
451         PreparedStatement stmt = null;
452         ResultSet rs = null;
453         int n = 0;
454
455         try {
456             conn = dataSource.getConnection();
457
458             PreparedWhere where = clause.getPreparedWhere();
459
460             String JavaDoc query = sql[SQL_COUNT_PRINCIPALS];
461
462             if (where.sql.length()>0) {
463                 query += " where " + where.sql;
464             }
465
466             stmt = conn.prepareStatement(query);
467
468             for (int i=0; i<where.parameters.length; ++i) {
469                 stmt.setObject(i+1, where.parameters[i]);
470             }
471
472             rs = stmt.executeQuery();
473             while (rs.next()) {
474                 n = rs.getInt(1);
475             }
476
477             String JavaDoc[] s = new String JavaDoc[1];
478             s[0] = "" + n;
479             return s;
480
481         } catch (SQLException e) {
482             throw new PersistentStoreException("Error reading count principals ", e);
483         } finally {
484             DBTools.close(conn, stmt, rs);
485         }
486     }
487
488     // -------------------------------------------------------------------------
489
// Sync4jDevice
490
// -------------------------------------------------------------------------
491

492     private Object JavaDoc[] readAllDevices(Clause clause)
493     throws PersistentStoreException {
494         Connection conn = null;
495         PreparedStatement stmt = null;
496         ResultSet rs = null;
497
498         ArrayList JavaDoc ret = new ArrayList JavaDoc();
499
500         try {
501             conn = dataSource.getConnection();
502
503             PreparedWhere where = clause.getPreparedWhere();
504
505             String JavaDoc query = sql[SQL_SELECT_ALL_DEVICES];
506             if (where.sql.length() > 0) {
507                 query += " where " + where.sql;
508             }
509
510             stmt = conn.prepareStatement(query);
511
512             for (int i=0; i<where.parameters.length; ++i) {
513                 stmt.setObject(i+1, where.parameters[i]);
514             }
515
516             rs = stmt.executeQuery();
517
518             while (rs.next()) {
519                 ret.add(
520                     new Sync4jDevice(
521                         rs.getString(1),
522                         rs.getString(2),
523                         rs.getString(3)
524                     )
525                 );
526             }
527
528             return ret.toArray(new Sync4jDevice[ret.size()]);
529         } catch (SQLException e) {
530             throw new PersistentStoreException("Error reading devices", e);
531         } finally {
532             DBTools.close(conn, stmt, rs);
533         }
534     }
535
536     /**
537      * Read the device from the data store.
538      *
539      * @param d the device
540      *
541      * @throws PersistentException in case of error reading the data store
542      */

543     private void readDevice(Sync4jDevice d)
544     throws PersistentStoreException {
545         Connection conn = null;
546         PreparedStatement stmt = null;
547         ResultSet rs = null;
548
549         String JavaDoc value;
550         try {
551             conn = dataSource.getConnection();
552
553             stmt = conn.prepareStatement(sql[SQL_GET_DEVICE]);
554             stmt.setString(1, d.getDeviceId());
555
556             rs = stmt.executeQuery();
557
558             if (rs.next() == false) {
559                 throw new NotFoundException("Device not found for "
560                 + d.getDeviceId()
561                 );
562             }
563
564             d.setDescription(rs.getString(1));
565             d.setType (rs.getString(2));
566             d.setDigest (rs.getString(3));
567             value = rs.getString(4);
568             if (value == null) {
569                 d.setClientNonce(null);
570             } else if (value.equals("")) {
571                 d.setClientNonce(new byte[0]);
572             } else {
573                 d.setClientNonce(Base64.decode(value.getBytes()));
574             }
575
576             value = rs.getString(5);
577             if (value == null) {
578                 d.setServerNonce(null);
579             } else if (value.equals("")) {
580                 d.setServerNonce(new byte[0]);
581             } else {
582                 d.setServerNonce(Base64.decode(value.getBytes()));
583             }
584
585             d.setServerPassword(rs.getString(6));
586
587         } catch (SQLException e) {
588             throw new PersistentStoreException("Error reading the device " + d, e);
589         } finally {
590             DBTools.close(conn, stmt, rs);
591         }
592     }
593
594     /**
595      * Insert or Update the device from the data store.
596      *
597      * @param d the device
598      *
599      * @throws PersistentException in case of error reading the data store
600      */

601     private void storeDevice(Sync4jDevice d)
602     throws PersistentStoreException {
603         Connection conn = null;
604         PreparedStatement stmt = null;
605         int n = 0;
606
607         try {
608             conn = dataSource.getConnection();
609
610             if (d.getDeviceId() != null && !d.getDeviceId().equals("")) {
611                 stmt = conn.prepareStatement(sql[SQL_UPDATE_DEVICE]);
612
613                 stmt.setString(1, d.getDescription());
614                 stmt.setString(2, d.getType());
615                 stmt.setString(3, d.getDigest());
616                 byte[] nonce = d.getClientNonce();
617                 stmt.setString(4, ((nonce != null) ? new String JavaDoc(Base64.encode(nonce)) : null));
618                 nonce = d.getServerNonce();
619                 stmt.setString(5, ((nonce != null) ? new String JavaDoc(Base64.encode(nonce)) : null));
620                 stmt.setString(6, d.getServerPassword());
621
622                 stmt.setString(7, d.getDeviceId());
623
624
625                 n = stmt.executeUpdate();
626
627                 stmt.close();
628             }
629
630             if (n == 0) {
631                 //
632
// The first time!!!
633
//
634
if (d.getDeviceId() == null || d.getDeviceId().equals("")) {
635                     int deviceId = this.readCounter(NS_DEVICE);
636                     d.setDeviceId("" + deviceId);
637                 }
638
639                 stmt = conn.prepareStatement(sql[SQL_INSERT_DEVICE]);
640
641                 stmt.setString(1, d.getDeviceId());
642                 stmt.setString(2, d.getDescription());
643                 stmt.setString(3, d.getType());
644                 stmt.setString(4, d.getDigest());
645                 byte[] nonce = d.getClientNonce();
646                 stmt.setString(5, ((nonce != null) ? new String JavaDoc(Base64.encode(nonce)) : null));
647                 nonce = d.getServerNonce();
648                 stmt.setString(6, ((nonce != null) ? new String JavaDoc(Base64.encode(nonce)) : null));
649                 stmt.setString(7, d.getServerPassword());
650
651
652                 stmt.executeUpdate();
653             }
654         } catch (SQLException e) {
655             throw new PersistentStoreException("Error storing the device " + d, e);
656         } finally {
657             DBTools.close(conn, stmt, null);
658         }
659     }
660
661     /**
662      * Delete the device from the data store.
663      *
664      * @param d the device
665      *
666      * @throws PersistentException in case of error reading the data store
667      */

668     private void deleteDevice(Sync4jDevice d)
669     throws PersistentStoreException {
670         Connection conn = null;
671         PreparedStatement stmt = null;
672
673         try {
674             conn = dataSource.getConnection();
675
676             //select and delete all principal for this device
677
WhereClause c = new WhereClause("device", new String JavaDoc[] {d.getDeviceId()}, WhereClause.OPT_EQ, true);
678             Sync4jPrincipal[] sp = (Sync4jPrincipal[])readAllPrincipals(c);
679
680             for (int i=0; (sp != null) && i<sp.length; i++) {
681                 Sync4jPrincipal syncPrincipal = sp[i];
682                 this.deletePrincipal(syncPrincipal);
683             }
684
685             stmt = conn.prepareStatement(sql[SQL_DELETE_DEVICE]);
686
687             stmt.setString(1, d.getDeviceId());
688
689             stmt.executeUpdate();
690
691
692         } catch (SQLException e) {
693             throw new PersistentStoreException("Error deleting the device " + d, e);
694         } finally {
695             DBTools.close(conn, stmt, null);
696         }
697     }
698
699     /**
700      * Select the number of devices that satisfy the conditions specified in input
701      *
702      * @return int number of devices
703      */

704     public Object JavaDoc[] readCountDevices(Clause clause) throws PersistentStoreException {
705         Connection conn = null;
706         PreparedStatement stmt = null;
707         ResultSet rs = null;
708         int n = 0;
709
710         try {
711             conn = dataSource.getConnection();
712
713             PreparedWhere where = clause.getPreparedWhere();
714
715             String JavaDoc query = sql[SQL_COUNT_DEVICES];
716             if (where.sql.length()>0) {
717                 query += " where " + where.sql;
718             }
719
720             stmt = conn.prepareStatement(query);
721
722             for (int i=0; i<where.parameters.length; ++i) {
723                 stmt.setObject(i+1, where.parameters[i]);
724             }
725
726             rs = stmt.executeQuery();
727             while (rs.next()) {
728                 n = rs.getInt(1);
729             }
730
731             String JavaDoc[] s = new String JavaDoc[1];
732             s[0] = "" + n;
733             return s;
734
735         } catch (SQLException e) {
736             throw new PersistentStoreException("Error reading count devices ", e);
737         } finally {
738             DBTools.close(conn, stmt, rs);
739         }
740     }
741
742     // -------------------------------------------------------------------------
743

744     // -------------------------------------------------------------------------
745
// Sync4jSource
746
// -------------------------------------------------------------------------
747

748     /**
749      * Read all sources
750      *
751      * @return an array with the sources (empty if no objects are found)
752      *
753      * @throws PersistentException in case of error reading the data store
754      */

755     private Object JavaDoc[] readAllSources()
756     throws PersistentStoreException {
757         Connection conn = null;
758         PreparedStatement stmt = null;
759         ResultSet rs = null;
760
761         ArrayList JavaDoc ret = new ArrayList JavaDoc();
762
763         try {
764             conn = dataSource.getConnection();
765
766             stmt = conn.prepareStatement(sql[SQL_SELECT_ALL_SOURCES]);
767
768             rs = stmt.executeQuery();
769
770             while (rs.next()) {
771                 ret.add(
772                     new Sync4jSource(
773                         rs.getString(1),
774                         rs.getString(2)
775                     )
776                 );
777             }
778
779             return ret.toArray(new Sync4jSource[ret.size()]);
780         } catch (SQLException e) {
781             throw new PersistentStoreException("Error reading sources", e);
782         } finally {
783             DBTools.close(conn, stmt, rs);
784         }
785     }
786
787     private void storeSource(Sync4jSource s)
788     throws PersistentStoreException {
789         Connection conn = null;
790         PreparedStatement stmt = null;
791
792         try {
793             conn = dataSource.getConnection();
794
795             stmt = conn.prepareStatement(sql[SQL_UPDATE_SOURCE]);
796
797             stmt.setString(1, s.getConfig());
798             stmt.setString(2, s.getUri() );
799
800             int n = stmt.executeUpdate();
801
802             if (n == 0) {
803                 //
804
// The first time!!!
805
//
806
stmt.close();
807
808                 stmt = conn.prepareStatement(sql[SQL_INSERT_SOURCE]);
809
810                 stmt.setString(1, s.getUri() );
811                 stmt.setString(2, s.getConfig());
812
813                 stmt.executeUpdate();
814             }
815         } catch (SQLException e) {
816             throw new PersistentStoreException("Error storing the source " + s, e);
817         } finally {
818             DBTools.close(conn, stmt, null);
819         }
820     }
821
822     /**
823      * Read the source from the data store.
824      *
825      * @param s the source
826      *
827      * @throws PersistentException in case of error reading the data store
828      */

829     private void readSource(Sync4jSource s)
830     throws PersistentStoreException {
831         Connection conn = null;
832         PreparedStatement stmt = null;
833         ResultSet rs = null;
834
835         try {
836             conn = dataSource.getConnection();
837
838             stmt = conn.prepareStatement(sql[SQL_GET_SOURCE]);
839             stmt.setString(1, s.getUri());
840
841             rs = stmt.executeQuery();
842
843             if (rs.next() == false) {
844                 throw new NotFoundException("Source not found for "
845                 + s.getUri()
846                 );
847     &