You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lenya.apache.org by an...@apache.org on 2005/04/01 15:30:33 UTC

svn commit: r159685 [1/2] - in lenya/trunk/src: java/org/apache/lenya/cms/ant/ java/org/apache/lenya/cms/cocoon/acting/ java/org/apache/lenya/cms/cocoon/components/modules/input/ java/org/apache/lenya/cms/cocoon/flow/ java/org/apache/lenya/cms/metadata/dublincore/ java/org/apache/lenya/cms/publication/ java/org/apache/lenya/cms/rc/ java/org/apache/lenya/cms/site/tree/ java/org/apache/lenya/cms/usecase/ java/org/apache/lenya/cms/workflow/ java/org/apache/lenya/transaction/ webapp/lenya/pubs/default/java/src/org/apache/lenya/defaultpub/cms/usecases/

Author: andreas
Date: Fri Apr  1 05:30:25 2005
New Revision: 159685

URL: http://svn.apache.org/viewcvs?view=rev&rev=159685
Log:
added version number to revision control, implemented locking for Transactionables

Added:
    lenya/trunk/src/java/org/apache/lenya/transaction/Lock.java
Modified:
    lenya/trunk/src/java/org/apache/lenya/cms/ant/InitRCTask.java
    lenya/trunk/src/java/org/apache/lenya/cms/cocoon/acting/ReservedCheckinAction.java
    lenya/trunk/src/java/org/apache/lenya/cms/cocoon/acting/UploadAction.java
    lenya/trunk/src/java/org/apache/lenya/cms/cocoon/components/modules/input/OperationModule.java
    lenya/trunk/src/java/org/apache/lenya/cms/cocoon/flow/FlowHelperImpl.java
    lenya/trunk/src/java/org/apache/lenya/cms/metadata/dublincore/DublinCoreImpl.java
    lenya/trunk/src/java/org/apache/lenya/cms/metadata/dublincore/DublinCoreProxy.java
    lenya/trunk/src/java/org/apache/lenya/cms/publication/DefaultDocument.java
    lenya/trunk/src/java/org/apache/lenya/cms/publication/DefaultResourcesManager.java
    lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentManagerImpl.java
    lenya/trunk/src/java/org/apache/lenya/cms/rc/CheckInEntry.java
    lenya/trunk/src/java/org/apache/lenya/cms/rc/RCML.java
    lenya/trunk/src/java/org/apache/lenya/cms/rc/RCMLEntry.java
    lenya/trunk/src/java/org/apache/lenya/cms/rc/RevisionController.java
    lenya/trunk/src/java/org/apache/lenya/cms/site/tree/DefaultSiteTree.java
    lenya/trunk/src/java/org/apache/lenya/cms/site/tree/SiteTreeFactory.java
    lenya/trunk/src/java/org/apache/lenya/cms/site/tree/TreeSiteManager.java
    lenya/trunk/src/java/org/apache/lenya/cms/usecase/AbstractUsecase.java
    lenya/trunk/src/java/org/apache/lenya/cms/workflow/History.java
    lenya/trunk/src/java/org/apache/lenya/transaction/IdentityMap.java
    lenya/trunk/src/java/org/apache/lenya/transaction/IdentityMapImpl.java
    lenya/trunk/src/java/org/apache/lenya/transaction/Transactionable.java
    lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWork.java
    lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWorkImpl.java
    lenya/trunk/src/webapp/lenya/pubs/default/java/src/org/apache/lenya/defaultpub/cms/usecases/Publish.java

Modified: lenya/trunk/src/java/org/apache/lenya/cms/ant/InitRCTask.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/ant/InitRCTask.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/ant/InitRCTask.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/ant/InitRCTask.java Fri Apr  1 05:30:25 2005
@@ -94,7 +94,7 @@
                         language);
                 String filename = destDoc.getFile().getCanonicalPath();
                 filename = filename.substring(publicationPath.length());
-                this.rc.reservedCheckIn(filename, getUserId(), true);
+                this.rc.reservedCheckIn(filename, getUserId(), true, true);
             }
         } catch (Exception e) {
             throw new BuildException(e);

Modified: lenya/trunk/src/java/org/apache/lenya/cms/cocoon/acting/ReservedCheckinAction.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/cocoon/acting/ReservedCheckinAction.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/cocoon/acting/ReservedCheckinAction.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/cocoon/acting/ReservedCheckinAction.java Fri Apr  1 05:30:25 2005
@@ -50,7 +50,7 @@
         getLogger().debug("Backup: " + backup);
 
         try {
-            getRc().reservedCheckIn(getFilename(), getUsername(), backup);
+            getRc().reservedCheckIn(getFilename(), getUsername(), backup, true);
         } catch (FileReservedCheckInException e) {
             actionMap.put("exception", "fileReservedCheckInException");
             actionMap.put("filename", getFilename());

Modified: lenya/trunk/src/java/org/apache/lenya/cms/cocoon/acting/UploadAction.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/cocoon/acting/UploadAction.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/cocoon/acting/UploadAction.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/cocoon/acting/UploadAction.java Fri Apr  1 05:30:25 2005
@@ -154,7 +154,7 @@
         dublinCoreParams.put("extent", Integer.toString(fileSize));
 
         if (uploadType.equals("asset")) {
-            ResourcesManager resourcesMgr = new DefaultResourcesManager(this.document);
+            ResourcesManager resourcesMgr = new DefaultResourcesManager(this.document, this.manager);
             assetFile = new File(resourcesMgr.getPath(), fileName);
 
             if (!resourcesMgr.getPath().exists()) {

Modified: lenya/trunk/src/java/org/apache/lenya/cms/cocoon/components/modules/input/OperationModule.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/cocoon/components/modules/input/OperationModule.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/cocoon/components/modules/input/OperationModule.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/cocoon/components/modules/input/OperationModule.java Fri Apr  1 05:30:25 2005
@@ -65,7 +65,7 @@
                getLogger().debug("OperationModule.getUnitOfWork() does not yet have instance, looking up role [" + UnitOfWork.ROLE + "]");
 
            this.unitOfWork = (UnitOfWork) this.manager.lookup(UnitOfWork.ROLE);
-           this.unitOfWork.addIdentityMap(getDocumentIdentityMap());
+           this.unitOfWork.setIdentityMap(getDocumentIdentityMap());
         }
 
         return this.unitOfWork;

Modified: lenya/trunk/src/java/org/apache/lenya/cms/cocoon/flow/FlowHelperImpl.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/cocoon/flow/FlowHelperImpl.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/cocoon/flow/FlowHelperImpl.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/cocoon/flow/FlowHelperImpl.java Fri Apr  1 05:30:25 2005
@@ -198,7 +198,10 @@
         final Publication publication = getPageEnvelope(cocoon).getPublication();
         final String filename = pageEnvelope.getDocument().getFile().getCanonicalPath()
                 .substring(publication.getDirectory().getCanonicalPath().length());
-        getRevisionController(cocoon).reservedCheckIn(filename, identity.getUser().getId(), backup);
+        getRevisionController(cocoon).reservedCheckIn(filename,
+                identity.getUser().getId(),
+                backup,
+                true);
     }
 
     private ServiceManager manager;

Modified: lenya/trunk/src/java/org/apache/lenya/cms/metadata/dublincore/DublinCoreImpl.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/metadata/dublincore/DublinCoreImpl.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/metadata/dublincore/DublinCoreImpl.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/metadata/dublincore/DublinCoreImpl.java Fri Apr  1 05:30:25 2005
@@ -19,18 +19,20 @@
 
 package org.apache.lenya.cms.metadata.dublincore;
 
-import java.io.File;
-import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
-
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.ProcessingException;
+import org.apache.excalibur.source.ModifiableSource;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
 import org.apache.lenya.cms.publication.Document;
 import org.apache.lenya.cms.publication.DocumentException;
 import org.apache.lenya.cms.publication.PageEnvelope;
@@ -38,15 +40,13 @@
 import org.apache.lenya.xml.NamespaceHelper;
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
 
 /**
  * Access dublin core meta data in documents. This class uses the dublin core specification from
  * 2003-03-04.
  */
 public class DublinCoreImpl {
-    private Document cmsdocument;
-    private File infofile;
+    private String sourceUri;
 
     private Map elements = new HashMap();
     private Map terms = new HashMap();
@@ -87,28 +87,29 @@
             DublinCore.TERM_EDUCATIONLEVEL, DublinCore.TERM_ACCESSRIGHTS,
             DublinCore.TERM_BIBLIOGRAPHICCITATION };
 
+    private ServiceManager manager;
+
     /**
      * Creates a new instance of Dublin Core
      * @param aDocument the document for which the Dublin Core instance is created.
+     * @param manager The service manager.
      * @throws DocumentException if an error occurs
      */
-    protected DublinCoreImpl(Document aDocument) throws DocumentException {
-        this.cmsdocument = aDocument;
-        this.infofile = this.cmsdocument.getPublication().getPathMapper().getFile(
-                this.cmsdocument.getPublication(), this.cmsdocument.getArea(), this.cmsdocument.getId(),
-                this.cmsdocument.getLanguage());
+    protected DublinCoreImpl(Document aDocument, ServiceManager manager) throws DocumentException {
+        this.manager = manager;
+        this.sourceUri = aDocument.getSourceURI();
         loadValues();
     }
 
     /**
-     * Creates a new instance of Dublin Core 
-     * @param file the File for which the Dublin Core instance is created.
-     * TODO This is a hack until resources are treated as documents, and .meta files
-     * can be accessed through the Document interface.
+     * Creates a new instance of Dublin Core
+     * @param sourceUri The source URI.
+     * @param manager The service manager.
      * @throws DocumentException if an error occurs
      */
-    public DublinCoreImpl(File file) throws DocumentException {
-        this.infofile = file;
+    public DublinCoreImpl(String sourceUri, ServiceManager manager) throws DocumentException {
+        this.sourceUri = sourceUri;
+        this.manager = manager;
         loadValues();
     }
 
@@ -118,16 +119,65 @@
      */
     protected void loadValues() throws DocumentException {
 
-        if (this.infofile.exists()) {
-            org.w3c.dom.Document doc = null;
-            try {
-                doc = DocumentHelper.readDocument(this.infofile);
-            } catch (Exception e) {
-                throw new DocumentException("Parsing file [" + this.infofile + "] failed: ", e);
+        SourceResolver resolver = null;
+        Source source = null;
+        try {
+            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
+            source = resolver.resolveURI(this.sourceUri);
+            if (source.exists()) {
+                org.w3c.dom.Document doc = DocumentHelper.readDocument(source.getInputStream());
+
+                // FIXME: what if "lenya:meta" element doesn't exist yet?
+                // Currently the element is inserted.
+                Element metaElement = getMetaElement(doc);
+
+                String[] namespaces = { DC_NAMESPACE, DCTERMS_NAMESPACE };
+                String[] prefixes = { DC_PREFIX, DCTERMS_PREFIX };
+                String[][] arrays = { ELEMENTS, TERMS };
+                Map[] maps = { this.elements, this.terms };
+
+                for (int type = 0; type < 2; type++) {
+                    NamespaceHelper helper = new NamespaceHelper(namespaces[type], prefixes[type],
+                            doc);
+                    String[] elementNames = arrays[type];
+                    for (int i = 0; i < elementNames.length; i++) {
+                        Element[] children = helper.getChildren(metaElement, elementNames[i]);
+                        String[] values = new String[children.length];
+                        for (int valueIndex = 0; valueIndex < children.length; valueIndex++) {
+                            values[valueIndex] = DocumentHelper
+                                    .getSimpleElementText(children[valueIndex]);
+                        }
+                        maps[type].put(elementNames[i], values);
+                    }
+                }
             }
+        } catch (Exception e) {
+            throw new DocumentException(e);
+        } finally {
+            if (resolver != null) {
+                if (source != null) {
+                    resolver.release(source);
+                }
+                this.manager.release(resolver);
+            }
+        }
+    }
+
+    /**
+     * Save the meta data.
+     * @throws DocumentException if the meta data could not be made persistent.
+     */
+    public void save() throws DocumentException {
+
+        SourceResolver resolver = null;
+        ModifiableSource source = null;
+        try {
+
+            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
+            source = (ModifiableSource) resolver.resolveURI(this.sourceUri);
+
+            org.w3c.dom.Document doc = DocumentHelper.readDocument(source.getInputStream());
 
-            // FIXME: what if "lenya:meta" element doesn't exist yet?
-            // Currently the element is inserted.
             Element metaElement = getMetaElement(doc);
 
             String[] namespaces = { DC_NAMESPACE, DCTERMS_NAMESPACE };
@@ -140,66 +190,38 @@
                 String[] elementNames = arrays[type];
                 for (int i = 0; i < elementNames.length; i++) {
                     Element[] children = helper.getChildren(metaElement, elementNames[i]);
-                    String[] values = new String[children.length];
                     for (int valueIndex = 0; valueIndex < children.length; valueIndex++) {
-                        values[valueIndex] = DocumentHelper
-                                .getSimpleElementText(children[valueIndex]);
+                        metaElement.removeChild(children[valueIndex]);
+                    }
+                    String[] values = (String[]) maps[type].get(elementNames[i]);
+                    for (int valueIndex = 0; valueIndex < values.length; valueIndex++) {
+                        Element valueElement = helper.createElement(elementNames[i],
+                                values[valueIndex]);
+                        metaElement.appendChild(valueElement);
                     }
-                    maps[type].put(elementNames[i], values);
                 }
             }
-        }
 
-    }
-
-    /**
-     * Save the meta data.
-     * @throws DocumentException if the meta data could not be made persistent.
-     */
-    public void save() throws DocumentException {
-        org.w3c.dom.Document doc = null;
-        try {
-            doc = DocumentHelper.readDocument(this.infofile);
-        } catch (final ParserConfigurationException e) {
-            throw new DocumentException(e);
-        } catch (final SAXException e) {
-            throw new DocumentException(e);
-        } catch (final IOException e) {
-            throw new DocumentException(e);
-        }
-
-        Element metaElement = getMetaElement(doc);
-
-        String[] namespaces = { DC_NAMESPACE, DCTERMS_NAMESPACE };
-        String[] prefixes = { DC_PREFIX, DCTERMS_PREFIX };
-        String[][] arrays = { ELEMENTS, TERMS };
-        Map[] maps = { this.elements, this.terms };
-
-        for (int type = 0; type < 2; type++) {
-            NamespaceHelper helper = new NamespaceHelper(namespaces[type], prefixes[type], doc);
-            String[] elementNames = arrays[type];
-            for (int i = 0; i < elementNames.length; i++) {
-                Element[] children = helper.getChildren(metaElement, elementNames[i]);
-                for (int valueIndex = 0; valueIndex < children.length; valueIndex++) {
-                    metaElement.removeChild(children[valueIndex]);
-                }
-                String[] values = (String[]) maps[type].get(elementNames[i]);
-                for (int valueIndex = 0; valueIndex < values.length; valueIndex++) {
-                    Element valueElement = helper
-                            .createElement(elementNames[i], values[valueIndex]);
-                    metaElement.appendChild(valueElement);
+            OutputStream oStream = source.getOutputStream();
+            Writer writer = new OutputStreamWriter(oStream);
+            DocumentHelper.writeDocument(doc, writer);
+            if (oStream != null) {
+                oStream.flush();
+                try {
+                    oStream.close();
+                } catch (Throwable t) {
+                    throw new ProcessingException("Could not write document: ", t);
                 }
             }
-        }
-
-        try {
-            DocumentHelper.writeDocument(doc, this.infofile);
-        } catch (TransformerConfigurationException e) {
-            throw new DocumentException(e);
-        } catch (TransformerException e) {
-            throw new DocumentException(e);
-        } catch (IOException e) {
+        } catch (Exception e) {
             throw new DocumentException(e);
+        } finally {
+            if (resolver != null) {
+                if (source != null) {
+                    resolver.release(source);
+                }
+                this.manager.release(resolver);
+            }
         }
 
     }

Modified: lenya/trunk/src/java/org/apache/lenya/cms/metadata/dublincore/DublinCoreProxy.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/metadata/dublincore/DublinCoreProxy.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/metadata/dublincore/DublinCoreProxy.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/metadata/dublincore/DublinCoreProxy.java Fri Apr  1 05:30:25 2005
@@ -19,6 +19,7 @@
 
 package org.apache.lenya.cms.metadata.dublincore;
 
+import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.lenya.cms.publication.Document;
 import org.apache.lenya.cms.publication.DocumentException;
 
@@ -30,15 +31,17 @@
 
     private DublinCoreImpl dcCore;
     private Document cmsDocument;
-
+    private ServiceManager manager;
 
     /** 
      * Creates a new instance of Dublin Core
      * 
      * @param aDocument the document for which the Dublin Core instance is created.
+     * @param manager The service manager.
      */
-    public DublinCoreProxy(Document aDocument) {
+    public DublinCoreProxy(Document aDocument, ServiceManager manager) {
         this.cmsDocument = aDocument;
+        this.manager = manager;
     }
 
     /**
@@ -49,7 +52,7 @@
      */
     protected DublinCoreImpl instance() throws DocumentException {
         if (this.dcCore == null) {
-            this.dcCore = new DublinCoreImpl(this.cmsDocument);
+            this.dcCore = new DublinCoreImpl(this.cmsDocument, this.manager);
         }
         return this.dcCore;
     }

Modified: lenya/trunk/src/java/org/apache/lenya/cms/publication/DefaultDocument.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/publication/DefaultDocument.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/publication/DefaultDocument.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/publication/DefaultDocument.java Fri Apr  1 05:30:25 2005
@@ -33,6 +33,7 @@
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceResolver;
 import org.apache.lenya.ac.User;
+import org.apache.lenya.cms.cocoon.source.SourceUtil;
 import org.apache.lenya.cms.metadata.dublincore.DublinCore;
 import org.apache.lenya.cms.metadata.dublincore.DublinCoreProxy;
 import org.apache.lenya.cms.publication.util.DocumentVisitor;
@@ -41,6 +42,7 @@
 import org.apache.lenya.cms.site.SiteManager;
 import org.apache.lenya.cms.workflow.CMSHistory;
 import org.apache.lenya.cms.workflow.History;
+import org.apache.lenya.transaction.Lock;
 import org.apache.lenya.transaction.TransactionException;
 import org.apache.lenya.workflow.Situation;
 import org.apache.lenya.workflow.Version;
@@ -84,7 +86,7 @@
         setArea(_area);
         setLanguage(getPublication().getDefaultLanguage());
 
-        this.dublincore = new DublinCoreProxy(this);
+        this.dublincore = new DublinCoreProxy(this, this.manager);
     }
 
     /**
@@ -112,7 +114,7 @@
         this.language = _language;
         setArea(_area);
 
-        this.dublincore = new DublinCoreProxy(this);
+        this.dublincore = new DublinCoreProxy(this, this.manager);
     }
 
     /**
@@ -381,7 +383,7 @@
      */
     public ResourcesManager getResourcesManager() {
         if (this.resourcesManager == null) {
-            this.resourcesManager = new DefaultResourcesManager(this);
+            this.resourcesManager = new DefaultResourcesManager(this, this.manager);
             ContainerUtil.enableLogging(this.resourcesManager, getLogger());
         }
         return this.resourcesManager;
@@ -402,9 +404,50 @@
     }
 
     /**
+     * If the document is involved in a unit of work, a temporary source is created to be used in
+     * the transaction.
      * @see org.apache.lenya.cms.publication.Document#getSourceURI()
      */
     public String getSourceURI() {
+        String uri = getRealSourceURI();
+
+        if (getIdentityMap().getUnitOfWork() != null) {
+            String workUri = getWorkSourceURI();
+
+            SourceResolver resolver = null;
+            ModifiableSource realSource = null;
+            ModifiableSource workSource = null;
+            try {
+                resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
+                realSource = (ModifiableSource) resolver.resolveURI(uri);
+                workSource = (ModifiableSource) resolver.resolveURI(workUri);
+                if (realSource.exists() && !workSource.exists()) {
+                    SourceUtil.copy(realSource, workSource, true);
+                }
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            } finally {
+                if (resolver != null) {
+                    if (realSource != null) {
+                        resolver.release(realSource);
+                    }
+                    if (workSource != null) {
+                        resolver.release(workSource);
+                    }
+                    this.manager.release(resolver);
+                }
+            }
+
+            uri = workUri;
+        }
+
+        return uri;
+    }
+
+    /**
+     * @return The real source URI.
+     */
+    protected String getRealSourceURI() {
         try {
             return "file:/" + getFile().getCanonicalPath();
         } catch (IOException e) {
@@ -413,6 +456,19 @@
     }
 
     /**
+     * @return A source URI to be used in a transaction.
+     */
+    protected String getWorkSourceURI() {
+        String workUri = "file:/" + getPublication().getDirectory().getAbsolutePath() + "/work/";
+        workUri += getUserId();
+
+        String path = getPublication().getPathMapper().getPath(getId(), getLanguage());
+        workUri += "/" + getArea() + "/" + path;
+
+        return workUri;
+    }
+
+    /**
      * @see org.apache.lenya.cms.publication.Document#accept(org.apache.lenya.cms.publication.util.DocumentVisitor)
      */
     public void accept(DocumentVisitor visitor) throws PublicationException {
@@ -492,12 +548,36 @@
      * @see org.apache.lenya.transaction.Transactionable#save()
      */
     public void save() throws TransactionException {
+
+        SourceResolver sourceResolver = null;
+        ModifiableSource realSource = null;
+        ModifiableSource workSource = null;
         try {
             getDublinCore().save();
-        } catch (DocumentException e) {
+            getHistory().save();
+
+            sourceResolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
+            realSource = (ModifiableSource) sourceResolver.resolveURI(getRealSourceURI());
+            workSource = (ModifiableSource) sourceResolver.resolveURI(getWorkSourceURI());
+            if (workSource.exists()) {
+                SourceUtil.copy(workSource, realSource, true);
+                workSource.delete();
+            }
+
+        } catch (Exception e) {
             throw new TransactionException(e);
+        } finally {
+            if (sourceResolver != null) {
+                if (realSource != null) {
+                    sourceResolver.release(realSource);
+                }
+                if (workSource != null) {
+                    sourceResolver.release(workSource);
+                }
+                this.manager.release(sourceResolver);
+            }
         }
-        getHistory().save();
+
     }
 
     /**
@@ -506,12 +586,12 @@
     public void checkin() throws TransactionException {
         checkin(true);
     }
-    
+
     protected void checkin(boolean backup) throws TransactionException {
         try {
-            String fileName = getFile().getCanonicalPath();
-            String userName = getUserName();
-            getRevisionController().reservedCheckIn(fileName, userName, backup);
+            String userName = getUserId();
+            boolean newVersion = getIdentityMap().getUnitOfWork().isDirty(this);
+            getRevisionController().reservedCheckIn(getRCPath(), userName, backup, newVersion);
         } catch (Exception e) {
             throw new TransactionException(e);
         }
@@ -520,11 +600,11 @@
     /**
      * @return The username of the unit of work's identity.
      */
-    protected String getUserName() {
+    protected String getUserId() {
         String userName = null;
         User user = getIdentityMap().getUnitOfWork().getIdentity().getUser();
         if (user != null) {
-            userName = user.getName();
+            userName = user.getId();
         }
         return userName;
     }
@@ -534,9 +614,8 @@
      */
     public void checkout() throws TransactionException {
         try {
-            String fileName = getFile().getCanonicalPath();
-            String userName = getUserName();
-            getRevisionController().reservedCheckOut(fileName, userName);
+            String userName = getUserId();
+            getRevisionController().reservedCheckOut(getRCPath(), userName);
         } catch (Exception e) {
             throw new TransactionException(e);
         }
@@ -547,9 +626,8 @@
      */
     public boolean isCheckedOut() throws TransactionException {
         try {
-            String fileName = getFile().getCanonicalPath();
-            String userName = getUserName();
-            return !getRevisionController().canCheckOut(fileName, userName);
+            String userName = getUserId();
+            return !getRevisionController().canCheckOut(getRCPath(), userName);
         } catch (Exception e) {
             throw new TransactionException(e);
         }
@@ -559,22 +637,21 @@
      * @see org.apache.lenya.transaction.Transactionable#lock()
      */
     public void lock() throws TransactionException {
-        checkout();
+        this.lock = new Lock(getVersion());
     }
 
     /**
      * @see org.apache.lenya.transaction.Transactionable#unlock()
      */
     public void unlock() throws TransactionException {
-        checkin(false);
+        this.lock = null;
     }
 
     /**
      * @see org.apache.lenya.transaction.Transactionable#isLocked()
      */
     public boolean isLocked() throws TransactionException {
-        // TODO Auto-generated method stub
-        return false;
+        return this.lock != null;
     }
 
     /**
@@ -589,17 +666,27 @@
      */
     public void delete() throws TransactionException {
         SourceResolver sourceResolver = null;
-        Source source = null;
+        Source realSource = null;
+        Source workSource = null;
         try {
             sourceResolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-            source = sourceResolver.resolveURI(getSourceURI());
-            ((ModifiableSource) source).delete();
+            realSource = sourceResolver.resolveURI(getSourceURI());
+            if (realSource.exists()) {
+                ((ModifiableSource) realSource).delete();
+            }
+            workSource = sourceResolver.resolveURI(getWorkSourceURI());
+            if (workSource.exists()) {
+                ((ModifiableSource) workSource).delete();
+            }
         } catch (Exception e) {
             throw new TransactionException(e);
         } finally {
             if (sourceResolver != null) {
-                if (source != null) {
-                    sourceResolver.release(source);
+                if (realSource != null) {
+                    sourceResolver.release(realSource);
+                }
+                if (workSource != null) {
+                    sourceResolver.release(workSource);
                 }
                 this.manager.release(sourceResolver);
             }
@@ -632,6 +719,35 @@
             }
         }
         return this.revisionController;
+    }
+
+    private Lock lock;
+
+    /**
+     * @see org.apache.lenya.transaction.Transactionable#getLock()
+     */
+    public Lock getLock() {
+        return this.lock;
+    }
+
+    /**
+     * @see org.apache.lenya.transaction.Transactionable#getVersion()
+     */
+    public int getVersion() throws TransactionException {
+        try {
+            String fileName = getRCPath();
+            return getRevisionController().getLatestVersion(fileName);
+        } catch (Exception e) {
+            throw new TransactionException(e);
+        }
+    }
+
+    /**
+     * @return The path to use for the revision controller.
+     * @throws IOException if an error occurs.
+     */
+    protected String getRCPath() throws IOException {
+        return getArea() + "/" + getPublication().getPathMapper().getPath(getId(), getLanguage());
     }
 
 }

Modified: lenya/trunk/src/java/org/apache/lenya/cms/publication/DefaultResourcesManager.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/publication/DefaultResourcesManager.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/publication/DefaultResourcesManager.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/publication/DefaultResourcesManager.java Fri Apr  1 05:30:25 2005
@@ -33,6 +33,7 @@
 import java.util.Map;
 
 import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.service.ServiceManager;
 
 import org.apache.avalon.excalibur.io.FileUtil;
 
@@ -41,7 +42,6 @@
 import org.apache.lenya.xml.DocumentHelper;
 import org.apache.lenya.xml.NamespaceHelper;
 
-
 /**
  * Manager for resources of a CMS document.
  */
@@ -95,15 +95,17 @@
     }
 
     private Document document = null;
-    
+    private ServiceManager manager;
+
     protected static final String NAMESPACE_META = "http://lenya.apache.org/meta/1.0";
 
     /**
      * Create a new instance of Resources.
      * @param _document the document for which the resources are managed
      */
-    public DefaultResourcesManager(Document _document) {
+    public DefaultResourcesManager(Document _document, ServiceManager manager) {
         this.document = _document;
+        this.manager = manager;
     }
 
     /**
@@ -145,15 +147,15 @@
 
             /*
              * } // must be a content upload then else { resourceFile = new
-             * File(document.getFile().getParent(), fileName);
-             * getLogger().debug("resourceFile: " + resourceFile); }
+             * File(document.getFile().getParent(), fileName); getLogger().debug("resourceFile: " +
+             * resourceFile); }
              */
             saveResource(resourceFile, part);
         } catch (final DocumentException e) {
-            getLogger().error("Document exception " +e.toString());
+            getLogger().error("Document exception " + e.toString());
             throw new RuntimeException(e);
         } catch (final IOException e) {
-            getLogger().error("IO Error " +e.toString());
+            getLogger().error("IO Error " + e.toString());
             throw e;
         }
     }
@@ -167,7 +169,7 @@
     protected void saveResource(File resourceFile, Part part) throws IOException {
         FileOutputStream out = null;
         InputStream in = null;
-        
+
         if (!resourceFile.exists()) {
             boolean created = resourceFile.createNewFile();
             if (!created) {
@@ -175,7 +177,7 @@
             }
         }
 
-	    try {
+        try {
             byte[] buf = new byte[4096];
             out = new FileOutputStream(resourceFile);
             in = part.getInputStream();
@@ -186,13 +188,13 @@
                 read = in.read(buf);
             }
         } catch (final FileNotFoundException e) {
-            getLogger().error("file not found" +e.toString());
+            getLogger().error("file not found" + e.toString());
             throw new IOException(e.toString());
         } catch (IOException e) {
-            getLogger().error("IO error " +e.toString());
+            getLogger().error("IO error " + e.toString());
             throw new IOException(e.toString());
         } catch (Exception e) {
-            getLogger().error("Exception" +e.toString());
+            getLogger().error("Exception" + e.toString());
             throw new IOException(e.toString());
         } finally {
             if (in != null)
@@ -208,27 +210,27 @@
      * @param metadata a <code>Map</code> containing the dublin core values
      * @throws DocumentException if an error occurs
      */
-    protected void createMetaData(File metaDataFile, Map metadata)
-            throws DocumentException {
+    protected void createMetaData(File metaDataFile, Map metadata) throws DocumentException {
 
         assert (metaDataFile.getParentFile().exists());
-		try {
-            
+        try {
+
             if (!metaDataFile.exists()) {
                 metaDataFile.createNewFile();
                 NamespaceHelper helper = new NamespaceHelper(NAMESPACE_META, "", "meta");
                 DocumentHelper.writeDocument(helper.getDocument(), metaDataFile);
             }
-            String		key;
-            String		value;
-            Map.Entry	entry;
-            DublinCoreImpl dc = new DublinCoreImpl(metaDataFile);
+            String key;
+            String value;
+            Map.Entry entry;
+            String sourceUrl = "file:/" + metaDataFile.getAbsolutePath();
+            DublinCoreImpl dc = new DublinCoreImpl(sourceUrl, this.manager);
             Iterator iter = metadata.entrySet().iterator();
 
             while (iter.hasNext()) {
-            	entry 	= (Map.Entry)iter.next();
-            	key 	= (String)entry.getKey();
-            	value 	= (String)entry.getValue();
+                entry = (Map.Entry) iter.next();
+                key = (String) entry.getKey();
+                value = (String) entry.getValue();
                 dc.setValue(key, value);
             }
             dc.save();
@@ -303,8 +305,7 @@
 
     /**
      * Get the meta data for all resources for the associated document.
-     * @return all meta data files for the resources for the associated
-     *         document.
+     * @return all meta data files for the resources for the associated document.
      */
     public File[] getMetaFiles() {
         FileFilter filter = new MetaSuffixFileFilter();
@@ -314,8 +315,8 @@
     /**
      * Returns a meta file for a given resource.
      * @param resource A resource the meta file should be returned for.
-     * @return A file containing meta information about a resource. Returns null
-     *         if no meta file was found.
+     * @return A file containing meta information about a resource. Returns null if no meta file was
+     *         found.
      * @throws IllegalArgumentException If resource is a meta file itself.
      */
     public File getMetaFile(final File resource) throws IllegalArgumentException {

Modified: lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentManagerImpl.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentManagerImpl.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentManagerImpl.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentManagerImpl.java Fri Apr  1 05:30:25 2005
@@ -38,6 +38,7 @@
 import org.apache.lenya.cms.site.tree.SiteTreeNode;
 import org.apache.lenya.cms.site.tree.TreeSiteManager;
 import org.apache.lenya.cms.workflow.WorkflowManager;
+import org.apache.lenya.transaction.UnitOfWork;
 
 /**
  * Abstract DocumentManager implementation.
@@ -138,7 +139,9 @@
             selector = (ServiceSelector) this.manager.lookup(SiteManager.ROLE + "Selector");
             siteManager = (SiteManager) selector.select(publication.getSiteManagerHint());
             siteManager.delete(document);
-            document.delete();
+            
+            UnitOfWork unit = document.getIdentityMap().getUnitOfWork();
+            unit.registerRemoved(document);
         } catch (Exception e) {
             throw new PublicationException(e);
         } finally {
@@ -431,6 +434,7 @@
             destination = sourceResolver.resolveURI(destinationDocument.getSourceURI());
             SourceUtil.copy(source, (ModifiableSource) destination, true);
             destinationDocument.getDublinCore().replaceBy(sourceDocument.getDublinCore());
+            destinationDocument.getIdentityMap().getUnitOfWork().registerDirty(destinationDocument);
         } catch (Exception e) {
             throw new PublicationException(e);
         } finally {

Modified: lenya/trunk/src/java/org/apache/lenya/cms/rc/CheckInEntry.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/rc/CheckInEntry.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/rc/CheckInEntry.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/rc/CheckInEntry.java Fri Apr  1 05:30:25 2005
@@ -28,9 +28,21 @@
      * Creates a new CheckInEntry object.
      * @param identity The identity to use
      * @param time The time
+     * @param version The version number.
      */
-    public CheckInEntry(String identity, long time) {
+    public CheckInEntry(String identity, long time, int version) {
         super(identity, time);
         setType(RCML.ci);
+        this.version = version;
     }
+    
+    /**
+     * @return The version number.
+     */
+    public int getVersion() {
+        return this.version;
+    }
+
+    private int version = 0;
+    
 }

Modified: lenya/trunk/src/java/org/apache/lenya/cms/rc/RCML.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/rc/RCML.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/rc/RCML.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/rc/RCML.java Fri Apr  1 05:30:25 2005
@@ -78,9 +78,9 @@
     /**
      * create a RCML-File if no one exists already
      * @param rcmlDirectory The rcml directory.
-     * @param filename The path of the file from the publication (e.g. for file with 
-     * absolute path home/...//lenya/pubs/{publication id}/content/authoring/foo/bar.xml
-     * the filename is content/authoring/foo/bar.xml)
+     * @param filename The path of the file from the publication (e.g. for file with absolute path
+     *            home/...//lenya/pubs/{publication id}/content/authoring/foo/bar.xml the filename
+     *            is content/authoring/foo/bar.xml)
      * @param rootDirectory The publication directory
      * @throws Exception if an error occurs
      */
@@ -104,7 +104,7 @@
             // system checked the document in. We use the filesystem
             // modification date as checkin time.
             //
-            checkOutIn(RCML.ci, RevisionController.systemUsername, lastModified, false);
+            checkOutIn(RCML.ci, RevisionController.systemUsername, lastModified, false, false);
 
             File parent = new File(this.rcmlFile.getParent());
             parent.mkdirs();
@@ -125,7 +125,7 @@
 
     /**
      * Call the methode write, if the document is dirty
-     *
+     * 
      * @throws IOException if an error occurs
      * @throws Exception if an error occurs
      */
@@ -135,8 +135,9 @@
             write();
         }
     }
+
     /**
-     * Write the xml RCML-document in the RCML-file. 
+     * Write the xml RCML-document in the RCML-file.
      * @throws IOException if an error occurs
      * @throws Exception if an error occurs
      */
@@ -152,15 +153,16 @@
      * @param identity The identity of the user
      * @param time Time at which the check in/out is made
      * @param backup Create backup element
+     * @param newVersion If true, a new version will be created.
      * @throws IOException if an error occurs
      * @throws Exception if an error occurs
      */
-    public void checkOutIn(short type, String identity, long time, boolean backup)
-        throws IOException, Exception {
+    public void checkOutIn(short type, String identity, long time, boolean backup,
+            boolean newVersion) throws IOException, Exception {
 
         if (type != co && type != ci) {
-            throw new IllegalArgumentException(
-                "ERROR: " + this.getClass().getName() + ".checkOutIn(): No such type");
+            throw new IllegalArgumentException("ERROR: " + this.getClass().getName()
+                    + ".checkOutIn(): No such type");
         }
 
         NamespaceHelper helper = new NamespaceHelper(null, "", this.document);
@@ -174,6 +176,19 @@
         checkOutElement.appendChild(identityElement);
         checkOutElement.appendChild(timeElement);
 
+        if (type == ci) {
+            int version = 0;
+            CheckInEntry latestEntry = getLatestCheckInEntry();
+            if (latestEntry != null) {
+                version = latestEntry.getVersion();
+            }
+            if (newVersion) {
+                version++;
+            }
+            Element versionElement = helper.createElement("Version", "" + version);
+            checkOutElement.appendChild(versionElement);
+        }
+
         if (backup) {
             Element backupElement = helper.createElement(ELEMENT_BACKUP);
             checkOutElement.appendChild(backupElement);
@@ -215,8 +230,9 @@
         Node time = null;
         String rcIdentity = null;
 
-       identity = XPathAPI.selectSingleNode(parent,"/XPSRevisionControl/CheckOut[1]/Identity/text()");
-       time = XPathAPI.selectSingleNode(parent,"/XPSRevisionControl/CheckOut[1]/Time/text()");
+        identity = XPathAPI.selectSingleNode(parent,
+                "/XPSRevisionControl/CheckOut[1]/Identity/text()");
+        time = XPathAPI.selectSingleNode(parent, "/XPSRevisionControl/CheckOut[1]/Time/text()");
 
         if (identity == null && time == null) {
             // No checkout at all
@@ -235,21 +251,25 @@
      */
     public CheckInEntry getLatestCheckInEntry() throws Exception {
         Element parent = this.document.getDocumentElement();
-        Node identity = null;
-        Node time = null;
-        String rcIdentity = null;
 
-       identity = XPathAPI.selectSingleNode(parent,"/XPSRevisionControl/CheckIn[1]/Identity/text()");
-       time = XPathAPI.selectSingleNode(parent,"/XPSRevisionControl/CheckIn[1]/Time/text()");
+        Node identity = XPathAPI.selectSingleNode(parent,
+                "/XPSRevisionControl/CheckIn[1]/Identity/text()");
+        Node time = XPathAPI.selectSingleNode(parent, "/XPSRevisionControl/CheckIn[1]/Time/text()");
+        Node versionNode = XPathAPI.selectSingleNode(parent,
+                "/XPSRevisionControl/CheckOut[1]/Version/text()");
 
         if (identity == null && time == null) {
             // No checkout at all
             return null;
         }
-        rcIdentity = identity.getNodeValue();
+        String rcIdentity = identity.getNodeValue();
         long rcTime = new Long(time.getNodeValue()).longValue();
+        int version = 0;
+        if (versionNode != null) {
+            version = new Integer(versionNode.getNodeValue()).intValue();
+        }
 
-        return new CheckInEntry(rcIdentity, rcTime);
+        return new CheckInEntry(rcIdentity, rcTime, version);
     }
 
     /**
@@ -280,21 +300,28 @@
      * @throws Exception if an error occurs
      */
     public Vector getEntries() throws Exception {
-    	Element parent = this.document.getDocumentElement();
-    	NodeList entries =
-    		XPathAPI.selectNodeList(parent, "/XPSRevisionControl/CheckOut|/XPSRevisionControl/CheckIn");
+        Element parent = this.document.getDocumentElement();
+        NodeList entries = XPathAPI.selectNodeList(parent,
+                "/XPSRevisionControl/CheckOut|/XPSRevisionControl/CheckIn");
         Vector RCMLEntries = new Vector();
 
         for (int i = 0; i < entries.getLength(); i++) {
             Element elem = (Element) entries.item(i);
             String time = elem.getElementsByTagName("Time").item(0).getFirstChild().getNodeValue();
-            String identity =
-                elem.getElementsByTagName("Identity").item(0).getFirstChild().getNodeValue();
+            String identity = elem.getElementsByTagName("Identity").item(0).getFirstChild()
+                    .getNodeValue();
 
             if (elem.getTagName().equals("CheckOut")) {
                 RCMLEntries.add(new CheckOutEntry(identity, new Long(time).longValue()));
             } else {
-                RCMLEntries.add(new CheckInEntry(identity, new Long(time).longValue()));
+                NodeList versionElements = elem.getElementsByTagName("Version");
+                int version = 0;
+                if (versionElements.getLength() > 0) {
+                    String versionString = elem.getFirstChild().getNodeValue();
+                    version = new Integer(versionString).intValue();
+                }
+
+                RCMLEntries.add(new CheckInEntry(identity, new Long(time).longValue(), version));
             }
         }
 
@@ -302,22 +329,22 @@
     }
 
     /**
-     * Prune the list of entries and delete the corresponding backups. Limit the number of entries to the value
-     * maximalNumberOfEntries (2maxNumberOfRollbacks(configured)+1)
+     * Prune the list of entries and delete the corresponding backups. Limit the number of entries
+     * to the value maximalNumberOfEntries (2maxNumberOfRollbacks(configured)+1)
      * @param backupDir The backup directory
      * @throws Exception if an error occurs
      */
     public void pruneEntries(String backupDir) throws Exception {
-    	Element parent = this.document.getDocumentElement();
-    	NodeList entries =
-    		XPathAPI.selectNodeList(parent, "/XPSRevisionControl/CheckOut|/XPSRevisionControl/CheckIn");
+        Element parent = this.document.getDocumentElement();
+        NodeList entries = XPathAPI.selectNodeList(parent,
+                "/XPSRevisionControl/CheckOut|/XPSRevisionControl/CheckIn");
 
         for (int i = this.maximalNumberOfEntries; i < entries.getLength(); i++) {
             Element current = (Element) entries.item(i);
 
             // remove the backup file associated with this entry
-            String time =
-                current.getElementsByTagName("Time").item(0).getFirstChild().getNodeValue();
+            String time = current.getElementsByTagName("Time").item(0).getFirstChild()
+                    .getNodeValue();
             File backupFile = new File(backupDir + "/" + time + ".bak");
             backupFile.delete();
             // remove the entry from the list
@@ -326,21 +353,22 @@
     }
 
     /**
-     * Get a clone document 
+     * Get a clone document
      * @return org.w3c.dom.Document The clone document
      * @throws Exception if an error occurs
      */
     public org.w3c.dom.Document getDOMDocumentClone() throws Exception {
         Document documentClone = DocumentHelper.createDocument(null, "dummy", null);
         documentClone.removeChild(documentClone.getDocumentElement());
-        documentClone.appendChild(documentClone.importNode(this.document.getDocumentElement(), true));
+        documentClone.appendChild(documentClone
+                .importNode(this.document.getDocumentElement(), true));
 
         return documentClone;
     }
 
     /**
      * Check if the document is dirty
-     * @return boolean dirty 
+     * @return boolean dirty
      */
     public boolean isDirty() {
         return this.dirty;
@@ -387,7 +415,7 @@
             Element elem = (Element) entries.item(i);
             String time = elem.getElementsByTagName("Time").item(0).getFirstChild().getNodeValue();
             NodeList backupNodes = elem.getElementsByTagName(ELEMENT_BACKUP);
-            if (backupNodes != null && backupNodes.getLength()>0) {
+            if (backupNodes != null && backupNodes.getLength() > 0) {
                 times.add(time);
             }
         }
@@ -402,11 +430,9 @@
     public boolean delete() {
         File directory = this.rcmlFile.getParentFile();
         boolean deleted = this.rcmlFile.delete();
-        if (directory.exists()
-            && directory.isDirectory()
-            && directory.listFiles().length == 0) {
+        if (directory.exists() && directory.isDirectory() && directory.listFiles().length == 0) {
             directory.delete();
         }
         return deleted;
     }
-}
+}
\ No newline at end of file

Modified: lenya/trunk/src/java/org/apache/lenya/cms/rc/RCMLEntry.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/rc/RCMLEntry.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/rc/RCMLEntry.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/rc/RCMLEntry.java Fri Apr  1 05:30:25 2005
@@ -61,7 +61,7 @@
     public short getType() {
         return this.type;
     }
-
+    
     /**
      * Set the type.
      * @param s the type

Modified: lenya/trunk/src/java/org/apache/lenya/cms/rc/RevisionController.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/rc/RevisionController.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/rc/RevisionController.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/rc/RevisionController.java Fri Apr  1 05:30:25 2005
@@ -29,18 +29,16 @@
 import org.apache.log4j.Logger;
 
 /**
- * Controller for the reserved check-in, check-out, the backup versions and the rollback 
+ * Controller for the reserved check-in, check-out, the backup versions and the rollback
  */
 public class RevisionController {
     private static Logger log = Logger.getLogger(RevisionController.class);
 
     /**
-     * <code>systemUsername</code> The system user name. This is used for 
-     *  - creating dummy checkin events in a new RCML file
-     * when it is created on-the-fly
-     *  - system override on checkin, i.e. you can force
-     *  a checkin into the repository if you use this
-     *  username as identity parameter to reservedCheckIn()
+     * <code>systemUsername</code> The system user name. This is used for - creating dummy checkin
+     * events in a new RCML file when it is created on-the-fly - system override on checkin, i.e.
+     * you can force a checkin into the repository if you use this username as identity parameter to
+     * reservedCheckIn()
      */
     public static final String systemUsername = "System";
 
@@ -50,7 +48,7 @@
 
     /**
      * Creates a new RevisionController object.
-     *
+     * 
      * @param rcmlDirectory The directory for the RCML files
      * @param backupDirectory The directory for the backup versions
      * @param rootDirectory The publication directory
@@ -66,7 +64,8 @@
      * @return String The rcml directory, the backup directory, the publication directory
      */
     public String toString() {
-        return "rcmlDir=" + this.rcmlDir + " , rcbakDir=" + this.backupDir + " , rootDir=" + this.rootDir;
+        return "rcmlDir=" + this.rcmlDir + " , rcbakDir=" + this.backupDir + " , rootDir="
+                + this.rootDir;
     }
 
     /**
@@ -82,21 +81,35 @@
     }
 
     /**
+     * Returns the latest version of a source.
+     * @param source The path of the file from the publication.
+     * @return A version number.
+     * @throws Exception if an error occurs.
+     */
+    public int getLatestVersion(String source) throws Exception {
+        RCML rcml = new RCML(this.rcmlDir, source, this.rootDir);
+        CheckInEntry entry = rcml.getLatestCheckInEntry();
+        int version = 0;
+        if (entry != null) {
+            version = entry.getVersion();
+        }
+        return version;
+    }
+
+    /**
      * Try to make a reserved check out of the file source for a user with identity
-     *
+     * 
      * @param source The filename of the file to check out
      * @param identity The identity of the user
      * @return File File to check out
      * @throws Exception if an error occurs
      */
     public File reservedCheckOut(String source, String identity) throws Exception {
-        
+
         File file = new File(this.rootDir + source);
         /*
-        if (!file.isFile()) {
-            throw new FileNotFoundException(file.getAbsolutePath());
-        }
-        */
+         * if (!file.isFile()) { throw new FileNotFoundException(file.getAbsolutePath()); }
+         */
 
         RCML rcml = new RCML(this.rcmlDir, source, this.rootDir);
 
@@ -111,13 +124,12 @@
             log.debug("entry.identity" + entry.getIdentity());
         }
 
-        if ((entry != null)
-            && (entry.getType() != RCML.ci)
-            && !entry.getIdentity().equals(identity)) {
+        if ((entry != null) && (entry.getType() != RCML.ci)
+                && !entry.getIdentity().equals(identity)) {
             throw new FileReservedCheckOutException(this.rootDir + source, rcml);
         }
 
-        rcml.checkOutIn(RCML.co, identity, new Date().getTime(), false);
+        rcml.checkOutIn(RCML.co, identity, new Date().getTime(), false, false);
 
         return file;
     }
@@ -143,8 +155,8 @@
             log.debug("entry.identity" + entry.getIdentity());
         }
 
-        boolean checkedOutByOther =
-            entry != null && entry.getType() != RCML.ci && !entry.getIdentity().equals(identity);
+        boolean checkedOutByOther = entry != null && entry.getType() != RCML.ci
+                && !entry.getIdentity().equals(identity);
 
         return !checkedOutByOther;
     }
@@ -152,19 +164,20 @@
     /**
      * Try to make a reserved check in of the file destination for a user with identity. A backup
      * copy can be made.
-     *
+     * 
      * @param destination The file we want to check in
      * @param identity The identity of the user
      * @param backup if true, a backup will be created, else no backup will be made.
-     *
+     * @param newVersion If true, a new version will be created.
+     * 
      * @return long The time.
-     *
+     * 
      * @exception FileReservedCheckInException if the document couldn't be checked in (for instance
-     *            because it is already checked out by someone other ...)
+     *                because it is already checked out by someone other ...)
      * @exception Exception if other problems occur
      */
-    public long reservedCheckIn(String destination, String identity, boolean backup)
-        throws FileReservedCheckInException, Exception {
+    public long reservedCheckIn(String destination, String identity, boolean backup,
+            boolean newVersion) throws FileReservedCheckInException, Exception {
         FileInputStream in = null;
         FileOutputStream out = null;
 
@@ -187,23 +200,19 @@
             if (!((coe == null) || identity.equals(RevisionController.systemUsername))) {
                 /*
                  * Possible cases and rules:
-                 *
+                 * 
                  * 1.) we were able to read the latest checkin and it is later than latest checkout
-                 *     (i.e. there is no open checkout to match this checkin, an unusual case)
-                 *     1.1.) identity of latest checkin is equal to current user
-                 *           -> checkin allowed, same user may check in repeatedly
-                 *     1.2.) identity of latest checkin is not equal to current user
-                 *           -> checkin rejected, may not overwrite the revision which
-                 *              another user checked in previously
-                 * 2.) there was no checkin or the latest checkout is later than latest checkin
-                 *     (i.e. there is an open checkout)
-                 *     2.1.) identity of latest checkout is equal to current user
-                 *           -> checkin allowed, user checked out and may check in again
-                 *              (the most common case)
-                 *     2.2.) identity of latest checkout is not equal to current user
-                 *           -> checkin rejected, may not check in while another
-                 *              user is working on this document
-                 *
+                 * (i.e. there is no open checkout to match this checkin, an unusual case) 1.1.)
+                 * identity of latest checkin is equal to current user -> checkin allowed, same user
+                 * may check in repeatedly 1.2.) identity of latest checkin is not equal to current
+                 * user -> checkin rejected, may not overwrite the revision which another user
+                 * checked in previously 2.) there was no checkin or the latest checkout is later
+                 * than latest checkin (i.e. there is an open checkout) 2.1.) identity of latest
+                 * checkout is equal to current user -> checkin allowed, user checked out and may
+                 * check in again (the most common case) 2.2.) identity of latest checkout is not
+                 * equal to current user -> checkin rejected, may not check in while another user is
+                 * working on this document
+                 *  
                  */
                 if ((cie != null) && (cie.getTime() > coe.getTime())) {
                     // We have case 1
@@ -223,7 +232,7 @@
             }
 
             File originalFile = new File(this.rootDir, destination);
- 
+
             if (backup && originalFile.isFile()) {
                 File backupFile = new File(this.backupDir, destination + ".bak." + time);
                 File parent = new File(backupFile.getParent());
@@ -232,10 +241,7 @@
                     parent.mkdirs();
                 }
 
-                log.debug(
-                    "Backup: copy "
-                        + originalFile.getAbsolutePath()
-                        + " to "
+                log.debug("Backup: copy " + originalFile.getAbsolutePath() + " to "
                         + backupFile.getAbsolutePath());
 
                 in = new FileInputStream(originalFile.getAbsolutePath());
@@ -248,26 +254,26 @@
                 }
             }
 
-            rcml.checkOutIn(RCML.ci, identity, time, backup);
+            rcml.checkOutIn(RCML.ci, identity, time, backup, newVersion);
             rcml.pruneEntries(this.backupDir);
             rcml.write();
 
         } catch (final FileNotFoundException e) {
-            log.error("File not found" +e.toString());
+            log.error("File not found" + e.toString());
         } catch (final IOException e) {
-            log.error("IO error " +e.toString());
+            log.error("IO error " + e.toString());
         } finally {
-	        if (in != null)
-	            in.close();
-	        if (out != null)
-	            out.close();
+            if (in != null)
+                in.close();
+            if (out != null)
+                out.close();
         }
         return time;
     }
 
     /**
-     * Get the absolute path of a backup version  
-     * @param time The time of the backup 
+     * Get the absolute path of a backup version
+     * @param time The time of the backup
      * @param filename The path of the file from the {publication}
      * @return String The absolute path of the backup version
      */
@@ -277,8 +283,8 @@
     }
 
     /**
-     * Get the file of a backup version  
-     * @param time The time of the backup 
+     * Get the file of a backup version
+     * @param time The time of the backup
      * @param filename The path of the file from the {publication}
      * @return File The file of the backup version
      */
@@ -288,7 +294,7 @@
     }
 
     /**
-     * Rolls back to the given point in time.  
+     * Rolls back to the given point in time.
      * @param destination File which will be rolled back
      * @param identity The identity of the user
      * @param backupFlag If true, a backup of the current version will be made before the rollback
@@ -300,12 +306,9 @@
      * @exception Exception if another problem occurs
      */
     public long rollback(String destination, String identity, boolean backupFlag, long time)
-        throws
-            FileReservedCheckInException,
-            FileReservedCheckOutException,
-            FileNotFoundException,
-            Exception {
-        
+            throws FileReservedCheckInException, FileReservedCheckOutException,
+            FileNotFoundException, Exception {
+
         FileInputStream in = null;
         FileOutputStream out = null;
 
@@ -335,22 +338,22 @@
                 out.write(buffer, 0, length);
             }
         } catch (FileNotFoundException e) {
-            log.error("File not found " +e.toString());
+            log.error("File not found " + e.toString());
         } catch (IOException e) {
-            log.error("IO error " +e.toString());
+            log.error("IO error " + e.toString());
         } catch (Exception e) {
-            log.error("Exception " +e.toString());
+            log.error("Exception " + e.toString());
         } finally {
-	        if (in != null)
-	            in.close();
-	        if (out != null)
-	            out.close();
+            if (in != null)
+                in.close();
+            if (out != null)
+                out.close();
         }
 
         // Try to check back in, this might cause
         // a backup of the current version to be created if
         // desired by the user.
-        long newtime = reservedCheckIn(destination, identity, backupFlag);
+        long newtime = reservedCheckIn(destination, identity, backupFlag, false);
 
         return newtime;
     }
@@ -359,8 +362,8 @@
      * Delete the check in and roll back the file to the backup at time
      * @param time The time point of the back version we want to retrieve
      * @param destination The File for which we want undo the check in
-     * @exception Exception FileNotFoundException if the back  version or the current version
-     *            couldn't be found
+     * @exception Exception FileNotFoundException if the back version or the current version
+     *                couldn't be found
      */
     public void undoCheckIn(long time, String destination) throws Exception {
         FileInputStream in = null;
@@ -392,55 +395,54 @@
 
             rcml.deleteFirstCheckIn();
         } catch (FileNotFoundException e) {
-            log.error("File not found " +e.toString());
+            log.error("File not found " + e.toString());
         } catch (IOException e) {
-            log.error("IO error " +e.toString());
+            log.error("IO error " + e.toString());
         } catch (Exception e) {
-            log.error("Exception " +e.toString());
+            log.error("Exception " + e.toString());
         } finally {
-	        if (in != null)
-	            in.close();
-	        if (out != null)
-	            out.close();
+            if (in != null)
+                in.close();
+            if (out != null)
+                out.close();
         }
     }
 
     /**
      * delete the revisions
-	 * @param filename of the document
-	 * @throws RevisionControlException when somthing went wrong
-	 */
-	public void deleteRevisions(String filename) throws RevisionControlException{
+     * @param filename of the document
+     * @throws RevisionControlException when somthing went wrong
+     */
+    public void deleteRevisions(String filename) throws RevisionControlException {
         try {
-			RCML rcml = this.getRCML(filename);
+            RCML rcml = this.getRCML(filename);
             String[] times = rcml.getBackupsTime();
-            for (int i=0; i < times.length; i++) {
+            for (int i = 0; i < times.length; i++) {
                 long time = new Long(times[i]).longValue();
                 File backup = this.getBackupFile(time, filename);
-                File parentDirectory = null; 
-                parentDirectory = backup.getParentFile(); 
+                File parentDirectory = null;
+                parentDirectory = backup.getParentFile();
                 boolean deleted = backup.delete();
                 if (!deleted) {
-                    throw new RevisionControlException("The backup file, "+backup.getCanonicalPath()+" could not be deleted!");
+                    throw new RevisionControlException("The backup file, "
+                            + backup.getCanonicalPath() + " could not be deleted!");
                 }
-                if (parentDirectory != null 
-                    && parentDirectory.exists()
-                    && parentDirectory.isDirectory()
-                    && parentDirectory.listFiles().length == 0) {
-                        parentDirectory.delete();
+                if (parentDirectory != null && parentDirectory.exists()
+                        && parentDirectory.isDirectory() && parentDirectory.listFiles().length == 0) {
+                    parentDirectory.delete();
                 }
             }
-		} catch (Exception e) {
+        } catch (Exception e) {
             throw new RevisionControlException(e);
-		}
+        }
     }
-    
+
     /**
      * delete the rcml file
-	 * @param filename of the document
-	 * @throws RevisionControlException if something went wrong
-	 */
-	public void deleteRCML(String filename) throws RevisionControlException{
+     * @param filename of the document
+     * @throws RevisionControlException if something went wrong
+     */
+    public void deleteRCML(String filename) throws RevisionControlException {
         try {
             RCML rcml = this.getRCML(filename);
             boolean deleted = rcml.delete();
@@ -451,5 +453,5 @@
             throw new RevisionControlException(e);
         }
     }
-    
-}
+
+}
\ No newline at end of file

Modified: lenya/trunk/src/java/org/apache/lenya/cms/site/tree/DefaultSiteTree.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/site/tree/DefaultSiteTree.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/site/tree/DefaultSiteTree.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/site/tree/DefaultSiteTree.java Fri Apr  1 05:30:25 2005
@@ -28,10 +28,17 @@
 
 import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.lenya.ac.Identity;
+import org.apache.lenya.ac.User;
 import org.apache.lenya.cms.publication.Publication;
+import org.apache.lenya.cms.rc.RCEnvironment;
+import org.apache.lenya.cms.rc.RevisionController;
 import org.apache.lenya.cms.site.Label;
 import org.apache.lenya.cms.site.SiteException;
+import org.apache.lenya.transaction.IdentityMap;
+import org.apache.lenya.transaction.Lock;
 import org.apache.lenya.transaction.TransactionException;
+import org.apache.lenya.transaction.UnitOfWork;
 import org.apache.lenya.xml.DocumentHelper;
 import org.apache.lenya.xml.NamespaceHelper;
 import org.apache.xpath.XPathAPI;
@@ -64,6 +71,13 @@
     // the area is only retained to provide some more info when raising an
     // exception.
     private String area = "";
+    private IdentityMap identityMap;
+    private Publication publication;
+
+    protected void setup(IdentityMap map, Publication publication) {
+        this.identityMap = map;
+        this.publication = publication;
+    }
 
     /**
      * Create a DefaultSiteTree
@@ -549,48 +563,82 @@
      * @see org.apache.lenya.transaction.Transactionable#checkin()
      */
     public void checkin() throws TransactionException {
-        // TODO Auto-generated method stub
+        checkin(true);
+    }
 
+    protected void checkin(boolean backup) throws TransactionException {
+        try {
+            String userName = getUserID();
+            boolean newVersion = this.identityMap.getUnitOfWork().isDirty(this);
+            getRevisionController().reservedCheckIn(getRCPath(), userName, backup, newVersion);
+        } catch (Exception e) {
+            throw new TransactionException(e);
+        }
+    }
+
+    /**
+     * @return The username of the unit of work's identity.
+     */
+    protected String getUserID() {
+        String userName = null;
+        UnitOfWork unit = this.identityMap.getUnitOfWork();
+        Identity identity = unit.getIdentity();
+        User user = identity.getUser();
+        if (user != null) {
+            userName = user.getId();
+        }
+        return userName;
     }
 
     /**
      * @see org.apache.lenya.transaction.Transactionable#checkout()
      */
     public void checkout() throws TransactionException {
-        // TODO Auto-generated method stub
-
+        try {
+            String userName = getUserID();
+            getRevisionController().reservedCheckOut(getRCPath(), userName);
+        } catch (Exception e) {
+            throw new TransactionException(e);
+        }
+    }
+    
+    protected String getRCPath() {
+        return this.area + "/" + SITE_TREE_FILENAME;
     }
 
     /**
      * @see org.apache.lenya.transaction.Transactionable#isCheckedOut()
      */
     public boolean isCheckedOut() throws TransactionException {
-        // TODO Auto-generated method stub
-        return false;
+        try {
+            String userName = getUserID();
+            return !getRevisionController().canCheckOut(getRCPath(), userName);
+        } catch (Exception e) {
+            throw new TransactionException(e);
+        }
     }
 
+    private Lock lock;
+
     /**
      * @see org.apache.lenya.transaction.Transactionable#lock()
      */
     public void lock() throws TransactionException {
-        // TODO Auto-generated method stub
-
+        this.lock = new Lock(getVersion());
     }
 
     /**
      * @see org.apache.lenya.transaction.Transactionable#unlock()
      */
     public void unlock() throws TransactionException {
-        // TODO Auto-generated method stub
-
+        this.lock = null;
     }
 
     /**
      * @see org.apache.lenya.transaction.Transactionable#isLocked()
      */
     public boolean isLocked() throws TransactionException {
-        // TODO Auto-generated method stub
-        return false;
+        return this.lock != null;
     }
 
     /**
@@ -612,4 +660,44 @@
     public void create() throws TransactionException {
     }
 
+    private RevisionController revisionController;
+
+    protected RevisionController getRevisionController() throws TransactionException {
+        if (this.revisionController == null) {
+            try {
+                String publicationPath = this.publication.getDirectory().getCanonicalPath();
+                RCEnvironment rcEnvironment = RCEnvironment.getInstance(this.publication
+                        .getServletContext().getCanonicalPath());
+                String rcmlDirectory = publicationPath + File.separator
+                        + rcEnvironment.getRCMLDirectory();
+                String backupDirectory = publicationPath + File.separator
+                        + rcEnvironment.getBackupDirectory();
+
+                this.revisionController = new RevisionController(rcmlDirectory, backupDirectory,
+                        publicationPath);
+            } catch (IOException e) {
+                throw new TransactionException(e);
+            }
+        }
+        return this.revisionController;
+    }
+
+    /**
+     * @see org.apache.lenya.transaction.Transactionable#getLock()
+     */
+    public Lock getLock() {
+        return this.lock;
+    }
+
+    /**
+     * @see org.apache.lenya.transaction.Transactionable#getVersion()
+     */
+    public int getVersion() throws TransactionException {
+        try {
+            String fileName = this.treefile.getCanonicalPath();
+            return getRevisionController().getLatestVersion(fileName);
+        } catch (Exception e) {
+            throw new TransactionException(e);
+        }
+    }
 }

Modified: lenya/trunk/src/java/org/apache/lenya/cms/site/tree/SiteTreeFactory.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/site/tree/SiteTreeFactory.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/site/tree/SiteTreeFactory.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/site/tree/SiteTreeFactory.java Fri Apr  1 05:30:25 2005
@@ -58,7 +58,7 @@
 
         SourceResolver resolver = null;
         Source source = null;
-        SiteTree tree;
+        DefaultSiteTree tree;
         try {
             resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
             source = resolver.resolveURI("context://");
@@ -69,6 +69,7 @@
                     .getAbsolutePath());
            
             tree = new DefaultSiteTree(publication.getDirectory(), area);
+            tree.setup(map, publication);
             ContainerUtil.enableLogging(tree, getLogger());
             
         } finally {

Modified: lenya/trunk/src/java/org/apache/lenya/cms/site/tree/TreeSiteManager.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/site/tree/TreeSiteManager.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/site/tree/TreeSiteManager.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/site/tree/TreeSiteManager.java Fri Apr  1 05:30:25 2005
@@ -32,6 +32,7 @@
 import org.apache.lenya.cms.site.AbstractSiteManager;
 import org.apache.lenya.cms.site.Label;
 import org.apache.lenya.cms.site.SiteException;
+import org.apache.lenya.transaction.TransactionException;
 import org.apache.lenya.transaction.TransactionableFactory;
 
 /**
@@ -60,15 +61,16 @@
     public SiteTree getTree(DocumentIdentityMap map, Publication publication, String area)
             throws SiteException {
 
+        String key = getKey(publication, area);
+        DefaultSiteTree sitetree;
         TransactionableFactory factory = map.getFactory(SiteTree.TRANSACTIONABLE_TYPE);
         if (factory == null) {
             factory = new SiteTreeFactory(this.manager);
             ContainerUtil.enableLogging(factory, getLogger());
             map.setFactory(SiteTree.TRANSACTIONABLE_TYPE, factory);
         }
+        sitetree = (DefaultSiteTree) map.get(SiteTree.TRANSACTIONABLE_TYPE, key);
 
-        String key = getKey(publication, area);
-        DefaultSiteTree sitetree = (DefaultSiteTree) map.get(SiteTree.TRANSACTIONABLE_TYPE, key);
         return sitetree;
     }
 
@@ -240,7 +242,11 @@
             destinationTree.setLabel(destinationDocument.getId(), label);
         }
 
-        sourceDocument.getIdentityMap().getUnitOfWork().registerDirty(destinationTree);
+        try {
+            sourceDocument.getIdentityMap().getUnitOfWork().registerDirty(destinationTree);
+        } catch (TransactionException e) {
+            throw new SiteException(e);
+        }
     }
 
     /**
@@ -273,8 +279,11 @@
         if (node.getLabels().length == 0) {
             tree.removeNode(document.getId());
         }
-
-        document.getIdentityMap().getUnitOfWork().registerDirty(tree);
+        try {
+            document.getIdentityMap().getUnitOfWork().registerDirty(tree);
+        } catch (TransactionException e) {
+            throw new SiteException(e);
+        }
     }
 
     /**
@@ -295,7 +304,11 @@
 
         SiteTree tree = getTree(document);
         tree.setLabel(document.getId(), labelObject);
-        document.getIdentityMap().getUnitOfWork().registerDirty(tree);
+        try {
+            document.getIdentityMap().getUnitOfWork().registerDirty(tree);
+        } catch (TransactionException e) {
+            throw new SiteException(e);
+        }
     }
 
     /**
@@ -357,7 +370,11 @@
         if (node == null) {
             Label[] labels = { label };
             tree.addNode(document.getId(), labels, null, null, false);
-            document.getIdentityMap().getUnitOfWork().registerDirty(tree);
+            try {
+                document.getIdentityMap().getUnitOfWork().registerDirty(tree);
+            } catch (TransactionException e) {
+                throw new SiteException(e);
+            }
         } else {
             tree.addLabel(document.getId(), label);
         }

Modified: lenya/trunk/src/java/org/apache/lenya/cms/usecase/AbstractUsecase.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/usecase/AbstractUsecase.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/usecase/AbstractUsecase.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/usecase/AbstractUsecase.java Fri Apr  1 05:30:25 2005
@@ -29,6 +29,7 @@
 import org.apache.avalon.framework.context.Context;
 import org.apache.avalon.framework.context.ContextException;
 import org.apache.avalon.framework.context.Contextualizable;
+import org.apache.avalon.framework.service.ServiceException;
 import org.apache.cocoon.components.ContextHelper;
 import org.apache.cocoon.environment.Request;
 import org.apache.cocoon.environment.Session;
@@ -201,11 +202,11 @@
             clearInfoMessages();
             doExecute();
             dumpErrorMessages();
-            
+
             if (getErrorMessages().size() == 0) {
                 getUnitOfWork().commit();
             }
-            
+
         } catch (Exception e) {
             getLogger().error(e.getMessage(), e);
             addErrorMessage(e.getMessage() + " - Please consult the logfiles.");
@@ -405,19 +406,21 @@
         this.context = _context;
     }
 
-    private DocumentIdentityMap documentIdentityMap;
-    
     protected DocumentIdentityMap getDocumentIdentityMap() {
-        return this.documentIdentityMap;
+        try {
+            return (DocumentIdentityMap) getUnitOfWork().getIdentityMap();
+        } catch (ServiceException e) {
+            throw new RuntimeException(e);
+        }
     }
-    
+
     /**
      * @see org.apache.avalon.framework.activity.Initializable#initialize()
      */
     public final void initialize() throws Exception {
         super.initialize();
-        this.documentIdentityMap = new DocumentIdentityMap(this.manager, getLogger());
-        getUnitOfWork().addIdentityMap(this.documentIdentityMap);
+        DocumentIdentityMap map = new DocumentIdentityMap(this.manager, getLogger());
+        getUnitOfWork().setIdentityMap(map);
         Request request = ContextHelper.getRequest(this.context);
         Session session = request.getSession(true);
         Identity identity = (Identity) session.getAttribute(Identity.class.getName());

Modified: lenya/trunk/src/java/org/apache/lenya/cms/workflow/History.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/workflow/History.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/workflow/History.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/workflow/History.java Fri Apr  1 05:30:25 2005
@@ -226,7 +226,6 @@
                 Element versionElement = versions[i].getVersionElement(helper);
                 documentElement.appendChild(versionElement);
             }
-System.out.println("Saving file [" + getHistoryFile().getAbsolutePath() + "]");
             DocumentHelper.writeDocument(helper.getDocument(), getHistoryFile());
         } catch (final Exception e) {
             throw new RuntimeException(e);

Modified: lenya/trunk/src/java/org/apache/lenya/transaction/IdentityMap.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/transaction/IdentityMap.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/transaction/IdentityMap.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/transaction/IdentityMap.java Fri Apr  1 05:30:25 2005
@@ -54,5 +54,10 @@
      * @param unit The unit of work to use.
      */
     void setUnitOfWork(UnitOfWork unit);
+    
+    /**
+     * @return All objects in this map.
+     */
+    Transactionable[] getObjects();
 
 }

Modified: lenya/trunk/src/java/org/apache/lenya/transaction/IdentityMapImpl.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/transaction/IdentityMapImpl.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/transaction/IdentityMapImpl.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/transaction/IdentityMapImpl.java Fri Apr  1 05:30:25 2005
@@ -17,7 +17,10 @@
 package org.apache.lenya.transaction;
 
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.avalon.framework.logger.AbstractLogEnabled;
 
@@ -43,6 +46,7 @@
         if (transactionable == null) {
             try {
                 transactionable = getFactory(type).build(this, key);
+                transactionable.lock();
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
@@ -82,6 +86,20 @@
      */
     public void setUnitOfWork(UnitOfWork unit) {
         this.unitOfWork = unit;
+    }
+
+    /**
+     * @see org.apache.lenya.transaction.IdentityMap#getObjects()
+     */
+    public Transactionable[] getObjects() {
+        Set objects = new HashSet();
+        for (Iterator i = this.maps.values().iterator(); i.hasNext(); ) {
+            Map map = (Map) i.next();
+            for (Iterator j = map.values().iterator(); j.hasNext(); ) {
+                objects.add(j.next());
+            }
+        }
+        return (Transactionable[]) objects.toArray(new Transactionable[objects.size()]);
     }
 
 }

Added: lenya/trunk/src/java/org/apache/lenya/transaction/Lock.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/transaction/Lock.java?view=auto&rev=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/transaction/Lock.java (added)
+++ lenya/trunk/src/java/org/apache/lenya/transaction/Lock.java Fri Apr  1 05:30:25 2005
@@ -0,0 +1,43 @@
+/*
+ * Copyright  1999-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.lenya.transaction;
+
+/**
+ * A lock on a transactionable.
+ *
+ * @version $Id:$
+ */
+public class Lock {
+
+    /**
+     * Ctor.
+     * @param version The version of the transactionable when it was locked.
+     */
+    public Lock(int version) {
+        this.version = version;
+    }
+    
+    private int version;
+    
+    /**
+     * @return The version number.
+     */
+    public int getVersion() {
+        return this.version;
+    }
+    
+}

Modified: lenya/trunk/src/java/org/apache/lenya/transaction/Transactionable.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/transaction/Transactionable.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/transaction/Transactionable.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/transaction/Transactionable.java Fri Apr  1 05:30:25 2005
@@ -66,6 +66,11 @@
     void lock() throws TransactionException;
     
     /**
+     * @return The lock which is held by this object.
+     */
+    Lock getLock();
+    
+    /**
      * Unlocks this object.
      * @throws TransactionException if an error occurs.
      */
@@ -81,5 +86,11 @@
      * @return The type of the transactionable.
      */
     String getTransactionableType();
+    
+    /**
+     * @return The latest version.
+     * @throws TransactionException if an error occurs.
+     */
+    int getVersion() throws TransactionException;
     
 }

Modified: lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWork.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWork.java?view=diff&r1=159684&r2=159685
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWork.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/transaction/UnitOfWork.java Fri Apr  1 05:30:25 2005
@@ -38,34 +38,36 @@
     String ROLE = UnitOfWork.class.getName();
 
     /**
-     * Returns the identity maps.
-     * @return An array of identity maps.
+     * Returns the identity map.
+     * @return An identity map.
      */
-    IdentityMap[] getIdentityMaps();
+    IdentityMap getIdentityMap();
     
     /**
-     * Adds an identity map.
-     * @param map The map to add.
+     * @param map The identity map to use.
      */
-    void addIdentityMap(IdentityMap map);
-
+    void setIdentityMap(IdentityMap map);
+    
     /**
      * Registers an object as new.
      * @param object The object.
+     * @throws TransactionException if an error occurs.
      */
-    void registerNew(Transactionable object);
+    void registerNew(Transactionable object) throws TransactionException;
     
     /**
      * Registers an object as modified.
      * @param object The object.
+     * @throws TransactionException if an error occurs.
      */
-    void registerDirty(Transactionable object);
+    void registerDirty(Transactionable object) throws TransactionException;
     
     /**
      * Registers an object as removed.
      * @param object The object.
+     * @throws TransactionException if an error occurs.
      */
-    void registerRemoved(Transactionable object);
+    void registerRemoved(Transactionable object) throws TransactionException;
     
     /**
      * Commits the transaction.
@@ -82,4 +84,10 @@
      * @param identity The identity.
      */
     void setIdentity(Identity identity);
+    
+    /**
+     * @param transactionable A transactionable.
+     * @return If the transactionable is registered as dirty.
+     */
+    boolean isDirty(Transactionable transactionable);
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@lenya.apache.org
For additional commands, e-mail: commits-help@lenya.apache.org