/*
* $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/store/StandardStore.java,v 1.23 2004/07/28 09:34:40 ib Exp $
* $Revision: 1.23 $
* $Date: 2004/07/28 09:34:40 $
*
* ====================================================================
*
* 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.store;
import java.util.Enumeration;
import java.util.Vector;
import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.Service;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.ServiceInitializationFailedException;
import org.apache.slide.common.Uri;
import org.apache.slide.content.NodeRevisionContent;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionDescriptors;
import org.apache.slide.content.NodeRevisionNumber;
import org.apache.slide.content.RevisionAlreadyExistException;
import org.apache.slide.content.RevisionDescriptorNotFoundException;
import org.apache.slide.content.RevisionNotFoundException;
import org.apache.slide.lock.LockTokenNotFoundException;
import org.apache.slide.lock.NodeLock;
import org.apache.slide.security.NodePermission;
import org.apache.slide.structure.ObjectAlreadyExistsException;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.util.HashMapObjectCache;
import org.apache.slide.util.ObjectCache;
/**
* Abstract implementation of a store. Handles all caching operations.
*
* @deprecated This store is deprecated as it has no reasonable transaction support, use ExtendedStore instead.
* @version $Revision: 1.23 $
*/
public class StandardStore extends AbstractStore {
// ----------------------------------------------------------- Constructors
/**
* Constructor. Handles caches initialization.
*/
public StandardStore() {
super();
objectsCache = new HashMapObjectCache(1000, 10000, 0.95);
permissionsCache = new HashMapObjectCache(1000, 10000, 0.95);
locksCache = new HashMapObjectCache(1000, 10000, 0.95);
descriptorsCache = new HashMapObjectCache(1000, 10000, 0.95);
descriptorCache = new HashMapObjectCache(1000, 10000, 0.8);
}
// ----------------------------------------------------- Instance Variables
/**
* Nodes cache.
*/
protected ObjectCache objectsCache;
/**
* Permissions cache.
*/
protected ObjectCache permissionsCache;
/**
* Locks cache.
*/
protected ObjectCache locksCache;
/**
* Revision descriptors cache.
*/
protected ObjectCache descriptorsCache;
/**
* Revision descriptor cache.
*/
protected ObjectCache descriptorCache;
// ---------------------------------------------------- ServiceImpl Methods
/**
* Initializes descriptors store.
*
* @exception ServiceInitializationFailedException Throws an exception
* if the descriptors store has already been initialized before
*/
public void initialize(NamespaceAccessToken token)
throws ServiceInitializationFailedException {
super.initialize(token);
}
// ----------------------------------------------- DescriptorsStore Methods
/**
* Retrive an object from the Descriptors Store.
*
* @param uri Uri of the object we want to retrieve
* @exception ServiceAccessException Error accessing the Descriptors Store
* @exception ObjectNotFoundException The object to retrieve was not found
*/
public ObjectNode retrieveObject(Uri uri)
throws ServiceAccessException, ObjectNotFoundException {
if (nodeStore.cacheResults()) {
Object tempObject = objectsCache.get(uri.toString());
if (tempObject != null) {
return ((ObjectNode) tempObject).cloneObject();
} else {
ObjectNode objectNode = nodeStore.retrieveObject(uri);
objectNode.validate(uri.toString());
objectsCache.put(uri.toString(), objectNode.cloneObject());
return objectNode;
}
} else {
return super.retrieveObject(uri);
}
}
/**
* Store an object in the Descriptors Store.
*
* @param object Object to update
* @exception ServiceAccessException Error accessing the Descriptors Store
* @exception ObjectNotFoundException The object to update was not found
*/
public void storeObject(Uri uri, ObjectNode object)
throws ServiceAccessException, ObjectNotFoundException {
super.storeObject(uri, object);
if (nodeStore.cacheResults()) {
objectsCache.put(uri.toString(), object.cloneObject());
}
}
/**
* Create a new object in the Descriptors Store.
*
* @param object SlideObject
* @param uri Uri of the object we want to create
* @exception ServiceAccessException Error accessing the Descriptors Store
* @exception ObjectAlreadyExistsException An object already exists
* at this Uri
*/
public void createObject(Uri uri, ObjectNode object)
throws ServiceAccessException, ObjectAlreadyExistsException {
super.createObject(uri, object);
if (nodeStore.cacheResults()) {
objectsCache.put(uri.toString(), object.cloneObject());
}
}
/**
* Remove an object from the Descriptors Store.
*
* @param object Object to remove
* @exception ServiceAccessException Error accessing the Descriptors Store
* @exception ObjectNotFoundException The object to remove was not found
*/
public void removeObject(Uri uri, ObjectNode object)
throws ServiceAccessException, ObjectNotFoundException {
super.removeObject(uri, object);
if (nodeStore.cacheResults()) {
objectsCache.remove(uri.toString());
}
}
/**
* Store an object permissions in the Descriptors Store.
*
* @param permission Permission we want to create
* @exception ServiceAccessException Error accessing the Descriptors Store
*/
public void grantPermission(Uri uri, NodePermission permission)
throws ServiceAccessException {
super.grantPermission(uri, permission);
if (securityStore.cacheResults()) {
NodePermission tempPermission = permission.cloneObject();
Object value = permissionsCache.get(uri.toString());
if (value == null) {
// populate the cache with the existing entries
enumeratePermissions(uri);
// and check if the cache contains a corresponding entry now
value = permissionsCache.get(uri.toString());
if (value == null) {
// no permissions for the Uri in the cache, so create a new
// entry
Vector permissionsVector = new Vector();
permissionsVector.addElement(tempPermission);
permissionsCache.put(uri.toString(), permissionsVector);
}
} else {
Vector permissionsVector = (Vector) value;
permissionsVector.addElement(tempPermission);
}
}
}
/**
* Store an object permissions in the Descriptors Store.
*
* @param permission Permission we want to create
* @exception ServiceAccessException Error accessing the Descriptors Store
*/
public void revokePermission(Uri uri, NodePermission permission)
throws ServiceAccessException {
super.revokePermission(uri, permission);
if (securityStore.cacheResults()) {
Object value = permissionsCache.get(uri.toString());
Vector permissionsVector = null;
if (value != null) {
permissionsVector = (Vector) value;
permissionsVector.removeElement(permission);
}
}
}
/**
* Revoke all the permissions on the object.
*
* @param uri The uri of the object
* @exception ServiceAccessException Error accessing the Descriptors Store
*/
public void revokePermissions(Uri uri)
throws ServiceAccessException {
super.revokePermissions(uri);
if (securityStore.cacheResults()) {
Object value = permissionsCache.get(uri.toString());
Vector permissionsVector = null;
if (value != null) {
permissionsVector = (Vector) value;
permissionsVector.removeAllElements();
}
}
}
/**
* Enumerate an object permissions.
*
* @param uri The uri of the object
* @exception ServiceAccessException Error accessing the Descriptors Store
* @return A enumeration of all
* {@link org.apache.slide.security.NodePermission permissions} on this object.
*/
public Enumeration enumeratePermissions(Uri uri)
throws ServiceAccessException {
// TODO : The vectors elements MUST be cloned for non chached Results
if (securityStore.cacheResults()) {
Object value = permissionsCache.get(uri.toString());
Vector permissionsVector = null;
if (value != null) {
permissionsVector = (Vector) value;
} else {
permissionsVector = new Vector();
Enumeration tempEnum = securityStore.enumeratePermissions(uri);
while (tempEnum.hasMoreElements()) {
NodePermission tempPermission =
(NodePermission) tempEnum.nextElement();
tempPermission.validate(uri.toString());
permissionsVector.addElement(tempPermission);
}
permissionsCache.put(uri.toString(), permissionsVector);
}
return ((Vector) permissionsVector.clone()).elements();
} else {
return super.enumeratePermissions(uri);
}
}
/**
* Puts a lock on a subject.
*
* @param lock Lock token
* @exception ServiceAccessException Service access error
*/
public void putLock(Uri uri, NodeLock lock)
throws ServiceAccessException {
super.putLock(uri, lock);
if (lockStore.cacheResults()) {
Object value = locksCache.get(uri.toString());
Vector locksVector = null;
if (value == null) {
locksVector = new Vector();
locksCache.put(uri.toString(), locksVector);
} else {
locksVector = (Vector) value;
}
locksVector.addElement(lock.cloneObject());
}
}
/**
* Renews a lock.
*
* @param lock Token to renew
* @exception ServiceAccessException Service access error
* @exception LockTokenNotFoundException Lock token was not found
*/
public void renewLock(Uri uri, NodeLock lock)
throws ServiceAccessException, LockTokenNotFoundException {
super.renewLock(uri, lock);
if (lockStore.cacheResults()) {
Object value = locksCache.get(uri.toString());
Vector locksVector = null;
if (value != null) {
locksVector = (Vector) value;
boolean wasPresent = locksVector.removeElement(lock);
if (!wasPresent) {
throw new LockTokenNotFoundException(lock);
}
locksVector.addElement(lock.cloneObject());
}
}
}
/**
* Removes (cancels) a lock.
*
* @param lock Token to remove
* @exception ServiceAccessException Service access error
* @exception LockTokenNotFoundException Lock token was not found
*/
public void removeLock(Uri uri, NodeLock lock)
throws ServiceAccessException, LockTokenNotFoundException {
super.removeLock(uri, lock);
if (lockStore.cacheResults()) {
Object value = locksCache.get(uri.toString());
Vector locksVector = null;
if (value != null) {
locksVector = (Vector) value;
boolean wasPresent = locksVector.removeElement(lock);
if (!wasPresent) {
throw new LockTokenNotFoundException(lock);
}
}
}
}
/**
* Kills a lock.
*
* @param lock Token to remove
* @exception ServiceAccessException Service access error
* @exception LockTokenNotFoundException Lock token was not found
*/
public void killLock(Uri uri, NodeLock lock)
throws ServiceAccessException, LockTokenNotFoundException {
super.killLock(uri, lock);
if (lockStore.cacheResults()) {
Object value = locksCache.get(uri.toString());
Vector locksVector = null;
if (value != null) {
locksVector = (Vector) value;
boolean wasPresent = locksVector.removeElement(lock);
if (!wasPresent) {
throw new LockTokenNotFoundException(lock);
}
}
}
}
/**
* Enumerate locks on an object.
*
* @param uri Uri of the subject
* @return Enumeration List of {@link org.apache.slide.lock.NodeLock locks}
* which have been put on the subject
* @exception ServiceAccessException Service access error
*/
public Enumeration enumerateLocks(Uri uri)
throws ServiceAccessException {
if (lockStore.cacheResults()) {
Object value = locksCache.get(uri.toString());
Vector locksVector = null;
if (value == null) {
locksVector = new Vector();
Enumeration lockList = lockStore.enumerateLocks(uri);
while (lockList.hasMoreElements()) {
NodeLock tempLock = (NodeLock) lockList.nextElement();
tempLock.validate(uri.toString());
locksVector.addElement(tempLock);
}
locksCache.put(uri.toString(), locksVector);
} else {
locksVector = (Vector) value;
}
return ((Vector) locksVector.clone()).elements();
} else {
return super.enumerateLocks(uri);
}
}
/**
* Retrieve a revision descriptors.
*
* @param uri Uri
* @exception ServiceAccessException Service access error
* @exception RevisionDescriptorNotFoundException Revision descriptor
* was not found
*/
public NodeRevisionDescriptors retrieveRevisionDescriptors(Uri uri)
throws ServiceAccessException, RevisionDescriptorNotFoundException {
if (revisionDescriptorsStore.cacheResults()) {
Object tempObject = descriptorsCache.get(uri.toString());
if (tempObject != null) {
return ((NodeRevisionDescriptors) tempObject).cloneObject();
} else {
NodeRevisionDescriptors revisionDescriptors =
revisionDescriptorsStore.retrieveRevisionDescriptors(uri);
revisionDescriptors = revisionDescriptors.cloneObject();
descriptorsCache.put(uri.toString(),
revisionDescriptors);
revisionDescriptors.validate(uri.toString());
return revisionDescriptors;
}
} else {
return super.retrieveRevisionDescriptors(uri);
}
}
/**
* Create new revision descriptors.
*
* @param uri Uri
* @param revisionDescriptors Node revision descriptors
* @exception ServiceAccessException Service access error
*/
public void createRevisionDescriptors
(Uri uri, NodeRevisionDescriptors revisionDescriptors)
throws ServiceAccessException {
super.createRevisionDescriptors(uri, revisionDescriptors);
if (revisionDescriptorsStore.cacheResults()) {
descriptorsCache.put(uri.toString(),
revisionDescriptors.cloneObject());
}
}
/**
* Update revision descriptors.
*
* @param uri Uri
* @param revisionDescriptors Node revision descriptors
* @exception ServiceAccessException Service access error
* @exception RevisionDescriptorNotFoundException Revision descriptor
* was not found
*/
public void storeRevisionDescriptors
(Uri uri, NodeRevisionDescriptors revisionDescriptors)
throws ServiceAccessException, RevisionDescriptorNotFoundException {
super.storeRevisionDescriptors(uri, revisionDescriptors);
if (revisionDescriptorsStore.cacheResults()) {
descriptorsCache.put(uri.toString(),
revisionDescriptors.cloneObject());
}
}
/**
* Remove revision descriptors.
*
* @param uri Uri
* @exception ServiceAccessException Service access error
*/
public void removeRevisionDescriptors(Uri uri)
throws ServiceAccessException {
if (revisionDescriptorsStore.cacheResults()) {
descriptorsCache.remove(uri.toString());
}
super.removeRevisionDescriptors(uri);
}
/**
* Retrieve revision descriptor.
*
* @param uri Uri
* @param revisionNumber Node revision number
*/
public NodeRevisionDescriptor retrieveRevisionDescriptor
(Uri uri, NodeRevisionNumber revisionNumber)
throws ServiceAccessException, RevisionDescriptorNotFoundException {
if (revisionDescriptorStore.cacheResults()) {
Object result = descriptorCache.get(uri + "-" + revisionNumber);
if (result != null) {
return ((NodeRevisionDescriptor) result).cloneObject();
} else {
NodeRevisionDescriptor revisionDescriptor =
revisionDescriptorStore
.retrieveRevisionDescriptor(uri, revisionNumber)
.cloneObject();
revisionDescriptor.validate();
descriptorCache.put(uri + "-" + revisionNumber,
revisionDescriptor);
return revisionDescriptor;
}
} else {
return super.retrieveRevisionDescriptor(uri, revisionNumber);
}
}
/**
* Create new revision descriptor.
*
* @param uri Uri
* @param revisionDescriptor Node revision descriptor
* @exception ServiceAccessException Service access error
*/
public void createRevisionDescriptor
(Uri uri, NodeRevisionDescriptor revisionDescriptor)
throws ServiceAccessException {
super.createRevisionDescriptor(uri, revisionDescriptor);
if (revisionDescriptorStore.cacheResults()) {
descriptorCache.put(uri + "-"
+ revisionDescriptor.getRevisionNumber(),
revisionDescriptor.cloneObject());
}
}
/**
* Update revision descriptor.
*
* @param uri Uri
* @param revisionDescriptor Node revision descriptor
* @exception ServiceAccessException Service access error
* @exception RevisionDescriptorNotFoundException Revision descriptor
* was not found
*/
public void storeRevisionDescriptor
(Uri uri, NodeRevisionDescriptor revisionDescriptor)
throws ServiceAccessException, RevisionDescriptorNotFoundException {
super.storeRevisionDescriptor(uri, revisionDescriptor);
if (revisionDescriptorStore.cacheResults()) {
String key = uri + "-" + revisionDescriptor.getRevisionNumber();
descriptorCache.put(key, revisionDescriptor.cloneObject());
}
}
/**
* Remove revision descriptor.
*
* @param uri Uri
* @param number Revision number
* @exception ServiceAccessException Service access error
*/
public void removeRevisionDescriptor(Uri uri, NodeRevisionNumber number)
throws ServiceAccessException {
super.removeRevisionDescriptor(uri, number);
if (revisionDescriptorStore.cacheResults()) {
descriptorCache.remove(uri + "-" + number);
}
}
/**
* Retrive revision content.
*
* @param uri Uri
* @param revisionDescriptor Node revision descriptor
*/
public NodeRevisionContent retrieveRevisionContent
(Uri uri, NodeRevisionDescriptor revisionDescriptor)
throws ServiceAccessException, RevisionNotFoundException {
return super.retrieveRevisionContent(uri, revisionDescriptor);
}
/**
* Create a new revision
*
* @param uri Uri
* @param revisionDescriptor Node revision descriptor
* @param revisionContent Node revision content
*/
public void createRevisionContent
(Uri uri, NodeRevisionDescriptor revisionDescriptor,
NodeRevisionContent revisionContent)
throws ServiceAccessException, RevisionAlreadyExistException {
super.createRevisionContent(uri, revisionDescriptor, revisionContent);
}
/**
* Modify the latest revision of an object.
*
* @param uri Uri
* @param revisionDescriptor Node revision descriptor
* @param revisionContent Node revision content
*/
public void storeRevisionContent
(Uri uri, NodeRevisionDescriptor revisionDescriptor,
NodeRevisionContent revisionContent)
throws ServiceAccessException, RevisionNotFoundException {
super.storeRevisionContent(uri, revisionDescriptor, revisionContent);
}
/**
* Remove revision.
*
* @param uri Uri
* @param revisionDescriptor Node revision descriptor
*/
public void removeRevisionContent(Uri uri,
NodeRevisionDescriptor revisionDescriptor)
throws ServiceAccessException {
super.removeRevisionContent(uri, revisionDescriptor);
}
/**
* Return the name of this store
*
*/
public String toString() {
return getName() + "(" + getClass().getName() + ")";
}
// ------------------------------------------------------ Protected Methods
/**
* Delist (suspend) the resource manager in the current transaction.
*/
protected void delist(Service service, boolean success)
throws ServiceAccessException {
if (!success) {
// If there's a failure which will cause the transaction to be
// rollbacked, flush the caches
resetCaches();
}
super.delist(service, success);
}
/**
* Reset the caches.
*/
protected void resetCaches() {
objectsCache.clear();
permissionsCache.clear();
locksCache.clear();
descriptorsCache.clear();
descriptorCache.clear();
}
}