stefan 2004/07/01 11:29:41
Modified: proposals/jcrri/src/org/apache/slide/jcr/core ItemImpl.java
RepositoryImpl.java ItemManager.java
NamespaceRegistryImpl.java TicketImpl.java
WorkspaceImpl.java
Log:
jcrri
Revision Changes Path
1.8 +32 -19
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemImpl.java
Index: ItemImpl.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemImpl.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- ItemImpl.java 30 Jun 2004 14:36:32 -0000 1.7
+++ ItemImpl.java 1 Jul 2004 18:29:41 -0000 1.8
@@ -28,6 +28,7 @@
import org.apache.slide.jcr.core.nodetype.NodeDefImpl;
import org.apache.slide.jcr.core.nodetype.NodeTypeImpl;
import org.apache.slide.jcr.core.nodetype.PropertyDefImpl;
+import org.apache.slide.jcr.core.observation.EventStateCollection;
import org.apache.slide.jcr.core.state.*;
import org.apache.slide.jcr.util.IteratorHelper;
@@ -449,6 +450,7 @@
/**
* Failsafe mapping of internal <code>id</code> to JCR path for use in
* diagnostic output, error messages etc.
+ *
* @return JCR path or some fallback value
*/
protected String safeGetJCRPath() {
@@ -500,15 +502,15 @@
* persistent item that has been transiently removed
*/
case ItemState.STATUS_EXISTING_REMOVED:
- /**
- * persistent item that has been transiently modified
- */
+ /**
+ * persistent item that has been transiently modified
+ */
case ItemState.STATUS_EXISTING_MODIFIED:
- /**
- * persistent item that has been transiently modified or removed
- * and the underlying persistent state has been externally
- * modified since the transient modification/removal.
- */
+ /**
+ * persistent item that has been transiently modified or removed
+ * and the underlying persistent state has been externally
+ * modified since the transient modification/removal.
+ */
case ItemState.STATUS_STALE_MODIFIED:
ItemState persistentState = state.getOverlayedState();
// the state is a transient wrapper for the underlying
@@ -527,11 +529,11 @@
}
return;
- /**
- * persistent item that has been transiently modified or removed
- * and the underlying persistent state has been externally
- * destroyed since the transient modification/removal.
- */
+ /**
+ * persistent item that has been transiently modified or removed
+ * and the underlying persistent state has been externally
+ * destroyed since the transient modification/removal.
+ */
case ItemState.STATUS_STALE_DESTROYED:
// set state of this instance to 'destroyed'
status = STATUS_DESTROYED;
@@ -543,9 +545,9 @@
notifyDestroyed();
return;
- /**
- * new item that has been transiently added
- */
+ /**
+ * new item that has been transiently added
+ */
case ItemState.STATUS_NEW:
// set state of this instance to 'destroyed'
status = STATUS_DESTROYED;
@@ -622,12 +624,17 @@
ArrayList dirty = new ArrayList();
ItemState transientState;
+ // list of events that are generated by saved changes
+ EventStateCollection events = new EventStateCollection(ticket.getUserId());
+
// check status of this item's state
if (isTransient()) {
switch (state.getStatus()) {
case ItemState.STATUS_EXISTING_MODIFIED:
// add this item's state to the list
dirty.add(state);
+ // create event
+ events.createEventStates(state);
break;
case ItemState.STATUS_NEW:
@@ -666,8 +673,10 @@
switch (transientState.getStatus()) {
case ItemState.STATUS_NEW:
case ItemState.STATUS_EXISTING_MODIFIED:
- // add new or modified state to the list
+ // add modified state to the list
dirty.add(transientState);
+ // create events
+ events.createEventStates(transientState);
break;
case ItemState.STATUS_STALE_MODIFIED:
@@ -782,6 +791,10 @@
// dispose the transient state, it is no longer used
itemMgr.getTransientStateMgr().disposeItemState(transientState);
}
+
+ // all changes are persisted, now dispatch events
+ WorkspaceImpl ws = (WorkspaceImpl) ticket.getWorkspace();
+
ws.getRepository().getObservationManagerFactory(ws.wsDef).dispatchEvents(events);
}
/**
1.11 +23 -2
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryImpl.java
Index: RepositoryImpl.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryImpl.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- RepositoryImpl.java 30 Jun 2004 14:36:32 -0000 1.10
+++ RepositoryImpl.java 1 Jul 2004 18:29:41 -0000 1.11
@@ -26,6 +26,7 @@
import org.apache.commons.collections.BeanMap;
import org.apache.log4j.Logger;
import org.apache.slide.jcr.core.nodetype.NodeTypeRegistry;
+import org.apache.slide.jcr.core.observation.ObservationManagerFactory;
import org.apache.slide.jcr.core.state.ItemStateException;
import org.apache.slide.jcr.core.state.PersistenceManager;
import org.apache.slide.jcr.core.state.PersistentItemStateManager;
@@ -77,6 +78,9 @@
// the same named workspace, i.e. the same physical storage)
private final HashMap wspStateMgrs = new HashMap();
+ // map of observation managers
+ private final HashMap wspObsMgrFactory = new HashMap();
+
/**
* Package private constructor.
*
@@ -269,6 +273,17 @@
return stateMgr;
}
+ synchronized ObservationManagerFactory
getObservationManagerFactory(WorkspaceDef wd) {
+ String wspName = wd.getName();
+ ObservationManagerFactory obsMgr
+ = (ObservationManagerFactory) wspObsMgrFactory.get(wspName);
+ if (obsMgr == null) {
+ obsMgr = new ObservationManagerFactory();
+ wspObsMgrFactory.put(wspName, obsMgr);
+ }
+ return obsMgr;
+ }
+
/**
* @param wspDef
* @return
@@ -312,6 +327,12 @@
repStore.close();
} catch (FileSystemException e) {
log.error("Error while closing filesystem", e);
+ }
+
+ // stop / dispose all ObservationManagers
+ for (Iterator it = wspObsMgrFactory.values().iterator(); it.hasNext();) {
+ ObservationManagerFactory obsMgr = (ObservationManagerFactory) it.next();
+ obsMgr.dispose();
}
}
1.6 +4 -4
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemManager.java
Index: ItemManager.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemManager.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ItemManager.java 24 Jun 2004 16:31:06 -0000 1.5
+++ ItemManager.java 1 Jul 2004 18:29:41 -0000 1.6
@@ -61,7 +61,7 @@
* @author Stefan Guggisberg
* @version $Revision$, $Date$
*/
-class ItemManager implements ItemLifeCycleListener, HierarchyManager {
+public class ItemManager implements ItemLifeCycleListener, HierarchyManager {
private static Logger log = Logger.getLogger(ItemManager.class);
@@ -244,7 +244,7 @@
* @return
* @throws RepositoryException
*/
- synchronized ItemImpl getItem(ItemId id)
+ public synchronized ItemImpl getItem(ItemId id)
throws ItemNotFoundException, AccessDeniedException, RepositoryException {
// check privileges
if (!((AccessManagerImpl) ticket.getAccessManager()).isGranted(id,
Permission.READ_ITEM)) {
1.4 +32 -21
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/NamespaceRegistryImpl.java
Index: NamespaceRegistryImpl.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/NamespaceRegistryImpl.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- NamespaceRegistryImpl.java 22 Jun 2004 18:03:07 -0000 1.3
+++ NamespaceRegistryImpl.java 1 Jul 2004 18:29:41 -0000 1.4
@@ -30,12 +30,12 @@
import javax.jcr.NamespaceException;
import javax.jcr.NamespaceRegistry;
import javax.jcr.RepositoryException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Properties;
import java.util.Iterator;
-import java.io.OutputStream;
-import java.io.InputStream;
+import java.util.Properties;
/**
* A <code>NamespaceRegistryImpl</code> ...
@@ -98,6 +98,7 @@
/**
* Package private constructor: Constructs a new instance of this class.
+ *
* @param nsRegStore
* @throws RepositoryException
*/
@@ -179,7 +180,7 @@
while (iter.hasNext()) {
String prefix = (String) iter.next();
String uri = (String) prefixToURI.get(prefix);
- props.setProperty(prefix, uri);
+ props.setProperty(prefix, uri);
}
try {
@@ -201,6 +202,12 @@
*/
public void registerNamespace(String prefix, String uri)
throws NamespaceException, RepositoryException {
+ if (prefix == null || uri == null) {
+ throw new IllegalArgumentException("prefix/uri can not be null");
+ }
+ if (NS_EMPTY_PREFIX.equals(prefix) || NS_DEFAULT_URI.equals(uri)) {
+ throw new NamespaceException("default namespace is reserved and can not be
changed");
+ }
if (reservedURIs.contains(uri)) {
throw new NamespaceException("failed to register namespace " + prefix + "
-> " + uri + ": reserved URI");
}
@@ -208,13 +215,24 @@
throw new NamespaceException("failed to register namespace " + prefix + "
-> " + uri + ": reserved prefix");
}
- if (uriToPrefix.containsKey(uri)) {
- throw new NamespaceException("failed to register namespace " + prefix + "
-> " + uri + ": URI already exists");
+ String oldPrefix = (String) uriToPrefix.get(uri);
+ if (oldPrefix != null) {
+ // existing namespace
+ if (oldPrefix.equals(prefix)) {
+ throw new NamespaceException("failed to register namespace " + prefix
+ " -> " + uri + ": mapping already exists");
+ }
+ // remove old prefix
+ prefixToURI.remove(oldPrefix);
+ uriToPrefix.remove(uri);
}
+
if (prefixToURI.containsKey(prefix)) {
- throw new NamespaceException("failed to register namespace " + prefix + "
-> " + uri + ": prefix already exists");
+ // prevent remapping of existing prefixes because this would in effect
+ // remove the previously assigned namespace;
+ // as we can't guarantee that there are no references to this namespace
+ // (in names of nodes/properties/node types etc.) we simply don't allow it.
+ throw new NamespaceException("failed to register namespace " + prefix + "
-> " + uri + ": remapping existing prefixes is not supported.");
}
- // @todo implement further validations according to spec
prefixToURI.put(prefix, uri);
uriToPrefix.put(uri, prefix);
@@ -234,17 +252,10 @@
if (!prefixToURI.containsKey(prefix)) {
throw new NamespaceException("unknown prefix: " + prefix);
}
- throw new NamespaceException("not yet supported");
-
- // @todo implement further validations according to spec
-/*
- String uri = getURI(prefix);
- prefixToURI.remove(prefix);
- uriToPrefix.remove(uri);
-
- // persist mappings
- store();
-*/
+ // as we can't guarantee that there are no references to the specified
+ // namespace (in names of nodes/properties/node types etc.) we simply
+ // don't allow it.
+ throw new NamespaceException("unregistering namespaces is not supported.");
}
/**
1.10 +36 -8
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/TicketImpl.java
Index: TicketImpl.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/TicketImpl.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- TicketImpl.java 22 Jun 2004 18:03:07 -0000 1.9
+++ TicketImpl.java 1 Jul 2004 18:29:41 -0000 1.10
@@ -119,7 +119,7 @@
}
ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), this);
- wsp = new WorkspaceImpl(wd.getName(), rep.getWorkspaceStateManager(wd), rep,
this);
+ wsp = new WorkspaceImpl(wd, rep.getWorkspaceStateManager(wd), rep, this);
itemMgr = new ItemManager(wsp.getPersistentStateManager(), this,
ntMgr.getRootNodeDefinition(), rep.getRootNodeUUID());
accessMgr = new AccessManagerImpl(credentials, itemMgr.getHierarchyMgr(),
getNamespaceResolver());
@@ -357,6 +357,8 @@
// discard all transient changes
itemMgr.getTransientStateMgr().disposeAllItemStates();
+ log.debug("disposing workspace");
+ wsp.dispose();
// @todo implement logout, i.e. invalidate ticket, free resources, prepare to
get gc'ed etc.
}
@@ -450,7 +452,15 @@
void setNamespacePrefix(String prefix, String uri)
throws NamespaceException, RepositoryException {
- // check if namespace exists
+ if (prefix == null || uri == null) {
+ throw new IllegalArgumentException("prefix/uri can not be null");
+ }
+ if (NamespaceRegistryImpl.NS_EMPTY_PREFIX.equals(prefix) ||
+ NamespaceRegistryImpl.NS_DEFAULT_URI.equals(uri)) {
+ throw new NamespaceException("default namespace is reserved and can
not be changed");
+ }
+ // check if namespace exists (the following call will
+ // trigger a NamespaceException if it doesn't)
String globalPrefix = nsReg.getPrefix(uri);
// check new prefix for collision
@@ -463,8 +473,11 @@
if (globalURI != null) {
// prefix is already mapped in global namespace registry;
// check if it refers to a namespace that has been locally
- // remapped
+ // remapped, thus hiding it
if (!hiddenPrefixes.contains(prefix)) {
+ // we don't allow to hide a namespace because we can't
+ // guarantee that there are no references to it
+ // (in names of nodes/properties/node types etc.)
throw new NamespaceException(prefix + ": prefix is already mapped
to the namespace: " + globalURI);
}
}
@@ -472,14 +485,29 @@
// check if namespace is already locally mapped
String oldPrefix = (String) uriToPrefix.get(uri);
if (oldPrefix != null) {
+ // resurrect hidden global prefix
+ hiddenPrefixes.remove(nsReg.getPrefix(uri));
// remove old mapping
uriToPrefix.remove(uri);
prefixToURI.remove(oldPrefix);
}
- prefixToURI.put(prefix, uri);
- uriToPrefix.put(uri, prefix);
- hiddenPrefixes.add(globalPrefix);
+ // check if prefix is already locally mapped
+ String oldURI = (String) prefixToURI.get(prefix);
+ if (oldURI != null) {
+ // resurrect hidden global prefix
+ hiddenPrefixes.remove(nsReg.getPrefix(oldURI));
+ // remove old mapping
+ uriToPrefix.remove(oldURI);
+ prefixToURI.remove(prefix);
+ }
+
+ if (!prefix.equals(globalPrefix)) {
+ // store new mapping
+ prefixToURI.put(prefix, uri);
+ uriToPrefix.put(uri, prefix);
+ hiddenPrefixes.add(globalPrefix);
+ }
}
String[] getPrefixes() {
1.4 +38 -15
jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/WorkspaceImpl.java
Index: WorkspaceImpl.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/WorkspaceImpl.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- WorkspaceImpl.java 22 Jun 2004 18:03:07 -0000 1.3
+++ WorkspaceImpl.java 1 Jul 2004 18:29:41 -0000 1.4
@@ -33,6 +33,8 @@
import javax.jcr.access.AccessManager;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.EventListenerIterator;
import javax.jcr.observation.ObservationManager;
import javax.jcr.query.QueryManager;
import javax.jcr.version.Version;
@@ -52,10 +54,9 @@
private static Logger log = Logger.getLogger(WorkspaceImpl.class);
/**
- * the name of the workspace represented by <i>this</i>
- * <code>Workspace</code> instance
+ * The <code>WorkspaceDef</code> for this <code>Workspace</code> instance.
*/
- protected final String name;
+ protected final WorkspaceDef wsDef;
/**
* The repository that created this workspace instance
@@ -69,6 +70,11 @@
protected final PersistentItemStateManager persistentStateMgr;
/**
+ * The <code>ObservationManager</code> instance for this ticket.
+ */
+ protected ObservationManager obsMgr;
+
+ /**
* the ticket that was used to acquire this <code>Workspace</code>
*/
protected final TicketImpl ticket;
@@ -76,13 +82,13 @@
/**
* Package private constructor.
*
- * @param name
+ * @param wsDef
* @param persistentStateMgr
* @param rep
* @param ticket
*/
- WorkspaceImpl(String name, PersistentItemStateManager persistentStateMgr,
RepositoryImpl rep, TicketImpl ticket) {
- this.name = name;
+ WorkspaceImpl(WorkspaceDef wsDef, PersistentItemStateManager
persistentStateMgr, RepositoryImpl rep, TicketImpl ticket) {
+ this.wsDef = wsDef;
this.rep = rep;
this.persistentStateMgr = persistentStateMgr;
this.ticket = ticket;
@@ -101,21 +107,37 @@
* (used for diagnostic purposes).
*
* @param ps
- *
* @throws RepositoryException
*/
void dump(PrintStream ps) throws RepositoryException {
- ps.println("Workspace: " + name + " (" + this + ")");
+ ps.println("Workspace: " + wsDef.getName() + " (" + this + ")");
ps.println();
persistentStateMgr.dump(ps);
}
+ /**
+ * Disposes this <code>WorkspaceImpl</code> and frees resources.
+ */
+ void dispose() {
+ try {
+ ObservationManager om = getObservationManager();
+ EventListenerIterator it = om.getRegisteredEventListeners();
+ while (it.hasNext()) {
+ EventListener l = it.nextEventListener();
+ log.debug("removing EventListener: " + l);
+ om.removeEventListener(l);
+ }
+ } catch (RepositoryException e) {
+ log.error("Exception while disposing Workspace:", e);
+ }
+ }
+
//------------------------------------------------------------< Workspace >
/**
* @see Workspace#getName
*/
public String getName() {
- return name;
+ return wsDef.getName();
}
/**
@@ -189,10 +211,11 @@
/**
* @see Workspace#getObservationManager
*/
- public ObservationManager getObservationManager()
- throws UnsupportedRepositoryOperationException {
- // @todo implement observation support
- throw new UnsupportedRepositoryOperationException();
+ public synchronized ObservationManager getObservationManager() {
+ if (obsMgr == null) {
+ obsMgr =
rep.getObservationManagerFactory(wsDef).createObservationManager(ticket,
ticket.itemMgr);
+ }
+ return obsMgr;
}
/**
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]