svn commit: r560277 - in /lenya/trunk/src: java/org/apache/lenya/cms/repository/ java/org/apache/lenya/transaction/ modules-core/usecase/java/src/org/apache/lenya/cms/usecase/ modules/sourcerepository/java/src/org/apache/lenya/cms/repository/

[email protected]
Newsgroups gmane.comp.cms.lenya.cvs
Message-ID <[email protected]>
Author: andreas
Date: Fri Jul 27 08:37:04 2007
New Revision: 560277

URL: http://svn.apache.org/viewvc?view=rev&rev=560277
Log:
Added ConcurrentModificationException, improved session and usecase error handling

Added:
    lenya/trunk/src/java/org/apache/lenya/transaction/ConcurrentModificationException.java
Modified:
    lenya/trunk/src/java/org/apache/lenya/cms/repository/Session.java
    lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java
    lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWorkImpl.java
    lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java
    lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/UsecaseMessage.java
    lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeRCML.java

Modified: lenya/trunk/src/java/org/apache/lenya/cms/repository/Session.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/java/org/apache/lenya/cms/repository/Session.java?view=diff&rev=560277&r1=560276&r2=560277
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/repository/Session.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/repository/Session.java Fri Jul 27 08:37:04 2007
@@ -20,6 +20,7 @@
 import org.apache.lenya.ac.Identity;
 import org.apache.lenya.cms.observation.RepositoryEvent;
 import org.apache.lenya.cms.observation.RepositoryListener;
+import org.apache.lenya.transaction.ConcurrentModificationException;
 import org.apache.lenya.transaction.UnitOfWork;
 
 /**
@@ -35,8 +36,10 @@
     /**
      * Commits the transaction.
      * @throws RepositoryException if an error occurs.
+     * @throws ConcurrentModificationException if a transactionable has been
+     *         modified by another session.
      */
-    void commit() throws RepositoryException;
+    void commit() throws RepositoryException, ConcurrentModificationException;
 
     /**
      * Rolls the transaction back.
@@ -58,27 +61,27 @@
      * @throws RepositoryException if the listener is already registered.
      */
     void addListener(RepositoryListener listener) throws RepositoryException;
-    
+
     /**
      * Checks if a listener is registered.
      * @param listener The listener.
      * @return A boolean value.
      */
     boolean isListenerRegistered(RepositoryListener listener);
-    
+
     /**
      * @param event The event to add to the queue.
      */
     void enqueueEvent(RepositoryEvent event);
-    
+
     /**
      * @param identity The identity.
      */
     void setIdentity(Identity identity);
-    
+
     /**
      * @return if the repository items in this session can be modified.
      */
     boolean isModifiable();
-    
+
 }

Modified: lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java?view=diff&rev=560277&r1=560276&r2=560277
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java Fri Jul 27 08:37:04 2007
@@ -32,6 +32,7 @@
 import org.apache.lenya.cms.observation.ObservationRegistry;
 import org.apache.lenya.cms.observation.RepositoryEvent;
 import org.apache.lenya.cms.observation.RepositoryListener;
+import org.apache.lenya.transaction.ConcurrentModificationException;
 import org.apache.lenya.transaction.IdentityMap;
 import org.apache.lenya.transaction.IdentityMapImpl;
 import org.apache.lenya.transaction.Lock;
@@ -105,12 +106,16 @@
     /**
      * Commits the transaction.
      * @throws RepositoryException if an error occurs.
+     * @throws ConcurrentModificationException if a transactionable has been
+     *         modified by another session.
      */
-    public void commit() throws RepositoryException {
+    public void commit() throws RepositoryException, ConcurrentModificationException {
 
         try {
             getUnitOfWork().commit();
             getSharedItemStore().clear();
+        } catch (ConcurrentModificationException e) {
+            throw e;
         } catch (TransactionException e) {
             throw new RepositoryException(e);
         }

Added: lenya/trunk/src/java/org/apache/lenya/transaction/ConcurrentModificationException.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/java/org/apache/lenya/transaction/ConcurrentModificationException.java?view=auto&rev=560277
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/transaction/ConcurrentModificationException.java (added)
+++ lenya/trunk/src/java/org/apache/lenya/transaction/ConcurrentModificationException.java Fri Jul 27 08:37:04 2007
@@ -0,0 +1,47 @@
+/*
+ * 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.lenya.transaction;
+
+import org.apache.lenya.util.Assert;
+
+/**
+ * Exception which is thrown when a different identity changed a transactionable
+ * object in an optimistic offline lock scenario.
+ */
+public class ConcurrentModificationException extends TransactionException {
+
+    private Transactionable transactionable;
+
+    public ConcurrentModificationException(Transactionable t) {
+        super();
+        Assert.notNull("transactionable", t);
+        this.transactionable = t;
+    }
+
+    public String getMessage() {
+        return "The object [" + this.transactionable + "] was modified after it has been locked.";
+    }
+
+    /**
+     * @return The transactionable that was modified by a different identity.
+     */
+    public Transactionable getTransactionable() {
+        return this.transactionable;
+    }
+
+}

Modified: lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWorkImpl.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWorkImpl.java?view=diff&rev=560277&r1=560276&r2=560277
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWorkImpl.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWorkImpl.java Fri Jul 27 08:37:04 2007
@@ -101,8 +101,7 @@
         for (Iterator i = lockedObjects.iterator(); i.hasNext();) {
             Transactionable t = (Transactionable) i.next();
             if (t.hasChanged()) {
-                throw new LockException("Cannot commit transaction: The object [" + t
-                        + "] was modified after it has been locked.");
+                throw new ConcurrentModificationException(t);
             }
         }
 

Modified: lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java?view=diff&rev=560277&r1=560276&r2=560277
==============================================================================
--- lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java (original)
+++ lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java Fri Jul 27 08:37:04 2007
@@ -45,6 +45,7 @@
 import org.apache.lenya.cms.repository.RepositoryException;
 import org.apache.lenya.cms.repository.RepositoryUtil;
 import org.apache.lenya.cms.repository.Session;
+import org.apache.lenya.transaction.ConcurrentModificationException;
 import org.apache.lenya.transaction.LockException;
 
 /**
@@ -87,9 +88,9 @@
     protected String SOURCE_URL = "private.sourceUrl";
 
     /**
-     * @see org.apache.lenya.cms.usecase.Usecase#getSourceURL()
-     * We don't use getParameterAsString() because this will typically
-     * cause stack overflows or NPEs in connection with initParameters().
+     * @see org.apache.lenya.cms.usecase.Usecase#getSourceURL() We don't use
+     *      getParameterAsString() because this will typically cause stack
+     *      overflows or NPEs in connection with initParameters().
      */
     public String getSourceURL() {
         return (String) this.parameters.get(SOURCE_URL);
@@ -232,13 +233,13 @@
         try {
             clearErrorMessages();
             clearInfoMessages();
-            
+
             Node[] nodes = getNodesToLock();
             if (!canCheckOut(nodes)) {
                 addErrorMessage(ERROR_OBJECTS_CHECKED_OUT);
             }
             doCheckPreconditions();
-            
+
             List _errorMessages = getErrorMessages();
             for (int i = 0; i < _errorMessages.size(); i++) {
                 getLogger().info(_errorMessages.get(i).toString());
@@ -303,8 +304,12 @@
                 } else {
                     getSession().rollback();
                 }
+            } catch (ConcurrentModificationException e) {
+                getLogger().error(
+                        "Could not commit/rollback usecase [" + getName() + "]: " + e.getMessage());
+                addErrorMessage(e.getMessage());
             } catch (Exception e1) {
-                getLogger().error("Exception during commit or rollback: ", e1);
+                getLogger().error("Could not commit/rollback usecase [" + getName() + "]: ", e1);
                 addErrorMessage("Exception during commit or rollback: " + e1.getMessage()
                         + " (see logfiles for details)");
             }

Modified: lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/UsecaseMessage.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/UsecaseMessage.java?view=diff&rev=560277&r1=560276&r2=560277
==============================================================================
--- lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/UsecaseMessage.java (original)
+++ lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/UsecaseMessage.java Fri Jul 27 08:37:04 2007
@@ -81,10 +81,14 @@
     }
 
     /**
-     * Accomodates scripts which do no care about parameters
-     * @return a string representation disregarding any parameters
+     * @return A string representation, the parameters are included as a comma-separated list.
      */
     public String toString() {
-        return message;
+        StringBuffer msg = new StringBuffer(getMessage());
+        String[] params = getParameters();
+        for (int i = 0; i < params.length; i++) {
+            msg.append(", " + params[i]);
+        }
+        return msg.toString();
     }
 }

Modified: lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeRCML.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeRCML.java?view=diff&rev=560277&r1=560276&r2=560277
==============================================================================
--- lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeRCML.java (original)
+++ lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeRCML.java Fri Jul 27 08:37:04 2007
@@ -127,17 +127,18 @@
             throws IOException, Exception {
 
         Document doc = getDocument();
-        
+        String elementName = (String) ELEMENTS.get(new Short(type));
+
         Vector entries = getEntries();
         if (entries.size() == 0) {
             if (type == ci) {
                 throw new IllegalStateException("Can't check in - not checked out.");
             }
-        }
-        else {
+        } else {
             RCMLEntry latestEntry = getLatestEntry();
             if (type == latestEntry.getType()) {
-                throw new IllegalStateException("RCMLEntry type " + type + " not allowed twice in a row.");
+                throw new IllegalStateException("RCML entry type <" + elementName
+                        + "> not allowed twice in a row.");
             }
         }
 
@@ -155,7 +156,6 @@
         Element timeElement = doc.createElement("Time");
         timeElement.appendChild(doc.createTextNode("" + time));
 
-        String elementName = (String) ELEMENTS.get(new Short(type));
         Element checkOutElement = doc.createElement(elementName);
 
         checkOutElement.appendChild(identityElement);
@@ -214,8 +214,7 @@
                     this.xml = SourceUtil.readDOM(getRcmlSourceUri(), this.manager);
                     this.lastModified = sourceLastModified;
                 }
-            }
-            else {
+            } else {
                 if (this.xml == null) {
                     this.xml = DocumentHelper.createDocument(null, "XPSRevisionControl", null);
                 }
@@ -560,16 +559,17 @@
     }
 
     public void copyFrom(RCML otherRcml) throws RevisionControlException {
-        
+
         SourceNodeRCML other = (SourceNodeRCML) otherRcml;
-        
+
         try {
 
             Vector backupEntries = other.getBackupEntries();
-            for (Iterator i = backupEntries.iterator(); i.hasNext(); ) {
+            for (Iterator i = backupEntries.iterator(); i.hasNext();) {
                 RCMLEntry entry = (RCMLEntry) i.next();
                 long time = entry.getTime();
-                String otherContentUri = other.getBackupSourceUri(other.node.getContentSource(), time);
+                String otherContentUri = other.getBackupSourceUri(other.node.getContentSource(),
+                        time);
                 String thisContentUri = this.getBackupSourceUri(this.node.getContentSource(), time);
                 SourceUtil.copy(this.manager, otherContentUri, thisContentUri);
                 String otherMetaUri = other.getBackupSourceUri(other.node.getMetaSource(), time);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.