jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r448587 - in /jackrabbit/trunk/contrib/spi/spi2dav: ./ src/main/java/org/apache/jackrabbit/spi2dav/
Date Thu, 21 Sep 2006 15:40:54 GMT
Author: angela
Date: Thu Sep 21 08:40:53 2006
New Revision: 448587

URL: http://svn.apache.org/viewvc?view=rev&rev=448587
Log:
work in progress

- move to commons-httpclient 3.0
- adjust to latest changes in jcr-server (JCR-544)
- simplify creation of info objects
- various minor improvements



Added:
    jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/IdURICache.java   (with props)
    jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/NamespaceResolverImpl.java   (with props)
    jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolverImpl.java   (with props)
Modified:
    jackrabbit/trunk/contrib/spi/spi2dav/project.xml
    jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ItemInfoImpl.java
    jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/NodeInfoImpl.java
    jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/PropertyInfoImpl.java
    jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
    jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolver.java

Modified: jackrabbit/trunk/contrib/spi/spi2dav/project.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/project.xml?view=diff&rev=448587&r1=448586&r2=448587
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/project.xml (original)
+++ jackrabbit/trunk/contrib/spi/spi2dav/project.xml Thu Sep 21 08:40:53 2006
@@ -88,7 +88,7 @@
         <dependency>
             <groupId>commons-httpclient</groupId>
             <artifactId>commons-httpclient</artifactId>
-            <version>2.0.2</version>
+            <version>3.0</version>
         </dependency>
         <!-- runtime dependency -->
         <dependency>

Added: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/IdURICache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/IdURICache.java?view=auto&rev=448587
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/IdURICache.java (added)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/IdURICache.java Thu Sep 21 08:40:53 2006
@@ -0,0 +1,76 @@
+/*
+ * 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.spi2dav;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.spi.ItemId;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * <code>IdURICache</code>...
+ */
+class IdURICache {
+
+    private static Logger log = LoggerFactory.getLogger(IdURICache.class);
+
+    private final String workspaceUri;
+
+    private Map idToUriCache = new HashMap();
+    private Map uriToIdCache = new HashMap();
+
+    IdURICache(String workspaceUri) {
+        this.workspaceUri = workspaceUri;
+    }
+
+    public ItemId getItemId(String uri) {
+        return (ItemId) uriToIdCache.get(uri);
+    }
+
+    public String getUri(ItemId itemId) {
+        return (String) idToUriCache.get(itemId);
+    }
+
+    public boolean containsUri(String uri) {
+        return uriToIdCache.containsKey(uri);
+    }
+
+    public boolean containsItemId(ItemId itemId) {
+        return idToUriCache.containsKey(itemId);
+    }
+
+    public void add(String uri, ItemId itemId) {
+        if (!uri.startsWith(workspaceUri)) {
+            throw new IllegalArgumentException("Workspace missmatch.");
+        }
+        uriToIdCache.put(uri, itemId);
+        idToUriCache.put(itemId, uri);
+        log.debug("Added: ItemId = " + itemId + " URI = " + uri);
+    }
+
+    public void remove(String uri) {
+        Object itemId = uriToIdCache.remove(uri);
+        log.debug("Removed: ItemId = " + itemId + " URI = " + uri);
+    }
+
+    public void remove(ItemId itemId) {
+        Object uri = idToUriCache.remove(itemId);
+        log.debug("Removed: ItemId = " + itemId + " URI = " + uri);
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/IdURICache.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/IdURICache.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ItemInfoImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ItemInfoImpl.java?view=diff&rev=448587&r1=448586&r2=448587
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ItemInfoImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ItemInfoImpl.java Thu Sep 21 08:40:53 2006
@@ -16,23 +16,11 @@
  */
 package org.apache.jackrabbit.spi2dav;
 
-import org.apache.jackrabbit.webdav.MultiStatusResponse;
-import org.apache.jackrabbit.webdav.DavServletResponse;
-import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants;
-import org.apache.jackrabbit.webdav.property.DavProperty;
-import org.apache.jackrabbit.webdav.property.HrefProperty;
-import org.apache.jackrabbit.webdav.property.DavPropertySet;
-import org.apache.jackrabbit.name.NameException;
-import org.apache.jackrabbit.name.QName;
-import org.apache.jackrabbit.name.NameFormat;
 import org.apache.jackrabbit.spi.ItemInfo;
 import org.apache.jackrabbit.spi.NodeId;
-import org.apache.jackrabbit.spi.SessionInfo;
 import org.slf4j.LoggerFactory;
 import org.slf4j.Logger;
 
-import javax.jcr.RepositoryException;
-
 /**
  * <code>ItemInfoImpl</code>...
  */
@@ -40,43 +28,14 @@
 
     private static Logger log = LoggerFactory.getLogger(ItemInfoImpl.class);
 
-    private final QName name;
     private final NodeId parentId;
 
-    public ItemInfoImpl(MultiStatusResponse response, URIResolver uriResolver, SessionInfo sessionInfo) throws RepositoryException {
-
-        DavPropertySet propSet = response.getProperties(DavServletResponse.SC_OK);
-        DavProperty nameProp = propSet.get(ItemResourceConstants.JCR_NAME);
-	if (nameProp != null && nameProp.getValue() != null) {
-            // not root node
-            // TODO: jcrName is transported from jackrabbit-webdav impl
-            String jcrName = nameProp.getValue().toString();
-            try {
-                name = NameFormat.parse(jcrName, uriResolver);
-            } catch (NameException e) {
-                throw new RepositoryException("Unable to build ItemInfo object, invalid name found: " + jcrName);
-            }
-	} else {
-            // root
-            name = QName.ROOT;
-        }
-        // set the parent id unless its the root item
-        if (propSet.contains(ItemResourceConstants.JCR_PARENT)) {
-            HrefProperty parentProp = new HrefProperty(propSet.get(ItemResourceConstants.JCR_PARENT));
-            String parentHref = parentProp.getHrefs().get(0).toString();
-            parentId = uriResolver.getNodeId(parentHref, sessionInfo);
-        } else {
-            parentId = null;
-        }
+    public ItemInfoImpl(NodeId parentId) {
+        // set parentId
+        this.parentId = parentId;
     }
 
     public NodeId getParentId() {
         return parentId;
     }
-
-    public QName getQName() {
-        return name;
-    }
-
-    public abstract boolean denotesNode();
 }

Added: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/NamespaceResolverImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/NamespaceResolverImpl.java?view=auto&rev=448587
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/NamespaceResolverImpl.java (added)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/NamespaceResolverImpl.java Thu Sep 21 08:40:53 2006
@@ -0,0 +1,75 @@
+/*
+ * 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.spi2dav;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.name.AbstractNamespaceResolver;
+import org.apache.jackrabbit.name.NamespaceResolver;
+
+import javax.jcr.NamespaceException;
+import java.util.Properties;
+
+/**
+ * <code>NamespaceResolverImpl</code>...
+ */
+public class NamespaceResolverImpl extends AbstractNamespaceResolver {
+
+    private static Logger log = LoggerFactory.getLogger(NamespaceResolverImpl.class);
+
+    private Properties prefixToURI = new Properties();
+    private Properties uriToPrefix = new Properties();
+
+    void add(String prefix, String uri) {
+        prefixToURI.put(prefix, uri);
+        uriToPrefix.put(uri, prefix);
+    }
+
+    void remove(String prefix, String uri) {
+        prefixToURI.remove(prefix);
+        uriToPrefix.remove(uri);
+    }
+
+    Properties getNamespaces() {
+        Properties namespaces = new Properties();
+        namespaces.putAll(prefixToURI);
+        return namespaces;
+    }
+    
+    //--------------------------------------------------< NamespaceResolver >---
+    /**
+     * @see NamespaceResolver#getURI(String)
+     */
+    public String getURI(String prefix) throws NamespaceException {
+        String uri = (String) prefixToURI.get(prefix);
+        if (uri == null) {
+            throw new NamespaceException(prefix + ": is not a registered namespace prefix.");
+        }
+        return uri;
+    }
+
+    /**
+     * @see NamespaceResolver#getPrefix(String)
+     */
+    public String getPrefix(String uri) throws NamespaceException {
+        String prefix = (String) uriToPrefix.get(uri);
+        if (prefix == null) {
+            throw new NamespaceException(uri + ": is not a registered namespace uri.");
+        }
+        return prefix;
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/NamespaceResolverImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/NamespaceResolverImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/NodeInfoImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/NodeInfoImpl.java?view=diff&rev=448587&r1=448586&r2=448587
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/NodeInfoImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/NodeInfoImpl.java Thu Sep 21 08:40:53 2006
@@ -16,22 +16,20 @@
  */
 package org.apache.jackrabbit.spi2dav;
 
-import org.apache.jackrabbit.webdav.MultiStatusResponse;
-import org.apache.jackrabbit.webdav.DavServletResponse;
-import org.apache.jackrabbit.webdav.DavException;
 import org.apache.jackrabbit.webdav.jcr.nodetype.NodeTypeProperty;
 import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants;
 import org.apache.jackrabbit.webdav.property.DavPropertySet;
-import org.apache.jackrabbit.webdav.property.HrefProperty;
-import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.DavProperty;
 import org.apache.jackrabbit.name.NameException;
 import org.apache.jackrabbit.name.QName;
 import org.apache.jackrabbit.name.NameFormat;
+import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.name.Path;
 import org.apache.jackrabbit.spi.NodeInfo;
 import org.apache.jackrabbit.spi.IdIterator;
 import org.apache.jackrabbit.spi.NodeId;
 import org.apache.jackrabbit.spi.PropertyId;
-import org.apache.jackrabbit.spi.SessionInfo;
+import org.apache.jackrabbit.spi.ItemId;
 import org.slf4j.LoggerFactory;
 import org.slf4j.Logger;
 
@@ -49,6 +47,7 @@
     private static Logger log = LoggerFactory.getLogger(NodeInfoImpl.class);
 
     private final NodeId id;
+    private final QName qName;
 
     private QName primaryNodeTypeName = null;
     private QName[] mixinNodeTypeNames = new QName[0];
@@ -57,17 +56,43 @@
     private final List nodeIds = new ArrayList();
     private final List propertyIds = new ArrayList();
 
-    public NodeInfoImpl(MultiStatusResponse response, List childItemResponses, URIResolver uriResolver, SessionInfo sessionInfo) throws RepositoryException, DavException {
-        super(response, uriResolver, sessionInfo);
+    public NodeInfoImpl(NodeId id, NodeId parentId, DavPropertySet propSet,
+                        NamespaceResolver nsResolver) throws RepositoryException {
+        super(parentId);
+
+        // set id
+        this.id = id;
+
+        // retrieve name
+        if (id.getRelativePath() == null) {
+            DavProperty nameProp = propSet.get(ItemResourceConstants.JCR_NAME);
+            if (nameProp != null && nameProp.getValue() != null) {
+                // not root node
+                // jcrName is transported from jackrabbit-webdav -> convert
+                // note, that unescaping is not required.
+                String jcrName = nameProp.getValue().toString();
+                try {
+                    qName = NameFormat.parse(jcrName, nsResolver);
+                } catch (NameException e) {
+                    throw new RepositoryException("Unable to build ItemInfo object, invalid name found: " + jcrName);
+                }
+            } else {
+                // root
+                qName = QName.ROOT;
+            }
+        } else {
+            Path.PathElement el = id.getRelativePath().getNameElement();
+            qName = (Path.CURRENT_ELEMENT == el) ? QName.ROOT : el.getName();
+        }
+
 
-        id = uriResolver.getNodeId(getParentId(), response);
-        DavPropertySet propSet = response.getProperties(DavServletResponse.SC_OK);
+        // retrieve properties
         try {
             if (propSet.contains(ItemResourceConstants.JCR_PRIMARYNODETYPE)) {
                 Iterator it = new NodeTypeProperty(propSet.get(ItemResourceConstants.JCR_PRIMARYNODETYPE)).getNodeTypeNames().iterator();
                 if (it.hasNext()) {
                     String jcrName = it.next().toString();
-                    primaryNodeTypeName = NameFormat.parse(jcrName, uriResolver);
+                    primaryNodeTypeName = NameFormat.parse(jcrName, nsResolver);
                 } else {
                     throw new RepositoryException("Missing primary nodetype for node " + id + ".");
                 }
@@ -81,45 +106,25 @@
                 int i = 0;
                 while(it.hasNext()) {
                     String jcrName = it.next().toString();
-                    mixinNodeTypeNames[i] = NameFormat.parse(jcrName, uriResolver);
+                    mixinNodeTypeNames[i] = NameFormat.parse(jcrName, nsResolver);
                     i++;
                 }
             }
         } catch (NameException e) {
             throw new RepositoryException("Error while resolving nodetype names: " + e.getMessage());
         }
-
-        if (propSet.contains(ItemResourceConstants.JCR_REFERENCES)) {
-            HrefProperty refProp = new HrefProperty(propSet.get(ItemResourceConstants.JCR_REFERENCES));
-            Iterator hrefIter = refProp.getHrefs().iterator();
-            while(hrefIter.hasNext()) {
-                String propertyHref = hrefIter.next().toString();
-                PropertyId propertyId = uriResolver.getPropertyId(propertyHref, sessionInfo);
-                references.add(propertyId);
-            }
-        }
-
-        // build the child-item entries
-        Iterator it = childItemResponses.iterator();
-        while (it.hasNext()) {
-            MultiStatusResponse resp = (MultiStatusResponse)it.next();
-            DavPropertySet childProps = resp.getProperties(DavServletResponse.SC_OK);
-            if (childProps.contains(DavPropertyName.RESOURCETYPE) &&
-                childProps.get(DavPropertyName.RESOURCETYPE).getValue() != null) {
-                // any other resource type than default (empty) is represented by a node item
-                NodeId childId = uriResolver.getNodeId(id, resp);
-                nodeIds.add(childId);
-            } else {
-                PropertyId propertyId = uriResolver.getPropertyId(id, resp);
-                propertyIds.add(propertyId);
-            }
-        }
     }
 
+    //-----------------------------------------------------------< ItemInfo >---
     public boolean denotesNode() {
         return true;
     }
 
+    public QName getQName() {
+        return qName;
+    }
+
+    //-----------------------------------------------------------< NodeInfo >---
     public NodeId getId() {
         return id;
     }
@@ -142,5 +147,18 @@
 
     public IdIterator getPropertyIds() {
         return new IteratorHelper(propertyIds);
+    }
+
+    //--------------------------------------------------------------------------
+    void addReference(PropertyId referenceId) {
+        references.add(referenceId);
+    }
+
+    void addChildId(ItemId childId) {
+        if (childId.denotesNode()) {
+           nodeIds.add(childId);
+        } else {
+           propertyIds.add(childId);
+        }
     }
 }

Modified: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/PropertyInfoImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/PropertyInfoImpl.java?view=diff&rev=448587&r1=448586&r2=448587
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/PropertyInfoImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/PropertyInfoImpl.java Thu Sep 21 08:40:53 2006
@@ -16,17 +16,16 @@
  */
 package org.apache.jackrabbit.spi2dav;
 
-import org.apache.jackrabbit.webdav.MultiStatusResponse;
-import org.apache.jackrabbit.webdav.DavServletResponse;
 import org.apache.jackrabbit.webdav.DavException;
 import org.apache.jackrabbit.webdav.jcr.property.ValuesProperty;
 import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants;
 import org.apache.jackrabbit.webdav.property.DavPropertySet;
 import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.name.QName;
 import org.apache.jackrabbit.value.ValueFormat;
 import org.apache.jackrabbit.spi.PropertyId;
 import org.apache.jackrabbit.spi.PropertyInfo;
-import org.apache.jackrabbit.spi.SessionInfo;
+import org.apache.jackrabbit.spi.NodeId;
 import org.slf4j.LoggerFactory;
 import org.slf4j.Logger;
 
@@ -51,15 +50,15 @@
     private boolean isMultiValued;
     private Object[] values;
 
-    public PropertyInfoImpl(MultiStatusResponse response, URIResolver uriResolver,
-                            NamespaceResolver nsResolver, SessionInfo sessionInfo,
-                            ValueFactory valueFactory)
+    public PropertyInfoImpl(PropertyId id, NodeId parentId, DavPropertySet propSet,
+                            NamespaceResolver nsResolver, ValueFactory valueFactory)
         throws RepositoryException, DavException {
-        super(response, uriResolver, sessionInfo);
 
-        id = uriResolver.getPropertyId(getParentId(), response);
+        super(parentId);
+        // set id
+        this.id = id;
 
-        DavPropertySet propSet = response.getProperties(DavServletResponse.SC_OK);
+        // retrieve properties
         String typeName = propSet.get(ItemResourceConstants.JCR_TYPE).getValue().toString();
         type = PropertyType.valueFromName(typeName);
 
@@ -91,10 +90,16 @@
         }
     }
 
+    //-----------------------------------------------------------< ItemInfo >---
     public boolean denotesNode() {
         return false;
     }
 
+    public QName getQName() {
+        return id.getQName();
+    }
+
+    //-------------------------------------------------------< PropertyInfo >---
     public PropertyId getId() {
         return id;
     }

Modified: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java?view=diff&rev=448587&r1=448586&r2=448587
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java Thu Sep 21 08:40:53 2006
@@ -23,7 +23,10 @@
 import org.apache.commons.httpclient.UsernamePasswordCredentials;
 import org.apache.commons.httpclient.HttpState;
 import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.auth.AuthScope;
 import org.apache.commons.httpclient.methods.HeadMethod;
+import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
+import org.apache.commons.collections.map.LRUMap;
 import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
 import org.apache.jackrabbit.webdav.property.DavPropertySet;
 import org.apache.jackrabbit.webdav.property.DavPropertyName;
@@ -82,7 +85,6 @@
 import org.apache.jackrabbit.webdav.jcr.version.report.RepositoryDescriptorsReport;
 import org.apache.jackrabbit.webdav.jcr.version.report.RegisteredNamespacesReport;
 import org.apache.jackrabbit.webdav.jcr.version.report.NodeTypesReport;
-import org.apache.jackrabbit.webdav.jcr.version.report.LocateByUuidReport;
 import org.apache.jackrabbit.webdav.jcr.nodetype.NodeTypeConstants;
 import org.apache.jackrabbit.webdav.jcr.nodetype.NodeTypeProperty;
 import org.apache.jackrabbit.webdav.jcr.property.ValuesProperty;
@@ -90,16 +92,10 @@
 import org.apache.jackrabbit.webdav.jcr.observation.SubscriptionImpl;
 import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants;
 import org.apache.jackrabbit.util.Text;
-import org.apache.jackrabbit.name.AbstractNamespaceResolver;
 import org.apache.jackrabbit.name.NoPrefixDeclaredException;
-import org.apache.jackrabbit.name.NameException;
 import org.apache.jackrabbit.name.NamespaceResolver;
 import org.apache.jackrabbit.name.QName;
-import org.apache.jackrabbit.name.Path;
-import org.apache.jackrabbit.name.MalformedPathException;
-import org.apache.jackrabbit.name.PathFormat;
 import org.apache.jackrabbit.name.NameFormat;
-import org.apache.jackrabbit.BaseException;
 import org.apache.jackrabbit.spi.Batch;
 import org.apache.jackrabbit.spi.RepositoryService;
 import org.apache.jackrabbit.spi.SessionInfo;
@@ -152,12 +148,12 @@
 import java.util.Properties;
 import java.util.List;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.Iterator;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.Collection;
+import java.util.Collections;
 import java.io.InputStream;
 import java.io.IOException;
 
@@ -166,45 +162,43 @@
  */
 // TODO: encapsulate URI building, escaping, unescaping...
 // TODO: cache info objects
-public class RepositoryServiceImpl extends AbstractNamespaceResolver implements URIResolver, RepositoryService, DavConstants {
+// TODO: improve handling of HttpClient
+// TODO: TO-BE-FIXED. caches don't get adjusted upon removal/move of items
+public class RepositoryServiceImpl implements RepositoryService, DavConstants {
 
     private static Logger log = LoggerFactory.getLogger(RepositoryServiceImpl.class);
 
-    private final Document domFactory;
-
-    private final HostConfiguration hostConfig;
-    private final URI repositoryUri;
-
-    // URI/ID resolution
-    private final Map uriCache = new HashMap();
-    private final Map idCache = new HashMap();
-
     private final IdFactory idFactory;
     private final ValueFactory valueFactory;
 
-    // namespace resolver
-    private Properties prefixToURI = new Properties();
-    private Properties uriToPrefix = new Properties();
+    private final Document domFactory;
+    private final NamespaceResolverImpl nsResolver;
+    private final URIResolverImpl uriResolver;
+
+    private final HostConfiguration hostConfig;
+    // remember most frequently used http clients
+    private final Map clientCache = Collections.synchronizedMap(new LRUMap());
 
     public RepositoryServiceImpl(String uri, IdFactory idFactory, ValueFactory valueFactory) throws RepositoryException {
         if (uri == null || "".equals(uri)) {
-            throw new RepositoryException("Invalid repository uri.");
+            throw new RepositoryException("Invalid repository uri '" + uri + "'.");
         }
-        if (idFactory == null) {
-            throw new RepositoryException("IdFactory must not be null.");
+        if (idFactory == null || valueFactory == null) {
+            throw new RepositoryException("IdFactory and ValueFactory may not be null.");
         }
         this.idFactory = idFactory;
         this.valueFactory = valueFactory;
 
         try {
+            URI repositoryUri = new URI((uri.endsWith("/")) ? uri : uri+"/", true);
             hostConfig = new HostConfiguration();
-            if (!uri.endsWith("/")) {
-                uri += "/";
-            }
-            repositoryUri = new URI(uri);
             hostConfig.setHost(repositoryUri);
 
             domFactory = DomUtil.BUILDER_FACTORY.newDocumentBuilder().newDocument();
+
+            nsResolver = new NamespaceResolverImpl();
+            uriResolver = new URIResolverImpl(repositoryUri, this, nsResolver, domFactory);
+
         } catch (URIException e) {
             throw new RepositoryException(e);
         } catch (ParserConfigurationException e) {
@@ -213,93 +207,94 @@
     }
 
     private HttpClient getClient(Credentials credentials) {
-        HttpClient client = new HttpClient();
-        client.setHostConfiguration(hostConfig);
-        UsernamePasswordCredentials creds;
-        if (credentials == null) {
-            creds = new UsernamePasswordCredentials(null, null);
-        } else if (credentials instanceof SimpleCredentials) {
-            SimpleCredentials sCred = (SimpleCredentials) credentials;
-            creds = new UsernamePasswordCredentials(sCred.getUserID(), 
-                    String.valueOf(sCred.getPassword()));
+        if (clientCache.containsKey(credentials)) {
+            return (HttpClient) clientCache.get(credentials);
         } else {
-            // TODO properly build http client credentials
-            creds = new UsernamePasswordCredentials(credentials.toString());
+            HttpClient client = new HttpClient();
+            client.setHostConfiguration(hostConfig);
+            UsernamePasswordCredentials creds;
+            if (credentials == null) {
+                // NOTE: null credentials only work if 'missing-auth-mapping' param is set on the server
+                creds = null;
+            } else if (credentials instanceof SimpleCredentials) {
+                SimpleCredentials sCred = (SimpleCredentials) credentials;
+                creds = new UsernamePasswordCredentials(sCred.getUserID(),
+                    String.valueOf(sCred.getPassword()));
+            } else {
+                creds = new UsernamePasswordCredentials(credentials.toString());
+            }
+            HttpState httpState = client.getState();
+
+            // set authentication scope and credentials
+            AuthScope authscope = new AuthScope(hostConfig.getHost(), hostConfig.getPort());
+            httpState.setCredentials(authscope, creds);
+
+            // always send authentication not waiting for 401
+            client.getParams().setAuthenticationPreemptive(true);
+
+            clientCache.put(credentials, client);
+            return client;
         }
-        HttpState httpState = client.getState();
-        httpState.setCredentials(null, hostConfig.getHost(), creds);
-        return client;
     }
 
-    private HttpClient getClient(SessionInfo sessionInfo) {
+    HttpClient getClient(SessionInfo sessionInfo) {
         Credentials credentials = null;
         if (sessionInfo instanceof SessionInfoImpl) {
             credentials = ((SessionInfoImpl) sessionInfo).getCredentials();
+        } else {
+            log.warn("Unexpected SessionInfo implementation. Using 'null' credentials for connection.");
         }
         return getClient(credentials);
     }
 
+    private static void initMethod(DavMethod method, SessionInfo sessionInfo, boolean addIfHeader) {
+        if (addIfHeader) {
+            String[] locktokens = sessionInfo.getLockTokens();
+            // TODO: ev. build tagged if header
+            if (locktokens != null && locktokens.length > 0) {
+                IfHeader ifH = new IfHeader(locktokens);
+                method.setRequestHeader(ifH.getHeaderName(), ifH.getHeaderValue());
+            }
+        }
+        if (sessionInfo instanceof SessionInfoImpl) {
+            String txId = ((SessionInfoImpl) sessionInfo).getBatchId();
+            if (txId != null) {
+                CodedUrlHeader ch = new CodedUrlHeader(TransactionConstants.HEADER_TRANSACTIONID, txId);
+                method.setRequestHeader(ch.getHeaderName(), ch.getHeaderValue());
+            }
+        }
+    }
+
+    private URIResolver getURIResolver() {
+        return uriResolver;
+    }
+
+    private NamespaceResolver getNamespaceResolver() {
+        return nsResolver;
+    }
+
     private String getRepositoryUri() {
-        return repositoryUri.getEscapedURI();
+        return uriResolver.getRepositoryUri();
     }
 
     private String getWorkspaceUri(String workspaceName) {
-        String workspaceUri = getRepositoryUri();
-        if (workspaceName != null) {
-            workspaceUri += Text.escape(workspaceName);
-        }
-        return workspaceUri;
+        return uriResolver.getWorkspaceUri(workspaceName);
     }
 
-    private String getRootItemUri(SessionInfo sessionInfo) {
-        String rootUri = getWorkspaceUri(sessionInfo.getWorkspaceName()) + "/";
-        return rootUri;
+    private String getRootItemUri(String workspaceName) {
+        return uriResolver.getRootItemUri(workspaceName);
     }
 
-    private String getItemUri(String workspaceName, ItemId itemId, SessionInfo sessionInfo) throws RepositoryException {
-        String uri = getWorkspaceUri(workspaceName);
-        String uuid = itemId.getUUID();
-        if (uuid != null) {
-            if (uriCache.containsKey(uuid)) {
-                uri = (String) uriCache.get(uuid);
-            } else {
-                // retrieve info related to uuid using the locate-by-uuid report
-                ReportInfo rInfo = new ReportInfo(LocateByUuidReport.LOCATE_BY_UUID_REPORT);
-                rInfo.setContentElement(DomUtil.hrefToXml(uuid, domFactory));
-                try {
-                    ReportMethod rm = new ReportMethod(uri, rInfo);
-                    getClient(sessionInfo).executeMethod(rm);
-                    MultiStatus ms = rm.getResponseBodyAsMultiStatus();
-                    uri = ms.getResponses()[0].getHref();
-                    uriCache.put(uuid, uri);
-                } catch (IOException e) {
-                    throw new RepositoryException(e.getMessage());
-                } catch (DavException e) {
-                    throw ExceptionConverter.generate(e);
-                }
-            }
-        }
-        Path relativePath = itemId.getRelativePath();
-        if (relativePath != null) {
-            try {
-                String jcrPath = PathFormat.format(relativePath, this);
-                uri += Text.escapePath(jcrPath);
-            } catch (NoPrefixDeclaredException e) {
-                throw new RepositoryException(e);
-            }
-        }
-        if (itemId.denotesNode() && !uri.endsWith("/")) {
-            uri += "/";
-        }
-        return uri;
+    private String getItemUri(ItemId itemId, SessionInfo sessionInfo) throws RepositoryException {
+        return uriResolver.getItemUri(itemId, sessionInfo.getWorkspaceName(), sessionInfo);
     }
 
-    private String getItemUri(ItemId itemId, SessionInfo sessionInfo) throws RepositoryException {
-        return getItemUri(sessionInfo.getWorkspaceName(), itemId, sessionInfo);
+    private String getItemUri(ItemId itemId, String workspaceName, SessionInfo sessionInfo) throws RepositoryException {
+        return uriResolver.getItemUri(itemId, workspaceName, sessionInfo);
     }
 
     private String getItemUri(NodeId parentId, QName childName, SessionInfo sessionInfo) throws RepositoryException {
-        String parentUri = getItemUri(parentId, sessionInfo);
+        String parentUri = uriResolver.getItemUri(parentId, sessionInfo.getWorkspaceName(), sessionInfo);
         try {
             return parentUri + NameFormat.format(childName, getNamespaceResolver());
         } catch (NoPrefixDeclaredException e) {
@@ -307,22 +302,17 @@
         }
     }
 
-    private static void initMethod(DavMethod method, SessionInfo sessionInfo, boolean addIfHeader) {
-        if (addIfHeader) {
-            String[] locktokens = sessionInfo.getLockTokens();
-            // TODO: ev. build tagged if header
-            if (locktokens != null && locktokens.length > 0) {
-                IfHeader ifH = new IfHeader(locktokens);
-                method.setRequestHeader(ifH.getHeaderName(), ifH.getHeaderValue());
-            }
-        }
-        if (sessionInfo instanceof SessionInfoImpl) {
-            String txId = ((SessionInfoImpl) sessionInfo).getBatchId();
-            if (txId != null) {
-                CodedUrlHeader ch = new CodedUrlHeader(TransactionConstants.HEADER_TRANSACTIONID, txId);
-                method.setRequestHeader(ch.getHeaderName(), ch.getHeaderValue());
+    private NodeId getParentId(DavPropertySet propSet, SessionInfo sessionInfo)
+        throws RepositoryException {
+        NodeId parentId = null;
+        if (propSet.contains(ItemResourceConstants.JCR_PARENT)) {
+            HrefProperty parentProp = new HrefProperty(propSet.get(ItemResourceConstants.JCR_PARENT));
+            String parentHref = parentProp.getHrefs().get(0).toString();
+            if (parentHref != null && parentHref.length() > 0) {
+                parentId = getURIResolver().getNodeId(parentHref, sessionInfo);
             }
         }
+        return parentId;
     }
 
     //--------------------------------------------------< RepositoryService >---
@@ -340,7 +330,8 @@
         ReportInfo info = new ReportInfo(RepositoryDescriptorsReport.REPOSITORY_DESCRIPTORS_REPORT, DavConstants.DEPTH_0);
         ReportMethod method = null;
         try {
-            method = new ReportMethod(repositoryUri.getEscapedPath(), info);
+            method = new ReportMethod(getRepositoryUri(), info);
+
             getClient((Credentials) null).executeMethod(method);
             method.checkSuccess();
             Document doc = method.getResponseBodyAsDocument();
@@ -355,7 +346,7 @@
                     if (key != null && descriptor != null) {
                         descriptors.setProperty(key, descriptor);
                     } else {
-                        log.error("Invalid descriptor key / descriptor pair: " + key + " -> " + descriptor);
+                        log.error("Invalid descriptor key / value pair: " + key + " -> " + descriptor);
                     }
                 }
             }
@@ -496,13 +487,8 @@
      * @see RepositoryService#getRootId(SessionInfo)
      */
     public NodeId getRootId(SessionInfo sessionInfo) throws RepositoryException {
-        String rootUri = getRootItemUri(sessionInfo);
-        if (idCache.containsKey(rootUri)) {
-            return (NodeId) idCache.get(rootUri);
-        } else {
-            NodeId rootId = retrieveNodeId(rootUri, null, sessionInfo);
-            return rootId;
-        }
+        String rootUri = getRootItemUri(sessionInfo.getWorkspaceName());
+        return getURIResolver().getNodeId(rootUri, sessionInfo);
     }
 
     /**
@@ -626,7 +612,6 @@
 
             MultiStatusResponse nodeResponse = null;
             List childResponses = new ArrayList();
-
             for (int i = 0; i < responses.length; i++) {
                 String respHref = responses[i].getHref();
                 if (uri.equals(respHref)) {
@@ -638,7 +623,37 @@
             if (nodeResponse == null) {
                 throw new ItemNotFoundException("Unable to retrieve the node with id " + nodeId);
             }
-            NodeInfo nInfo = new NodeInfoImpl(nodeResponse, childResponses, getURIResolver(), sessionInfo);
+
+            DavPropertySet propSet = nodeResponse.getProperties(DavServletResponse.SC_OK);
+            NodeId parentId = getParentId(propSet, sessionInfo);
+            NodeId id = uriResolver.buildNodeId(parentId, nodeResponse, sessionInfo.getWorkspaceName());
+
+            NodeInfoImpl nInfo = new NodeInfoImpl(id, parentId, propSet, getNamespaceResolver());
+
+            for (Iterator it = childResponses.iterator(); it.hasNext();) {
+                MultiStatusResponse resp = (MultiStatusResponse) it.next();
+                DavPropertySet childProps = resp.getProperties(DavServletResponse.SC_OK);
+                if (childProps.contains(DavPropertyName.RESOURCETYPE) &&
+                    childProps.get(DavPropertyName.RESOURCETYPE).getValue() != null) {
+                    // any other resource type than default (empty) is represented by a node item
+                    NodeId childId = uriResolver.buildNodeId(id, resp, sessionInfo.getWorkspaceName());
+                    nInfo.addChildId(childId);
+                } else {
+                    PropertyId childId = uriResolver.buildPropertyId(id, resp, sessionInfo.getWorkspaceName());
+                    nInfo.addChildId(childId);
+                }
+            }
+
+            if (propSet.contains(ItemResourceConstants.JCR_REFERENCES)) {
+                HrefProperty refProp = new HrefProperty(propSet.get(ItemResourceConstants.JCR_REFERENCES));
+                Iterator hrefIter = refProp.getHrefs().iterator();
+                while(hrefIter.hasNext()) {
+                    String propertyHref = hrefIter.next().toString();
+                    PropertyId propertyId = getURIResolver().getPropertyId(propertyHref, sessionInfo);
+                    nInfo.addReference(propertyId);
+                }
+            }
+
             return nInfo;
         } catch (IOException e) {
             throw new RepositoryException(e);
@@ -646,7 +661,7 @@
             throw ExceptionConverter.generate(e);
         } finally {
             if (method != null) {
-                method.releaseConnection();
+                //method.releaseConnection();
             }
         }
     }
@@ -676,8 +691,12 @@
                 throw new ItemNotFoundException("Unable to retrieve the property with id " + propertyId);
             }
 
-            PropertyInfo pInfo = new PropertyInfoImpl(responses[0],
-                getURIResolver(), getNamespaceResolver(), sessionInfo, valueFactory);
+
+            DavPropertySet propSet = responses[0].getProperties(DavServletResponse.SC_OK);
+            NodeId parentId = getParentId(propSet, sessionInfo);
+            PropertyId id = uriResolver.buildPropertyId(parentId, responses[0], sessionInfo.getWorkspaceName());
+
+            PropertyInfo pInfo = new PropertyInfoImpl(id, parentId, propSet, getNamespaceResolver(), valueFactory);
             return pInfo;
         } catch (IOException e) {
             throw new RepositoryException(e);
@@ -755,7 +774,7 @@
             String uri = getItemUri(parentId, nodeName, sessionInfo);
             method = new MkColMethod(uri);
             initMethod(method, sessionInfo, true);
-            method.setRequestBody(xmlStream);
+            method.setRequestEntity(new InputStreamRequestEntity(xmlStream, "text/xml"));
 
             getClient(sessionInfo).executeMethod(method);
             method.checkSuccess();
@@ -806,7 +825,7 @@
     public EventIterator copy(SessionInfo sessionInfo, String srcWorkspaceName, NodeId srcNodeId, NodeId destParentNodeId, QName destName) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, UnsupportedRepositoryOperationException, RepositoryException {
         CopyMethod method = null;
         try {
-            String uri = getItemUri(srcWorkspaceName, srcNodeId, sessionInfo);
+            String uri = getItemUri(srcNodeId, srcWorkspaceName, sessionInfo);
             String destUri = getItemUri(destParentNodeId, destName, sessionInfo);
             method = new CopyMethod(uri, destUri, true, false);
             initMethod(method, sessionInfo, true);
@@ -1332,8 +1351,7 @@
                     if (uri != null) {
                         namespaces.setProperty(prefix, uri);
                         // TODO: not correct since nsRegistry is retrieved from each session
-                        prefixToURI.setProperty(prefix, uri);
-                        uriToPrefix.setProperty(uri, prefix);
+                        nsResolver.add(prefix, uri);
                     } else {
                         log.error("Invalid prefix / uri pair: " + prefix + " -> " + uri);
                     }
@@ -1355,29 +1373,29 @@
      * @see RepositoryService#registerNamespace(SessionInfo, String, String)
      */
     public void registerNamespace(SessionInfo sessionInfo, String prefix, String uri) throws NamespaceException, UnsupportedRepositoryOperationException, AccessDeniedException, RepositoryException {
-        Properties namespaces = new Properties();
-        namespaces.putAll(prefixToURI);
+        Properties namespaces = nsResolver.getNamespaces();
+        // add new pair that needs to be registered.
         namespaces.setProperty(prefix, uri);
+
         internalSetNamespaces(sessionInfo, namespaces);
         // adjust internal mappings:
         // TODO: not correct since nsRegistry is retrieved from each session
-        prefixToURI.setProperty(prefix, uri);
-        uriToPrefix.setProperty(uri, prefix);
+        nsResolver.add(prefix, uri);
     }
 
     /**
      * @see RepositoryService#unregisterNamespace(SessionInfo, String)
      */
     public void unregisterNamespace(SessionInfo sessionInfo, String uri) throws NamespaceException, UnsupportedRepositoryOperationException, AccessDeniedException, RepositoryException {
-        String prefix = uriToPrefix.getProperty(uri);
-        Properties namespaces = new Properties();
-        namespaces.putAll(prefixToURI);
+        String prefix = nsResolver.getPrefix(uri);
+        Properties namespaces = nsResolver.getNamespaces();
+        // remove pair that needs to be unregistered
         namespaces.remove(prefix);
+
         internalSetNamespaces(sessionInfo, namespaces);
         // adjust internal mappings:
         // TODO: not correct since nsRegistry is retrieved from each session
-        prefixToURI.remove(prefix);
-        uriToPrefix.remove(uri);
+        nsResolver.remove(prefix, uri);
     }
 
     /**
@@ -1465,184 +1483,6 @@
         // TODO: missing implementation
     }
 
-    //--------------------------------------------------< NamespaceResolver >---
-    private NamespaceResolver getNamespaceResolver() {
-        return this;
-    }
-
-    public String getURI(String prefix) throws NamespaceException {
-        String uri = (String) prefixToURI.get(prefix);
-        if (uri == null) {
-            throw new NamespaceException(prefix + ": is not a registered namespace prefix.");
-        }
-        return uri;
-    }
-
-    public String getPrefix(String uri) throws NamespaceException {
-        String prefix = (String) uriToPrefix.get(uri);
-        if (prefix == null) {
-            throw new NamespaceException(uri
-                + ": is not a registered namespace uri.");
-        }
-        return prefix;
-    }
-
-    //-------------------------------------------------------< URI resolver >---
-
-    private URIResolver getURIResolver() {
-        return this;
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public Path getQPath(String uri, SessionInfo sessionInfo) throws RepositoryException {
-        String repoUri = getRepositoryUri();
-        String wspUri = getWorkspaceUri(sessionInfo.getWorkspaceName());
-        String jcrPath;
-        if (uri.startsWith(wspUri)) {
-            jcrPath = uri.substring(wspUri.length());
-        } else if (uri.startsWith(repoUri)) {
-            jcrPath = uri.substring(repoUri.length());
-            // then cut workspace name
-            jcrPath = jcrPath.substring(jcrPath.indexOf('/', 1));
-        } else {
-            // todo: probably rather an error?
-            jcrPath = uri;
-        }
-        try {
-            return PathFormat.parse(jcrPath, this);
-        } catch (MalformedPathException e) {
-            throw new RepositoryException();
-        }
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public NodeId getNodeId(NodeId parentId, MultiStatusResponse response) throws RepositoryException {
-        // build the id
-        NodeId nodeId;
-        DavPropertySet propSet = response.getProperties(DavServletResponse.SC_OK);
-        String nodeURI = response.getHref();
-        if (propSet.contains(ItemResourceConstants.JCR_UUID)) {
-            String uuid = propSet.get(ItemResourceConstants.JCR_UUID).getValue().toString();
-            // make sure the mapping uuid -> uri is cached
-            uriCache.put(uuid, nodeURI);
-            nodeId = idFactory.createNodeId(uuid);
-        } else {
-            DavProperty nameProp = propSet.get(ItemResourceConstants.JCR_NAME);
-            if (nameProp != null && nameProp.getValue() != null) {
-                // not root node. Note that 'unespacing' is not required since
-                // the jcr:name property does not provide the value in escaped form.
-                String jcrName = nameProp.getValue().toString();
-                int index = org.apache.jackrabbit.name.Path.INDEX_UNDEFINED;
-                DavProperty indexProp = propSet.get(ItemResourceConstants.JCR_INDEX);
-                if (indexProp != null && indexProp.getValue() != null) {
-                    index = Integer.parseInt(indexProp.getValue().toString());
-                }
-                try {
-                    QName qName = NameFormat.parse(jcrName, getNamespaceResolver());
-                    nodeId = idFactory.createNodeId(parentId, Path.create(qName, index));
-                } catch (NameException e) {
-                    throw new RepositoryException(e);
-                }
-            } else {
-                // special case: root node
-                nodeId = idFactory.createNodeId((String)null, Path.ROOT);
-            }
-        }
-
-        // mapping href to nodeId
-        idCache.put(nodeURI, nodeId);
-        return nodeId;
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public NodeId getNodeId(String uri, SessionInfo sessionInfo) throws RepositoryException {
-        if (idCache.containsKey(uri)) {
-            // id has been accessed before and
-            return (NodeId) idCache.get(uri);
-        } else {
-            // retrieve parentId from cache or by recursive calls
-            NodeId parentId;
-            if (getRootItemUri(sessionInfo).equals(uri)) {
-                parentId = null;
-            } else {
-                String parentUri = Text.getRelativeParent(uri, 1, true);
-                if (!parentUri.endsWith("/")) {
-                    parentUri += "/";
-                }
-                parentId = getNodeId(parentUri, sessionInfo);
-            }
-            NodeId id = retrieveNodeId(uri, parentId, sessionInfo);
-            idCache.put(uri, id);
-            return id;
-        }
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public PropertyId getPropertyId(NodeId parentId, MultiStatusResponse response) throws RepositoryException {
-        try {
-            DavPropertySet propSet = response.getProperties(DavServletResponse.SC_OK);
-            QName name = NameFormat.parse(propSet.get(ItemResourceConstants.JCR_NAME).getValue().toString(), getNamespaceResolver());
-            PropertyId propertyId = idFactory.createPropertyId(parentId, name);
-            return propertyId;
-        } catch (BaseException e) {
-            throw new RepositoryException(e);
-        }
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public PropertyId getPropertyId(String uri, SessionInfo sessionInfo) throws RepositoryException {
-        String propertyUri = uri;
-        // separate parent uri and property JCRName
-        String parentUri = Text.getRelativeParent(propertyUri, 1, true);
-        // make sure propName is unescaped
-        String propName = Text.unescape(Text.getName(propertyUri));
-        // retrieve parent node id
-        NodeId parentId = getNodeId(parentUri, sessionInfo);
-        // build property id
-        try {
-            PropertyId propertyId = idFactory.createPropertyId(parentId, NameFormat.parse(propName, getNamespaceResolver()));
-            return propertyId;
-        } catch (NameException e) {
-            throw new RepositoryException(e);
-        }
-    }
-
-    private NodeId retrieveNodeId(String uri, NodeId parentId, SessionInfo sessionInfo) throws RepositoryException {
-        DavPropertyNameSet nameSet = new DavPropertyNameSet();
-        nameSet.add(ItemResourceConstants.JCR_UUID);
-        nameSet.add(ItemResourceConstants.JCR_NAME);
-        nameSet.add(ItemResourceConstants.JCR_INDEX);
-        DavMethodBase method = null;
-        try {
-            method = new PropFindMethod(uri, nameSet, DEPTH_0);
-            initMethod(method, sessionInfo, false);
-            getClient(sessionInfo).executeMethod(method);
-            MultiStatusResponse[] responses = method.getResponseBodyAsMultiStatus().getResponses();
-            if (responses.length != 1) {
-                throw new ItemNotFoundException("Unable to retrieve the node with id " + uri);
-            }
-            return getNodeId(parentId, responses[0]);
-        } catch (IOException e) {
-            throw new RepositoryException(e);
-        } catch (DavException e) {
-            throw ExceptionConverter.generate(e);
-        } finally {
-            if (method != null) {
-                method.releaseConnection();
-            }
-        }
-    }
-
     //------------------------------------------------< Inner Class 'Batch' >---
     private class BatchImpl implements Batch {
 
@@ -1658,7 +1498,7 @@
         private HttpClient start() throws RepositoryException {
             checkConsumed();
             try {
-                String uri = getRootItemUri(sessionInfo);
+                String uri = getRootItemUri(sessionInfo.getWorkspaceName());
                 LockMethod method = new LockMethod(uri, TransactionConstants.LOCAL, TransactionConstants.TRANSACTION, null, DavConstants.INFINITE_TIMEOUT, true);
                 initMethod(method, sessionInfo, false);
 
@@ -1679,7 +1519,7 @@
         private void end(HttpClient client, boolean discard) throws RepositoryException {
             checkConsumed();
             try {
-                String uri = getRootItemUri(sessionInfo);
+                String uri = getRootItemUri(sessionInfo.getWorkspaceName());
                 UnLockMethod method = new UnLockMethod(uri, sessionInfo.getBatchId());
                 // todo: check if 'initmethod' would work (ev. conflict with TxId header).
                 String[] locktokens = sessionInfo.getLockTokens();

Modified: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolver.java?view=diff&rev=448587&r1=448586&r2=448587
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolver.java (original)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolver.java Thu Sep 21 08:40:53 2006
@@ -16,8 +16,6 @@
  */
 package org.apache.jackrabbit.spi2dav;
 
-import org.apache.jackrabbit.name.NamespaceResolver;
-import org.apache.jackrabbit.webdav.MultiStatusResponse;
 import org.apache.jackrabbit.spi.NodeId;
 import org.apache.jackrabbit.spi.PropertyId;
 import org.apache.jackrabbit.name.Path;
@@ -26,24 +24,13 @@
 import javax.jcr.RepositoryException;
 
 /**
- * <code>URIResolver</code> used to build HTTP compliant request URIs from
- * a given ItemId.
- * This includes:
- * <ul>
- * <li>converting qualified names consisting of {uri}localName to URI compliant jcr names</li>
- * <li>adding trailing base (repository) uri and workspace name in order to form the proper url</li>
- * </ul>
+ * <code>URIResolver</code> used to build ItemIds from URIs.
  */
-// todo: namespace resolver needed for the remapping. potential consistency problems with NamespaceRegistryImpl in jcr2spi layer?
-interface URIResolver extends NamespaceResolver {
+interface URIResolver {
 
     Path getQPath(String uri, SessionInfo sessionInfo) throws RepositoryException;
 
-    NodeId getNodeId(NodeId parentId, MultiStatusResponse response) throws RepositoryException;
-
     NodeId getNodeId(String uri, SessionInfo sessionInfo) throws RepositoryException;
-
-    PropertyId getPropertyId(NodeId parentId, MultiStatusResponse response) throws RepositoryException;
 
     PropertyId getPropertyId(String uri, SessionInfo sessionInfo) throws RepositoryException;
 }

Added: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolverImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolverImpl.java?view=auto&rev=448587
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolverImpl.java (added)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolverImpl.java Thu Sep 21 08:40:53 2006
@@ -0,0 +1,356 @@
+/*
+ * 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.spi2dav;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.name.Path;
+import org.apache.jackrabbit.name.PathFormat;
+import org.apache.jackrabbit.name.MalformedPathException;
+import org.apache.jackrabbit.name.NameFormat;
+import org.apache.jackrabbit.name.NameException;
+import org.apache.jackrabbit.name.NoPrefixDeclaredException;
+import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.spi.SessionInfo;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.PropertyId;
+import org.apache.jackrabbit.spi.ItemId;
+import org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.apache.jackrabbit.webdav.property.DavPropertySet;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants;
+import org.apache.jackrabbit.webdav.jcr.version.report.LocateByUuidReport;
+import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
+import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
+import org.apache.jackrabbit.webdav.client.methods.ReportMethod;
+import org.apache.jackrabbit.webdav.client.methods.DavMethod;
+import org.apache.jackrabbit.webdav.MultiStatusResponse;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.MultiStatus;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.transaction.TransactionConstants;
+import org.apache.jackrabbit.webdav.header.CodedUrlHeader;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.version.report.ReportInfo;
+import org.apache.jackrabbit.BaseException;
+import org.apache.commons.httpclient.URI;
+import org.w3c.dom.Document;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.ItemNotFoundException;
+import java.io.IOException;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * <code>URIResolverImpl</code>...
+ */
+class URIResolverImpl implements URIResolver {
+
+    private static Logger log = LoggerFactory.getLogger(URIResolverImpl.class);
+
+    private final URI repositoryUri;
+    private final RepositoryServiceImpl service;
+    private final NamespaceResolver nsResolver;
+    private final Document domFactory;
+
+    // TODO: to-be-fixed. uri/id-caches don't get updated
+    // for each workspace a separate idUri-cache is created
+    private final Map idURICaches = new HashMap();
+
+    URIResolverImpl(URI repositoryUri, RepositoryServiceImpl service,
+                    NamespaceResolver nsResolver, Document domFactory) {
+        this.repositoryUri = repositoryUri;
+        this.service = service;
+        this.nsResolver = nsResolver;
+        this.domFactory = domFactory;
+    }
+
+    private static void initMethod(DavMethod method, SessionInfo sessionInfo) {
+        if (sessionInfo instanceof SessionInfoImpl) {
+            String txId = ((SessionInfoImpl) sessionInfo).getBatchId();
+            if (txId != null) {
+                CodedUrlHeader ch = new CodedUrlHeader(TransactionConstants.HEADER_TRANSACTIONID, txId);
+                method.setRequestHeader(ch.getHeaderName(), ch.getHeaderValue());
+            }
+        }
+    }
+
+    private IdURICache getCache(String workspaceName) {
+        if (idURICaches.containsKey(workspaceName)) {
+            return (IdURICache) idURICaches.get(workspaceName);
+        } else {
+            IdURICache c = new IdURICache(getWorkspaceUri(workspaceName));
+            idURICaches.put(workspaceName, c);
+            return c;
+        }
+    }
+
+    String getRepositoryUri() {
+        return repositoryUri.getEscapedURI();
+    }
+
+    String getWorkspaceUri(String workspaceName) {
+        String workspaceUri = getRepositoryUri();
+        if (workspaceName != null) {
+            workspaceUri += Text.escape(workspaceName);
+        }
+        return workspaceUri;
+    }
+
+    String getRootItemUri(String workspaceName) {
+        return getWorkspaceUri(workspaceName) + Text.escapePath(ItemResourceConstants.ROOT_ITEM_RESOURCEPATH) + "/";
+    }
+
+    String getItemUri(ItemId itemId, String workspaceName,
+                      SessionInfo sessionInfo) throws RepositoryException {
+        IdURICache cache = getCache(workspaceName);
+        // check if uri is available from cache
+        if (cache.containsItemId(itemId)) {
+            return cache.getUri(itemId);
+        } else {
+            StringBuffer uriBuffer = new StringBuffer();
+
+            Path relativePath = itemId.getRelativePath();
+            String uuid = itemId.getUUID();
+
+            // resolver uuid part
+            if (uuid != null) {
+                ItemId uuidId = (relativePath == null) ? itemId : service.getIdFactory().createNodeId(uuid);
+                if (relativePath != null & cache.containsItemId(uuidId)) {
+                    // append uri of parent node, that is already cached
+                    uriBuffer.append(cache.getUri(uuidId));
+                } else {
+                    // request locate-by-uuid report to build the uri
+                    ReportInfo rInfo = new ReportInfo(LocateByUuidReport.LOCATE_BY_UUID_REPORT);
+                    rInfo.setContentElement(DomUtil.hrefToXml(uuid, domFactory));
+                    try {
+                        String wspUri = getWorkspaceUri(workspaceName);
+                        ReportMethod rm = new ReportMethod(wspUri, rInfo);
+                        initMethod(rm, sessionInfo);
+
+                        service.getClient(sessionInfo).executeMethod(rm);
+
+                        MultiStatus ms = rm.getResponseBodyAsMultiStatus();
+                        if (ms.getResponses().length == 1) {
+                            uriBuffer.append(ms.getResponses()[0].getHref());
+                            cache.add(ms.getResponses()[0].getHref(), uuidId);
+                        } else {
+                            throw new RepositoryException("Cannot identify item with uuid " + uuid);
+                        }
+
+                    } catch (IOException e) {
+                        throw new RepositoryException(e.getMessage());
+                    } catch (DavException e) {
+                        throw ExceptionConverter.generate(e);
+                    }
+                }
+            } else {
+                // start build uri from root-item
+                uriBuffer.append(getRootItemUri(workspaceName));
+            }
+            // resolve relative-path part unless it denotes the root-item
+            if (relativePath != null && !relativePath.denotesRoot()) {
+                try {
+                    String jcrPath = PathFormat.format(relativePath, nsResolver);
+                    // TODO: TOBEFIXED rootId is currently build from absolute path and not
+                    // from '.' as description in RS.getRootId defines. similarly
+                    // the PathResolver does not accept a non-normalized root-path.
+                    if (relativePath.isAbsolute()) {
+                        jcrPath = jcrPath.substring(1);
+                    }
+                    uriBuffer.append(Text.escapePath(jcrPath));
+                } catch (NoPrefixDeclaredException e) {
+                    throw new RepositoryException(e);
+                }
+            }
+            // add training / for nodes
+            if (itemId.denotesNode() && uriBuffer.charAt(uriBuffer.length()-1) != '/') {
+                uriBuffer.append('/');
+            }
+
+            String itemUri = uriBuffer.toString();
+            if (!cache.containsItemId(itemId)) {
+                cache.add(itemUri, itemId);
+            }
+            return itemUri;
+        }
+    }
+
+    NodeId buildNodeId(NodeId parentId, MultiStatusResponse response,
+                       String workspaceName) throws RepositoryException {
+        IdURICache cache = getCache(workspaceName);
+        if (cache.containsUri(response.getHref())) {
+            return (NodeId) cache.getItemId(response.getHref());
+        }
+
+        NodeId nodeId;
+        DavPropertySet propSet = response.getProperties(DavServletResponse.SC_OK);
+
+        if (propSet.contains(ItemResourceConstants.JCR_UUID)) {
+            String uuid = propSet.get(ItemResourceConstants.JCR_UUID).getValue().toString();
+            nodeId = service.getIdFactory().createNodeId(uuid);
+        } else {
+            DavProperty nameProp = propSet.get(ItemResourceConstants.JCR_NAME);
+            if (nameProp != null && nameProp.getValue() != null) {
+                // not root node. Note that 'unespacing' is not required since
+                // the jcr:name property does not provide the value in escaped form.
+                String jcrName = nameProp.getValue().toString();
+                int index = Path.INDEX_UNDEFINED;
+                DavProperty indexProp = propSet.get(ItemResourceConstants.JCR_INDEX);
+                if (indexProp != null && indexProp.getValue() != null) {
+                    index = Integer.parseInt(indexProp.getValue().toString());
+                }
+                try {
+                    QName qName = NameFormat.parse(jcrName, nsResolver);
+                    nodeId = service.getIdFactory().createNodeId(parentId, Path.create(qName, index));
+                } catch (NameException e) {
+                    throw new RepositoryException(e);
+                }
+            } else {
+                // TODO: TO_BE_FIXED.... special case: root node
+                return service.getIdFactory().createNodeId((String) null, Path.ROOT);
+            }
+        }
+
+        // cache
+        cache.add(response.getHref(), nodeId);
+        return nodeId;
+    }
+
+    PropertyId buildPropertyId(NodeId parentId, MultiStatusResponse response,
+                               String workspaceName) throws RepositoryException {
+        IdURICache cache = getCache(workspaceName);
+        if (cache.containsUri(response.getHref())) {
+            return (PropertyId) cache.getItemId(response.getHref());
+        } else {
+            try {
+                DavPropertySet propSet = response.getProperties(DavServletResponse.SC_OK);
+                QName name = NameFormat.parse(propSet.get(ItemResourceConstants.JCR_NAME).getValue().toString(), nsResolver);
+                PropertyId propertyId = service.getIdFactory().createPropertyId(parentId, name);
+
+                cache.add(response.getHref(), propertyId);
+                return propertyId;
+            } catch (BaseException e) {
+                throw new RepositoryException(e);
+            }
+        }
+    }
+
+    //-------------------------------------------------------< URI resolver >---
+    /**
+     * @inheritDoc
+     */
+    public Path getQPath(String uri, SessionInfo sessionInfo) throws RepositoryException {
+        String repoUri = getRepositoryUri();
+        String wspUri = getWorkspaceUri(sessionInfo.getWorkspaceName());
+        String jcrPath;
+        if (uri.startsWith(wspUri)) {
+            jcrPath = uri.substring(wspUri.length());
+        } else if (uri.startsWith(repoUri)) {
+            jcrPath = uri.substring(repoUri.length());
+            // then cut workspace name
+            jcrPath = jcrPath.substring(jcrPath.indexOf('/', 1));
+        } else {
+            // todo: probably rather an error?
+            jcrPath = uri;
+        }
+        try {
+            return PathFormat.parse(jcrPath, nsResolver);
+        } catch (MalformedPathException e) {
+            throw new RepositoryException();
+        }
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public NodeId getNodeId(String uri, SessionInfo sessionInfo) throws RepositoryException {
+        IdURICache cache = getCache(sessionInfo.getWorkspaceName());
+        if (cache.containsUri(uri)) {
+            // id has been accessed before and is cached
+            return (NodeId) cache.getItemId(uri);
+        } else {
+            // retrieve parentId from cache or by recursive calls
+            NodeId parentId;
+            if (uri.equals(getRootItemUri(sessionInfo.getWorkspaceName()))) {
+                parentId = null;
+            } else {
+                String parentUri = Text.getRelativeParent(uri, 1, true);
+                if (!parentUri.endsWith("/")) {
+                    parentUri += "/";
+                }
+                parentId = getNodeId(parentUri, sessionInfo);
+            }
+
+            DavPropertyNameSet nameSet = new DavPropertyNameSet();
+            nameSet.add(ItemResourceConstants.JCR_UUID);
+            nameSet.add(ItemResourceConstants.JCR_NAME);
+            nameSet.add(ItemResourceConstants.JCR_INDEX);
+            DavMethodBase method = null;
+            try {
+                method = new PropFindMethod(uri, nameSet, DavConstants.DEPTH_0);
+                initMethod(method, sessionInfo);
+
+                service.getClient(sessionInfo).executeMethod(method);
+                MultiStatusResponse[] responses = method.getResponseBodyAsMultiStatus().getResponses();
+                if (responses.length != 1) {
+                    throw new ItemNotFoundException("Unable to retrieve the node with id " + uri);
+                }
+                return buildNodeId(parentId, responses[0], sessionInfo.getWorkspaceName());
+
+            } catch (IOException e) {
+                throw new RepositoryException(e);
+            } catch (DavException e) {
+                throw ExceptionConverter.generate(e);
+            } finally {
+                if (method != null) {
+                    method.releaseConnection();
+                }
+            }
+        }
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public PropertyId getPropertyId(String uri, SessionInfo sessionInfo) throws RepositoryException {
+        IdURICache cache = getCache(sessionInfo.getWorkspaceName());
+        if (cache.containsUri(uri)) {
+            return (PropertyId) cache.getItemId(uri);
+        } else {
+            // separate parent uri and property JCRName
+            String parentUri = Text.getRelativeParent(uri, 1, true);
+            // make sure propName is unescaped
+            String propName = Text.unescape(Text.getName(uri, true));
+            // retrieve parent node id
+            NodeId parentId = getNodeId(parentUri, sessionInfo);
+            // build property id
+            try {
+                PropertyId propertyId = service.getIdFactory().createPropertyId(parentId, NameFormat.parse(propName, nsResolver));
+                cache.add(uri, propertyId);
+
+                return propertyId;
+            } catch (NameException e) {
+                throw new RepositoryException(e);
+            }
+        }
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolverImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolverImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url



Mime
View raw message