/*
* Portions of this file Copyright 1999-2005 University of Chicago
* Portions of this file Copyright 1999-2005 The University of Southern California.
*
* This file or a portion of this file is licensed under the
* terms of the Globus Toolkit Public License, found at
* http://www.globus.org/toolkit/download/license.html.
* If you redistribute this file, with or without
* modifications, you must include this notice in the file.
*/
package org.globus.mds.bigindex.impl.database.xml.xindice;
import org.globus.wsrf.utils.PerformanceLog;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.Date;
import java.util.Calendar;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.axis.message.MessageElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock;
/**
*
*/
public class XindiceIndexDatabase
{
static Log logger =
LogFactory.getLog(XindiceIndexDatabase.class.getName());
static PerformanceLog performanceLogger =
new PerformanceLog(
XindiceIndexDatabase.class.getName() + ".performance");
private static final String BASE_COLLECTION_NAME = "bigindex-service";
private static final String METADATA_TAG = "document-metadata";
private static final String DEFAULT_ELEMENT_INDEX_NAME = "defaultElementIndex";
private static final String DEFAULT_ATTRIB_INDEX_NAME = "defaultAttributeIndex";
private String rootURI = "xindice-embed:///db";
private String baseURI = rootURI + "/" + this.BASE_COLLECTION_NAME;
private String rootCollectionName;
private String defaultElementIndexPattern = null;
private String defaultAttributeIndexPattern = null;
private XindiceDriver db = null;
private boolean isDebug = logger.isDebugEnabled();
private boolean isLocal = true;
private boolean addAsString = true;
private boolean isProfiling = true;
private boolean indexAdded = false;
private ReentrantWriterPreferenceReadWriteLock rwLock =
new ReentrantWriterPreferenceReadWriteLock();
public XindiceIndexDatabase(String collectionName) throws Exception
{
this.init(collectionName,null);
}
public XindiceIndexDatabase(String collectionName, String dbURI)
throws Exception
{
this.init(collectionName, dbURI);
}
protected void init(String collectionName, String dbURI)
{
try
{
if ((dbURI != null) && (dbURI.length()>0)) {
this.setDatabaseURI(dbURI);
}
this.db = new XindiceDriver(this.isLocal);
this.db.setProfiling(true);
this.db.setVerbose(false);
this.initializeCollection(collectionName, true, true);
}
catch (Exception e)
{
logger.warn("Exception while initializing Xindice database: " + e);
}
}
private void setDatabaseURI(String dbURI) throws Exception
{
if ((dbURI != null) || (dbURI.length()!=0)) {
this.rootURI = dbURI;
}
if (this.rootURI.startsWith("xindice-embed:")) {
this.isLocal = true;
} else {
this.isLocal = false;
}
this.baseURI = this.rootURI + "/" + this.BASE_COLLECTION_NAME;
}
private void initializeCollection(String collectionName,
boolean createDefaultIndex,
boolean replaceExisting)
throws Exception
{
try
{
if (this.isProfiling) {
this.performanceLogger.start();
}
String colURI = this.baseURI + "/" + collectionName;
if (!this.db.findCollection(this.rootURI,
this.BASE_COLLECTION_NAME)) {
synchronized(this.db) {
this.db.createCollection(this.rootURI,
this.BASE_COLLECTION_NAME);
}
this.db.checkpointCollection(
this.rootURI + "/" + this.BASE_COLLECTION_NAME);
}
synchronized(this.db)
{
boolean create = true;
if (this.db.findCollection(this.baseURI, collectionName)) {
if (replaceExisting) {
this.db.dropCollection(this.baseURI, collectionName);
} else {
create = false;
}
}
if (create) {
this.db.createCollection(this.baseURI, collectionName);
}
}
this.db.checkpointCollection(colURI);
this.rootCollectionName = collectionName;
}
finally
{
if (this.isProfiling) {
this.performanceLogger.stop("initializeCollection");
}
}
}
public void checkpointCollection(String colURI) throws Exception
{
try
{
this.rwLock.writeLock().acquire();
this.db.checkpointCollection(colURI);
}
finally
{
this.rwLock.writeLock().release();
}
}
public String createID(String parentCol) throws Exception
{
return this.db.createUniqueID(parentCol);
}
public String getDefaultCollectionURI()
{
return this.getCollectionURI(null);
}
public String getCollectionURI(String colName)
{
String URI = this.baseURI + "/" + this.rootCollectionName;
if ((colName != null) &&
(colName.length()>0))
{
try
{
if (this.isProfiling) {
this.performanceLogger.start();
}
if (!this.db.findCollection(URI, colName)) {
synchronized(this.db) {
this.db.createCollection(URI, colName);
}
this.db.checkpointCollection(URI + "/" + colName);
}
URI += "/" + colName;
}
catch (Exception e)
{
logger.error("Exception getting current collection uri: " + e);
}
finally
{
if (this.isProfiling) {
this.performanceLogger.stop("getCurrentCollectionURI");
}
}
}
return URI;
}
public String addDocument(String collectionURI,
String docName,
Object doc,
boolean asString)
throws Exception
{
String docID = collectionURI + "/";
try {
rwLock.writeLock().acquire();
if (this.isProfiling) {
this.performanceLogger.start();
}
if (asString)
{
docID = docID +
this.db.addDocumentString(collectionURI, (String)doc, docName);
if (this.isProfiling) {
this.performanceLogger.stop("addData(string) " + docName);
}
}
else
{
docID = docID +
this.db.addDocumentDOM(collectionURI, (Node)doc, docName);
if (this.isProfiling) {
this.performanceLogger.stop("addData(node) " + docName);
}
}
this.db.checkpointCollection(collectionURI);
this.addDefaultIndexers(collectionURI);
}
finally
{
rwLock.writeLock().release();
}
return docID;
}
public Object getDocument(String colURI,
String docName,
boolean asString)
throws Exception
{
Object result;
if (this.isProfiling) {
this.performanceLogger.start();
}
if (asString)
{
result = this.db.getDocumentAsString(colURI, docName);
if (this.isProfiling) {
this.performanceLogger.stop("getData(string)");
}
}
else
{
result = this.db.getDocumentAsDOM(colURI, docName);
if (result instanceof Document) {
result = ((Document)result).getDocumentElement();
}
if (this.isProfiling) {
this.performanceLogger.stop("getData(node)");
}
}
return result;
}
public void removeDocument(String collectionURI,
String docName)
throws Exception
{
try {
rwLock.writeLock().acquire();
if (this.isProfiling) {
this.performanceLogger.start();
}
this.db.deleteDocument(collectionURI, docName);
if (this.isProfiling) {
this.performanceLogger.stop("removeDocument " + docName);
}
} finally {
rwLock.writeLock().release();
}
}
public List query(String xpath, String[] namespaces)
throws Exception
{
if (this.isProfiling) {
this.performanceLogger.start();
}
String URI = this.baseURI + "/" + this.rootCollectionName;
ArrayList results = new ArrayList();
if (!this.db.findCollection(this.baseURI, this.rootCollectionName)) {
if (logger.isDebugEnabled()) {
logger.debug("Could not find collection: " + this.rootCollectionName);
}
return results;
}
try {
rwLock.readLock().acquire();
Object[] queryResults =
this.db.XPathQuery(URI,
xpath,
namespaces,
XindiceDriver.XINDICE_DOCTYPE_DOM);
if (queryResults != null) {
for (int i=0;i<queryResults.length;i++) {
results.add(
new MessageElement(
((Document)queryResults[i]).getDocumentElement()));
}
}
if (this.isProfiling) {
this.performanceLogger.stop("query");
}
} finally {
rwLock.readLock().release();
}
return results;
}
public void setDefaultElementIndexPattern(String pattern) {
this.defaultElementIndexPattern = pattern;
}
public String getDefaultElementIndexPattern() {
return this.defaultElementIndexPattern;
}
public void setDefaultAttributeIndexPattern(String pattern) {
this.defaultAttributeIndexPattern = pattern;
}
public String getDefaultAttributeIndexPattern() {
return this.defaultAttributeIndexPattern;
}
private synchronized void addDefaultIndexers(String colURI) throws Exception
{
if (this.indexAdded) {
return;
}
if (this.defaultElementIndexPattern != null) {
this.db.addIndexer(colURI,
DEFAULT_ELEMENT_INDEX_NAME,
null,
this.defaultElementIndexPattern);
this.indexAdded = true;
}
if (this.defaultAttributeIndexPattern != null) {
this.db.addIndexer(colURI,
DEFAULT_ATTRIB_INDEX_NAME,
null,
this.defaultAttributeIndexPattern);
this.indexAdded = true;
}
}
public void finalize() {
try {
this.db.shutdown(baseURI);
} catch (Exception e) {
logger.warn("Exception while performing database shutdown: " + e);
}
}
public void destroy() throws Exception
{
try
{
if (this.isProfiling) {
this.performanceLogger.start();
}
this.db.dropCollection(this.baseURI, this.rootCollectionName);
}
finally
{
if (this.isProfiling) {
this.performanceLogger.stop("destroy");
}
}
}
}