You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by js...@apache.org on 2002/10/30 20:13:02 UTC

cvs commit: jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly jelly.properties

jstrachan    2002/10/30 11:13:02

  Modified:    jelly/src/java/org/apache/commons/jelly jelly.properties
  Added:       jelly/src/test/org/apache/commons/jelly/threads wait4.jelly
                        sync.jelly group1.jelly basic.jelly wait1.jelly
                        wait2.jelly wait3.jelly suite.jelly TestJelly.java
               jelly/src/java/org/apache/commons/jelly/tags/threads
                        MutexTag.java SleepTag.java
                        RequirementException.java JoinTag.java
                        ThreadTag.java ThreadsTagLibrary.java
                        SynchronizeTag.java GroupTag.java UseMutexTag.java
                        JellyThread.java TimeoutException.java
                        UseThreadTag.java WaitForTag.java
                        RunnableStatus.java package.html WaitTag.java
                        NotifyTag.java Mutex.java InterruptTag.java
  Log:
  Added the new Threads library created by Jason Horman which allows simple and complex threading to be used inside a Jelly script.
  This is especially useful for evaluating different Jelly scripts in parallel and then joining them back together.
  
  Revision  Changes    Path
  1.1                  jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/threads/wait4.jelly
  
  Index: wait4.jelly
  ===================================================================
  <?xml version="1.0"?>
  
  <!--
  This test shows the waitFor tag waiting for multiple threads. 
  -->
  
  <jelly xmlns="jelly:core" xmlns:threads="jelly:threads" xmlns:bsh="jelly:beanshell">
      <threads:thread var="thread1">
          <whitespace>
          thread1: going to sleep for 1 second
          </whitespace>
          <threads:sleep for="1000"/>
      </threads:thread>
  
      <threads:thread var="thread2">
          <whitespace>
          thread2: going to sleep for 2 seconds
          </whitespace>
          <threads:sleep for="2000"/>
      </threads:thread>
  
      <!-- results in a FAILURE -->
      <threads:thread var="thread3">
          <bsh:script>
              throw new Exception("thread 3 exception");
          </bsh:script>
      </threads:thread>
  
      <!-- waits for thread 1 and 2 -->
      <threads:thread>
          <threads:waitfor thread="${thread1}" status="SUCCESS"/>
          <threads:waitfor thread="${thread2}" status="SUCCESS"/>
  
          <whitespace>
          thread4: finished waiting for thread1 and thread2
          </whitespace>
      </threads:thread>
  
      <!-- waits for thread 3 success -->
      <threads:thread>
          <threads:waitfor thread="${thread1}" status="SUCCESS"/>
          <threads:waitfor thread="${thread2}" status="SUCCESS"/>
          <threads:waitfor thread="${thread3}" status="SUCCESS"/>
  
          <whitespace>
          thread5: finished waiting for thread1 and thread2 and thread3 success
          </whitespace>
      </threads:thread>
  
      <!-- waits for thread 3 failure -->
      <threads:thread>
          <threads:waitfor thread="${thread1}" status="SUCCESS"/>
          <threads:waitfor thread="${thread2}" status="SUCCESS"/>
          <threads:waitfor thread="${thread3}" status="FAILURE"/>
  
          <whitespace>
          thread6: finished waiting for thread1 and thread2 and thread3 failure
          </whitespace>
      </threads:thread>
  
   </jelly>
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/threads/sync.jelly
  
  Index: sync.jelly
  ===================================================================
  <?xml version="1.0"?>
  
  <!--
  This example shows coordinating between 2 threads using
  mutexes and sleep. Thread 1 should execute after thread 2.
  -->
  
  <jelly xmlns="jelly:core" xmlns:threads="jelly:threads">
  
      <threads:mutex var="mutex"/>
  
      <threads:thread var="thread1">
          <!-- give the other thread a chance to get the mutex -->
          <threads:sleep for="100"/>
  
          <!-- get the mutex -->
          <threads:synchronize mutex="${mutex}">
  
              <whitespace>
                  [thread1]: finally I got it
              </whitespace>
  
          </threads:synchronize>
      </threads:thread>
  
      <threads:thread>
          <!-- get the mutex -->
          <threads:synchronize mutex="${mutex}">
  
              <whitespace>
                  [thread2]: making the other thread wait for 2 secs
              </whitespace>
  
              <!-- make the other thread wait -->
              <threads:sleep for="2000"/>
          </threads:synchronize>
      </threads:thread>
  
      <whitespace>
          [main]: waiting for threads to finish
      </whitespace>
  
      <threads:join thread="${thread1}"/>
  
      <whitespace>
          [main]: threads are now done
      </whitespace>
  
  </jelly>
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/threads/group1.jelly
  
  Index: group1.jelly
  ===================================================================
  <?xml version="1.0"?>
  
  <!--
  Basic thread group example.
  -->
  
  <jelly xmlns="jelly:core" xmlns:threads="jelly:threads">
  
      <threads:group var="group1">
          <threads:thread>
              <threads:sleep for="100"/>
              1
          </threads:thread>
  
          <threads:thread>
              <threads:sleep for="100"/>
              2
          </threads:thread>
      </threads:group>
  
      <threads:thread>
          <!-- wait for both thread 1 and 2 to complete -->
          <threads:waitFor group="${group1}"/>
          3
      </threads:thread>
  
  </jelly>
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/threads/basic.jelly
  
  Index: basic.jelly
  ===================================================================
  <?xml version="1.0"?>
  
  <!--
  Basic example. Should print the numbers in reverse.
  -->
  
  <jelly xmlns="jelly:core" xmlns:threads="jelly:threads">
  
      <threads:thread var="thread1">
          <threads:sleep for="1000"/>
          1
      </threads:thread>
  
      <threads:thread>
          <threads:sleep for="500"/>
          2
      </threads:thread>
  
      <threads:thread>
          <threads:sleep for="100"/>
          3
      </threads:thread>
  
      <threads:thread>
          4
      </threads:thread>
  
  <whitespace>
  [main]: waiting for threads to finish
  </whitespace>
  
          <threads:join thread="${thread1}"/>
  
  <whitespace>
  [main]: threads are now done
  </whitespace>
  
  </jelly>
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/threads/wait1.jelly
  
  Index: wait1.jelly
  ===================================================================
  <?xml version="1.0"?>
  
  <!--
  This test shows coordinating between 2 threads using
  mutexes with wait/notify. Numbers between threads
  should increment together.
  -->
  
  <jelly xmlns="jelly:core" xmlns:threads="jelly:threads">
  
      <!-- get the mutex -->
      <threads:mutex var="mutex"/>
  
      <threads:thread var="thread1">
          <set var="counter1" value="0"/>
  
          <!-- get the mutex -->
          <threads:synchronize mutex="${mutex}">
              <!-- loop -->
              <while test="${counter1 != 20}">
  
  <whitespace>
  counter1: ${counter1}
  </whitespace>
  
                  <set var="counter1" value="${counter1+1}"/>
  
                  <!-- let the other thread proceed -->
                  <threads:notify mutex="${mutex}"/>
  
                  <!-- wait for 1 iteration of the other thread -->
                  <threads:wait mutex="${mutex}"/>
              </while>
  
              <!-- let the other thread proceed -->
              <threads:notify mutex="${mutex}"/>
  
          </threads:synchronize>
      </threads:thread>
  
      <threads:thread var="thread2">
          <set var="counter2" value="0"/>
          <threads:sleep for="100"/>
          <!-- get the mutex -->
          <threads:synchronize mutex="${mutex}">
              <!-- loop -->
              <while test="${counter2 != 20}">
  
  <whitespace>
  counter2: ${counter2}
  </whitespace>
  
                  <set var="counter2" value="${counter2+1}"/>
  
                  <!-- let the other thread proceed -->
                  <threads:notify mutex="${mutex}"/>
  
                  <!-- wait for 1 iteration of the other thread -->
                  <threads:wait mutex="${mutex}"/>
              </while>
  
              <!-- let the other thread proceed -->
              <threads:notify mutex="${mutex}"/>
  
          </threads:synchronize>
      </threads:thread>
  
  <whitespace>
  [main]: waiting for threads to finish
  </whitespace>
  
      <threads:join thread="${thread1}"/>
      <threads:join thread="${thread2}"/>
  
  <whitespace>
  [main]: threads are now done
  </whitespace>
  
  </jelly>
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/threads/wait2.jelly
  
  Index: wait2.jelly
  ===================================================================
  <?xml version="1.0"?>
  
  <!--
  This test shows coordinating between 2 threads using
  mutexes with wait/notify. Numbers between threads
  should increment together.
  -->
  
  <jelly xmlns="jelly:core" xmlns:threads="jelly:threads">
      <threads:thread var="thread1">
  
          <whitespace>
          thread1: going to sleep for 2 seconds
          </whitespace>
  
          <threads:sleep for="2000"/>
      </threads:thread>
  
      <threads:thread var="thread2">
          <threads:waitfor thread="${thread1}"/>
  
          <whitespace>
          thread2: finished waiting for thread1, sleeping for 2 seconds
          </whitespace>
  
          <threads:sleep for="1000"/>
      </threads:thread>
  
      <threads:thread>
          <threads:waitfor thread="${thread1}"/>
  
          <whitespace>
          thread3: finished waiting for thread1
          </whitespace>
  
      </threads:thread>
  
      <threads:thread>
          <threads:waitfor thread="${thread2}"/>
  
          <whitespace>
          thread4: finished waiting for thread2
          </whitespace>
  
      </threads:thread>
  </jelly>
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/threads/wait3.jelly
  
  Index: wait3.jelly
  ===================================================================
  <?xml version="1.0"?>
  
  <!--
  This test shows how the waitFor tag works.
  -->
  
  <jelly xmlns="jelly:core" xmlns:threads="jelly:threads">
      <threads:thread var="thread1">
  
          <whitespace>
          thread1: going to sleep for 2 seconds
          </whitespace>
  
          <threads:sleep for="2000"/>
      </threads:thread>
  
      <threads:thread var="thread2">
          <whitespace>
          thread2: waiting for thread1 for 1 second
          </whitespace>
  
          <!-- this thread will be marked as avoided -->
          <threads:waitfor thread="${thread1}" onlyWait="1000"/>
  
          <whitespace>
          thread2: finished waiting for thread1
          </whitespace>
  
          <threads:sleep for="1000"/>
      </threads:thread>
  
      <threads:thread>
          <!-- wait for thread2's avoided status -->
          <threads:waitfor thread="${thread2}" status="AVOIDED"/>
  
          <whitespace>
          thread3: finished waiting for thread2 avoided status
          </whitespace>
  
      </threads:thread>
  
      <threads:thread var="thread4">
          <!-- wait for the thread2's success -->
          <threads:waitfor thread="${thread2}" status="SUCCESS"/>
  
          <whitespace>
          thread4: finished waiting for thread2 success status
          </whitespace>
  
      </threads:thread>
  
      <threads:thread>
          <!-- wait for the thread2's success -->
          <threads:waitfor thread="${thread4}" status="AVOIDED"/>
  
          <whitespace>
          thread6: finished waiting for thread4 avoided status
          </whitespace>
  
      </threads:thread>
  
   </jelly>
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/threads/suite.jelly
  
  Index: suite.jelly
  ===================================================================
  <?xml version="1.0"?>
  <test:suite xmlns="jelly:core" xmlns:test="jelly:junit" xmlns:threads="jelly:threads" xmlns:bsh="jelly:beanshell">
      <test:case name="testBasic">
          <set var="result" value=""/>
  
          <threads:thread var="thread1">
              <threads:sleep for="700"/>
              <set var="result" value="${result}1"/>
              <test:assertEquals expected="4321" actual="${result}"/>
          </threads:thread>
  
          <threads:thread>
              <threads:sleep for="400"/>
              <set var="result" value="${result}2"/>
          </threads:thread>
  
          <threads:thread>
              <threads:sleep for="100"/>
              <set var="result" value="${result}3"/>
          </threads:thread>
  
          <threads:thread>
              <set var="result" value="${result}4"/>
          </threads:thread>
      </test:case>
  
      <test:case name="testSync">
          <set var="result" value=""/>
          <threads:mutex var="mutex"/>
  
          <threads:thread var="thread1">
              <threads:synchronize mutex="${mutex}">
                  <set var="cnt1" value="0"/>
                  <while test="${cnt1 != 5}">
                      <set var="result" value="${result}${cnt1}"/>
                      <set var="cnt1" value="${cnt1 + 1}"/>
                      <threads:interrupt/>
                  </while>
              </threads:synchronize>
          </threads:thread>
  
          <threads:thread var="thread2">
              <!-- let the other thread start -->
              <threads:sleep for="100"/>
              <threads:synchronize mutex="${mutex}">
                  <set var="cnt2" value="5"/>
                  <while test="${cnt2 != 10}">
                      <set var="result" value="${result}${cnt2}"/>
                      <set var="cnt2" value="${cnt2 + 1}"/>
                      <threads:interrupt/>
                  </while>
              </threads:synchronize>
          </threads:thread>
  
          <threads:join thread="${thread1}"/>
          <threads:join thread="${thread2}"/>
          <test:assertEquals expected="0123456789" actual="${result}"/>
      </test:case>
  
      <test:case name="testWaitNotify">
          <set var="result" value=""/>
          <threads:mutex var="mutex"/>
  
          <threads:thread var="thread1">
              <threads:synchronize mutex="${mutex}">
                  <set var="cnt1" value="0"/>
                  <while test="${cnt1 != 5}">
                      <set var="result" value="${result}${cnt1}"/>
                      <set var="cnt1" value="${cnt1 + 1}"/>
                      <!-- let the other thread go -->
                      <threads:notify mutex="${mutex}"/>
                      <threads:wait mutex="${mutex}"/>
                  </while>
                  <!-- one last notify -->
                  <threads:notify mutex="${mutex}"/>
              </threads:synchronize>
          </threads:thread>
  
          <threads:thread var="thread2">
              <!-- let the other thread start -->
              <threads:sleep for="100"/>
              <threads:synchronize mutex="${mutex}">
                  <set var="cnt2" value="0"/>
                  <while test="${cnt2 != 5}">
                      <set var="result" value="${result}${cnt2}"/>
                      <set var="cnt2" value="${cnt2 + 1}"/>
                      <!-- let the other thread go -->
                      <threads:notify mutex="${mutex}"/>
                      <threads:wait mutex="${mutex}"/>
                  </while>
                  <!-- one last notify -->
                  <threads:notify mutex="${mutex}"/>
              </threads:synchronize>
          </threads:thread>
  
          <threads:join thread="${thread1}"/>
          <threads:join thread="${thread2}"/>
          <test:assertEquals expected="0011223344" actual="${result}"/>
      </test:case>
  
      <test:case name="testWaitFor">
          <set var="result" value=""/>
  
          <threads:thread var="thread1">
              <set var="cnt1" value="0"/>
              <while test="${cnt1 != 5}">
                  <set var="result" value="${result}${cnt1}"/>
                  <set var="cnt1" value="${cnt1 + 1}"/>
                  <!-- force an interrupt, shouldn't matter -->
                  <threads:interrupt/>
              </while>
          </threads:thread>
  
          <threads:thread var="thread2">
              <threads:waitfor thread="${thread1}"/>
              <set var="cnt2" value="5"/>
              <while test="${cnt2 != 10}">
                  <set var="result" value="${result}${cnt2}"/>
                  <set var="cnt2" value="${cnt2 + 1}"/>
              </while>
          </threads:thread>
  
          <threads:join thread="${thread1}"/>
          <threads:join thread="${thread2}"/>
          <test:assertEquals expected="0123456789" actual="${result}"/>
      </test:case>
  
      <test:case name="testWaitForTimeout">
          <set var="result" value=""/>
  
          <threads:thread var="thread1">
              <set var="cnt1" value="0"/>
              <while test="${cnt1 != 5}">
                  <set var="result" value="${result}${cnt1}"/>
                  <set var="cnt1" value="${cnt1 + 1}"/>
                  <!-- force an interrupt, shouldn't matter -->
                  <threads:sleep for="500"/>
              </while>
          </threads:thread>
  
          <threads:thread var="thread2">
              <!-- this will fail since thread 1 is sleeping -->
              <threads:waitfor thread="${thread1}" onlyWait="100"/>
              <set var="cnt2" value="5"/>
              <while test="${cnt2 != 10}">
                  <set var="result" value="${result}${cnt2}"/>
                  <set var="cnt2" value="${cnt2 + 1}"/>
              </while>
          </threads:thread>
  
          <threads:thread var="thread3">
              <threads:waitfor thread="${thread1}"/>
              <!-- thread2 will have been avoided -->
              <threads:waitfor thread="${thread2}" status="AVOIDED"/>
              <set var="cnt2" value="10"/>
              <while test="${cnt2 != 15}">
                  <set var="result" value="${result}${cnt2}"/>
                  <set var="cnt2" value="${cnt2 + 1}"/>
              </while>
          </threads:thread>
  
          <threads:join thread="${thread1}"/>
          <threads:join thread="${thread2}"/>
          <threads:join thread="${thread3}"/>
          <test:assertEquals expected="012341011121314" actual="${result}"/>
      </test:case>
  
      <test:case name="testWaitForFailure">
          <set var="result" value=""/>
  
          <threads:thread var="thread1">
              THROW AN EXCEPTION
              <bsh:script>
                  throw new Exception("This exception SHOULD happen");
              </bsh:script>
          </threads:thread>
  
          <threads:thread var="thread2">
              <!-- this will fail since thread 1 is sleeping -->
              <threads:waitfor thread="${thread1}" status="SUCCESS"/>
              <set var="cnt2" value="5"/>
              <while test="${cnt2 != 10}">
                  <set var="result" value="${result}${cnt2}"/>
                  <set var="cnt2" value="${cnt2 + 1}"/>
              </while>
          </threads:thread>
  
          <threads:thread var="thread3">
              <!-- this will fail since thread 1 is sleeping -->
              <threads:waitfor thread="${thread1}" status="FAILURE"/>
              <set var="cnt2" value="10"/>
              <while test="${cnt2 != 15}">
                  <set var="result" value="${result}${cnt2}"/>
                  <set var="cnt2" value="${cnt2 + 1}"/>
              </while>
          </threads:thread>
  
          <threads:join thread="${thread1}"/>
          <threads:join thread="${thread2}"/>
          <threads:join thread="${thread3}"/>
          <test:assertEquals expected="1011121314" actual="${result}"/>
      </test:case>
  
      <test:case name="testThreadGroup">
          <set var="result" value=""/>
  
          <threads:group var="group1">
              <threads:thread var="thread1">
                  <!-- let thread 3 try and go -->
                  <threads:sleep for="100"/>
                  <set var="result" value="${result}1"/>
              </threads:thread>
  
              <threads:thread>
                  <threads:waitFor thread="${thread1}"/>
                  <!-- let thread 3 try and go -->
                  <threads:sleep for="100"/>
                  <set var="result" value="${result}2"/>
              </threads:thread>
          </threads:group>
  
          <threads:thread>
              <!-- wait for the thread group to complete -->
              <threads:waitFor group="${group1}"/>
              <set var="result" value="${result}3"/>
              <test:assertEquals expected="123" actual="${result}"/>
          </threads:thread>
      </test:case>
      
  </test:suite>
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/threads/TestJelly.java
  
  Index: TestJelly.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/core/JellyTestSuite.java,v 1.8 2002/07/06 13:53:39 dion Exp $
   * $Revision: 1.8 $
   * $Date: 2002/07/06 13:53:39 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   * 
   * $Id: JellyTestSuite.java,v 1.8 2002/07/06 13:53:39 dion Exp $
   */
  package org.apache.commons.jelly.threads;
  
  import junit.framework.TestSuite;
  import junit.textui.TestRunner;
  
  import org.apache.commons.jelly.tags.junit.JellyTestSuite;
  
  /** 
   * A helper class to run jelly test cases as part of Ant's JUnit tests
   *
   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
   * @version $Revision: 1.8 $
   */
  public class TestJelly extends JellyTestSuite {
  
      public static void main( String[] args ) throws Exception {
          TestRunner.run( suite() );
      }
      
      public static TestSuite suite() throws Exception {
          return createTestSuite(TestJelly.class, "suite.jelly");
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/MutexTag.java
  
  Index: MutexTag.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  
  /**
   * Creates a mutex object and stores it in a variable
   * 
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class MutexTag extends TagSupport {
      /** The variable name of the mutex */
      private String var = null;
  
      /** Create and set the mutex */
      public void doTag(XMLOutput output) throws Exception {
          if (var == null) {
              throw new JellyException("mutexes require a var attribute");
          }
  
          context.setVariable(var, this);
      }
  
      /**
       * Sets the variable name to export
       * @param var The variable name
       */
      public void setVar(String var) {
          this.var = var;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/SleepTag.java
  
  Index: SleepTag.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  
  /**
   * Puts the current thread to sleep for some amount of time.
   *
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class SleepTag extends TagSupport {
      /** How long to sleep for */
      private long howLong = 0;
  
      /** Put the thread to sleep */
      public void doTag(XMLOutput output) throws Exception {
          Thread.sleep(howLong);
      }
  
      /**
       * How long to put the thread to sleep for
       * @param howLong in millis
       */
      public void setFor(long howLong) {
          this.howLong = howLong;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/RequirementException.java
  
  Index: RequirementException.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.commons.jelly.tags.threads;
  
  /**
   * Thrown by the {@link WaitForTag} when a requirement is not met.
   *
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class RequirementException extends RuntimeException {
      public RequirementException(String message) {
          super(message);
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/JoinTag.java
  
  Index: JoinTag.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.jelly.XMLOutput;
  
  import java.util.List;
  
  /**
   * A thread join waits until a thread or threadGroup is complete.
   * 
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class JoinTag extends UseThreadTag {
      /** how long to wait */
      private long timeout = -1;
  
      /** Perform the thread join */
      protected void useThread(Thread thread, XMLOutput output) throws Exception {
          joinThread(thread);
      }
  
      /** Join all of the threads in a thread group */
      protected void useThreadGroup(List threadGroup, XMLOutput output) throws Exception {
          for (int i = 0; i < threadGroup.size(); i++) {
              joinThread((Thread) threadGroup.get(i));
          }
      }
  
      /** Join a thread */
      private void joinThread(Thread thread) throws InterruptedException {
          if (timeout > 0) {
              thread.join(timeout);
          } else {
              thread.join();
          }
      }
  
      /**
       * How long should the join wait. If <= 0 the join waits until the
       * thread is dead.
       * @param timeout in millis
       */
      public void setTimeout(long timeout) {
          this.timeout = timeout;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/ThreadTag.java
  
  Index: ThreadTag.java
  ===================================================================
  /*
  *
  * ====================================================================
  *
  * The Apache Software License, Version 1.1
  *
  * Copyright (c) 2002 The Apache Software Foundation.  All rights
  * reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. The end-user documentation included with the redistribution, if
  *    any, must include the following acknowlegement:
  *       "This product includes software developed by the
  *        Apache Software Foundation (http://www.apache.org/)."
  *    Alternately, this acknowlegement may appear in the software itself,
  *    if and wherever such third-party acknowlegements normally appear.
  *
  * 4. The names "The Jakarta Project", "Commons", and "Apache Software
  *    Foundation" must not be used to endorse or promote products derived
  *    from this software without prior written permission. For written
  *    permission, please contact apache@apache.org.
  *
  * 5. Products derived from this software may not be called "Apache"
  *    nor may "Apache" appear in their names without prior written
  *    permission of the Apache Group.
  *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * ====================================================================
  *
  * This software consists of voluntary contributions made by many
  * individuals on behalf of the Apache Software Foundation.  For more
  * information on the Apache Software Foundation, please see
  * <http://www.apache.org/>.
  */
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.jelly.JellyContext;
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  import org.apache.commons.jelly.util.NestedRuntimeException;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  import java.io.FileOutputStream;
  import java.io.IOException;
  
  /**
   * A tag that spawns the contained script in a separate thread.  A thread
   * can wait on another thread or another thread group to finish before starting.
   *
   * @author <a href="mailto:vinayc@apache.org">Vinay Chandran</a>
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  public class ThreadTag extends TagSupport {
      /** The Log to which logging calls will be made. */
      private static final Log log = LogFactory.getLog(ThreadTag.class);
  
      /** The current thread number. Used for default thread naming */
      private static int threadNumber = 0;
  
      /** Variable to place the thread into */
      private String var = null;
      /** Thread Name */
      private String name = null;
      /** Thread priority, defaults to Thread.NORM_PRIORITY */
      private int priority = Thread.NORM_PRIORITY;
      /** Set if the thread should be a daemon or not */
      private boolean daemon = false;
      /** the destination of output */
      private XMLOutput xmlOutput;
      /** Should we close the underlying output */
      private boolean closeOutput;
      /** Should a new context be created */
      private boolean newContext = false;
      /** Keep a reference to the thread */
      private JellyThread thread = new JellyThread();
  
      public ThreadTag() {
          super();
      }
  
      public ThreadTag(boolean shouldTrim) {
          super(shouldTrim);
      }
  
      // Tag interface
      //-------------------------------------------------------------------------
      public void doTag(final XMLOutput output) throws Exception {
          if (xmlOutput == null) {
              // lets default to system.out
              xmlOutput = XMLOutput.createXMLOutput(System.out);
          }
  
          // lets create a child context
          final JellyContext useThisContext = newContext ? context.newJellyContext() : context;
  
          // set the target to run
          thread.setTarget(new Runnable() {
              public void run() {
                  try {
                      getBody().run(useThisContext, xmlOutput);
                      if (closeOutput) {
                          xmlOutput.close();
                      } 
                      else {
                          xmlOutput.flush();
                      }
                  } 
                  catch (JellyException e) {
                      // jelly wraps the exceptions thrown
                      Throwable subException = e.getCause();
                      if (subException != null) {
                          if (subException instanceof TimeoutException) {
                              throw (TimeoutException)subException;
                          } else if (subException instanceof RequirementException) {
                              throw (RequirementException)subException;
                          }
                      }
  
                      log.error(e);
  
                      // wrap the exception with a RuntimeException
                      throw new NestedRuntimeException(e);
                  }
                  catch (Exception e) {
                      log.error(e);
  
                      // wrap the exception with a RuntimeException
                      if (e instanceof RuntimeException) {
                      	throw (RuntimeException) e;
                      }
                      else {
                      	throw new NestedRuntimeException(e);
                      }
                  }
              }
          });
  
          // set the threads priority
          thread.setPriority(priority);
  
          // set the threads name
          if (name != null) {
              thread.setName(name);
          } else {
              thread.setName("Jelly Thread #" + (threadNumber++));
          }
  
          // set whether this thread is a daemon thread
          thread.setDaemon(daemon);
  
          // save the thread in a context variable
          if (var != null) {
              context.setVariable(var, thread);
          }
  
          // check if this tag is nested inside a group tag. if so
          // add this thread to the thread group but do not start it.
          // all threads in a thread group should start together.
          GroupTag gt = (GroupTag) findAncestorWithClass(GroupTag.class);
          if (gt != null) {
              gt.addThread(thread);
          } else {
              // start the thread
              thread.start();
          }
      }
  
      /**
       * Sets the variable name to export, optional
       * @param var The variable name
       */
      public void setVar(String var) {
          this.var = var;
          if (name == null) {
              name = var;
          }
      }
  
      /**
       * Sets the name of the thread.
       * @param name The name to set
       */
      public void setName(String name) {
          this.name = name;
      }
  
      /**
       * Set the threads priority. Defaults to Thread.NORM_PRIORITY
       */
      public void setPriority(int priority) {
          this.priority = priority;
      }
  
      /**
       * Sets the thread to be a daemon thread if true
       */
      public void setDaemon(boolean daemon) {
          this.daemon = daemon;
      }
  
      /**
       * Sets the destination of output
       */
      public void setXmlOutput(XMLOutput xmlOutput) {
          this.closeOutput = false;
          this.xmlOutput = xmlOutput;
      }
  
      /**
       * Set the file which is generated from the output
       * @param name The output file name
       */
      public void setFile(String name) throws IOException {
          this.closeOutput = true;
          setXmlOutput(XMLOutput.createXMLOutput(new FileOutputStream(name)));
      }
  
      /**
       * Should a new context be created for this thread?
       */
      public void setNewContext(boolean newContext) {
          this.newContext = newContext;
      }
  
      /**
       * Get the thread instance
       * @return The thread
       */
      public Thread getThread() {
          return thread;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/ThreadsTagLibrary.java
  
  Index: ThreadsTagLibrary.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.jelly.TagLibrary;
  
  /**
   * Thread related tags
   *
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class ThreadsTagLibrary extends TagLibrary {
      public ThreadsTagLibrary() {
          registerTag("thread", ThreadTag.class);
          registerTag("interrupt", InterruptTag.class);
          registerTag("join", JoinTag.class);
          registerTag("mutex", MutexTag.class);
          registerTag("notify", NotifyTag.class);
          registerTag("sleep", SleepTag.class);
          registerTag("wait", WaitTag.class);
          registerTag("synchronize", SynchronizeTag.class);
          registerTag("waitFor", WaitForTag.class);
          registerTag("waitfor", WaitForTag.class);
          registerTag("group", GroupTag.class);
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/SynchronizeTag.java
  
  Index: SynchronizeTag.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.jelly.XMLOutput;
  
  /**
   * Synchronize a block inside of a thread using the passed in mutex. The
   * mutex object passed in does not have to have been created using the
   * mutex tag, it can be any object at all.
   *
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class SynchronizeTag extends UseMutexTag {
      /** Synchronize on the mutex */
      protected void useMutex(Object mutex, XMLOutput output) throws Exception {
          synchronized (mutex) {
              invokeBody(output);
          }
      }
  }
  
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/GroupTag.java
  
  Index: GroupTag.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * Represents a group of threads. This is not the same as Java's thread groups.
   * All of the threads in a thread group are started at the same time, not as they
   * are defined. Use this in conjunction with other tags like join to manipulate
   * a group of threads.
   *
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class GroupTag extends TagSupport {
      /** Variable to place the thread group into */
      private String var = null;
      /** The thread list */
      private List threads = new ArrayList();
  
      /** Child threads will add themselves and will then all be started together */
      public void doTag(XMLOutput output) throws Exception {
          invokeBody(output);
  
          // store the group in a jelly variable
          if (var != null) {
              context.setVariable(var, threads);
          }
  
          // start the threads
          for (int i = 0; i < threads.size(); i++) {
              Thread thread = (Thread) threads.get(i);
              thread.start();
          }
      }
  
      /** Add a thread to the thread group list */
      public void addThread(Thread thread) {
          threads.add(thread);
      }
  
      /** Get the list of threads in this thread group */
      public List getThreads() {
          return threads;
      }
  
      /** Set the variable name to store the thread group in */
      public void setVar(String var) {
          this.var = var;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/UseMutexTag.java
  
  Index: UseMutexTag.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  
  /**
   * Base class for tags that will "use" mutexes.
   *
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public abstract class UseMutexTag extends TagSupport {
      /** The mutex to use in some way. */
      private Object mutex = null;
  
      /** Calls useMutex after checking to make sure that <i>setMutex</i> was called */
      public void doTag(XMLOutput output) throws Exception {
          // either use the set thread or search for a parent thread to use
          if (mutex == null) {
              throw new JellyException("no mutex set");
          }
  
          useMutex(mutex, output);
      }
  
      /** Implement this method to do something with the mutex */
      protected abstract void useMutex(Object mutex, XMLOutput output) throws Exception;
  
      /** Get the mutex */
      public Object getMutex() {
          return mutex;
      }
  
      /** Set the mutex. Any object can be used as a mutex. */
      public void setMutex(Object mutex) {
          this.mutex = mutex;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/JellyThread.java
  
  Index: JellyThread.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  /**
   * Adds some functionality to the jdk thread class.
   *
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class JellyThread extends Thread {
      /** The Log to which logging calls will be made. */
      private static final Log log = LogFactory.getLog(ThreadTag.class);
  
      /** While this thread is still running it owns this mutex */
      private Mutex runningMutex = new Mutex();
      /** The Runnable target */
      private Runnable target = null;
  
      /** Tracks the status of this thread */
      RunnableStatus status = new RunnableStatus();
  
      public JellyThread() {
          // aquire my still running lock immediately
          while (true) {
              try {
                  runningMutex.acquire();
                  break;
              } catch (InterruptedException e) {
              }
          }
      }
  
      /**
       * Set the Runnable target that will be run
       */
      public void setTarget(Runnable target) {
          this.target = target;
      }
  
      /**
       * Run the thread
       */
      public void run() {
          log.debug("Starting thread \"" + getName() + "\"");
  
          // run the runnable item
          try {
  
              log.debug("Thread \"" + getName() + "\" running");
              target.run();
  
              // as long as there were no runtime exceptions set SUCCESS
              status.set(RunnableStatus.SUCCESS);
  
          } catch(RequirementException e) {
  
              status.set(RunnableStatus.AVOIDED);
              log.warn("Thread \"" + getName() + "\" avoided, " + e.getMessage());
  
          } catch(TimeoutException e) {
  
              status.set(RunnableStatus.AVOIDED);
              log.warn("Thread \"" + getName() + "\" avoided, " + e.getMessage());
  
          } catch (Exception e) {
  
              // runtime exceptions will cause a status of FAILURE
              status.set(RunnableStatus.FAILURE, e);
              log.error("Thread \"" + getName() + "\" failure, " + e.getMessage());
              log.debug(e);
  
          }
  
          // release the i'm still running mutex
          runningMutex.release();
  
          log.debug("Thread \"" + getName() + "\" finished");
      }
  
      /**
       * Call this method from a different thread to wait until this thread is done. This
       * is used by the {@link WaitForTag} class.
       */
      public void waitUntilDone(long howLong) throws TimeoutException {
          if (Thread.currentThread() == this) {
              throw new RuntimeException("This method should be called from a different thread than itself");
          }
  
          // wait until the calling thread can aquire the lock
          while (true) {
              try {
                  if (howLong == -1) {
                      runningMutex.acquire();
                      break;
                  } else if (!runningMutex.attempt(howLong)) {
                      throw new TimeoutException("max wait time exceeded");
                  }
              } catch (InterruptedException e) {
              }
          }
  
          // release the lock, just needed it to get started
          runningMutex.release();
      }
  
      /** Get the status of this thread */
      public RunnableStatus getStatus() {
          return status;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/TimeoutException.java
  
  Index: TimeoutException.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.commons.jelly.tags.threads;
  
  /**
   * Can be thrown when the {@link WaitForTag} tries to wait for another
   * thread to finish.
   *
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class TimeoutException extends RuntimeException {
      public TimeoutException(String message) {
          super(message);
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/UseThreadTag.java
  
  Index: UseThreadTag.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  
  import java.util.List;
  
  /**
   * Base class for tags that will "use" threads.
   *
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public abstract class UseThreadTag extends TagSupport {
      /** The thread to use in some way. */
      private Thread thread = null;
      /** Threads can be grouped and acted on as a set */
      private List threadGroup = null;
      /** If true doTag will search for a parent thread to use if setThread was not called */
      private boolean searchForParent = true;
  
      /**
       * The default behavior is to either use the set thread or to
       * search for a parent thread to use.
       */
      public void doTag(XMLOutput output) throws Exception {
          // either use the set thread or search for a parent thread to use
          if (thread != null) {
              useThread(thread, output);
          } else if (threadGroup != null) {
              useThreadGroup(threadGroup, output);
          } else {
              // check if this tag is nested inside a thread. if so
              // use the parent thread.
              if (searchForParent) {
                  // first look for parent threads
                  ThreadTag tt = (ThreadTag) findAncestorWithClass(ThreadTag.class);
                  if (tt != null) {
                      useThread(tt.getThread(), output);
                  } else {
                      // then look for parent thread groups
                      GroupTag gt = (GroupTag) findAncestorWithClass(GroupTag.class);
                      if (gt != null) {
                          useThreadGroup(gt.getThreads(), output);
                      } else {
                          throw new JellyException("no thread or thread group found");
                      }
                  }
              } else {
                  throw new JellyException("no thread or thread group found");
              }
          }
      }
  
      /** Implement this method to do something with the thread */
      protected abstract void useThread(Thread thread, XMLOutput output) throws Exception;
  
      /** Implement this method to do something with the threadGroup */
      protected abstract void useThreadGroup(List threadGroup, XMLOutput output) throws Exception;
  
      /**
       * Set the thread to use in some way.
       */
      public void setThread(Thread thread) {
          this.thread = thread;
      }
  
      /**
       * Get a reference to the thread to use
       */
      public Thread getThread() {
          return thread;
      }
  
      /**
       * Set the thread group to "use".
       * @param threadGroup The threadGroup created with the <i>group</i> tag.
       */
      public void setThreadGroup(List threadGroup) {
          this.threadGroup = threadGroup;
      }
  
      /**
       * Get the thread group
       */
      public List getThreadGroup() {
          return threadGroup;
      }
  
      /**
       * If true the tag will search for a parent thread tag to "use" if
       * no thread was set via <i>setThread</i>. This is <i>true</i> by default.
       */
      public void setSearchForParentThread(boolean searchForParent) {
          this.searchForParent = searchForParent;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/WaitForTag.java
  
  Index: WaitForTag.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.jelly.JellyException;
  import org.apache.commons.jelly.TagSupport;
  import org.apache.commons.jelly.XMLOutput;
  
  import java.util.List;
  
  /**
   * This tag creates a dependency on another thread. If onlyWait is set
   * a {@link TimeoutException} can be thrown. If status is set a {@link RequirementException}
   * can be thrown.
   *
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class WaitForTag extends TagSupport {
      private int status = RunnableStatus.NONE;
      private JellyThread thread = null;
      private List group = null;
      private long onlyWait = -1;
  
      /**
       * Wait for a specific status. "SUCCESS", "FAILURE", "TIMED_OUT", or "AVOIDED". If
       * waiting on a thread group each thread in the group will have to have this status
       * set.
       */
      public void setStatus(String status) {
          this.status = RunnableStatus.getStatusCode(status);
      }
  
      /**
       * Which thread will this tag check the status of
       */
      public void setThread(JellyThread thread) {
          this.thread = thread;
      }
  
      /**
       * Set the group of threads to wait on
       */
      public void setGroup(List group) {
          this.group = group;
      }
  
      /**
       * Set how long to wait for the thread to finish. If waiting for a group
       * this will be the time to wait for each thread in the group to finish.
       */
      public void setOnlyWait(long onlyWait) {
          this.onlyWait = onlyWait;
      }
  
      /**
       * Check the requirements
       * @throws TimeoutException If the call to waitUntilDone(onlyWait) times out
       * @throws RequirementException If a threads status doesn't match the setStatus() value
       */
      public void doTag(XMLOutput output) throws TimeoutException, RequirementException, Exception {
          if (thread == null && group == null) {
              throw new JellyException("This tag requires that you set the thread or group attribute");
          }
  
          // wait on the thread
          if (thread != null) {
              thread.waitUntilDone(onlyWait);
              if (status != RunnableStatus.NONE) {
                  if (!thread.getStatus().equals(status)) {
                      throw new RequirementException("Requirement on thread \"" + thread.getName() + "\" not met");
                  }
              }
          }
  
          // wait on the threadgroup
          if (group != null) {
              for (int i = 0; i < group.size(); i++) {
                  JellyThread gthread = (JellyThread) group.get(i);
                  gthread.waitUntilDone(onlyWait);
                  if (status != RunnableStatus.NONE) {
                      if (!gthread.getStatus().equals(status)) {
                          throw new RequirementException("Requirement on thread \"" + gthread.getName() + "\" not met");
                      }
                  }
              }
          }
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/RunnableStatus.java
  
  Index: RunnableStatus.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.commons.jelly.tags.threads;
  
  /**
   * Represents the status of {@link JellyThread}.
   *
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class RunnableStatus {
      public static final int NONE = 0;
      public static final int SUCCESS = 1;
      public static final int FAILURE = 2;
      public static final int AVOIDED = 3;
      public static final int TIMED_OUT = 4;
      public static final int KILLED = 5;
  
      private int status = NONE;
  
      /** On a status change to FAILURE an exception can be set */
      private Exception exception = null;
  
      public RunnableStatus() {
  
      }
  
      public RunnableStatus(int status) {
          set(status);
      }
  
      public synchronized void set(int status) {
          set(status, null);
      }
  
      public synchronized void set(int status, Exception e) {
          // this check is important since I may call setStatus(BLAH) again
          // to trigger the callback
          if (this.status != status) {
              this.status = status;
  
              // store the exception if one was set
              if (e != null)
                  this.exception = e;
          }
      }
  
      public synchronized int get() {
          return status;
      }
  
      public synchronized boolean isSuccess() {
          return (status == SUCCESS);
      }
  
      public synchronized boolean isFailure() {
          return (status == FAILURE);
      }
  
      public synchronized boolean isAvoided() {
          return (status == AVOIDED);
      }
  
      public synchronized boolean isTimedOut() {
          return (status == TIMED_OUT);
      }
  
      public synchronized boolean isKilled() {
          return (status == KILLED);
      }
  
      public synchronized Exception getException() {
          return exception;
      }
  
      public synchronized boolean equals(RunnableStatus status) {
          return status.get() == this.status;
      }
  
      public synchronized boolean equals(int status) {
          return this.status == status;
      }
  
      /**
       * Used to get the status code from a string representation. Mainly used for
       * xml parsing.
       * @param status The status string rep.
       * @return The status enum value
       */
      public static int getStatusCode(String status) {
          if (status.equalsIgnoreCase("SUCCESS")) {
              return SUCCESS;
          } else if (status.equalsIgnoreCase("FAILURE")) {
              return FAILURE;
          } else if (status.equalsIgnoreCase("TIMED_OUT")) {
              return TIMED_OUT;
          } else if (status.equalsIgnoreCase("AVOIDED")) {
              return AVOIDED;
          } else if (status.equalsIgnoreCase("KILLED")) {
              return KILLED;
          } else {
              throw new IllegalArgumentException(status + " is invalid status");
          }
      }
  
      /**
       * The reverse of getStatusCode
       */
      public static String getStatusString(int status) {
          if (status == SUCCESS) {
              return "SUCCESS";
          } else if (status == FAILURE) {
              return "FAILURE";
          } else if (status == TIMED_OUT) {
              return "TIMED_OUT";
          } else if (status == AVOIDED) {
              return "AVOIDED";
          } else if (status == KILLED) {
              return "KILLED";
          } else {
              throw new IllegalArgumentException(status + " is invalid status");
          }
      }
  
      public static boolean isValidStatus(int status) {
          if (status == SUCCESS) {
              return true;
          } else if (status == FAILURE) {
              return true;
          } else if (status == TIMED_OUT) {
              return true;
          } else if (status == AVOIDED) {
              return true;
          } else if (status == KILLED) {
              return true;
          } else {
              return false;
          }
      }
  
      public String toString() {
          return getStatusString(status);
      }
  }
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/package.html
  
  Index: package.html
  ===================================================================
  <html>
  <head>
  </head>
  <body>
  
    <p>
    	A library for processing Jelly scripts using multiple threads.
    </p>
    
  </body>
  </html>
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/WaitTag.java
  
  Index: WaitTag.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.jelly.XMLOutput;
  
  /**
   * This calls mutex.wait() on the mutex passed in via the "mutex" attribute.
   *
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class WaitTag extends UseMutexTag {
      /** How long should the wait last. If <=0 it lasts until a notify. */
      private long timeout = -1;
  
      /** Start waiting */
      public void useMutex(Object mutex, XMLOutput output) throws Exception {
          if (timeout > 0) {
              mutex.wait(timeout);
          } else {
              mutex.wait();
          }
      }
  
      /**
       * Set how long the wait should last. If <= 0 the wait will last
       * until a notify occurs.
       * @param timeout in millis
       */
      public void setTimeout(long timeout) {
          this.timeout = timeout;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/NotifyTag.java
  
  Index: NotifyTag.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.jelly.XMLOutput;
  
  /**
   * This calls mutex.notify() or mutex.notifyAll() on the mutex passed
   * in via the "mutex" attribute.
   *
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class NotifyTag extends UseMutexTag {
      /** True means mutex.notifyAll() will be called */
      private boolean notifyAll = false;
  
      /** Perform the notify */
      public void useMutex(Object mutex, XMLOutput output) throws Exception {
          if (notifyAll) {
              mutex.notifyAll();
          } else {
              mutex.notify();
          }
      }
  
      /**
       * If set to true the notify will notify all waiting threads
       */
      public void setNotifyAll(boolean notifyAll) {
          this.notifyAll = notifyAll;
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/Mutex.java
  
  Index: Mutex.java
  ===================================================================
  /*
    File: Mutex.java
  
    Originally written by Doug Lea and released into the public domain.
    This may be used for any purposes whatsoever without acknowledgment.
    Thanks for the assistance and support of Sun Microsystems Labs,
    and everyone contributing, testing, and using this code.
  
    History:
    Date       Who                What
    11Jun1998  dl               Create public version
  */
  
  package org.apache.commons.jelly.tags.threads;
  
  /**
   * A simple non-reentrant mutual exclusion lock.
   * The lock is free upon construction. Each acquire gets the
   * lock, and each release frees it. Releasing a lock that
   * is already free has no effect.
   * <p>
   * This implementation makes no attempt to provide any fairness
   * or ordering guarantees. If you need them, consider using one of
   * the Semaphore implementations as a locking mechanism.
   * <p>
   * <b>Sample usage</b><br>
   * <p>
   * Mutex can be useful in constructions that cannot be
   * expressed using java synchronized blocks because the
   * acquire/release pairs do not occur in the same method or
   * code block. For example, you can use them for hand-over-hand
   * locking across the nodes of a linked list. This allows
   * extremely fine-grained locking,  and so increases
   * potential concurrency, at the cost of additional complexity and
   * overhead that would normally make this worthwhile only in cases of
   * extreme contention.
   * <pre>
   * class Node {
   *   Object item;
   *   Node next;
   *   Mutex lock = new Mutex(); // each node keeps its own lock
   *
   *   Node(Object x, Node n) { item = x; next = n; }
   * }
   *
   * class List {
   *    protected Node head; // pointer to first node of list
   *
   *    // Use plain java synchronization to protect head field.
   *    //  (We could instead use a Mutex here too but there is no
   *    //  reason to do so.)
   *    protected synchronized Node getHead() { return head; }
   *
   *    boolean search(Object x) throws InterruptedException {
   *      Node p = getHead();
   *      if (p == null) return false;
   *
   *      //  (This could be made more compact, but for clarity of illustration,
   *      //  all of the cases that can arise are handled separately.)
   *
   *      p.lock.acquire();              // Prime loop by acquiring first lock.
   *                                     //    (If the acquire fails due to
   *                                     //    interrupt, the method will throw
   *                                     //    InterruptedException now,
   *                                     //    so there is no need for any
   *                                     //    further cleanup.)
   *      for (;;) {
   *        if (x.equals(p.item)) {
   *          p.lock.release();          // release current before return
   *          return true;
   *        }
   *        else {
   *          Node nextp = p.next;
   *          if (nextp == null) {
   *            p.lock.release();       // release final lock that was held
   *            return false;
   *          }
   *          else {
   *            try {
   *              nextp.lock.acquire(); // get next lock before releasing current
   *            }
   *            catch (InterruptedException ex) {
   *              p.lock.release();    // also release current if acquire fails
   *              throw ex;
   *            }
   *            p.lock.release();      // release old lock now that new one held
   *            p = nextp;
   *          }
   *        }
   *      }
   *    }
   *
   *    synchronized void add(Object x) { // simple prepend
   *      // The use of `synchronized'  here protects only head field.
   *      // The method does not need to wait out other traversers
   *      // who have already made it past head.
   *
   *      head = new Node(x, head);
   *    }
   *
   *    // ...  other similar traversal and update methods ...
   * }
   * </pre>
   * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
   *
   * --------------------------------------------------------------------------------------------
   * This Mutex is used to add the still running lock to the JellyThread tag.
   **/
  
  public class Mutex {
  
      /** The lock status **/
      protected boolean inuse_ = false;
  
      public void acquire() throws InterruptedException {
          if (Thread.interrupted()) throw new InterruptedException();
          synchronized (this) {
              try {
                  while (inuse_) wait();
                  inuse_ = true;
              } catch (InterruptedException ex) {
                  notify();
                  throw ex;
              }
          }
      }
  
      public synchronized void release() {
          inuse_ = false;
          notify();
      }
  
  
      public boolean attempt(long msecs) throws InterruptedException {
          if (Thread.interrupted()) throw new InterruptedException();
          synchronized (this) {
              if (!inuse_) {
                  inuse_ = true;
                  return true;
              } else if (msecs <= 0)
                  return false;
              else {
                  long waitTime = msecs;
                  long start = System.currentTimeMillis();
                  try {
                      for (; ;) {
                          wait(waitTime);
                          if (!inuse_) {
                              inuse_ = true;
                              return true;
                          } else {
                              waitTime = msecs - (System.currentTimeMillis() - start);
                              if (waitTime <= 0)
                                  return false;
                          }
                      }
                  } catch (InterruptedException ex) {
                      notify();
                      throw ex;
                  }
              }
          }
      }
  
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/threads/InterruptTag.java
  
  Index: InterruptTag.java
  ===================================================================
  /*
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.commons.jelly.tags.threads;
  
  import org.apache.commons.jelly.XMLOutput;
  
  import java.util.List;
  
  /**
   * Interrupts a thread or thread group.
   * 
   * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
   */
  
  public class InterruptTag extends UseThreadTag {
      /** Interrupt one thread */
      protected void useThread(Thread thread, XMLOutput output) throws Exception {
          thread.interrupt();
      }
  
      /** Interrupt all of the threads in a group */
      protected void useThreadGroup(List threadGroup, XMLOutput output) throws Exception {
          for (int i = 0; i < threadGroup.size(); i++) {
              ((Thread) threadGroup.get(i)).interrupt();
          }
      }
  }
  
  
  
  1.28      +1 -0      jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/jelly.properties
  
  Index: jelly.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/jelly.properties,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- jelly.properties	30 Oct 2002 11:54:11 -0000	1.27
  +++ jelly.properties	30 Oct 2002 19:13:02 -0000	1.28
  @@ -12,6 +12,7 @@
   junit 	    = org.apache.commons.jelly.tags.junit.JUnitTagLibrary
   bean		= org.apache.commons.jelly.tags.bean.BeanTagLibrary
   dynabean	= org.apache.commons.jelly.tags.dynabean.DynabeanTagLibrary
  +threads  	= org.apache.commons.jelly.tags.threads.ThreadsTagLibrary
   
   # optional taglibs
   swing	    = org.apache.commons.jelly.tags.swing.SwingTagLibrary
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>