diff --git a/src/org/exist/collections/CollectionConfigurationManager.java b/src/org/exist/collections/CollectionConfigurationManager.java index 074cda5d8cc..2ae2e8134a3 100644 --- a/src/org/exist/collections/CollectionConfigurationManager.java +++ b/src/org/exist/collections/CollectionConfigurationManager.java @@ -1,6 +1,6 @@ /* * eXist Open Source Native XML Database - * Copyright (C) 2001-2012 The eXist Project + * Copyright (C) 2001-2014 The eXist Project * http://exist-db.org * * This program is free software; you can redistribute it and/or @@ -16,8 +16,6 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * $Id$ */ package org.exist.collections; @@ -26,7 +24,6 @@ import org.exist.dom.DocumentImpl; import org.exist.memtree.SAXAdapter; import org.exist.security.PermissionDeniedException; -import org.exist.storage.BrokerPool; import org.exist.storage.DBBroker; import org.exist.storage.IndexSpec; import org.exist.storage.lock.Lock; @@ -48,100 +45,109 @@ * Manages index configurations. Index configurations are stored in a collection * hierarchy below /db/system/config. CollectionConfigurationManager is called * by {@link org.exist.collections.Collection} to retrieve the - * {@link org.exist.collections.CollectionConfiguration} instance for a given collection. + * {@link org.exist.collections.CollectionConfiguration} instance for a given + * collection. * * @author wolf */ public class CollectionConfigurationManager { - private static final Logger LOG = Logger.getLogger(CollectionConfigurationManager.class); + private static final Logger LOG = Logger.getLogger(CollectionConfigurationManager.class); public final static String CONFIG_COLLECTION = XmldbURI.SYSTEM_COLLECTION + "/config"; /** /db/system/config **/ public final static XmldbURI CONFIG_COLLECTION_URI = XmldbURI.create(CONFIG_COLLECTION); - //TODO : create using resolve() + // TODO : create using resolve() /** /db/system/config/db **/ public final static XmldbURI ROOT_COLLECTION_CONFIG_URI = CONFIG_COLLECTION_URI.append(XmldbURI.ROOT_COLLECTION_NAME); - + public final static String COLLECTION_CONFIG_FILENAME = "collection.xconf"; public final static CollectionURI COLLECTION_CONFIG_PATH = new CollectionURI(CONFIG_COLLECTION_URI.getRawCollectionPath()); - + private Map configurations = new HashMap(); private Object latch; private CollectionConfiguration defaultConfig; - private BrokerPool pool; - public CollectionConfigurationManager(DBBroker broker) throws EXistException, CollectionConfigurationException, PermissionDeniedException, LockException { - this.pool = broker.getBrokerPool(); - this.latch = pool.getCollectionsCache(); - + this.latch = broker.getBrokerPool().getCollectionsCache(); + checkCreateCollection(broker, CONFIG_COLLECTION_URI); checkCreateCollection(broker, ROOT_COLLECTION_CONFIG_URI); - + loadAllConfigurations(broker); defaultConfig = new CollectionConfiguration(broker.getBrokerPool()); defaultConfig.setIndexConfiguration(broker.getIndexConfiguration()); } /** - * Add a new collection configuration. The XML document is passed as a string. - * - * @param transaction The transaction that will hold the WRITE locks until they are released by commit()/abort() + * Add a new collection configuration. The XML document is passed as a + * string. + * + * @param txn + * The transaction that will hold the WRITE locks until they are + * released by commit()/abort() * @param broker - * @param collection the collection to which the configuration applies. - * @param config the xconf document as a String. - * @throws CollectionConfigurationException - */ - public void addConfiguration(Txn transaction, DBBroker broker, Collection collection, String config) throws CollectionConfigurationException { + * @param collection + * the collection to which the configuration applies. + * @param config + * the xconf document as a String. + * @throws CollectionConfigurationException + */ + public void addConfiguration(Txn txn, DBBroker broker, Collection collection, String config) throws CollectionConfigurationException { try { - //TODO : use XmldbURI.resolve() ! - final XmldbURI path = CONFIG_COLLECTION_URI.append(collection.getURI()); - - final Collection confCol = broker.getOrCreateCollection(transaction, path); - if(confCol == null) - {throw new CollectionConfigurationException("Failed to create config collection: " + path);} - - XmldbURI configurationDocumentName = null; - //Replaces the current configuration file if there is one + final XmldbURI path = CONFIG_COLLECTION_URI.append(collection.getURI()); + + final Collection confCol = broker.getOrCreateCollection(txn, path); + if (confCol == null) { + throw new CollectionConfigurationException("Failed to create config collection: " + path); + } + + XmldbURI configurationDocumentName = null; + // Replaces the current configuration file if there is one final CollectionConfiguration conf = getConfiguration(broker, collection); if (conf != null) { configurationDocumentName = conf.getDocName(); - if (configurationDocumentName != null) - {LOG.warn("Replacing current configuration file '" + configurationDocumentName + "'");} + if (configurationDocumentName != null) { + LOG.warn("Replacing current configuration file '" + configurationDocumentName + "'"); + } + } + if (configurationDocumentName == null) { + configurationDocumentName = CollectionConfiguration.DEFAULT_COLLECTION_CONFIG_FILE_URI; } - if (configurationDocumentName == null) - {configurationDocumentName = CollectionConfiguration.DEFAULT_COLLECTION_CONFIG_FILE_URI;} - - broker.saveCollection(transaction, confCol); - final IndexInfo info = confCol.validateXMLResource(transaction, broker, configurationDocumentName, config); - //TODO : unlock the collection here ? - confCol.store(transaction, broker, info, config, false); - //broker.sync(Sync.MAJOR_SYNC); + + broker.saveCollection(txn, confCol); + final IndexInfo info = confCol.validateXMLResource(txn, broker, configurationDocumentName, config); + // TODO : unlock the collection here ? + confCol.store(txn, broker, info, config, false); + // broker.sync(Sync.MAJOR_SYNC); synchronized (latch) { configurations.remove(new CollectionURI(path.getRawCollectionPath())); loadConfiguration(broker, confCol); } } catch (final CollectionConfigurationException e) { - throw e; + throw e; } catch (final Exception e) { - throw new CollectionConfigurationException("Failed to store collection configuration: " + e.getMessage(), e); - } + throw new CollectionConfigurationException("Failed to store collection configuration: " + e.getMessage(), e); + } } /** - * Check the passed collection configuration. Throws an exception if errors are detected in the - * configuration document. Note: some configuration settings depend on the current environment, in particular - * the availability of trigger or index classes. - * - * @param broker DBBroker - * @param config the configuration to test - * @throws CollectionConfigurationException if errors were detected + * Check the passed collection configuration. Throws an exception if errors + * are detected in the configuration document. Note: some configuration + * settings depend on the current environment, in particular the + * availability of trigger or index classes. + * + * @param broker + * DBBroker + * @param config + * the configuration to test + * @throws CollectionConfigurationException + * if errors were detected */ public void testConfiguration(DBBroker broker, String config) throws CollectionConfigurationException { try { @@ -165,7 +171,7 @@ public void testConfiguration(DBBroker broker, String config) throws CollectionC public List getCustomIndexSpecs(String customIndexId) { List configs = new ArrayList(10); synchronized (latch) { - for (CollectionConfiguration config: configurations.values()) { + for (CollectionConfiguration config : configurations.values()) { IndexSpec spec = config.getIndexConfiguration(); if (spec != null) { Object customConfig = spec.getCustomIndexSpec(customIndexId); @@ -179,9 +185,9 @@ public List getCustomIndexSpecs(String customIndexId) { } /** - * Retrieve the collection configuration instance for the given collection. This - * creates a new CollectionConfiguration object and recursively scans the collection - * hierarchy for available configurations. + * Retrieve the collection configuration instance for the given collection. + * This creates a new CollectionConfiguration object and recursively scans + * the collection hierarchy for available configurations. * * @param broker * @param collection @@ -189,24 +195,25 @@ public List getCustomIndexSpecs(String customIndexId) { * @throws CollectionConfigurationException */ protected CollectionConfiguration getConfiguration(DBBroker broker, Collection collection) throws CollectionConfigurationException { - - final CollectionURI path = new CollectionURI(COLLECTION_CONFIG_PATH); + + final CollectionURI path = new CollectionURI(COLLECTION_CONFIG_PATH); path.append(collection.getURI().getRawCollectionPath()); - /* - * This used to go from the root collection (/db), and continue all the - * way to the end of the path, checking each collection on the way. I - * modified it to start at the collection path and work its way back to - * the root, stopping at the first config file it finds. This should be - * more efficient, and fit more appropriately will the XmldbURI api - */ + /* + * This used to go from the root collection (/db), and continue all the + * way to the end of the path, checking each collection on the way. I + * modified it to start at the collection path and work its way back to + * the root, stopping at the first config file it finds. This should be + * more efficient, and fit more appropriately will the XmldbURI api + */ CollectionConfiguration conf; synchronized (latch) { - while(!path.equals(COLLECTION_CONFIG_PATH)) { + while (!path.equals(COLLECTION_CONFIG_PATH)) { conf = configurations.get(path); - if (conf != null) - {return conf;} + if (conf != null) { + return conf; + } path.removeLastSegment(); } } @@ -219,37 +226,42 @@ protected void loadAllConfigurations(DBBroker broker) throws CollectionConfigura loadAllConfigurations(broker, root); } - protected void loadAllConfigurations(DBBroker broker, Collection configCollection) throws CollectionConfigurationException, PermissionDeniedException, LockException { - if (configCollection == null) - {return;} + protected void loadAllConfigurations(DBBroker broker, Collection configCollection) throws CollectionConfigurationException, PermissionDeniedException, + LockException { + if (configCollection == null) { + return; + } loadConfiguration(broker, configCollection); final XmldbURI path = configCollection.getURI(); - for(final Iterator i = configCollection.collectionIterator(broker); i.hasNext(); ) { + for (final Iterator i = configCollection.collectionIterator(broker); i.hasNext();) { final XmldbURI childName = i.next(); final Collection child = broker.getCollection(path.appendInternal(childName)); - if (child == null) - {LOG.error("Collection is registered but could not be loaded: " + childName);} + if (child == null) { + LOG.error("Collection is registered but could not be loaded: " + childName); + } loadAllConfigurations(broker, child); } } - protected void loadConfiguration(DBBroker broker, Collection configCollection) throws CollectionConfigurationException, PermissionDeniedException, LockException { + protected void loadConfiguration(DBBroker broker, Collection configCollection) throws CollectionConfigurationException, PermissionDeniedException, + LockException { if (configCollection != null && configCollection.getDocumentCount(broker) > 0) { - for(final Iterator i = configCollection.iterator(broker); i.hasNext(); ) { + for (final Iterator i = configCollection.iterator(broker); i.hasNext();) { final DocumentImpl confDoc = i.next(); - if(confDoc.getFileURI().endsWith(CollectionConfiguration.COLLECTION_CONFIG_SUFFIX_URI)) { - if (LOG.isTraceEnabled()) - {LOG.trace("Reading collection configuration from '" + confDoc.getURI() + "'");} + if (confDoc.getFileURI().endsWith(CollectionConfiguration.COLLECTION_CONFIG_SUFFIX_URI)) { + if (LOG.isTraceEnabled()) { + LOG.trace("Reading collection configuration from '" + confDoc.getURI() + "'"); + } final CollectionConfiguration conf = new CollectionConfiguration(broker.getBrokerPool()); - // TODO DWES Temporary workaround for bug - // [ 1807744 ] Invalid collection.xconf causes a non startable database + // TODO DWES Temporary workaround for bug + // [ 1807744 ] Invalid collection.xconf causes a non + // startable database // http://sourceforge.net/tracker/index.php?func=detail&aid=1807744&group_id=17691&atid=117691 try { conf.read(broker, confDoc, false, configCollection.getURI(), confDoc.getFileURI()); } catch (final CollectionConfigurationException e) { - final String message = "Failed to read configuration document " + confDoc.getFileURI() + " in " - + configCollection.getURI() + ". " + final String message = "Failed to read configuration document " + confDoc.getFileURI() + " in " + configCollection.getURI() + ". " + e.getMessage(); LOG.error(message); System.out.println(message); @@ -258,47 +270,50 @@ protected void loadConfiguration(DBBroker broker, Collection configCollection) t synchronized (latch) { configurations.put(new CollectionURI(configCollection.getURI().getRawCollectionPath()), conf); } - //Allow just one configuration document per collection - //TODO : do not break if a system property allows several ones -pb + // Allow just one configuration document per collection + // TODO : do not break if a system property allows several + // ones -pb break; } } } } - + public CollectionConfiguration getOrCreateCollectionConfiguration(DBBroker broker, Collection collection) { final CollectionURI path = new CollectionURI(COLLECTION_CONFIG_PATH); path.append(collection.getURI().getRawCollectionPath()); CollectionConfiguration conf; synchronized (latch) { - conf = configurations.get(path); - if (conf == null) { - conf = new CollectionConfiguration(broker.getBrokerPool()); - configurations.put(path, conf); - } + conf = configurations.get(path); + if (conf == null) { + conf = new CollectionConfiguration(broker.getBrokerPool()); + configurations.put(path, conf); + } } - + return conf; } /** - * Notify the manager that a collection.xconf file has changed. All cached configurations - * for the corresponding collection and its sub-collections will be cleared. + * Notify the manager that a collection.xconf file has changed. All cached + * configurations for the corresponding collection and its sub-collections + * will be cleared. * * @param collectionPath */ public void invalidateAll(XmldbURI collectionPath) { - //TODO : use XmldbURI.resolve ! - if (!collectionPath.startsWith(CONFIG_COLLECTION_URI)) - {return;} - + // TODO : use XmldbURI.resolve ! + if (!collectionPath.startsWith(CONFIG_COLLECTION_URI)) { + return; + } + synchronized (latch) { LOG.debug("Invalidating collection " + collectionPath); configurations.remove(new CollectionURI(collectionPath.getRawCollectionPath())); } } - + /** * Called by the collection cache if a collection is removed from the cache. * This will delete the cached configuration instance for this collection. @@ -306,106 +321,110 @@ public void invalidateAll(XmldbURI collectionPath) { * @param collectionPath */ protected void invalidate(XmldbURI collectionPath) { - //TODO : use XmldbURI.resolve ! -// if (!collectionPath.startsWith(XmldbURI.CONFIG_COLLECTION_URI)) -// return; -// collectionPath = collectionPath.trimFromBeginning(XmldbURI.CONFIG_COLLECTION_URI); -// CollectionCache collectionCache = pool.getCollectionsCache(); -// synchronized (collectionCache) { -// CollectionConfiguration config = (CollectionConfiguration) cache.get(collectionPath); -// if (config != null) { -// config.getCollection().invalidateConfiguration(); -// cache.remove(collectionPath); -// } -// } + // TODO : use XmldbURI.resolve ! + // if (!collectionPath.startsWith(XmldbURI.CONFIG_COLLECTION_URI)) + // return; + // collectionPath = + // collectionPath.trimFromBeginning(XmldbURI.CONFIG_COLLECTION_URI); + // CollectionCache collectionCache = pool.getCollectionsCache(); + // synchronized (collectionCache) { + // CollectionConfiguration config = (CollectionConfiguration) + // cache.get(collectionPath); + // if (config != null) { + // config.getCollection().invalidateConfiguration(); + // cache.remove(collectionPath); + // } + // } } - - /** - * Check if the collection exists below the system collection. If not, create it. - * - * @param broker - * @param uri - * @throws EXistException - */ + + /** + * Check if the collection exists below the system collection. If not, + * create it. + * + * @param broker + * @param uri + * @throws EXistException + */ private void checkCreateCollection(DBBroker broker, XmldbURI uri) throws EXistException { - final TransactionManager transact = pool.getTransactionManager(); + final TransactionManager transact = broker.getDatabase().getTransactionManager(); Txn txn = null; - try { - Collection collection = broker.getCollection(uri); - if(collection == null) { - txn = transact.beginTransaction(); - collection = broker.getOrCreateCollection(txn, uri); + try { + Collection collection = broker.getCollection(uri); + if (collection == null) { + txn = transact.beginTransaction(); + collection = broker.getOrCreateCollection(txn, uri); SanityCheck.THROW_ASSERT(collection != null); - broker.saveCollection(txn, collection); + broker.saveCollection(txn, collection); transact.commit(txn); - } - } catch (final Exception e) { - transact.abort(txn); - throw new EXistException("Failed to initialize '" + uri + "' : " + e.getMessage()); - } finally { + } + } catch (final Exception e) { + transact.abort(txn); + throw new EXistException("Failed to initialize '" + uri + "' : " + e.getMessage()); + } finally { transact.close(txn); } } - /** Create a stored default configuration document for the root collection - * @param broker The broker which will do the operation + /** + * Create a stored default configuration document for the root collection + * + * @param broker + * The broker which will do the operation * @throws EXistException */ public void checkRootCollectionConfig(DBBroker broker) throws EXistException, PermissionDeniedException { - final String configuration = - "" + - " " + - - //Copied from the legacy conf.xml in order to make the test suite work - //TODO : backward compatibility could be ensured by copying the relevant parts of conf.xml - " " + - " " + - " " + - - " " + - ""; - - final TransactionManager transact = pool.getTransactionManager(); - final Txn transaction = transact.beginTransaction(); - try { + // Copied from the legacy conf.xml in order to make the test suite work + // TODO : backward compatibility could be ensured by copying the + // relevant parts of conf.xml + + final String configuration = + "" + + " " + + " " + + " " + + " " + + " " + + ""; + + final TransactionManager transact = broker.getDatabase().getTransactionManager(); + final Txn txn = transact.beginTransaction(); + try { Collection collection = null; - try { - collection = broker.openCollection(XmldbURI.ROOT_COLLECTION_URI, Lock.READ_LOCK); - if (collection == null) { - transact.abort(transaction); - throw new EXistException("collection " + XmldbURI.ROOT_COLLECTION_URI + " not found!"); - } - final CollectionConfiguration conf = getConfiguration(broker, collection); - if (conf != null) { - //We already have a configuration document : do not erase it - if (conf.getDocName() != null) { - transact.abort(transaction); - return; - } - } + try { + collection = broker.openCollection(XmldbURI.ROOT_COLLECTION_URI, Lock.READ_LOCK); + if (collection == null) { + transact.abort(txn); + throw new EXistException("collection " + XmldbURI.ROOT_COLLECTION_URI + " not found!"); + } + final CollectionConfiguration conf = getConfiguration(broker, collection); + if (conf != null) { + // We already have a configuration document : do not erase + // it + if (conf.getDocName() != null) { + transact.abort(txn); + return; + } + } } finally { - if (collection != null) - {collection.release(Lock.READ_LOCK);} + if (collection != null) { + collection.release(Lock.READ_LOCK); + } } - //Configure the root collection - addConfiguration(transaction, broker, collection, configuration); - transact.commit(transaction); - LOG.info("Configured '" + collection.getURI() + "'"); + // Configure the root collection + addConfiguration(txn, broker, collection, configuration); + transact.commit(txn); + LOG.info("Configured '" + collection.getURI() + "'"); } catch (final CollectionConfigurationException e) { - transact.abort(transaction); + transact.abort(txn); throw new EXistException(e.getMessage()); } finally { - transact.close(transaction); + transact.close(txn); } } /* - private void debugCache() { - StringBuilder buf = new StringBuilder(); - for (Iterator i = configurations.keySet().iterator(); i.hasNext(); ) { - buf.append(i.next()).append(' '); - } - LOG.debug(buf.toString()); - } - */ + * private void debugCache() { StringBuilder buf = new StringBuilder(); for + * (Iterator i = configurations.keySet().iterator(); i.hasNext(); ) { + * buf.append(i.next()).append(' '); } LOG.debug(buf.toString()); } + */ } \ No newline at end of file