/*
* $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/common/Namespace.java,v 1.56.2.2 2004/02/05 16:05:04 mholz Exp $
* $Revision: 1.56.2.2 $
* $Date: 2004/02/05 16:05:04 $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.slide.common;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
import org.apache.slide.authenticate.CredentialsToken;
import org.apache.slide.content.ContentInterceptor;
import org.apache.slide.store.ContentStore;
import org.apache.slide.store.LockStore;
import org.apache.slide.store.NodeStore;
import org.apache.slide.store.RevisionDescriptorStore;
import org.apache.slide.store.RevisionDescriptorsStore;
import org.apache.slide.store.SecurityStore;
import org.apache.slide.store.Store;
import org.apache.slide.structure.ObjectAlreadyExistsException;
import org.apache.slide.structure.SubjectNode;
import org.apache.slide.transaction.SlideTransactionManager;
import org.apache.slide.util.conf.Configuration;
import org.apache.slide.util.conf.ConfigurationException;
import org.apache.slide.util.logger.Logger;
/**
* A Namespace contains a hierarchically organized tree of information.
*
* <p>
* Objects in the namespace are generally referred to as <i>Nodes</i>. Nodes
* may have a parent, children, content and meta-data. They can also be
* versioned (so that multiple revisions of the object's content and
* metadata are stored) and locked (so that only specific principals are
* allowed to read or modify the object). In addition, access control
* information can be assigned to every node.
* </p>
* <p>
* Nodes in the hierarchy are identified by their URI (Unique Resource
* Identifier). A URI is analogous to a file path in traditional file
* systems. For example:
* <pre>
* /users/john/documents/my_document.txt
* </pre>
* As you can see, the slash ("/") is used to separate nodes in the path.
* </p>
* <p>
* Client applications can not access a Namespace object directly. Instead,
* access must be requested from the {@link Domain Domain}, which will hand
* out a proxy object ({@link NamespaceAccessToken NamespaceAccessToken})
* that enables the client application to access the namespace using the
* helpers.
* </p>
* <p>
* Namespaces are necessarily self-contained. What this means is that a
* namespace cannot reference or contain links to another namespace. A
* namespace is typically assigned per-application, which effectively
* isolates it's data and security context from those of other applications.
* </p>
*
* @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
* @author Dirk Verbeeck
* @version $Revision: 1.56.2.2 $
*/
public final class Namespace {
// -------------------------------------------------------------- Constants
public static final String REFERENCE = "reference";
public static final String NODE_STORE = "nodestore";
public static final String SECURITY_STORE = "securitystore";
public static final String LOCK_STORE = "lockstore";
public static final String REVISION_DESCRIPTORS_STORE =
"revisiondescriptorsstore";
public static final String REVISION_DESCRIPTOR_STORE =
"revisiondescriptorstore";
public static final String CONTENT_STORE = "contentstore";
/**
* Log channel for logger
*/
private static final String LOG_CHANNEL = Namespace.class.getName();
protected static final String I_CREATESTORELISTENERCLASS = "createStoreListenerClass";
protected static final String I_CREATESTORELISTENERCLASS_DEFAULT = "org.apache.slide.webdav.util.UriHandler";
protected static Class createStoreListenerClass;
static {
try {
String createStoreListenerClassName = Domain.getParameter(I_CREATESTORELISTENERCLASS, I_CREATESTORELISTENERCLASS_DEFAULT);
createStoreListenerClass = Class.forName( createStoreListenerClassName );
}
catch( Exception x ) {
Domain.warn( "Loading of create_store_listener class failed: "+x.getMessage() );
}
}
// ----------------------------------------------------- Instance Variables
/**
* Namespace name.
*/
private String name;
/**
* classname of the search implementation
*/
private String searchClassName;
/**
* Static Vector which holds a reference, and provides access to all
* the services instances used by the Slide namespace.
*/
private transient Vector connectedServices;
/**
* Registered DescriptorStores on this Namespace.
*/
private transient Hashtable stores;
/**
* Current namespace configuration.
*/
private NamespaceConfig config;
/**
* Uri cache.
*/
private Hashtable uriCache;
/**
* Default descriptors store classname.
*/
private String defaultStoreClassname =
"org.apache.slide.store.ExtendedStore";
/**
* Transaction manager associated with this namespace.
*/
private TransactionManager transactionManager =
new SlideTransactionManager();
/**
* Logger.
*/
private Logger logger;
/**
* Application logger.
*/
private Logger applicationLogger;
// ------------------------------------------------------------ Constructor
/**
* Constructor.
*/
Namespace() {
stores = new Hashtable();
connectedServices = new Vector();
name = new String();
uriCache = new Hashtable();
}
// ------------------------------------------------------------- Properties
/**
* Sets the qualified name of the namespace.
*
* @param name Name of the namespace
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the qulified name of the namespace.
*
* @return String Namespace name
*/
public String getName() {
return name;
}
/**
* Method setSearchClassName
*
* @param searchClassName classname of the search implementation
*/
public void setSearchClassName (String searchClassName) {
this.searchClassName = searchClassName;
}
/**
* Method getSearchClassName
*
* @return classname of the search implementation
*/
public String getSearchClassName() {
return searchClassName;
}
/**
* Returns the namespace configuration.
*
* @return NamespaceConfig Namespace configuration
*/
public NamespaceConfig getConfig() {
return config;
}
/**
* Enumerate all scopes managed by this namespace.
*
* @return return an enumeration of all scopes
*/
public Enumeration enumerateScopes() {
return stores.keys();
}
/**
* Transaction manager accessor.
*/
public TransactionManager getTransactionManager() {
return transactionManager;
}
/**
* Return the current logger.
*/
public Logger getLogger() {
if (logger != null)
return logger;
else
return Domain.getLogger();
}
/**
* Set the logger used by this namespace.
*/
public void setLogger(Logger logger) {
this.logger = logger;
if (transactionManager instanceof SlideTransactionManager) {
((SlideTransactionManager) transactionManager).setLogger(logger);
}
}
/**
* Return the current application logger.
*/
public Logger getApplicationLogger() {
if (applicationLogger != null)
return applicationLogger;
else if (logger != null)
return logger;
else
return Domain.getLogger();
}
/**
* Set the logger used by this namespace.
*/
public void setApplicationLogger(Logger logger) {
this.applicationLogger = logger;
}
// --------------------------------------------------------- Public Methods
/**
* Used to register a Store in the namespace for the specified scope.
* First, the function instantiate the Store, then gives it
* its init parameters. It is then stored in the stores
* Hashtable, associated with the given scope.
*
* @param storeClass Class of the Data Source
* @param parameters Init parameters for the Data Source
* @param scope Scope for which the Data Source is registered
* @param childStores Instances of the typed stores
* @exception ServiceRegistrationFailed An error occured during
* instantiation of the service
* @exception ServiceParameterErrorException Incorrect service parameter
* @exception ServiceParameterMissingException Service parameter missing
*/
public void registerStore(String storeName, Class storeClass,
Hashtable parameters, Scope scope,
Hashtable childStores)
throws ServiceRegistrationFailedException,
ServiceParameterErrorException, ServiceParameterMissingException {
if (!stores.containsKey(scope)) {
try {
Store store = (Store) storeClass.newInstance();
store.setName(storeName);
store.setParameters(parameters);
stores.put(scope, store);
// Now assigning the child stores
Object nodeStore = childStores.get(NODE_STORE);
if (nodeStore instanceof String) {
// Resolving reference
store.setNodeStore((NodeStore) childStores.get(nodeStore));
} else {
store.setNodeStore((NodeStore) nodeStore);
}
Object securityStore = childStores.get(SECURITY_STORE);
if (securityStore instanceof String) {
// Resolving reference
store.setSecurityStore
((SecurityStore) childStores.get(securityStore));
} else {
store.setSecurityStore
((SecurityStore) securityStore);
}
Object lockStore = childStores.get(LOCK_STORE);
if (lockStore instanceof String) {
store.setLockStore
((LockStore) childStores.get(lockStore));
} else {
store.setLockStore((LockStore) lockStore);
}
Object revisionDescriptorsStore = childStores
.get(REVISION_DESCRIPTORS_STORE);
if (revisionDescriptorsStore instanceof String) {
store.setRevisionDescriptorsStore
((RevisionDescriptorsStore) childStores
.get(revisionDescriptorsStore));
} else {
store.setRevisionDescriptorsStore
((RevisionDescriptorsStore) revisionDescriptorsStore);
}
Object revisionDescriptorStore = childStores
.get(REVISION_DESCRIPTOR_STORE);
if (revisionDescriptorStore instanceof String) {
store.setRevisionDescriptorStore
((RevisionDescriptorStore) childStores
.get(revisionDescriptorStore));
} else {
store.setRevisionDescriptorStore
((RevisionDescriptorStore) revisionDescriptorStore);
}
Object contentStore = childStores.get(CONTENT_STORE);
if (contentStore instanceof String) {
// Resolving reference
store.setContentStore
((ContentStore) childStores.get(contentStore));
} else {
store.setContentStore((ContentStore) contentStore);
}
// set the scope in the father and child stores
store.setScope(scope);
// call the create_store_listener
notifyStoreCreated( this.name, scope.toString(), storeName );
} catch(InstantiationException e) {
throw new ServiceRegistrationFailedException
(storeClass);
} catch(IllegalAccessException e) {
throw new ServiceRegistrationFailedException
(storeClass);
} catch(NullPointerException e) {
throw new ServiceRegistrationFailedException
(storeClass);
} catch(ClassCastException e) {
// TEMP
getLogger().log(e,LOG_CHANNEL, Logger.ERROR);
// --TEMP
throw new ServiceRegistrationFailedException
(storeClass);
}
}
}
/**
* At the end of the service registration, this service is called to
* perform any required initialization task.
*
* @exception ServicesInitializationFailedException One or more
* exception occured while initializing services
*/
public void initializeServices()
throws ServicesInitializationFailedException {
// We create the nested exception which will hold all thrown exception
// during the initialization process.
ServicesInitializationFailedException nestedException
= new ServicesInitializationFailedException();
// Initializing DesciptorsStores
Enumeration serviceList = stores.elements();
while (serviceList.hasMoreElements()) {
Service service = (Service) serviceList.nextElement();
try {
getLogger().log("Initializing Store " + service,LOG_CHANNEL,Logger.INFO);
service.setNamespace(this);
service.initialize(new NamespaceAccessTokenImpl(this));
} catch (ServiceInitializationFailedException e) {
// We add the exception which just occured to the
// nested exception
nestedException.addException(e);
}
}
// If the nested exception is not empty, we throw it.
if (!nestedException.isEmpty()) {
throw nestedException;
}
}
/**
* Reinitialize namespace.
*/
public void clearNamespace() {
stores.clear();
}
/**
* Connects a data source on demand.
*
* @param service Service on which a connection attempt will be made
* @param token the credentials token containing e.g. the credential
* @exception ServiceConnectionFailedException Error connecting service
* @exception ServiceAccessException Unspecified low level service
* access exception
*/
public void connectService(Service service, CredentialsToken token)
throws ServiceConnectionFailedException, ServiceAccessException {
// Try to connect ...
boolean newConnection = service.connectIfNeeded(token);
// If successfull (ie, no exception was thrown), we add it to the list
// of the connected components.
if (newConnection) {
connectedServices.addElement(service);
}
}
/**
* Disconnects all services.
*
* @exception ServicesShutDownFailedException Error disconnecting one or
* more services
*/
public void disconnectServices()
throws ServicesShutDownFailedException {
// We create the nested exception which will hold all thrown exception
// during shut down of services.
ServicesShutDownFailedException nestedException
= new ServicesShutDownFailedException();
for (int i=0; i<connectedServices.size(); i++) {
try {
Service service = (Service) connectedServices.elementAt(i);
if (service.isConnected()) {
getLogger().log("Shutting down service " + service,LOG_CHANNEL,Logger.INFO);
service.disconnect();
}
} catch (ServiceDisconnectionFailedException e) {
nestedException.addException(e);
} catch (ServiceAccessException e) {
nestedException.addException(e);
}
}
connectedServices.removeAllElements();
// If the nested exception is not empty, we throw it.
if (!nestedException.isEmpty()) {
throw nestedException;
}
}
/**
* Remove a Store from the registry.
*
* @param scope Scope to disconnect
* @exception ServiceDisconnctionFailedException Error disconnecting
* DescriptorsStore
* @exception ServiceAccessException Unspecified error during
* service access
*/
public void unregisterStore(Scope scope)
throws ServiceDisconnectionFailedException, ServiceAccessException {
if (stores.containsKey(scope)) {
Store store = (Store) stores.get(scope);
if (store.isConnected()) {
store.disconnect();
connectedServices.removeElement(store);
}
stores.remove(scope);
store = null;
}
}
/**
* Get the Data Source associated with the given scope, if any.
* In contrary to the retrieveStore method, this methos does not
* perform a connection.
*
* @param scope Scope to match
*/
public Store getStore(Scope scope) {
Store store = null;
if (stores.containsKey(scope)) {
store = (Store) stores.get(scope);
}
return store;
}
/**
* Get the Data Source associated with the given scope, if any and
* connect to the store.
*
* @param scope Scope to match
* @param token the Credeantials token containing e.g. the credential
* @exception ServiceConnectionFailedException Connection to Store failed
* @exception ServiceAccessException Unspecified service access exception
*/
public Store retrieveStore(Scope scope, CredentialsToken token)
throws ServiceConnectionFailedException, ServiceAccessException {
Store store = getStore(scope);
if (store != null) {
connectService(store, token);
}
return store;
}
/**
* Builds a new uri object to access this namespace. This call will
* return a Uri which doesn't have its token field set. The store should
* accept such Uri as valid, and bypass any check that is made based on the
* state.
*
* @param uri Requested Uri
* @return Uri
*/
public Uri getUri(String uri) {
return getUri(null, uri);
}
/**
* Builds a new uri object to access this namespace.
*
* @param token SlideToken
* @param uri Requested Uri
* @return Uri
*/
public Uri getUri(SlideToken token, String uri) {
return getUri(token, uri, token==null
?false
:token.isForceStoreEnlistment());
}
/**
* Builds a new uri object to access this namespace.
*
* @param token SlideToken
* @param uri Requested Uri
* @param forcedEnlistment may differ from the value set in token
* @return Uri
*/
public Uri getUri(SlideToken token, String uri, boolean forcedEnlistment) {
Uri result = null;
Object temp = null;
temp = uriCache.get(uri);
if (temp == null) {
result = new Uri(token, this, uri);
uriCache.put(uri, result);
if (uriCache.size() > 10000) {
clearUriCache();
}
} else {
result = (Uri) temp;
result = result.cloneObject();
result.setToken(token);
result.reconnectServices();
}
// if a different forceEnlistment value want to be used
// wrap the used token to reflect the different value
if (token != null && token.isForceStoreEnlistment() != forcedEnlistment) {
result.setToken(new SlideTokenWrapper(token, forcedEnlistment));
}
return result;
}
/**
* Clear uri cache.
*/
void clearUriCache() {
uriCache.clear();
}
/**
* Get content interceptors associated with this namespace.
*/
public ContentInterceptor[] getContentInterceptors() {
return config.getContentInterceptors();
}
// -------------------------------------------------------- Package Methods
/**
* Parses the contents of the specified definition object, and uses that
* info to initialize the namespace.
*
* @param definition Definiton of the scopes and stores of
* the namespace
* @exception SlideException Something went wrong during registry or
* services initialization
* @exception ConfigurationException Error parsing configuration file
*/
void loadDefinition(Configuration definition)
throws SlideException, ConfigurationException {
getLogger().log("Loading namespace definition",LOG_CHANNEL,Logger.INFO);
// Loading stores
Hashtable storesClass = new Hashtable();
Hashtable storesParameters = new Hashtable();
Hashtable childStores = new Hashtable();
Enumeration storeDefinitions =
definition.getConfigurations("store");
while (storeDefinitions.hasMoreElements()) {
loadStoreDefinition
((Configuration) storeDefinitions.nextElement(),
storesClass, storesParameters, childStores);
}
Enumeration scopeDefinitions =
definition.getConfigurations("scope");
while (scopeDefinitions.hasMoreElements()) {
loadScopeDefinition
((Configuration) scopeDefinitions.nextElement(),
storesClass, storesParameters, childStores);
}
// Initialize all loaded services.
initializeServices();
}
/**
* Parses the contents of the specified reader, and uses that info to
* initialize the specified Slide namespace.
*
* @param namespaceBaseDataDefinition Namespace base data
* @exception SlideException Something went wrong during registry or
* services initialization
*/
void loadBaseData(Configuration namespaceBaseDataDefinition)
throws SlideException, ConfigurationException {
getLogger().log("Loading namespace " + getName() + " base data",LOG_CHANNEL,Logger.INFO);
// Load Namespace Base Data
try {
// start transaction for temp object creation
getTransactionManager().begin();
SlideToken slideToken = new SlideTokenImpl(new CredentialsToken(""));
slideToken.setForceStoreEnlistment(true);
// First, we create the root node
Uri rootUri = getUri(slideToken, "/");
SubjectNode rootNode = new SubjectNode("/");
try {
rootUri.getStore().createObject(rootUri, rootNode);
} catch (ObjectAlreadyExistsException e) {
// abort the failed transaction
getTransactionManager().rollback();
// start a new one to continue processing
getTransactionManager().begin();
}
// end transaction for temp object creation
getTransactionManager().commit();
getLogger().log("Init namespace " + getName() + " configuration",LOG_CHANNEL,Logger.INFO);
// Create the dummy configuration
config.initializeAsDummyConfig(this);
// Create the Access token
NamespaceAccessToken token = new NamespaceAccessTokenImpl(this);
// start the transaction, NOTE some operations are outside this TA
token.begin();
getLogger().log("Import data into namespace " + getName(),LOG_CHANNEL,Logger.INFO);
token.importData(slideToken, namespaceBaseDataDefinition);
// end the transaction, NOTE some operations are outside this TA
token.commit();
// start transaction for temp object removal
getTransactionManager().begin();
getLogger().log("Finish init namespace " + getName() + " configuration",LOG_CHANNEL,Logger.INFO);
// And remove the all permission from the root node
rootNode =
(SubjectNode) rootUri.getStore().retrieveObject(rootUri);
rootUri.getStore().storeObject(rootUri, rootNode);
// end transaction for temp object removal
getTransactionManager().commit();
} catch (SlideException e) {
// If that occurs, then most likely the base config was
// already done before
e.printStackTrace();
getLogger().log("Namespace base configuration was already done before",LOG_CHANNEL,Logger.INFO);
try {
if (getTransactionManager().getStatus()==Status.STATUS_ACTIVE)
getTransactionManager().rollback();
}
catch (SystemException ex) {
getLogger().log("Could not rollback namespace base configuration: " + ex.toString(),LOG_CHANNEL,Logger.WARNING);
}
} catch (Exception e) {
getLogger().log("Unable to read Namespace base configuration file : ",LOG_CHANNEL,Logger.ERROR);
getLogger().log(e,LOG_CHANNEL, Logger.ERROR);
// Unable to load the base configuration XML file.
// Log the event, and hope it was already done before.
try {
if (getTransactionManager().getStatus()==Status.STATUS_ACTIVE)
getTransactionManager().rollback();
}
catch (SystemException ex) {
getLogger().log("Could not rollback namespace base configuration after load error: " + ex.toString(),LOG_CHANNEL,Logger.WARNING);
}
}
}
/**
* Parses the contents of the specified reader, and uses that info to
* initialize the specified Slide namespace.
*
* @param namespaceConfigurationDefinition The configuration to load.
* @exception SlideException Something went wrong during registry or
* services initialization
*/
void loadConfiguration(Configuration namespaceConfigurationDefinition)
throws SlideException {
getLogger().log("Loading namespace " + getName() + " configuration",LOG_CHANNEL,Logger.INFO);
// Load Namespace Config
config = new NamespaceConfig();
config.initializeNamespaceConfig(this,
namespaceConfigurationDefinition);
}
/**
* Parses the contents of the specified reader, and uses that info to
* initialize the specified Slide namespace.
*
* @param namespaceConfigurationDefinition Namespace configuration
* @exception SlideException Something went wrong during registry or
* services initialization
*/
void loadParameters(Configuration namespaceConfigurationDefinition)
throws SlideException {
getLogger().log("Loading namespace " + getName() + " parameters",LOG_CHANNEL,Logger.INFO);
// Load Namespace Config
config = new NamespaceConfig();
config.initializeNamespaceParameters(this,
namespaceConfigurationDefinition);
}
// -------------------------------------------------------- Private Methods
/**
* Parse the store definition.
*
* @param storeDefinition store definition
* @param storesClass Class names of the stores
* @param storesParameters Parameters of the stores
* @param childStores Child stores
* @exception ConfigurationException Error parsing configuration file
* @exception SlideException Error loading the specified class
*/
private void loadStoreDefinition
(Configuration storeDefinition,
Hashtable storesClass,
Hashtable storesParameters,
Hashtable childStores)
throws ConfigurationException, SlideException {
String storeName = storeDefinition.getAttribute("name");
String storeClassname = defaultStoreClassname;
try {
storeClassname = storeDefinition.getAttribute("classname");
} catch (ConfigurationException e) {
}
Enumeration storeParametersDefinitions =
storeDefinition.getConfigurations("parameter");
// Load descriptors store class
Class storeClass = null;
try {
storeClass = Class.forName(storeClassname);
} catch (Exception e) {
getLogger().log(e,LOG_CHANNEL, Logger.ERROR);
throw new SlideException(e.getMessage());
}
storesClass.put(storeName, storeClass);
// Load descriptor store parameters
Hashtable storeParameters = new Hashtable();
while (storeParametersDefinitions.hasMoreElements()) {
Configuration parameterDefinition = (Configuration)
storeParametersDefinitions.nextElement();
String parameterName = parameterDefinition.getAttribute("name");
String parameterValue = parameterDefinition.getValue();
storeParameters.put(parameterName, parameterValue);
}
storesParameters.put(storeName, storeParameters);
// Now reading the "child" stores
Hashtable currentStoreChildStores = new Hashtable();
// Loading node store (if any)
try {
Configuration nodeStoreDefinition =
storeDefinition.getConfiguration(NODE_STORE);
try {
Configuration referenceDefinition =
storeDefinition.getConfiguration(REFERENCE);
currentStoreChildStores.put
(NODE_STORE, referenceDefinition.getAttribute("store"));
getLogger().log("Node store references " + referenceDefinition.getAttribute("store"),LOG_CHANNEL,Logger.INFO);
} catch (ConfigurationException ex) {
getLogger().log("Node store: " + nodeStoreDefinition.getAttribute("classname"),LOG_CHANNEL,Logger.INFO);
NodeStore nodeStore =
(NodeStore) loadChildStore(nodeStoreDefinition,
storeParameters);
if (nodeStore != null) {
currentStoreChildStores.put(NODE_STORE, nodeStore);
}
}
} catch (Exception e) {
}
// Loading security store (if any)
try {
Configuration securityStoreDefinition =
storeDefinition.getConfiguration(SECURITY_STORE);
try {
Configuration referenceDefinition =
securityStoreDefinition.getConfiguration(REFERENCE);
currentStoreChildStores.put
(SECURITY_STORE,
referenceDefinition.getAttribute("store"));
getLogger().log("Security store references " + referenceDefinition.getAttribute("store"),LOG_CHANNEL,Logger.INFO);
} catch (ConfigurationException ex) {
getLogger().log("Security store: " + securityStoreDefinition.getAttribute("classname"),LOG_CHANNEL,Logger.INFO);
SecurityStore securityStore =
(SecurityStore) loadChildStore(securityStoreDefinition,
storeParameters);
if (securityStore != null) {
currentStoreChildStores.put(SECURITY_STORE, securityStore);
}
}
} catch (Exception e) {
}
// Loading lock store (if any)
try {
Configuration lockStoreDefinition =
storeDefinition.getConfiguration(LOCK_STORE);
try {
Configuration referenceDefinition =
lockStoreDefinition.getConfiguration(REFERENCE);
currentStoreChildStores.put
(LOCK_STORE, referenceDefinition.getAttribute("store"));
getLogger().log("Lock store store references " + referenceDefinition.getAttribute("store"),LOG_CHANNEL,Logger.INFO);
} catch (ConfigurationException ex) {
getLogger().log("Lock store store: " + lockStoreDefinition.getAttribute("classname"),LOG_CHANNEL,Logger.INFO);
LockStore lockStore =
(LockStore) loadChildStore(lockStoreDefinition,
storeParameters);
if (lockStore != null) {
currentStoreChildStores.put(LOCK_STORE, lockStore);
}
}
} catch (Exception e) {
}
// Loading revision descriptors store (if any)
try {
Configuration revisionDescriptorsStoreDefinition =
storeDefinition.getConfiguration
(REVISION_DESCRIPTORS_STORE);
try {
Configuration referenceDefinition =
revisionDescriptorsStoreDefinition
.getConfiguration(REFERENCE);
currentStoreChildStores.put
(REVISION_DESCRIPTORS_STORE,
referenceDefinition.getAttribute("store"));
getLogger().log("Revision descriptors store references " + referenceDefinition.getAttribute("store"),LOG_CHANNEL,Logger.INFO);
} catch (ConfigurationException ex) {
getLogger().log("Revision descriptors store: " + revisionDescriptorsStoreDefinition.getAttribute("classname"),LOG_CHANNEL,Logger.INFO);
RevisionDescriptorsStore revisionDescriptorsStore =
(RevisionDescriptorsStore) loadChildStore
(revisionDescriptorsStoreDefinition, storeParameters);
if (revisionDescriptorsStore != null) {
currentStoreChildStores.put(REVISION_DESCRIPTORS_STORE,
revisionDescriptorsStore);
}
}
} catch (Exception e) {
}
// Loading revision descriptor store (if any)
try {
Configuration revisionDescriptorStoreDefinition =
storeDefinition.getConfiguration(REVISION_DESCRIPTOR_STORE);
try {
Configuration referenceDefinition =
revisionDescriptorStoreDefinition
.getConfiguration(REFERENCE);
currentStoreChildStores.put
(REVISION_DESCRIPTOR_STORE,
referenceDefinition.getAttribute("store"));
getLogger().log("Revision descriptor store references " + referenceDefinition.getAttribute("store"),LOG_CHANNEL,Logger.INFO);
} catch (ConfigurationException ex) {
getLogger().log("Revision descriptor store: " + revisionDescriptorStoreDefinition.getAttribute("classname"),LOG_CHANNEL,Logger.INFO);
RevisionDescriptorStore revisionDescriptorStore =
(RevisionDescriptorStore) loadChildStore
(revisionDescriptorStoreDefinition, storeParameters);
if (revisionDescriptorStore != null) {
currentStoreChildStores.put(REVISION_DESCRIPTOR_STORE,
revisionDescriptorStore);
}
}
} catch (Exception e) {
}
// Loading content store (if any)
try {
Configuration contentStoreDefinition =
storeDefinition.getConfiguration(CONTENT_STORE);
try {
Configuration referenceDefinition =
contentStoreDefinition.getConfiguration(REFERENCE);
currentStoreChildStores.put
(CONTENT_STORE, referenceDefinition.getAttribute("store"));
getLogger().log("Content store references " + referenceDefinition.getAttribute("store"),LOG_CHANNEL,Logger.INFO);
} catch (ConfigurationException ex) {
getLogger().log("Content store: " + contentStoreDefinition.getAttribute("classname"),LOG_CHANNEL,Logger.INFO);
ContentStore contentStore =
(ContentStore) loadChildStore(contentStoreDefinition,
storeParameters);
if (contentStore != null) {
currentStoreChildStores.put(CONTENT_STORE, contentStore);
}
}
} catch (Exception e) {
}
childStores.put(storeName, currentStoreChildStores);
}
/**
* Load a child descriptors store.
*
* @param childStoreDefinition XML definition of the child store
* @param fatherParameters XML parameters defined for the father
* @return Service Instance of the child store
* @exception ConfigurationException Error parsing configuration file
* @exception SlideException Error loading the specified class
*/
private Service loadChildStore(Configuration childStoreDefinition,
Hashtable fatherParameters)
throws ConfigurationException, SlideException {
// Load classname
String childStoreClassname =
childStoreDefinition.getAttribute("classname");
// Load descriptors store class
Service childStore = null;
try {
Class childStoreClass =
Class.forName(childStoreClassname);
childStore = (Service) childStoreClass.newInstance();
} catch (Exception e) {
getLogger().log(e,LOG_CHANNEL, Logger.ERROR);
return null;
}
// Retrieve parent parameters
Hashtable childStoreParameters = new Hashtable();
Enumeration fatherParametersKeys = fatherParameters.keys();
while (fatherParametersKeys.hasMoreElements()) {
Object key = fatherParametersKeys.nextElement();
Object value = fatherParameters.get(key);
childStoreParameters.put(key, value);
}
// Load parameters
Enumeration childStoreParametersDefinitions =
childStoreDefinition.getConfigurations("parameter");
while (childStoreParametersDefinitions.hasMoreElements()) {
Configuration parameterDefinition = (Configuration)
childStoreParametersDefinitions.nextElement();
String parameterName = parameterDefinition.getAttribute("name");
String parameterValue = parameterDefinition.getValue();
childStoreParameters.put(parameterName, parameterValue);
}
childStore.setParameters(childStoreParameters);
return childStore;
}
/**
* Parse the content store definition.
*
* @param storesClass Class names of the descriptors stores
* @param storesParameters Parameters of the descriptors stores
* @param childStores Child stores instances
* @exception ConfigurationException Error parsing configuration file
* @exception UnknownServiceDeclarationException Reference to
* unknown service
* @exception ServiceParameterErrorException Service parameter error
* @exception ServiceParameterMissingException Service parameter missing
* @exception ServiceRegistrationFailedException Error registering service
*/
private void loadScopeDefinition(Configuration scopeDefinition,
Hashtable storesClass,
Hashtable storesParameters,
Hashtable childStores)
throws ConfigurationException, UnknownServiceDeclarationException,
ServiceParameterErrorException, ServiceParameterMissingException,
ServiceRegistrationFailedException {
String match = scopeDefinition.getAttribute("match");
// First, we get the correct class and parameters from the Hashtables.
String storeName = scopeDefinition.getAttribute("store");
if (storeName != null) {
if ((!storesClass.containsKey(storeName)) ||
(!storesParameters.containsKey(storeName))) {
throw new UnknownServiceDeclarationException(storeName);
}
registerStore(storeName,
(Class) storesClass.get(storeName),
(Hashtable) storesParameters.get(storeName),
new Scope(match),
(Hashtable) childStores.get(storeName));
getLogger().log("Registering Store "
+ storeName
+ " ("
+ storesClass.get(storeName)
+ ") with parameters "
+ storesParameters.get(storeName)
+ " on scope " + match,LOG_CHANNEL,Logger.INFO);
}
}
/**
*
*/
private void notifyStoreCreated( String namespaceName, String scope, String storeName ) {
if( createStoreListenerClass != null ) {
try {
Method nsc = createStoreListenerClass.getMethod(
"notifyStoreCreated", new Class[]{String.class, String.class, String.class} );
nsc.invoke( null, new Object[]{namespaceName, scope, storeName} ); // obj=null since method is static
}
catch( Exception x ) {
Domain.warn( "Notification of store creation "+
"(namespace="+namespaceName+", scope="+scope+", store="+storeName+") failed: "+x.getMessage() );
}
}
}
// --------------------------------------------------------- Object Methods
/**
* Get a String representation of this namespace.
*/
public String toString() {
return getName();
}
}