You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2006/12/05 13:46:16 UTC

svn commit: r482627 - in /jackrabbit/trunk: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/ jackrabbit-webapp/ jackrabbit-webapp/src/mai...

Author: mreutegg
Date: Tue Dec  5 04:46:14 2006
New Revision: 482627

URL: http://svn.apache.org/viewvc?view=rev&rev=482627
Log:
Work in progress
- Removed is-local flag from event bundle response and added transaction id which is equal to the lock token that was used to save changes.
- Added TransactionListener. SubscriptionManagerImpl now listens on the TxLockManagerImpl for transaction commits and registers special EventListeners for a short period of time to associate the lockToken / transactionId with an event bundle.
- Remove SubscriptionImpl as event listener when subscription expires
- Update currentVersion to 1.2-SNAPSHOT

Added:
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java
    jackrabbit/trunk/jackrabbit-webapp/project.xml
    jackrabbit/trunk/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java
    jackrabbit/trunk/jackrabbit-webdav/project.xml
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java?view=diff&rev=482627&r1=482626&r2=482627
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java Tue Dec  5 04:46:14 2006
@@ -20,6 +20,10 @@
 import org.apache.jackrabbit.webdav.DavException;
 import org.apache.jackrabbit.webdav.DavResourceLocator;
 import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.transaction.TransactionResource;
+import org.apache.jackrabbit.webdav.jcr.transaction.TransactionListener;
+import org.apache.jackrabbit.webdav.jcr.JcrDavSession;
+import org.apache.jackrabbit.webdav.jcr.JcrDavException;
 import org.apache.jackrabbit.webdav.observation.EventBundle;
 import org.apache.jackrabbit.webdav.observation.EventDiscovery;
 import org.apache.jackrabbit.webdav.observation.EventType;
@@ -36,9 +40,11 @@
 import org.w3c.dom.Element;
 
 import javax.jcr.RepositoryException;
+import javax.jcr.Session;
 import javax.jcr.observation.Event;
 import javax.jcr.observation.EventIterator;
 import javax.jcr.observation.EventListener;
+import javax.jcr.observation.ObservationManager;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -92,6 +98,7 @@
     private final DavResourceLocator locator;
     private final String subscriptionId = UUID.randomUUID().toString();
     private final List eventBundles = new ArrayList();
+    private final ObservationManager obsMgr;
 
     /**
      * Create a new <code>Subscription</code> with the given {@link SubscriptionInfo}
@@ -99,10 +106,19 @@
      *
      * @param info
      * @param resource
+     * @throws DavException if resource is not based on a JCR repository or
+     * the repository does not support observation.
      */
-    public SubscriptionImpl(SubscriptionInfo info, ObservationResource resource) {
+    public SubscriptionImpl(SubscriptionInfo info, ObservationResource resource)
+            throws DavException {
         setInfo(info);
         locator = resource.getLocator();
+        Session s = JcrDavSession.getRepositorySession(resource.getSession());
+        try {
+            obsMgr = s.getWorkspace().getObservationManager();
+        } catch (RepositoryException e) {
+            throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e);
+        }
     }
 
     //-------------------------------------------------------< Subscription >---
@@ -261,19 +277,82 @@
         return ed;
     }
 
+    /**
+     * Creates a new transaction listener for the scope of a transaction
+     * commit (save call).
+     * @return a transaction listener for this subscription.
+     */
+    TransactionListener createTransactionListener() {
+        if (info.isNoLocal()) {
+            // a subscription which is not interested in local changes does
+            // not need the transaction id
+            return new TransactionEvent() {
+                public void onEvent(EventIterator events) {
+                    // ignore
+                }
+
+                public void beforeCommit(TransactionResource resource, String lockToken) {
+                    // ignore
+                }
+
+                public void afterCommit(TransactionResource resource,
+                                        String lockToken,
+                                        boolean success) {
+                    // ignore
+                }
+            };
+        } else {
+            return new TransactionEvent();
+        }
+    }
+
+    /**
+     * Suspend this subscription. This call will remove this subscription as
+     * event listener from the observation manager.
+     */
+    void suspend() throws DavException {
+        try {
+            obsMgr.removeEventListener(this);
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
+    /**
+     * Resumes this subscription. This call will register this subscription
+     * again as event listener to the observation manager.
+     */
+    void resume() throws DavException {
+        try {
+            obsMgr.addEventListener(this, getJcrEventTypes(),
+                    getLocator().getRepositoryPath(), isDeep(), getUuidFilters(),
+                    getNodetypeNameFilters(), isNoLocal());
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
     //--------------------------------------------< EventListener interface >---
     /**
      * Records the events passed as a new event bundle in order to make them
-     * available with the next {@link #discoverEvents()} request.
+     * available with the next {@link #discoverEvents()} request. If this
+     * subscription is expired it will remove itself as listener from the
+     * observation manager.
      *
      * @param events to be recorded.
      * @see EventListener#onEvent(EventIterator)
      * @see #discoverEvents()
      */
     public synchronized void onEvent(EventIterator events) {
-        // TODO: correct not to accept events after expiration? without unsubscribing?
         if (!isExpired()) {
             eventBundles.add(new EventBundleImpl(events));
+        } else {
+            // expired -> unsubscribe
+            try {
+                obsMgr.removeEventListener(this);
+            } catch (RepositoryException e) {
+                log.warn("Exception while unsubscribing: " + e);
+            }
         }
     }
 
@@ -372,13 +451,22 @@
 
         private final EventIterator events;
 
+        private final String transactionId;
+
         private EventBundleImpl(EventIterator events) {
+            this(events, null);
+        }
+
+        private EventBundleImpl(EventIterator events, String transactionId) {
             this.events = events;
+            this.transactionId = transactionId;
         }
 
         public Element toXml(Document document) {
             Element bundle = DomUtil.createElement(document, XML_EVENTBUNDLE, NAMESPACE);
-            DomUtil.setAttribute(bundle, XML_EVENT_IS_LOCAL, NAMESPACE, Boolean.toString(!info.isNoLocal()));
+            if (transactionId != null) {
+                DomUtil.setAttribute(bundle, XML_EVENT_TRANSACTION_ID, NAMESPACE, transactionId);
+            }
             while (events.hasNext()) {
                 Event event = events.nextEvent();
                 Element eventElem = DomUtil.addChildElement(bundle, XML_EVENT, NAMESPACE);
@@ -399,6 +487,66 @@
                 DomUtil.addChildElement(eventElem, XML_EVENTUSERID, NAMESPACE, event.getUserID());
             }
             return bundle;
+        }
+    }
+
+    //----------------------------< TransactionEvent >------------------------
+
+    /**
+     * Implements a transaction event which listenes for events during a save
+     * call on the repository.
+     */
+    private class TransactionEvent implements EventListener, TransactionListener {
+
+        private String transactionId;
+
+        /**
+         * {@inheritDoc}
+         */
+        public void onEvent(EventIterator events) {
+            String tId = transactionId;
+            if (tId == null) {
+                tId = UUID.randomUUID().toString();
+            }
+            eventBundles.add(new EventBundleImpl(events, tId));
+        }
+
+        //-----------------------------< TransactionListener >------------------
+
+        /**
+         * {@inheritDoc}
+         */
+        public void beforeCommit(TransactionResource resource, String lockToken) {
+            try {
+                transactionId = lockToken;
+                obsMgr.addEventListener(this, getJcrEventTypes(),
+                        getLocator().getRepositoryPath(), isDeep(), getUuidFilters(),
+                        getNodetypeNameFilters(), isNoLocal());
+                // suspend the subscription
+                suspend();
+            } catch (RepositoryException e) {
+                log.warn("Unable to register TransactionListener: " + e);
+            } catch (DavException e) {
+                log.warn("Unable to register TransactionListener: " + e);
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void afterCommit(TransactionResource resource,
+                                String lockToken,
+                                boolean success) {
+            try {
+                // resume the subscription
+                resume();
+                // remove this transaction event
+                obsMgr.removeEventListener(this);
+            } catch (RepositoryException e) {
+                log.warn("Unable to remove listener: " + e);
+            } catch (DavException e) {
+                log.warn("Unable to resume Subscription: " + e);
+            }
         }
     }
 }

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java?view=diff&rev=482627&r1=482626&r2=482627
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java Tue Dec  5 04:46:14 2006
@@ -19,8 +19,10 @@
 import org.apache.jackrabbit.webdav.DavException;
 import org.apache.jackrabbit.webdav.DavResourceLocator;
 import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.transaction.TransactionResource;
 import org.apache.jackrabbit.webdav.jcr.JcrDavException;
 import org.apache.jackrabbit.webdav.jcr.JcrDavSession;
+import org.apache.jackrabbit.webdav.jcr.transaction.TransactionListener;
 import org.apache.jackrabbit.webdav.observation.EventDiscovery;
 import org.apache.jackrabbit.webdav.observation.ObservationResource;
 import org.apache.jackrabbit.webdav.observation.Subscription;
@@ -39,6 +41,9 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
 
 /**
  * <code>SubscriptionManager</code> collects all subscriptions requested, handles
@@ -46,7 +51,7 @@
  * present on a given resource as well as events for an specific subscription.
  */
 // todo: make sure all expired subscriptions are removed!
-public class SubscriptionManagerImpl implements SubscriptionManager {
+public class SubscriptionManagerImpl implements SubscriptionManager, TransactionListener {
 
     private static Logger log = LoggerFactory.getLogger(SubscriptionManager.class);
 
@@ -55,6 +60,8 @@
      */
     private final SubscriptionMap subscriptions = new SubscriptionMap();
 
+    private final Map transactionListenerById = new HashMap();
+
     /**
      * Retrieve the {@link org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery}
      * object for the given resource. Note, that the discovery object will be empty
@@ -227,6 +234,37 @@
         return JcrDavSession.getRepositorySession(resource.getSession());
     }
 
+    //---------------------------< TransactionListener >------------------------
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized void beforeCommit(TransactionResource resource,
+                                          String lockToken) {
+        // suspend regular subscriptions during a commit
+        List transactionListeners = new ArrayList();
+        for (Iterator it = subscriptions.iterator(); it.hasNext(); ) {
+            SubscriptionImpl sub = (SubscriptionImpl) it.next();
+            TransactionListener tl = sub.createTransactionListener();
+            tl.beforeCommit(resource, lockToken);
+            transactionListeners.add(tl);
+        }
+        transactionListenerById.put(lockToken, transactionListeners);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void afterCommit(TransactionResource resource, String lockToken, boolean success) {
+        List transactionListeners = (List) transactionListenerById.remove(lockToken);
+        if (transactionListeners != null) {
+            for (Iterator it = transactionListeners.iterator(); it.hasNext(); ) {
+                TransactionListener txListener = (TransactionListener) it.next();
+                txListener.afterCommit(resource, lockToken, success);
+            }
+        }
+    }
+
     //----------------------------------------------< private inner classes >---
     /**
      * Private inner class wrapping around an <code>Subscription</code> as
@@ -269,6 +307,10 @@
             return (Subscription) subscriptions.get(subscriptionId);
         }
 
+        private Iterator iterator() {
+            return subscriptions.values().iterator();
+        }
+
         private void put(String subscriptionId, SubscriptionImpl subscription) {
             subscriptions.put(subscriptionId, subscription);
             DavResourceLocator key = subscription.getLocator();
@@ -305,4 +347,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}

Added: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.java?view=auto&rev=482627
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.java Tue Dec  5 04:46:14 2006
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.jcr.transaction;
+
+import org.apache.jackrabbit.webdav.transaction.TransactionResource;
+
+/**
+ * <code>TransactionListener</code> provides callbacks when a transaction
+ * is committed.
+ */
+public interface TransactionListener {
+
+    /**
+     * This method is called right before a transaction is committed.
+     *
+     * @param resource the transaction resource which will be committed.
+     * @param lockToken the lock token
+     */
+    public void beforeCommit(TransactionResource resource, String lockToken);
+
+    /**
+     * This method is called after the commit has been executed.
+     *
+     * @param resource the transaction resource which had been committed.
+     * @param lockToken the lock token.
+     * @param success if the commit was successful.
+     */
+    public void afterCommit(TransactionResource resource, String lockToken, boolean success);
+}

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

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java?view=diff&rev=482627&r1=482626&r2=482627
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java Tue Dec  5 04:46:14 2006
@@ -35,6 +35,7 @@
 import org.apache.jackrabbit.webdav.transaction.TransactionResource;
 import org.apache.jackrabbit.webdav.transaction.TxActiveLock;
 import org.apache.jackrabbit.webdav.transaction.TxLockManager;
+import org.apache.commons.collections.set.MapBackedSet;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -47,6 +48,8 @@
 import javax.transaction.xa.Xid;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Set;
+import java.util.IdentityHashMap;
 
 /**
  * <code>TxLockManagerImpl</code> manages locks with locktype
@@ -67,6 +70,8 @@
 
     private TransactionMap map = new TransactionMap();
 
+    private Set listeners = MapBackedSet.decorate(new IdentityHashMap());
+
     /**
      * Create a new lock.
      *
@@ -212,7 +217,25 @@
             throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction lock for resource '" + resource.getResourcePath() + "' was already expired.");
         } else {
             if (lockInfo.isCommit()) {
-                tx.commit(resource);
+                TransactionListener[] txListeners;
+                synchronized (listeners) {
+                    txListeners = (TransactionListener[]) listeners.toArray(new TransactionListener[0]);
+                }
+                for (int i = 0; i < txListeners.length; i++) {
+                    txListeners[i].beforeCommit(resource, lockToken);
+                }
+                DavException ex = null;
+                try {
+                    tx.commit(resource);
+                } catch (DavException e) {
+                    ex = e;
+                }
+                for (int i = 0; i < txListeners.length; i++) {
+                    txListeners[i].afterCommit(resource, lockToken, ex == null);
+                }
+                if (ex != null) {
+                    throw ex;
+                }
             } else {
                 tx.rollback(resource);
             }
@@ -271,6 +294,28 @@
             }
         }
         return lock;
+    }
+
+    //-----------------------------< listener support >-------------------------
+
+    /**
+     * Adds a transaction listener to this <code>TxLockManager</code>.
+     * @param listener the listener to add.
+     */
+    public void addTransactionListener(TransactionListener listener) {
+        synchronized (listeners) {
+            listeners.add(listener);
+        }
+    }
+
+    /**
+     * Removes a transaction listener from this <code>TxLockManager</code>.
+     * @param listener the listener to remove.
+     */
+    public void removeTransactionListener(TransactionListener listener) {
+        synchronized (listeners) {
+            listeners.remove(listener);
+        }
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-webapp/project.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webapp/project.xml?view=diff&rev=482627&r1=482626&r2=482627
==============================================================================
--- jackrabbit/trunk/jackrabbit-webapp/project.xml (original)
+++ jackrabbit/trunk/jackrabbit-webapp/project.xml Tue Dec  5 04:46:14 2006
@@ -24,7 +24,7 @@
     <artifactId>jackrabbit-webapp</artifactId>
     
     <name>Jackrabbit WebApplication</name>
-    <currentVersion>1.1-SNAPSHOT</currentVersion>
+    <currentVersion>1.2-SNAPSHOT</currentVersion>
     <inceptionYear>2005</inceptionYear>
     <package>org.apache.jackrabbit.*</package>
     

Modified: jackrabbit/trunk/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java?view=diff&rev=482627&r1=482626&r2=482627
==============================================================================
--- jackrabbit/trunk/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java (original)
+++ jackrabbit/trunk/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java Tue Dec  5 04:46:14 2006
@@ -111,6 +111,7 @@
 
         txMgr = new TxLockManagerImpl();
         subscriptionMgr = new SubscriptionManagerImpl();
+        txMgr.addTransactionListener((SubscriptionManagerImpl) subscriptionMgr);
 
         // todo: ev. make configurable
         resourceFactory = new DavResourceFactoryImpl(txMgr, subscriptionMgr);

Modified: jackrabbit/trunk/jackrabbit-webdav/project.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/project.xml?view=diff&rev=482627&r1=482626&r2=482627
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/project.xml (original)
+++ jackrabbit/trunk/jackrabbit-webdav/project.xml Tue Dec  5 04:46:14 2006
@@ -24,7 +24,7 @@
     <artifactId>jackrabbit-webdav</artifactId>
     
     <name>Jackrabbit Webdav Library</name>
-    <currentVersion>1.1-SNAPSHOT</currentVersion>
+    <currentVersion>1.2-SNAPSHOT</currentVersion>
     <inceptionYear>2005</inceptionYear>
     <package>org.apache.jackrabbit.webdav.*</package>
     

Modified: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java?view=diff&rev=482627&r1=482626&r2=482627
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java (original)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java Tue Dec  5 04:46:14 2006
@@ -61,7 +61,7 @@
 
     public static final String XML_EVENTDISCOVERY = "eventdiscovery";
     public static final String XML_EVENTBUNDLE = "eventbundle";
-    public static final String XML_EVENT_IS_LOCAL = "islocal";
+    public static final String XML_EVENT_TRANSACTION_ID = "transactionid";
     public static final String XML_EVENT = "event";
     public static final String XML_EVENTUSERID = "eventuserid";
 
@@ -71,4 +71,4 @@
      * existing subscriptions present on the specified resource.
      */
     public static final DavPropertyName SUBSCRIPTIONDISCOVERY = DavPropertyName.create("subscriptiondiscovery", NAMESPACE);
-}
\ No newline at end of file
+}