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;
}