You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2005/10/21 16:29:03 UTC
svn commit: r327199 - in
/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit:
core/CachingNamespaceResolver.java core/LocalNamespaceMappings.java
core/NamespaceRegistryImpl.java name/AbstractNamespaceResolver.java
name/NamespaceListener.java
Author: stefan
Date: Fri Oct 21 07:28:53 2005
New Revision: 327199
URL: http://svn.apache.org/viewcvs?rev=327199&view=rev
Log:
JCR-242: locally remap conflicting prefix if the registration of a new global prefix collides with a session-local prefix
Modified:
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/CachingNamespaceResolver.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/LocalNamespaceMappings.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceListener.java
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/CachingNamespaceResolver.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/CachingNamespaceResolver.java?rev=327199&r1=327198&r2=327199&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/CachingNamespaceResolver.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/CachingNamespaceResolver.java Fri Oct 21 07:28:53 2005
@@ -113,12 +113,19 @@
}
//----------------------------------------------------< NamespaceListener >
+ /**
+ * @inheritDoc
+ */
+ public void namespaceAdded(String prefix, String uri) {
+ // since it is a new namespace there's no need to flush the
+ // cached mappings
+ }
/**
* @inheritDoc
* Invalidates all cached mappings.
*/
- public synchronized void prefixRemapped(String prefix, String uri) {
+ public void namespaceRemapped(String oldPrefix, String newPrefix, String uri) {
qnameToJCRName.clear();
jcrNameToQName.clear();
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/LocalNamespaceMappings.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/LocalNamespaceMappings.java?rev=327199&r1=327198&r2=327199&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/LocalNamespaceMappings.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/LocalNamespaceMappings.java Fri Oct 21 07:28:53 2005
@@ -46,7 +46,7 @@
* underlying namespace registry.
*/
class LocalNamespaceMappings extends AbstractNamespaceResolver
- implements NamespaceListener{
+ implements NamespaceListener {
/** The underlying global and persistent namespace registry. */
private final NamespaceRegistryImpl nsReg;
@@ -124,7 +124,9 @@
// 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);
+ throw new NamespaceException(prefix
+ + ": prefix is already mapped to the namespace: "
+ + globalURI);
}
}
@@ -193,6 +195,34 @@
nsReg.removeListener(this);
}
+ /**
+ * {@inheritDoc}
+ */
+ public QName getQName(String name)
+ throws IllegalNameException, UnknownPrefixException {
+ if (prefixToURI.isEmpty()) {
+ // shortcut
+ return nsReg.getQName(name);
+ }
+ try {
+ // first try registry, this might result in a wrong QName because
+ // of locally overlayed mappings
+ QName candidate = nsReg.getQName(name);
+ // check if valid
+ String prefix = nsReg.getPrefix(candidate.getNamespaceURI());
+ if (!hiddenPrefixes.contains(prefix)) {
+ return candidate;
+ }
+ } catch (UnknownPrefixException e) {
+ // try using local mappings
+ } catch (NamespaceException e) {
+ // may be thrown by nsReg.getPrefix() but should never happend
+ // because we got the namespace from the nsReg itself
+ throw new UnknownPrefixException(name);
+ }
+ return super.getQName(name);
+ }
+
//----------------------------------------------------< NamespaceResolver >
/**
* {@inheritDoc}
@@ -238,34 +268,6 @@
/**
* {@inheritDoc}
*/
- public QName getQName(String name)
- throws IllegalNameException, UnknownPrefixException {
- if (prefixToURI.isEmpty()) {
- // shortcut
- return nsReg.getQName(name);
- }
- try {
- // first try registry, this might result in a wrong QName because
- // of locally overlayed mappings
- QName candidate = nsReg.getQName(name);
- // check if valid
- String prefix = nsReg.getPrefix(candidate.getNamespaceURI());
- if (!hiddenPrefixes.contains(prefix)) {
- return candidate;
- }
- } catch (UnknownPrefixException e) {
- // try using local mappings
- } catch (NamespaceException e) {
- // may be thrown by nsReg.getPrefix() but should never happend
- // because we got the namespace from the nsReg itself
- throw new UnknownPrefixException(name);
- }
- return super.getQName(name);
- }
-
- /**
- * {@inheritDoc}
- */
public String getJCRName(QName name)
throws NoPrefixDeclaredException {
if (uriToPrefix.isEmpty()) {
@@ -281,12 +283,52 @@
}
}
+ //----------------------------------------------------< NamespaceListener >
+ /**
+ * @inheritDoc
+ * This method gets called when a new namespace is registered in
+ * the global NamespaceRegistry. Overridden in order to check for/resolve
+ * collision of new global prefix with existing local prefix.
+ */
+ public void namespaceAdded(String prefix, String uri) {
+ if (prefixToURI.containsKey(prefix)) {
+ // the new global prefix is already in use locally;
+ // need to change it locally by appending underscore(s)
+ // in order to guarantee unambiguous mappings
+ String uniquePrefix = prefix + "_";
+ while (prefixToURI.containsKey(uniquePrefix)) {
+ uniquePrefix += "_";
+ }
+ // add new local mapping
+ prefixToURI.put(uniquePrefix, uri);
+ uriToPrefix.put(uri, uniquePrefix);
+ }
+ }
+
/**
* @inheritDoc
- * This method gets called when the NamespaceRegistry remapped a namespace
- * to a new prefix or if a new namespace is registered.
+ * This method gets called when an existing namespace is remapped to a new
+ * prefix in the global NamespaceRegistry. Overridden in order to check
+ * for/resolve collision of new global prefix with existing local prefix.
*/
- public void prefixRemapped(String prefix, String uri) {
- // todo check overlayed mappings and adjust prefixes if necessary
+ public void namespaceRemapped(String oldPrefix, String newPrefix, String uri) {
+ if (prefixToURI.containsKey(newPrefix)) {
+ // the new global prefix is already in use locally;
+ // check uri
+ if (uriToPrefix.containsKey(uri)) {
+ // since namespace is already remapped locally to
+ // a different prefix there's no collision
+ return;
+ }
+ // need to change enw prefix locally by appending underscore(s)
+ // in order to guarantee unambiguous mappings
+ String uniquePrefix = newPrefix + "_";
+ while (prefixToURI.containsKey(uniquePrefix)) {
+ uniquePrefix += "_";
+ }
+ // add new local mapping
+ prefixToURI.put(uniquePrefix, uri);
+ uriToPrefix.put(uri, uniquePrefix);
+ }
}
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java?rev=327199&r1=327198&r2=327199&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NamespaceRegistryImpl.java Fri Oct 21 07:28:53 2005
@@ -270,7 +270,13 @@
store();
// notify listeners
- notifyPrefixRemapped(prefix, uri);
+ if (oldPrefix != null) {
+ // remapped existing namespace uri to new prefix
+ notifyNamespaceRemapped(oldPrefix, prefix, uri);
+ } else {
+ // added new namespace uri mapped to prefix
+ notifyNamespaceAdded(prefix, uri);
+ }
}
/**
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java?rev=327199&r1=327198&r2=327199&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/AbstractNamespaceResolver.java Fri Oct 21 07:28:53 2005
@@ -111,14 +111,44 @@
}
/**
- * Notifies listeners that a prefix has been remapped.
+ * Notifies the listeners that a new namespace <code>uri</code> has been
+ * added and mapped to <code>prefix</code>.
*
- * @param prefix the new prefix.
- * @param uri the according namespace uri.
+ * @param prefix the prefix.
+ * @param uri the namespace uri.
*/
- protected void notifyPrefixRemapped(String prefix, String uri) {
+ protected void notifyNamespaceAdded(String prefix, String uri) {
if (listeners == null) {
- throw new UnsupportedOperationException("notifyPrefixRemapped");
+ throw new UnsupportedOperationException("notifyNamespaceAdded");
+ }
+ // addition is infrequent compared to listener registration
+ // -> use copy-on-read
+ NamespaceListener[] currentListeners;
+ synchronized (listeners) {
+ int i = 0;
+ currentListeners = new NamespaceListener[listeners.size()];
+ for (Iterator it = listeners.iterator(); it.hasNext(); ) {
+ currentListeners[i++] = (NamespaceListener) it.next();
+ }
+ }
+ for (int i = 0; i < currentListeners.length; i++) {
+ currentListeners[i].namespaceAdded(prefix, uri);
+ }
+ }
+
+ /**
+ * Notifies listeners that an existing namespace uri has been remapped
+ * to a new prefix.
+ *
+ * @param oldPrefix the old prefix.
+ * @param newPrefix the new prefix.
+ * @param uri the associated namespace uri.
+ */
+ protected void notifyNamespaceRemapped(String oldPrefix,
+ String newPrefix,
+ String uri) {
+ if (listeners == null) {
+ throw new UnsupportedOperationException("notifyNamespaceRemapped");
}
// remapping is infrequent compared to listener registration
// -> use copy-on-read
@@ -131,7 +161,7 @@
}
}
for (int i = 0; i < currentListeners.length; i++) {
- currentListeners[i].prefixRemapped(prefix, uri);
+ currentListeners[i].namespaceRemapped(oldPrefix, newPrefix, uri);
}
}
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceListener.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceListener.java?rev=327199&r1=327198&r2=327199&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceListener.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/name/NamespaceListener.java Fri Oct 21 07:28:53 2005
@@ -22,11 +22,21 @@
public interface NamespaceListener {
/**
- * Notifies the listener that the namespace <code>uri</code> has been
- * re-mapped to the new <code>prefix</code>.
+ * Notifies the listeners that an existing namespace <code>uri</code> has
+ * been re-mapped from <code>oldPrefix</code> to <code>newPrefix</code>.
*
- * @param prefix the new prefix for <code>uri</code>.
+ * @param oldPrefix the old prefix.
+ * @param newPrefix the new prefix.
+ * @param uri the associated namespace uri.
+ */
+ public void namespaceRemapped(String oldPrefix, String newPrefix, String uri);
+
+ /**
+ * Notifies the listeners that a new namespace <code>uri</code> has been
+ * added and mapped to <code>prefix</code>.
+ *
+ * @param prefix the prefix.
* @param uri the namespace uri.
*/
- public void prefixRemapped(String prefix, String uri);
+ public void namespaceAdded(String prefix, String uri);
}