jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r448257 [1/2] - in /jackrabbit/trunk/jcr-server: server/src/java/org/apache/jackrabbit/webdav/jcr/ server/src/java/org/apache/jackrabbit/webdav/simple/ webapp/src/java/org/apache/jackrabbit/j2ee/
Date Wed, 20 Sep 2006 16:32:53 GMT
Author: angela
Date: Wed Sep 20 09:32:51 2006
New Revision: 448257

URL: http://svn.apache.org/viewvc?view=rev&rev=448257
Log:
JCR-417 (preparation):
- add AbstractLocatorFactory
- add separate loc-factory to simple project => reducing dependency
  to 'jcr' package.

JCR-544
- add separate workspace resource representing the jcr workspace
- move Workspace.restore call to workspace resource.
- consequently RootItemCollection not used any more

minor improvements
- root, workspace resource must not support 'observation' -> moving
  constant to item-resources
- get rid of 'setModificationTime'


Added:
    jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java   (with props)
    jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.java   (with props)
Removed:
    jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootItemCollection.java
Modified:
    jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java
    jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java
    jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java
    jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java
    jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java
    jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java
    jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.java
    jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java
    jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java
    jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java
    jackrabbit/trunk/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java
    jackrabbit/trunk/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java

Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java?view=diff&rev=448257&r1=448256&r2=448257
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java Wed Sep 20 09:32:51 2006
@@ -22,20 +22,24 @@
 import org.apache.jackrabbit.webdav.DavResourceFactory;
 import org.apache.jackrabbit.webdav.DavResourceLocator;
 import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavCompliance;
+import org.apache.jackrabbit.webdav.io.OutputContext;
+import org.apache.jackrabbit.webdav.observation.ObservationResource;
+import org.apache.jackrabbit.webdav.observation.SubscriptionManager;
+import org.apache.jackrabbit.webdav.observation.Subscription;
+import org.apache.jackrabbit.webdav.observation.SubscriptionInfo;
+import org.apache.jackrabbit.webdav.observation.EventDiscovery;
+import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery;
 import org.apache.jackrabbit.webdav.jcr.nodetype.ItemDefinitionImpl;
 import org.apache.jackrabbit.webdav.jcr.nodetype.NodeDefinitionImpl;
 import org.apache.jackrabbit.webdav.jcr.nodetype.PropertyDefinitionImpl;
-import org.apache.jackrabbit.webdav.jcr.version.report.LocateByUuidReport;
-import org.apache.jackrabbit.webdav.jcr.version.report.NodeTypesReport;
-import org.apache.jackrabbit.webdav.jcr.version.report.RegisteredNamespacesReport;
-import org.apache.jackrabbit.webdav.jcr.version.report.RepositoryDescriptorsReport;
 import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
 import org.apache.jackrabbit.webdav.property.HrefProperty;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
 import org.apache.jackrabbit.webdav.security.CurrentUserPrivilegeSetProperty;
 import org.apache.jackrabbit.webdav.security.Privilege;
 import org.apache.jackrabbit.webdav.transaction.TxLockEntry;
-import org.apache.jackrabbit.webdav.version.report.ReportType;
-import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -48,16 +52,18 @@
 import java.security.AccessControlException;
 import java.util.ArrayList;
 import java.util.List;
+import java.io.IOException;
 
 /**
  * <code>AbstractItemResource</code> covers common functionality for the various
  * resources, that represent a repository item.
  */
 abstract class AbstractItemResource extends AbstractResource implements
-    ItemResourceConstants {
+    ObservationResource, ItemResourceConstants {
 
     private static Logger log = LoggerFactory.getLogger(AbstractItemResource.class);
 
+    private SubscriptionManager subsMgr;
     protected final Item item;
 
     /**
@@ -71,7 +77,7 @@
         super(locator, session, factory);
         this.item = item;
 
-	// initialize the supported locks and reports
+        // initialize the supported locks and reports
         initLockSupport();
         initSupportedReports();
     }
@@ -81,7 +87,8 @@
      * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass()
      */
     public String getComplianceClass() {
-        return ItemResourceConstants.COMPLIANCE_CLASS;
+        String cc = super.getComplianceClass() + "," + DavCompliance.OBSERVATION;
+        return cc;
     }
 
     /**
@@ -117,6 +124,44 @@
     }
 
     /**
+     * Spools the properties of this resource to the context. Note that subclasses
+     * are in charge of spooling the data to the output stream provided by the
+     * context.
+     *
+     * @see DavResource#spool(OutputContext)
+     */
+    public void spool(OutputContext outputContext) throws IOException {
+        if (!initedProps) {
+            initProperties();
+        }
+        // export properties
+        outputContext.setModificationTime(getModificationTime());
+        DavProperty etag = getProperty(DavPropertyName.GETETAG);
+        if (etag != null) {
+            outputContext.setETag(String.valueOf(etag.getValue()));
+        }
+        DavProperty contentType = getProperty(DavPropertyName.GETCONTENTTYPE);
+        if (contentType != null) {
+            outputContext.setContentType(String.valueOf(contentType.getValue()));
+        }
+        DavProperty contentLength = getProperty(DavPropertyName.GETCONTENTLENGTH);
+        if (contentLength != null) {
+            try {
+                long length = Long.parseLong(contentLength.getValue() + "");
+                if (length > 0) {
+                    outputContext.setContentLength(length);
+                }
+            } catch (NumberFormatException e) {
+                log.error("Could not build content length from property value '" + contentLength.getValue() + "'");
+            }
+        }
+        DavProperty contentLanguage = getProperty(DavPropertyName.GETCONTENTLANGUAGE);
+        if (contentLanguage != null) {
+            outputContext.setContentLanguage(contentLanguage.getValue().toString());
+        }
+    }
+
+    /**
      * Returns the resource representing the parent item of the repository item
      * represented by this resource. If this resoure represents the root item
      * a {@link RootCollection} is returned.
@@ -129,13 +174,8 @@
     public DavResource getCollection() {
         DavResource collection = null;
 
-        String resourcePath = getResourcePath();
-        // No special treatment for the root-item needed, because this is
-        // covered by the RootItemCollection itself.
-        String parentResourcePath = Text.getRelativeParent(resourcePath, 1);
-        String parentWorkspacePath = getLocator().getWorkspacePath();
-
-        DavResourceLocator parentLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), parentWorkspacePath, parentResourcePath);
+        String parentPath = Text.getRelativeParent(getResourcePath(), 1);
+        DavResourceLocator parentLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), getLocator().getWorkspacePath(), parentPath);
         try {
             collection = createResourceFromLocator(parentLoc);
         } catch (DavException e) {
@@ -223,6 +263,39 @@
         }
     }
 
+    //--------------------------------------< ObservationResource interface >---
+    /**
+     * @see ObservationResource#init(SubscriptionManager)
+     */
+    public void init(SubscriptionManager subsMgr) {
+        this.subsMgr = subsMgr;
+    }
+
+    /**
+     * @see ObservationResource#subscribe(org.apache.jackrabbit.webdav.observation.SubscriptionInfo, String)
+     * @see SubscriptionManager#subscribe(org.apache.jackrabbit.webdav.observation.SubscriptionInfo, String, org.apache.jackrabbit.webdav.observation.ObservationResource)
+     */
+    public Subscription subscribe(SubscriptionInfo info, String subscriptionId)
+            throws DavException {
+        return subsMgr.subscribe(info, subscriptionId, this);
+    }
+
+    /**
+     * @see ObservationResource#unsubscribe(String)
+     * @see SubscriptionManager#unsubscribe(String, org.apache.jackrabbit.webdav.observation.ObservationResource)
+     */
+    public void unsubscribe(String subscriptionId) throws DavException {
+        subsMgr.unsubscribe(subscriptionId, this);
+    }
+
+    /**
+     * @see ObservationResource#poll(String)
+     * @see SubscriptionManager#poll(String, org.apache.jackrabbit.webdav.observation.ObservationResource)
+     */
+    public EventDiscovery poll(String subscriptionId) throws DavException {
+        return subsMgr.poll(subscriptionId, this);
+    }
+
     //--------------------------------------------------------------------------
     /**
      * Initialize the {@link org.apache.jackrabbit.webdav.lock.SupportedLock} property
@@ -241,24 +314,6 @@
     }
 
     /**
-     * Define the set of reports supported by this resource.
-     *
-     * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty
-     * @see AbstractResource#initSupportedReports()
-     */
-    protected void initSupportedReports() {
-        if (exists()) {
-            supportedReports = new SupportedReportSetProperty(new ReportType[] {
-                ReportType.EXPAND_PROPERTY,
-                NodeTypesReport.NODETYPES_REPORT,
-                LocateByUuidReport.LOCATE_BY_UUID_REPORT,
-                RegisteredNamespacesReport.REGISTERED_NAMESPACES_REPORT,
-                RepositoryDescriptorsReport.REPOSITORY_DESCRIPTORS_REPORT
-            });
-        }
-    }
-
-    /**
      * Fill the property set for this resource.
      */
     protected void initProperties() {
@@ -285,7 +340,7 @@
                 // should not get here
                 log.error("Error while accessing jcr properties: " + e.getMessage());
             }
-            
+
             // transaction resource additional protected properties
             if (item.isNew()) {
                 properties.add(new DefaultDavProperty(JCR_ISNEW, null, true));
@@ -294,6 +349,10 @@
             }
         }
 
+        // observation resource
+        SubscriptionDiscovery subsDiscovery = subsMgr.getSubscriptionDiscovery(this);
+        properties.add(subsDiscovery);
+
         // TODO complete set of properties defined by RFC 3744
         Privilege[] allPrivs = new Privilege[] {PRIVILEGE_JCR_READ,
                                                 PRIVILEGE_JCR_ADD_NODE,
@@ -325,12 +384,13 @@
      */
     protected String getWorkspaceHref() {
         String workspaceHref = null;
-	DavResourceLocator locator = getLocator();
-        if (locator != null && locator.getWorkspaceName() != null) {
-            DavResourceLocator wspLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), ItemResourceConstants.ROOT_ITEM_PATH);
+        DavResourceLocator locator = getLocator();
+        if (locator != null && locator.getWorkspacePath() != null) {
+            String wspPath = locator.getWorkspacePath();
+            DavResourceLocator wspLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), wspPath, wspPath);
             workspaceHref = wspLocator.getHref(true);
         }
-	log.info(workspaceHref);
+        log.debug(workspaceHref);
         return workspaceHref;
     }
 

Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java?view=diff&rev=448257&r1=448256&r2=448257
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java Wed Sep 20 09:32:51 2006
@@ -27,9 +27,13 @@
 import org.apache.jackrabbit.webdav.DavSession;
 import org.apache.jackrabbit.webdav.MultiStatus;
 import org.apache.jackrabbit.webdav.MultiStatusResponse;
-import org.apache.jackrabbit.webdav.io.OutputContext;
+import org.apache.jackrabbit.webdav.DavCompliance;
 import org.apache.jackrabbit.webdav.jcr.search.SearchResourceImpl;
 import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl;
+import org.apache.jackrabbit.webdav.jcr.version.report.NodeTypesReport;
+import org.apache.jackrabbit.webdav.jcr.version.report.LocateByUuidReport;
+import org.apache.jackrabbit.webdav.jcr.version.report.RegisteredNamespacesReport;
+import org.apache.jackrabbit.webdav.jcr.version.report.RepositoryDescriptorsReport;
 import org.apache.jackrabbit.webdav.lock.ActiveLock;
 import org.apache.jackrabbit.webdav.lock.LockDiscovery;
 import org.apache.jackrabbit.webdav.lock.LockInfo;
@@ -37,12 +41,6 @@
 import org.apache.jackrabbit.webdav.lock.Scope;
 import org.apache.jackrabbit.webdav.lock.SupportedLock;
 import org.apache.jackrabbit.webdav.lock.Type;
-import org.apache.jackrabbit.webdav.observation.EventDiscovery;
-import org.apache.jackrabbit.webdav.observation.ObservationResource;
-import org.apache.jackrabbit.webdav.observation.Subscription;
-import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery;
-import org.apache.jackrabbit.webdav.observation.SubscriptionInfo;
-import org.apache.jackrabbit.webdav.observation.SubscriptionManager;
 import org.apache.jackrabbit.webdav.property.DavProperty;
 import org.apache.jackrabbit.webdav.property.DavPropertyName;
 import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
@@ -74,7 +72,9 @@
 import javax.jcr.Item;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
-import java.io.IOException;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.Iterator;
@@ -84,21 +84,31 @@
  * <code>AbstractResource</code> provides functionality common to all
  * resources.
  */
-abstract class AbstractResource implements DavResource, ObservationResource,
-        TransactionResource, DeltaVResource, SearchResource {
+abstract class AbstractResource implements DavResource, TransactionResource,
+    DeltaVResource, SearchResource {
 
     private static Logger log = LoggerFactory.getLogger(AbstractResource.class);
 
+    private static final String COMPLIANCE_CLASSES =
+        DavCompliance.concatComplianceClasses(new String[] {
+        DavCompliance._1_,
+        DavCompliance._2_,
+        DavCompliance.VERSION_CONTROL,
+        DavCompliance.VERSION_HISTORY,
+        DavCompliance.CHECKOUT_IN_PLACE,
+        DavCompliance.LABEL,
+        DavCompliance.MERGE,
+        DavCompliance.UPDATE,
+        DavCompliance.WORKSPACE
+    });
+
     private final DavResourceLocator locator;
     private final JcrDavSession session;
     private final DavResourceFactory factory;
 
-    private SubscriptionManager subsMgr;
     private TxLockManagerImpl txMgr;
     private String transactionId;
 
-    private long modificationTime = IOUtil.UNDEFINED_TIME;
-
     protected boolean initedProps;
     protected DavPropertySet properties = new DavPropertySet();
     protected SupportedLock supportedLock = new SupportedLock();
@@ -121,6 +131,23 @@
     }
 
     /**
+     * Returns a string listing the compliance classes for this resource as it
+     * is required for the DAV response header. This includes DAV 1, 2 which
+     * is supported by all derived classes as well as a subset of the
+     * classes defined by DeltaV: version-control, version-history, checkout-in-place,
+     * label, merge, update and workspace.<br>
+     * Those compliance classes are added as required by RFC3253 since all
+     * all resources in the jcr-server support at least the reporting and some
+     * basic versioning functionality.
+     *
+     * @return string listing the compliance classes.
+     * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass()
+     */
+    public String getComplianceClass() {
+        return COMPLIANCE_CLASSES;
+    }
+
+    /**
      * @see org.apache.jackrabbit.webdav.DavResource#getLocator()
      */
     public DavResourceLocator getLocator() {
@@ -149,65 +176,6 @@
     }
 
     /**
-     * @see org.apache.jackrabbit.webdav.DavResource#getModificationTime()
-     */
-    public long getModificationTime() {
-        return modificationTime;
-    }
-
-    /**
-     * Set the modificationTime field and adds the {@link DavPropertyName#GETLASTMODIFIED}
-     * property to the set of properties.
-     *
-     * @param modificationTime
-     */
-    void setModificationTime(long modificationTime) {
-        if (modificationTime > IOUtil.UNDEFINED_TIME) {
-            this.modificationTime = modificationTime;
-            String lastModified = IOUtil.getLastModified(modificationTime);
-            properties.add(new DefaultDavProperty(DavPropertyName.GETLASTMODIFIED, lastModified));
-        }
-    }
-
-    /**
-     * Spools the properties of this resource to the context. Note that subclasses
-     * are in charge of spooling the data to the output stream provided by the
-     * context.
-     *
-     * @see DavResource#spool(OutputContext)
-     */
-    public void spool(OutputContext outputContext) throws IOException {
-        if (!initedProps) {
-            initProperties();
-        }
-        // export properties
-        outputContext.setModificationTime(getModificationTime());
-        DavProperty etag = getProperty(DavPropertyName.GETETAG);
-        if (etag != null) {
-            outputContext.setETag(String.valueOf(etag.getValue()));
-        }
-        DavProperty contentType = getProperty(DavPropertyName.GETCONTENTTYPE);
-        if (contentType != null) {
-            outputContext.setContentType(String.valueOf(contentType.getValue()));
-        }
-        DavProperty contentLength = getProperty(DavPropertyName.GETCONTENTLENGTH);
-        if (contentLength != null) {
-            try {
-                long length = Long.parseLong(contentLength.getValue() + "");
-                if (length > 0) {
-                    outputContext.setContentLength(length);
-                }
-            } catch (NumberFormatException e) {
-                log.error("Could not build content length from property value '" + contentLength.getValue() + "'");
-            }
-        }
-        DavProperty contentLanguage = getProperty(DavPropertyName.GETCONTENTLANGUAGE);
-        if (contentLanguage != null) {
-            outputContext.setContentLanguage(contentLanguage.getValue().toString());
-        }
-    }
-
-    /**
      * @see org.apache.jackrabbit.webdav.DavResource#getPropertyNames()
      */
     public DavPropertyName[] getPropertyNames() {
@@ -436,39 +404,6 @@
         return session;
     }
 
-    //--------------------------------------< ObservationResource interface >---
-    /**
-     * @see ObservationResource#init(SubscriptionManager)
-     */
-    public void init(SubscriptionManager subsMgr) {
-        this.subsMgr = subsMgr;
-    }
-
-    /**
-     * @see ObservationResource#subscribe(org.apache.jackrabbit.webdav.observation.SubscriptionInfo, String)
-     * @see SubscriptionManager#subscribe(org.apache.jackrabbit.webdav.observation.SubscriptionInfo, String, org.apache.jackrabbit.webdav.observation.ObservationResource)
-     */
-    public Subscription subscribe(SubscriptionInfo info, String subscriptionId)
-            throws DavException {
-        return subsMgr.subscribe(info, subscriptionId, this);
-    }
-
-    /**
-     * @see ObservationResource#unsubscribe(String)
-     * @see SubscriptionManager#unsubscribe(String, org.apache.jackrabbit.webdav.observation.ObservationResource)
-     */
-    public void unsubscribe(String subscriptionId) throws DavException {
-        subsMgr.unsubscribe(subscriptionId, this);
-    }
-
-    /**
-     * @see ObservationResource#poll(String)
-     * @see SubscriptionManager#poll(String, org.apache.jackrabbit.webdav.observation.ObservationResource)
-     */
-    public EventDiscovery poll(String subscriptionId) throws DavException {
-        return subsMgr.poll(subscriptionId, this);
-    }
-
     //--------------------------------------< TransactionResource interface >---
     /**
      * @see TransactionResource#init(TxLockManager, String)
@@ -623,6 +558,7 @@
     public MultiStatus search(SearchInfo sInfo) throws DavException {
         return new SearchResourceImpl(getLocator(), session).search(sInfo);
     }
+    
     //--------------------------------------------------------------------------
     /**
      * Fill the set of default properties
@@ -643,7 +579,9 @@
         // todo: add etag
 
         // default last modified
-        setModificationTime(new Date().getTime());
+        String lastModified = IOUtil.getLastModified(getModificationTime());
+        properties.add(new DefaultDavProperty(DavPropertyName.GETLASTMODIFIED, lastModified));
+
         // default creation time
         properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, DavConstants.creationDateFormat.format(new Date(0))));
 
@@ -654,10 +592,6 @@
         // an empty lockdiscovery will be returned in the response.
         properties.add(new LockDiscovery(getLocks()));
 
-        // observation resource
-        SubscriptionDiscovery subsDiscovery = subsMgr.getSubscriptionDiscovery(this);
-        properties.add(subsDiscovery);
-
         properties.add(new SupportedMethodSetProperty(getSupportedMethods().split(",\\s")));
 
 	// DeltaV properties
@@ -741,7 +675,23 @@
      *
      * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty
      */
-    abstract protected void initSupportedReports();
+    /**
+     * Define the set of reports supported by this resource.
+     *
+     * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty
+     * @see AbstractResource#initSupportedReports()
+     */
+    protected void initSupportedReports() {
+        if (exists()) {
+            supportedReports = new SupportedReportSetProperty(new ReportType[] {
+                ReportType.EXPAND_PROPERTY,
+                NodeTypesReport.NODETYPES_REPORT,
+                LocateByUuidReport.LOCATE_BY_UUID_REPORT,
+                RegisteredNamespacesReport.REGISTERED_NAMESPACES_REPORT,
+                RepositoryDescriptorsReport.REPOSITORY_DESCRIPTORS_REPORT
+            });
+        }
+    }
 
     /**
      * Retrieve the href of the workspace the current session belongs to.
@@ -749,4 +699,67 @@
      * @return href of the workspace
      */
     abstract protected String getWorkspaceHref();
+
+    //--------------------------------------------------------------------------
+    /**
+     * Register the specified event listener with the observation manager present
+     * the repository session.
+     *
+     * @param listener
+     * @param nodePath
+     * @throws javax.jcr.RepositoryException
+     */
+    void registerEventListener(EventListener listener, String nodePath) throws RepositoryException {
+        getRepositorySession().getWorkspace().getObservationManager().addEventListener(listener, EListener.ALL_EVENTS, nodePath, true, null, null, false);
+    }
+
+    /**
+     * Unregister the specified event listener with the observation manager present
+     * the repository session.
+     *
+     * @param listener
+     * @throws javax.jcr.RepositoryException
+     */
+    void unregisterEventListener(EventListener listener) throws RepositoryException {
+        getRepositorySession().getWorkspace().getObservationManager().removeEventListener(listener);
+    }
+
+    //------------------------------------------------------< inner classes >---
+    /**
+     * Simple EventListener that creates a new {@link org.apache.jackrabbit.webdav.MultiStatusResponse} object
+     * for each event and adds it to the specified {@link org.apache.jackrabbit.webdav.MultiStatus}.
+     */
+    class EListener implements EventListener {
+
+        private static final int ALL_EVENTS = Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED;
+
+        private final DavPropertyNameSet propNameSet;
+        private MultiStatus ms;
+
+        EListener(DavPropertyNameSet propNameSet, MultiStatus ms) {
+            this.propNameSet = propNameSet;
+            this.ms = ms;
+        }
+
+        /**
+         * @see EventListener#onEvent(javax.jcr.observation.EventIterator)
+         */
+        public void onEvent(EventIterator events) {
+            while (events.hasNext()) {
+                try {
+                    Event e = events.nextEvent();
+                    DavResourceLocator loc = getLocatorFromItemPath(e.getPath());
+                    DavResource res = createResourceFromLocator(loc);
+                    ms.addResponse(new MultiStatusResponse(res, propNameSet));
+
+                } catch (DavException e) {
+                    // should not occur
+                    log.error("Error while building MultiStatusResponse from Event: " + e.getMessage());
+                } catch (RepositoryException e) {
+                    // should not occur
+                    log.error("Error while building MultiStatusResponse from Event: " + e.getMessage());
+                }
+            }
+        }
+    }
 }

Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java?view=diff&rev=448257&r1=448256&r2=448257
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java Wed Sep 20 09:32:51 2006
@@ -16,312 +16,76 @@
  */
 package org.apache.jackrabbit.webdav.jcr;
 
-import org.apache.jackrabbit.util.Text;
-import org.apache.jackrabbit.webdav.DavLocatorFactory;
-import org.apache.jackrabbit.webdav.DavResourceLocator;
+import org.apache.jackrabbit.webdav.AbstractLocatorFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * <code>DavLocatorFactoryImpl</code>...
  */
-public class DavLocatorFactoryImpl implements DavLocatorFactory {
+public class DavLocatorFactoryImpl extends AbstractLocatorFactory {
 
     private static Logger log = LoggerFactory.getLogger(DavLocatorFactoryImpl.class);
 
-    private final String pathPrefix;
-
     /**
      * Create a new factory
      *
      * @param pathPrefix Prefix, that needs to be removed in order to retrieve
-     *                   the path of the repository item from a given <code>DavResourceLocator</code>.
+     * the repository path from a given href.
      */
     public DavLocatorFactoryImpl(String pathPrefix) {
-        this.pathPrefix = pathPrefix;
+        super(pathPrefix);
     }
 
+    //----------------------------------------------------------------------
     /**
-     * Create a new <code>DavResourceLocator</code>. Any leading
-     * path-prefix (as defined with the constructor) and trailing '/' with
-     * the request handle is removed. The first label of the remaining handle is
-     * treated as workspace name. The remaining part of the given request handle
-     * is said to be the resource handle ("/" if an empty string remains).
-     * If the request handle does neither provide workspace name nor resource
-     * handle both values are set to <code>null</code>; the path object then
-     * represents the root resource that has no corresponding item in the JCR
-     * repository.
      *
-     * @param prefix
-     * @param href
-     * @return a new <code>DavResourceLocator</code>
-     * @throws IllegalArgumentException if the request handle is <code>null</code>
+     * @param resourcePath
+     * @param wspPath
+     * @return
+     * @see AbstractLocatorFactory#getRepositoryPath(String, String)
      */
-    public DavResourceLocator createResourceLocator(String prefix, String href) {
-        if (href == null) {
-            throw new IllegalArgumentException("Request handle must not be null.");
-        }
-
-        StringBuffer b = new StringBuffer("");
-        if (prefix != null) {
-            b.append(prefix);
-            if (pathPrefix != null && !prefix.endsWith(pathPrefix)) {
-                b.append(pathPrefix);
-            }
-        }
-        String rlPrefix = b.toString();
-
-        // remove any prefix that may still be present with the given href
-        if (pathPrefix != null && href.startsWith(pathPrefix)) {
-            href = href.substring(pathPrefix.length());
-        } else if (!"".equals(rlPrefix) && href.startsWith(rlPrefix)) {
-            href = href.substring(rlPrefix.length());
-        }
-
-        // remove trailing "/" that is present with collections
-        if (href.endsWith("/")) {
-            href = href.substring(0, href.length() - 1);
+    protected String getRepositoryPath(String resourcePath, String wspPath) {
+        if (resourcePath == null) {
+            return null;
         }
-
-        String resourcePath;
-        String workspacePath;
-
-        // an empty requestHandle (after removal of the "/") signifies a request
-        // to the root that does not represent a repository item.
-        if ("".equals(href)) {
-            resourcePath = null;
-            workspacePath = null;
+        if (resourcePath.equals(wspPath)) {
+            // workspace
+            log.info("Resource path represents workspace path -> repository path is null.");
+            return null;
         } else {
-            // look for the first slash ignoring the leading one
-            int pos = href.indexOf('/', 1);
-            if (pos == -1) {
-                // request to a 'workspace' resource that in the same time
-                // represent the root node of the repository.
-                workspacePath = Text.unescape(href);
-                resourcePath = ItemResourceConstants.ROOT_ITEM_PATH;
+            // a repository item  -> remove wspPath + /jcr:root
+            String pfx = wspPath + ItemResourceConstants.ROOT_ITEM_RESOURCEPATH;
+            if (resourcePath.startsWith(pfx)) {
+                String repositoryPath = resourcePath.substring(pfx.length());
+                return (repositoryPath.length() == 0) ? ItemResourceConstants.ROOT_ITEM_PATH : repositoryPath;
             } else {
-                // separate the workspace name from the path of the repository
-                // item.
-                workspacePath = Text.unescape(href.substring(0, pos));
-                resourcePath = Text.unescape(href.substring(pos));
+                log.error("Unexpected format of resource path.");
+                throw new IllegalArgumentException("Unexpected format of resource path.");
             }
         }
-
-        return new DavResourceLocatorImpl(rlPrefix, workspacePath, resourcePath, this);
     }
 
     /**
-     * Create a new <code>DavResourceLocator</code> from the specified prefix,
-     * workspace path and resource path, whithout modifying the specified Strings.
      *
-     * @param prefix
-     * @param workspacePath
-     * @param resourcePath
-     * @return a new <code>DavResourceLocator</code>
-     * @see DavLocatorFactory#createResourceLocator(String, String, String)
-     */
-    public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) {
-        return createResourceLocator(prefix, workspacePath, resourcePath, true);
-    }
-
-    /**
-     *
-     * @param prefix
-     * @param workspacePath
-     * @param path
-     * @param isResourcePath
+     * @param repositoryPath
+     * @param wspPath
      * @return
-     * @see DavLocatorFactory#createResourceLocator(String, String, String, boolean)
+     * @see AbstractLocatorFactory#getResourcePath(String, String)
      */
-    public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) {
-        return new DavResourceLocatorImpl(prefix, workspacePath, path, this);
-    }
-
-    /**
-     * Private inner class <code>DavResourceLocatorImpl</code> implementing
-     * the <code>DavResourceLocator</code> interface.
-     */
-    private class DavResourceLocatorImpl implements DavResourceLocator {
-
-        private final String prefix;
-        private final String workspacePath;
-        private final String resourcePath;
-        private final DavLocatorFactory factory;
-
-        private final String href;
-
-        /**
-         * Create a new <code>DavResourceLocatorImpl</code>.
-         *
-         * @param prefix
-         * @param workspacePath
-         * @param resourcePath
-         */
-        DavResourceLocatorImpl(String prefix, String workspacePath, String resourcePath, DavLocatorFactory factory) {
-            this.prefix = prefix;
-            this.workspacePath = workspacePath;
-            this.resourcePath = resourcePath;
-            this.factory = factory;
-
-            StringBuffer buf = new StringBuffer(prefix);
-            if (workspacePath != null) {
-                buf.append(Text.escapePath(workspacePath));
-            }
-            if (resourcePath != null) {
-                buf.append(Text.escapePath(resourcePath));
-            }
-            int length = buf.length();
-            if (length > 0 && buf.charAt(length - 1) != '/') {
-                buf.append("/");
-            }
-            href = buf.toString();
-        }
-
-        /**
-         * Return the prefix used to build the href String. This includes the initial
-         * hrefPrefix as well a the path prefix.
-         *
-         * @return prefix String used to build the href.
-         */
-        public String getPrefix() {
-            return prefix;
-        }
-
-        /**
-         * Return the resource path of <code>null</code> if this locator object
-         * represents the '/' request handle. To a request handle specifying a
-         * workspace name only the '/' resource path is assigned, which represents
-         * the root node of the repository.
-         *
-         * @return resource path or <code>null</code>
-         * @see org.apache.jackrabbit.webdav.DavResourceLocator#getResourcePath()
-         */
-        public String getResourcePath() {
-            return resourcePath;
-        }
-
-        /**
-         * Return the workspace path or <code>null</code> if this locator object
-         * represents the '/' request handle.
-         *
-         * @return workspace path or <code>null</code>
-         * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspacePath()
-         */
-        public String getWorkspacePath() {
-            return workspacePath;
-        }
-
-        /**
-         * Return the workspace name or <code>null</code> if this locator object
-         * represents the '/' request handle.
-         *
-         * @return workspace name or <code>null</code>
-         * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspaceName()
-         */
-        public String getWorkspaceName() {
-            if (workspacePath != null) {
-                return workspacePath.substring(1);
+    protected String getResourcePath(String repositoryPath, String wspPath) {
+        if (wspPath != null) {
+            StringBuffer b = new StringBuffer(wspPath);
+            if (repositoryPath != null) {
+                b.append(ItemResourceConstants.ROOT_ITEM_RESOURCEPATH);
+                if (!ItemResourceConstants.ROOT_ITEM_PATH.equals(repositoryPath)) {
+                    b.append(repositoryPath);
+                }
             }
+            return b.toString();
+        } else {
+            log.info("Workspace path is 'null' -> 'null' resource path");
             return null;
-        }
-
-        /**
-         * Returns true if the specified locator object refers to a resource within
-         * the same workspace.
-         *
-         * @param locator
-         * @return true if the workspace name is equal to this workspace name.
-         * @see DavResourceLocator#isSameWorkspace(org.apache.jackrabbit.webdav.DavResourceLocator)
-         */
-        public boolean isSameWorkspace(DavResourceLocator locator) {
-            return (locator == null) ? false : isSameWorkspace(locator.getWorkspaceName());
-        }
-
-        /**
-         * Returns true if the specified string equals to this workspace name or
-         * if this workspace name is null.
-         *
-         * @param workspaceName
-         * @return true if the workspace name is equal to this workspace name.
-         * @see DavResourceLocator#isSameWorkspace(String)
-         */
-        public boolean isSameWorkspace(String workspaceName) {
-            if (getWorkspaceName() == null) {
-                return true;
-            } else {
-                return getWorkspaceName().equals(workspaceName);
-            }
-        }
-
-        /**
-         * Builds the 'href' from the prefix, the workspace name and the
-         * resource path present and assures a trailing '/' in case the href
-         * is used for collection. Note, that the resource path is
-         * {@link Text#escapePath(String) escaped}.
-         *
-         * @param isCollection
-         * @return href String representing the text of the href element
-         * @see org.apache.jackrabbit.webdav.DavConstants#XML_HREF
-         * @see DavResourceLocator#getHref(boolean)
-         */
-        public String getHref(boolean isCollection) {
-            return (isCollection) ? href : href.substring(0, href.length() - 1);
-        }
-
-        /**
-         * Returns true if the 'workspaceName' field is <code>null</code>.
-         *
-         * @return true if the 'workspaceName' field is <code>null</code>.
-         * @see org.apache.jackrabbit.webdav.DavResourceLocator#isRootLocation()
-         */
-        public boolean isRootLocation() {
-            return workspacePath == null;
-        }
-
-        /**
-         * Return the factory that created this locator.
-         *
-         * @return factory
-         * @see org.apache.jackrabbit.webdav.DavResourceLocator#getFactory()
-         */
-        public DavLocatorFactory getFactory() {
-            return factory;
-        }
-
-        /**
-         * Returns the same as {@link #getResourcePath()}. No encoding is performed
-         * at all.
-         * @see DavResourceLocator#getRepositoryPath()
-         */
-        public String getRepositoryPath() {
-            return getResourcePath();
-        }
-
-        /**
-         * Computes the hash code from the href, that is built from the prefix,
-         * the workspace name and the resource path all of them representing
-         * final instance fields.
-         *
-         * @return the hash code
-         */
-        public int hashCode() {
-            return href.hashCode();
-        }
-
-        /**
-         * Returns true, if the given object is a <code>DavResourceLocator</code>
-         * with the same hash code.
-         *
-         * @param obj the object to compare to
-         * @return <code>true</code> if the 2 objects are equal;
-         *         <code>false</code> otherwise
-         */
-        public boolean equals(Object obj) {
-            if (obj instanceof DavResourceLocator) {
-                DavResourceLocator other = (DavResourceLocator) obj;
-                return hashCode() == other.hashCode();
-            }
-            return false;
         }
     }
 }

Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java?view=diff&rev=448257&r1=448256&r2=448257
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java Wed Sep 20 09:32:51 2006
@@ -88,8 +88,13 @@
 
         DavResource resource;
         if (locator.isRootLocation()) {
+            // root
             resource = new RootCollection(locator, session, this);
+        } else if (locator.getResourcePath().equals(locator.getWorkspacePath())) {
+            // workspace resource
+            resource = new WorkspaceResourceImpl(locator, session, this);
         } else {
+            // resource corresponds to a repository item
             try {
                 resource = createResourceForItem(locator, session);
 
@@ -116,13 +121,17 @@
                     resource = new DefaultItemResource(locator, session, this, null);
                 }
             } catch (RepositoryException e) {
-                log.error("Failed to build resource from item '"+ locator.getResourcePath() + "'");
+                log.error("Failed to build resource from item '"+ locator.getRepositoryPath() + "'");
                 throw new JcrDavException(e);
             }
         }
 
-        ((TransactionResource)resource).init(txMgr, ((TransactionDavServletRequest)request).getTransactionId());
-        ((ObservationResource)resource).init(subsMgr);
+        if (request instanceof TransactionDavServletRequest && resource instanceof TransactionResource) {
+            ((TransactionResource)resource).init(txMgr, ((TransactionDavServletRequest)request).getTransactionId());
+        }
+        if (resource instanceof ObservationResource) {
+            ((ObservationResource)resource).init(subsMgr);
+        }
         return resource;
     }
 
@@ -139,14 +148,17 @@
     public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException {
         JcrDavSession.checkImplementation(session);
         JcrDavSession sessionImpl = (JcrDavSession)session;
+
         DavResource resource;
-        try {
-            resource = createResourceForItem(locator, sessionImpl);
-        } catch (RepositoryException e) {
-            log.info("Creating resource for non-existing repository item ...");
-            if (locator.isRootLocation()) {
-                resource =  new RootCollection(locator, sessionImpl, this);
-            } else {
+        if (locator.isRootLocation()) {
+            resource =  new RootCollection(locator, sessionImpl, this);
+        } else if (locator.getResourcePath().equals(locator.getWorkspacePath())) {
+            resource = new WorkspaceResourceImpl(locator, sessionImpl, this);
+        } else {
+            try {
+                resource = createResourceForItem(locator, sessionImpl);
+            } catch (RepositoryException e) {
+                log.debug("Creating resource for non-existing repository item: " + locator.getRepositoryPath());
                 // todo: is this correct?
                 resource = new VersionControlledItemCollection(locator, sessionImpl, this, null);
             }
@@ -154,7 +166,9 @@
 
         // todo: currently transactionId is set manually after creation > to be improved.
         resource.addLockManager(txMgr);
-        ((ObservationResource)resource).init(subsMgr);
+        if (resource instanceof ObservationResource) {
+            ((ObservationResource)resource).init(subsMgr);
+        }
         return resource;
     }
 
@@ -178,9 +192,7 @@
                 resource = new VersionItemCollection(locator, sessionImpl, this, item);
             } else if (item instanceof VersionHistory) {
                 resource = new VersionHistoryItemCollection(locator, sessionImpl, this, item);
-            } else if (ItemResourceConstants.ROOT_ITEM_PATH.equals(item.getPath())) {
-                resource =  new RootItemCollection(locator, sessionImpl, this, item);
-            }  else{
+            } else{
                 resource = new VersionControlledItemCollection(locator, sessionImpl, this, item);
             }
         } else {

Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java?view=diff&rev=448257&r1=448256&r2=448257
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java Wed Sep 20 09:32:51 2006
@@ -115,21 +115,46 @@
      * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass()
      */
     public String getComplianceClass() {
-        StringBuffer sb = new StringBuffer(super.getComplianceClass());
-        sb.append(", ").append(OrderingResource.COMPLIANCE_CLASS);
-        return sb.toString();
+        String cc = super.getComplianceClass();
+        if (isOrderable()) {
+            StringBuffer sb = new StringBuffer(cc);
+            sb.append(", ").append(OrderingResource.COMPLIANCE_CLASS);
+            return sb.toString();
+        } else {
+            return cc;
+        }
+    }
+
+    public long getModificationTime() {
+        // retrieve mod-time from jcr:lastmodified property if existing
+        if (exists()) {
+            try {
+                if (((Node)item).hasProperty(JcrConstants.JCR_LASTMODIFIED)) {
+                    return ((Node)item).getProperty(JcrConstants.JCR_LASTMODIFIED).getLong();
+                }
+            } catch (RepositoryException e) {
+                log.warn("Error while accessing jcr:lastModified property");
+            }
+        }
+        // fallback: return 'now'
+        return new Date().getTime();
     }
 
     /**
      * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods()
      */
     public String getSupportedMethods() {
-        StringBuffer sb = new StringBuffer(super.getSupportedMethods());
-        // Ordering
+        String ms = super.getSupportedMethods();
         if (isOrderable()) {
-           sb.append(", ").append(OrderingResource.METHODS);
+            StringBuffer sb = new StringBuffer(ms);
+            // Ordering
+            if (isOrderable()) {
+                sb.append(", ").append(OrderingResource.METHODS);
+            }
+            return sb.toString();
+        } else {
+            return ms;
         }
-        return sb.toString();
     }
 
     /**
@@ -803,14 +828,6 @@
             // resource is serialized as system-view (xml)
             properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTTYPE, "text/xml"));
             Node n = (Node)item;
-            // overwrite the default modificationtime if possible
-            try {
-                if (n.hasProperty(JcrConstants.JCR_LASTMODIFIED)) {
-                    setModificationTime(n.getProperty(JcrConstants.JCR_LASTMODIFIED).getLong());
-                }
-            } catch (RepositoryException e) {
-                log.warn("Error while accessing jcr:lastModified property");
-            }
             // overwrite the default creation date if possible
             try {
                 if (n.hasProperty(JcrConstants.JCR_CREATED)) {

Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java?view=diff&rev=448257&r1=448256&r2=448257
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java Wed Sep 20 09:32:51 2006
@@ -58,6 +58,7 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Date;
 
 /**
  * <code>DefaultItemResource</code> represents JCR property item.
@@ -91,6 +92,16 @@
     }
 
     /**
+     * Always returns 'now'
+     *
+     * @return
+     * @see DavResource#getModificationTime() 
+     */
+    public long getModificationTime() {
+        return new Date().getTime();
+    }
+
+    /**
      * In case an underlying repository {@link Property property} exists the following
      * logic is applyed to spool the property content:
      * <ul>
@@ -297,7 +308,7 @@
                     contentType = "text/xml";
                 }
                 properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTTYPE, contentType));
-                
+
 
                 // add jcr-specific resource properties
                 properties.add(new DefaultDavProperty(JCR_TYPE, PropertyType.nameFromValue(type)));

Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.java?view=diff&rev=448257&r1=448256&r2=448257
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.java Wed Sep 20 09:32:51 2006
@@ -32,12 +32,7 @@
  * representing repository items.
  */
 public interface ItemResourceConstants {
-
-    /**
-     * Complience classes common to all item resources.
-     */
-    public static final String COMPLIANCE_CLASS = DavResource.COMPLIANCE_CLASS + ", " +ObservationResource.COMPLIANCE_CLASS + ", " + DeltaVResource.COMPLIANCE_CLASS;
-
+    
     /**
      * Methods common to all item resources.
      */
@@ -47,6 +42,10 @@
      * The resource path of the root-item-resource.
      */
     public static final String ROOT_ITEM_PATH = "/";
+    /**
+     * Placeholder resource path for the JCR root node.
+     */
+    public static final String ROOT_ITEM_RESOURCEPATH = "/jcr:root";
 
     /**
      * The version storage item resource path.

Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java?view=diff&rev=448257&r1=448256&r2=448257
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java Wed Sep 20 09:32:51 2006
@@ -23,28 +23,26 @@
 import org.apache.jackrabbit.webdav.DavResourceIteratorImpl;
 import org.apache.jackrabbit.webdav.DavResourceLocator;
 import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.search.SearchResource;
 import org.apache.jackrabbit.webdav.io.InputContext;
-import org.apache.jackrabbit.webdav.jcr.version.report.NodeTypesReport;
-import org.apache.jackrabbit.webdav.jcr.version.report.RegisteredNamespacesReport;
-import org.apache.jackrabbit.webdav.jcr.version.report.RepositoryDescriptorsReport;
-import org.apache.jackrabbit.webdav.version.report.ReportType;
-import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty;
+import org.apache.jackrabbit.webdav.io.OutputContext;
+import org.apache.jackrabbit.webdav.version.DeltaVResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.jcr.RepositoryException;
-import javax.jcr.Session;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
+import java.util.Date;
+import java.io.IOException;
 
 /**
  * <code>RootCollection</code> represent the WebDAV root resource that does not
  * represent any repository item. A call to getMembers() returns a
- * <code>DavResourceIterator</code> containing only <code>RootItemCollection</code>
- * resources, thus revealing the names of the accessable workspaces.
+ * <code>DavResourceIterator</code> containing only workspace resources
+ * resources, thus revealing the names of the accessable JCR workspaces.
  */
-public class RootCollection extends AbstractResource implements DavResource {
+public class RootCollection extends AbstractResource {
 
     private static Logger log = LoggerFactory.getLogger(RootCollection.class);
 
@@ -57,7 +55,6 @@
     protected RootCollection(DavResourceLocator locator, JcrDavSession session,
                              DavResourceFactory factory) {
         super(locator, session, factory);
-        setModificationTime(new Date().getTime());
 
         // initialize the supported locks and reports
         initLockSupport();
@@ -65,17 +62,6 @@
     }
 
     /**
-     * Returns a string listing the complieance classes for this resource as it
-     * is required for the DAV response header.
-     *
-     * @return string listing the compliance classes.
-     * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass()
-     */
-    public String getComplianceClass() {
-        return DavResource.COMPLIANCE_CLASS;
-    }
-
-    /**
      * Returns a string listing the METHODS for this resource as it
      * is required for the "Allow" response header.
      *
@@ -84,6 +70,8 @@
      */
     public String getSupportedMethods() {
         StringBuffer sb = new StringBuffer(DavResource.METHODS);
+        sb.append(DeltaVResource.METHODS_INCL_MKWORKSPACE);
+        sb.append(SearchResource.METHODS);
         return sb.toString();
     }
 
@@ -118,6 +106,26 @@
     }
 
     /**
+     * Always returns 'now'
+     *
+     * @return
+     */
+    public long getModificationTime() {
+        return new Date().getTime();
+    }
+
+    /**
+     * Sets content lengths to '0' and retrieves the modification time.
+     *
+     * @param outputContext
+     * @throws IOException
+     */
+    public void spool(OutputContext outputContext) throws IOException {
+        outputContext.setContentLength(0);
+        outputContext.setModificationTime(getModificationTime());
+    }
+
+    /**
      * Always returns <code>null</code>
      *
      * @return <code>null</code> for the root resource is not internal member
@@ -138,8 +146,7 @@
 
     /**
      * Returns an iterator over the member resources, which are all
-     * <code>RootItemCollection</code> resources, revealing
-     * the names of all available workspaces.
+     * workspace resources available.
      *
      * @return members of this collection
      * @see org.apache.jackrabbit.webdav.DavResource#getMembers()
@@ -149,7 +156,8 @@
         try {
             String[] wsNames = getRepositorySession().getWorkspace().getAccessibleWorkspaceNames();
             for (int i = 0; i < wsNames.length; i++) {
-                DavResourceLocator childLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), "/"+wsNames[i], ItemResourceConstants.ROOT_ITEM_PATH);
+                String wspPath = "/"+wsNames[i];
+                DavResourceLocator childLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), wspPath, wspPath);
                 memberList.add(createResourceFromLocator(childLoc));
             }
         } catch (RepositoryException e) {
@@ -178,32 +186,14 @@
     }
 
     /**
-     * @see AbstractResource#initSupportedReports()
-     */
-    protected void initSupportedReports() {
-        supportedReports = new SupportedReportSetProperty(new ReportType[] {
-            ReportType.EXPAND_PROPERTY,
-            NodeTypesReport.NODETYPES_REPORT,
-            RegisteredNamespacesReport.REGISTERED_NAMESPACES_REPORT,
-            RepositoryDescriptorsReport.REPOSITORY_DESCRIPTORS_REPORT
-        });
-    }
-
-    /**
      * Since the root resource does not represent a repository item and therefore
-     * is not member of a workspace resource, the workspace href is calculated
-     * from the workspace name retrieved from the underlying repository session.
+     * is not member of a workspace resource, this method always returns
+     * <code>null</code>.
      *
-     * @return workspace href build from workspace name.
+     * @return <code>null</code>
      * @see AbstractResource#getWorkspaceHref()
      */
     protected String getWorkspaceHref() {
-        Session session = getRepositorySession();
-        if (session != null) {
-            String workspaceName = session.getWorkspace().getName();
-            DavResourceLocator loc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), "/"+workspaceName, ItemResourceConstants.ROOT_ITEM_PATH);
-            return loc.getHref(true);
-        }
         return null;
     }
 }

Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java?view=diff&rev=448257&r1=448256&r2=448257
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java Wed Sep 20 09:32:51 2006
@@ -26,7 +26,6 @@
 import org.apache.jackrabbit.webdav.MultiStatus;
 import org.apache.jackrabbit.webdav.MultiStatusResponse;
 import org.apache.jackrabbit.webdav.property.DavPropertyName;
-import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
 import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
 import org.apache.jackrabbit.webdav.property.HrefProperty;
 import org.apache.jackrabbit.webdav.property.DavProperty;
@@ -51,9 +50,6 @@
 import javax.jcr.Session;
 import javax.jcr.Value;
 import javax.jcr.ValueFormatException;
-import javax.jcr.Workspace;
-import javax.jcr.observation.Event;
-import javax.jcr.observation.EventIterator;
 import javax.jcr.observation.EventListener;
 import javax.jcr.version.Version;
 import javax.jcr.version.VersionHistory;
@@ -231,7 +227,7 @@
         }
     }
 
-    //--------------------------------< VersionControlledResource interface >---
+    //--------------------------------------< VersionableResource interface >---
     /**
      * Adds version control to this resource. If the resource is already under
      * version control, this method has no effect.
@@ -254,6 +250,7 @@
         } // else: is already version controlled -> ignore
     }
 
+    //--------------------------------< VersionControlledResource interface >---
     /**
      * Calls {@link javax.jcr.Node#checkin()} on the underlying repository node.
      *
@@ -316,7 +313,6 @@
      * <li>{@link Node#restore(javax.jcr.version.Version, boolean)}</li>
      * <li>{@link Node#restore(javax.jcr.version.Version, String, boolean)}</li>
      * <li>{@link Node#restoreByLabel(String, boolean)}</li>
-     * <li>{@link Workspace#restore(javax.jcr.version.Version[], boolean)}</li>
      * <li>{@link Node#update(String)}</li>
      * </ul>
      * </p>
@@ -349,35 +345,30 @@
 
             // perform the update/restore according to the update info
             if (updateInfo.getVersionHref() != null) {
-                VersionHistory vh = node.getVersionHistory();
                 String[] hrefs = updateInfo.getVersionHref();
-                Version[] versions = new Version[hrefs.length];
-                for (int  i = 0; i < hrefs.length; i++) {
-                    String itemPath = getLocatorFromHref(hrefs[i]).getRepositoryPath();
-                    versions[i] = vh.getVersion(getItemName(itemPath));
+                if (hrefs.length != 1) {
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body missing version href or containing multiple version hrefs.");
                 }
-                if (versions.length == 1) {
-                    String relPath = DomUtil.getChildText(udElem, XML_RELPATH, NAMESPACE);
-                    if (relPath == null) {
-                        node.restore(versions[0], removeExisting);
-                    } else {
-                        node.restore(versions[0], relPath, removeExisting);
-                    }
+
+                String versionPath = getLocatorFromHref(hrefs[0]).getRepositoryPath();
+                String versionName = getItemName(versionPath);
+
+                String relPath = DomUtil.getChildText(udElem, XML_RELPATH, NAMESPACE);
+                if (relPath == null) {
+                    // restore version by name
+                    node.restore(versionName, removeExisting);
                 } else {
-                    getRepositorySession().getWorkspace().restore(versions, removeExisting);
+                    Version v = node.getVersionHistory().getVersion(versionName);
+                    node.restore(v, relPath, removeExisting);
                 }
+
             } else if (updateInfo.getLabelName() != null) {
                 String[] labels = updateInfo.getLabelName();
-                if (labels.length == 1) {
-                    node.restoreByLabel(labels[0], removeExisting);
-                } else {
-                    Version[] vs = new Version[labels.length];
-                    VersionHistory vh = node.getVersionHistory();
-                    for (int  i = 0; i < labels.length; i++) {
-                        vs[i] = vh.getVersionByLabel(labels[i]);
-                    }
-                    getRepositorySession().getWorkspace().restore(vs, removeExisting);
+                if (labels.length != 1) {
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body: Multiple labels specified.");
                 }
+                node.restoreByLabel(labels[0], removeExisting);
+
             } else if (updateInfo.getWorkspaceHref() != null) {
                 String workspaceName = getLocatorFromHref(updateInfo.getWorkspaceHref()).getWorkspaceName();
                 node.update(workspaceName);
@@ -610,67 +601,5 @@
         DavLocatorFactory f = getLocator().getFactory();
         String prefix = getLocator().getPrefix();
         return f.createResourceLocator(prefix, href);
-    }
-
-    /**
-     * Register the specified event listener with the observation manager present
-     * the repository session.
-     *
-     * @param listener
-     * @param nodePath
-     * @throws javax.jcr.RepositoryException
-     */
-    private void registerEventListener(EventListener listener, String nodePath) throws RepositoryException {
-        getRepositorySession().getWorkspace().getObservationManager().addEventListener(listener, EListener.ALL_EVENTS, nodePath, true, null, null, false);
-    }
-
-    /**
-     * Unregister the specified event listener with the observation manager present
-     * the repository session.
-     *
-     * @param listener
-     * @throws javax.jcr.RepositoryException
-     */
-    private void unregisterEventListener(EventListener listener) throws RepositoryException {
-        getRepositorySession().getWorkspace().getObservationManager().removeEventListener(listener);
-    }
-
-    //------------------------------------------------------< inner classes >---
-    /**
-     * Simple EventListener that creates a new {@link org.apache.jackrabbit.webdav.MultiStatusResponse} object
-     * for each event and adds it to the specified {@link org.apache.jackrabbit.webdav.MultiStatus}.
-     */
-    private class EListener implements EventListener {
-
-        private static final int ALL_EVENTS = Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED;
-
-        private final DavPropertyNameSet propNameSet;
-        private MultiStatus ms;
-
-        private EListener(DavPropertyNameSet propNameSet, MultiStatus ms) {
-            this.propNameSet = propNameSet;
-            this.ms = ms;
-        }
-
-        /**
-         * @see EventListener#onEvent(javax.jcr.observation.EventIterator)
-         */
-        public void onEvent(EventIterator events) {
-            while (events.hasNext()) {
-                try {
-                    Event e = events.nextEvent();
-                    DavResourceLocator loc = getLocatorFromItemPath(e.getPath());
-                    DavResource res = createResourceFromLocator(loc);
-                    ms.addResponse(new MultiStatusResponse(res, propNameSet));
-
-                } catch (DavException e) {
-                    // should not occur
-                    log.error("Error while building MultiStatusResponse from Event: " + e.getMessage());
-                } catch (RepositoryException e) {
-                    // should not occur
-                    log.error("Error while building MultiStatusResponse from Event: " + e.getMessage());
-                }
-            }
-        }
     }
 }

Added: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java?view=auto&rev=448257
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java (added)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java Wed Sep 20 09:32:51 2006
@@ -0,0 +1,408 @@
+/*
+ * 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.webdav.jcr;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.webdav.version.WorkspaceResource;
+import org.apache.jackrabbit.webdav.version.DeltaVResource;
+import org.apache.jackrabbit.webdav.version.UpdateInfo;
+import org.apache.jackrabbit.webdav.version.VersionControlledResource;
+import org.apache.jackrabbit.webdav.version.MergeInfo;
+import org.apache.jackrabbit.webdav.version.LabelInfo;
+import org.apache.jackrabbit.webdav.version.VersionHistoryResource;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResourceIterator;
+import org.apache.jackrabbit.webdav.DavResourceLocator;
+import org.apache.jackrabbit.webdav.MultiStatusResponse;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavResourceIteratorImpl;
+import org.apache.jackrabbit.webdav.DavResourceFactory;
+import org.apache.jackrabbit.webdav.MultiStatus;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.search.SearchResource;
+import org.apache.jackrabbit.webdav.jcr.property.NamespacesProperty;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.io.InputContext;
+import org.apache.jackrabbit.webdav.io.OutputContext;
+import org.w3c.dom.Element;
+
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.RepositoryException;
+import javax.jcr.Workspace;
+import javax.jcr.Item;
+import javax.jcr.Session;
+import javax.jcr.version.Version;
+import javax.jcr.observation.EventListener;
+import java.util.Properties;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Date;
+import java.io.IOException;
+
+/**
+ * <code>WorkspaceResourceImpl</code>...
+ */
+public class WorkspaceResourceImpl extends AbstractResource
+    implements WorkspaceResource, VersionControlledResource {
+
+    private static Logger log = LoggerFactory.getLogger(WorkspaceResourceImpl.class);
+
+    /**
+     * Create a new <code>WorkspaceResourceImpl</code>
+     *
+     * @param locator
+     * @param session
+     */
+    WorkspaceResourceImpl(DavResourceLocator locator, JcrDavSession session, DavResourceFactory factory) {
+        super(locator, session, factory);
+
+        // initialize the supported locks and reports
+        initLockSupport();
+        initSupportedReports();
+    }
+
+    //--------------------------------------------------------< DavResource >---
+
+    public String getSupportedMethods() {
+        StringBuffer sb = new StringBuffer(DavResource.METHODS);
+        sb.append(DeltaVResource.METHODS_INCL_MKWORKSPACE);
+        sb.append(SearchResource.METHODS);
+        // from vc-resource methods only UPDATE is supported
+        sb.append(DavMethods.METHOD_UPDATE);
+        return sb.toString();
+    }
+
+    /**
+     * @return true
+     */
+    public boolean exists() {
+        return true;
+    }
+
+    /**
+     * @return true
+     */
+    public boolean isCollection() {
+        return true;
+    }
+
+    /**
+     * Returns the name of the workspace.
+     *
+     * @return The workspace name
+     * @see org.apache.jackrabbit.webdav.DavResource#getDisplayName()
+     * @see javax.jcr.Workspace#getName()
+     */
+    public String getDisplayName() {
+        return getLocator().getWorkspaceName();
+    }
+
+    /**
+     * Always returns 'now'
+     *
+     * @return
+     */
+    public long getModificationTime() {
+        return new Date().getTime();
+    }
+
+    /**
+     * Sets content lengths to '0' and retrieves the modification time.
+     *
+     * @param outputContext
+     * @throws IOException
+     */
+    public void spool(OutputContext outputContext) throws IOException {
+        outputContext.setContentLength(0);
+        outputContext.setModificationTime(getModificationTime());
+    }
+
+    /**
+     * Retrieve the collection that has all workspace collections
+     * as internal members.
+     *
+     * @see org.apache.jackrabbit.webdav.DavResource#getCollection()
+     */
+    public DavResource getCollection() {
+        DavResource collection = null;
+        // create location with 'null' values for workspace-path and resource-path
+        DavResourceLocator parentLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), null, null);
+        try {
+            collection = createResourceFromLocator(parentLoc);
+        } catch (DavException e) {
+            log.error("Unexpected error while retrieving collection: " + e.getMessage());
+        }
+        return collection;
+    }
+
+    /**
+     * Throws 403 exception (Forbidden)
+     *
+     * @param resource
+     * @param inputContext
+     * @throws DavException
+     */
+    public void addMember(DavResource resource, InputContext inputContext) throws DavException {
+        log.error("Cannot add a new member to the workspace resource.");
+        throw new DavException(DavServletResponse.SC_FORBIDDEN);
+    }
+
+    /**
+     * Returns the resource representing the JCR root node.
+     *
+     * @return
+     */
+    public DavResourceIterator getMembers() {
+        List l = new ArrayList();
+        try {
+            DavResourceLocator loc = getLocatorFromItem(getRepositorySession().getRootNode());
+            l.add(createResourceFromLocator(loc));
+        } catch (DavException e) {
+            log.error("Internal error while building resource for the root node.", e);
+        } catch (RepositoryException e) {
+            log.error("Internal error while building resource for the root node.", e);
+        }
+        return new DavResourceIteratorImpl(l);
+    }
+
+    /**
+     * Throws 403 exception (Forbidden)
+     *
+     * @param member
+     * @throws DavException
+     */
+    public void removeMember(DavResource member) throws DavException {
+        log.error("Cannot add a remove the root node.");
+        throw new DavException(DavServletResponse.SC_FORBIDDEN);
+    }
+
+    /**
+     * Allows to alter the registered namespaces ({@link ItemResourceConstants#JCR_NAMESPACES}) and
+     * forwards any other property to the super class.<p/>
+     * Note that again no property status is set. Any failure while setting
+     * a property results in an exception (violating RFC 2518).
+     *
+     * @param property
+     * @throws DavException
+     * @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty)
+     */
+    public void setProperty(DavProperty property) throws DavException {
+        if (ItemResourceConstants.JCR_NAMESPACES.equals(property.getName())) {
+            NamespacesProperty nsp = new NamespacesProperty(property);
+            try {
+                Properties changes = nsp.getNamespaces();
+                NamespaceRegistry nsReg = getRepositorySession().getWorkspace().getNamespaceRegistry();
+                String[] registeredPrefixes = nsReg.getPrefixes();
+                for (int i = 0; i < registeredPrefixes.length; i++) {
+                    String prfx = registeredPrefixes[i];
+                    if (!changes.containsKey(prfx)) {
+                        // prefix not present amongst the new values any more > unregister
+                        nsReg.unregisterNamespace(prfx);
+                    } else if (changes.get(prfx).equals(nsReg.getURI(prfx))) {
+                        // present with same uri-value >> no action required
+                        changes.remove(prfx);
+                    }
+                }
+
+                // try to register any prefix/uri pair that has a changed uri or
+                // it has not been present before.
+                Iterator prefixIt = changes.keySet().iterator();
+                while (prefixIt.hasNext()) {
+                    String prefix = (String)prefixIt.next();
+                    String uri = (String)changes.get(prefix);
+                    nsReg.registerNamespace(prefix, uri);
+                }
+            } catch (RepositoryException e) {
+                throw new JcrDavException(e);
+            }
+        } else {
+            // only jcr:namespace can be modified
+            throw new DavException(DavServletResponse.SC_CONFLICT);
+        }
+    }
+
+    /**
+     * Handles an attempt to set {@link ItemResourceConstants#JCR_NAMESPACES}
+     * and forwards any other set or remove requests to the super class.
+     *
+     * @see #setProperty(DavProperty)
+     * @see DefaultItemCollection#alterProperties(org.apache.jackrabbit.webdav.property.DavPropertySet, org.apache.jackrabbit.webdav.property.DavPropertyNameSet)
+     */
+    public MultiStatusResponse alterProperties(List changeList) throws DavException {
+        if (changeList.size() == 1) {
+           Object propEntry = changeList.get(0);
+            // only modification of prop is allowed. removal is not possible
+            if (propEntry instanceof DavProperty
+                && ItemResourceConstants.JCR_NAMESPACES.equals(((DavProperty)propEntry).getName())) {
+                DavProperty namespaceProp = (DavProperty) propEntry;
+                setProperty(namespaceProp);
+            } else {
+                // attempt to remove the namespace property
+                throw new DavException(DavServletResponse.SC_CONFLICT);
+            }
+        } else {
+            // changelist contains more than the jcr:namespaces property
+            // TODO: build multistatus instead
+            throw new DavException(DavServletResponse.SC_CONFLICT);
+        }
+        return new MultiStatusResponse(getHref(), DavServletResponse.SC_OK);
+    }
+
+    //------------------------------------------------< VersionableResource >---
+    /**
+     * @throws DavException (403) since workspace is not versionable. implementing
+     * <code>VersionControlledResource</code> only for 'update'.
+     */
+    public void addVersionControl() throws DavException {
+        throw new DavException(DavServletResponse.SC_FORBIDDEN);
+    }
+
+    //------------------------------------------< VersionControlledResource >---
+    /**
+     * @throws DavException (403) since workspace is not versionable. implementing
+     * <code>VersionControlledResource</code> only for 'update'.
+     */
+    public String checkin() throws DavException {
+        throw new DavException(DavServletResponse.SC_FORBIDDEN);
+    }
+
+    /**
+     * @throws DavException (403) since workspace is not versionable. implementing
+     * <code>VersionControlledResource</code> only for 'update'.
+     */
+    public void checkout() throws DavException {
+        throw new DavException(DavServletResponse.SC_FORBIDDEN);
+    }
+
+    /**
+     * @throws DavException (403) since workspace is not versionable. implementing
+     * <code>VersionControlledResource</code> only for 'update'.
+     */
+    public void uncheckout() throws DavException {
+        throw new DavException(DavServletResponse.SC_FORBIDDEN);
+    }
+
+    /**
+     * While RFC 3253 does not define any version-related operations for the
+     * workspace resource, this implementation uses {@link VersionControlledResource#update(UpdateInfo)}
+     * to map {@link Workspace#restore(javax.jcr.version.Version[], boolean)} to
+     * a WebDAV call.
+     * </p>
+     * Limitation: note that the <code>MultiStatus</code> returned by this method
+     * will not list any nodes that have been removed due to an Uuid conflict.
+     *
+     * @param updateInfo
+     * @return
+     * @throws org.apache.jackrabbit.webdav.DavException
+     * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#update(org.apache.jackrabbit.webdav.version.UpdateInfo)
+     */
+    public MultiStatus update(UpdateInfo updateInfo) throws DavException {
+        if (updateInfo == null) {
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid update request body required.");
+        }
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+
+        Session session = getRepositorySession();
+        MultiStatus ms = new MultiStatus();
+        try {
+            Element udElem = updateInfo.getUpdateElement();
+            boolean removeExisting = DomUtil.hasChildElement(udElem, ItemResourceConstants.XML_REMOVEEXISTING, ItemResourceConstants.NAMESPACE);
+
+            // register eventListener in order to be able to report the modified resources.
+            EventListener el = new EListener(updateInfo.getPropertyNameSet(), ms);
+            registerEventListener(el, session.getRootNode().getPath());
+
+            String[] hrefs = updateInfo.getVersionHref();
+            if (hrefs == null || hrefs.length < 1) {
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body: at least a single version href must be specified.");
+            }
+            // perform the update/restore according to the update info
+            Version[] versions = new Version[hrefs.length];
+            for (int i = 0; i < hrefs.length; i++) {
+                DavResourceLocator vLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), hrefs[i]);
+                String versionPath = vLoc.getRepositoryPath();
+                Item item = getRepositorySession().getItem(versionPath);
+                if (item instanceof Version) {
+                    versions[i] = (Version) item;
+                } else {
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body: href does not identify a version " + hrefs[i]);
+                }
+            }
+            session.getWorkspace().restore(versions, removeExisting);
+
+            // unregister the event listener again
+            unregisterEventListener(el);
+
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+        return ms;
+    }
+
+    /**
+     * @throws DavException (403) since workspace is not versionable. implementing
+     * <code>VersionControlledResource</code> only for 'update'.
+     */
+    public MultiStatus merge(MergeInfo mergeInfo) throws DavException {
+        throw new DavException(DavServletResponse.SC_FORBIDDEN);
+    }
+
+    /**
+     * @throws DavException (403) since workspace is not versionable. implementing
+     * <code>VersionControlledResource</code> only for 'update'.
+     */
+    public void label(LabelInfo labelInfo) throws DavException {
+        throw new DavException(DavServletResponse.SC_FORBIDDEN);
+    }
+
+    /**
+     * @throws DavException (403) since workspace is not versionable. implementing
+     * <code>VersionControlledResource</code> only for 'update'.
+     */
+    public VersionHistoryResource getVersionHistory() throws DavException {
+        throw new DavException(DavServletResponse.SC_FORBIDDEN);
+    }
+
+    //---------------------------------------------------< AbstractResource >---
+    protected void initLockSupport() {
+        // lock not allowed
+    }
+
+    protected String getWorkspaceHref() {
+        return getHref();
+    }
+
+    protected void initProperties() {
+        super.initProperties();
+        try {
+            // init workspace specific properties
+            NamespaceRegistry nsReg = getRepositorySession().getWorkspace().getNamespaceRegistry();
+            DavProperty namespacesProp = new NamespacesProperty(nsReg);
+            properties.add(namespacesProp);
+        } catch (RepositoryException e) {
+            log.error("Failed to access NamespaceRegistry: " + e.getMessage());
+        }
+
+        // TODO: required property DAV:workspace-checkout-set (computed)
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java?view=diff&rev=448257&r1=448256&r2=448257
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java (original)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java Wed Sep 20 09:32:51 2006
@@ -38,17 +38,26 @@
     }
 
     public DavResourceLocator createResourceLocator(String prefix, String href) {
-        String rPrefix = prefix + repositoryPrefix;
-        String escPath = href;
-        // remove the configured repository prefix from the path
-        if (escPath != null && escPath.startsWith(repositoryPrefix)) {
-            escPath = escPath.substring(repositoryPrefix.length());
+        // build prefix string and remove all prefixes from the given href.
+        StringBuffer b = new StringBuffer("");
+        if (prefix != null && prefix.length() > 0) {
+            b.append(prefix);
+            if (href.startsWith(prefix)) {
+                href = href.substring(prefix.length());
+            }
         }
+        if (repositoryPrefix != null && repositoryPrefix.length() > 0 && !prefix.endsWith(repositoryPrefix)) {
+            b.append(repositoryPrefix);
+            if (href.startsWith(repositoryPrefix)) {
+                href = href.substring(repositoryPrefix.length());
+            }
+        }
+
         // special treatment for root item, that has no name but '/' path.
-        if (escPath == null || "".equals(escPath)) {
-            escPath = "/";
+        if (href == null || "".equals(href)) {
+            href = "/";
         }
-        return new Locator(rPrefix, Text.unescape(escPath), this);
+        return new Locator(b.toString(), Text.unescape(href), this);
     }
 
     public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) {

Added: jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.java?view=auto&rev=448257
==============================================================================
--- jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.java (added)
+++ jackrabbit/trunk/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.java Wed Sep 20 09:32:51 2006
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ *
+ * Copyright 1997-2005 Day Management AG
+ * Barfuesserplatz 6, 4001 Basel, Switzerland
+ * All Rights Reserved.
+ *
+ * This software is the confidential and proprietary information of
+ * Day Management AG, ("Confidential Information"). You shall not
+ * disclose such Confidential Information and shall use it only in
+ * accordance with the terms of the license agreement you entered into
+ * with Day.
+ */
+package org.apache.jackrabbit.webdav.simple;
+
+import org.apache.jackrabbit.webdav.AbstractLocatorFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <code>LocatorFactoryImplEx</code>...
+ */
+public class LocatorFactoryImplEx extends AbstractLocatorFactory {
+
+    private static Logger log = LoggerFactory.getLogger(LocatorFactoryImplEx.class);
+
+    /**
+     * Create a new factory
+     *
+     * @param pathPrefix Prefix, that needs to be removed in order to retrieve
+     *                   the path of the repository item from a given <code>DavResourceLocator</code>.
+     */
+    public LocatorFactoryImplEx(String pathPrefix) {
+        super(pathPrefix);
+    }
+
+    /**
+     *
+     * @see AbstractLocatorFactory#getRepositoryPath(String, String)
+     */
+    protected String getRepositoryPath(String resourcePath, String wspPath) {
+        if (resourcePath == null) {
+            return resourcePath;
+        }
+
+        if (resourcePath.startsWith(wspPath)) {
+            String repositoryPath = resourcePath.substring(wspPath.length());
+            return (repositoryPath.length() == 0) ? "/" : repositoryPath;
+        } else {
+            throw new IllegalArgumentException("Unexpected format of resource path.");
+        }
+    }
+
+    /**
+     *
+     * @see AbstractLocatorFactory#getResourcePath(String, String)
+     */
+    protected String getResourcePath(String repositoryPath, String wspPath) {
+        if (repositoryPath == null) {
+            throw new IllegalArgumentException("Cannot build resource path from 'null' repository path");
+        }
+        return (wspPath == null || repositoryPath.startsWith(wspPath)) ? repositoryPath : wspPath + repositoryPath;
+    }
+}



Mime
View raw message