jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tri...@apache.org
Subject svn commit: r156314 [6/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/webdav/spi/transaction/TxLockManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/transaction/TxLockManagerImpl.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/transaction/TxLockManagerImpl.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/transaction/TxLockManagerImpl.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,666 @@
+/*
+ * Copyright 2004 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.transaction;
+
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.webdav.*;
+import org.apache.jackrabbit.webdav.spi.*;
+import org.apache.jackrabbit.webdav.transaction.*;
+import org.apache.jackrabbit.webdav.util.Text;
+import org.apache.jackrabbit.webdav.lock.*;
+import org.apache.jackrabbit.core.XASession;
+
+import javax.jcr.*;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.Xid;
+import java.util.*;
+
+/**
+ * <code>TxLockManagerImpl</code> manages locks with locktype
+ * '{@link TransactionConstants#TRANSACTION jcr:transaction}'.
+ *
+ * todo: removing all expired locks
+ * todo: 'local' and 'global' are not accurate terms in the given context > replace
+ * todo: the usage of the 'global' transaction is not according to the JTA specification,
+ * which explicitely requires any transaction present on a servlet to be completed before
+ * the service method returns. Starting/completing transactions on the session object,
+ * which is possible with the jackrabbit implementation is a hack.
+ * todo: review of this transaction part is therefore required. Is there a use-case
+ * for those 'global' transactions at all...
+ */
+public class TxLockManagerImpl implements TxLockManager {
+
+    private static Logger log = Logger.getLogger(TxLockManagerImpl.class);
+
+    private TransactionMap map = new TransactionMap();
+
+    /**
+     * Create a new lock.
+     *
+     * @param lockInfo as present in the request body.
+     * @param resource
+     * @return the lock
+     * @throws DavException if the lock could not be obtained.
+     * @throws IllegalArgumentException if the resource is <code>null</code> or
+     * does not implement {@link TransactionResource} interface.
+     * @see LockManager#createLock(org.apache.jackrabbit.webdav.lock.LockInfo, org.apache.jackrabbit.webdav.DavResource)
+     */
+    public ActiveLock createLock(LockInfo lockInfo, DavResource resource)
+	    throws DavException {
+	if (resource == null || !(resource instanceof TransactionResource)) {
+	    throw new IllegalArgumentException("Invalid resource");
+	}
+	return createLock(lockInfo, (TransactionResource)resource);
+    }
+
+    /**
+     * Create a new lock.
+     *
+     * @param lockInfo
+     * @param resource
+     * @return the lock
+     * @throws DavException if the request lock has the wrong lock type or if
+     * the lock could not be obtained for any reason.
+     */
+    private synchronized ActiveLock createLock(LockInfo lockInfo, TransactionResource resource)
+	    throws DavException {
+	if (!lockInfo.isDeep() || !TransactionConstants.TRANSACTION.equals(lockInfo.getType())) {
+	    throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED);
+	}
+
+	ActiveLock existing = getLock(lockInfo.getType(), lockInfo.getScope(), resource);
+	if (existing != null) {
+	    throw new DavException(DavServletResponse.SC_LOCKED);
+	}
+	// TODO: check for locks on member resources is required as well for lock is always deep!
+
+	Transaction tx = createTransaction(resource.getLocator(), lockInfo);
+	tx.start(resource);
+
+	// keep references to this lock
+	addReferences(tx, getMap(resource), resource);
+
+	return tx.getLock();
+    }
+
+    /**
+     * Build the transaction object associated by the lock.
+     *
+     * @param locator
+     * @param lockInfo
+     * @return
+     */
+    private Transaction createTransaction(DavResourceLocator locator, LockInfo lockInfo) {
+	if (TransactionConstants.GLOBAL.equals(lockInfo.getScope())) {
+	    return new GlobalTransaction(locator, new TxActiveLock(lockInfo));
+	} else {
+	    return new LocalTransaction(locator, new TxActiveLock(lockInfo));
+	}
+    }
+
+    /**
+     * Refresh the lock indentified by the given lock token.
+     *
+     * @param lockInfo
+     * @param lockToken
+     * @param resource
+     * @return the lock
+     * @throws DavException
+     * @throws IllegalArgumentException if the resource is <code>null</code> or
+     * does not implement {@link TransactionResource} interface.
+     * @see LockManager#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String, org.apache.jackrabbit.webdav.DavResource)
+     */
+    public ActiveLock refreshLock(LockInfo lockInfo, String lockToken,
+				  DavResource resource) throws DavException {
+	if (resource == null || !(resource instanceof TransactionResource)) {
+	    throw new IllegalArgumentException("Invalid resource");
+	}
+	return refreshLock(lockInfo, lockToken, (TransactionResource)resource);
+    }
+
+    /**
+     * Reset the timeout of the lock identified by the given lock token.
+     *
+     * @param lockInfo
+     * @param lockToken
+     * @param resource
+     * @return
+     * @throws DavException if the lockdid not exist or is expired.
+     */
+    private synchronized ActiveLock refreshLock(LockInfo lockInfo, String lockToken,
+						TransactionResource resource) throws DavException {
+
+	TransactionMap responsibleMap = getMap(resource);
+	Transaction tx = responsibleMap.get(lockToken);
+	if (tx == null) {
+	    throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No valid transaction lock found for resource '" + resource.getResourcePath()+ "'");
+	} else if (tx.getLock().isExpired()) {
+	    removeExpired(tx, responsibleMap, resource);
+	    throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction lock for resource '" + resource.getResourcePath()+ "' was already expired.");
+	} else {
+	    tx.getLock().setTimeout(lockInfo.getTimeout());
+	}
+	return tx.getLock();
+    }
+
+    /**
+     * Throws UnsupportedOperationException.
+     *
+     * @param lockToken
+     * @param resource
+     * @throws DavException
+     * @see LockManager#releaseLock(String, org.apache.jackrabbit.webdav.DavResource)
+     */
+    public void releaseLock(String lockToken, DavResource resource)
+	    throws DavException {
+	throw new UnsupportedOperationException("A transaction lock can only be release with a TransactionInfo object and a lock token.");
+    }
+
+    /**
+     * Release the lock identified by the given lock token.
+     *
+     * @param lockInfo
+     * @param lockToken
+     * @param resource
+     * @throws DavException
+     */
+    public synchronized void releaseLock(TransactionInfo lockInfo, String lockToken,
+					 TransactionResource resource) throws DavException {
+	if (resource == null) {
+	    throw new IllegalArgumentException("Resource must not be null.");
+	}
+	TransactionMap responsibleMap = getMap(resource);
+	Transaction tx = responsibleMap.get(lockToken);
+
+	if (tx == null) {
+	    throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No transaction lock found for resource '" + resource.getResourcePath()+ "'");
+	} else if (tx.getLock().isExpired()) {
+	    removeExpired(tx, responsibleMap, resource);
+	    throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction lock for resource '" + resource.getResourcePath()+ "' was already expired.");
+	} else {
+	    if (TransactionConstants.XML_COMMIT.equals(lockInfo.getStatus())) {
+		tx.commit(resource);
+	    } else {
+		tx.rollback(resource);
+	    }
+	    removeReferences(tx, responsibleMap, resource);
+	}
+    }
+
+    /**
+     * Always returns null
+     *
+     * @param type
+     * @param scope
+     * @param resource
+     * @return null
+     * @see #getLock(Type, Scope, TransactionResource)
+     * @see LockManager#getLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope, org.apache.jackrabbit.webdav.DavResource)
+     */
+    public ActiveLock getLock(Type type, Scope scope, DavResource resource) {
+	return null;
+    }
+
+    /**
+     * Return the lock applied to the given resource or <code>null</code>
+     *
+     * @param type
+     * @param scope
+     * @param resource
+     * @return lock applied to the given resource or <code>null</code>
+     * @see LockManager#getLock(Type, Scope, DavResource)
+     * todo: is it correct to return one that specific lock, the current session is token-holder of?
+     */
+    public ActiveLock getLock(Type type, Scope scope, TransactionResource resource) {
+	ActiveLock lock = null;
+	if (TransactionConstants.TRANSACTION.equals(type)) {
+	    String[] sessionTokens = resource.getSession().getRepositorySession().getLockTokens();
+	    int i = 0;
+	    while (lock == null && i < sessionTokens.length) {
+		String lockToken = sessionTokens[i];
+		lock = getLock(lockToken, scope, resource);
+		i++;
+	    }
+	}
+	return lock;
+    }
+
+    /**
+     * @param lockToken
+     * @param resource
+     * @return
+     */
+    private ActiveLock getLock(String lockToken, Scope scope, DavResource resource) {
+	if (!(resource instanceof TransactionResource)) {
+	    log.info("");
+	    return null;
+	}
+
+	ActiveLock lock = null;
+	Transaction tx = null;
+	TransactionMap m = map;
+	// check if main-map contains that txId
+	if (m.containsKey(lockToken)) {
+	    tx = m.get(lockToken);
+	} else {
+	    // look through all the nested tx-maps (i.e. global txs) for the given txId
+	    Iterator it = m.values().iterator();
+	    while (it.hasNext() && tx == null) {
+		Transaction txMap = (Transaction) it.next();
+		if (!txMap.isLocal()) {
+		    m = ((TransactionMap)txMap);
+		    if (m.containsKey(lockToken)) {
+			tx = ((TransactionMap)txMap).get(lockToken);
+		    }
+		}
+	    }
+	}
+
+	if (tx != null) {
+	    if (tx.getLock().isExpired()) {
+		removeExpired(tx, m, (TransactionResource)resource);
+	    } else if (tx.appliesToResource(resource) && (scope == null || tx.getLock().getScope().equals(scope))) {
+		lock = tx.getLock();
+	    }
+	}
+	return lock;
+    }
+
+    /**
+     * Returns true if the given lock token belongs to a lock that applies to
+     * the given resource, false otherwise. The token may either be retrieved
+     * from the {@link DavConstants#HEADER_LOCK_TOKEN Lock-Token header} or
+     * from the {@link TransactionConstants#HEADER_TRANSACTIONID TransactionId header}.
+     *
+     * @param token
+     * @param resource
+     * @return
+     * @see LockManager#hasLock(String token, DavResource resource)
+     */
+    public boolean hasLock(String token, DavResource resource) {
+	return getLock(token, null, resource) != null;
+    }
+
+    /**
+     * Return the map that may contain a transaction lock for the given resource.
+     * In case the resource provides a transactionId, the map must be a
+     * repository transaction that is identified by the given id and which in
+     * turn can act as map.
+     *
+     * @param resource
+     * @return responsible map.
+     * @throws DavException if no map could be retrieved.
+     */
+    private TransactionMap getMap(TransactionResource resource)
+	    throws DavException {
+
+	String txKey = resource.getTransactionId();
+	if (txKey == null) {
+	    return map;
+	} else {
+	    if (!map.containsKey(txKey)) {
+		throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction map '" + map + " does not contain a transaction with TransactionId '" + txKey + "'.");
+	    }
+	    Transaction tx = map.get(txKey);
+	    if (tx.isLocal()) {
+		throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "TransactionId '" + txKey + "' points to a local transaction, that cannot act as transaction map");
+	    } else if (tx.getLock() != null && tx.getLock().isExpired()) {
+		removeExpired(tx, map, resource);
+		throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to retrieve an expired global transaction.");
+	    }
+	    // tx is a global transaction that acts as map as well.
+	    return (TransactionMap)tx;
+	}
+    }
+
+    /**
+     * Rollbacks the specified transaction and releases the lock. This includes
+     * the removal of all references.
+     *
+     * @param tx
+     * @param responsibleMap
+     * @param resource
+     */
+    private static void removeExpired(Transaction tx, TransactionMap responsibleMap,
+				      TransactionResource resource) {
+	log.info("Removing expired transaction lock " + tx);
+	try {
+	    tx.rollback(resource);
+	    removeReferences(tx, responsibleMap, resource);
+	} catch (DavException e) {
+	    log.error("Error while removing expired transaction lock: " + e.getMessage());
+	}
+    }
+
+    /**
+     * Create the required references to the new transaction specified by tx.
+     *
+     * @param tx
+     * @param responsibleMap
+     * @param resource
+     * @throws DavException
+     */
+    private static void addReferences(Transaction tx, TransactionMap responsibleMap,
+				      TransactionResource resource) throws DavException {
+	log.info("Adding transactionId '" + tx.getId() + "' as session lock token.");
+	resource.getSession().getRepositorySession().addLockToken(tx.getId());
+
+	responsibleMap.put(tx.getId(), tx);
+	resource.getSession().addReference(tx.getId());
+    }
+
+    /**
+     * Remove all references to the specified transaction.
+     *
+     * @param tx
+     * @param responsibleMap
+     * @param resource
+     */
+    private static void removeReferences(Transaction tx, TransactionMap responsibleMap,
+					 TransactionResource resource) {
+	log.info("Removing transactionId '" + tx.getId() + "' from session lock tokens.");
+	resource.getSession().getRepositorySession().removeLockToken(tx.getId());
+
+	responsibleMap.remove(tx.getId());
+	resource.getSession().removeReference(tx.getId());
+    }
+    //------------------------------------------< inner classes, interfaces >---
+    /**
+     * Internal <code>Transaction</code> interface
+     */
+    private interface Transaction {
+
+	TxActiveLock getLock();
+
+	/**
+	 * @return the id of this transaction.
+	 */
+	String getId();
+
+	/**
+	 * @return path of the lock holding resource
+	 */
+	String getResourcePath();
+
+	/**
+	 * @param resource
+	 * @return true if the lock defined by this transaction applies to the
+	 * given resource, either due to the resource holding that lock or due
+	 * to a deep lock hold by any ancestor resource.
+	 */
+	boolean appliesToResource(DavResource resource);
+
+	/**
+	 * @return true if this transaction is used to allow for transient changes
+	 * on the underlaying repository, that may be persisted with the final
+	 * UNLOCK request only.
+	 */
+	boolean isLocal();
+
+	/**
+	 * Start this transaction.
+	 *
+	 * @param resource
+	 * @throws DavException if an error occurs.
+	 */
+	void start(TransactionResource resource) throws DavException ;
+
+	/**
+	 * Commit this transaction
+	 *
+	 * @param resource
+	 * @throws DavException if an error occurs.
+	 */
+	void commit(TransactionResource resource) throws DavException ;
+
+	/**
+	 * Rollback this transaction.
+	 *
+	 * @param resource
+	 * @throws DavException if an error occurs.
+	 */
+	void rollback(TransactionResource resource) throws DavException ;
+    }
+
+    /**
+     * Abstract transaction covering functionally to both implementations.
+     */
+    private abstract static class AbstractTransaction extends TransactionMap implements Transaction {
+
+	private final DavResourceLocator locator;
+	private final TxActiveLock lock;
+
+	private AbstractTransaction(DavResourceLocator locator, TxActiveLock lock) {
+	    this.locator = locator;
+	    this.lock = lock;
+	}
+
+	/**
+	 * @see #getLock()
+	 */
+	public TxActiveLock getLock() {
+	    return lock;
+	}
+
+	/**
+	 * @see #getId()
+	 */
+	public String getId() {
+	    return lock.getToken();
+	}
+
+	/**
+	 * @see #getResourcePath()
+	 */
+	public String getResourcePath() {
+	    return locator.getResourcePath();
+	}
+
+	/**
+	 * @see #appliesToResource(DavResource)
+	 */
+	public boolean appliesToResource(DavResource resource) {
+	    if (locator.isSameWorkspace(resource.getLocator())) {
+		String lockResourcePath = getResourcePath();
+		String resPath = resource.getResourcePath();
+
+		while (!"".equals(resPath)) {
+		    if (lockResourcePath.equals(resPath)) {
+			return true;
+		    }
+		    resPath = Text.getRelativeParent(resPath, 1);
+		}
+	    }
+	    return false;
+	}
+    }
+
+    /**
+     *
+     */
+    private final static class LocalTransaction extends AbstractTransaction {
+
+	private LocalTransaction(DavResourceLocator locator, TxActiveLock lock) {
+	    super(locator, lock);
+	}
+
+	public boolean isLocal() {
+	    return true;
+	}
+
+	public void start(TransactionResource resource) throws DavException {
+	    // make sure, the given resource represents an existing repository item
+	    if (!resource.getSession().getRepositorySession().itemExists(getResourcePath())) {
+		throw new DavException(DavServletResponse.SC_CONFLICT, "Unable to start local transaction: no repository item present at "+getResourcePath());
+	    }
+	}
+
+	public void commit(TransactionResource resource) throws DavException {
+	    try {
+		DavSession session = resource.getSession();
+		session.getRepositorySession().getItem(getResourcePath()).save();
+	    } catch (RepositoryException e) {
+		throw new JcrDavException(e);
+	    }
+	}
+
+	public void rollback(TransactionResource resource) throws DavException  {
+	    try {
+		DavSession session = resource.getSession();
+		session.getRepositorySession().getItem(getResourcePath()).refresh(false);
+	    } catch (RepositoryException e) {
+		throw new JcrDavException(e);
+	    }
+	}
+
+	public Transaction put(String key, Transaction value) throws DavException {
+	    throw new DavException(WebdavResponse.SC_PRECONDITION_FAILED, "Attempt to nest a new transaction into a local one.");
+	}
+    }
+
+    /**
+     *
+     */
+    private static class GlobalTransaction extends AbstractTransaction {
+
+	private Xid xid;
+
+	private GlobalTransaction(DavResourceLocator locator, TxActiveLock lock) {
+	    super(locator, lock);
+	    xid = new XidImpl(lock.getToken());
+	}
+
+	public boolean isLocal() {
+	    return false;
+	}
+
+	public void start(TransactionResource resource) throws DavException {
+	    XAResource xaRes = getXAResource(resource);
+	    try {
+		xaRes.setTransactionTimeout((int)getLock().getTimeout()/1000);
+		xaRes.start(xid, XAResource.TMNOFLAGS);
+	    } catch (XAException e) {
+		throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage());
+	    }
+	}
+
+	public void commit(TransactionResource resource) throws DavException {
+	    XAResource xaRes = getXAResource(resource);
+	    try {
+		xaRes.commit(xid, false);
+		removeLocalTxReferences(resource);
+	    } catch (XAException e) {
+		throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage());
+	    }
+	}
+
+	public void rollback(TransactionResource resource) throws DavException {
+	    XAResource xaRes = getXAResource(resource);
+	    try {
+		xaRes.rollback(xid);
+		removeLocalTxReferences(resource);
+	    } catch (XAException e) {
+		throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage());
+	    }
+	}
+
+	private XAResource getXAResource(TransactionResource resource) throws DavException {
+	    Session session = resource.getSession().getRepositorySession();
+	    if (session instanceof XASession) {
+		return ((XASession)session).getXAResource();
+	    } else {
+		throw new DavException(DavServletResponse.SC_FORBIDDEN);
+	    }
+	}
+
+	private void removeLocalTxReferences(TransactionResource resource) {
+	    Iterator it = values().iterator();
+	    while (it.hasNext()) {
+		Transaction tx = (Transaction) it.next();
+		removeReferences(tx, this, resource);
+	    }
+	}
+
+	public Transaction put(String key, Transaction value) throws DavException {
+	    if (!(value instanceof LocalTransaction)) {
+		throw new DavException(WebdavResponse.SC_PRECONDITION_FAILED, "Attempt to nest global transaction into a global one.");
+	    }
+	    return (Transaction) super.put(key, value);
+	}
+    }
+
+    /**
+     *
+     */
+    private static class TransactionMap extends HashMap {
+
+	public Transaction get(String key) {
+	    Transaction tx = null;
+	    if (containsKey(key)) {
+		tx = (Transaction) super.get(key);
+	    }
+	    return tx;
+	}
+
+	public Transaction put(String key, Transaction value) throws DavException {
+	    // any global an local transactions allowed.
+	    return (Transaction) super.put(key, value);
+	}
+    }
+
+    /**
+     * Private class implementing Xid interface.
+     */
+    private static class XidImpl implements Xid {
+
+	private final String id;
+
+	/**
+	 * Create a new Xid
+	 *
+	 * @param id
+	 */
+	private XidImpl(String id) {
+	    this.id = id;
+	}
+
+	/**
+	 * @return 1
+	 * @see javax.transaction.xa.Xid#getFormatId()
+	 */
+	public int getFormatId() {
+	    // todo: define reasonable format id
+	    return 1;
+	}
+
+	/**
+	 * @return an empty byte array.
+	 * @see javax.transaction.xa.Xid#getBranchQualifier()
+	 */
+	public byte[] getBranchQualifier() {
+	    return new byte[0];
+	}
+
+	/**
+	 * @return id as byte array
+	 * @see javax.transaction.xa.Xid#getGlobalTransactionId()
+	 */
+	public byte[] getGlobalTransactionId() {
+	    return id.getBytes();
+	}
+    }
+}

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

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

Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/VersionControlledItemCollection.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/VersionControlledItemCollection.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/VersionControlledItemCollection.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/VersionControlledItemCollection.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,584 @@
+/*
+ * 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.version;
+
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.webdav.property.*;
+import org.apache.jackrabbit.webdav.*;
+import org.apache.jackrabbit.webdav.spi.JcrDavException;
+import org.apache.jackrabbit.webdav.spi.DefaultItemCollection;
+import org.apache.jackrabbit.webdav.version.*;
+import org.apache.jackrabbit.webdav.version.report.*;
+
+import javax.jcr.*;
+import javax.jcr.observation.*;
+import javax.jcr.observation.EventListener;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import java.util.List;
+
+/**
+ * <code>VersionControlledItemCollection</code> represents a JCR node item and
+ * covers all functionality related to versioning of {@link Node}s.
+ *
+ * @see Node
+ */
+public class VersionControlledItemCollection extends DefaultItemCollection
+        implements VersionControlledResource {
+
+    private static Logger log = Logger.getLogger(VersionControlledItemCollection.class);
+
+    /**
+     * Create a new <code>VersionControlledItemCollection</code>.
+     *
+     * @param locator
+     * @param session
+     */
+    public VersionControlledItemCollection(DavResourceLocator locator, DavSession session, DavResourceFactory factory) {
+        super(locator, session, factory);
+        if (exists() && !(item instanceof Node)) {
+            throw new IllegalArgumentException("A collection resource can not be constructed from a Property item.");
+        }
+    }
+
+    //----------------------------------------------< DavResource interface >---
+    /**
+     * Return a comma separated string listing the supported method names.
+     *
+     * @return the supported method names.
+     * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods()
+     */
+    public String getSupportedMethods() {
+        StringBuffer sb = new StringBuffer(super.getSupportedMethods());
+        // Versioning support
+        sb.append(", ").append(VersionableResource.METHODS);
+        if (this.isVersionControlled()) {
+            try {
+                if (((Node)item).isCheckedOut()) {
+                    sb.append(", ").append(VersionControlledResource.methods_checkedOut);
+                } else {
+                    sb.append(", ").append(VersionControlledResource.methods_checkedIn);
+                }
+            } catch (RepositoryException e) {
+                // should not occur.
+                log.error(e.getMessage());
+            }
+        }
+        return sb.toString();
+    }
+
+    //--------------------------------< VersionControlledResource interface >---
+    /**
+     * Adds version control to this resource. If the resource is already under
+     * version control, this method has no effect.
+     *
+     * @throws org.apache.jackrabbit.webdav.DavException if this resource does not
+     * exist yet or if an error occurs while making the underlaying node versionable.
+     * @see org.apache.jackrabbit.webdav.version.VersionableResource#addVersionControl()
+     */
+    public void addVersionControl() throws DavException {
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+        if (!isVersionControlled()) {
+            try {
+                ((Node)item).addMixin(MIX_VERSIONABLE);
+                item.save();
+            } catch (RepositoryException e) {
+                throw new JcrDavException(e);
+            }
+        } // else: is already version controlled -> ignore
+    }
+
+    /**
+     * Calls {@link javax.jcr.Node#checkin()} on the underlaying repository node.
+     *
+     * @throws org.apache.jackrabbit.webdav.DavException
+     * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkin()
+     */
+    public String checkin() throws DavException {
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+        if (!isVersionControlled()) {
+            throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+        }
+        try {
+            Version v = ((Node) item).checkin();
+            DavResourceLocator loc = getLocator();
+            String versionHref = loc.getFactory().createResourceLocator(loc.getPrefix(), loc.getWorkspacePath(), v.getPath()).getHref(true);
+            return versionHref;
+        } catch (RepositoryException e) {
+            // UnsupportedRepositoryException should not occur
+            throw new JcrDavException(e);
+        }
+    }
+
+    /**
+     * Calls {@link javax.jcr.Node#checkout()} on the underlaying repository node.
+     *
+     * @throws org.apache.jackrabbit.webdav.DavException
+     * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkout()
+     */
+    public void checkout() throws DavException {
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+        if (!isVersionControlled()) {
+            throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+        }
+        try {
+            ((Node) item).checkout();
+        } catch (RepositoryException e) {
+            // UnsupportedRepositoryException should not occur
+            throw new JcrDavException(e);
+        }
+    }
+
+    /**
+     * Not implemented. Always throws a <code>DavException</code> with error code
+     * {@link org.apache.jackrabbit.webdav.DavServletResponse#SC_NOT_IMPLEMENTED}.
+     *
+     * @throws org.apache.jackrabbit.webdav.DavException
+     * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#uncheckout()
+     */
+    public void uncheckout() throws DavException {
+        throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED);
+    }
+
+    /**
+     * Perform an update on this resource. Depending on the format of the <code>updateInfo</code>
+     * this is translated to one of the following methods defined by the JCR API:
+     * <ul>
+     * <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>
+     * 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)
+     * @todo with jcr the node must not be versionable in order to perform Node.update.
+     */
+    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);
+        }
+
+        MultiStatus ms = new MultiStatus();
+        try {
+            Node node = (Node)item;
+            boolean removeExisting = updateInfo.getUpdateElement().getChild(XML_REMOVEEXISTING, NAMESPACE) != null;
+
+            // register eventListener in order to be able to report the modified resources.
+            EventListener el = new EListener(updateInfo.getPropertyNameSet(), ms);
+            registerEventListener(el, node.getPath());
+
+            // 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++) {
+                    versions[i] = vh.getVersion(getResourceName(hrefs[i], true));
+                }
+                if (versions.length == 1) {
+                    String relPath = updateInfo.getUpdateElement().getChildText(XML_RELPATH, NAMESPACE);
+                    if (relPath == null) {
+                        node.restore(versions[0], removeExisting);
+                    } else {
+                        node.restore(versions[0], relPath, removeExisting);
+                    }
+                } else {
+                    getRepositorySession().getWorkspace().restore(versions, 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);
+                }
+            } else if (updateInfo.getWorkspaceHref() != null) {
+                String workspaceName = getResourceName(updateInfo.getWorkspaceHref(), true);
+                node.update(workspaceName);
+            } else {
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body.");
+            }
+
+            // unregister the event listener again
+            unregisterEventListener(el);
+
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+        return ms;
+    }
+
+    /**
+     * Merge the repository node represented by this resource according to the
+     * information present in the given {@link MergeInfo} object.
+     *
+     * @param mergeInfo
+     * @return <code>MultiStatus</code> reccording all repository items affected
+     * by this merge call.
+     * @throws org.apache.jackrabbit.webdav.DavException
+     * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#merge(org.apache.jackrabbit.webdav.version.MergeInfo)
+     * @see Node#merge(String, boolean)
+     * @todo with jcr the node must not be versionable in order to perform Node.merge
+     */
+    public MultiStatus merge(MergeInfo mergeInfo) throws DavException {
+        if (mergeInfo == null) {
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+
+        MultiStatus ms = new MultiStatus();
+        try {
+            Node node = (Node)item;
+
+            // register eventListener in order to be able to report the modifications.
+            EventListener el = new EListener(mergeInfo.getPropertyNameSet(), ms);
+            registerEventListener(el, node.getPath());
+
+            String workspaceName = getResourceName(mergeInfo.getSourceHref(), true);
+            node.merge(workspaceName, !mergeInfo.isNoAutoMerge());
+
+            // unregister the event listener again
+            unregisterEventListener(el);
+
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+
+        return ms;
+    }
+
+    /**
+     * Resolve the merge conflicts according to the value of the {@link #AUTO_MERGE_SET DAV:auto-merge-set}
+     * property present in the specified <code>DavPropertySet</code>s.
+     *
+     * @param setProperties
+     * @param removePropertyNames
+     * @throws org.apache.jackrabbit.webdav.DavException
+     * @see VersionControlledResource#resolveMergeConflict(DavPropertySet, DavPropertyNameSet)
+     * @see Node#doneMerge(Version)
+     * @see Node#cancelMerge(Version)
+     */
+    public void resolveMergeConflict(DavPropertySet setProperties,
+                                     DavPropertyNameSet removePropertyNames) throws DavException {
+
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+        if (!isVersionControlled()) {
+            throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+        }
+
+        try {
+            Node n = (Node)item;
+            if (removePropertyNames.contains(AUTO_MERGE_SET)) {
+                // retrieve the current jcr:mergeFailed property values
+                if (!((Node)item).hasProperty(PROP_MERGEFAILED)) {
+                    throw new DavException(DavServletResponse.SC_CONFLICT, "Attempt to resolve non-existing merge conflicts.");
+                }
+                Value[] mergeFailed = ((Node)item).getProperty(PROP_MERGEFAILED).getValues();
+
+                // resolve all remaining merge conflicts with 'cancel'
+                for (int i = 0; i < mergeFailed.length; i++) {
+                    n.cancelMerge((Version)getRepositorySession().getNodeByUUID(mergeFailed[i].getString()));
+                }
+                // adjust removeProperty set
+                removePropertyNames.remove(AUTO_MERGE_SET);
+
+            } else if (setProperties.contains(AUTO_MERGE_SET) && setProperties.contains(PREDECESSOR_SET)){
+                // retrieve the current jcr:mergeFailed property values
+                if (!((Node)item).hasProperty(PROP_MERGEFAILED)) {
+                    throw new DavException(DavServletResponse.SC_CONFLICT, "Attempt to resolve non-existing merge conflicts.");
+                }
+                Value[] mergeFailed = ((Node)item).getProperty(PROP_MERGEFAILED).getValues();
+
+
+                // check which mergeFailed entries have been removed from the
+                // auto-merge-set (cancelMerge) and have been moved over to the
+                // predecessor set (doneMerge)
+                List mergeset = new HrefProperty(setProperties.get(AUTO_MERGE_SET)).getHrefs();
+                List predecSet = new HrefProperty(setProperties.get(PREDECESSOR_SET)).getHrefs();
+
+                Session session = getRepositorySession();
+                for (int i = 0; i < mergeFailed.length; i++) {
+                    // build version-href from each entry in the jcr:mergeFailed property
+                    Version version = (Version) session.getNodeByUUID(mergeFailed[i].getString());
+                    String href = this.getLocatorFromItem(version).getHref(true);
+
+                    // Test if that version has been removed from the merge-set.
+                    // thus indicating that the merge-conflict needs to be resolved.
+                    if (!mergeset.contains(href)) {
+                        // Test if the 'href' has been moved over to the
+                        // predecessor-set (thus 'doneMerge' is appropriate) or
+                        // if it is not present in the predecessor set and the
+                        // the conflict is resolved by 'cancelMerge'.
+                        if (predecSet.contains(href)) {
+                            n.doneMerge(version);
+                        } else {
+                            n.cancelMerge(version);
+                        }
+                    }
+                }
+                // adjust setProperty set
+                setProperties.remove(AUTO_MERGE_SET);
+                setProperties.remove(PREDECESSOR_SET);
+            } else {
+                // setPropertySet and removePropertySet do not ask for resolving merge conflicts */
+                log.debug("setProperties and removeProperties sets do not request for merge conflict resolution.");
+            }
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
+    /**
+     * Modify the labels present with the versions of this resource.
+     *
+     * @param labelInfo
+     * @throws DavException
+     * @see VersionHistory#addVersionLabel(String, String, boolean)
+     * @see VersionHistory#removeVersionLabel(String)
+     */
+    public void label(LabelInfo labelInfo) throws DavException {
+        if (labelInfo == null) {
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required.");
+        }
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+
+        try {
+            if (!isVersionControlled() || ((Node)item).isCheckedOut()) {
+                throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "A LABEL request may only be applied to a version-controlled, checked-in resource.");
+            }
+            DavResource[] resArr = this.getReferenceResources(CHECKED_IN);
+            if (resArr.length == 1 && resArr[0] instanceof VersionResource) {
+                ((VersionResource)resArr[0]).label(labelInfo);
+            } else {
+                throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "DAV:checked-in property on '" + getHref() + "' did not point to a single VersionResource.");
+            }
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
+    /**
+     * Returns the {@link VersionHistory} associated with the repository node.
+     * If the node is not versionable an exception is thrown.
+     *
+     * @return the {@link VersionHistoryResource} associated with this resource.
+     * @throws org.apache.jackrabbit.webdav.DavException
+     * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#getVersionHistory()
+     * @see javax.jcr.Node#getVersionHistory()
+     */
+    public VersionHistoryResource getVersionHistory() throws DavException {
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+
+        try {
+            VersionHistory vh = ((Node)item).getVersionHistory();
+            DavResourceLocator loc = getLocatorFromItem(vh);
+            return (VersionHistoryResource) createResourceFromLocator(loc);
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     * Define the set of reports supported by this resource.
+     *
+     * @see SupportedReportSetProperty
+     */
+    protected void initSupportedReports() {
+        super.initSupportedReports();
+        if (exists()) {
+	    supportedReports.addReportType(ReportType.LOCATE_BY_HISTORY);
+            if (this.isVersionControlled()) {
+            supportedReports.addReportType(ReportType.VERSION_TREE);
+	    }            
+        }
+    }
+
+    /**
+     * Fill the property set for this resource.
+     */
+    protected void initProperties() {
+        super.initProperties();
+        if (exists()) {
+            Node n = (Node)item;
+            // properties defined by RFC 3253 for version-controlled resources
+            if (isVersionControlled()) {
+                // workspace property already set in AbstractResource.initProperties()
+                try {
+                    // DAV:version-history (computed)
+                    String vhHref = getLocatorFromResourcePath(n.getVersionHistory().getPath()).getHref(true);
+                    properties.add(new HrefProperty(VERSION_HISTORY, vhHref, true));
+
+                    // DAV:auto-version property: there is no auto version, explicit CHECKOUT is required.
+                    properties.add(new DefaultDavProperty(AUTO_VERSION, null, false));
+
+                    String baseVHref = getLocatorFromResourcePath(n.getBaseVersion().getPath()).getHref(true);
+                    if (n.isCheckedOut()) {
+                        // DAV:checked-out property (protected)
+                        properties.add(new HrefProperty(CHECKED_OUT, baseVHref, true));
+
+                        // DAV:predecessors property
+                        if (n.hasProperty(PROP_PREDECESSORS)) {
+                            Value[] predec = n.getProperty(PROP_PREDECESSORS).getValues();
+                            addHrefProperty(PREDECESSOR_SET, predec, false);
+                        }
+                        // DAV:auto-merge-set property. NOTE: the DAV:merge-set
+                        // never occurs, because merging without bestEffort flag
+                        // being set results in an exception on failure.
+                        if (n.hasProperty(PROP_MERGEFAILED)) {
+                            ReferenceValue[] mergeFailed = (ReferenceValue[]) n.getProperty(PROP_MERGEFAILED).getValues();
+                            addHrefProperty(AUTO_MERGE_SET, mergeFailed, false);
+                        }
+                        // todo: checkout-fork, checkin-fork
+                    } else {
+                        // DAV:checked-in property (protected)
+                        properties.add(new HrefProperty(CHECKED_IN, baseVHref, true));
+                    }
+                } catch (RepositoryException e) {
+                    log.error(e.getMessage());
+                }
+            }
+        }
+    }
+
+    /**
+     * Add a {@link org.apache.jackrabbit.webdav.property.HrefProperty} with the specified property name and values.
+     *
+     * @param name
+     * @param values Array of {@link ReferenceValue}s.
+     * @param isProtected
+     * @throws javax.jcr.ValueFormatException
+     * @throws IllegalStateException
+     * @throws javax.jcr.RepositoryException
+     */
+    private void addHrefProperty(DavPropertyName name, Value[] values,
+                                 boolean isProtected)
+            throws ValueFormatException, IllegalStateException, RepositoryException {
+        Node[] nodes = new Node[values.length];
+        for (int i = 0; i < values.length; i++) {
+            nodes[i] = getRepositorySession().getNodeByUUID(values[i].getString());
+        }
+        addHrefProperty(name, nodes, isProtected);
+    }
+
+    /**
+     * @return true, if this resource represents an existing repository node
+     * that has the mixin nodetype 'mix:versionable' set.
+     */
+    private boolean isVersionControlled() {
+        boolean vc = false;
+        if (exists()) {
+            try {
+                vc = ((Node) item).isNodeType("mix:versionable");
+            } catch (RepositoryException e) {
+                log.warn(e.getMessage());
+            }
+        }
+        return vc;
+    }
+
+    /**
+     * 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();
+                    String itemPath = e.getPath();
+                    DavResourceLocator loc = getLocatorFromResourcePath(itemPath);
+                    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());
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

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

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

Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/VersionHistoryItemCollection.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/VersionHistoryItemCollection.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/VersionHistoryItemCollection.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/VersionHistoryItemCollection.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,136 @@
+/*
+ * 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.version;
+
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.webdav.version.*;
+import org.apache.jackrabbit.webdav.property.HrefProperty;
+import org.apache.jackrabbit.webdav.spi.ItemResourceConstants;
+import org.apache.jackrabbit.webdav.spi.JcrDavException;
+import org.apache.jackrabbit.webdav.spi.DefaultItemCollection;
+import org.apache.jackrabbit.webdav.*;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionIterator;
+import java.util.ArrayList;
+
+/**
+ * <code>VersionHistoryItemCollection</code> represents a JCR version history.
+ *
+ * @see VersionHistory
+ */
+public class VersionHistoryItemCollection extends DefaultItemCollection
+        implements VersionHistoryResource {
+
+    private static Logger log = Logger.getLogger(VersionHistoryItemCollection.class);
+
+    /**
+     * Create a new <code>VersionHistoryItemCollection</code> resource.
+     *
+     * @param resourcePath
+     * @param session
+     * @param factory
+     */
+    public VersionHistoryItemCollection(DavResourceLocator resourcePath, DavSession session, DavResourceFactory factory) {
+        super(resourcePath, session, factory);
+        if (item == null || !(item instanceof VersionHistory)) {
+            throw new IllegalArgumentException("VersionHistory item expected.");
+        }
+    }
+
+    //----------------------------------------------< DavResource interface >---
+    /**
+     * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods()
+     */
+    public String getSupportedMethods() {
+        StringBuffer sb = new StringBuffer(ItemResourceConstants.METHODS);
+        sb.append(", ").append(VersionHistoryResource.METHODS);
+        return sb.toString();
+    }
+
+    /**
+     * Removing a version resource is achieved by calling <code>removeVersion</code>
+     * on the versionhistory item this version belongs to.
+     *
+     * @throws DavException if the version does not exist or if an error occurs
+     * while deleting.
+     * @see DavResource#removeMember(org.apache.jackrabbit.webdav.DavResource)
+     */
+    public void removeMember(DavResource member) throws DavException {
+        if (exists()) {
+            VersionHistory versionHistory = (VersionHistory) item;
+            try {
+                versionHistory.removeVersion(getResourceName(member.getHref(), true));
+            } catch (RepositoryException e) {
+                throw new JcrDavException(e);
+            }
+        } else {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+    }
+    //-----------------------------------< VersionHistoryResource interface >---
+    /**
+     * Return an array of {@link VersionResource}s representing all versions
+     * present in the underlaying JCR version history.
+     *
+     * @return array of {@link VersionResource}s representing all versions
+     * present in the underlaying JCR version history.
+     * @throws DavException
+     * @see org.apache.jackrabbit.webdav.version.VersionHistoryResource#getVersions()
+     */
+    public VersionResource[] getVersions() throws DavException {
+        try {
+            VersionIterator vIter = ((VersionHistory)item).getAllVersions();
+            ArrayList l = new ArrayList();
+            while (vIter.hasNext()) {
+                DavResourceLocator versionLoc = getLocatorFromItem(vIter.nextVersion());
+                DavResource vr = createResourceFromLocator(versionLoc);
+                l.add(vr);
+            }
+            return (VersionResource[]) l.toArray(new VersionResource[l.size()]);
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+    
+    //--------------------------------------------------------------------------
+    /**
+     * Fill the property set for this resource.
+     */
+    protected void initProperties() {
+        super.initProperties();
+
+        // change resourcetype defined by default item collection
+        properties.add(new ResourceType(ResourceType.VERSION_HISTORY));
+
+        // required root-version property for version-history resource
+        try {
+            String rootVersionResourcePath = ((VersionHistory)item).getRootVersion().getPath();
+            properties.add(new HrefProperty(VersionHistoryResource.ROOT_VERSION, getLocatorFromResourcePath(rootVersionResourcePath).getHref(true), true));
+        } catch (RepositoryException e) {
+            log.error(e.getMessage());
+        }
+
+        // required, protected version-set property for version-history resource
+        try {
+            VersionIterator vIter = ((VersionHistory)item).getAllVersions();
+            addHrefProperty(VersionHistoryResource.VERSION_SET, vIter, true);
+        } catch (RepositoryException e) {
+            log.error(e.getMessage());
+        }
+    }
+}
\ No newline at end of file

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

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

Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/VersionItemCollection.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/VersionItemCollection.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/VersionItemCollection.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/VersionItemCollection.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,202 @@
+/*
+ * 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.version;
+
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.webdav.spi.JcrDavException;
+import org.apache.jackrabbit.webdav.spi.ItemResourceConstants;
+import org.apache.jackrabbit.webdav.spi.DefaultItemCollection;
+import org.apache.jackrabbit.webdav.*;
+import org.apache.jackrabbit.webdav.property.*;
+import org.apache.jackrabbit.webdav.version.*;
+import org.apache.jackrabbit.webdav.version.report.ReportType;
+import org.jdom.Element;
+
+import javax.jcr.*;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * <code>VersionItemCollection</code> represents a JCR version.
+ *
+ * @see Version
+ */
+public class VersionItemCollection extends DefaultItemCollection
+        implements VersionResource {
+
+    private static Logger log = Logger.getLogger(VersionItemCollection.class);
+
+    /**
+     * Create a new <code>VersionItemCollection</code>.
+     *
+     * @param locator
+     * @param session
+     * @param factory
+     */
+    public VersionItemCollection(DavResourceLocator locator, DavSession session, DavResourceFactory factory) {
+        super(locator, session, factory);
+        if (item == null || !(item instanceof Version)) {
+            throw new IllegalArgumentException("Version item expected.");
+        }
+    }
+
+    //----------------------------------------------< DavResource interface >---
+    /**
+     * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods()
+     */
+    public String getSupportedMethods() {
+        StringBuffer sb = new StringBuffer(ItemResourceConstants.METHODS);
+        sb.append(", ").append(VersionResource.METHODS);
+        return sb.toString();
+    }
+
+    //------------------------------------------< VersionResource interface >---
+    /**
+     * Modify the labels defined for the underlaying repository version.
+     *
+     * @param labelInfo
+     * @throws DavException
+     * @see VersionResource#label(org.apache.jackrabbit.webdav.version.LabelInfo)
+     * @see VersionHistory#addVersionLabel(String, String, boolean)
+     * @see VersionHistory#removeVersionLabel(String)
+     */
+    public void label(LabelInfo labelInfo) throws DavException {
+        if (labelInfo == null) {
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required.");
+        }
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+        try {
+            VersionHistory vh = getVersionHistoryItem();
+            if (labelInfo.getType() == LabelInfo.TYPE_REMOVE) {
+                vh.removeVersionLabel(labelInfo.getLabelName());
+            } else if (labelInfo.getType() == LabelInfo.TYPE_ADD) {
+                // ADD: only add if not yet existing
+                vh.addVersionLabel(item.getName(), labelInfo.getLabelName(), false);
+            } else {
+                // SET: move label if already existing
+                vh.addVersionLabel(item.getName(), labelInfo.getLabelName(), true);
+            }
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
+    /**
+     * Returns the {@link VersionHistory} associated with the repository version.
+     * Note: in contrast to a versionable node, the version history of a version
+     * item is always represented by its nearest ancestor.
+     *
+     * @return the {@link VersionHistoryResource} associated with this resource.
+     * @throws org.apache.jackrabbit.webdav.DavException
+     * @see org.apache.jackrabbit.webdav.version.VersionResource#getVersionHistory()
+     * @see javax.jcr.Item#getParent()
+     */
+    public VersionHistoryResource getVersionHistory() throws DavException {
+        if (!exists()) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        }
+
+        try {
+            VersionHistory vh = getVersionHistoryItem();
+            DavResourceLocator loc = getLocatorFromItem(vh);
+            return (VersionHistoryResource) createResourceFromLocator(loc);
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
+    /**
+     * Return the nearest ancestor of the underlaying repository item.
+     *
+     * @return nearest ancestor of the underlaying repository item.
+     * @throws RepositoryException
+     */
+    private VersionHistory getVersionHistoryItem() throws RepositoryException {
+        return (VersionHistory) item.getParent();
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     * Define the set of reports supported by this resource.
+     *
+     * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty
+     */
+    protected void initSupportedReports() {
+        super.initSupportedReports();
+        if (exists()) {
+            supportedReports.addReportType(ReportType.VERSION_TREE);
+        }
+    }
+
+    /**
+     * Fill the property set for this resource.
+     */
+    protected void initProperties() {
+        super.initProperties();
+
+        if (exists()) {
+            Version v = (Version)item;
+            // created and creationDate properties
+            try {
+                String creationDate = DavConstants.creationDateFormat.format(v.getCreated().getTime());
+                // jcr specific 'created' property
+                properties.add(new DefaultDavProperty(CREATED, creationDate));
+                // replace dummy creation date from default collection
+                properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, creationDate));
+
+                // required, protected DAV:version-name property
+                properties.add(new DefaultDavProperty(VERSION_NAME, v.getName(), true));
+
+                // required, protected DAV:label-name-set property
+                String[] labels = getVersionHistoryItem().getVersionLabels(v);
+                Element[] labelElems = new Element[labels.length];
+                for (int i = 0; i < labels.length; i++) {
+                    labelElems[i] = new Element(DeltaVConstants.XML_LABEL_NAME, NAMESPACE).setText(labels[i]);
+                }
+                properties.add(new DefaultDavProperty(LABEL_NAME_SET, labelElems, true));
+
+                // required DAV:predecessor-set (protected) and DAV:successor-set (computed) properties
+                addHrefProperty(VersionResource.PREDECESSOR_SET, v.getPredecessors(), true);
+                addHrefProperty(SUCCESSOR_SET, v.getSuccessors(), true);
+
+                // required DAV:version-history (computed) property
+                String vhPath = getVersionHistoryItem().getPath();
+                properties.add(new HrefProperty(VersionResource.VERSION_HISTORY, getLocatorFromResourcePath(vhPath).getHref(true), true));
+
+                // required DAV:checkout-set (computed) property
+                PropertyIterator it = v.getReferences();
+                List nodeList = new ArrayList();
+                while (it.hasNext()) {
+                    Property p = it.nextProperty();
+                    if (PROP_BASEVERSION.equals(p.getName())) {
+                        Node n = p.getParent();
+                        if (n.isCheckedOut()) {
+                           nodeList.add(n);
+                        }
+                    }
+                }
+                addHrefProperty(CHECKOUT_SET, (Node[]) nodeList.toArray(new Node[nodeList.size()]), true);
+
+            } catch (RepositoryException e) {
+                log.error(e.getMessage());
+            }
+        }
+    }
+}
\ No newline at end of file

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

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

Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/package.html
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/package.html?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/package.html (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/package.html Sun Mar  6 06:02:39 2005
@@ -0,0 +1,9 @@
+<body>
+Contains JCR specific implementations for the following interfaces:
+<ul>
+<li>VersionableResource</li>
+<li>VersionControlledResource</li>
+<li>VersionResource</li>
+<li>VersionHistoryResource</li>
+</ul>
+</body>
\ No newline at end of file

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

Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/report/ExportViewReport.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/report/ExportViewReport.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/report/ExportViewReport.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/report/ExportViewReport.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,156 @@
+/*
+ * 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.version.report;
+
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.webdav.spi.ItemResourceConstants;
+import org.apache.jackrabbit.webdav.spi.JcrDavException;
+import org.apache.jackrabbit.webdav.version.report.*;
+import org.apache.jackrabbit.webdav.version.DeltaVResource;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavSession;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.util.Text;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+
+import javax.jcr.Session;
+import javax.jcr.RepositoryException;
+import javax.jcr.PathNotFoundException;
+import java.io.*;
+
+/**
+ * <code>ExportViewReport</code> handles REPORT requests for the 'exportview'
+ * report. The 'exportview' report is used to export
+ * {@link Session#exportDocView(String, java.io.OutputStream, boolean, boolean) DocView}
+ * and {@link Session#exportSysView(String, java.io.OutputStream, boolean, boolean) SysView}
+ * of the {@link javax.jcr.Item item} represented by the requested resource.
+ * <p/>
+ * The request body must contain a jcr:exportview element:
+ * <pre>
+ * &lt;!ELEMENT exportview  ( (sysview | docview)?, skipbinary?, norecurse ) &gt;
+ * &lt;!ELEMENT sysview EMPTY &gt;
+ * &lt;!ELEMENT docview EMPTY &gt;
+ * &lt;!ELEMENT skipbinary EMPTY &gt;
+ * &lt;!ELEMENT norecurse EMPTY &gt;
+ * </pre>
+ * If no view type is specified the DocView is generated.
+ */
+public class ExportViewReport implements Report {
+
+    private static Logger log = Logger.getLogger(ExportViewReport.class);
+
+    private static final String REPORT_NAME = "exportview";
+
+    /**
+     * The exportview report type
+     */
+    public static final ReportType EXPORTVIEW_REPORT = ReportType.register(REPORT_NAME, ItemResourceConstants.NAMESPACE, ExportViewReport.class);
+
+    private String absPath;
+    private Session session;
+    private ReportInfo info;
+
+    /**
+     * Returns {@link #EXPORTVIEW_REPORT} report type.
+     *
+     * @return {@link #EXPORTVIEW_REPORT}
+     * @see org.apache.jackrabbit.webdav.version.report.Report#getType()
+     */
+    public ReportType getType() {
+        return EXPORTVIEW_REPORT;
+    }
+
+    /**
+     * @param resource The resource this report is generated from. NOTE: the
+     * {@link org.apache.jackrabbit.webdav.DavResource#getResourcePath() resource path}
+     * of the resource is used as 'absPath' argument for exporting the specified
+     * view.
+     * @throws IllegalArgumentException if the resource is <code>null</code> or
+     * if the session object provided with the resource is <code>null</code>.
+     * @see Report#setResource(org.apache.jackrabbit.webdav.version.DeltaVResource)
+     */
+    public void setResource(DeltaVResource resource) {
+        if (resource == null) {
+            throw new IllegalArgumentException("Resource must not be null.");
+        }
+        DavSession davSession = resource.getSession();
+        if (davSession == null || davSession.getRepositorySession() == null) {
+            throw new IllegalArgumentException("The resource must provide a non-null session object in order to create the jcr:nodetypes report.");
+        }
+        session = davSession.getRepositorySession();
+        absPath = resource.getResourcePath();
+    }
+
+    /**
+     * @param info
+     * @throws IllegalArgumentException if the specified {@link ReportInfo info}
+     * object does not contain a jcr:exportview element.
+     * @see Report#setInfo(org.apache.jackrabbit.webdav.version.report.ReportInfo)
+     */
+    public void setInfo(ReportInfo info) {
+        if (info == null || !REPORT_NAME.equals(info.getReportElement().getName())) {
+            throw new IllegalArgumentException("jcr:exportview element expected.");
+        }
+        this.info = info;
+    }
+
+    /**
+     * Creates a Xml document from the generated view.
+     *
+     * @return Xml document representing the output of the specified view.
+     * @throws DavException if the report document could not be created.
+     * @see org.apache.jackrabbit.webdav.version.report.Report#toXml()
+     */
+    public Document toXml() throws DavException {
+        Element reportElem = info.getReportElement();
+        boolean skipBinary = reportElem.getChild("skipbinary", ItemResourceConstants.NAMESPACE) != null;
+        boolean noRecurse = reportElem.getChild("norecurse", ItemResourceConstants.NAMESPACE) != null;
+
+        try {
+            // create tmpFile in default system-tmp directory
+            String prefix = "_tmp_" + Text.getLabel(absPath);
+            File tmpfile = File.createTempFile(prefix, null, null);
+            tmpfile.deleteOnExit();
+            FileOutputStream out = new FileOutputStream(tmpfile);
+
+            if (reportElem.getChild("sysview", ItemResourceConstants.NAMESPACE) != null) {
+                session.exportSysView(absPath, out, skipBinary, noRecurse);
+            } else {
+                // default is docview
+                session.exportDocView(absPath, out, skipBinary, noRecurse);
+            }
+            out.close();
+
+            SAXBuilder builder = new SAXBuilder(false);
+            InputStream in = new FileInputStream(tmpfile);
+            return builder.build(in);
+
+        } catch (FileNotFoundException e) {
+            throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR);
+        } catch (IOException e) {
+            throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR);
+        } catch (PathNotFoundException e) {
+            throw new DavException(DavServletResponse.SC_NOT_FOUND);
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        } catch (JDOMException e) {
+            throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR);
+        }
+    }
+}
\ No newline at end of file

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

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

Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/report/LocateByUuidReport.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/report/LocateByUuidReport.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/report/LocateByUuidReport.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/spi/version/report/LocateByUuidReport.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,122 @@
+/*
+ * 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.version.report;
+
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.webdav.version.report.*;
+import org.apache.jackrabbit.webdav.version.DeltaVResource;
+import org.apache.jackrabbit.webdav.spi.ItemResourceConstants;
+import org.apache.jackrabbit.webdav.spi.JcrDavException;
+import org.apache.jackrabbit.webdav.*;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.jdom.Document;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+/**
+ * <code>LocateByUuidReport</code> handles REPORT requests for the 'locate-by-uuid'
+ * report.
+ * <p/>
+ * The request body must be a 'jcr:locate-by-uuid' XML element:
+ * <pre>
+ * &lt;!ELEMENT locate-by-uuid ( href , prop? ) &gt;
+ * </pre>
+ * The response to a successful report request will be a Multi-Status response.
+ */
+public class LocateByUuidReport implements Report {
+
+    private static Logger log = Logger.getLogger(LocateByUuidReport.class);
+
+    private static final String REPORT_NAME = "locate-by-uuid";
+
+    /**
+     * The exportview report type
+     */
+    public static final ReportType LOCATE_BY_UUID_REPORT = ReportType.register(REPORT_NAME, ItemResourceConstants.NAMESPACE, LocateByUuidReport.class);
+
+    private DeltaVResource resource;
+    private ReportInfo info;
+
+    /**
+     * Returns {@link #LOCATE_BY_UUID_REPORT} report type.
+     *
+     * @return {@link #LOCATE_BY_UUID_REPORT}
+     * @see org.apache.jackrabbit.webdav.version.report.Report#getType()
+     */
+    public ReportType getType() {
+        return LOCATE_BY_UUID_REPORT;
+    }
+
+    /**
+     * @param resource
+     * @throws IllegalArgumentException if the resource is <code>null</code> or
+     * if the session object provided with the resource is <code>null</code>.
+     * @see Report#setResource(org.apache.jackrabbit.webdav.version.DeltaVResource)
+     */
+    public void setResource(DeltaVResource resource) {
+        if (resource == null) {
+            throw new IllegalArgumentException("Resource must not be null.");
+        }
+        DavSession davSession = resource.getSession();
+        if (davSession == null || davSession.getRepositorySession() == null) {
+            throw new IllegalArgumentException("The resource must provide a non-null session object in order to create the jcr:nodetypes report.");
+        }
+        this.resource = resource;
+    }
+
+    /**
+     * @param info
+     * @throws IllegalArgumentException if the specified {@link ReportInfo info}
+     * object does not contain a jcr:exportview element.
+     * @see Report#setInfo(org.apache.jackrabbit.webdav.version.report.ReportInfo)
+     */
+    public void setInfo(ReportInfo info) {
+        if (info == null || !REPORT_NAME.equals(info.getReportElement().getName())) {
+            throw new IllegalArgumentException("jcr:locate-by-uuid element expected.");
+        }
+        this.info = info;
+    }
+
+    /**
+     * Creates a Xml document from the generated view.
+     *
+     * @return Xml document representing the output of the specified view.
+     * @throws DavException if the report document could not be created.
+     * @see org.apache.jackrabbit.webdav.version.report.Report#toXml()
+     */
+    public Document toXml() throws DavException {
+        String uuid = info.getReportElement().getChildText(DavConstants.XML_HREF, DavConstants.NAMESPACE);
+        DavPropertyNameSet propNameSet = info.getPropertyNameSet();
+
+        try {
+            DavSession session = resource.getSession();
+            DavResourceLocator resourceLoc = resource.getLocator();
+
+            Node n = session.getRepositorySession().getNodeByUUID(uuid);
+
+            DavResourceLocator loc = resourceLoc.getFactory().createResourceLocator(resourceLoc.getPrefix(), resourceLoc.getWorkspacePath(), n.getPath());
+            DavResource res = resource.getFactory().createResource(loc, session);
+
+            MultiStatus ms = new MultiStatus();
+            ms.addResourceProperties(res, propNameSet, 0);
+            return ms.toXml();
+
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+}
\ No newline at end of file

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

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



Mime
View raw message