svn commit: r564264 [2/3] - in /lenya/trunk/src: impl/java/org/apache/lenya/cms/repository/ impl/test/org/apache/lenya/cms/rc/ impl/test/org/apache/lenya/transaction/ java/org/apache/lenya/cms/cocoon/acting/ java/org/apache/lenya/cms/cocoon/flow/ java/...

[email protected]
Newsgroups gmane.comp.cms.lenya.cvs
Message-ID <[email protected]>
Modified: lenya/trunk/src/modules/development/test/jmeter/lenyaJMeterTest.jmx
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/development/test/jmeter/lenyaJMeterTest.jmx?view=diff&rev=564264&r1=564263&r2=564264
==============================================================================
--- lenya/trunk/src/modules/development/test/jmeter/lenyaJMeterTest.jmx (original)
+++ lenya/trunk/src/modules/development/test/jmeter/lenyaJMeterTest.jmx Thu Aug  9 09:28:15 2007
@@ -1,7 +1,7 @@
 <jmeterTestPlan version="1.2" properties="1.8">
   <hashTree>
     <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="CMS" enabled="true">
-      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
+      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="Benutzer definierte Variablen" enabled="true">
         <collectionProp name="Arguments.arguments">
           <elementProp name="server" elementType="Argument">
             <stringProp name="Argument.metadata">=</stringProp>
@@ -25,10 +25,10 @@
         <longProp name="ThreadGroup.start_time">1178792744000</longProp>
         <stringProp name="ThreadGroup.delay"></stringProp>
         <stringProp name="ThreadGroup.duration"></stringProp>
-        <stringProp name="ThreadGroup.num_threads">2</stringProp>
+        <stringProp name="ThreadGroup.num_threads">5</stringProp>
         <boolProp name="ThreadGroup.scheduler">false</boolProp>
         <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Controlador Loop" enabled="true">
-          <stringProp name="LoopController.loops">25</stringProp>
+          <stringProp name="LoopController.loops">1</stringProp>
           <boolProp name="LoopController.continue_forever">false</boolProp>
         </elementProp>
         <longProp name="ThreadGroup.end_time">1178792744000</longProp>
@@ -46,18 +46,28 @@
           <stringProp name="HTTPSampler.path"></stringProp>
           <stringProp name="HTTPSampler.domain">${server}</stringProp>
           <stringProp name="HTTPSampler.protocol">HTTP</stringProp>
+          <stringProp name="HTTPSampler.port">8888</stringProp>
           <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables definidas por el Usuario" enabled="true">
             <collectionProp name="Arguments.arguments"/>
           </elementProp>
-          <stringProp name="HTTPSampler.port">8888</stringProp>
         </ConfigTestElement>
         <hashTree/>
+        <Arguments guiclass="ArgumentsPanel" testclass="Arguments" testname="Variables" enabled="true">
+          <collectionProp name="Arguments.arguments">
+            <elementProp name="password" elementType="Argument">
+              <stringProp name="Argument.metadata">=</stringProp>
+              <stringProp name="Argument.value">foo123</stringProp>
+              <stringProp name="Argument.name">password</stringProp>
+            </elementProp>
+          </collectionProp>
+        </Arguments>
+        <hashTree/>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
-          <stringProp name="RandomTimer.range">500</stringProp>
           <stringProp name="ConstantTimer.delay">1500</stringProp>
+          <stringProp name="RandomTimer.range">500</stringProp>
         </GaussianRandomTimer>
         <hashTree/>
-        <OnceOnlyController guiclass="OnceOnlyControllerGui" testclass="OnceOnlyController" testname="Only once" enabled="true"/>
+        <OnceOnlyController guiclass="OnceOnlyControllerGui" testclass="OnceOnlyController" testname="Login &quot;lenya&quot;" enabled="true"/>
         <hashTree>
           <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Login page" enabled="true">
             <stringProp name="HTTPSampler.path">/default/authoring/index.html</stringProp>
@@ -81,8 +91,266 @@
               <stringProp name="RegexExtractor.default">error</stringProp>
               <stringProp name="RegexExtractor.regex">lenya.continuation=(.*?)&amp;amp;lenya.usecase=ac.login&quot;&gt;</stringProp>
               <stringProp name="RegexExtractor.useHeaders">false</stringProp>
+              <stringProp name="RegexExtractor.match_number">0</stringProp>
+              <stringProp name="RegexExtractor.template">$1$</stringProp>
+              <stringProp name="RegexExtractor.refname">lenya.continuation</stringProp>
+            </RegexExtractor>
+            <hashTree/>
+          </hashTree>
+          <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Login page" enabled="true">
+            <stringProp name="HTTPSampler.path">/default/authoring/jmeter.html?lenya.usecase=ac.login&amp;lenya.continuation=${lenya.continuation}</stringProp>
+            <stringProp name="HTTPSampler.method">POST</stringProp>
+            <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
+            <stringProp name="HTTPSampler.protocol"></stringProp>
+            <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
+            <stringProp name="HTTPSampler.port"></stringProp>
+            <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables definidas por el Usuario" enabled="true">
+              <collectionProp name="Arguments.arguments">
+                <elementProp name="" elementType="HTTPArgument">
+                  <stringProp name="Argument.metadata">=</stringProp>
+                  <stringProp name="Argument.value">lenya</stringProp>
+                  <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                  <stringProp name="Argument.name">username</stringProp>
+                  <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                </elementProp>
+                <elementProp name="" elementType="HTTPArgument">
+                  <stringProp name="Argument.metadata">=</stringProp>
+                  <stringProp name="Argument.value">levi</stringProp>
+                  <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                  <stringProp name="Argument.name">password</stringProp>
+                  <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                </elementProp>
+                <elementProp name="" elementType="HTTPArgument">
+                  <stringProp name="Argument.metadata">=</stringProp>
+                  <stringProp name="Argument.value">Login</stringProp>
+                  <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                  <stringProp name="Argument.name">submit</stringProp>
+                  <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                </elementProp>
+              </collectionProp>
+            </elementProp>
+            <stringProp name="HTTPSampler.mimetype"></stringProp>
+            <stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
+            <stringProp name="HTTPSampler.monitor">false</stringProp>
+            <stringProp name="HTTPSampler.domain"></stringProp>
+            <stringProp name="HTTPSampler.FILE_NAME"></stringProp>
+            <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
+          </HTTPSampler>
+          <hashTree>
+            <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header" enabled="true">
+              <collectionProp name="HeaderManager.headers">
+                <elementProp name="" elementType="Header">
+                  <stringProp name="Header.value">application/x-www-form-urlencoded</stringProp>
+                  <stringProp name="Header.name">Content-Type</stringProp>
+                </elementProp>
+              </collectionProp>
+            </HeaderManager>
+            <hashTree/>
+          </hashTree>
+        </hashTree>
+        <OnceOnlyController guiclass="OnceOnlyControllerGui" testclass="OnceOnlyController" testname="Add admin user" enabled="true"/>
+        <hashTree>
+          <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Add user" enabled="true">
+            <stringProp name="HTTPSampler.path">/default/authoring/index.html?lenya.usecase=admin.addUser</stringProp>
+            <stringProp name="HTTPSampler.method">GET</stringProp>
+            <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
+            <stringProp name="HTTPSampler.protocol"></stringProp>
+            <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
+            <stringProp name="HTTPSampler.port"></stringProp>
+            <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables definidas por el Usuario" enabled="true">
+              <collectionProp name="Arguments.arguments"/>
+            </elementProp>
+            <stringProp name="HTTPSampler.mimetype"></stringProp>
+            <stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
+            <stringProp name="HTTPSampler.monitor">false</stringProp>
+            <stringProp name="HTTPSampler.domain"></stringProp>
+            <stringProp name="HTTPSampler.FILE_NAME"></stringProp>
+            <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
+          </HTTPSampler>
+          <hashTree>
+            <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor" enabled="true">
+              <stringProp name="RegexExtractor.default">error</stringProp>
+              <stringProp name="RegexExtractor.regex">name=\&quot;lenya.continuation\&quot;[\s]value=\&quot;(.*)\&quot;</stringProp>
+              <stringProp name="RegexExtractor.useHeaders">false</stringProp>
+              <stringProp name="RegexExtractor.match_number">1</stringProp>
+              <stringProp name="RegexExtractor.template">$1$</stringProp>
+              <stringProp name="RegexExtractor.refname">lenya.continuation</stringProp>
+            </RegexExtractor>
+            <hashTree/>
+          </hashTree>
+          <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Add user" enabled="true">
+            <stringProp name="HTTPSampler.path">/default/authoring/jmeter.html?lenya.usecase=admin.addUser&amp;lenya.continuation=${lenya.continuation}</stringProp>
+            <stringProp name="HTTPSampler.method">POST</stringProp>
+            <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
+            <stringProp name="HTTPSampler.protocol"></stringProp>
+            <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
+            <stringProp name="HTTPSampler.port"></stringProp>
+            <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables definidas por el Usuario" enabled="true">
+              <collectionProp name="Arguments.arguments">
+                <elementProp name="" elementType="HTTPArgument">
+                  <stringProp name="Argument.metadata">=</stringProp>
+                  <stringProp name="Argument.value">admin${__threadNum}</stringProp>
+                  <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                  <stringProp name="Argument.name">userId</stringProp>
+                  <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                </elementProp>
+                <elementProp name="" elementType="HTTPArgument">
+                  <stringProp name="Argument.metadata">=</stringProp>
+                  <stringProp name="Argument.value">${password}</stringProp>
+                  <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                  <stringProp name="Argument.name">newPassword</stringProp>
+                  <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                </elementProp>
+                <elementProp name="" elementType="HTTPArgument">
+                  <stringProp name="Argument.metadata">=</stringProp>
+                  <stringProp name="Argument.value">Submit</stringProp>
+                  <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                  <stringProp name="Argument.name">submit</stringProp>
+                  <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                </elementProp>
+                <elementProp name="" elementType="HTTPArgument">
+                  <stringProp name="Argument.metadata">=</stringProp>
+                  <stringProp name="Argument.value">${password}</stringProp>
+                  <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                  <stringProp name="Argument.name">confirmPassword</stringProp>
+                  <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                </elementProp>
+                <elementProp name="" elementType="HTTPArgument">
+                  <stringProp name="Argument.metadata">=</stringProp>
+                  <stringProp name="Argument.value">[email protected]</stringProp>
+                  <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                  <stringProp name="Argument.name">email</stringProp>
+                  <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                </elementProp>
+                <elementProp name="" elementType="HTTPArgument">
+                  <stringProp name="Argument.metadata">=</stringProp>
+                  <stringProp name="Argument.value">org.apache.lenya.ac.file.FileUser</stringProp>
+                  <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                  <stringProp name="Argument.name">className</stringProp>
+                  <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                </elementProp>
+              </collectionProp>
+            </elementProp>
+            <stringProp name="HTTPSampler.mimetype"></stringProp>
+            <stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
+            <stringProp name="HTTPSampler.monitor">false</stringProp>
+            <stringProp name="HTTPSampler.domain"></stringProp>
+            <stringProp name="HTTPSampler.FILE_NAME"></stringProp>
+            <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
+          </HTTPSampler>
+          <hashTree>
+            <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header" enabled="true">
+              <collectionProp name="HeaderManager.headers">
+                <elementProp name="" elementType="Header">
+                  <stringProp name="Header.value">application/x-www-form-urlencoded</stringProp>
+                  <stringProp name="Header.name">Content-Type</stringProp>
+                </elementProp>
+              </collectionProp>
+            </HeaderManager>
+            <hashTree/>
+          </hashTree>
+        </hashTree>
+        <OnceOnlyController guiclass="OnceOnlyControllerGui" testclass="OnceOnlyController" testname="Logout" enabled="true"/>
+        <hashTree>
+          <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Logout page" enabled="true">
+            <stringProp name="HTTPSampler.path">/default/authoring/index.html</stringProp>
+            <stringProp name="HTTPSampler.method">GET</stringProp>
+            <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
+            <stringProp name="HTTPSampler.protocol"></stringProp>
+            <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
+            <stringProp name="HTTPSampler.port"></stringProp>
+            <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables definidas por el Usuario" enabled="true">
+              <collectionProp name="Arguments.arguments">
+                <elementProp name="" elementType="HTTPArgument">
+                  <stringProp name="Argument.metadata">=</stringProp>
+                  <stringProp name="Argument.value">ac.logout</stringProp>
+                  <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                  <stringProp name="Argument.name">lenya.usecase</stringProp>
+                  <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                </elementProp>
+              </collectionProp>
+            </elementProp>
+            <stringProp name="HTTPSampler.mimetype"></stringProp>
+            <stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
+            <stringProp name="HTTPSampler.monitor">false</stringProp>
+            <stringProp name="HTTPSampler.domain"></stringProp>
+            <stringProp name="HTTPSampler.FILE_NAME"></stringProp>
+            <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
+          </HTTPSampler>
+          <hashTree>
+            <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor" enabled="true">
+              <stringProp name="RegexExtractor.default">error</stringProp>
+              <stringProp name="RegexExtractor.regex">name=\&quot;lenya.continuation\&quot;[\s]value=\&quot;(.*)\&quot;</stringProp>
+              <stringProp name="RegexExtractor.useHeaders">false</stringProp>
+              <stringProp name="RegexExtractor.match_number">1</stringProp>
               <stringProp name="RegexExtractor.template">$1$</stringProp>
+              <stringProp name="RegexExtractor.refname">lenya.continuation</stringProp>
+            </RegexExtractor>
+            <hashTree/>
+          </hashTree>
+          <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Logout page" enabled="true">
+            <stringProp name="HTTPSampler.path">/default/authoring/jmeter.html?lenya.usecase=ac.logout&amp;lenya.continuation=${lenya.continuation}</stringProp>
+            <stringProp name="HTTPSampler.method">POST</stringProp>
+            <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
+            <stringProp name="HTTPSampler.protocol"></stringProp>
+            <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
+            <stringProp name="HTTPSampler.port"></stringProp>
+            <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables definidas por el Usuario" enabled="true">
+              <collectionProp name="Arguments.arguments">
+                <elementProp name="" elementType="HTTPArgument">
+                  <stringProp name="Argument.metadata">=</stringProp>
+                  <stringProp name="Argument.value">Login</stringProp>
+                  <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                  <stringProp name="Argument.name">submit</stringProp>
+                  <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                </elementProp>
+              </collectionProp>
+            </elementProp>
+            <stringProp name="HTTPSampler.mimetype"></stringProp>
+            <stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
+            <stringProp name="HTTPSampler.monitor">false</stringProp>
+            <stringProp name="HTTPSampler.domain"></stringProp>
+            <stringProp name="HTTPSampler.FILE_NAME"></stringProp>
+            <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
+          </HTTPSampler>
+          <hashTree>
+            <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header" enabled="true">
+              <collectionProp name="HeaderManager.headers">
+                <elementProp name="" elementType="Header">
+                  <stringProp name="Header.value">application/x-www-form-urlencoded</stringProp>
+                  <stringProp name="Header.name">Content-Type</stringProp>
+                </elementProp>
+              </collectionProp>
+            </HeaderManager>
+            <hashTree/>
+          </hashTree>
+        </hashTree>
+        <OnceOnlyController guiclass="OnceOnlyControllerGui" testclass="OnceOnlyController" testname="Login admin user" enabled="true"/>
+        <hashTree>
+          <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Login page" enabled="true">
+            <stringProp name="HTTPSampler.path">/default/authoring/index.html</stringProp>
+            <stringProp name="HTTPSampler.method">GET</stringProp>
+            <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
+            <stringProp name="HTTPSampler.protocol"></stringProp>
+            <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
+            <stringProp name="HTTPSampler.port"></stringProp>
+            <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables definidas por el Usuario" enabled="true">
+              <collectionProp name="Arguments.arguments"/>
+            </elementProp>
+            <stringProp name="HTTPSampler.mimetype"></stringProp>
+            <stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
+            <stringProp name="HTTPSampler.monitor">false</stringProp>
+            <stringProp name="HTTPSampler.domain"></stringProp>
+            <stringProp name="HTTPSampler.FILE_NAME"></stringProp>
+            <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
+          </HTTPSampler>
+          <hashTree>
+            <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor" enabled="true">
+              <stringProp name="RegexExtractor.default">error</stringProp>
+              <stringProp name="RegexExtractor.regex">lenya.continuation=(.*?)&amp;amp;lenya.usecase=ac.login&quot;&gt;</stringProp>
+              <stringProp name="RegexExtractor.useHeaders">false</stringProp>
               <stringProp name="RegexExtractor.match_number">0</stringProp>
+              <stringProp name="RegexExtractor.template">$1$</stringProp>
               <stringProp name="RegexExtractor.refname">lenya.continuation</stringProp>
             </RegexExtractor>
             <hashTree/>
@@ -98,7 +366,7 @@
               <collectionProp name="Arguments.arguments">
                 <elementProp name="" elementType="HTTPArgument">
                   <stringProp name="Argument.metadata">=</stringProp>
-                  <stringProp name="Argument.value">admin${__counter(FALSE,numAdmin)}</stringProp>
+                  <stringProp name="Argument.value">lenya</stringProp>
                   <boolProp name="HTTPArgument.use_equals">true</boolProp>
                   <stringProp name="Argument.name">username</stringProp>
                   <boolProp name="HTTPArgument.always_encode">false</boolProp>
@@ -138,9 +406,10 @@
             <hashTree/>
           </hashTree>
         </hashTree>
-        <InterleaveControl guiclass="InterleaveControlGui" testclass="InterleaveControl" testname="Interleave" enabled="true">
-          <intProp name="InterleaveControl.style">1</intProp>
-        </InterleaveControl>
+        <LoopController guiclass="LoopControlPanel" testclass="LoopController" testname="Loop" enabled="true">
+          <stringProp name="LoopController.loops">20</stringProp>
+          <boolProp name="LoopController.continue_forever">true</boolProp>
+        </LoopController>
         <hashTree>
           <GenericController guiclass="LogicControllerGui" testclass="GenericController" testname="News" enabled="true"/>
           <hashTree>
@@ -166,135 +435,153 @@
                 <stringProp name="RegexExtractor.default">error</stringProp>
                 <stringProp name="RegexExtractor.regex">name=&quot;lenya.continuation&quot; value=&quot;(.*?)&quot;</stringProp>
                 <stringProp name="RegexExtractor.useHeaders">false</stringProp>
-                <stringProp name="RegexExtractor.template">$1$</stringProp>
                 <stringProp name="RegexExtractor.match_number">0</stringProp>
+                <stringProp name="RegexExtractor.template">$1$</stringProp>
                 <stringProp name="RegexExtractor.refname">lenya.continuation</stringProp>
               </RegexExtractor>
               <hashTree/>
             </hashTree>
-            <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Validation" enabled="true">
-              <stringProp name="HTTPSampler.path">/default/authoring/jmeter.html</stringProp>
-              <stringProp name="HTTPSampler.method">GET</stringProp>
-              <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
-              <stringProp name="HTTPSampler.protocol"></stringProp>
-              <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
-              <stringProp name="HTTPSampler.port"></stringProp>
-              <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables definidas por el Usuario" enabled="true">
-                <collectionProp name="Arguments.arguments">
-                  <elementProp name="" elementType="HTTPArgument">
-                    <stringProp name="Argument.metadata">=</stringProp>
-                    <stringProp name="Argument.value">${lenya.continuation}</stringProp>
-                    <boolProp name="HTTPArgument.use_equals">true</boolProp>
-                    <stringProp name="Argument.name">lenya.continuation</stringProp>
-                    <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                  </elementProp>
-                  <elementProp name="" elementType="HTTPArgument">
-                    <stringProp name="Argument.metadata">=</stringProp>
-                    <stringProp name="Argument.value">sitemanagement.create</stringProp>
-                    <boolProp name="HTTPArgument.use_equals">true</boolProp>
-                    <stringProp name="Argument.name">lenya.usecase</stringProp>
-                    <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                  </elementProp>
-                  <elementProp name="" elementType="HTTPArgument">
-                    <stringProp name="Argument.metadata">=</stringProp>
-                    <stringProp name="Argument.value">Noticia${contador_noticia}</stringProp>
-                    <boolProp name="HTTPArgument.use_equals">true</boolProp>
-                    <stringProp name="Argument.name">nodeName</stringProp>
-                    <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                  </elementProp>
-                  <elementProp name="" elementType="HTTPArgument">
-                    <stringProp name="Argument.metadata">=</stringProp>
-                    <stringProp name="Argument.value">Noticia+${contador_noticia}</stringProp>
-                    <boolProp name="HTTPArgument.use_equals">true</boolProp>
-                    <stringProp name="Argument.name">dublincore.title</stringProp>
-                    <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                  </elementProp>
-                  <elementProp name="" elementType="HTTPArgument">
-                    <stringProp name="Argument.metadata">=</stringProp>
-                    <stringProp name="Argument.value">true</stringProp>
-                    <boolProp name="HTTPArgument.use_equals">true</boolProp>
-                    <stringProp name="Argument.name">visibleInNav</stringProp>
-                    <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                  </elementProp>
-                  <elementProp name="" elementType="HTTPArgument">
-                    <stringProp name="Argument.metadata">=</stringProp>
-                    <stringProp name="Argument.value">child</stringProp>
-                    <boolProp name="HTTPArgument.use_equals">true</boolProp>
-                    <stringProp name="Argument.name">relation</stringProp>
-                    <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                  </elementProp>
-                  <elementProp name="" elementType="HTTPArgument">
-                    <stringProp name="Argument.metadata">=</stringProp>
-                    <stringProp name="Argument.value">en</stringProp>
-                    <boolProp name="HTTPArgument.use_equals">true</boolProp>
-                    <stringProp name="Argument.name">language</stringProp>
-                    <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                  </elementProp>
-                  <elementProp name="" elementType="HTTPArgument">
-                    <stringProp name="Argument.metadata">=</stringProp>
-                    <stringProp name="Argument.value">lenya</stringProp>
-                    <boolProp name="HTTPArgument.use_equals">true</boolProp>
-                    <stringProp name="Argument.name">dublincore.creator</stringProp>
-                    <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                  </elementProp>
-                  <elementProp name="" elementType="HTTPArgument">
-                    <stringProp name="Argument.metadata">=</stringProp>
-                    <stringProp name="Argument.value"></stringProp>
-                    <boolProp name="HTTPArgument.use_equals">true</boolProp>
-                    <stringProp name="Argument.name">dublincore.subject</stringProp>
-                    <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                  </elementProp>
-                  <elementProp name="" elementType="HTTPArgument">
-                    <stringProp name="Argument.metadata">=</stringProp>
-                    <stringProp name="Argument.value"></stringProp>
-                    <boolProp name="HTTPArgument.use_equals">true</boolProp>
-                    <stringProp name="Argument.name">dublincore.publisher</stringProp>
-                    <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                  </elementProp>
-                  <elementProp name="" elementType="HTTPArgument">
-                    <stringProp name="Argument.metadata">=</stringProp>
-                    <stringProp name="Argument.value"></stringProp>
-                    <boolProp name="HTTPArgument.use_equals">true</boolProp>
-                    <stringProp name="Argument.name">dublincore.rights</stringProp>
-                    <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                  </elementProp>
-                  <elementProp name="" elementType="HTTPArgument">
-                    <stringProp name="Argument.metadata">=</stringProp>
-                    <stringProp name="Argument.value">Default+Sample</stringProp>
-                    <boolProp name="HTTPArgument.use_equals">true</boolProp>
-                    <stringProp name="Argument.name">sample</stringProp>
-                    <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                  </elementProp>
-                  <elementProp name="" elementType="HTTPArgument">
-                    <stringProp name="Argument.metadata">=</stringProp>
-                    <stringProp name="Argument.value">Create</stringProp>
-                    <boolProp name="HTTPArgument.use_equals">true</boolProp>
-                    <stringProp name="Argument.name">submit</stringProp>
-                    <boolProp name="HTTPArgument.always_encode">false</boolProp>
-                  </elementProp>
-                </collectionProp>
-              </elementProp>
-              <stringProp name="HTTPSampler.mimetype"></stringProp>
-              <stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
-              <stringProp name="HTTPSampler.monitor">false</stringProp>
-              <stringProp name="HTTPSampler.domain"></stringProp>
-              <stringProp name="HTTPSampler.FILE_NAME"></stringProp>
-              <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
-            </HTTPSampler>
+            <IfController guiclass="IfControllerPanel" testclass="IfController" testname="If Controller" enabled="true">
+              <stringProp name="IfController.condition">&quot;${lenya.continuation}&quot; != &quot;&quot;</stringProp>
+            </IfController>
             <hashTree>
-              <CounterConfig guiclass="CounterConfigGui" testclass="CounterConfig" testname="counter" enabled="true">
-                <stringProp name="CounterConfig.start">1</stringProp>
-                <stringProp name="CounterConfig.incr">1</stringProp>
-                <stringProp name="CounterConfig.name">contador_noticia</stringProp>
-                <stringProp name="CounterConfig.format"></stringProp>
-                <boolProp name="CounterConfig.per_user">false</boolProp>
-                <stringProp name="CounterConfig.end">10000</stringProp>
-              </CounterConfig>
-              <hashTree/>
+              <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Validation" enabled="true">
+                <stringProp name="HTTPSampler.path">/default/authoring/jmeter.html</stringProp>
+                <stringProp name="HTTPSampler.method">GET</stringProp>
+                <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
+                <stringProp name="HTTPSampler.protocol"></stringProp>
+                <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
+                <stringProp name="HTTPSampler.port"></stringProp>
+                <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables definidas por el Usuario" enabled="true">
+                  <collectionProp name="Arguments.arguments">
+                    <elementProp name="" elementType="HTTPArgument">
+                      <stringProp name="Argument.metadata">=</stringProp>
+                      <stringProp name="Argument.value">${lenya.continuation}</stringProp>
+                      <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                      <stringProp name="Argument.name">lenya.continuation</stringProp>
+                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                    </elementProp>
+                    <elementProp name="" elementType="HTTPArgument">
+                      <stringProp name="Argument.metadata">=</stringProp>
+                      <stringProp name="Argument.value">sitemanagement.create</stringProp>
+                      <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                      <stringProp name="Argument.name">lenya.usecase</stringProp>
+                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                    </elementProp>
+                    <elementProp name="" elementType="HTTPArgument">
+                      <stringProp name="Argument.metadata">=</stringProp>
+                      <stringProp name="Argument.value">Noticia${__Random(1,10000,DOCUMENT)}</stringProp>
+                      <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                      <stringProp name="Argument.name">nodeName</stringProp>
+                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                    </elementProp>
+                    <elementProp name="" elementType="HTTPArgument">
+                      <stringProp name="Argument.metadata">=</stringProp>
+                      <stringProp name="Argument.value">Noticia+${__Random(1,10000,DOCUMENT)}</stringProp>
+                      <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                      <stringProp name="Argument.name">dublincore.title</stringProp>
+                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                    </elementProp>
+                    <elementProp name="" elementType="HTTPArgument">
+                      <stringProp name="Argument.metadata">=</stringProp>
+                      <stringProp name="Argument.value">true</stringProp>
+                      <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                      <stringProp name="Argument.name">visibleInNav</stringProp>
+                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                    </elementProp>
+                    <elementProp name="" elementType="HTTPArgument">
+                      <stringProp name="Argument.metadata">=</stringProp>
+                      <stringProp name="Argument.value">child</stringProp>
+                      <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                      <stringProp name="Argument.name">relation</stringProp>
+                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                    </elementProp>
+                    <elementProp name="" elementType="HTTPArgument">
+                      <stringProp name="Argument.metadata">=</stringProp>
+                      <stringProp name="Argument.value">en</stringProp>
+                      <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                      <stringProp name="Argument.name">language</stringProp>
+                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                    </elementProp>
+                    <elementProp name="" elementType="HTTPArgument">
+                      <stringProp name="Argument.metadata">=</stringProp>
+                      <stringProp name="Argument.value">lenya</stringProp>
+                      <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                      <stringProp name="Argument.name">dublincore.creator</stringProp>
+                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                    </elementProp>
+                    <elementProp name="" elementType="HTTPArgument">
+                      <stringProp name="Argument.metadata">=</stringProp>
+                      <stringProp name="Argument.value"></stringProp>
+                      <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                      <stringProp name="Argument.name">dublincore.subject</stringProp>
+                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                    </elementProp>
+                    <elementProp name="" elementType="HTTPArgument">
+                      <stringProp name="Argument.metadata">=</stringProp>
+                      <stringProp name="Argument.value"></stringProp>
+                      <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                      <stringProp name="Argument.name">dublincore.publisher</stringProp>
+                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                    </elementProp>
+                    <elementProp name="" elementType="HTTPArgument">
+                      <stringProp name="Argument.metadata">=</stringProp>
+                      <stringProp name="Argument.value"></stringProp>
+                      <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                      <stringProp name="Argument.name">dublincore.rights</stringProp>
+                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                    </elementProp>
+                    <elementProp name="" elementType="HTTPArgument">
+                      <stringProp name="Argument.metadata">=</stringProp>
+                      <stringProp name="Argument.value">Default+Sample</stringProp>
+                      <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                      <stringProp name="Argument.name">sample</stringProp>
+                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                    </elementProp>
+                    <elementProp name="" elementType="HTTPArgument">
+                      <stringProp name="Argument.metadata">=</stringProp>
+                      <stringProp name="Argument.value">Create</stringProp>
+                      <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                      <stringProp name="Argument.name">submit</stringProp>
+                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                    </elementProp>
+                  </collectionProp>
+                </elementProp>
+                <stringProp name="HTTPSampler.mimetype"></stringProp>
+                <stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
+                <stringProp name="HTTPSampler.monitor">false</stringProp>
+                <stringProp name="HTTPSampler.domain"></stringProp>
+                <stringProp name="HTTPSampler.FILE_NAME"></stringProp>
+                <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
+              </HTTPSampler>
+              <hashTree>
+                <CounterConfig guiclass="CounterConfigGui" testclass="CounterConfig" testname="counter" enabled="true">
+                  <stringProp name="CounterConfig.start">1</stringProp>
+                  <stringProp name="CounterConfig.incr">1</stringProp>
+                  <stringProp name="CounterConfig.name">contador_noticia</stringProp>
+                  <stringProp name="CounterConfig.format"></stringProp>
+                  <boolProp name="CounterConfig.per_user">false</boolProp>
+                  <stringProp name="CounterConfig.end">10000</stringProp>
+                </CounterConfig>
+                <hashTree/>
+              </hashTree>
             </hashTree>
+            <Arguments guiclass="ArgumentsPanel" testclass="Arguments" testname="Variables" enabled="true">
+              <collectionProp name="Arguments.arguments">
+                <elementProp name="DOCUMENT" elementType="Argument">
+                  <stringProp name="Argument.metadata">=</stringProp>
+                  <stringProp name="Argument.value">${__Random(0,10000,FOO)}</stringProp>
+                  <stringProp name="Argument.name">DOCUMENT</stringProp>
+                </elementProp>
+                <elementProp name="lenya.continuation" elementType="Argument">
+                  <stringProp name="Argument.metadata">=</stringProp>
+                  <stringProp name="Argument.value"></stringProp>
+                  <stringProp name="Argument.name">lenya.continuation</stringProp>
+                </elementProp>
+              </collectionProp>
+            </Arguments>
+            <hashTree/>
           </hashTree>
-          <GenericController guiclass="LogicControllerGui" testclass="GenericController" testname="Files" enabled="true"/>
-          <hashTree/>
         </hashTree>
         <ResultCollector guiclass="StatVisualizer" testclass="ResultCollector" testname="Report" enabled="true">
           <objProp>
@@ -384,10 +671,10 @@
           <stringProp name="HTTPSampler.path"></stringProp>
           <stringProp name="HTTPSampler.domain">${server}</stringProp>
           <stringProp name="HTTPSampler.protocol">HTTP</stringProp>
+          <stringProp name="HTTPSampler.port">8888</stringProp>
           <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables definidas por el Usuario" enabled="true">
             <collectionProp name="Arguments.arguments"/>
           </elementProp>
-          <stringProp name="HTTPSampler.port">8888</stringProp>
         </ConfigTestElement>
         <hashTree/>
         <CSVDataSet guiclass="TestBeanGUI" testclass="CSVDataSet" testname="CSV Data Set" enabled="true">
@@ -398,8 +685,8 @@
         </CSVDataSet>
         <hashTree/>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random timer" enabled="true">
-          <stringProp name="RandomTimer.range">500</stringProp>
           <stringProp name="ConstantTimer.delay">1500</stringProp>
+          <stringProp name="RandomTimer.range">500</stringProp>
         </GaussianRandomTimer>
         <hashTree/>
         <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Login page" enabled="true">
@@ -424,21 +711,12 @@
             <stringProp name="RegexExtractor.default">error</stringProp>
             <stringProp name="RegexExtractor.regex">lenya.continuation=(.*?)&amp;amp;lenya.usecase=ac.login&quot;&gt;</stringProp>
             <stringProp name="RegexExtractor.useHeaders">false</stringProp>
-            <stringProp name="RegexExtractor.template">$1$</stringProp>
             <stringProp name="RegexExtractor.match_number">0</stringProp>
+            <stringProp name="RegexExtractor.template">$1$</stringProp>
             <stringProp name="RegexExtractor.refname">lenya.continuation</stringProp>
           </RegexExtractor>
           <hashTree/>
         </hashTree>
-        <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="regex" enabled="true">
-          <stringProp name="RegexExtractor.default">error</stringProp>
-          <stringProp name="RegexExtractor.regex">lenya.continuation=(.*?)&amp;amp;lenya.usecase=ac.login&quot;&gt;</stringProp>
-          <stringProp name="RegexExtractor.useHeaders">false</stringProp>
-          <stringProp name="RegexExtractor.template">$1$</stringProp>
-          <stringProp name="RegexExtractor.match_number">0</stringProp>
-          <stringProp name="RegexExtractor.refname">lenya.continuation</stringProp>
-        </RegexExtractor>
-        <hashTree/>
         <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Login page" enabled="true">
           <stringProp name="HTTPSampler.path">/default/authoring/jmeter.html?lenya.usecase=ac.login&amp;lenya.continuation=${lenya.continuation}</stringProp>
           <stringProp name="HTTPSampler.method">POST</stringProp>
@@ -489,15 +767,6 @@
           </HeaderManager>
           <hashTree/>
         </hashTree>
-        <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP header" enabled="true">
-          <collectionProp name="HeaderManager.headers">
-            <elementProp name="" elementType="Header">
-              <stringProp name="Header.value">application/x-www-form-urlencoded</stringProp>
-              <stringProp name="Header.name">Content-Type</stringProp>
-            </elementProp>
-          </collectionProp>
-        </HeaderManager>
-        <hashTree/>
         <InterleaveControl guiclass="InterleaveControlGui" testclass="InterleaveControl" testname="Interleave" enabled="true">
           <intProp name="InterleaveControl.style">1</intProp>
         </InterleaveControl>

Modified: lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNode.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNode.java?view=diff&rev=564264&r1=564263&r2=564264
==============================================================================
--- lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNode.java (original)
+++ lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNode.java Thu Aug  9 09:28:15 2007
@@ -35,7 +35,7 @@
 import org.apache.lenya.cms.observation.RepositoryEvent;
 import org.apache.lenya.cms.observation.RepositoryEventFactory;
 import org.apache.lenya.cms.rc.RCML;
-import org.apache.lenya.cms.rc.RCMLEntry;
+import org.apache.lenya.cms.rc.RevisionControlException;
 import org.apache.lenya.cms.rc.RevisionController;
 import org.apache.lenya.transaction.Lock;
 import org.apache.lenya.transaction.TransactionException;
@@ -103,17 +103,18 @@
      * @see org.apache.lenya.transaction.Transactionable#checkin()
      */
     public void checkin() throws RepositoryException {
-        if (!isCheckedOut()) {
-            throw new RepositoryException("Cannot check in node [" + getSourceURI()
-                    + "]: not checked out!");
-        }
-
-        try {
-            String userName = getUserId();
-            boolean newVersion = getSession().isDirty(this);
-            getRevisionController().reservedCheckIn(this, userName, exists(), newVersion);
-        } catch (Exception e) {
-            throw new RepositoryException(e);
+        RCML rcml = getRcml();
+        synchronized (rcml) {
+            try {
+                if (!rcml.isCheckedOut()) {
+                    throw new RepositoryException("Cannot check in node [" + getSourceURI()
+                            + "]: not checked out!");
+                }
+                boolean newVersion = getSession().isDirty(this);
+                rcml.checkIn(this, exists(), newVersion);
+            } catch (Exception e) {
+                throw new RepositoryException(e);
+            }
         }
     }
 
@@ -122,25 +123,19 @@
      */
     public boolean isCheckedOut() throws RepositoryException {
         try {
-            return getRevisionController().isCheckedOut(this);
+            return getRcml().isCheckedOut();
         } catch (Exception e) {
             throw new RepositoryException(e);
         }
     }
 
     /**
-     * @see org.apache.lenya.transaction.Transactionable#isCheckedOutByUser()
+     * @see org.apache.lenya.transaction.Transactionable#isCheckedOutBySession()
      */
-    public boolean isCheckedOutByUser() throws RepositoryException {
+    public boolean isCheckedOutBySession() throws RepositoryException {
         try {
-            if (getRcml().getEntries().size() > 0) {
-                RCMLEntry entry = getRcml().getLatestEntry();
-                if (entry.getIdentity().equals(getUserId()) && isCheckedOut()) {
-                    return true;
-                }
-            }
-            return false;
-        } catch (Exception e) {
+            return getRcml().isCheckedOutBySession(getSession());
+        } catch (RevisionControlException e) {
             throw new RepositoryException(e);
         }
     }
@@ -153,10 +148,17 @@
         if (getLogger().isDebugEnabled())
             getLogger().debug("SourceNode::checkout() called, sourceURI [" + getSourceURI() + "]");
 
-        if (!isCheckedOut()) {
+        RCML rcml = getRcml();
+        synchronized (rcml) {
             try {
-                getRevisionController().reservedCheckOut(this, getUserId());
-            } catch (Exception e) {
+                if (rcml.isCheckedOut() && !rcml.isCheckedOutBySession(getSession())) {
+                    throw new RepositoryException("The node [" + this
+                            + "] is already checked out by another session!");
+                }
+                if (!rcml.isCheckedOut()) {
+                    rcml.checkOut(this);
+                }
+            } catch (RevisionControlException e) {
                 throw new RepositoryException(e);
             }
         }
@@ -223,8 +225,9 @@
      * @see org.apache.lenya.transaction.Transactionable#lock()
      */
     public void lock() throws RepositoryException {
-        if (isCheckedOut() && !isCheckedOutByUser()) {
-            throw new RepositoryException("Cannot lock [" + this + "]: node is checked out.");
+        if (isCheckedOut() && !isCheckedOutBySession()) {
+            throw new RepositoryException("Cannot lock [" + this
+                    + "]: node is checked out by this session.");
         }
         if (getLogger().isDebugEnabled()) {
             getLogger().debug("Locking [" + this + "]");
@@ -342,8 +345,8 @@
     }
 
     protected void enqueueEvent(Object descriptor) {
-        RepositoryEvent event = RepositoryEventFactory.createEvent(this.manager, this,
-                getLogger(), descriptor);
+        RepositoryEvent event = RepositoryEventFactory.createEvent(this.manager, this, getLogger(),
+                descriptor);
         getSession().enqueueEvent(event);
     }
 
@@ -358,13 +361,10 @@
 
     private RCML rcml;
 
-    public RCML getRcml() {
+    public synchronized RCML getRcml() {
         if (this.rcml == null) {
-            try {
-                this.rcml = new SourceNodeRCML(this, this.manager);
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
+            SourceNodeRcmlFactory factory = SourceNodeRcmlFactory.getInstance();
+            this.rcml = factory.getRcml(this, this.manager);
         }
         return this.rcml;
     }
@@ -416,7 +416,11 @@
         return this.metaSource.getMetaDataNamespaceUris();
     }
 
-    public void saveTransactionable() throws TransactionException {
+    public synchronized void saveTransactionable() throws TransactionException {
+        if (!isCheckedOut()) {
+            throw new RepositoryException("Cannot save node [" + getSourceURI()
+                    + "]: not checked out!");
+        }
         this.contentSource.saveTransactionable();
         this.metaSource.saveTransactionable();
     }

Modified: lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeMetaData.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeMetaData.java?view=diff&rev=564264&r1=564263&r2=564264
==============================================================================
--- lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeMetaData.java (original)
+++ lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeMetaData.java Thu Aug  9 09:28:15 2007
@@ -26,7 +26,6 @@
 import org.apache.lenya.cms.metadata.MetaData;
 import org.apache.lenya.cms.metadata.MetaDataException;
 import org.apache.lenya.cms.metadata.MetaDataRegistry;
-import org.apache.lenya.util.Assert;
 
 /**
  * Source-node-based meta data.

Modified: lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeMetaDataHandler.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeMetaDataHandler.java?view=diff&rev=564264&r1=564263&r2=564264
==============================================================================
--- lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeMetaDataHandler.java (original)
+++ lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeMetaDataHandler.java Thu Aug  9 09:28:15 2007
@@ -85,16 +85,14 @@
 
     protected Map namespace2metamap = null;
 
-    protected Map getMetaDataMap(String namespaceUri) throws MetaDataException {
+    protected synchronized Map getMetaDataMap(String namespaceUri) throws MetaDataException {
         if (this.namespace2metamap == null) {
             loadMetaData();
         }
         Map map = (Map) this.namespace2metamap.get(namespaceUri);
         if (map == null) {
-            synchronized (this) {
-                map = new HashMap();
-                this.namespace2metamap.put(namespaceUri, map);
-            }
+            map = new HashMap();
+            this.namespace2metamap.put(namespaceUri, map);
         }
         return map;
     }

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=564264&r1=564263&r2=564264
==============================================================================
--- 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 Thu Aug  9 09:28:15 2007
@@ -21,15 +21,14 @@
 package org.apache.lenya.cms.repository;
 
 import java.io.IOException;
-import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Vector;
 
-import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.excalibur.source.SourceResolver;
 import org.apache.lenya.cms.cocoon.source.SourceUtil;
@@ -50,14 +49,16 @@
 public class SourceNodeRCML implements RCML {
 
     protected static final String NAMESPACE = "";
-    
-    private SourceNode node;
-    private Document xml = null;
+
     private boolean dirty = false;
     private int maximalNumberOfEntries = 5;
+    private Vector entries;
 
     private ServiceManager manager;
 
+    private String contentSourceUri;
+    private String metaSourceUri;
+
     private static Map ELEMENTS = new HashMap();
     protected static final String ELEMENT_CHECKIN = "CheckIn";
     protected static final String ELEMENT_CHECKOUT = "CheckOut";
@@ -66,6 +67,7 @@
     protected static final String ELEMENT_VERSION = "Version";
     protected static final String ELEMENT_IDENTITY = "Identity";
     protected static final String ELEMENT_XPSREVISIONCONTROL = "XPSRevisionControl";
+    protected static final String ELEMENT_SESSION = "session";
 
     {
         ELEMENTS.put(new Short(ci), ELEMENT_CHECKIN);
@@ -73,25 +75,22 @@
     }
 
     /**
-     * create a RCML-File if no one exists already
-     * @param node The node to control.
+     * @param contentSourceUri The content source URI.
+     * @param metaSourceUri The meta source URI.
      * @param manager The service manager.
-     * @throws Exception if an error occurs
      */
-    public SourceNodeRCML(SourceNode node, ServiceManager manager) throws Exception {
-
+    public SourceNodeRCML(String contentSourceUri, String metaSourceUri, ServiceManager manager) {
         this.maximalNumberOfEntries = 10;
         this.maximalNumberOfEntries = (2 * this.maximalNumberOfEntries) + 1;
-
-        this.node = node;
         this.manager = manager;
-
+        this.contentSourceUri = contentSourceUri;
+        this.metaSourceUri = metaSourceUri;
     }
 
     protected static final String RCML_EXTENSION = ".rcml";
 
     protected String getRcmlSourceUri() {
-        return this.node.getContentSource().getRealSourceUri() + RCML_EXTENSION;
+        return this.contentSourceUri + RCML_EXTENSION;
     }
 
     /**
@@ -105,19 +104,18 @@
             write();
         }
     }
-    
-    private static final Object classLock = SourceNodeRCML.class;
-    
+
     /**
-     * Write the xml RCML-document in the RCML-file.
-     * @throws IOException if an error occurs
-     * @throws Exception if an error occurs
+     * Write the XML RCML-document in the RCML-file.
+     * @throws RevisionControlException if an error occurs
      */
-    public synchronized void write() throws Exception {
-        Document xml = getDocument();
-        Assert.notNull("XML document", xml);
-        synchronized (classLock) {
-            SourceUtil.writeDOM(xml, getRcmlSourceUri(), this.manager);
+    public synchronized void write() throws RevisionControlException {
+        NamespaceHelper helper = saveToXml();
+        Assert.notNull("XML document", helper);
+        try {
+            SourceUtil.writeDOM(helper.getDocument(), getRcmlSourceUri(), this.manager);
+        } catch (Exception e) {
+            throw new RevisionControlException(e);
         }
         clearDirty();
     }
@@ -125,18 +123,16 @@
     /**
      * Write a new entry for a check out or a check in the RCML-File made by the
      * user with identity at time
+     * @param node The node.
      * @param type co for a check out, ci for a check in
-     * @param identity The identity of the user
-     * @param time Time at which the check in/out is made
+     * @param time
      * @param backup Create backup element
-     * @throws IOException if an error occurs
-     * @throws Exception if an error occurs
+     * @throws RevisionControlException if an error occurs
      */
-    public synchronized void checkOutIn(short type, String identity, long time, boolean backup)
-            throws IOException, Exception {
+    public synchronized void checkOutIn(Node node, short type, long time, boolean backup)
+            throws RevisionControlException {
 
-        NamespaceHelper helper = getNamespaceHelper();
-        String elementName = (String) ELEMENTS.get(new Short(type));
+        String identity = node.getSession().getIdentity().getUser().getId();
 
         Vector entries = getEntries();
         if (entries.size() == 0) {
@@ -146,100 +142,84 @@
         } else {
             RCMLEntry latestEntry = getLatestEntry();
             if (type == latestEntry.getType()) {
+                String elementName = (String) ELEMENTS.get(new Short(type));
                 throw new IllegalStateException("RCML entry type <" + elementName
-                        + "> not allowed twice in a row.");
+                        + "> not allowed twice in a row. Before: [" + latestEntry.getIdentity()
+                        + "], now: [" + identity + "], node: [" + this.contentSourceUri + "]");
             }
         }
 
-        if (identity == null) {
-            throw new IllegalArgumentException("The identity must not be null!");
-        }
-
-        if (type != co && type != ci) {
-            throw new IllegalArgumentException("ERROR: " + this.getClass().getName()
-                    + ".checkOutIn(): No such type");
-        }
-
-        Element identityElement = helper.createElement(ELEMENT_IDENTITY, identity);
-        Element timeElement = helper.createElement(ELEMENT_TIME, Long.toString(time));
-
-        Element checkOutElement = helper.createElement(elementName);
-
-        checkOutElement.appendChild(identityElement);
-        checkOutElement.appendChild(timeElement);
+        String sessionId = node.getSession().getId();
 
-        if (type == ci) {
+        RCMLEntry entry;
+        switch (type) {
+        case RCML.ci:
             int version = 0;
             CheckInEntry latestEntry = getLatestCheckInEntry();
             if (latestEntry != null) {
                 version = latestEntry.getVersion();
             }
             version++;
-            Element versionElement = helper.createElement(ELEMENT_VERSION, Integer
-                    .toString(version));
-            checkOutElement.appendChild(versionElement);
-        }
-
-        if (backup) {
-            Element backupElement = helper.createElement(ELEMENT_BACKUP);
-            checkOutElement.appendChild(backupElement);
+            entry = new CheckInEntry(sessionId, identity, time, version, backup);
+            break;
+        case RCML.co:
+            entry = new CheckOutEntry(sessionId, identity, time);
+            break;
+        default:
+            throw new IllegalArgumentException("No such type: [" + type + "]");
         }
 
-        Element root = helper.getDocument().getDocumentElement();
-        root.insertBefore(checkOutElement, root.getFirstChild());
-
+        entries.add(0, entry);
         setDirty();
-
-        // If this is a checkout, we write back the changed state
-        // to the file immediately because otherwise another
-        // process might read the file and think there is no open
-        // checkout (as it is only visible in our private DOM tree
-        // at this time).
-        //
-        // If, however, this is a checkin, we do not yet write it
-        // out because then another process might again check it
-        // out immediately and manipulate the file contents
-        // *before* our caller has finished writing back the
-        // changed data to the destination file. We therefore rely
-        // on either our caller invoking the write() method when
-        // finished or the garbage collector calling the finalize()
-        // method.
-        //
-        // if (type == co) {
-        // }
         write();
     }
 
-    private long lastModified = 0;
+    protected Element saveToXml(NamespaceHelper helper, RCMLEntry entry)
+            throws RevisionControlException {
+        String elementName = (String) ELEMENTS.get(new Short(entry.getType()));
+        Element sessionElement = helper.createElement(ELEMENT_SESSION, entry.getSessionId());
+        Element identityElement = helper.createElement(ELEMENT_IDENTITY, entry.getIdentity());
+        Element timeElement = helper.createElement(ELEMENT_TIME, Long.toString(entry.getTime()));
+
+        Element entryElement = helper.createElement(elementName);
+
+        entryElement.appendChild(identityElement);
+        entryElement.appendChild(timeElement);
+        entryElement.appendChild(sessionElement);
 
-    protected NamespaceHelper getNamespaceHelper() throws RevisionControlException {
-        return new NamespaceHelper(NAMESPACE, "", getDocument());
+        if (entry.getType() == ci) {
+            CheckInEntry checkInEntry = (CheckInEntry) entry;
+            Element versionElement = helper.createElement(ELEMENT_VERSION, Integer
+                    .toString(checkInEntry.getVersion()));
+            entryElement.appendChild(versionElement);
+            if (checkInEntry.hasBackup()) {
+                Element backupElement = helper.createElement(ELEMENT_BACKUP);
+                entryElement.appendChild(backupElement);
+            }
+        }
+
+        return entryElement;
     }
 
-    protected Document getDocument() throws RevisionControlException {
+    protected NamespaceHelper saveToXml() throws RevisionControlException {
         try {
-            String uri = getRcmlSourceUri();
-            if (SourceUtil.exists(uri, this.manager)) {
-                long sourceLastModified = SourceUtil.getLastModified(uri, manager);
-                if (this.xml == null || sourceLastModified > this.lastModified) {
-                    this.xml = SourceUtil.readDOM(getRcmlSourceUri(), this.manager);
-                    this.lastModified = sourceLastModified;
-                }
-            } else {
-                if (this.xml == null) {
-                    NamespaceHelper helper = new NamespaceHelper(NAMESPACE, "",
-                            ELEMENT_XPSREVISIONCONTROL);
-                    this.xml = helper.getDocument();
-                }
+            NamespaceHelper helper = new NamespaceHelper(NAMESPACE, "", ELEMENT_XPSREVISIONCONTROL);
+            Element root = helper.getDocument().getDocumentElement();
+            Vector entries = getEntries();
+            for (Iterator i = entries.iterator(); i.hasNext();) {
+                RCMLEntry entry = (RCMLEntry) i.next();
+                Element element = saveToXml(helper, entry);
+                root.appendChild(element);
             }
+            return helper;
         } catch (Exception e) {
-            throw new RevisionControlException("Could not read RC file [" + getRcmlSourceUri()
-                    + "]");
+            throw new RevisionControlException("Could create revision control XML ["
+                    + getRcmlSourceUri() + "]", e);
         }
-        return this.xml;
     }
 
-    protected Element getLatestElement(NamespaceHelper helper, String type) throws Exception {
+    protected Element getLatestElement(NamespaceHelper helper, String type)
+            throws RevisionControlException {
         Element parent = helper.getDocument().getDocumentElement();
         return helper.getFirstChild(parent, type);
     }
@@ -247,52 +227,61 @@
     /**
      * get the latest check out
      * @return CheckOutEntry The entry of the check out
-     * @throws Exception if an error occurs
+     * @throws RevisionControlException if an error occurs
      */
-    public CheckOutEntry getLatestCheckOutEntry() throws Exception {
-        return (CheckOutEntry) getLatestEntry(getNamespaceHelper(), (String) ELEMENTS
-                .get(new Short(RCML.co)));
+    public CheckOutEntry getLatestCheckOutEntry() throws RevisionControlException {
+        return (CheckOutEntry) getLatestEntry(RCML.co);
     }
 
     /**
      * get the latest check in
      * @return CheckInEntry The entry of the check in
-     * @throws Exception if an error occurs
+     * @throws RevisionControlException if an error occurs
      */
-    public CheckInEntry getLatestCheckInEntry() throws Exception {
-        return (CheckInEntry) getLatestEntry(getNamespaceHelper(), (String) ELEMENTS.get(new Short(
-                RCML.ci)));
+    public CheckInEntry getLatestCheckInEntry() throws RevisionControlException {
+        return (CheckInEntry) getLatestEntry(RCML.ci);
     }
 
     /**
      * get the latest entry (a check out or check in)
+     * @param type The type.
      * @return RCMLEntry The entry of the check out/in
-     * @throws Exception if an error occurs
+     * @throws RevisionControlException if an error occurs
      */
-    public RCMLEntry getLatestEntry() throws Exception {
-        return getLatestEntry(getNamespaceHelper(), "*");
+    public RCMLEntry getLatestEntry(short type) throws RevisionControlException {
+        Vector entries = getEntries();
+        for (Iterator i = entries.iterator(); i.hasNext(); ) {
+            RCMLEntry entry = (RCMLEntry) i.next();
+            if (entry.getType() == type) {
+                return entry;
+            }
+        }
+        return null;
     }
 
-    protected RCMLEntry getLatestEntry(NamespaceHelper helper, String elementName) throws Exception {
-        Element element = getLatestElement(helper, elementName);
-        if (element == null) {
+    public RCMLEntry getLatestEntry() throws RevisionControlException {
+        Vector entries = getEntries();
+        if (entries.isEmpty()) {
             return null;
-        } else {
-            return getEntry(helper, element);
+        }
+        else {
+            return (RCMLEntry) entries.firstElement();
         }
     }
 
     protected RCMLEntry getEntry(NamespaceHelper helper, Element element) {
         String type = element.getLocalName();
+        String sessionId = getChildValue(helper, element, ELEMENT_SESSION, "");
         String identity = getChildValue(helper, element, ELEMENT_IDENTITY);
         String timeString = getChildValue(helper, element, ELEMENT_TIME);
         long time = new Long(timeString).longValue();
         if (type.equals(ELEMENT_CHECKIN)) {
             String versionString = getChildValue(helper, element, ELEMENT_VERSION);
             int version = new Integer(versionString).intValue();
-            return new CheckInEntry(identity, time, version);
+            boolean backup = helper.getChildren(element, ELEMENT_BACKUP).length > 0;
+            return new CheckInEntry(sessionId, identity, time, version, backup);
         } else if (type.equals(ELEMENT_CHECKOUT)) {
-            return new CheckOutEntry(identity, time);
+            return new CheckOutEntry(sessionId, identity, time);
         } else {
             throw new RuntimeException("Unsupported RCML entry type: [" + type + "]");
         }
@@ -321,18 +310,29 @@
     /**
      * get all check in and check out
      * @return Vector of all check out and check in entries in this RCML-file
-     * @throws Exception if an error occurs
+     * @throws RevisionControlException if an error occurs
      */
-    public Vector getEntries() throws Exception {
-        NamespaceHelper helper = getNamespaceHelper();
-        Element parent = helper.getDocument().getDocumentElement();
-        Element[] elements = helper.getChildren(parent);
-        Vector entries = new Vector();
-        for (int i = 0; i < elements.length; i++) {
-            RCMLEntry entry = getEntry(helper, elements[i]);
-            entries.add(entry);
+    public synchronized Vector getEntries() throws RevisionControlException {
+        if (this.entries == null) {
+            this.entries = new Vector();
+            String uri = getRcmlSourceUri();
+            try {
+                if (SourceUtil.exists(uri, this.manager)) {
+                    Document xml = SourceUtil.readDOM(uri, this.manager);
+                    NamespaceHelper helper = new NamespaceHelper(NAMESPACE, "", xml);
+                    Element parent = xml.getDocumentElement();
+                    Element[] elements = helper.getChildren(parent);
+                    for (int i = 0; i < elements.length; i++) {
+                        RCMLEntry entry = getEntry(helper, elements[i]);
+                        entries.add(entry);
+                    }
+                }
+            } catch (Exception e) {
+                throw new RevisionControlException(e);
+            }
+
         }
-        return entries;
+        return this.entries;
     }
 
     /**
@@ -340,46 +340,42 @@
      * @return Vector of all entries in this RCML-file with a backup
      * @throws Exception if an error occurs
      */
-    public Vector getBackupEntries() throws Exception {
-        NamespaceHelper helper = getNamespaceHelper();
-        Element parent = helper.getDocument().getDocumentElement();
-        Element[] elements = helper.getChildren(parent, ELEMENT_CHECKIN);
-
-        Vector entries = new Vector();
-
-        for (int i = 0; i < elements.length; i++) {
-            if (helper.getChildren(elements[i], ELEMENT_BACKUP).length > 0) {
-                RCMLEntry entry = getEntry(helper, elements[i]);
-                entries.add(entry);
+    public synchronized Vector getBackupEntries() throws Exception {
+        Vector entries = getEntries();
+        Vector backupEntries = new Vector();
+        for (Iterator i = entries.iterator(); i.hasNext();) {
+            RCMLEntry entry = (RCMLEntry) i.next();
+            if (entry.getType() == RCML.ci && ((CheckInEntry) entry).hasBackup()) {
+                backupEntries.add(entry);
             }
         }
-
-        return entries;
+        return backupEntries;
     }
 
-    public void makeBackup(long time) throws RevisionControlException {
-        makeBackup(this.node.getContentSource(), time);
-        makeBackup(this.node.getMetaSource(), time);
+    public synchronized void makeBackup(long time) throws RevisionControlException {
+        makeBackup(this.contentSourceUri, time);
+        makeBackup(this.metaSourceUri, time);
     }
 
-    protected void makeBackup(SourceWrapper wrapper, long time) throws RevisionControlException {
-        String backupSourceUri = getBackupSourceUri(wrapper, time);
+    protected synchronized void makeBackup(String sourceUri, long time)
+            throws RevisionControlException {
+        String backupSourceUri = getBackupSourceUri(sourceUri, time);
         try {
-            String uri = wrapper.getRealSourceUri();
-            if (SourceUtil.exists(uri, manager)) {
-                SourceUtil.copy(this.manager, uri, backupSourceUri);
+            if (SourceUtil.exists(sourceUri, manager)) {
+                SourceUtil.copy(this.manager, sourceUri, backupSourceUri);
             }
         } catch (Exception e) {
             throw new RevisionControlException(e);
         }
     }
 
-    public void restoreBackup(long time) throws RevisionControlException {
-        restoreBackup(this.node.getContentSource(), time);
-        restoreBackup(this.node.getMetaSource(), time);
+    public synchronized void restoreBackup(Node node, long time) throws RevisionControlException {
+        SourceNode sourceNode = (SourceNode) node;
+        restoreBackup(sourceNode.getContentSource(), time);
+        restoreBackup(sourceNode.getMetaSource(), time);
     }
 
-    protected void restoreBackup(SourceWrapper wrapper, long time) throws RevisionControlException {
+    protected synchronized void restoreBackup(SourceWrapper wrapper, long time) throws RevisionControlException {
         String backupSourceUri = getBackupSourceUri(wrapper, time);
         SourceResolver resolver = null;
         try {
@@ -407,45 +403,33 @@
      * Prune the list of entries and delete the corresponding backups. Limit the
      * number of entries to the value maximalNumberOfEntries
      * (2maxNumberOfRollbacks(configured)+1)
-     * @throws Exception if an error occurs
+     * @throws RevisionControlException if an error occurs
      */
-    public void pruneEntries() throws Exception {
-        NamespaceHelper helper = getNamespaceHelper();
-        Element parent = helper.getDocument().getDocumentElement();
-        Element[] elements = helper.getChildren(parent);
-
-        for (int i = this.maximalNumberOfEntries; i < elements.length; i++) {
+    public synchronized void pruneEntries() throws RevisionControlException {
+        Vector entries = getEntries();
+        RCMLEntry[] array = (RCMLEntry[]) entries.toArray(new RCMLEntry[entries.size()]);
 
+        for (int i = this.maximalNumberOfEntries; i < entries.size(); i++) {
             // remove the backup file associated with this entry
-            String time = getChildValue(helper, elements[i], ELEMENT_TIME);
-            long timeLong = Long.valueOf(time).longValue();
-            deleteBackup(this.node.getContentSource(), timeLong);
-            deleteBackup(this.node.getMetaSource(), timeLong);
-
-            parent.removeChild(elements[i]);
+            RCMLEntry entry = array[i];
+            if (entry.getType() == ci && ((CheckInEntry) entry).hasBackup()) {
+                long time = entry.getTime();
+                deleteBackup(this.contentSourceUri, time);
+                deleteBackup(this.metaSourceUri, time);
+                this.entries.remove(entry);
+            }
         }
         setDirty();
     }
 
-    protected void deleteBackup(SourceWrapper wrapper, long time) throws ServiceException,
-            MalformedURLException, IOException {
-        String uri = getBackupSourceUri(wrapper, time);
-        SourceUtil.delete(uri, this.manager);
-        SourceUtil.deleteEmptyCollections(uri, this.manager);
-    }
-
-    /**
-     * 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(getDocument().getDocumentElement(), true));
-
-        return documentClone;
+    protected synchronized void deleteBackup(String sourceUri, long time) throws RevisionControlException {
+        String uri = getBackupSourceUri(sourceUri, time);
+        try {
+            SourceUtil.delete(uri, this.manager);
+            SourceUtil.deleteEmptyCollections(uri, this.manager);
+        } catch (Exception e) {
+            throw new RevisionControlException(e);
+        }
     }
 
     /**
@@ -461,7 +445,6 @@
      */
     protected void setDirty() {
         this.dirty = true;
-        this.lastModified = new Date().getTime();
     }
 
     /**
@@ -473,27 +456,23 @@
 
     /**
      * Delete the latest check in
-     * @throws Exception if an error occurs
+     * @throws RevisionControlException if an error occurs
      */
-    public void deleteFirstCheckIn() throws Exception {
-        deleteLatestEntry(ELEMENT_CHECKIN);
+    public synchronized void deleteFirstCheckIn() throws RevisionControlException {
+        deleteLatestEntry(ci);
     }
 
     /**
      * Delete the latest check in
-     * @throws Exception if an error occurs
+     * @throws RevisionControlException if an error occurs
      */
-    public void deleteFirstCheckOut() throws Exception {
-        deleteLatestEntry(ELEMENT_CHECKOUT);
+    public synchronized void deleteFirstCheckOut() throws RevisionControlException {
+        deleteLatestEntry(co);
     }
 
-    protected void deleteLatestEntry(String type) throws RevisionControlException, Exception {
-        NamespaceHelper helper = getNamespaceHelper();
-        Element parent = helper.getDocument().getDocumentElement();
-        Element element = getLatestElement(helper, type);
-        parent.removeChild(element);
-        // parent.removeChild(parent.getFirstChild()); // remove EOL (end of
-        // line)
+    protected synchronized void deleteLatestEntry(short type) throws RevisionControlException {
+        RCMLEntry entry = getLatestEntry(type);
+        this.entries.remove(entry);
         setDirty();
     }
 
@@ -503,15 +482,13 @@
      * @throws Exception if an error occurs
      */
     public String[] getBackupsTime() throws Exception {
-        NamespaceHelper helper = getNamespaceHelper();
-        Element parent = helper.getDocument().getDocumentElement();
-        Element[] elements = helper.getChildren(parent, ELEMENT_CHECKIN);
 
-        ArrayList times = new ArrayList();
-        for (int i = 0; i < elements.length; i++) {
-            String time = getChildValue(helper, elements[i], ELEMENT_TIME);
-            if (helper.getChildren(elements[i], ELEMENT_BACKUP).length > 0) {
-                times.add(time);
+        Vector entries = getEntries();
+        List times = new ArrayList();
+        for (Iterator i = entries.iterator(); i.hasNext(); ) {
+            RCMLEntry entry = (RCMLEntry) i.next();
+            if (entry.getType() == ci && ((CheckInEntry) entry).hasBackup()) {
+                times.add(Long.toString(entry.getTime()));
             }
         }
         return (String[]) times.toArray(new String[times.size()]);
@@ -523,7 +500,7 @@
      * empty.
      * @return boolean true, if the file was deleted
      */
-    public boolean delete() {
+    public synchronized boolean delete() {
         try {
             deleteRevisions();
             SourceUtil.delete(getRcmlSourceUri(), this.manager);
@@ -538,43 +515,102 @@
      * delete the revisions
      * @throws RevisionControlException when somthing went wrong
      */
-    public void deleteRevisions() throws RevisionControlException {
+    public synchronized void deleteRevisions() throws RevisionControlException {
         try {
             String[] times = getBackupsTime();
             for (int i = 0; i < times.length; i++) {
                 long time = new Long(times[i]).longValue();
-                deleteBackup(this.node.getContentSource(), time);
-                deleteBackup(this.node.getMetaSource(), time);
+                deleteBackup(this.contentSourceUri, time);
+                deleteBackup(this.metaSourceUri, time);
             }
         } catch (Exception e) {
             throw new RevisionControlException(e);
         }
     }
 
-    public void copyFrom(RCML otherRcml) throws RevisionControlException {
+    public synchronized void copyFrom(Node node, Node otherNode) throws RevisionControlException {
 
-        SourceNodeRCML other = (SourceNodeRCML) otherRcml;
+        SourceNode otherSourceNode = (SourceNode) otherNode;
+        SourceNode sourceNode = (SourceNode) node;
+        SourceNodeRCML otherRcml = (SourceNodeRCML) otherNode.getRcml();
 
         try {
 
-            Vector backupEntries = other.getBackupEntries();
+            Vector backupEntries = otherRcml.getBackupEntries();
             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 thisContentUri = this.getBackupSourceUri(this.node.getContentSource(), time);
+                String otherContentUri = otherRcml.getBackupSourceUri(otherSourceNode
+                        .getContentSource(), time);
+                String thisContentUri = this
+                        .getBackupSourceUri(sourceNode.getContentSource(), time);
                 SourceUtil.copy(this.manager, otherContentUri, thisContentUri);
-                String otherMetaUri = other.getBackupSourceUri(other.node.getMetaSource(), time);
-                String thisMetaUri = this.getBackupSourceUri(this.node.getMetaSource(), time);
+
+                String otherMetaUri = otherRcml.getBackupSourceUri(otherSourceNode.getMetaSource(),
+                        time);
+                String thisMetaUri = this.getBackupSourceUri(sourceNode.getMetaSource(), time);
                 SourceUtil.copy(this.manager, otherMetaUri, thisMetaUri);
             }
 
-            this.xml = other.getDocument();
+            this.entries = new Vector();
+            Vector otherEntries = otherRcml.getEntries();
+            for (Iterator i = otherEntries.iterator(); i.hasNext();) {
+                RCMLEntry entry = (RCMLEntry) i.next();
+                RCMLEntry newEntry = null;
+                switch (entry.getType()) {
+                case co:
+                    newEntry = new CheckOutEntry(entry.getSessionId(), entry.getIdentity(), entry
+                            .getTime());
+                    break;
+                case ci:
+                    CheckInEntry ciEntry = (CheckInEntry) entry;
+                    newEntry = new CheckInEntry(ciEntry.getSessionId(), ciEntry.getIdentity(),
+                            ciEntry.getTime(), ciEntry.getVersion(), ciEntry.hasBackup());
+                    break;
+                }
+                this.entries.add(newEntry);
+            }
+
             write();
         } catch (Exception e) {
             throw new RevisionControlException(e);
         }
+    }
+
+    public synchronized boolean isCheckedOut() throws RevisionControlException {
+        RCMLEntry entry = getLatestEntry();
+        return entry != null && entry.getType() == RCML.co;
+    }
+
+    public synchronized void checkIn(Node node, boolean backup, boolean newVersion)
+            throws RevisionControlException {
+
+        long time = new Date().getTime();
+
+        if (backup) {
+            makeBackup(time);
+        }
+
+        if (newVersion) {
+            checkOutIn(node, RCML.ci, time, backup);
+        } else {
+            deleteFirstCheckOut();
+        }
+        pruneEntries();
+        write();
+    }
+
+    public synchronized void checkOut(Node node) throws RevisionControlException {
+        checkOutIn(node, RCML.co, new Date().getTime(), false);
+    }
+
+    public boolean isCheckedOutBySession(Session session) throws RevisionControlException {
+        Vector entries = getEntries();
+        if (entries.size() > 0) {
+            RCMLEntry entry = (RCMLEntry) entries.get(0);
+            return entry.getType() == co && entry.getSessionId().equals(session.getId());
+        }
+        return false;
     }
 
 }
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.