jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tri...@apache.org
Subject svn commit: r156314 [3/15] - in incubator/jackrabbit/trunk/contrib/jcr-server: ./ client/ client/src/ client/src/java/ client/src/java/org/ client/src/java/org/apache/ client/src/java/org/apache/jackrabbit/ client/src/java/org/apache/jackrabbit/client/ server/ server/src/ server/src/java/ server/src/java/org/ server/src/java/org/apache/ server/src/java/org/apache/jackrabbit/ server/src/java/org/apache/jackrabbit/server/ server/src/java/org/apache/jackrabbit/server/simple/ server/src/java/org/apache/jackrabbit/server/simple/dav/ server/src/java/org/apache/jackrabbit/server/simple/dav/lock/ server/src/java/org/apache/jackrabbit/webdav/ server/src/java/org/apache/jackrabbit/webdav/spi/ server/src/java/org/apache/jackrabbit/webdav/spi/lock/ server/src/java/org/apache/jackrabbit/webdav/spi/nodetype/ server/src/java/org/apache/jackrabbit/webdav/spi/observation/ server/src/java/org/apache/jackrabbit/webdav/spi/search/ server/src/java/org/apache/jackrabbit/webdav/spi/transaction/ server/src/java/org/apache/jackrabbit/webdav/spi/version/ server/src/java/org/apache/jackrabbit/webdav/spi/version/report/ webapp/ webapp/src/ webapp/src/webapp/ webapp/src/webapp/WEB-INF/ webapp/src/webapp/WEB-INF/repository/ webdav/ webdav/src/ webdav/src/java/ webdav/src/java/org/ webdav/src/java/org/apache/ webdav/src/java/org/apache/jackrabbit/ webdav/src/java/org/apache/jackrabbit/webdav/ webdav/src/java/org/apache/jackrabbit/webdav/lock/ webdav/src/java/org/apache/jackrabbit/webdav/observation/ webdav/src/java/org/apache/jackrabbit/webdav/ordering/ webdav/src/java/org/apache/jackrabbit/webdav/property/ webdav/src/java/org/apache/jackrabbit/webdav/search/ webdav/src/java/org/apache/jackrabbit/webdav/transaction/ webdav/src/java/org/apache/jackrabbit/webdav/util/ webdav/src/java/org/apache/jackrabbit/webdav/version/ webdav/src/java/org/apache/jackrabbit/webdav/version/report/
Date Sun, 06 Mar 2005 14:03:10 GMT
Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/DavResourceImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/DavResourceImpl.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/DavResourceImpl.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/DavResourceImpl.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,659 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.server.simple.dav;
+
+import javax.jcr.*;
+import java.util.*;
+import java.io.*;
+
+import org.apache.jackrabbit.webdav.*;
+import org.apache.jackrabbit.webdav.util.Text;
+import org.apache.jackrabbit.webdav.spi.lock.JcrActiveLock;
+import org.apache.jackrabbit.webdav.spi.JcrDavException;
+import org.apache.jackrabbit.webdav.lock.*;
+import org.apache.jackrabbit.webdav.property.*;
+
+/**
+ * DavResourceImpl imeplements a DavResource.
+ */
+public class DavResourceImpl implements DavResource {
+
+    private DavResourceFactory factory;
+    private LockManager lockManager;
+    private DavSession session;
+    private Node node;
+    private DavResourceLocator locator;
+
+    private DavPropertySet properties;
+    private boolean isCollection = true;
+
+    /** is created on initProperties */
+    private NodeResource nodeResource;
+
+    /**
+     * Create a new {@link DavResource}.
+     *
+     * @param locator
+     * @param factory
+     * @param session
+     */
+    public DavResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session) {
+        this.session = session;
+        this.factory = factory;
+        this.locator = locator;
+        if (locator != null && locator.getResourcePath() != null) {
+            try {
+                init(session.getRepositorySession().getItem(locator.getResourcePath()));
+            } catch (RepositoryException e) {
+                // ignore: exists field evaluates to false
+            }
+        }
+    }
+
+    /**
+     * Init the webdav resource and retrieve the relevant property.
+     *
+     * @param repositoryItem
+     * @throws RepositoryException
+     */
+    private void init(Item repositoryItem) throws RepositoryException {
+        if (repositoryItem == null || !repositoryItem.isNode()) {
+            return;
+        }
+        node = (Node)repositoryItem;
+
+        // define what is a resource in webdav
+        if (node.isNodeType("nt:resource") || node.isNodeType("nt:file")) {
+            isCollection = false;
+        }
+    }
+
+    /**
+     * @return DavResource#COMPLIANCE_CLASS
+     * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass()
+     */
+    public String getComplianceClass() {
+        return DavResource.COMPLIANCE_CLASS;
+    }
+
+    /**
+     * @return DavResource#METHODS
+     * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods()
+     */
+    public String getSupportedMethods() {
+        return DavResource.METHODS;
+    }
+
+    /**
+     * @see DavResource#exists() )
+     */
+    public boolean exists() {
+        return node != null;
+    }
+
+    /**
+     * @see DavResource#isCollection()
+     */
+    public boolean isCollection() {
+        return isCollection;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.DavResource#getLocator()
+     */
+    public DavResourceLocator getLocator() {
+        return locator;
+    }
+
+    /**
+     * @see DavResource#getResourcePath()
+     */
+    public String getResourcePath() {
+        return locator.getResourcePath();
+    }
+
+    /**
+     * @see DavResource#getHref()
+     */
+    public String getHref() {
+        return locator.getHref(isCollection());
+    }
+
+    /**
+     * @see DavResource#getDisplayName()
+     */
+    public String getDisplayName() {
+        String name = null;
+        if (exists()) {
+            try {
+                name = node.getName();
+            } catch (RepositoryException e) {
+                // ignore
+            }
+        }
+        if (name == null && getResourcePath() != null) {
+            name = Text.getLabel(getResourcePath());
+        }
+        return name;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.DavResource#getModificationTime()
+     */
+    public long getModificationTime() {
+	initProperties();
+	return nodeResource == null ? 0 : nodeResource.getModificationTime();
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.DavResource#getStream()
+     */
+    public InputStream getStream() {
+	initProperties();
+	return nodeResource == null ? null : nodeResource.getStream();
+    }
+
+    /**
+     * @see DavResource#getProperty(org.apache.jackrabbit.webdav.property.DavPropertyName)
+     */
+    public DavProperty getProperty(DavPropertyName name) {
+        initProperties();
+        return properties.get(name);
+    }
+
+    /**
+     * @see DavResource#getProperties()
+     */
+    public DavPropertySet getProperties() {
+        initProperties();
+        return properties;
+    }
+
+    /**
+     * @see DavResource#getPropertyNames()
+     */
+    public DavPropertyName[] getPropertyNames() {
+        return getProperties().getPropertyNames();
+    }
+
+    /**
+     * Fill the set of properties
+     */
+    private void initProperties() {
+        if (properties == null && exists()) {
+            properties = new DavPropertySet();
+            try {
+                nodeResource = new NodeResource(this, node);
+                properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTLENGTH, nodeResource.getContentLength()+""));
+                properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, nodeResource.getCreationDate()));
+                properties.add(new DefaultDavProperty(DavPropertyName.GETLASTMODIFIED, nodeResource.getLastModified()));
+                String contentType = nodeResource.getContentType();
+                if (contentType != null) {
+                    properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTTYPE, contentType));
+                }
+                properties.add(new DefaultDavProperty(DavPropertyName.GETETAG, nodeResource.getETag()));
+            } catch (RepositoryException e) {
+                // should not occure....
+            }
+
+            if (getDisplayName() != null) {
+                properties.add(new DefaultDavProperty(DavPropertyName.DISPLAYNAME, getDisplayName()));
+            }
+            if (isCollection()) {
+                properties.add(new ResourceType(ResourceType.COLLECTION));
+                // Windows XP support
+                properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "1"));
+            } else {
+                properties.add(new ResourceType(ResourceType.DEFAULT_RESOURCE));
+                // Windows XP support
+                properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "0"));
+            }
+
+            /* set current lock information. If no lock is set to this resource,
+            an empty lockdiscovery will be returned in the response. */
+            properties.add(new LockDiscovery(getLock(Type.WRITE, Scope.EXCLUSIVE)));
+
+            /* lock support information: all locks are lockable. */
+            SupportedLock supportedLock = new SupportedLock();
+            supportedLock.addEntry(Type.WRITE, Scope.EXCLUSIVE);
+            properties.add(supportedLock);
+        }
+    }
+
+    /**
+     * @param property
+     * @throws DavException
+     * @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty)
+     */
+    public void setProperty(DavProperty property) throws DavException {
+        if (isLocked(this)) {
+            throw new DavException(DavServletResponse.SC_LOCKED);
+        }
+        throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+    }
+
+    /**
+     * @param propertyName
+     * @throws DavException
+     * @see DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName)
+     */
+    public void removeProperty(DavPropertyName propertyName) throws DavException {
+        if (isLocked(this)) {
+            throw new DavException(DavServletResponse.SC_LOCKED);
+        }
+        throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+    }
+
+    /**
+     * @see DavResource#getCollection()
+     */
+    public DavResource getCollection() {
+        DavResource parent = null;
+        if (getResourcePath() != null && !getResourcePath().equals("/")) {
+            String parentPath = Text.getRelativeParent(getResourcePath(), 1);
+            if (parentPath.equals("")) {
+                parentPath="/";
+            }
+            DavResourceLocator parentloc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), parentPath);
+            try {
+                parent = factory.createResource(parentloc, session);
+            } catch (DavException e) {
+                // should not occur
+            }
+        }
+        return parent;
+    }
+
+    /**
+     * @see DavResource#getMembers()
+     */
+    public DavResourceIterator getMembers() {
+        ArrayList list = new ArrayList();
+        if (exists() && isCollection()) {
+            try {
+                NodeIterator it = node.getNodes();
+                while(it.hasNext()) {
+                    list.add(buildResourceFromItem(it.nextNode()));
+                }
+            } catch (RepositoryException e) {
+                // should not occure
+            } catch (DavException e) {
+                // should not occure
+            }
+        }
+        return new DavResourceIteratorImpl(list);
+    }
+
+    /**
+     * @see DavResource#addMember(DavResource, InputStream)
+     */
+    public void addMember(DavResource member, InputStream in) throws DavException {
+        if (!exists() || in == null) {
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+
+        try {
+            String fileName = member.getDisplayName();
+	    Node file;
+	    boolean makeVersionable = true; // todo: to be configurable somewhere
+	    if (node.hasNode(fileName)) {
+		file = node.getNode(fileName);
+		if (file.hasNode("jcr:content")) {
+		    // remove an existing repository entry for 'overwriting' is not possible
+		    file.getNode("jcr:content").remove();
+		}
+	    } else {
+		file = node.addNode(fileName, "nt:file");
+		if (makeVersionable) {
+		    file.addMixin("mix:versionable");
+		}
+	    }
+
+	    if (fileName.endsWith(".xml")) {
+		importXml(file, in, "text/xml");
+	    } else {
+		// todo: retrieve proper mimetype from filename
+		importFile(file, in, "application/octet-stream");
+	    }
+            session.getRepositorySession().save();
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        } catch (IOException e) {
+            throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+        }
+    }
+
+    /**
+     * Imports a xml into the repository
+     * @param parentNode
+     * @param in
+     * @param contentType
+     * @throws RepositoryException
+     * @throws IOException
+     */
+    private void importXml(Node parentNode, InputStream in, String contentType)
+	    throws RepositoryException, IOException {
+	Node content = parentNode.addNode("jcr:content", "nt:unstructured");
+	content.setProperty("jcr:mimeType", contentType);
+	content.setProperty("jcr:lastModified", Calendar.getInstance());
+	session.getRepositorySession().importXML(content.getPath(), in);
+    }
+
+    /**
+     * Imports a plain file to the repository
+     * @param parentNode
+     * @param in
+     * @param contentType
+     * @throws RepositoryException
+     */
+    private void importFile(Node parentNode, InputStream in, String contentType)
+	    throws RepositoryException {
+	Node content = parentNode.addNode("jcr:content", "nt:resource");
+	content.setProperty("jcr:mimeType", contentType);
+	content.setProperty("jcr:encoding", "");
+	content.setProperty("jcr:data", in);
+	content.setProperty("jcr:lastModified", Calendar.getInstance());
+    }
+
+    /**
+     * @see DavResource#addMember(DavResource)
+     */
+    public void addMember(DavResource member) throws DavException {
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_CONFLICT);
+        }
+        try {
+            node.addNode(member.getDisplayName(), "nt:folder");
+            node.save();
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
+    /**
+     * @see DavResource#removeMember(DavResource)
+     */
+    public void removeMember(DavResource member) throws DavException {
+        if (!exists() || !member.exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+        if (isLocked(this) || isLocked(member)) {
+            throw new DavException(DavServletResponse.SC_LOCKED);
+        }
+
+        try {
+            // make sure, non-jcr locks are removed.
+	    /*
+	     do not use jcr locks until implemented
+
+            if (!isJsrLockable()) {
+                ActiveLock lock = getLock(Type.WRITE, Scope.EXCLUSIVE);
+                if (lock != null) {
+                    lockManager.releaseLock(lock.getToken(), member);
+                }
+            }
+	    */
+	    ActiveLock lock = getLock(Type.WRITE, Scope.EXCLUSIVE);
+	    if (lock != null && lockManager.hasLock(lock.getToken(), member)) {
+		lockManager.releaseLock(lock.getToken(), member);
+	    }
+
+            Session s = session.getRepositorySession();
+            Item memItem = s.getItem(member.getResourcePath());
+            memItem.remove();
+            s.save();
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
+    /**
+     * @see DavResource#move(DavResource)
+     */
+    public void move(DavResource destination) throws DavException {
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+        if (isLocked(this)) {
+            throw new DavException(DavServletResponse.SC_LOCKED);
+        }
+        try {
+            session.getRepositorySession().getWorkspace().move(getResourcePath(), destination.getResourcePath());
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
+    /**
+     * @see DavResource#copy(DavResource, boolean)
+     */
+    public void copy(DavResource destination, boolean shallow) throws DavException {
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+        if (isLocked(destination)) {
+            throw new DavException(DavServletResponse.SC_LOCKED);
+        }
+        // TODO: support shallow and deep copy
+        if (shallow) {
+            throw new DavException(DavServletResponse.SC_FORBIDDEN, "Unable to perform shallow copy.");
+        }
+        try {
+            session.getRepositorySession().getWorkspace().copy(getResourcePath(), destination.getResourcePath());
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
+    /**
+     * @param type
+     * @param scope
+     * @return true if type is {@link Type#WRITE} and scope is {@link Scope#EXCLUSIVE}
+     * @see DavResource#isLockable(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope)
+     */
+    public boolean isLockable(Type type, Scope scope) {
+        return Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope);
+    }
+
+    /**
+     * @see DavResource#hasLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope)
+     */
+    public boolean hasLock(Type type, Scope scope) {
+        return getLock(type, scope) != null;
+    }
+
+    /**
+     * @see DavResource#getLock(Type, Scope)
+     */
+    public ActiveLock getLock(Type type, Scope scope) {
+        ActiveLock lock = null;
+        if (exists() && Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope)) {
+            // try to retrieve the repository lock information first
+	    /*
+	    do not use jcr locks until implemented
+
+            if (isJsrLockable()) {
+                try {
+                    Lock jcrLock = node.getLock();
+                    if (jcrLock != null && jcrLock.isLive()) {
+                        lock = new JcrActiveLock(jcrLock);
+                    }
+                } catch (RepositoryException e) {
+                    // LockException: no lock applies to this node >> ignore
+                    // RepositoryException, AccessDeniedException or another error >> ignore
+                }
+            } else {
+                // not-jcr lockable >> check for webdav lock
+                lock = lockManager.getLock(type, scope, this);
+            }
+	    */
+	    lock = lockManager.getLock(type, scope, this);
+        }
+        return lock;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.DavResource#getLocks()
+     */
+    public ActiveLock[] getLocks() {
+        return new ActiveLock[] {getLock(Type.WRITE, Scope.EXCLUSIVE)};
+    }
+
+    /**
+     * @see DavResource#lock(LockInfo)
+     */
+    public ActiveLock lock(LockInfo lockInfo) throws DavException {
+	ActiveLock lock = null;
+	if (isLockable(lockInfo.getType(), lockInfo.getScope())) {
+	    /*
+	    do not use jcr lock until implemented
+
+	    if (isJsrLockable()) {
+		try {
+		    // try to execute the lock operation
+		    Lock jcrLock = node.lock(lockInfo.isDeep(), false);
+		    if (jcrLock != null) {
+			lock = new JcrActiveLock(jcrLock);
+		    }
+		} catch (RepositoryException e) {
+		    throw new JcrDavException(e);
+		}
+	    } else {
+		// create a new lock which creates a random lock token
+		lock = lockManager.createLock(lockInfo, this);
+	    }
+	    */
+	    lock = lockManager.createLock(lockInfo, this);
+	}
+	return lock;
+    }
+
+    /**
+     * @see DavResource#refreshLock(LockInfo, String)
+     */
+    public ActiveLock refreshLock(LockInfo lockInfo, String lockToken) throws DavException{
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+
+        /* since lock is always has infinite timeout >> no extra refresh needed
+        return a lockdiscovery with the lock-info and the default scope and type */
+        ActiveLock lock = getLock(lockInfo.getType(), lockInfo.getScope());
+        if (lock == null) {
+           throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No lock present on resource " + getResourcePath());
+        } else if (lock.isLockedByToken(lockToken)) {
+            if (lock instanceof JcrActiveLock) {
+                try {
+                    // refresh JCR lock and return the original lock object.
+                    node.getLock().refresh();
+                } catch (RepositoryException e) {
+                    throw new JcrDavException(e);
+                }
+            } else {
+                lock = lockManager.refreshLock(lockInfo, lockToken, this);
+            }
+        } else {
+            throw new DavException(DavServletResponse.SC_LOCKED);
+        }
+        return lock;
+    }
+
+    /**
+     * @see DavResource#unlock(String)
+     */
+    public void unlock(String lockToken) throws DavException {
+        ActiveLock lock = getLock(Type.WRITE, Scope.EXCLUSIVE);
+        if (lock == null) {
+            throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED);
+        } else if (lock.isLockedByToken(lockToken)) {
+            if (lock instanceof JcrActiveLock) {
+                try {
+                    node.unlock();
+                } catch (RepositoryException e) {
+                    throw new JcrDavException(e);
+                }
+            } else {
+                lockManager.releaseLock(lockToken, this);
+            }
+        } else {
+            throw new DavException(DavServletResponse.SC_LOCKED);
+        }
+    }
+
+    /**
+     * @see DavResource#addLockManager(org.apache.jackrabbit.webdav.lock.LockManager)
+     */
+    public void addLockManager(LockManager lockMgr) {
+        this.lockManager = lockMgr;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.DavResource#getFactory()
+     */
+    public DavResourceFactory getFactory() {
+        return factory;
+    }
+
+    /**
+     * Returns true, if this webdav resource allows for locking without checking
+     * its current lock status.
+     *
+     * @return true if this resource is lockable.
+     */
+    private boolean isJsrLockable() {
+        boolean lockable = false;
+        if (exists()) {
+            try {
+                lockable =  node.isNodeType("mix:lockable");
+            } catch (RepositoryException e) {
+                // not jcr-lockable
+            }
+        }
+        return lockable;
+    }
+
+    /**
+     * Return true if this resource cannot be modified due to a write lock
+     * that is not owned by the given session.
+     *
+     * @return true if this resource cannot be modified due to a write lock
+     */
+    private boolean isLocked(DavResource res) {
+        ActiveLock lock = res.getLock(Type.WRITE, Scope.EXCLUSIVE);
+        if (lock == null) {
+            return false;
+        } else {
+            String[] sLockTokens = session.getLockTokens();
+            for (int i = 0; i < sLockTokens.length; i++) {
+                if (sLockTokens[i].equals(lock.getToken())) {
+                   return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    /**
+     * @param item
+     * @return
+     * @throws DavException
+     * @throws RepositoryException
+     */
+    private DavResource buildResourceFromItem(Item item) throws DavException, RepositoryException {
+        DavResourceLocator parentloc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), item.getPath());
+        return factory.createResource(parentloc, session);
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/DavResourceImpl.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/DavResourceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/LocatorFactoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/LocatorFactoryImpl.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/LocatorFactoryImpl.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/LocatorFactoryImpl.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jackrabbit.server.simple.dav;
+
+import org.apache.jackrabbit.webdav.*;
+
+/**
+ * ResourceFactoryImpl implements a simple DavLocatorFactory
+ */
+public class LocatorFactoryImpl implements DavLocatorFactory {
+
+    private final String repositoryPrefix;
+
+    public LocatorFactoryImpl(String repositoryPrefix) {
+        this.repositoryPrefix = repositoryPrefix;
+    }
+
+    public DavResourceLocator createResourceLocator(String prefix, String requestHandle) {
+        String rPrefix = prefix + repositoryPrefix;
+        String rHandle = requestHandle;
+        if (rHandle != null && rHandle.startsWith(repositoryPrefix)) {
+            rHandle = rHandle.substring(repositoryPrefix.length());
+        }
+        if (rHandle == null || "".equals(rHandle)) {
+            rHandle = "/";
+        }
+        return new Locator(rPrefix, rHandle, this);
+    }
+
+    public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) {
+        return new Locator(prefix, resourcePath, this);
+    }
+
+    private class Locator implements DavResourceLocator {
+
+        private final String prefix;
+        private final String itemPath;
+        private final DavLocatorFactory factory;
+
+        private Locator(String prefix, String itemPath, DavLocatorFactory factory) {
+            this.prefix = prefix;
+            this.factory = factory;
+            if (itemPath.endsWith("/") && !"/".equals(itemPath)) {
+                itemPath = itemPath.substring(0, itemPath.length()-1);
+            }
+            this.itemPath = itemPath;
+        }
+
+        public String getPrefix() {
+            return prefix;
+        }
+
+        public String getResourcePath() {
+            return itemPath;
+        }
+
+        public String getWorkspacePath() {
+            return "";
+        }
+
+        public String getWorkspaceName() {
+            return "";
+        }
+
+        public boolean isSameWorkspace(DavResourceLocator path) {
+            return isSameWorkspace(path.getWorkspaceName());
+        }
+
+        public boolean isSameWorkspace(String workspaceName) {
+            return getWorkspaceName().equals(workspaceName);
+        }
+
+        public String getHref(boolean isCollection) {
+            return prefix + itemPath + (isCollection ? "/" : "");
+        }
+
+        public boolean isRootLocation() {
+            return "/".equals(itemPath);
+        }
+
+        public DavLocatorFactory getFactory() {
+            return factory;
+        }
+
+        /**
+         * Computes the hash code using the prefix and the itemPath
+         *
+         * @return the hash code
+         */
+        public int hashCode() {
+            int hashCode = prefix.hashCode();
+            if (itemPath != null) {
+                hashCode += itemPath.hashCode();
+            }
+            return hashCode % Integer.MAX_VALUE;
+        }
+
+        /**
+         * Equality of path is achieved if the specified object is a <code>DavResourceLocator</code>
+         * and the return values of the two <code>getHref(boolean)</code> methods are
+         * equal.
+         *
+         * @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 path = (DavResourceLocator) obj;
+                this.getHref(true).equals(path.getHref(true));
+            }
+            return false;
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/LocatorFactoryImpl.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/LocatorFactoryImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/NodeResource.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/NodeResource.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/NodeResource.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/NodeResource.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.server.simple.dav;
+
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.webdav.util.Text;
+
+import javax.jcr.*;
+import java.util.Date;
+import java.util.Locale;
+import java.io.*;
+import java.text.SimpleDateFormat;
+
+/**
+ * The <code>NodeResource</code> class wraps a jcr item in order to respond
+ * to 'GET', 'HEAD', 'PROPFIND' or 'PROPPATCH' requests. If the item is a
+ * {@link javax.jcr.Node} its primary property is determined. The value of the
+ * primary property can be accessed by {@link #getStream()}. If possible other
+ * required information (last modification date, content type...) is retrieved
+ * from the property siblings.<br>
+ * If the requested item is a {@link javax.jcr.Property} it is treated accordingly.
+ */
+public class NodeResource {
+
+    /** the default logger */
+    private static final Logger log = Logger.getLogger(NodeResource.class);
+
+    /**
+     * modificationDate date format per RFC 1123
+     */
+    public static SimpleDateFormat modificationDateFormat =
+	new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
+
+    /**
+     * Simple date format for the creation date ISO representation (partial).
+     */
+    public static SimpleDateFormat creationDateFormat =
+	new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+
+    private static final String PROP_MIMETYPE = "jcr:mimeType";
+    private static final String PROP_ENCODING = "jcr:encoding";
+    private static final String PROP_LASTMODIFIED = "jcr:lastModified";
+    private static final String PROP_CREATED = "jcr:created";
+
+    private long creationTime = 0;
+    private long modificationTime = new Date().getTime();
+    private long contentLength = 0;
+    private String contentType = null;
+    private InputStream in = null;
+
+    /**
+     * Create a new <code>NodeResource</code> that wraps a JSR170 item.
+     *
+     * @throws ItemNotFoundException
+     * @throws RepositoryException
+     * @throws IllegalArgumentException if the given item is <code>null</code>
+     */
+    public NodeResource(DavResourceImpl davResource, Node node) throws ItemNotFoundException, RepositoryException {
+	try {
+	    if (davResource.isCollection()) {
+		createDirListingContent(node);
+	    } else {
+		if (node.hasProperty(PROP_CREATED)) {
+		    creationTime = node.getProperty(PROP_CREATED).getValue().getLong();
+		}
+		Node content = node.getPrimaryNodeType().getName().equals("nt:file")
+			? node.getNode("jcr:content")
+			: node;
+		if (content.getPrimaryNodeType().getName().equals("nt:resource")) {
+		    createPlainFileContent(content);
+		} else {
+		    createDocViewContent(content);
+		}
+	    }
+	} catch (IOException e) {
+	    // ignore
+	}
+    }
+
+    private void createPlainFileContent(Node content) throws IOException, RepositoryException {
+	if (content.hasProperty(PROP_LASTMODIFIED)) {
+	    modificationTime = content.getProperty(PROP_LASTMODIFIED).getLong();
+	}
+	if (content.hasProperty(PROP_MIMETYPE)) {
+	    contentType = content.getProperty(PROP_MIMETYPE).getString();
+	}
+	if (content.hasProperty(PROP_ENCODING)) {
+	    String encoding = content.getProperty(PROP_ENCODING).getString();
+	    if (!encoding.equals("")) {
+		contentType+="; charset=\"" + encoding + "\"";
+	    }
+	}
+	if (content.hasProperty("jcr:data")) {
+	    Property p = content.getProperty("jcr:data");
+	    contentLength = p.getLength();
+	    in = p.getStream();
+	} else {
+	    contentLength = 0;
+	}
+    }
+
+    private void createDocViewContent(Node node) throws IOException, RepositoryException {
+	File tmpfile = File.createTempFile("__webdav", ".xml");
+	FileOutputStream out = new FileOutputStream(tmpfile);
+	node.getSession().exportDocView(node.getPath(), out, true, false);
+	out.close();
+	in = new FileInputStream(tmpfile);
+	contentLength = tmpfile.length();
+	modificationTime = tmpfile.lastModified();
+	contentType = "text/xml";
+	tmpfile.deleteOnExit();
+    }
+
+    private void createSysViewContent(Node node) throws IOException, RepositoryException {
+	File tmpfile = File.createTempFile("__webdav", ".xml");
+	FileOutputStream out = new FileOutputStream(tmpfile);
+	node.getSession().exportSysView(node.getPath(), out, true, false);
+	out.close();
+	in = new FileInputStream(tmpfile);
+	contentLength = tmpfile.length();
+	modificationTime = tmpfile.lastModified();
+	contentType = "text/xml";
+	tmpfile.deleteOnExit();
+    }
+
+    private void createDirListingContent(Node node) throws IOException, RepositoryException {
+	File tmpfile = File.createTempFile("__webdav", ".xml");
+	FileOutputStream out = new FileOutputStream(tmpfile);
+
+	String repName = node.getSession().getRepository().getDescriptor(Repository.REP_NAME_DESC);
+	String repURL = node.getSession().getRepository().getDescriptor(Repository.REP_VENDOR_URL_DESC);
+	String repVersion = node.getSession().getRepository().getDescriptor(Repository.REP_VERSION_DESC);
+	PrintWriter writer = new PrintWriter(out);
+	writer.print("<html><head><title>");
+	writer.print(repName);
+	writer.print(" ");
+	writer.print(repVersion);
+	writer.print(" ");
+	writer.print(node.getPath());
+	writer.print("</title></head>");
+	writer.print("<body><h2>");
+	writer.print(node.getPath());
+	writer.print("</h2><ul>");
+	writer.print("<li><a href=\"..\">..</a></li>");
+	NodeIterator iter = node.getNodes();
+	while (iter.hasNext()) {
+	    Node child = iter.nextNode();
+	    String label = Text.getLabel(child.getPath());
+	    writer.print("<li><a href=\"");
+	    writer.print(Text.escape(label));
+	    if (!child.getPrimaryNodeType().getName().equals("nt:file")) {
+		writer.print("/");
+	    }
+	    writer.print("\">");
+	    writer.print(label);
+	    writer.print("</a></li>");
+	}
+	writer.print("</ul><hr size=\"1\"><em>Powered by <a href=\"");
+	writer.print(repURL);
+	writer.print("\">");
+	writer.print(repName);
+	writer.print("</a> version ");
+	writer.print(repVersion);
+	writer.print("</em></body></html>");
+
+	writer.close();
+	out.close();
+	in = new FileInputStream(tmpfile);
+	contentLength = tmpfile.length();
+	modificationTime = tmpfile.lastModified();
+	contentType = "text/html";
+	tmpfile.deleteOnExit();
+    }
+
+    /**
+     * Return the content length or '0'.
+     * @return content Length or '0' if it could not be determined.
+     */
+    public long getContentLength() {
+	return contentLength;
+    }
+
+    /**
+     * Return the creation time or '0'.
+     *
+     * @return creation time or '0' if it could not be determined.
+     */
+    public long getCreationTime() {
+	return creationTime;
+    }
+
+    /**
+     * Return the last modification time. By default it is set to the current
+     * time.
+     *
+     * @return time of last modification or the current time, if it could not
+     * be determined.
+     */
+    public long getModificationTime() {
+	return modificationTime;
+    }
+
+    /**
+     * Return the last modification time as formatted string.
+     *
+     * @return last modification time as string.
+     * @see NodeResource#modificationDateFormat
+     */
+    public String getLastModified() {
+	if (modificationTime >= 0) {
+	    return modificationDateFormat.format(new Date(modificationTime));
+	} else {
+	    return null;
+	}
+    }
+
+    /**
+     * Return the creation time as formatted string.
+     *
+     * @return creation time as string.
+     * @see NodeResource#creationDateFormat
+     */
+    public String getCreationDate() {
+	if (creationTime >= 0) {
+	    return creationDateFormat.format(new Date(creationTime));
+	} else {
+	    return null;
+	}
+    }
+
+    /**
+     * Return the weak ETag
+     *
+     * @return weak ETag
+     */
+    public String getETag() {
+	return "W/\"" + this.contentLength + "-" + this.modificationTime + "\"";
+    }
+
+    /**
+     * Return the strong ETag or empty string if it cannot be determined.
+     *
+     * @return strong ETag
+     */
+    public String getStrongETag() {
+	return "";
+    }
+
+    /**
+     * Return the content type or <code>null</code> if it could not be determined.
+     *
+     * @return content type
+     */
+    public String getContentType() {
+	return contentType;
+    }
+
+    /**
+     * Return a stream to the resource value.
+     *
+     * @return
+     */
+    public InputStream getStream() {
+	return in;
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/NodeResource.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/NodeResource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/ResourceFactoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/ResourceFactoryImpl.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/ResourceFactoryImpl.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/ResourceFactoryImpl.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jackrabbit.server.simple.dav;
+
+import org.apache.jackrabbit.webdav.*;
+import org.apache.jackrabbit.webdav.lock.LockManager;
+
+/**
+ * ResourceFactoryImpl implements a simple DavResourceFactory
+ */
+public class ResourceFactoryImpl implements DavResourceFactory {
+
+    private final LockManager lockMgr;
+
+    public ResourceFactoryImpl(LockManager lockMgr) {
+        this.lockMgr = lockMgr;
+    }
+
+    public DavResource createResource(DavResourceLocator locator, DavServletRequest request,
+                                      DavServletResponse response) throws DavException {
+        return createResource(locator, request.getDavSession());
+    }
+
+    public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException {
+        DavResource res = new DavResourceImpl(locator, this, session);
+        res.addLockManager(lockMgr);
+        return res;
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/ResourceFactoryImpl.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/ResourceFactoryImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/lock/SimpleLockManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/lock/SimpleLockManager.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/lock/SimpleLockManager.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/lock/SimpleLockManager.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.server.simple.dav.lock;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.apache.jackrabbit.webdav.lock.*;
+import org.apache.jackrabbit.webdav.*;
+import org.apache.jackrabbit.webdav.util.Text;
+
+/**
+ * Simple manager for webdav locks.<br>
+ * NOTE: the timeout requested is always replace by a infinite timeout and
+ * expiration of locks is not checked.
+ */
+public class SimpleLockManager implements LockManager {
+
+    /** map of locks */
+    private HashMap locks = new HashMap();
+
+    /**
+     *
+     * @param lockToken
+     * @param resource
+     * @return
+     * @see LockManager#hasLock(String, org.apache.jackrabbit.webdav.DavResource)
+     */
+    public boolean hasLock(String lockToken, DavResource resource) {
+	ActiveLock lock = (ActiveLock) locks.get(resource.getResourcePath());
+	if (lock != null && lock.getToken().equals(lockToken)) {
+	    return true;
+	}
+	return false;
+    }
+
+    /**
+     * Returns the lock applying to the given resource or <code>null</code> if
+     * no lock can be found.
+     *
+     * @param type
+     * @param scope
+     * @param resource
+     * @return lock that applies to the given resource or <code>null</code>.
+     */
+    public ActiveLock getLock(Type type, Scope scope, DavResource resource) {
+	if (!(Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope))) {
+	    return null;
+	}
+	String key = resource.getResourcePath();
+	ActiveLock lock = (locks.containsKey(key)) ? (ActiveLock)locks.get(key) : null;
+
+	// look for an inherited lock
+	if (lock == null) {
+	    // cut path instead of retrieving the parent resource
+	    String parentPath = Text.getRelativeParent(key, 1);
+	    boolean found = false;
+	    /* stop as soon as parent lock is found:
+	    if the lock is deep or the parent is a collection the lock
+	    applies to the given resource. */
+	    while (!"/".equals(parentPath) && !(found = locks.containsKey(parentPath))) {
+		parentPath = Text.getRelativeParent(parentPath, 1);
+	    }
+	    if (found) {
+		ActiveLock parentLock = (ActiveLock)locks.get(parentPath);
+		if (parentLock.isDeep()) {
+		    lock = parentLock;
+		}
+	    }
+	}
+	// since locks have infinite timeout, check for expired lock is omitted.
+	return lock;
+    }
+
+    /**
+     * Adds the lock for the given resource, replacing any existing lock.
+     *
+     * @param lockInfo
+     * @param resource being the lock holder
+     */
+    public synchronized ActiveLock createLock(LockInfo lockInfo, DavResource resource)
+	    throws DavException {
+	if (lockInfo == null || resource == null) {
+	    throw new IllegalArgumentException("Neither lockInfo nor resource must be null.");
+	}
+
+	String resourcePath = resource.getResourcePath();
+	// test if there is already a lock present on this resource
+	if (locks.containsKey(resourcePath)) {
+	    throw new DavException(DavServletResponse.SC_LOCKED, "Resource '" + resource.getResourcePath() + "' already holds a lock.");
+	}
+	// test if the new lock would conflict with any lock inherited from the
+	// collection or with a lock present on any member resource.
+	Iterator it = locks.keySet().iterator();
+	while (it.hasNext()) {
+	    String key = (String) it.next();
+	    // TODO: is check for lock on internal-member correct?
+	    if (Text.isDescendant(key, resourcePath)) {
+		ActiveLock l = (ActiveLock) locks.get(key);
+		if (l.isDeep() || (key.equals(Text.getRelativeParent(resourcePath, 1)) && !resource.isCollection())) {
+		    throw new DavException(DavServletResponse.SC_LOCKED, "Resource '" + resource.getResourcePath() + "' already inherits a lock by its collection.");
+		}
+	    } else if (Text.isDescendant(resourcePath, key)) {
+		if (lockInfo.isDeep() || isInternalMember(resource, key)) {
+		    throw new DavException(DavServletResponse.SC_LOCKED, "Resource '" + resource.getResourcePath() + "' cannot be locked due to a lock present on a member resource '" + key + "'.");
+		}
+
+	    }
+	}
+	ActiveLock lock = new DefaultActiveLock(lockInfo);
+	// Lazy: reset the timeout to 'Infinite', in order to omit the tests for
+	// lock expiration.
+	lock.setTimeout(DavConstants.INFINITE_TIMEOUT);
+	locks.put(resource.getResourcePath(), lock);
+	return lock;
+    }
+
+    /**
+     *
+     * @param lockInfo
+     * @param lockToken
+     * @param resource
+     * @return
+     * @throws DavException
+     * @see DavResource#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String)
+     */
+    public ActiveLock refreshLock(LockInfo lockInfo, String lockToken, DavResource resource)
+	    throws DavException {
+	// timeout is always infinite > no test for expiration or adjusting timeout needed.
+	ActiveLock lock = (ActiveLock)locks.get(resource.getResourcePath());
+	if (lock == null) {
+	    throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED);
+	} else if (!lock.getToken().equals(lockToken)) {
+	    throw new DavException(DavServletResponse.SC_LOCKED);
+	}
+	return lock;
+    }
+
+    /**
+     * Remove the lock hold by the given resource.
+     *
+     * @param lockToken
+     * @param resource that is the lock holder
+     */
+    public synchronized void releaseLock(String lockToken, DavResource resource)
+	    throws DavException {
+	if (!locks.containsKey(resource.getResourcePath())) {
+	    throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED);
+	}
+	// since locks have infinite timeout, check for expiration is omitted.
+
+	ActiveLock lock = (ActiveLock) locks.get(resource.getResourcePath());
+	if (lock.getToken().equals(lockToken)) {
+	    locks.remove(resource.getResourcePath());
+	} else {
+	    throw new DavException(DavServletResponse.SC_LOCKED);
+	}
+    }
+
+    /**
+     * Return true, if the resource with the given memberPath is a internal
+     * non-collection member of the given resource, thus affected by a
+     * non-deep lock present on the resource.
+     *
+     * @param resource
+     * @param memberPath
+     * @return
+     */
+    private static boolean isInternalMember(DavResource resource, String memberPath) {
+	if (resource.getResourcePath().equals(Text.getRelativeParent(memberPath, 1))) {
+	    // find the member with the given path
+	    DavResourceIterator it = resource.getMembers();
+	    while (it.hasNext()) {
+		DavResource member = it.nextResource();
+		if (member.getResourcePath().equals(memberPath)) {
+		    // return true if that member is not a collection
+		    return !member.isCollection();
+		}
+	    }
+	}
+	return false;
+    }
+}
+

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/lock/SimpleLockManager.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/simple/dav/lock/SimpleLockManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/AbstractItemResource.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/AbstractItemResource.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/AbstractItemResource.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/AbstractItemResource.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,483 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.spi;
+
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.webdav.property.*;
+import org.apache.jackrabbit.webdav.*;
+import org.apache.jackrabbit.webdav.spi.search.SearchResourceImpl;
+import org.apache.jackrabbit.webdav.spi.version.report.NodeTypesReport;
+import org.apache.jackrabbit.webdav.spi.version.report.ExportViewReport;
+import org.apache.jackrabbit.webdav.spi.version.report.LocateByUuidReport;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.transaction.TxLockEntry;
+import org.apache.jackrabbit.webdav.version.report.*;
+import org.apache.jackrabbit.webdav.version.DeltaVResource;
+import org.apache.jackrabbit.webdav.version.DeltaVConstants;
+import org.apache.jackrabbit.webdav.version.OptionsResponse;
+import org.apache.jackrabbit.webdav.version.OptionsInfo;
+import org.apache.jackrabbit.webdav.search.*;
+import org.apache.jackrabbit.webdav.util.Text;
+
+import javax.jcr.*;
+import java.util.*;
+
+/**
+ * <code>AbstractItemResource</code> covers common functionality for the various
+ * resources, that represent a repository item.
+ */
+abstract class AbstractItemResource extends AbstractResource implements DavResource,
+        SearchResource, DeltaVResource, ItemResourceConstants {
+
+    private static Logger log = Logger.getLogger(AbstractItemResource.class);
+
+    protected final Item item;
+    protected SupportedReportSetProperty supportedReports;
+
+    /**
+     * Create a new <code>AbstractItemResource</code>.
+     *
+     * @param locator
+     * @param session
+     */
+    AbstractItemResource(DavResourceLocator locator, DavSession session, DavResourceFactory factory) {
+        super(locator, session, factory);
+        Item repositoryItem = null;
+        if (locator != null) {
+            try {
+                repositoryItem = getRepositorySession().getItem(locator.getResourcePath());
+            } catch (RepositoryException e) {
+                // ignore: exists field evaluates to false
+                log.info(e.getMessage());
+            }
+        }
+        item = repositoryItem;
+        // initialize the supported locks and reports
+        initLockSupport();
+        initSupportedReports();
+    }
+
+    //----------------------------------------------< DavResource interface >---
+    /**
+     * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass()
+     */
+    public String getComplianceClass() {
+        return ItemResourceConstants.COMPLIANCE_CLASS;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods()
+     */
+    public String getSupportedMethods() {
+        return ItemResourceConstants.METHODS;
+    }
+
+    /**
+     * Returns true if there exists a {@link Item repository item} with the given
+     * resource path, false otherwise.
+     *
+     * @see DavResource#exists()
+     */
+    public boolean exists() {
+        return item != null;
+    }
+
+    /**
+     * @see DavResource#getDisplayName() )
+     */
+    public String getDisplayName() {
+        String name = null;
+        if (exists()) {
+            try {
+                name = item.getName();
+            } catch (RepositoryException e) {
+                // ignore: should not occure
+                log.warn(e.getMessage());
+            }
+        }
+        String resPath = getResourcePath();
+        if (name == null && resPath != null) {
+            int pos = resPath.lastIndexOf('/');
+            if (pos>=0) {
+                name = resPath.substring(pos+1);
+            } else {
+                name = resPath;
+            }
+            // note: since index info is present only with existing resources
+            // there is no need to check for any '[index]' suffix.
+        }
+        return name;
+    }
+
+    /**
+     * 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.
+     *
+     * @return the collection this resource is internal member of. Except for the
+     * repository root, the returned collection always represent the parent
+     * repository node.
+     * @see DavResource#getCollection()
+     */
+    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);
+        try {
+            collection = createResourceFromLocator(parentLoc);
+        } catch (DavException e) {
+            log.error("Unexpected error while retrieving collection: " + e.getMessage());
+        }
+
+        return collection;
+    }
+
+    /**
+     * Moves the underlaying repository item to the indicated destination.
+     *
+     * @param destination
+     * @throws DavException
+     * @see DavResource#move(DavResource)
+     * @see Session#move(String, String)
+     */
+    public void move(DavResource destination) throws DavException {
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+        DavResourceLocator destPath = destination.getLocator();
+        if (!getLocator().isSameWorkspace(destPath)) {
+            throw new DavException(DavServletResponse.SC_FORBIDDEN);
+        }
+
+        try {
+            getRepositorySession().move(getResourcePath(), destination.getResourcePath());
+            complete();
+
+        } catch (PathNotFoundException e) {
+            // according to rfc 2518
+            throw new DavException(DavServletResponse.SC_NOT_FOUND, e.getMessage());
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
+    /**
+     * Copies the underlaying repository item to the indicated destination. If
+     * the locator of the specified destination resource indicates a different
+     * workspace, {@link Workspace#copy(String, String, String)} is used to perform
+     * the copy operation, {@link Workspace#copy(String, String)} otherwise.
+     * <p/>
+     * Note, that this implementation does not support shallow copy.
+     *
+     * @param destination
+     * @param shallow
+     * @throws DavException
+     * @see DavResource#copy(DavResource, boolean)
+     * @see Workspace#copy(String, String)
+     * @see Workspace#copy(String, String, String)
+     */
+    public void copy(DavResource destination, boolean shallow) throws DavException {
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+        // TODO: support shallow and deep copy is required by RFC 2518
+        if (shallow) {
+            throw new DavException(DavServletResponse.SC_FORBIDDEN, "Unable to perform shallow copy.");
+        }
+
+        if (!(destination instanceof AbstractItemResource)) {
+            throw new DavException(DavServletResponse.SC_FORBIDDEN, "Cannot copy a resource that does not represent a repository item.");
+        }
+
+        try {
+            AbstractItemResource destResource = (AbstractItemResource) destination;
+            String destResourcePath = destResource.getResourcePath();
+            Workspace workspace = getRepositorySession().getWorkspace();
+            if (getLocator().isSameWorkspace(destination.getLocator())) {
+                workspace.copy(getResourcePath(), destResourcePath);
+            } else {
+                Workspace destWorkspace = destResource.getRepositorySession().getWorkspace();
+                destWorkspace.copy(workspace.getName(), getResourcePath(), destResourcePath);
+            }
+        } catch (PathNotFoundException e) {
+            // according to RFC 2518, should not occur
+            throw new DavException(DavServletResponse.SC_NOT_FOUND, e.getMessage());
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
+    //-------------------------------------------< SearchResource interface >---
+    /**
+     * @return
+     * @see org.apache.jackrabbit.webdav.search.SearchResource#getQueryGrammerSet()
+     */
+    public QueryGrammerSet getQueryGrammerSet() {
+        return new SearchResourceImpl(getLocator(), getSession()).getQueryGrammerSet();
+    }
+
+    /**
+     * @param sRequest
+     * @return
+     * @throws DavException
+     * @see SearchResource#search(org.apache.jackrabbit.webdav.search.SearchRequest)
+     */
+    public MultiStatus search(SearchRequest sRequest) throws DavException {
+        return new SearchResourceImpl(getLocator(), getSession()).search(sRequest);
+    }
+
+    //-------------------------------------------< DeltaVResource interface >---
+    /**
+     * @param optionsInfo
+     * @return object to be used in the OPTIONS response body or <code>null</code>
+     * @see DeltaVResource#getOptionResponse(org.apache.jackrabbit.webdav.version.OptionsInfo)
+     */
+    public OptionsResponse getOptionResponse(OptionsInfo optionsInfo) {
+        OptionsResponse oR = null;
+        if (optionsInfo != null) {
+            oR = new OptionsResponse();
+            // currently on DAV:version-history-collection-set and
+            // DAV:workspace-collection-set is supported.
+            if (optionsInfo.containsElement(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE)) {
+                String[] hrefs = new String[] { getLocatorFromResourcePath(VERSIONSTORAGE_PATH).getHref(true)};
+                oR.addEntry(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE, hrefs);
+            } else if (optionsInfo.containsElement(DeltaVConstants.XML_WSP_COLLECTION_SET, DeltaVConstants.NAMESPACE)) {
+                // workspaces cannot be created anywhere.
+                oR.addEntry(DeltaVConstants.XML_WSP_COLLECTION_SET, DeltaVConstants.NAMESPACE, new String[0]);
+            }
+        }
+        return oR;
+    }
+
+    /**
+     * @param reportInfo
+     * @return the requested report
+     * @throws DavException
+     * @see DeltaVResource#getReport(org.apache.jackrabbit.webdav.version.report.ReportInfo)
+     */
+    public Report getReport(ReportInfo reportInfo) throws DavException {
+        if (reportInfo == null) {
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "A REPORT request must provide a valid XML request body.");
+        }
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+
+        if (supportedReports.isSupportedReport(reportInfo)) {
+            try {
+                Report report = ReportType.getType(reportInfo).createReport();
+                report.setInfo(reportInfo);
+                report.setResource(this);
+                return report;
+            } catch (IllegalArgumentException e) {
+                // should never occur.
+                throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+            }
+        } else {
+            throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, "Unkown report "+ reportInfo.getReportElement().getNamespacePrefix() + reportInfo.getReportElement().getName() +"requested.");
+        }
+    }
+
+    /**
+     * The JCR api does not provide methods to create new workspaces. Calling
+     * <code>addWorkspace</code> on this resource will always fail.
+     *
+     * @param workspace
+     * @throws DavException Always throws.
+     * @see DeltaVResource#addWorkspace(org.apache.jackrabbit.webdav.DavResource)
+     */
+    public void addWorkspace(DavResource workspace) throws DavException {
+        throw new DavException(DavServletResponse.SC_FORBIDDEN);
+    }
+
+    /**
+     * Return an array of <code>DavResource</code> objects that are referenced
+     * by the property with the specified name.
+     *
+     * @param hrefPropertyName
+     * @return array of <code>DavResource</code>s
+     * @throws DavException
+     * @see DeltaVResource#getReferenceResources(org.apache.jackrabbit.webdav.property.DavPropertyName)
+     */
+    public DavResource[] getReferenceResources(DavPropertyName hrefPropertyName) throws DavException {
+        DavProperty prop = getProperty(hrefPropertyName);
+        if (prop == null || !(prop instanceof HrefProperty)) {
+            throw new DavException(DavServletResponse.SC_CONFLICT, "Unknown Href-Property '"+hrefPropertyName+"' on resource "+getResourcePath());
+        }
+
+        List hrefs = ((HrefProperty)prop).getHrefs();
+        DavResource[] refResources = new DavResource[hrefs.size()];
+        Iterator hrefIter = hrefs.iterator();
+        int i = 0;
+        while (hrefIter.hasNext()) {
+            refResources[i] = getResourceFromHref((String)hrefIter.next());
+            i++;
+        }
+        return refResources;
+    }
+
+    /**
+     * Retrieve the <code>DavResource</code> object that is represented by
+     * the given href String.
+     *
+     * @param href
+     * @return <code>DavResource</code> object
+     */
+    private DavResource getResourceFromHref(String href) throws DavException {
+        // build a new locator: remove trailing prefix
+        DavResourceLocator locator = getLocator();
+        String prefix = locator.getPrefix();
+        if (href.startsWith(prefix)) {
+            href = href.substring(prefix.length());
+        }
+        DavResourceLocator loc = locator.getFactory().createResourceLocator(prefix, href);
+
+        // create a new resource object
+        DavResource res;
+        if (getRepositorySession().itemExists(loc.getResourcePath())) {
+            res = createResourceFromLocator(loc);
+        } else {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+        return res;
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     * Initialize the {@link org.apache.jackrabbit.webdav.lock.SupportedLock} property
+     * with entries that are valid for any type item resources.
+     *
+     * @see org.apache.jackrabbit.webdav.lock.SupportedLock
+     * @see org.apache.jackrabbit.webdav.transaction.TxLockEntry
+     */
+    protected void initLockSupport() {
+        if (exists()) {
+            // add supportedlock entries for local and eventually for global transaction locks
+            supportedLock.addEntry(new TxLockEntry(true));
+            supportedLock.addEntry(new TxLockEntry(false));
+        }
+    }
+
+    /**
+     * Define the set of reports supported by this resource.
+     *
+     * @see SupportedReportSetProperty
+     */
+    protected void initSupportedReports() {
+        if (exists()) {
+            supportedReports = new SupportedReportSetProperty(new ReportType[] {
+                ReportType.EXPAND_PROPERTY,
+                NodeTypesReport.NODETYPES_REPORT,
+                ExportViewReport.EXPORTVIEW_REPORT,
+                LocateByUuidReport.LOCATE_BY_UUID_REPORT
+            });
+        } else {
+            supportedReports = new SupportedReportSetProperty();
+        }
+    }
+
+    /**
+     * Fill the property set for this resource.
+     */
+    protected void initProperties() {
+        super.initProperties();
+        if (exists()) {
+            try {
+                properties.add(new DefaultDavProperty(JCR_NAME, item.getName()));
+                properties.add(new DefaultDavProperty(JCR_PATH, item.getPath()));
+                properties.add(new DefaultDavProperty(JCR_DEPTH, String.valueOf(item.getDepth())));
+            } catch (RepositoryException e) {
+                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));
+            } else if (item.isModified()) {
+                properties.add(new DefaultDavProperty(JCR_ISMODIFIED, null, true));
+            }
+
+            // DeltaV properties
+            properties.add(supportedReports);
+            // creator-displayname, comment: not value available from jcr
+            properties.add(new DefaultDavProperty(DeltaVConstants.CREATOR_DISPLAYNAME, null, true));
+            properties.add(new DefaultDavProperty(DeltaVConstants.COMMENT, null, true));
+
+            // TODO: required supported-live-property-set
+        }
+    }
+
+    /**
+     * If this resource exists but does not contain a transaction id, complete
+     * will try to persist any modifications prsent on the underlaying repository
+     * item.
+     *
+     * @throws DavException if calling {@link Item#save()} fails
+     */
+    void complete() throws DavException {
+        if (exists() && getTransactionId() == null) {
+            try {
+                if (item.isModified()) {
+                    item.save();
+                }
+            } catch (RepositoryException e) {
+                // this includes LockException, ConstraintViolationException etc. not detected before
+                log.error("Error while completing request: " + e.getMessage() +" -> reverting changes.");
+                try {
+                    item.refresh(false);
+                } catch (RepositoryException re) {
+                    log.error("Error while reverting changes: " + re.getMessage());
+                }
+                throw new JcrDavException(e);
+            }
+        }
+    }
+
+    /**
+     * Build a new {@link DavResourceLocator} from the given repository item.
+     *
+     * @param repositoryItem
+     * @return a new locator for the specified item.
+     * @see #getLocatorFromResourcePath(String)
+     */
+    protected DavResourceLocator getLocatorFromItem(Item repositoryItem) {
+        String itemPath = null;
+        try {
+            if (repositoryItem != null) {
+                itemPath = repositoryItem.getPath();
+            }
+        } catch (RepositoryException e) {
+            // ignore: should not occur
+            log.warn(e.getMessage());
+        }
+        return getLocatorFromResourcePath(itemPath);
+    }
+
+    /**
+     * Shortcut for <code>getSession().getRepositorySession()</code>
+     *
+     * @return repository session present in the {@link #session}.
+     */
+    protected Session getRepositorySession() {
+        return getSession().getRepositorySession();
+    }
+}
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/AbstractItemResource.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/AbstractItemResource.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message