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 2007/08/09 18:28:19 UTC

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/...

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">foo@bar.com</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;
     }
 
 }



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