kevinross 2003/07/09 09:35:13
Modified: java/tests/src/org/apache/xindice/client/xmldb DatabaseImplTest.java src/documentation/content/xdocs/dev guide-internals.xml java/src/org/apache/xindice/core Database.java java/src/org/apache/xindice/client/xmldb DatabaseImpl.java java/src/org/apache/xindice/client/xmldb/embed DatabaseImpl.java Added: java/src/org/apache/xindice/server ManagedServer.java java/tests/src/org/apache/xindice IntegrationManagedTests.java java/src/org/apache/xindice/client/xmldb/managed ManagedDatabaseImpl.java Log: PR: 21402 Patch Submitted by: Kevin O'Neill ([EMAIL PROTECTED]) Reviewed by: Kevin Ross Added a new driver whos database instance is managed externally. Unlike the embeded driver if the database is not available the driver will fail to load. It's designed specifically for use in environments where there an external process is managing the lifecycle of the database. The patch also includes some updates to database to prevent a registration race condition (outlined in an earlier email). This has some flow on effects in the embeded driver. Revision Changes Path 1.1 xml-xindice/java/src/org/apache/xindice/server/ManagedServer.java Index: ManagedServer.java =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xindice" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 1999-2001, The dbXML * Group, L.L.C., http://www.dbxmlgroup.com. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * $Id: ManagedServer.java,v 1.1 2003/07/09 16:35:11 kevinross Exp $ */ package org.apache.xindice.server; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.xindice.core.Database; import org.apache.xindice.util.Configuration; import org.apache.xindice.util.ReadOnlyException; import org.apache.xindice.util.XindiceException; import org.apache.xindice.xml.dom.DOMParser; /** * Creates an registers a database instance for use of the managed driver. This class * may be used to create the database the managed driver uses (as is the case in the test * cases) but it is not required. Any method may be used to create the database instance * that the managed driver talks to. As long as the instance name exists when the driver * fires up all will be good. * * @author <a href="mailto:[EMAIL PROTECTED]">Kevin O'Neill</a> * * @version $Revision: 1.1 $ - $Date: 2003/07/09 16:35:11 $ */ public class ManagedServer { protected Log _log = LogFactory.getLog(getClass()); protected Database _db = null; protected boolean _running = false; public synchronized void start() throws Exception { if (!_running) { configure(); _running = true; } else { _log.warn("Start called on a running server, ignored"); } } public void stop() throws Exception { if (_running) { _db.close(); _db = null; } else { _log.warn("Stop called on a stopped server, ignored"); } } public void configure() throws FileNotFoundException, XindiceException { _db = Database.getDatabase(loadConfiguration()); if (null == _db) { _log.fatal("Unable to configure database"); throw new XindiceException("Unable to configure database"); } else if (_log.isInfoEnabled()) { _log.info("Database name: '" + _db.getName() + "'"); } } protected Configuration loadConfiguration() throws FileNotFoundException, XindiceException, ReadOnlyException { Configuration config; String configFile = System.getProperty(Xindice.PROP_XINDICE_CONFIGURATION); if (configFile != null && !configFile.equals("")) { if (_log.isInfoEnabled()) { _log.info("Specified configuration file: '" + configFile + "'"); } FileInputStream configXMLFile = new FileInputStream(new File(configFile)); config = new Configuration(DOMParser.toDocument(configXMLFile), false); } else { if (_log.isInfoEnabled()) { _log.info("No configuration file specified, going with the default configuration"); } config = new Configuration(DOMParser.toDocument(Xindice.DEFAULT_CONFIGURATION), false); } config = config.getChild("root-collection", false); return config; } } 1.3 +3 -3 xml-xindice/java/tests/src/org/apache/xindice/client/xmldb/DatabaseImplTest.java Index: DatabaseImplTest.java =================================================================== RCS file: /home/cvs/xml-xindice/java/tests/src/org/apache/xindice/client/xmldb/DatabaseImplTest.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- DatabaseImplTest.java 28 Oct 2002 08:39:19 -0000 1.2 +++ DatabaseImplTest.java 9 Jul 2003 16:35:11 -0000 1.3 @@ -77,7 +77,7 @@ public void testGetName() throws Exception { - assertEquals("xindice, xindice-embed", db.getName()); + assertEquals("xindice, xindice-embed, xindice-managed", db.getName()); } public void testAcceptXmlRpcURI() 1.12 +30 -1 xml-xindice/src/documentation/content/xdocs/dev/guide-internals.xml Index: guide-internals.xml =================================================================== RCS file: /home/cvs/xml-xindice/src/documentation/content/xdocs/dev/guide-internals.xml,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- guide-internals.xml 27 Dec 2002 17:23:02 -0000 1.11 +++ guide-internals.xml 9 Jul 2003 16:35:11 -0000 1.12 @@ -8,6 +8,7 @@ <title>Xindice internals</title> <authors> <person id="jb" name="James Bates" email="[EMAIL PROTECTED]"/> + <person id="kao" name="Kevin O'Neill" email="[EMAIL PROTECTED]"/> </authors> <notice/> <abstract> @@ -934,6 +935,34 @@ <section> <title>7.2. XML-RPC driver</title> </section> + <section> + <title>7.3. Managed driver</title> + <p>The Managed driver (<code>xindice-managed</code>) is designed for use in environments where the + life cycle of the xindice database is controlled by an external service. Like the Embeded driver accesses + a database running in the local vm. Unlike the Embeded driver the Manged driver will <strong>not</strong> + create the database instance. It will fail to load if the database instance is not available</p> + <section> + <title>7.3.1. Configuraton</title> + <p>Configuration of the driver is easy, create an instance of the class. There are two constructors provided, + a "no args" default constructure one that takes the name of the database to connect to. The "no args" constructor + will attempt to connect a database with the name of "db" or the value of the "xindice.drivers.managed.db" property. + When the second constructor is used the database name is explicitly passed.</p> + </section> + <section> + <title>7.3.2. ManagedServer</title> + <p>ManagedServer is a simple class that loads a database for access by the Managed driver. It is by + no means the only way to create and register a database instance. Configuration is the same as for + the embeded driver. This is suitable for simple tests and standalone applications, but managed environments + should provide their own configuration implementations.</p> + </section> + <section> + <title>7.3.3. Advantages of the Embeded driver</title> + <p>The main advantage is that the database has an explicit lifecycle. With the Emdeded driver database creation + is a side effect of access to the client driver. The determination of what lifecycle methods are run when + is unclear (for example when is the database closed). By making database instantiation an external task + to the driver this problem disappears.</p> + </section> + </section> </section> </body> 1.1 xml-xindice/java/tests/src/org/apache/xindice/IntegrationManagedTests.java Index: IntegrationManagedTests.java =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xindice" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 1999-2001, The dbXML * Group, L.L.C., http://www.dbxmlgroup.com. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * $Id: IntegrationManagedTests.java,v 1.1 2003/07/09 16:35:12 kevinross Exp $ */ package org.apache.xindice; import org.apache.xindice.integration.IntegrationTests; import org.apache.xindice.integration.client.XmlDbClient; import org.apache.xindice.integration.client.XmlDbClientSetup; import org.apache.xindice.server.ManagedServer; import org.xmldb.api.DatabaseManager; import org.xmldb.api.base.Database; import junit.framework.Test; import junitx.extensions.TestSetup; /** * Runs the Integration test suite using the managed driver. * * @author <a href="mailto:[EMAIL PROTECTED]">Kevin O'Neill</a> * @version $Revision: 1.1 $, $Date: 2003/07/09 16:35:12 $ */ public class IntegrationManagedTests { public static Test suite() throws Exception { return new TestSetup(new XmlDbClientSetup(IntegrationTests.testSuite("Managed client integration tests"), new XmlDbClient("xmldb:xindice-managed://"))) { private Database database; private ManagedServer server; public void setUp() throws Exception { server = new ManagedServer(); server.start(); String driver = "org.apache.xindice.client.xmldb.DatabaseImpl"; Class cls = Class.forName(driver); database = (Database) cls.newInstance(); DatabaseManager.registerDatabase(database); } public void tearDown() throws Exception { if (database != null) { DatabaseManager.deregisterDatabase(database); database = null; } server.stop(); server = null; } }; } } 1.18 +57 -30 xml-xindice/java/src/org/apache/xindice/core/Database.java Index: Database.java =================================================================== RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/Database.java,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- Database.java 27 Dec 2002 18:37:23 -0000 1.17 +++ Database.java 9 Jul 2003 16:35:12 -0000 1.18 @@ -88,7 +88,6 @@ private static final String METADATA = "use-metadata"; public static final String NAME = "name"; - private static Log log = LogFactory.getLog("org.apache.xindice.core"); public static final String PROP_XINDICE_HOME = "xindice.home"; @@ -110,7 +109,45 @@ private QueryEngine engine = new QueryEngine(this); public static Database getDatabase(String name) { - return (Database)databases.get(name); + + Database database = (Database) databases.get(name); + if (null == database) { + // in case it's currently being added (only pay the sync hit on a miss) + synchronized (databases) { + database = (Database) databases.get(name); + } + } + + return database; + } + + public static Database getDatabase(Configuration config) { + + String name = config.getAttribute(Database.NAME); + + // no name in the config file ... can't the database + if (null == name) { + log.error("Database configuration didn't contain a database name"); + + return null; + } + + Database database = (Database) databases.get(name); + if (null == database) { + // in case it's currently being added (only pay the sync hit on a miss) + synchronized (databases) { + // was it created while we waited? + database = (Database) databases.get(name); + if (null == database) { + database = new Database(); + database.setConfig(config); + + databases.put(database.getName(), database); + } + } + } + + return database; } public static String[] listDatabases() { @@ -137,8 +174,7 @@ Configuration queryCfg = config.getChild(QUERYENGINE); if ( queryCfg != null ) engine.setConfig(queryCfg); - } - catch ( Exception e ) { + } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("No message", e); } @@ -149,8 +185,7 @@ try { sysCol.init(); - } - catch ( XindiceException e ) { + } catch (XindiceException e) { if (log.isDebugEnabled()) { log.debug("No message", e); } @@ -175,29 +210,25 @@ } super.setConfig(new Configuration(colDoc.getDocumentElement(), false)); - } - catch ( Exception e ) { + } catch (Exception e) { if (log.isDebugEnabled()) { log.debug("No message", e); } } // Register the Database with the VM - databases.put(getName(), this); + // databases.put(getName(), this); // initialize the meta collection // but only if it's turned on in the config. String metaCfg = config.getAttribute(METADATA); - if ( metaCfg.equalsIgnoreCase("on") ) - { + if (metaCfg.equalsIgnoreCase("on")) { metaEnabled = true; - if (!metaInit) - { + if (!metaInit) { metaCol = new MetaSystemCollection(this); try { metaCol.init(); - } - catch ( XindiceException e ) { + } catch (XindiceException e) { if (log.isDebugEnabled()) { log.debug("Error initializing the meta collection", e); } @@ -234,8 +265,7 @@ * Return whether or not metadata is enabled on this database. * @return boolean */ - public boolean isMetaEnabled() - { + public boolean isMetaEnabled() { return metaEnabled; } @@ -251,8 +281,7 @@ try { Document d = config.getElement().getOwnerDocument(); sysCol.getCollection(SystemCollection.CONFIGS).setDocument(COLKEY, d); - } - catch ( Exception e ) { + } catch (Exception e) { if (log.isErrorEnabled()) { log.error("Error Writing Configuration '"+name+"', for database "+getName(), e); } @@ -263,7 +292,11 @@ public boolean close() throws DBException { flushConfig(); + + synchronized (databases) { databases.remove( getName() ); + } + return true; } @@ -287,15 +320,12 @@ } // methods for recording the times when meta data is enabled. - public synchronized void recordTime( String path, long created, long modified ) - { + public synchronized void recordTime(String path, long created, long modified) { TimeRecord rec = (TimeRecord)timestamps.get(path); if( null == rec ) { rec = new TimeRecord(created, modified); timestamps.put(path, rec); - } - else - { + } else { if( created > 0 ) rec.setCreatedTime(created); if( modified > 0 ) @@ -303,15 +333,12 @@ } } - public synchronized void removeTime( String path ) - { + public synchronized void removeTime(String path) { timestamps.remove(path); } - public synchronized TimeRecord getTime( String path ) - { + public synchronized TimeRecord getTime(String path) { TimeRecord rec = (TimeRecord)timestamps.get(path); return rec; } } - 1.13 +12 -12 xml-xindice/java/src/org/apache/xindice/client/xmldb/DatabaseImpl.java Index: DatabaseImpl.java =================================================================== RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/client/xmldb/DatabaseImpl.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- DatabaseImpl.java 30 May 2003 22:39:16 -0000 1.12 +++ DatabaseImpl.java 9 Jul 2003 16:35:12 -0000 1.13 @@ -59,13 +59,12 @@ * $Id$ */ -import java.lang.reflect.Constructor; - +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.xindice.client.xmldb.managed.ManagedDatabaseImpl; import org.xmldb.api.base.Database; import org.xmldb.api.base.ErrorCodes; import org.xmldb.api.base.XMLDBException; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * DatabaseImpl is the XML:DB driver implementation for Xindice. It is the entry @@ -94,11 +93,13 @@ */ public static String XMLRPC_URI = "xindice://"; public static String EMBED_URI = "xindice-embed://"; + public static String MANAGED_URI = "xindice-managed://"; + /** * Name used in the uri for collections associated with this instance. */ - public static String INSTANCE_NAME = "xindice, xindice-embed"; + public static String INSTANCE_NAME = "xindice, xindice-embed, xindice-managed"; /** * The XML:DB API Core Level Conformance of this implementation. @@ -212,14 +213,13 @@ * Since the user never sees the actual xmlrpc.DatabaseImpl object, * this is the only way to make sure that they can set that property. */ - Class driverClass - = Class.forName("org.apache.xindice.client.xmldb.xmlrpc.DatabaseImpl"); - Constructor constructor = driverClass.getConstructor( - new Class[]{CommonConfigurable.class}); - driver = (Database) constructor.newInstance(new Object[]{this}); + driver = new org.apache.xindice.client.xmldb.xmlrpc.DatabaseImpl(this); } else if (uri.startsWith(EMBED_URI)) { - driver = (Database) Class.forName("org.apache.xindice.client.xmldb.embed.DatabaseImpl").newInstance(); + driver = new org.apache.xindice.client.xmldb.embed.DatabaseImpl(); + } + else if (uri.startsWith(MANAGED_URI)) { + driver = new ManagedDatabaseImpl(); } } } 1.1 xml-xindice/java/src/org/apache/xindice/client/xmldb/managed/ManagedDatabaseImpl.java Index: ManagedDatabaseImpl.java =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xindice" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 1999-2001, The dbXML * Group, L.L.C., http://www.dbxmlgroup.com. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * $Id: ManagedDatabaseImpl.java,v 1.1 2003/07/09 16:35:12 kevinross Exp $ */ package org.apache.xindice.client.xmldb.managed; import java.io.FileNotFoundException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.xindice.client.xmldb.CommonConfigurable; import org.apache.xindice.client.xmldb.embed.CollectionImpl; import org.apache.xindice.core.Database; import org.apache.xindice.util.XindiceException; import org.xmldb.api.base.Collection; import org.xmldb.api.base.ErrorCodes; import org.xmldb.api.base.XMLDBException; /** * The xindice-managed is a xindice client driver that requires third party code * to create the database within the constraints of the client classloader. Typically * it is used in embebed environments where database creation is managed by third party * code. * * The driver will look for a database with the name passed in the constructor. If the no * argument constructor is used then the name defaults to 'db' though this can be changed * by setting [EMAIL PROTECTED] DATABASE_NAME_PROPERTY} property. * * This driver will throw an exception if the hasn't been registered. * * @author <a href="mailto:[EMAIL PROTECTED]">Kevin O'Neill</a> * * @version $Revision: 1.1 $ - $Date: 2003/07/09 16:35:12 $ */ public class ManagedDatabaseImpl extends CommonConfigurable implements org.xmldb.api.base.Database { /* prefix used to denote XML:DB URI's that should use this driver */ public static final String DRIVER_NAME = "xindice-managed"; public static final String DATABASE_NAME_PROPERTY = "xindice.drivers.managed.db"; /* XML:DB conformance level of this driver */ public static final String CONFORMANCE_LEVEL = "0"; public ManagedDatabaseImpl() throws FileNotFoundException, XindiceException { this(System.getProperty(DATABASE_NAME_PROPERTY, "db")); } public ManagedDatabaseImpl(String databaseName) throws FileNotFoundException, XindiceException { this.db = Database.getDatabase(databaseName); if (null == db) { log.fatal("The database " + databaseName + " has not been created."); throw new XindiceException("The " + getName() + " driver requires that the database instance be created and available in the JVM"); } } private Log log = LogFactory.getLog(getClass()); protected Database db; /* (non-Javadoc) * @see org.xmldb.api.base.Database#getName() */ public String getName() { return DRIVER_NAME; } /** * Retrieves a <code>Collection</code> instance based on the URI provided * in the <code>uri</code> parameter. The format of the URI is defined in the * documentation for DatabaseManager.getCollection().<p/> */ public Collection getCollection(String uri, String username, String password) throws XMLDBException { if (!acceptsURI(uri)) { throw new XMLDBException(ErrorCodes.INVALID_URI, "Invalid URL: " + uri); } /* Chop off driver prefix, and '://' */ uri = uri.substring(getName().length() + 3); /* Extract host name & port, if present */ int firstSlash = uri.indexOf('/'); if (firstSlash == -1) { throw new XMLDBException(ErrorCodes.INVALID_URI); } String collPath = uri.substring(firstSlash); // The path must start with a / if (collPath.startsWith("/")) { // find the database name. We just skip the first slash int colIndex = collPath.indexOf('/', 1); // We assume there's no collection specified String colName = "/"; // if colIndex isn't -1 then we need to pick out the db and collection if (colIndex != -1) { // The rest of the name locates the collection colName = collPath.substring(colIndex); if (colName.equals("")) { colName = "/"; } } try { return new CollectionImpl(db, colName); } catch (XMLDBException xmldbe) { if (xmldbe.errorCode == ErrorCodes.NO_SUCH_COLLECTION) { return null; } else { throw xmldbe; } } } else { throw new XMLDBException(ErrorCodes.INVALID_URI, "Collection name must begin with a '/'"); } } public boolean acceptsURI(String uri) throws XMLDBException { return ((uri != null) && uri.startsWith(getName() + "://")); } public String getConformanceLevel() throws XMLDBException { return CONFORMANCE_LEVEL; } } 1.9 +24 -34 xml-xindice/java/src/org/apache/xindice/client/xmldb/embed/DatabaseImpl.java Index: DatabaseImpl.java =================================================================== RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/client/xmldb/embed/DatabaseImpl.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- DatabaseImpl.java 14 Mar 2003 10:24:18 -0000 1.8 +++ DatabaseImpl.java 9 Jul 2003 16:35:12 -0000 1.9 @@ -63,6 +63,7 @@ import org.apache.xindice.core.Database; import org.apache.xindice.server.Xindice; import org.apache.xindice.util.Configuration; +import org.apache.xindice.util.ReadOnlyException; import org.apache.xindice.util.XindiceException; import org.apache.xindice.xml.dom.DOMParser; @@ -107,11 +108,23 @@ * use the Configurable interface and only create the database when the * getCollection method is called. */ - public DatabaseImpl() - throws FileNotFoundException, - XindiceException { + public DatabaseImpl() throws FileNotFoundException, XindiceException { Configuration config; + config = loadConfiguration(); + this.db = Database.getDatabase(config); + + if (null == this.db) { + log.fatal("Unable to configure database"); + + throw new XindiceException("Unable to configure database"); + } else if (log.isInfoEnabled()) { + log.info("Database name: '" + this.db.getName() + "'"); + } + } + + protected Configuration loadConfiguration() throws FileNotFoundException, XindiceException, ReadOnlyException { + Configuration config; String configFile = System.getProperty(Xindice.PROP_XINDICE_CONFIGURATION); if (configFile != null && !configFile.equals("")) { if (log.isInfoEnabled()) { @@ -120,8 +133,7 @@ FileInputStream configXMLFile = new FileInputStream(new File(configFile)); config = new Configuration(DOMParser.toDocument(configXMLFile), false); - } - else { + } else { if (log.isInfoEnabled()) { log.info("No configuration file specified, going with the default configuration"); } @@ -129,21 +141,7 @@ } config = config.getChild("root-collection", false); - - /* First try to find an existing Database by name. If it doesn't exist, - * we create one and in both cases we configure them with the current - * configuration */ - String dbname = config.getAttribute(Database.NAME); - - this.db = Database.getDatabase(dbname); - if (this.db == null) { - this.db = new Database(); - } - - if (log.isInfoEnabled()) { - log.info("Database name: '" + dbname + "'"); - } - db.setConfig(config); + return config; } /** @@ -187,14 +185,11 @@ * <code>ErrroCodes.PERMISSION_DENIED</code> If the <code>username</code> * and <code>password</code> were not accepted by the database. */ - public Collection getCollection(String uri, String userName, String password) - throws XMLDBException { - + public Collection getCollection(String uri, String userName, String password) throws XMLDBException { /* TODO: introduce authentication some day */ if (!acceptsURI(uri)) { - throw new XMLDBException(ErrorCodes.INVALID_URI, "Invalid URL: " - + uri); + throw new XMLDBException(ErrorCodes.INVALID_URI, "Invalid URL: " + uri); } /* Chop off driver prefix, and '://' */ @@ -231,18 +226,15 @@ try { return new CollectionImpl(db, colName); - } - catch(XMLDBException e) { + } catch (XMLDBException e) { if(e.errorCode == ErrorCodes.NO_SUCH_COLLECTION) { // per getCollection contract, return null if not found return null; } throw e; } - } - else { - throw new XMLDBException(ErrorCodes.INVALID_URI, - "Collection name must begin with a '/'" ); + } else { + throw new XMLDBException(ErrorCodes.INVALID_URI, "Collection name must begin with a '/'"); } } @@ -256,7 +248,6 @@ * specific errors that occur.<br /> */ public String getName() throws XMLDBException { - return DRIVER_NAME; } @@ -271,7 +262,6 @@ * specific errors that occur.<br /> */ public String getConformanceLevel() throws XMLDBException { - return CONFORMANCE_LEVEL; }