You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2006/03/22 23:38:27 UTC
svn commit: r387959 - in
/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml:
DocViewImportHandler.java ImportHandler.java NamespaceContext.java
SysViewImportHandler.java TargetImportHandler.java
Author: jukka
Date: Wed Mar 22 14:38:25 2006
New Revision: 387959
URL: http://svn.apache.org/viewcvs?rev=387959&view=rev
Log:
JCR-325: Applied the namespace-context.patch that makes the namespace context immutable and thus safe to use even after the processing of the current XML element.
Added:
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/NamespaceContext.java (with props)
Modified:
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/ImportHandler.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java
jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/TargetImportHandler.java
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java
URL: http://svn.apache.org/viewcvs/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java?rev=387959&r1=387958&r2=387959&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java Wed Mar 22 14:38:25 2006
@@ -17,7 +17,6 @@
package org.apache.jackrabbit.core.xml;
import org.apache.jackrabbit.name.NameException;
-import org.apache.jackrabbit.name.NamespaceResolver;
import org.apache.jackrabbit.name.QName;
import org.apache.jackrabbit.util.ISO9075;
import org.apache.jackrabbit.core.NodeId;
@@ -56,8 +55,8 @@
* @param importer
* @param nsContext
*/
- DocViewImportHandler(Importer importer, NamespaceResolver nsContext) {
- super(importer, nsContext);
+ DocViewImportHandler(Importer importer) {
+ super(importer);
}
/**
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/ImportHandler.java
URL: http://svn.apache.org/viewcvs/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/ImportHandler.java?rev=387959&r1=387958&r2=387959&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/ImportHandler.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/ImportHandler.java Wed Mar 22 14:38:25 2006
@@ -16,10 +16,13 @@
*/
package org.apache.jackrabbit.core.xml;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
import org.apache.jackrabbit.core.NamespaceRegistryImpl;
import org.apache.jackrabbit.name.NamespaceResolver;
import org.apache.jackrabbit.name.QName;
-import org.apache.jackrabbit.name.AbstractNamespaceResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
@@ -28,7 +31,6 @@
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
-import org.xml.sax.helpers.NamespaceSupport;
import javax.jcr.NamespaceException;
import javax.jcr.RepositoryException;
@@ -58,28 +60,22 @@
protected final NamespaceResolver nsResolver;
protected Locator locator;
- protected ContentHandler targetHandler;
- protected boolean systemViewXML;
- protected boolean initialized;
- protected final NamespaceContext nsContext;
+ private TargetImportHandler targetHandler;
/**
- * this flag is used to determine whether a namespace context needs to be
- * started in the startElement event or if the namespace context has already
- * been started in a preceeding startPrefixMapping event;
- * the flag is set per element in the first startPrefixMapping event and is
- * cleared again in the following startElement event;
+ * The local namespace mappings reported by
+ * {@link #startPrefixMapping(String, String)}. These mappings are used
+ * to instantiate the local namespace context in
+ * {@link #startElement(String, String, String, Attributes)}.
*/
- protected boolean nsContextStarted;
+ private Map localNamespaceMappings;
public ImportHandler(Importer importer, NamespaceResolver nsResolver,
NamespaceRegistryImpl nsReg) {
this.importer = importer;
this.nsResolver = nsResolver;
this.nsReg = nsReg;
-
- nsContext = new NamespaceContext();
}
//---------------------------------------------------------< ErrorHandler >
@@ -119,27 +115,18 @@
* {@inheritDoc}
*/
public void startDocument() throws SAXException {
- systemViewXML = false;
- initialized = false;
targetHandler = null;
- /**
- * start initial context containing existing mappings reflected
- * by nsResolver
- */
- nsContext.reset();
- nsContext.pushContext();
try {
+ localNamespaceMappings = new HashMap();
String[] uris = nsReg.getURIs();
for (int i = 0; i < uris.length; i++) {
- nsContext.declarePrefix(nsResolver.getPrefix(uris[i]), uris[i]);
+ localNamespaceMappings.put(
+ nsResolver.getPrefix(uris[i]), uris[i]);
}
} catch (RepositoryException re) {
throw new SAXException(re);
}
-
- // initialize flag
- nsContextStarted = false;
}
/**
@@ -148,48 +135,45 @@
public void endDocument() throws SAXException {
// delegate to target handler
targetHandler.endDocument();
- // cleanup
- nsContext.reset();
}
/**
- * {@inheritDoc}
+ * Records the given namespace mapping to be included in the local
+ * namespace context. The local namespace context is instantiated
+ * in {@link #startElement(String, String, String, Attributes)} using
+ * all the the namespace mappings recorded for the current XML element.
+ * <p>
+ * The namespace is also recorded in the persistent namespace registry
+ * unless it is already known.
+ *
+ * @param prefix namespace prefix
+ * @param uri namespace URI
*/
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
- // check if new context needs to be started
- if (!nsContextStarted) {
- // entering new namespace context
- nsContext.pushContext();
- nsContextStarted = true;
- }
+ localNamespaceMappings.put(prefix, uri);
try {
// this will trigger NamespaceException if namespace is unknown
- nsContext.getPrefix(uri);
+ nsReg.getPrefix(uri);
} catch (NamespaceException nse) {
- // namespace is not yet registered ...
- String newPrefix;
- if ("".equals(prefix)) {
- /**
- * the xml document specifies a default namespace
- * (i.e. an empty prefix); we need to create a random
- * prefix as the empty prefix is reserved according
- * to the JCR spec.
- */
- newPrefix = nsReg.getUniquePrefix(uri);
- } else {
- newPrefix = prefix;
- }
- // register new namespace
try {
- nsReg.registerNamespace(newPrefix, uri);
+ // namespace is not yet registered ...
+ if (prefix.length() == 0) {
+ /**
+ * the xml document specifies a default namespace
+ * (i.e. an empty prefix); we need to create a random
+ * prefix as the empty prefix is reserved according
+ * to the JCR spec.
+ */
+ prefix = nsReg.getUniquePrefix(uri);
+ }
+ // register new namespace
+ nsReg.registerNamespace(prefix, uri);
} catch (RepositoryException re) {
throw new SAXException(re);
}
}
- // map namespace in this context to given prefix
- nsContext.declarePrefix(prefix, uri);
}
/**
@@ -207,30 +191,22 @@
*/
public void startElement(String namespaceURI, String localName, String qName,
Attributes atts) throws SAXException {
- // check if new context needs to be started
- if (!nsContextStarted) {
- // there hasn't been a preceeding startPrefixMapping event
- // so enter new namespace context
- nsContext.pushContext();
- } else {
- // reset flag
- nsContextStarted = false;
- }
-
- if (!initialized) {
+ if (targetHandler == null) {
// the namespace of the first element determines the type of XML
// (system view/document view)
- systemViewXML = QName.NS_SV_URI.equals(namespaceURI);
-
- if (systemViewXML) {
- targetHandler = new SysViewImportHandler(importer, nsContext);
+ if (QName.NS_SV_URI.equals(namespaceURI)) {
+ targetHandler = new SysViewImportHandler(importer);
} else {
- targetHandler = new DocViewImportHandler(importer, nsContext);
+ targetHandler = new DocViewImportHandler(importer);
}
+
targetHandler.startDocument();
- initialized = true;
}
+ // Start a namespace context for this element
+ targetHandler.startNamespaceContext(localNamespaceMappings);
+ localNamespaceMappings.clear();
+
// delegate to target handler
targetHandler.startElement(namespaceURI, localName, qName, atts);
}
@@ -244,15 +220,14 @@
}
/**
+ * Delegates the call to the underlying target handler and asks the
+ * handler to end the current namespace context.
* {@inheritDoc}
*/
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
- // leaving element, pop namespace context
- nsContext.popContext();
-
- // delegate to target handler
targetHandler.endElement(namespaceURI, localName, qName);
+ targetHandler.endNamespaceContext();
}
/**
@@ -260,92 +235,5 @@
*/
public void setDocumentLocator(Locator locator) {
this.locator = locator;
- }
-
- //--------------------------------------------------------< inner classes >
- /**
- * <code>NamespaceContext</code> supports scoped namespace declarations.
- */
- class NamespaceContext extends AbstractNamespaceResolver {
-
- private final NamespaceSupport nsContext;
-
- /**
- * NamespaceSupport doesn't accept "" as default uri;
- * internally we're using " " instead
- */
- private static final String DUMMY_DEFAULT_URI = " ";
-
- NamespaceContext() {
- nsContext = new NamespaceSupport();
- }
-
- /**
- * {@inheritDoc}
- */
- void popContext() {
- nsContext.popContext();
- }
-
- /**
- * {@inheritDoc}
- */
- void pushContext() {
- nsContext.pushContext();
- }
-
- /**
- * {@inheritDoc}
- */
- void reset() {
- nsContext.reset();
- }
-
- /**
- * {@inheritDoc}
- */
- boolean declarePrefix(String prefix, String uri) {
- if (QName.NS_DEFAULT_URI.equals(uri)) {
- uri = DUMMY_DEFAULT_URI;
- }
- return nsContext.declarePrefix(prefix, uri);
- }
-
- //------------------------------------------------< NamespaceResolver >
- /**
- * {@inheritDoc}
- */
- public String getURI(String prefix) throws NamespaceException {
- String uri = nsContext.getURI(prefix);
- if (uri == null) {
- throw new NamespaceException("unknown prefix");
- } else if (DUMMY_DEFAULT_URI.equals(uri)) {
- return QName.NS_DEFAULT_URI;
- } else {
- return uri;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public String getPrefix(String uri) throws NamespaceException {
- if (QName.NS_DEFAULT_URI.equals(uri)) {
- uri = DUMMY_DEFAULT_URI;
- }
- String prefix = nsContext.getPrefix(uri);
- if (prefix == null) {
- /**
- * NamespaceSupport#getPrefix will never return the empty
- * (default) prefix; we have to do a reverse-lookup to check
- * whether it's the current default namespace
- */
- if (uri.equals(nsContext.getURI(QName.NS_EMPTY_PREFIX))) {
- return QName.NS_EMPTY_PREFIX;
- }
- throw new NamespaceException("unknown uri");
- }
- return prefix;
- }
}
}
Added: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/NamespaceContext.java
URL: http://svn.apache.org/viewcvs/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/NamespaceContext.java?rev=387959&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/NamespaceContext.java (added)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/NamespaceContext.java Wed Mar 22 14:38:25 2006
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * 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.jackrabbit.core.xml;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.jcr.NamespaceException;
+
+import org.apache.jackrabbit.name.IllegalNameException;
+import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.name.NoPrefixDeclaredException;
+import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.name.UnknownPrefixException;
+
+/**
+ * Hierarchically scoped namespace resolver. Each NamespaceContext instance
+ * contains an immutable set of namespace mappings and a reference (possibly
+ * <code>null</code>) to a parent NamespaceContext. Namespace resolution is
+ * performed by first looking at the local namespace mappings and then using
+ * the parent resolver if no local match is found.
+ * <p>
+ * The local namespace mappings are stored internally as two hash maps, one
+ * that maps the namespace prefixes to namespace URIs and another that contains
+ * the reverse mapping.
+ */
+class NamespaceContext implements NamespaceResolver {
+
+ /**
+ * The parent namespace context.
+ */
+ private final NamespaceContext parent;
+
+ /**
+ * The namespace prefix to namespace URI mapping.
+ */
+ private final Map prefixToURI;
+
+ /**
+ * The namespace URI to namespace prefix mapping.
+ */
+ private final Map uriToPrefix;
+
+ /**
+ * Creates a NamespaceContext instance with the given parent context
+ * and local namespace mappings.
+ *
+ * @param parent parent context
+ * @param mappings local namespace mappings (prefix -> URI)
+ */
+ public NamespaceContext(NamespaceContext parent, Map mappings) {
+ this.parent = parent;
+ this.prefixToURI = new HashMap();
+ this.uriToPrefix = new HashMap();
+
+ Iterator iterator = mappings.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry mapping = (Map.Entry) iterator.next();
+ prefixToURI.put(mapping.getKey(), mapping.getValue());
+ uriToPrefix.put(mapping.getValue(), mapping.getKey());
+ }
+ }
+
+ /**
+ * Returns the parent namespace context.
+ *
+ * @return parent namespace context
+ */
+ public NamespaceContext getParent() {
+ return parent;
+
+ }
+ //------------------------------------------------< NamespaceResolver >
+
+ /**
+ * Returns the namespace URI mapped to the given prefix.
+ *
+ * @param prefix namespace prefix
+ * @return namespace URI
+ * @throws NamespaceException if the prefix is not mapped
+ */
+ public String getURI(String prefix) throws NamespaceException {
+ String uri = (String) prefixToURI.get(prefix);
+ if (uri != null) {
+ return uri;
+ } else if (parent != null) {
+ return parent.getURI(prefix);
+ } else {
+ throw new NamespaceException("Unknown prefix: " + prefix);
+ }
+ }
+
+ /**
+ * Returns the namespace prefix mapped to the given URI.
+ *
+ * @param uri namespace URI
+ * @return namespace prefix
+ * @throws NamespaceException if the URI is not mapped
+ */
+ public String getPrefix(String uri) throws NamespaceException {
+ String prefix = (String) uriToPrefix.get(uri);
+ if (prefix != null) {
+ return prefix;
+ } else if (parent != null) {
+ return parent.getPrefix(uri);
+ } else {
+ throw new NamespaceException("Unknown URI: " + uri);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public String getJCRName(QName name) throws NoPrefixDeclaredException {
+ return name.toJCRName(this);
+ }
+
+ /** {@inheritDoc} */
+ public QName getQName(String name)
+ throws IllegalNameException, UnknownPrefixException {
+ return QName.fromJCRName(name, this);
+ }
+
+}
Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/NamespaceContext.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java
URL: http://svn.apache.org/viewcvs/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java?rev=387959&r1=387958&r2=387959&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java Wed Mar 22 14:38:25 2006
@@ -17,7 +17,6 @@
package org.apache.jackrabbit.core.xml;
import org.apache.jackrabbit.name.IllegalNameException;
-import org.apache.jackrabbit.name.NamespaceResolver;
import org.apache.jackrabbit.name.QName;
import org.apache.jackrabbit.name.UnknownPrefixException;
import org.apache.jackrabbit.core.NodeId;
@@ -60,8 +59,8 @@
* @param importer
* @param nsContext
*/
- SysViewImportHandler(Importer importer, NamespaceResolver nsContext) {
- super(importer, nsContext);
+ SysViewImportHandler(Importer importer) {
+ super(importer);
}
private void processNode(ImportState state, boolean start, boolean end)
Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/TargetImportHandler.java
URL: http://svn.apache.org/viewcvs/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/TargetImportHandler.java?rev=387959&r1=387958&r2=387959&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/TargetImportHandler.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/xml/TargetImportHandler.java Wed Mar 22 14:38:25 2006
@@ -16,7 +16,6 @@
*/
package org.apache.jackrabbit.core.xml;
-import org.apache.jackrabbit.name.NamespaceResolver;
import org.apache.jackrabbit.util.TransientFileFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -31,6 +30,7 @@
import java.io.Writer;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
+import java.util.Map;
import javax.jcr.RepositoryException;
@@ -44,12 +44,18 @@
private static Logger log = LoggerFactory.getLogger(TargetImportHandler.class);
protected final Importer importer;
- protected final NamespaceResolver nsContext;
- protected TargetImportHandler(Importer importer,
- NamespaceResolver nsContext) {
+ /**
+ * The current namespace context. A new namespace context is created
+ * for each XML element and the parent reference is used to link the
+ * namespace contexts together in a tree hierarchy. This variable contains
+ * a reference to the namespace context associated with the XML element
+ * that is currently being processed.
+ */
+ protected NamespaceContext nsContext;
+
+ protected TargetImportHandler(Importer importer) {
this.importer = importer;
- this.nsContext = nsContext;
}
/**
@@ -84,6 +90,7 @@
public void startDocument() throws SAXException {
try {
importer.start();
+ nsContext = null;
} catch (RepositoryException re) {
throw new SAXException(re);
}
@@ -102,6 +109,27 @@
} catch (RepositoryException re) {
throw new SAXException(re);
}
+ }
+
+ /**
+ * Starts a local namespace context for the current XML element.
+ * This method is called by {@link ImportHandler} when the processing of
+ * an XML element starts. The given local namespace mappings have been
+ * recorded by {@link ImportHandler#startPrefixMapping(String, String)}
+ * for the current XML element.
+ *
+ * @param mappings local namespace mappings
+ */
+ public final void startNamespaceContext(Map mappings) {
+ nsContext = new NamespaceContext(nsContext, mappings);
+ }
+
+ /**
+ * Restores the parent namespace context. This method is called by
+ * {@link ImportHandler} when the processing of an XML element ends.
+ */
+ public final void endNamespaceContext() {
+ nsContext = nsContext.getParent();
}
//--------------------------------------------------------< inner classes >