You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by dp...@apache.org on 2006/12/05 17:47:04 UTC
svn commit: r482707 - in
/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core:
./ cluster/ nodetype/
Author: dpfister
Date: Tue Dec 5 08:47:02 2006
New Revision: 482707
URL: http://svn.apache.org/viewvc?view=rev&rev=482707
Log:
JCR-623 - Clustering
+ Transmit namespace registrations
+ Transmit nodetype registrations
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NamespaceEventChannel.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NamespaceEventListener.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileJournal.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileRecordInput.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileRecordOutput.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/Journal.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/RecordProcessor.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java?view=diff&rev=482707&r1=482706&r2=482707
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java Tue Dec 5 08:47:02 2006
@@ -18,6 +18,8 @@
import org.apache.jackrabbit.core.fs.FileSystem;
import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.jackrabbit.core.cluster.NamespaceEventChannel;
+import org.apache.jackrabbit.core.cluster.NamespaceEventListener;
import org.apache.jackrabbit.name.AbstractNamespaceResolver;
import org.apache.jackrabbit.name.QName;
import org.apache.jackrabbit.name.NameCache;
@@ -41,7 +43,7 @@
* A <code>NamespaceRegistryImpl</code> ...
*/
public class NamespaceRegistryImpl extends AbstractNamespaceResolver
- implements NamespaceRegistry, NameCache {
+ implements NamespaceRegistry, NameCache, NamespaceEventListener {
private static Logger log = LoggerFactory.getLogger(NamespaceRegistryImpl.class);
@@ -79,6 +81,11 @@
private final FileSystem nsRegStore;
/**
+ * Namespace event channel.
+ */
+ private NamespaceEventChannel eventChannel;
+
+ /**
* Protected constructor: Constructs a new instance of this class.
*
* @param nsRegStore
@@ -249,6 +256,16 @@
}
}
+ /**
+ * Set an event channel to inform about changes.
+ *
+ * @param eventChannel event channel
+ */
+ public void setEventChannel(NamespaceEventChannel eventChannel) {
+ this.eventChannel = eventChannel;
+ eventChannel.setListener(this);
+ }
+
//----------------------------------------------------< NamespaceRegistry >
/**
* {@inheritDoc}
@@ -309,6 +326,10 @@
prefixToURI.put(prefix, uri);
uriToPrefix.put(uri, prefix);
+ if (eventChannel != null) {
+ eventChannel.remapped(oldPrefix, prefix, uri);
+ }
+
// persist mappings
store();
@@ -403,5 +424,46 @@
public void evictAllNames() {
// just delegate to internal cache
resolver.evictAllNames();
+ }
+
+ //-----------------------------------------------< NamespaceEventListener >
+
+ /**
+ * {@inheritDoc}
+ */
+ public void externalRemap(String oldPrefix, String newPrefix, String uri)
+ throws RepositoryException {
+
+ if (newPrefix == null) {
+ /**
+ * 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.");
+ }
+
+ if (oldPrefix != null) {
+ // remove old prefix mapping
+ prefixToURI.remove(oldPrefix);
+ uriToPrefix.remove(uri);
+ }
+
+ // add new prefix mapping
+ prefixToURI.put(newPrefix, uri);
+ uriToPrefix.put(uri, newPrefix);
+
+ // persist mappings
+ store();
+
+ // notify listeners
+ if (oldPrefix != null) {
+ // remapped existing namespace uri to new prefix
+ notifyNamespaceRemapped(oldPrefix, newPrefix, uri);
+ } else {
+ // added new namespace uri mapped to prefix
+ notifyNamespaceAdded(newPrefix, uri);
+ }
+
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?view=diff&rev=482707&r1=482706&r2=482707
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Tue Dec 5 08:47:02 2006
@@ -274,6 +274,8 @@
// will be interested in
if (repConfig.getClusterConfig() != null) {
clusterNode = createClusterNode();
+ nsReg.setEventChannel(clusterNode);
+ ntReg.setEventChannel(clusterNode);
}
// init version manager
@@ -365,7 +367,7 @@
VersionManagerImpl vMgr = new VersionManagerImpl(pm, fs, ntReg, delegatingDispatcher,
VERSION_STORAGE_NODE_ID, SYSTEM_ROOT_NODE_ID, cacheFactory);
if (clusterNode != null) {
- vMgr.setEventChannel(clusterNode.createUpdateChannel());
+ vMgr.setEventChannel(clusterNode);
}
return vMgr;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java?view=diff&rev=482707&r1=482706&r2=482707
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java Tue Dec 5 08:47:02 2006
@@ -21,6 +21,8 @@
import org.apache.jackrabbit.core.config.ClusterConfig;
import org.apache.jackrabbit.core.config.ConfigurationException;
import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
+import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException;
import org.apache.jackrabbit.core.observation.EventState;
import org.apache.jackrabbit.core.observation.EventStateCollection;
import org.apache.jackrabbit.core.state.ChangeLog;
@@ -36,11 +38,13 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
+import java.util.Collection;
/**
* Default clustered node implementation.
*/
-public class ClusterNode implements Runnable, UpdateEventChannel {
+public class ClusterNode implements Runnable, UpdateEventChannel,
+ NamespaceEventChannel, NodeTypeEventChannel {
/**
* System property specifying a node id to use.
@@ -103,6 +107,16 @@
private UpdateEventListener versionUpdateListener;
/**
+ * Namespace listener.
+ */
+ private NamespaceEventListener namespaceListener;
+
+ /**
+ * Node type listener.
+ */
+ private NodeTypeEventListener nodeTypeListener;
+
+ /**
* Initialize this cluster node.
*
* @throws ClusterException if an error occurs
@@ -240,15 +254,6 @@
}
/**
- * Create an {@link UpdateEventChannel} for versioning operations.
- *
- * @return update event channel
- */
- public UpdateEventChannel createUpdateChannel() {
- return this;
- }
-
- /**
* Create an {@link UpdateEventChannel} for some workspace.
*
* @param workspace workspace name
@@ -386,6 +391,58 @@
versionUpdateListener = listener;
}
+ //-----------------------------------------------< NamespaceEventListener >
+
+ /**
+ * {@inheritDoc}
+ */
+ public void remapped(String oldPrefix, String newPrefix, String uri) {
+ try {
+ journal.begin(null);
+ journal.log(oldPrefix, newPrefix, uri);
+ journal.prepare();
+ journal.commit();
+ } catch (JournalException e) {
+ String msg = "Unable to create log entry: " + e.getMessage();
+ log.error(msg);
+ } catch (Throwable e) {
+ String msg = "Unexpected error while creating log entry.";
+ log.error(msg, e);
+ }
+ }
+
+ public void setListener(NamespaceEventListener listener) {
+ namespaceListener = listener;
+ }
+
+ //------------------------------------------------< NodeTypeEventListener >
+
+ /**
+ * {@inheritDoc}
+ */
+ public void registered(Collection ntDefs) {
+ try {
+ journal.begin(null);
+ journal.log(ntDefs);
+ journal.prepare();
+ journal.commit();
+ } catch (JournalException e) {
+ String msg = "Unable to create log entry: " + e.getMessage();
+ log.error(msg);
+ } catch (Throwable e) {
+ String msg = "Unexpected error while creating log entry.";
+ log.error(msg, e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setListener(NodeTypeEventListener listener) {
+ nodeTypeListener = listener;
+ }
+
+
/**
* Workspace update channel.
*/
@@ -570,7 +627,6 @@
* {@inheritDoc}
*/
public void process(NodeId nodeId, boolean isDeep, String owner) {
- //todo should be aggregated
LockEventListener listener = (LockEventListener) wspLockListeners.get(workspace);
if (listener == null) {
try {
@@ -599,19 +655,18 @@
* {@inheritDoc}
*/
public void process(NodeId nodeId) {
- //todo should be aggregated
LockEventListener listener = (LockEventListener) wspLockListeners.get(workspace);
if (listener == null) {
try {
clusterContext.lockEventsReady(workspace);
} catch (RepositoryException e) {
- String msg = "Error making lock listener for workspace " +
+ String msg = "Unable to make lock listener for workspace " +
workspace + " online: " + e.getMessage();
log.warn(msg);
}
listener = (LockEventListener) wspLockListeners.get(workspace);
if (listener == null) {
- String msg = "Lock listener unavailable for workspace: " + workspace;
+ String msg = "Lock channel unavailable for workspace: " + workspace;
log.error(msg);
return;
}
@@ -619,7 +674,44 @@
try {
listener.externalUnlock(nodeId);
} catch (RepositoryException e) {
- String msg = "Unable to deliver unlock event: " + e.getMessage();
+ String msg = "Unable to deliver lock event: " + e.getMessage();
+ log.error(msg);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void process(String oldPrefix, String newPrefix, String uri) {
+ if (namespaceListener == null) {
+ String msg = "Namespace listener unavailable.";
+ log.error(msg);
+ return;
+ }
+ try {
+ namespaceListener.externalRemap(oldPrefix, newPrefix, uri);
+ } catch (RepositoryException e) {
+ String msg = "Unable to deliver namespace operation: " + e.getMessage();
+ log.error(msg);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void process(Collection ntDefs) {
+ if (nodeTypeListener == null) {
+ String msg = "NodeType listener unavailable.";
+ log.error(msg);
+ return;
+ }
+ try {
+ nodeTypeListener.externalRegistered(ntDefs);
+ } catch (InvalidNodeTypeDefException e) {
+ String msg = "Unable to deliver node type operation: " + e.getMessage();
+ log.error(msg);
+ } catch (RepositoryException e) {
+ String msg = "Unable to deliver node type operation: " + e.getMessage();
log.error(msg);
}
}
@@ -652,6 +744,7 @@
} else {
String msg = "Version update listener unavailable.";
log.error(msg);
+ return;
}
}
try {
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileJournal.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileJournal.java?view=diff&rev=482707&r1=482706&r2=482707
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileJournal.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileJournal.java Tue Dec 5 08:47:02 2006
@@ -17,6 +17,8 @@
package org.apache.jackrabbit.core.cluster;
import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
+import org.apache.jackrabbit.core.nodetype.compact.ParseException;
import org.apache.jackrabbit.core.state.ChangeLog;
import org.apache.jackrabbit.core.state.ItemState;
import org.apache.jackrabbit.core.state.NodeState;
@@ -39,6 +41,7 @@
import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;
+import java.util.Collection;
import EDU.oswego.cs.dl.util.concurrent.Mutex;
@@ -320,9 +323,6 @@
try {
workspace = in.readString();
- if (workspace.equals("")) {
- workspace = null;
- }
processor.start(workspace);
for (;;) {
@@ -356,13 +356,26 @@
childRelPath, ntName, mixins, userId);
} else if (c == 'L') {
NodeId nodeId = in.readNodeId();
- boolean isDeep = in.readBoolean();
- String owner = in.readString();
-
- processor.process(nodeId, isDeep, owner);
- } else if (c == 'U') {
- NodeId nodeId = in.readNodeId();
- processor.process(nodeId);
+ boolean isLock = in.readBoolean();
+ if (isLock) {
+ boolean isDeep = in.readBoolean();
+ String owner = in.readString();
+ processor.process(nodeId, isDeep, owner);
+ } else {
+ processor.process(nodeId);
+ }
+ } else if (c == 'S') {
+ String oldPrefix = in.readString();
+ String newPrefix = in.readString();
+ String uri = in.readString();
+ processor.process(oldPrefix, newPrefix, uri);
+ } else if (c == 'T') {
+ int size = in.readInt();
+ HashSet ntDefs = new HashSet();
+ for (int i = 0; i < size; i++) {
+ ntDefs.add(in.readNodeTypeDef());
+ }
+ processor.process(ntDefs);
} else {
throw new IllegalArgumentException("Unknown entry type: " + c);
}
@@ -373,6 +386,10 @@
String msg = "Unable to read revision " + record.getRevision() +
": " + e.getMessage();
throw new JournalException(msg);
+ } catch (ParseException e) {
+ String msg = "Unable to read revision " + record.getRevision() +
+ ": " + e.getMessage();
+ throw new JournalException(msg);
} catch (IOException e) {
String msg = "Unable to read revision " + record.getRevision() +
": " + e.getMessage();
@@ -406,7 +423,7 @@
record = new FileRecord(id, tempLog);
out = record.getOutput(resolver);
- out.writeString(workspace != null ? workspace : "");
+ out.writeString(workspace);
succeeded = true;
} catch (IOException e) {
@@ -461,12 +478,12 @@
/**
* {@inheritDoc}
*/
- public void log(NodeId nodeId, boolean isDeep, String owner) throws JournalException {
+ public void log(String oldPrefix, String newPrefix, String uri) throws JournalException {
try {
- out.writeChar('L');
- out.writeNodeId(nodeId);
- out.writeBoolean(isDeep);
- out.writeString(owner);
+ out.writeChar('S');
+ out.writeString(oldPrefix);
+ out.writeString(newPrefix);
+ out.writeString(uri);
} catch (IOException e) {
String msg = "Unable to write to journal log " + tempLog + ": " + e.getMessage();
throw new JournalException(msg);
@@ -476,14 +493,34 @@
/**
* {@inheritDoc}
*/
+ public void log(NodeId nodeId, boolean isDeep, String owner) throws JournalException {
+ log(nodeId, true, isDeep, owner);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void log(NodeId nodeId) throws JournalException {
+ log(nodeId, false, false, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void log(Collection ntDefs) throws JournalException {
try {
- out.writeChar('U');
- out.writeNodeId(nodeId);
+ out.writeChar('T');
+ out.writeInt(ntDefs.size());
+
+ Iterator iter = ntDefs.iterator();
+ while (iter.hasNext()) {
+ out.writeNodeTypeDef((NodeTypeDef) iter.next());
+ }
} catch (IOException e) {
String msg = "Unable to write to journal log " + tempLog + ": " + e.getMessage();
throw new JournalException(msg);
}
+
}
/**
@@ -546,6 +583,32 @@
} catch (NoPrefixDeclaredException e) {
String msg = "Unable to write to journal log " + tempLog + ": " + e.getMessage();
throw new JournalException(msg);
+ } catch (IOException e) {
+ String msg = "Unable to write to journal log " + tempLog + ": " + e.getMessage();
+ throw new JournalException(msg);
+ }
+ }
+
+ /**
+ * Log either a lock or an unlock operation.
+ *
+ * @param nodeId node id
+ * @param isLock <code>true</code> if this is a lock;
+ * <code>false</code> if this is an unlock
+ * @param isDeep flag indicating whether lock is deep
+ * @param owner lock owner
+ */
+ protected void log(NodeId nodeId, boolean isLock, boolean isDeep, String owner)
+ throws JournalException {
+
+ try {
+ out.writeChar('L');
+ out.writeNodeId(nodeId);
+ out.writeBoolean(isLock);
+ if (isLock) {
+ out.writeBoolean(isDeep);
+ out.writeString(owner);
+ }
} catch (IOException e) {
String msg = "Unable to write to journal log " + tempLog + ": " + e.getMessage();
throw new JournalException(msg);
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileRecordInput.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileRecordInput.java?view=diff&rev=482707&r1=482706&r2=482707
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileRecordInput.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileRecordInput.java Tue Dec 5 08:47:02 2006
@@ -18,6 +18,9 @@
import org.apache.jackrabbit.core.NodeId;
import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
+import org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefReader;
+import org.apache.jackrabbit.core.nodetype.compact.ParseException;
import org.apache.jackrabbit.name.NamespaceResolver;
import org.apache.jackrabbit.name.QName;
import org.apache.jackrabbit.name.NameFormat;
@@ -31,7 +34,9 @@
import java.io.IOException;
import java.io.DataInputStream;
+import java.io.StringReader;
import java.util.ArrayList;
+import java.util.List;
/**
* Allows reading data from a <code>FileRecord</code>.
@@ -120,13 +125,18 @@
/**
* Read a string from the underlying stream.
*
- * @return string
+ * @return string or <code>null</code>
* @throws IOException if an I/O error occurs
*/
public String readString() throws IOException {
checkOpen();
- return in.readUTF();
+ boolean isNull = in.readBoolean();
+ if (isNull) {
+ return null;
+ } else {
+ return in.readUTF();
+ }
}
/**
@@ -218,6 +228,24 @@
return new PropertyId(readNodeId(), readQName());
}
+
+ /**
+ * Read a <code>NodeTypeDef</code>
+ */
+ public NodeTypeDef readNodeTypeDef() throws IOException, ParseException {
+ checkOpen();
+
+ StringReader sr = new StringReader(readString());
+
+ CompactNodeTypeDefReader reader = new CompactNodeTypeDefReader(sr, "(internal)");
+ List ntds = reader.getNodeTypeDefs();
+ if (ntds.size() != 1) {
+ throw new IOException("Expected one node type definition: got " + ntds.size());
+ }
+ return (NodeTypeDef) ntds.get(0);
+ }
+
+
/**
* Close this input. Does not close underlying stream as this is a shared resource.
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileRecordOutput.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileRecordOutput.java?view=diff&rev=482707&r1=482706&r2=482707
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileRecordOutput.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/FileRecordOutput.java Tue Dec 5 08:47:02 2006
@@ -18,6 +18,8 @@
import org.apache.jackrabbit.core.NodeId;
import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
+import org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefWriter;
import org.apache.jackrabbit.name.NamespaceResolver;
import org.apache.jackrabbit.name.QName;
import org.apache.jackrabbit.name.NameFormat;
@@ -27,6 +29,7 @@
import java.io.IOException;
import java.io.DataOutputStream;
+import java.io.StringWriter;
import java.util.ArrayList;
/**
@@ -123,13 +126,18 @@
/**
* Write a string from the underlying stream.
*
- * @param s string
+ * @param s string, may be <code>null</code>
* @throws IOException if an I/O error occurs
*/
public void writeString(String s) throws IOException {
checkOpen();
- out.writeUTF(s);
+ if (s == null) {
+ out.writeBoolean(true);
+ } else {
+ out.writeBoolean(false);
+ out.writeUTF(s);
+ }
}
/**
@@ -210,6 +218,20 @@
writeNodeId(propertyId.getParentId());
writeQName(propertyId.getName());
+ }
+
+ /**
+ * Write a <code>NodeTypeDef</code>
+ */
+ public void writeNodeTypeDef(NodeTypeDef ntd) throws IOException {
+ checkOpen();
+
+ StringWriter sw = new StringWriter();
+ CompactNodeTypeDefWriter writer = new CompactNodeTypeDefWriter(sw, resolver, true);
+ writer.write(ntd);
+ writer.close();
+
+ writeString(sw.toString());
}
/**
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/Journal.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/Journal.java?view=diff&rev=482707&r1=482706&r2=482707
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/Journal.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/Journal.java Tue Dec 5 08:47:02 2006
@@ -19,7 +19,11 @@
import org.apache.jackrabbit.core.state.ChangeLog;
import org.apache.jackrabbit.core.observation.EventStateCollection;
import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.name.QName;
+
+import java.util.Collection;
/**
* Journal interface. Defines operations on a journal that are used to synchronize clustered repository nodes.
@@ -67,7 +71,8 @@
* @param owner lock owner
* @throws JournalException if an error occurs
*/
- public void log(NodeId nodeId, boolean isDeep, String owner) throws JournalException;
+ public void log(NodeId nodeId, boolean isDeep, String owner)
+ throws JournalException;
/**
* Log an unlock operation.
@@ -76,6 +81,23 @@
* @throws JournalException if an error occurs
*/
public void log(NodeId nodeId) throws JournalException;
+
+ /**
+ * Log a namespace registry operation.
+ *
+ * @param oldPrefix old prefix
+ * @param newPrefix new prefix
+ * @param uri URI
+ * @throws JournalException if an error occurs
+ */
+ public void log(String oldPrefix, String newPrefix, String uri) throws JournalException;
+
+ /**
+ * Log on or more node type registrations or reregistration.
+ *
+ * @param ntDefs node type definitions
+ */
+ public void log(Collection ntDefs) throws JournalException;
/**
* Prepare an update operation on the journal. This locks the journal exclusively for updates until this client
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NamespaceEventChannel.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NamespaceEventChannel.java?view=auto&rev=482707
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NamespaceEventChannel.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NamespaceEventChannel.java Tue Dec 5 08:47:02 2006
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.jackrabbit.core.cluster;
+
+/**
+ * Event channel used to transmit namespace registry operations.
+ */
+public interface NamespaceEventChannel {
+
+ /**
+ * Called when a namespace has been remapped.
+ *
+ * @param oldPrefix old prefix. if <code>null</code> this is a fresh mapping
+ * @param newPrefix new prefix. if <code>null</code> this is an unmap operation
+ * @param uri uri to map prefix to
+ */
+ public void remapped(String oldPrefix, String newPrefix, String uri);
+
+ /**
+ * Set listener that will receive information about incoming, external namespace events.
+ *
+ * @param listener namespace event listener
+ */
+ public void setListener(NamespaceEventListener listener);
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NamespaceEventListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NamespaceEventListener.java?view=auto&rev=482707
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NamespaceEventListener.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NamespaceEventListener.java Tue Dec 5 08:47:02 2006
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.jackrabbit.core.cluster;
+
+import org.apache.jackrabbit.core.NodeId;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Interface used to receive information about incoming, external namespace registry events.
+ */
+public interface NamespaceEventListener {
+
+ /**
+ * Called when a namespace has been externally remapped.
+ *
+ * @param oldPrefix old prefix. if <code>null</code> this is a fresh mapping
+ * @param newPrefix new prefix. if <code>null</code> this is an unmap operation
+ * @param uri uri to map prefix to
+ * @throws RepositoryException if an error occurs
+ */
+ public void externalRemap(String oldPrefix, String newPrefix, String uri)
+ throws RepositoryException;
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java?view=auto&rev=482707
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java Tue Dec 5 08:47:02 2006
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.jackrabbit.core.cluster;
+
+import java.util.Collection;
+
+/**
+ * Event channel used to transmit nodetype registry operations.
+ */
+public interface NodeTypeEventChannel {
+
+ /**
+ * Called when one or more node types have been registered.
+ *
+ * @param ntDefs collection of node type definitions
+ */
+ public void registered(Collection ntDefs);
+
+ /**
+ * Set listener that will receive information about incoming, external node type events.
+ *
+ * @param listener node type event listener
+ */
+ public void setListener(NodeTypeEventListener listener);
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java?view=auto&rev=482707
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java Tue Dec 5 08:47:02 2006
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.jackrabbit.core.cluster;
+
+import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException;
+
+import javax.jcr.RepositoryException;
+import java.util.Collection;
+
+/**
+ * Interface used to receive information about incoming, external node type registry events.
+ */
+public interface NodeTypeEventListener {
+
+ /**
+ * Called when one or more node types have been externally registered.
+ *
+ * @param ntDefs node type definitions
+ * @throws RepositoryException if an error occurs
+ * @throws InvalidNodeTypeDefException if the node type definition is invalid
+ */
+ public void externalRegistered(Collection ntDefs)
+ throws RepositoryException, InvalidNodeTypeDefException;
+}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/RecordProcessor.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/RecordProcessor.java?view=diff&rev=482707&r1=482706&r2=482707
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/RecordProcessor.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/RecordProcessor.java Tue Dec 5 08:47:02 2006
@@ -21,6 +21,7 @@
import org.apache.jackrabbit.name.QName;
import java.util.Set;
+import java.util.Collection;
/**
* Listener interface on a journal that gets called back for records that should be processed.
@@ -70,6 +71,22 @@
* @param nodeId node id
*/
public void process(NodeId nodeId);
+
+ /**
+ * Process a namespace operation.
+ *
+ * @param oldPrefix old prefix. if <code>null</code> this is a fresh mapping
+ * @param newPrefix new prefix. if <code>null</code> this is an unmap operation
+ * @param uri uri to map prefix to
+ */
+ public void process(String oldPrefix, String newPrefix, String uri);
+
+ /**
+ * Process one or more node type registrations.
+ *
+ * @param ntDefs node type definition
+ */
+ public void process(Collection ntDefs);
/**
* Invoked when a record ends.
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java?view=diff&rev=482707&r1=482706&r2=482707
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java Tue Dec 5 08:47:02 2006
@@ -22,6 +22,8 @@
import org.apache.jackrabbit.core.fs.FileSystemResource;
import org.apache.jackrabbit.core.util.Dumpable;
import org.apache.jackrabbit.core.value.InternalValue;
+import org.apache.jackrabbit.core.cluster.NodeTypeEventChannel;
+import org.apache.jackrabbit.core.cluster.NodeTypeEventListener;
import org.apache.jackrabbit.name.QName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -49,7 +51,7 @@
/**
* A <code>NodeTypeRegistry</code> ...
*/
-public class NodeTypeRegistry implements Dumpable {
+public class NodeTypeRegistry implements Dumpable, NodeTypeEventListener {
private static Logger log = LoggerFactory.getLogger(NodeTypeRegistry.class);
@@ -98,6 +100,11 @@
Collections.synchronizedMap(new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK));
/**
+ * Node type event channel.
+ */
+ private NodeTypeEventChannel eventChannel;
+
+ /**
* Create a new <code>NodeTypeRegistry</codes>
*
* @param nsReg
@@ -168,6 +175,12 @@
customNTDefs.add(ntd);
persistCustomNodeTypeDefs(customNTDefs);
+ if (eventChannel != null) {
+ HashSet ntDefs = new HashSet();
+ ntDefs.add(ntd);
+ eventChannel.registered(ntDefs);
+ }
+
// notify listeners
notifyRegistered(ntd.getName());
@@ -196,6 +209,12 @@
customNTDefs.add(ntDef);
}
persistCustomNodeTypeDefs(customNTDefs);
+
+ // inform cluster
+ if (eventChannel != null) {
+ eventChannel.registered(ntDefs);
+ }
+
// notify listeners
for (Iterator iter = ntDefs.iterator(); iter.hasNext();) {
NodeTypeDef ntDef = (NodeTypeDef) iter.next();
@@ -574,6 +593,29 @@
entCache.dump(ps);
}
+ //------------------------------------------------< NodeTypeEventListener >
+
+ /**
+ * {@inheritDoc}
+ */
+ public void externalRegistered(Collection ntDefs)
+ throws RepositoryException, InvalidNodeTypeDefException {
+
+ // validate and register new node type definitions
+ internalRegister(ntDefs);
+ // persist new node type definitions
+ for (Iterator iter = ntDefs.iterator(); iter.hasNext();) {
+ NodeTypeDef ntDef = (NodeTypeDef) iter.next();
+ customNTDefs.add(ntDef);
+ }
+ persistCustomNodeTypeDefs(customNTDefs);
+ // notify listeners
+ for (Iterator iter = ntDefs.iterator(); iter.hasNext();) {
+ NodeTypeDef ntDef = (NodeTypeDef) iter.next();
+ notifyRegistered(ntDef.getName());
+ }
+ }
+
//---------------------------------------------------------< overridables >
/**
* Protected constructor
@@ -851,6 +893,17 @@
public NodeDef getRootNodeDef() {
return rootNodeDef;
}
+
+ /**
+ * Set an event channel to inform about changes.
+ *
+ * @param eventChannel event channel
+ */
+ public void setEventChannel(NodeTypeEventChannel eventChannel) {
+ this.eventChannel = eventChannel;
+ eventChannel.setListener(this);
+ }
+
/**
* @param ntName