KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jetspeed > services > cms > repository > slide > CmsDescriptorsStore


1 /*
2  *
3  * The Apache Software License, Version 1.1
4  *
5  * Copyright (c) 1999 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution, if
21  * any, must include the following acknowlegement:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowlegement may appear in the software itself,
25  * if and wherever such third-party acknowlegements normally appear.
26  *
27  * 4. The names "The Jakarta Project", "Jetspeed", and "Apache Software
28  * Foundation" must not be used to endorse or promote products derived
29  * from this software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache"
33  * nor may "Apache" appear in their names without prior written
34  * permission of the Apache Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation. For more
52  * information on the Apache Software Foundation, please see
53  * <http://www.apache.org/>.
54  *
55  * [Additional notices, if required by prior licensing conditions]
56  *
57  */

58
59 package org.apache.jetspeed.services.cms.repository.slide;
60
61 import java.lang.reflect.Constructor JavaDoc;
62 import java.util.Hashtable JavaDoc;
63 import java.util.Enumeration JavaDoc;
64 import java.util.Vector JavaDoc;
65 import java.util.Date JavaDoc;
66 import java.io.FileWriter JavaDoc;
67 import java.io.IOException JavaDoc;
68 import java.sql.*;
69
70 import javax.transaction.xa.XAException JavaDoc;
71 import javax.transaction.xa.Xid JavaDoc;
72
73 import org.apache.slide.common.*;
74 import org.apache.slide.store.*;
75 import org.apache.slide.structure.*;
76 import org.apache.slide.security.*;
77 import org.apache.slide.lock.*;
78 import org.apache.slide.content.*;
79 import org.apache.slide.util.logger.Logger;
80
81 import org.apache.jetspeed.services.resources.JetspeedResources;
82 /**
83  * JDBC 1.0 and 2.0 compliant store implementation.
84  * This class comes from Slide code. Can be replace by another descriptor
85  * store.
86  *
87  *
88  *
89  * TO DO : Use J2EE Datastore instead of this class
90  *
91  * @author <a HREF="mailto:remm@apache.org">Remy Maucherat</a>
92  * @author Dirk Verbeeck
93  * @author <a HREF="mailto:christophe.lombart@skynet.be">Christophe Lombart</a>
94  */

95
96 public class CmsDescriptorsStore
97     extends AbstractSimpleService
98     implements
99         LockStore,
100         NodeStore,
101         RevisionDescriptorsStore,
102         RevisionDescriptorStore,
103         SecurityStore {
104
105     // -------------------------------------------------------------- Constants
106

107     // Column numbers
108

109     // Structure descriptors
110

111     protected static final int OBJECTS_URI = 1;
112     protected static final int OBJECTS_CLASS = 2;
113
114     protected static final int CHILDREN_URI = 1;
115     protected static final int CHILDREN_CHILDURI = 2;
116
117     protected static final int LINKS_LINK = 1;
118     protected static final int LINKS_LINKTO = 2;
119
120     // Security descriptors
121

122     protected static final int PERMISSIONS_OBJECT = 1;
123     protected static final int PERMISSIONS_REVISION_NUMBER = 2;
124     protected static final int PERMISSIONS_SUBJECT = 3;
125     protected static final int PERMISSIONS_ACTION = 4;
126     protected static final int PERMISSIONS_INHERITABLE = 5;
127     protected static final int PERMISSIONS_NEGATIVE = 6;
128
129     // Lock descriptors
130

131     protected static final int LOCKS_ID = 1;
132     protected static final int LOCKS_OBJECT = 2;
133     protected static final int LOCKS_SUBJECT = 3;
134     protected static final int LOCKS_TYPE = 4;
135     protected static final int LOCKS_EXPIRATIONDATE = 5;
136     protected static final int LOCKS_INHERITABLE = 6;
137     protected static final int LOCKS_EXCLUSIVE = 7;
138
139     // Content descriptors
140

141     protected static final int REVISIONS_URI = 1;
142     protected static final int REVISIONS_ISVERSIONED = 2;
143     protected static final int REVISIONS_INITIALREVISION = 3;
144
145     protected static final int WORKINGREVISION_URI = 1;
146     protected static final int WORKINGREVISION_BASEREVISION = 2;
147     protected static final int WORKINGREVISION_NUMBER = 3;
148
149     protected static final int LATESTREVISIONS_URI = 1;
150     protected static final int LATESTREVISIONS_BRANCHNAME = 2;
151     protected static final int LATESTREVISIONS_NUMBER = 3;
152
153     protected static final int BRANCHES_URI = 1;
154     protected static final int BRANCHES_NUMBER = 2;
155     protected static final int BRANCHES_CHILDNUMBER = 3;
156
157     protected static final int REVISION_URI = 1;
158     protected static final int REVISION_NUMBER = 2;
159     protected static final int REVISION_BRANCHNAME = 3;
160
161     protected static final int LABEL_URI = 1;
162     protected static final int LABEL_NUMBER = 2;
163     protected static final int LABEL_LABEL = 3;
164
165     protected static final int PROPERTY_URI = 1;
166     protected static final int PROPERTY_NUMBER = 2;
167     protected static final int PROPERTY_NAME = 3;
168     protected static final int PROPERTY_VALUE = 4;
169     protected static final int PROPERTY_NAMESPACE = 5;
170     protected static final int PROPERTY_TYPE = 6;
171     protected static final int PROPERTY_PROTECTED = 7;
172
173     // ----------------------------------------------------- Instance Variables
174

175     /**
176      * Database connection.
177      */

178     protected Connection connection;
179
180     /**
181      * Driver class name.
182      */

183     protected String JavaDoc driver;
184
185     /**
186      * Connection URL.
187      */

188     protected String JavaDoc url;
189
190     /**
191      * User name.
192      */

193     protected String JavaDoc user;
194
195     /**
196      * Password.
197      */

198     protected String JavaDoc password;
199
200     /**
201      * JDBC Version to use.
202      */

203     protected int jdbcVersion;
204
205     /**
206      * This store doesn't handle nested transactions, this variable keeps track
207      * if the store is already enlisted to a transaction.
208      */

209     protected boolean alreadyEnlisted = false;
210
211     // -------------------------------------------------------- Service Methods
212

213     /**
214      * Returns the sql statements to create the database objects.
215      */

216     protected String JavaDoc[] getDatabaseCreateStatements() {
217         String JavaDoc[] statements =
218             {
219                 "create table objects(uri varchar(65536) primary key,"
220                     + " classname varchar(4096))",
221                 "create table children(uri varchar(65536), "
222                     + " childuri varchar(65536))",
223                 "create table links(link varchar(65536), "
224                     + " linkto varchar(65536))",
225                 "create table permissions(object varchar(65536),"
226                     + " revisionnumber varchar(20), "
227                     + " subject varchar(65536), action varchar(65536), "
228                     + " inheritable int, negative int)",
229                 "create table locks(id varchar(65536), object varchar(4096),"
230                     + " subject varchar(4096), type varchar(4096), "
231                     + " expirationdate varchar(15), inheritable int, "
232                     + " xexclusive int)",
233                 "create table revisions(uri varchar(65536) primary key, "
234                     + " isversioned int, initialrevision varchar(10))",
235                 "create table workingrevision(uri varchar(65536), "
236                     + " baserevision varchar(20), xnumber varchar(20))",
237                 "create table latestrevisions(uri varchar(65536), "
238                     + " branchname varchar(4096), xnumber varchar(20))",
239                 "create table branches(uri varchar(65536), xnumber varchar(20),"
240                     + " childnumber varchar(20))",
241                 "create table revision(uri varchar(65536), xnumber varchar(20),"
242                     + " branchname varchar(4096))",
243                 "create table label(uri varchar(65536), xnumber varchar(20),"
244                     + " label varchar(4096))",
245                 "create table property(uri varchar(65536), xnumber varchar(20),"
246                     + " name varchar(4096), value varchar(65536), "
247                     + " namespace varchar(4096), type varchar(100), protected int)" };
248
249         return statements;
250     }
251
252     /**
253      * Initializes the data source with a set of parameters.
254      *
255      * @param parameters Hashtable containing the parameters' name
256      * and associated value
257      * @exception ServiceParameterErrorException Incorrect service parameter
258      * @exception ServiceParameterMissingException Service parameter missing
259      */

260     public void setParameters(Hashtable JavaDoc parameters)
261         throws ServiceParameterErrorException, ServiceParameterMissingException {
262
263         // Driver classname
264
driver =
265             JetspeedResources.getString(
266                 "services.CmsService.slide.descriptor.driver");
267
268         // Connection url - might contain variable like ${webappRoot}
269
url =
270             JetspeedResources.getString(
271                 "services.CmsService.slide.descriptor.url");
272
273         // FIXME: before slide 1.0.12 the database url was passed
274
// without "jdbc:" this compatibility code sould be removed in the
275
// future code changed 18 jul 2001
276
if (!url.startsWith("jdbc:")) {
277             url = "jdbc:" + url;
278         }
279         // end compatibility code
280

281         // User name
282
user =
283             JetspeedResources.getString(
284                 "services.CmsService.slide.descriptor.user");
285         if (user == null) {
286             user = new String JavaDoc();
287         }
288
289         // Password
290
password =
291             JetspeedResources.getString(
292                 "services.CmsService.slide.descriptor.password");
293         if (password == null) {
294             password = new String JavaDoc();
295         }
296
297         // JDBC version to use
298
jdbcVersion = 1;
299         String JavaDoc version =
300             JetspeedResources.getString(
301                 "services.CmsService.slide.descriptor.jdbcversion");
302         if (version != null) {
303             jdbcVersion = (new Integer JavaDoc(version)).intValue();
304         }
305     }
306
307     /**
308      * Connects to JDBC and creates the basic table structure.
309      *
310      * @exception ServiceConnectionFailedException Connection to the
311      * database failed
312      */

313     public synchronized void connect()
314         throws ServiceConnectionFailedException {
315         getLogger().log(
316             "Connecting to \"" + url + "\" as user \"" + user + "\"",
317             LOG_CHANNEL,
318             Logger.INFO);
319         try {
320             connection = DriverManager.getConnection(url, user, password);
321         } catch (SQLException e) {
322             getLogger().log(
323                 "Connecting to \"" + url + "\" as user \"" + user + "\" failed",
324                 LOG_CHANNEL,
325                 Logger.ERROR);
326             getLogger().log(e.toString(), LOG_CHANNEL, Logger.ERROR);
327             throw new ServiceConnectionFailedException(this, e);
328         }
329
330         // all updates must be done inside a transaction, no auto commits
331
try {
332             connection.setAutoCommit(true);
333         } catch (SQLException e) {
334         }
335         /*
336          Statement statement = null;
337          try {
338              statement = connection.createStatement();
339              String[] statements = getDatabaseCreateStatements();
340              for (int i=0; i<statements.length ; i++ ) {
341                  statement.execute(statements[i]);
342              }
343         
344              // Cloudscape needs a commit on DDL statements (create,...)
345              connection.commit();
346         
347          } catch (SQLException e) {
348              try { connection.rollback(); } catch (SQLException ex) { }
349          } finally {
350              closeStatement(statement);
351          }
352          */

353         // we are just connected and are not enlisted
354
alreadyEnlisted = false;
355     }
356
357     /**
358      * Disconnects from data source.
359      *
360      * @exception ServiceDisconnectionFailedException Disconnection
361      * from database failed
362      */

363     public void disconnect() throws ServiceDisconnectionFailedException {
364         getLogger().log(
365             "Disconnecting from \"" + url + "\" as user \"" + user + "\"",
366             LOG_CHANNEL,
367             Logger.INFO);
368         try {
369             if (connection != null) {
370                 connection.close();
371             }
372             connection = null;
373         } catch (SQLException e) {
374             getLogger().log(
375                 "Disconnecting from \""
376                     + url
377                     + "\" as user \""
378                     + user
379                     + "\" failed",
380                 LOG_CHANNEL,
381                 Logger.ERROR);
382             getLogger().log(e.toString(), LOG_CHANNEL, Logger.ERROR);
383             throw new ServiceDisconnectionFailedException(this, e);
384         }
385     }
386
387     /**
388      * Initializes data source.
389      * <p/>
390      * Occurs in four steps :
391      * <li>Driver class is loaded</li>
392      * <li>Driver is intantiated</li>
393      * <li>Driver registration in the driver manager</li>
394      * <li>Creation of the basic tables, if they didn't exist before</li>
395      *
396      * @exception ServiceInitializationFailedException Throws an exception
397      * if the data source has already been initialized before
398      */

399     public synchronized void initialize(NamespaceAccessToken token)
400         throws ServiceInitializationFailedException {
401         try {
402             // Loading and registering driver
403
token.getLogger().log(
404                 "Loading and registering driver: " + driver,
405                 LOG_CHANNEL,
406                 Logger.INFO);
407             Class JavaDoc driverClass = Class.forName(driver);
408             Driver databaseDriver = (Driver) driverClass.newInstance();
409             DriverManager.registerDriver(databaseDriver);
410         } catch (ClassNotFoundException JavaDoc e) {
411             token.getLogger().log(
412                 "Loading and registering driver " + driver + " failed",
413                 LOG_CHANNEL,
414                 Logger.ERROR);
415             token.getLogger().log(e.toString(), LOG_CHANNEL, Logger.ERROR);
416             throw new ServiceInitializationFailedException(
417                 this,
418                 e.getMessage());
419         } catch (InstantiationException JavaDoc e) {
420             token.getLogger().log(
421                 "Loading and registering driver " + driver + " failed",
422                 LOG_CHANNEL,
423                 Logger.ERROR);
424             token.getLogger().log(e.toString(), LOG_CHANNEL, Logger.ERROR);
425             throw new ServiceInitializationFailedException(
426                 this,
427                 e.getMessage());
428         } catch (IllegalAccessException JavaDoc e) {
429             token.getLogger().log(
430                 "Loading and registering driver " + driver + " failed",
431                 LOG_CHANNEL,
432                 Logger.ERROR);
433             token.getLogger().log(e.toString(), LOG_CHANNEL, Logger.ERROR);
434             throw new ServiceInitializationFailedException(
435                 this,
436                 e.getMessage());
437         } catch (SQLException e) {
438             token.getLogger().log(
439                 "Loading and registering driver " + driver + " failed",
440                 LOG_CHANNEL,
441                 Logger.ERROR);
442             token.getLogger().log(e.toString(), LOG_CHANNEL, Logger.ERROR);
443             throw new ServiceInitializationFailedException(
444                 this,
445                 e.getMessage());
446         } catch (ClassCastException JavaDoc e) {
447             token.getLogger().log(
448                 "Loading and registering driver " + driver + " failed",
449                 LOG_CHANNEL,
450                 Logger.ERROR);
451             token.getLogger().log(e.toString(), LOG_CHANNEL, Logger.ERROR);
452             throw new ServiceInitializationFailedException(
453                 this,
454                 e.getMessage());
455         } catch (Exception JavaDoc e) {
456             token.getLogger().log(
457                 "Loading and registering driver " + driver + " failed",
458                 LOG_CHANNEL,
459                 Logger.ERROR);
460             token.getLogger().log(e.toString(), LOG_CHANNEL, Logger.ERROR);
461             throw new ServiceInitializationFailedException(
462                 this,
463                 e.getMessage());
464         }
465     }
466
467     /**
468      * Deletes data source. Should remove stored data if possible.
469      *
470      * @exception ServiceResetFailedException Reset failed
471      */

472     public synchronized void reset() throws ServiceResetFailedException {
473         Statement statement = null;
474         /*
475          try {
476              connectIfNeeded();
477         
478              statement = connection.createStatement();
479              String s = null;
480         
481              s = "drop table objects";
482              statement.execute(s);
483         
484              s = "drop table children";
485              statement.execute(s);
486         
487              s = "drop table links";
488              statement.execute(s);
489         
490              s = "drop table permissions";
491              statement.execute(s);
492         
493              s = "drop table locks";
494              statement.execute(s);
495         
496              s = "drop table revisions";
497              statement.execute(s);
498         
499              s = "drop table workingrevision";
500              statement.execute(s);
501         
502              s = "drop table latestrevisions";
503              statement.execute(s);
504         
505              s = "drop table branches";
506              statement.execute(s);
507         
508              s = "drop table revision";
509              statement.execute(s);
510         
511              s = "drop table label";
512              statement.execute(s);
513         
514              s = "drop table property";
515              statement.execute(s);
516         
517              statement.close();
518              disconnect();
519          } catch (SQLException e) {
520              throw new ServiceResetFailedException(this, e.getMessage());
521          } catch (ServiceAccessException e) {
522              throw new ServiceResetFailedException(this, e.getMessage());
523          } catch (ServiceConnectionFailedException e) {
524              throw new ServiceResetFailedException(this, e.getMessage());
525          } catch (ServiceDisconnectionFailedException e) {
526              throw new ServiceResetFailedException(this, e.getMessage());
527          } finally {
528              closeStatement(statement);
529          }
530          */

531     }
532
533     /**
534      * This function tells whether or not the data source is connected.
535      *
536      * @return boolean true if we are connected
537      * @exception ServiceAccessException Error accessing DataSource
538      */

539     public boolean isConnected() throws ServiceAccessException {
540         try {
541             return ((connection != null) && (!connection.isClosed()));
542         } catch (SQLException e) {
543             throw new ServiceAccessException(this, e);
544         }
545     }
546
547     // ----------------------------------------------------- XAResource Methods
548

549     /**
550      * Commit the global transaction specified by xid.
551      */

552     public void commit(Xid JavaDoc xid, boolean onePhase) throws XAException JavaDoc {
553         super.commit(xid, onePhase);
554
555         try {
556             // getLogger().log("commit",LOG_CHANNEL,Logger.DEBUG);
557
connection.commit();
558         } catch (SQLException e) {
559             throw new XAException JavaDoc(XAException.XA_RBCOMMFAIL);
560         }
561         alreadyEnlisted = false;
562     }
563
564     /**
565      * Inform the resource manager to roll back work done on behalf of a
566      * transaction branch.
567      */

568     public void rollback(Xid JavaDoc xid) throws XAException JavaDoc {
569         super.rollback(xid);
570
571         try {
572             // getLogger().log("rollback",LOG_CHANNEL,Logger.DEBUG);
573
connection.rollback();
574         } catch (SQLException e) {
575             throw new XAException JavaDoc(XAException.XA_HEURCOM);
576         }
577         alreadyEnlisted = false;
578     }
579
580     /**
581      * Start work on behalf of a transaction branch specified in xid.
582      */

583     public void start(Xid JavaDoc xid, int flags) throws XAException JavaDoc {
584         super.start(xid, flags);
585         if (!alreadyEnlisted) {
586             try {
587                 // getLogger().log("start",LOG_CHANNEL,Logger.DEBUG);
588
// discard changes made outside a tranaction
589
connection.rollback();
590             } catch (SQLException e) {
591                 throw new XAException JavaDoc(XAException.XAER_RMERR);
592             }
593             alreadyEnlisted = true;
594         }
595     }
596
597     // ----------------------------------------------- DescriptorsStore Methods
598

599     /**
600      * Retrive an object.
601      *
602      * @param uri Uri of the object we want to retrieve
603      * @exception ServiceAccessException Error accessing the Service
604      * @exception ObjectNotFoundException The object to retrieve was not found
605      */

606     public ObjectNode retrieveObject(Uri uri)
607         throws ServiceAccessException, ObjectNotFoundException {
608
609         ObjectNode result = null;
610         PreparedStatement statement = null;
611
612         try {
613
614             statement =
615                 connection.prepareStatement(
616                     "select * from objects where uri= ?");
617             statement.setString(1, uri.toString());
618
619             ResultSet res = statement.executeQuery();
620
621             // Parsing result set
622

623             String JavaDoc className;
624
625             if (res.next()) {
626                 // Retrieving and loading the object
627
className = res.getString(OBJECTS_CLASS);
628             } else {
629                 // Object was not found ...
630
throw new ObjectNotFoundException(uri);
631             }
632
633             closeStatement(statement);
634
635             // Then, retrieve the children
636
statement =
637                 connection.prepareStatement(
638                     "select * from children where uri= ?");
639             statement.setString(1, uri.toString());
640             res = statement.executeQuery();
641
642             Vector JavaDoc childrenVector = new Vector JavaDoc();
643
644             // Parse result set
645
while (res.next()) {
646                 // Load each permission
647
childrenVector.addElement(res.getString(CHILDREN_CHILDURI));
648             }
649             closeStatement(statement);
650
651             statement =
652                 connection.prepareStatement(
653                     "select * from links where linkto= ?");
654             statement.setString(1, uri.toString());
655             res = statement.executeQuery();
656
657             Vector JavaDoc linksVector = new Vector JavaDoc();
658
659             // Parse result set
660
while (res.next()) {
661                 // Load each permission
662
linksVector.addElement(res.getString(LINKS_LINKTO));
663             }
664
665             closeStatement(statement);
666
667             if (className.equals("org.apache.slide.structure.LinkNode")) {
668
669                 String JavaDoc linkTo = new String JavaDoc();
670                 statement =
671                     connection.prepareStatement(
672                         "select * from links where link= ?");
673                 statement.setString(1, uri.toString());
674                 res = statement.executeQuery();
675
676                 if (res.next()) {
677                     linkTo = res.getString(LINKS_LINKTO);
678                 }
679
680                 closeStatement(statement);
681
682                 result =
683                     new LinkNode(
684                         uri.toString(),
685                         childrenVector,
686                         linksVector,
687                         linkTo);
688
689             } else {
690
691                 try {
692                     Class JavaDoc objclass = Class.forName(className);
693
694                     Class JavaDoc[] argClasses =
695                         {
696                             Class.forName("java.lang.String"),
697                             Class.forName("java.util.Vector"),
698                             Class.forName("java.util.Vector")};
699                     Object JavaDoc[] arguments =
700                         { uri.toString(), childrenVector, linksVector };
701
702                     Constructor JavaDoc constructor =
703                         objclass.getConstructor(argClasses);
704                     result = (ObjectNode) constructor.newInstance(arguments);
705                 } catch (Exception JavaDoc e) {
706                     // ClassNotFoundException, NoSuchMethodException, etc.
707
throw new ServiceAccessException(this, e);
708                 }
709             }
710         } catch (SQLException e) {
711             getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
712             throw new ServiceAccessException(this, e);
713         } finally {
714             closeStatement(statement);
715         }
716         return result;
717     }
718
719     /**
720      * Update an object.
721      *
722      * @param object Object to update
723      * @exception ServiceAccessException Error accessing the Service
724      * @exception ObjectNotFoundException The object to update was not found
725      */

726     public void storeObject(Uri uri, ObjectNode object)
727         throws ServiceAccessException, ObjectNotFoundException {
728
729         PreparedStatement statement = null;
730
731         try {
732             statement =
733                 connection.prepareStatement(
734                     "select * from objects where uri= ?");
735             statement.setString(1, uri.toString());
736
737             ResultSet res = statement.executeQuery();
738
739             // Parsing result set
740

741             if (!res.next()) {
742                 throw new ObjectNotFoundException(uri);
743             }
744
745             closeStatement(statement);
746
747             // Updating children
748
statement =
749                 connection.prepareStatement(
750                     "delete from children where uri= ?");
751             statement.setString(1, object.getUri());
752             statement.execute();
753             closeStatement(statement);
754
755             statement = null;
756             Enumeration JavaDoc children = object.enumerateChildren();
757             while (children.hasMoreElements()) {
758                 if (statement == null) {
759                     statement =
760                         connection.prepareStatement(
761                             "insert into children values(?, ?)");
762                 }
763                 statement.setString(1, object.getUri());
764                 statement.setString(2, (String JavaDoc) children.nextElement());
765                 statement.execute();
766             }
767             closeStatement(statement);
768
769             // Updating inbound links
770
/*
771             s = "delete from links where linkto='" + object.getUri() + "'";
772             statement.execute(s);
773             Enumeration links = object.enumerateLinks();
774             while (children.hasMoreElements()) {
775                 s = "insert into links values('"
776                     + (String) links.nextElement() + "', '"
777                     + object.getUri() + "')";
778                 statement.execute(s);
779             }
780             */

781
782             // Updating links
783
statement =
784                 connection.prepareStatement("delete from links where link= ?");
785             statement.setString(1, object.getUri());
786             statement.execute();
787             closeStatement(statement);
788
789             if (object instanceof LinkNode) {
790                 statement =
791                     connection.prepareStatement(
792                         "insert into links values(?,?)");
793                 statement.setString(1, object.getUri());
794                 statement.setString(2, ((LinkNode) object).getLinkedUri());
795                 statement.execute();
796                 closeStatement(statement);
797             }
798         } catch (SQLException e) {
799             getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
800             throw new ServiceAccessException(this, e);
801         } finally {
802             closeStatement(statement);
803         }
804     }
805
806     /**
807      * Create a new object.
808      *
809      * @param object ObjectNode
810      * @param uri Uri of the object we want to create
811      * @exception ServiceAccessException Error accessing the Service
812      * @exception ObjectAlreadyExistsException An object already exists
813      * at this Uri
814      */

815     public void createObject(Uri uri, ObjectNode object)
816         throws ServiceAccessException, ObjectAlreadyExistsException {
817
818         PreparedStatement statement = null;
819
820         try {
821
822             String JavaDoc className = object.getClass().getName();
823
824             statement =
825                 connection.prepareStatement(
826                     "select * from objects where uri= ?");
827             statement.setString(1, uri.toString());
828
829             ResultSet res = statement.executeQuery();
830
831             // Parsing result set
832

833             if (res.next()) {
834                 throw new ObjectAlreadyExistsException(uri.toString());
835             }
836
837             closeStatement(statement);
838
839             statement =
840                 connection.prepareStatement("insert into objects values(?,?)");
841             statement.setString(1, uri.toString());
842      &