You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xindice-dev@xml.apache.org by vg...@apache.org on 2004/02/06 14:05:56 UTC
cvs commit: xml-xindice/java/src/org/apache/xindice/client/xmldb/embed DatabaseImpl.java
vgritsenko 2004/02/06 05:05:56
Modified: . status.xml
config system.xml
java/src/org/apache/xindice/client/xmldb/embed
DatabaseImpl.java
Log:
Support multiple databases (embed driver only)
Revision Changes Path
1.26 +6 -1 xml-xindice/status.xml
Index: status.xml
===================================================================
RCS file: /home/cvs/xml-xindice/status.xml,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- status.xml 2 Feb 2004 14:36:19 -0000 1.25
+++ status.xml 6 Feb 2004 13:05:56 -0000 1.26
@@ -59,7 +59,12 @@
</todo>
<changes>
- <release version="1.1b4-dev" date="February 2 2004">
+ <release version="1.1b4-dev" date="February 6 2004">
+ <action dev="VG" type="update">
+ Embedded driver supports two configuration variables (see javadoc
+ for details), and multiple database instances (see system.xml for an
+ example).
+ </action>
<action dev="VG" type="update">
Add max-descriptors configuration attribute to all Filer implementations
based on Paged. Default value is 16 file descriptors (same as before).
1.15 +19 -5 xml-xindice/config/system.xml
Index: system.xml
===================================================================
RCS file: /home/cvs/xml-xindice/config/system.xml,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- system.xml 30 Dec 2003 13:07:38 -0000 1.14
+++ system.xml 6 Feb 2004 13:05:56 -0000 1.15
@@ -9,12 +9,13 @@
<xindice>
<!--
- - Defines the database instance. This release supports only one
- - database instance. Attributes:
+ - Defines the database instance. Xindice server in servlet mode currently
+ - supports only one database instance. Attributes:
- dbroot:
- - Identifies location of the database.
+ - Identifies location of the database. Relative paths will be
+ - resolved depending on mode of operation.
- name:
- - Name of the database instance,
+ - Name of the database instance.
- use-metadata:
- When set to 'on', enables external metadata facilities
- for this database instance.
@@ -30,6 +31,19 @@
</filer>
-->
+ <!--
+ - Query Engine Configuration.
+ -->
+ <queryengine>
+ <resolver autoindex="false" class="org.apache.xindice.core.query.XPathQueryResolver"/>
+ <resolver class="org.apache.xindice.core.xupdate.XUpdateQueryResolver"/>
+ </queryengine>
+ </root-collection>
+
+ <!--
+ - Embedded driver suuports several DB instances.
+ -->
+ <root-collection dbroot="./db2/" name="db2" use-metadata="off">
<queryengine>
<resolver autoindex="false" class="org.apache.xindice.core.query.XPathQueryResolver"/>
<resolver class="org.apache.xindice.core.xupdate.XUpdateQueryResolver"/>
1.23 +169 -75 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.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- DatabaseImpl.java 22 Jan 2004 03:23:37 -0000 1.22
+++ DatabaseImpl.java 6 Feb 2004 13:05:56 -0000 1.23
@@ -66,6 +66,8 @@
import org.apache.xindice.server.Xindice;
import org.apache.xindice.util.Configuration;
import org.apache.xindice.util.XindiceException;
+import org.apache.xindice.util.XindiceRuntimeException;
+import org.apache.xindice.util.ReadOnlyException;
import org.apache.xindice.xml.dom.DOMParser;
import org.xmldb.api.base.Collection;
@@ -75,14 +77,41 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.FileNotFoundException;
/**
- * implements XML:DB's <code>Database</code> interface providing
- * embedded access to a Xindice database.
+ * Implements XML:DB's <code>Database</code> interface providing embedded access to
+ * a Xindice database. Usually, this class is not used
+ * directly, use {@link org.apache.xindice.client.xmldb.DatabaseImpl} instead.
+ *
+ * Embedded database driver supports multiple database instances simultaneously. To use
+ * multiple instances, use several instances of this driver with different values for
+ * the Xindice DB Name property.
+ *
+ * Embedded database driver uses following configuration parameters:
+ * <ul>
+ * <li>Xindice DB Home</li>
+ * <li>Xindice Configuration</li>
+ * </ul>
+ *
+ * These parameters can be specified either:
+ * <ul>
+ * <li>by instantiating {@link org.apache.xindice.client.xmldb.DatabaseImpl}
+ * and setting its properties (see {@link #setProperty}). You don't need to use
+ * this class directly in this case.</li>
+ * <li>by setting Java system properties (see {@link System#setProperty(String, String)})</li>
+ * <li>by using constructor {@link DatabaseImpl#DatabaseImpl(CommonConfigurable)} and
+ * passing instance of CommonConfigurable with all properties already set.</li>
+ * <li>by using {@link #setProperty} <strong>before</strong> calling
+ * {@link #getCollection(String, String, String)}.</li>
+ *
+ * These properties are used in the getCollection method, and changes in those properties will
+ * not affect this instance of the driver after collection is obtained.
*
* @author <a href="mailto:kstaken@xmldatabases.org">Kimbro Staken</a>
* @author <a href="mailto:james.bates@amplexor.com">James Bates</a>
* @author <a href="mailto:vladimir@apache.org">Vladimir R. Bossicard</a>
+ * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
* @version CVS $Revision$, $Date$
*/
public class DatabaseImpl extends CommonConfigurable implements org.xmldb.api.base.Database {
@@ -90,6 +119,26 @@
private static final Log log = LogFactory.getLog(DatabaseImpl.class);
/**
+ * Driver property name for the xindice database home.
+ */
+ private static final String PROP_XINDICE_DB_HOME = "db-home";
+
+ /**
+ * System property name for the xindice database home.
+ */
+ private static final String SYSPROP_XINDICE_DB_HOME = Xindice.PROP_XINDICE_DB_HOME;
+
+ /**
+ * Driver property name for the xindice configuration file.
+ */
+ private static final String PROP_XINDICE_CONFIGURATION = "configuration";
+
+ /**
+ * Driver property name for the xindice configuration file.
+ */
+ private static final String SYSPROP_XINDICE_CONFIGURATION = Xindice.PROP_XINDICE_CONFIGURATION;
+
+ /**
* Prefix used to denote XML:DB URI's that should use this driver
*/
public static final String DRIVER_NAME = "xindice-embed";
@@ -99,18 +148,18 @@
*/
private static final String CONFORMANCE_LEVEL = "0";
+
/**
- * Database instance
+ * Database configuration location.
+ * Null if built-in configuration was used.
*/
- private Database database;
+ private String configFile;
+
/**
- * Creates new <code>DatabaseImpl</code> instance. The configuration is
- * loaded from the file defined in the PROP_XINDICE_CONFIGURATION system
- * variable.
+ * Creates new <code>DatabaseImpl</code> instance.
*/
- public DatabaseImpl() throws IOException, XindiceException {
- init();
+ public DatabaseImpl() {
}
/**
@@ -119,101 +168,151 @@
*
* This allows to pass properties such as PROP_XINDICE_CONFIGURATION
* to this instance. Usually this is done by instantiating not this
- * class, but <code>org.apache.xindice.client.xmldb.DatabaseImpl</code>,
+ * class, but {@link org.apache.xindice.client.xmldb.DatabaseImpl},
* set all the necessary parameters, and then get a collection.
*
* @param config from which the initial parameters for this
* DatabaseImpl object are copied.
*/
- public DatabaseImpl(CommonConfigurable config) throws IOException, XindiceException {
+ public DatabaseImpl(CommonConfigurable config) {
super(config);
- init();
}
/**
- * Init this database instance.
- *
- * This is only a temporarly solution since the question of a new init
- * method is raised in the xmldb:api group. Another solution could be to
- * use the Configurable interface and only create the database when the
- * getCollection method is called.
+ * Get named database instance. If database is not loaded yet, load it.
*
- * @throws IOException
- * @throws XindiceException
+ * @throws XMLDBException if configuration for this database is not found,
+ * or could not be read.
*/
- private void init() throws IOException, XindiceException {
- Configuration config = loadConfiguration();
+ private Database getDatabase(String dbName, String uri) throws XMLDBException {
+ Database database = Database.getDatabase(dbName);
+ if (database == null) {
+ Configuration dbConfig = getConfiguration(dbName);
+ if (log.isDebugEnabled()) {
+ log.debug("Mounting database: '" + dbName + "'");
+ }
- this.database = Database.getDatabase(config);
- if (null == this.database) {
- log.fatal("Unable to configure database");
- throw new XindiceException("Unable to configure database");
- }
+ if (dbConfig == null) {
+ throw new XMLDBException(ErrorCodes.NO_SUCH_DATABASE,
+ "Database '" + dbName + "' not found: " + uri);
+ }
- if (log.isDebugEnabled()) {
- log.info("Database name: '" + this.database.getName() + "'");
+ database = Database.getDatabase(dbConfig);
+ if (log.isDebugEnabled()) {
+ log.info("Mounted database: '" + database.getName() + "'");
+ }
}
- }
-
- protected Configuration loadConfiguration() throws IOException, XindiceException {
- Configuration config;
- String configDir = null;
- String configFile = null;
- try {
- // Try configuration first
- configFile = getProperty(Xindice.PROP_XINDICE_CONFIGURATION);
- } catch (XMLDBException ignored) {
- }
- if (configFile == null) {
- // Fallback to system property
- configFile = System.getProperty(Xindice.PROP_XINDICE_CONFIGURATION);
- }
+ return database;
+ }
- if (configFile != null && !configFile.equals("")) {
- if (log.isInfoEnabled()) {
- log.info("Specified configuration file: '" + configFile + "'");
- }
- FileInputStream configXMLFile = new FileInputStream(configFile);
+ /**
+ * Get configuration for the named database
+ */
+ protected Configuration getConfiguration(String dbName) throws XMLDBException {
+ Configuration config = loadConfiguration();
- config = new Configuration(DOMParser.toDocument(configXMLFile), false);
- configDir = new File(configFile).getAbsoluteFile().getParent();
- } else {
- if (log.isInfoEnabled()) {
- log.info("No configuration file specified, going with the default configuration");
+ // Find database config with the given database name
+ Configuration[] roots = config.getChildren("root-collection");
+ config = null;
+ for (int i = 0; i < roots.length; i++) {
+ if (dbName.equals(roots[i].getAttribute(Database.NAME))) {
+ config = roots[i];
+ break;
}
-
- config = new Configuration(DOMParser.toDocument(Xindice.DEFAULT_CONFIGURATION), false);
}
- config = config.getChild("root-collection", false);
+ if (config == null) {
+ return null;
+ }
+ // Figure out database root
String dbRoot = config.getAttribute(Database.DBROOT, Database.DBROOT_DEFAULT);
if (!new File(dbRoot).isAbsolute()) {
- // Let's see if the property was specified.
+ // Let's see if the XINDICE_DB_HOME property was specified.
String home = null;
try {
// Try configuration first
- home = getProperty(Xindice.PROP_XINDICE_DB_HOME);
+ home = getProperty(PROP_XINDICE_DB_HOME);
} catch (XMLDBException ignored) {
}
if (home == null) {
// Fallback to system property
- home = System.getProperty(Xindice.PROP_XINDICE_DB_HOME);
+ home = System.getProperty(SYSPROP_XINDICE_DB_HOME);
}
if (home != null) {
- dbRoot = new File(home + File.separator + dbRoot).getCanonicalPath();
- } else if (configDir != null) {
- dbRoot = configDir + File.separator + dbRoot;
+ try {
+ dbRoot = new File(home + File.separator + dbRoot).getCanonicalPath();
+ } catch (IOException e) {
+ log.warn("getCanonicalPath failed", e);
+ dbRoot = new File(home + File.separator + dbRoot).getAbsolutePath();
+ }
+ } else if (configFile != null) {
+ dbRoot = new File(configFile).getAbsoluteFile().getParent() + File.separator + dbRoot;
} else {
log.warn("The database configuration file is not specified and there was no "
- + Xindice.PROP_XINDICE_DB_HOME + " property set, "
+ + SYSPROP_XINDICE_DB_HOME + " property set, "
+ "so Xindice was unable to determine a database location. "
+ "Database will be created relative to the current directory.");
- dbRoot = new File("." + File.separator + dbRoot).getCanonicalPath();
+ try {
+ dbRoot = new File("." + File.separator + dbRoot).getCanonicalPath();
+ } catch (IOException e) {
+ log.warn("getCanonicalPath failed", e);
+ dbRoot = new File("." + File.separator + dbRoot).getAbsolutePath();
+ }
+ }
+ try {
+ config.setAttribute(Database.DBROOT, dbRoot);
+ } catch (ReadOnlyException ignore) {
+ }
+ }
+
+ return config;
+ }
+
+ private Configuration loadConfiguration() throws XMLDBException {
+ Configuration config;
+
+ if (configFile == null) {
+ try {
+ // Try configuration first
+ configFile = getProperty(PROP_XINDICE_CONFIGURATION);
+ } catch (XMLDBException ignored) {
+ }
+ if (configFile == null) {
+ // Fallback to system property
+ configFile = System.getProperty(SYSPROP_XINDICE_CONFIGURATION);
+ }
+ if ("".equals(configFile)) {
+ configFile = null;
+ }
+ }
+
+ if (configFile != null) {
+ if (log.isInfoEnabled()) {
+ log.info("Specified configuration file: '" + configFile + "'");
+ }
+ try {
+ FileInputStream configXMLFile = new FileInputStream(configFile);
+ config = new Configuration(DOMParser.toDocument(configXMLFile), false);
+ } catch (XindiceException e) {
+ throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR,
+ "Unable to parse database configuration file: " + configFile, e);
+ } catch (FileNotFoundException e) {
+ throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR,
+ "Database configuration file not found: " + configFile);
+ }
+ } else {
+ if (log.isInfoEnabled()) {
+ log.info("No configuration file specified, going with the default configuration");
+ }
+
+ try {
+ config = new Configuration(DOMParser.toDocument(Xindice.DEFAULT_CONFIGURATION), false);
+ } catch (XindiceException e) {
+ throw new XindiceRuntimeException("Unable to parse default database configuration", e);
}
- config.setAttribute(Database.DBROOT, dbRoot);
}
return config;
@@ -302,17 +401,12 @@
}
}
- // TODO: Is this correct behavior?
- if (!database.getName().equals(dbName)) {
- throw new XMLDBException(ErrorCodes.NO_SUCH_DATABASE,
- "Unknown database (must be '" + database.getName() + "'): " + uri);
- }
-
+ Database database = getDatabase(dbName, uri);
try {
return new CollectionImpl(database, colName);
} catch (XMLDBException e) {
if (e.errorCode == ErrorCodes.NO_SUCH_COLLECTION) {
- // per getCollection contract, return null if not found
+ // Per getCollection contract, return null if not found
return null;
}
throw e;