[jboss-cvs] JBossAS SVN: r84336 - in projects: jboss-threads and 34 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Feb 17 18:09:48 EST 2009


Author: david.lloyd at jboss.com
Date: 2009-02-17 18:09:48 -0500 (Tue, 17 Feb 2009)
New Revision: 84336

Added:
   projects/jboss-threads/
   projects/jboss-threads/branches/
   projects/jboss-threads/tags/
   projects/jboss-threads/trunk/
   projects/jboss-threads/trunk/COPYING.txt
   projects/jboss-threads/trunk/jbossmc/
   projects/jboss-threads/trunk/jbossmc/pom.xml
   projects/jboss-threads/trunk/jbossmc/src/
   projects/jboss-threads/trunk/jbossmc/src/main/
   projects/jboss-threads/trunk/jbossmc/src/main/java/
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/DirectExecutorMetaData.java
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ExceptionHandlerRefMetaData.java
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/InterruptHandlerRefMetaData.java
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/NotatingExecutorMetaData.java
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/PoolSizeMetaData.java
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/RejectPolicyMetaData.java
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadFactoryMetaData.java
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadGroupMetaData.java
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadPoolExecutorMetaData.java
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadsMetaData.java
   projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/TimeMetaData.java
   projects/jboss-threads/trunk/jbossmc/src/main/resources/
   projects/jboss-threads/trunk/jbossmc/src/main/resources/META-INF/
   projects/jboss-threads/trunk/jbossmc/src/main/resources/META-INF/jboss-beans.xml
   projects/jboss-threads/trunk/jbossmc/src/main/resources/schema/
   projects/jboss-threads/trunk/jbossmc/src/main/resources/schema/jboss-threads_1_0.xsd
   projects/jboss-threads/trunk/main/
   projects/jboss-threads/trunk/main/pom.xml
   projects/jboss-threads/trunk/main/src/
   projects/jboss-threads/trunk/main/src/main/
   projects/jboss-threads/trunk/main/src/main/java/
   projects/jboss-threads/trunk/main/src/main/java/org/
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ArrayQueue.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/DirectExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/DirectExecutorService.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/InterruptHandler.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossExecutors.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThread.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThreadFactory.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThreadPoolExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/OrderedExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedDirectExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedDirectExecutorService.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedExecutorService.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/RejectionPolicy.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/SimpleQueueExecutor.java
   projects/jboss-threads/trunk/main/src/main/resources/
   projects/jboss-threads/trunk/main/src/main/resources/META-INF/
   projects/jboss-threads/trunk/main/src/main/resources/META-INF/jboss-classloading.xml
   projects/jboss-threads/trunk/main/src/test/
   projects/jboss-threads/trunk/main/src/test/java/
   projects/jboss-threads/trunk/main/src/test/java/org/
   projects/jboss-threads/trunk/main/src/test/java/org/jboss/
   projects/jboss-threads/trunk/main/src/test/java/org/jboss/threads/
   projects/jboss-threads/trunk/main/src/test/java/org/jboss/threads/ArrayQueueTestCase.java
   projects/jboss-threads/trunk/main/src/test/java/org/jboss/threads/ThreadFactoryTestCase.java
   projects/jboss-threads/trunk/main/src/test/java/org/jboss/threads/ThreadPoolTestCase.java
   projects/jboss-threads/trunk/pom.xml
   projects/jboss-threads/trunk/test-support/
   projects/jboss-threads/trunk/test-support/src/
   projects/jboss-threads/trunk/test-support/src/main/
   projects/jboss-threads/trunk/test-support/src/main/java/
   projects/jboss-threads/trunk/test-support/src/main/java/org/
   projects/jboss-threads/trunk/test-support/src/main/java/org/jboss/
   projects/jboss-threads/trunk/test-support/src/main/java/org/jboss/testsupport/
   projects/jboss-threads/trunk/test-support/src/main/java/org/jboss/testsupport/LoggingHelper.java
   projects/jboss-threads/trunk/test-support/src/main/java/org/jboss/testsupport/LoggingSecurityManager.java
   projects/jboss-threads/trunk/test-support/src/main/resources/
   projects/jboss-threads/trunk/test-support/src/main/resources/testing.policy
Log:
Import jboss-threads project

Added: projects/jboss-threads/trunk/COPYING.txt
===================================================================
--- projects/jboss-threads/trunk/COPYING.txt	                        (rev 0)
+++ projects/jboss-threads/trunk/COPYING.txt	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,458 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS

Added: projects/jboss-threads/trunk/jbossmc/pom.xml
===================================================================
--- projects/jboss-threads/trunk/jbossmc/pom.xml	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/pom.xml	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,39 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.jboss.threads</groupId>
+    <artifactId>threads-metadata</artifactId>
+    <packaging>jar</packaging>
+    <version>1.0.0.CR1</version>
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.threads</groupId>
+            <artifactId>threads</artifactId>
+            <version>1.0.0.CR1</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.microcontainer</groupId>
+            <artifactId>jboss-kernel</artifactId>
+            <version>2.0.2.GA</version>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>2.0.2</version>
+                <configuration>
+                    <source>1.5</source>
+                    <target>1.5</target>
+                </configuration>
+            </plugin>
+        </plugins>
+        <finalName>jboss-threads-metadata</finalName>
+    </build>
+</project>

Added: projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/DirectExecutorMetaData.java
===================================================================
--- projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/DirectExecutorMetaData.java	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/DirectExecutorMetaData.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads.metadata;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ *
+ */
+ at XmlType(name = "direct-executor")
+public final class DirectExecutorMetaData {
+    private String name;
+
+    public String getName() {
+        return name;
+    }
+
+    @XmlAttribute(required = true)
+    public void setName(final String name) {
+        this.name = name;
+    }
+}

Added: projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ExceptionHandlerRefMetaData.java
===================================================================
--- projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ExceptionHandlerRefMetaData.java	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ExceptionHandlerRefMetaData.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads.metadata;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ *
+ */
+ at XmlType(name = "exception-handler")
+public final class ExceptionHandlerRefMetaData {
+    private String name;
+
+    public String getName() {
+        return name;
+    }
+
+    @XmlAttribute(required = true)
+    public void setName(final String name) {
+        this.name = name;
+    }
+}

Added: projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/InterruptHandlerRefMetaData.java
===================================================================
--- projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/InterruptHandlerRefMetaData.java	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/InterruptHandlerRefMetaData.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads.metadata;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ *
+ */
+ at XmlType(name = "interrupt-handler")
+public final class InterruptHandlerRefMetaData {
+    private String name;
+
+    public String getName() {
+        return name;
+    }
+
+    @XmlAttribute(required = true)
+    public void setName(final String name) {
+        this.name = name;
+    }
+}

Added: projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/NotatingExecutorMetaData.java
===================================================================
--- projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/NotatingExecutorMetaData.java	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/NotatingExecutorMetaData.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads.metadata;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ *
+ */
+ at XmlType(name = "notating-executor")
+public final class NotatingExecutorMetaData {
+    private String name;
+    private String parent;
+    private String note;
+
+    public String getName() {
+        return name;
+    }
+
+    @XmlAttribute(required = true)
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public String getParent() {
+        return parent;
+    }
+
+    @XmlAttribute(required = true)
+    public void setParent(final String parent) {
+        this.parent = parent;
+    }
+
+    public String getNote() {
+        return note;
+    }
+
+    @XmlAttribute(required = true)
+    public void setNote(final String note) {
+        this.note = note;
+    }
+}

Added: projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/PoolSizeMetaData.java
===================================================================
--- projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/PoolSizeMetaData.java	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/PoolSizeMetaData.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads.metadata;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ *
+ */
+ at XmlType(name = "pool-size")
+public final class PoolSizeMetaData {
+    private float count;
+    private float perCpu;
+
+    public float getCount() {
+        return count;
+    }
+
+    @XmlAttribute
+    public void setCount(final float count) {
+        this.count = count;
+    }
+
+    public float getPerCpu() {
+        return perCpu;
+    }
+
+    @XmlAttribute(name = "per-cpu")
+    public void setPerCpu(final float perCpu) {
+        this.perCpu = perCpu;
+    }
+}

Added: projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/RejectPolicyMetaData.java
===================================================================
--- projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/RejectPolicyMetaData.java	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/RejectPolicyMetaData.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads.metadata;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ *
+ */
+ at XmlType(name = "reject-policy")
+public final class RejectPolicyMetaData {
+    private String name;
+    private String executorName;
+
+    public String getName() {
+        return name;
+    }
+
+    @XmlAttribute(required = true)
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public String getExecutorName() {
+        return executorName;
+    }
+
+    @XmlAttribute(name = "executor-name")
+    public void setExecutorName(final String executorName) {
+        this.executorName = executorName;
+    }
+}

Added: projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadFactoryMetaData.java
===================================================================
--- projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadFactoryMetaData.java	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadFactoryMetaData.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,114 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads.metadata;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ *
+ */
+ at XmlType(name = "thread-factory")
+public final class ThreadFactoryMetaData {
+    private String name;
+    private String group;
+    private Boolean daemon;
+    private Integer initialPriority;
+    private Long stackSize;
+    private String threadNamePattern = "pool-%f-thread-%t";
+    private ExceptionHandlerRefMetaData exceptionHandler;
+    private InterruptHandlerRefMetaData[] interruptHandlers = new InterruptHandlerRefMetaData[0];
+
+    public String getName() {
+        return name;
+    }
+
+    @XmlAttribute(required = true)
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public String getGroup() {
+        return group;
+    }
+
+    @XmlAttribute
+    public void setGroup(final String group) {
+        this.group = group;
+    }
+
+    public Boolean getDaemon() {
+        return daemon;
+    }
+
+    @XmlAttribute
+    public void setDaemon(final Boolean daemon) {
+        this.daemon = daemon;
+    }
+
+    public Integer getInitialPriority() {
+        return initialPriority;
+    }
+
+    @XmlAttribute(name = "initial-priority")
+    public void setInitialPriority(final Integer initialPriority) {
+        this.initialPriority = initialPriority;
+    }
+
+    public Long getStackSize() {
+        return stackSize;
+    }
+
+    @XmlAttribute(name = "stack-size")
+    public void setStackSize(final Long stackSize) {
+        this.stackSize = stackSize;
+    }
+
+    public String getThreadNamePattern() {
+        return threadNamePattern;
+    }
+
+    @XmlAttribute(name = "thread-name-pattern")
+    public void setThreadNamePattern(final String threadNamePattern) {
+        this.threadNamePattern = threadNamePattern;
+    }
+
+    public ExceptionHandlerRefMetaData getExceptionHandler() {
+        return exceptionHandler;
+    }
+
+    @XmlElement(name = "exception-handler")
+    public void setExceptionHandler(final ExceptionHandlerRefMetaData exceptionHandler) {
+        this.exceptionHandler = exceptionHandler;
+    }
+
+    public InterruptHandlerRefMetaData[] getInterruptHandlers() {
+        return interruptHandlers;
+    }
+
+    @XmlElement(name = "interrupt-handler")
+    public void setInterruptHandlers(final InterruptHandlerRefMetaData[] interruptHandlers) {
+        this.interruptHandlers = interruptHandlers;
+    }
+}

Added: projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadGroupMetaData.java
===================================================================
--- projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadGroupMetaData.java	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadGroupMetaData.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,80 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads.metadata;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+ at XmlType(name = "thread-group")
+public final class ThreadGroupMetaData {
+    private String name;
+    private String groupName;
+    private String parent;
+    private Boolean daemon;
+    private Integer maxPriority;
+
+    public String getName() {
+        return name;
+    }
+
+    @XmlAttribute(required = true)
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public String getGroupName() {
+        return groupName;
+    }
+
+    @XmlAttribute(name = "group-name", required = true)
+    public void setGroupName(final String groupName) {
+        this.groupName = groupName;
+    }
+
+    public String getParent() {
+        return parent;
+    }
+
+    @XmlAttribute
+    public void setParent(final String parent) {
+        this.parent = parent;
+    }
+
+    public Boolean isDaemon() {
+        return daemon;
+    }
+
+    @XmlAttribute
+    public void setDaemon(final Boolean daemon) {
+        this.daemon = daemon;
+    }
+
+    public Integer getMaxPriority() {
+        return maxPriority;
+    }
+
+    @XmlAttribute(name = "max-priority")
+    public void setMaxPriority(final Integer maxPriority) {
+        this.maxPriority = maxPriority;
+    }
+}

Added: projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadPoolExecutorMetaData.java
===================================================================
--- projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadPoolExecutorMetaData.java	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadPoolExecutorMetaData.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,114 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads.metadata;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ *
+ */
+ at XmlType(name = "thread-pool-executor")
+public final class ThreadPoolExecutorMetaData {
+    private String name;
+    private String threadFactory;
+    private PoolSizeMetaData corePoolSize;
+    private PoolSizeMetaData maxPoolSize;
+    private TimeMetaData keepAliveTime;
+    private RejectPolicyMetaData rejectPolicyMetaData;
+    private Integer queueLength;
+    private boolean allowCoreTimeout;
+
+    public String getName() {
+        return name;
+    }
+
+    @XmlAttribute(required = true)
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public String getThreadFactory() {
+        return threadFactory;
+    }
+
+    @XmlAttribute(name = "thread-factory", required = true)
+    public void setThreadFactory(final String threadFactory) {
+        this.threadFactory = threadFactory;
+    }
+
+    public PoolSizeMetaData getCorePoolSize() {
+        return corePoolSize;
+    }
+
+    @XmlElement(name = "core-pool-size")
+    public void setCorePoolSize(final PoolSizeMetaData corePoolSize) {
+        this.corePoolSize = corePoolSize;
+    }
+
+    public PoolSizeMetaData getMaxPoolSize() {
+        return maxPoolSize;
+    }
+
+    @XmlElement(name = "max-pool-size")
+    public void setMaxPoolSize(final PoolSizeMetaData maxPoolSize) {
+        this.maxPoolSize = maxPoolSize;
+    }
+
+    public TimeMetaData getKeepAliveTime() {
+        return keepAliveTime;
+    }
+
+    @XmlElement(name = "keepalive-time")
+    public void setKeepAliveTime(final TimeMetaData keepAliveTime) {
+        this.keepAliveTime = keepAliveTime;
+    }
+
+    public RejectPolicyMetaData getRejectPolicyMetaData() {
+        return rejectPolicyMetaData;
+    }
+
+    @XmlElement(name = "reject-policy")
+    public void setRejectPolicyMetaData(final RejectPolicyMetaData rejectPolicyMetaData) {
+        this.rejectPolicyMetaData = rejectPolicyMetaData;
+    }
+
+    public Integer getQueueLength() {
+        return queueLength;
+    }
+
+    @XmlAttribute(name = "queue-length")
+    public void setQueueLength(final Integer queueLength) {
+        this.queueLength = queueLength;
+    }
+
+    public boolean isAllowCoreTimeout() {
+        return allowCoreTimeout;
+    }
+
+    @XmlAttribute(name = "allow-core-timeout")
+    public void setAllowCoreTimeout(final boolean allowCoreTimeout) {
+        this.allowCoreTimeout = allowCoreTimeout;
+    }
+}

Added: projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadsMetaData.java
===================================================================
--- projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadsMetaData.java	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/ThreadsMetaData.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,383 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads.metadata;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Collections;
+import java.util.Queue;
+import java.util.LinkedList;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ArrayBlockingQueue;
+import org.jboss.xb.annotations.JBossXmlSchema;
+import org.jboss.beans.metadata.spi.BeanMetaData;
+import org.jboss.beans.metadata.spi.ValueMetaData;
+import org.jboss.beans.metadata.spi.BeanMetaDataFactory;
+import org.jboss.beans.metadata.spi.builder.BeanMetaDataBuilder;
+import org.jboss.threads.JBossThreadFactory;
+import org.jboss.threads.InterruptHandler;
+import org.jboss.threads.SimpleQueueExecutor;
+import org.jboss.threads.JBossExecutors;
+import org.jboss.threads.RejectionPolicy;
+import org.jboss.threads.ArrayQueue;
+import org.jboss.threads.JBossThreadPoolExecutor;
+import org.jboss.threads.DirectExecutor;
+import org.jboss.dependency.spi.ControllerMode;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlNsForm;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlTransient;
+
+/**
+ *
+ */
+ at JBossXmlSchema(namespace = "urn:jboss:threads:1.0", elementFormDefault = XmlNsForm.QUALIFIED)
+ at XmlRootElement(name = "threads")
+ at XmlType(name = "threads")
+public final class ThreadsMetaData implements BeanMetaDataFactory {
+    private static final class StringEntry implements Map.Entry<String, String> {
+        private final String key;
+        private final String value;
+
+        private StringEntry(final String key, final String value) {
+            this.key = key;
+            this.value = value;
+        }
+
+        public String getKey() {
+            return key;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public String setValue(final String value) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private static StringEntry entry(final String key, final String value) {
+        return new StringEntry(key, value);
+    }
+
+    private static Map<String, String> stringMap(StringEntry... entries) {
+        final HashMap<String, String> hashMap = new HashMap<String, String>(entries.length);
+        for (Map.Entry<String, String> e : entries) {
+            hashMap.put(e.getKey(), e.getValue());
+        }
+        return Collections.unmodifiableMap(hashMap);
+    }
+
+    private static final Map<String, String> UNIT_NICK_NAMES = stringMap(
+            entry("S", "SECONDS"),
+            entry("SEC", "SECONDS"),
+            entry("M", "MINUTES"),
+            entry("MIN", "MINUTES"),
+            entry("MS", "MILLISECONDS"),
+            entry("NS", "NANOSECONDS"),
+            entry("H", "HOURS"),
+            entry("D", "DAYS"),
+            entry("MON", "MONTHS"),
+            entry("W", "WEEKS")
+    );
+
+    private List<ThreadGroupMetaData> threadGroups = new ArrayList<ThreadGroupMetaData>();
+    private List<ThreadFactoryMetaData> threadFactories = new ArrayList<ThreadFactoryMetaData>();
+    private List<ThreadPoolExecutorMetaData> threadPoolExecutors = new ArrayList<ThreadPoolExecutorMetaData>();
+    private List<DirectExecutorMetaData> directExecutors = new ArrayList<DirectExecutorMetaData>();
+    private List<NotatingExecutorMetaData> notatingExecutors = new ArrayList<NotatingExecutorMetaData>();
+
+    public List<ThreadGroupMetaData> getThreadGroups() {
+        return threadGroups;
+    }
+
+    @XmlElement(name = "thread-group")
+    public void setThreadGroups(final List<ThreadGroupMetaData> threadGroups) {
+        this.threadGroups = threadGroups;
+    }
+
+    public List<ThreadFactoryMetaData> getThreadFactories() {
+        return threadFactories;
+    }
+
+    @XmlElement(name = "thread-factory")
+    public void setThreadFactories(final List<ThreadFactoryMetaData> threadFactories) {
+        this.threadFactories = threadFactories;
+    }
+
+    public List<ThreadPoolExecutorMetaData> getThreadPoolExecutors() {
+        return threadPoolExecutors;
+    }
+
+    @XmlElement(name = "thread-pool-executor")
+    public void setThreadPoolExecutors(final List<ThreadPoolExecutorMetaData> threadPoolExecutors) {
+        this.threadPoolExecutors = threadPoolExecutors;
+    }
+
+    public List<DirectExecutorMetaData> getDirectExecutors() {
+        return directExecutors;
+    }
+
+    @XmlElement(name = "direct-executor")
+    public void setDirectExecutors(final List<DirectExecutorMetaData> directExecutors) {
+        this.directExecutors = directExecutors;
+    }
+
+    public List<NotatingExecutorMetaData> getNotatingExecutors() {
+        return notatingExecutors;
+    }
+
+    @XmlElement(name = "notating-executor")
+    public void setNotatingExecutors(final List<NotatingExecutorMetaData> notatingExecutors) {
+        this.notatingExecutors = notatingExecutors;
+    }
+
+    @XmlTransient
+    public List<BeanMetaData> getBeans() {
+        List<BeanMetaData> beanMetaDataList = new ArrayList<BeanMetaData>();
+        for (ThreadGroupMetaData metaData : threadGroups) {
+            final String name = metaData.getName();
+            final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(name, ThreadGroup.class.getName());
+            builder.setMode(ControllerMode.ON_DEMAND);
+            final String parent = metaData.getParent();
+            if (parent != null && parent.length() > 0) {
+                builder.addConstructorParameter(ThreadGroup.class.getName(), builder.createInject(parent));
+            }
+            builder.addConstructorParameter(String.class.getName(), builder.createValue(name));
+            if (metaData.isDaemon() != null) {
+                builder.addPropertyMetaData("daemon", builder.createValue(metaData.isDaemon()));
+            }
+            final Integer maxPriorityMeta = metaData.getMaxPriority();
+            if (maxPriorityMeta != null) {
+                builder.addPropertyMetaData("maxPriority", builder.createValue(maxPriorityMeta));
+            }
+            builder.ignoreStop();
+            beanMetaDataList.add(builder.getBeanMetaData());
+        }
+        for (ThreadFactoryMetaData metaData : threadFactories) {
+            final String name = metaData.getName();
+            final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(name, JBossThreadFactory.class.getName());
+            builder.setMode(ControllerMode.ON_DEMAND);
+            final String group = metaData.getGroup();
+            builder.addConstructorParameter(ThreadGroup.class.getName(), group == null ? builder.createNull() : builder.createInject(group));
+            final Boolean daemon = metaData.getDaemon();
+            builder.addConstructorParameter(Boolean.class.getName(), daemon == null ? builder.createNull() : builder.createValue(daemon));
+            final Integer priorityMeta = metaData.getInitialPriority();
+            final Integer actualPriorityMeta;
+            if (priorityMeta != null) {
+                actualPriorityMeta = priorityMeta;
+            } else {
+                actualPriorityMeta = null;
+            }
+            builder.addConstructorParameter(Integer.class.getName(), actualPriorityMeta == null ? builder.createNull() : builder.createValue(actualPriorityMeta));
+            builder.addConstructorParameter(String.class.getName(), builder.createValue(metaData.getThreadNamePattern()));
+            final List<ValueMetaData> interruptHandlers = builder.createArray(InterruptHandler[].class.getName(), InterruptHandler.class.getName());
+            for (InterruptHandlerRefMetaData ihmd : metaData.getInterruptHandlers()) {
+                interruptHandlers.add(builder.createInject(ihmd.getName()));
+            }
+            builder.addConstructorParameter(InterruptHandler[].class.getName(), (ValueMetaData) interruptHandlers);
+            final ExceptionHandlerRefMetaData ehmd = metaData.getExceptionHandler();
+            builder.addConstructorParameter(Thread.UncaughtExceptionHandler.class.getName(), ehmd == null ? builder.createNull() : builder.createInject(ehmd.getName()));
+            final Long stackSize = metaData.getStackSize();
+            builder.addConstructorParameter(Long.class.getName(), stackSize == null ? builder.createNull() : builder.createValue(stackSize));
+            beanMetaDataList.add(builder.getBeanMetaData());
+        }
+        for (ThreadPoolExecutorMetaData metaData : threadPoolExecutors) {
+            final String name = metaData.getName();
+            final PoolSizeMetaData corePoolSizeMetaData = metaData.getCorePoolSize();
+            final int corePoolSize;
+            if (corePoolSizeMetaData == null) {
+                corePoolSize = 0;
+            } else {
+                corePoolSize = Math.max(calcPoolSize(corePoolSizeMetaData), 0);
+            }
+            final PoolSizeMetaData maxPoolSizeMetaData = metaData.getMaxPoolSize();
+            final int maxPoolSize;
+            if (maxPoolSizeMetaData == null) {
+                maxPoolSize = corePoolSize;
+            } else {
+                maxPoolSize = Math.max(calcPoolSize(maxPoolSizeMetaData), corePoolSize < 1 ? 1 : corePoolSize);
+            }
+            final TimeMetaData timeMetaData = metaData.getKeepAliveTime();
+            final long time;
+            final TimeUnit unit;
+            if (timeMetaData == null) {
+                time = Long.MAX_VALUE;
+                unit = TimeUnit.NANOSECONDS;
+            } else {
+                time = Math.max(0L, timeMetaData.getTime());
+                final String unitName = timeMetaData.getUnit();
+
+                if (unitName == null) {
+                    unit = TimeUnit.MILLISECONDS;
+                } else {
+                    final String upperUnitName = unitName.toUpperCase();
+                    if (UNIT_NICK_NAMES.containsKey(upperUnitName)) {
+                        unit = TimeUnit.valueOf(UNIT_NICK_NAMES.get(upperUnitName));
+                    } else {
+                        unit = TimeUnit.valueOf(upperUnitName);
+                    }
+                }
+            }
+            final String threadFactory = metaData.getThreadFactory();
+            final Integer queueLength = metaData.getQueueLength();
+            final RejectPolicyMetaData rejectPolicyMetaData = metaData.getRejectPolicyMetaData();
+            final String policyName = rejectPolicyMetaData == null ? "block" : rejectPolicyMetaData.getName();
+            final BeanMetaDataBuilder executorBuilder;
+            // here is where we decide which thread pool implementation to use
+            // right now, our criteria is simple - if blocking is desired, use the queue executor instead
+            if ("block".equals(policyName)) {
+                // use SimpleQueueExecutor
+                executorBuilder = BeanMetaDataBuilder.createBuilder(SimpleQueueExecutor.class.getName());
+                final RejectionPolicy rejectionPolicy;
+                final ValueMetaData handoffExecutorValue;
+                if ("abort".equals(policyName)) {
+                    rejectionPolicy = RejectionPolicy.ABORT;
+                    handoffExecutorValue = executorBuilder.createNull();
+                } else if ("block".equals(policyName)) {
+                    rejectionPolicy = RejectionPolicy.BLOCK;
+                    handoffExecutorValue = executorBuilder.createNull();
+                } else if ("caller-runs".equals(policyName)) {
+                    rejectionPolicy = RejectionPolicy.HANDOFF;
+                    handoffExecutorValue = executorBuilder.createValue(JBossExecutors.directExecutor());
+                } else if ("discard".equals(policyName)) {
+                    rejectionPolicy = RejectionPolicy.DISCARD;
+                    handoffExecutorValue = executorBuilder.createNull();
+                } else if ("discard-oldest".equals(policyName)) {
+                    rejectionPolicy = RejectionPolicy.DISCARD_OLDEST;
+                    handoffExecutorValue = executorBuilder.createNull();
+                } else if ("handoff".equals(policyName)) {
+                    rejectionPolicy = RejectionPolicy.HANDOFF;
+                    handoffExecutorValue = executorBuilder.createInject(rejectPolicyMetaData.getExecutorName());
+                } else {
+                    throw new IllegalStateException();
+                }
+                final Queue<Runnable> queue;
+                if (queueLength == null) {
+                    queue = new LinkedList<Runnable>();
+                } else {
+                    queue = new ArrayQueue<Runnable>(queueLength.intValue());
+                }
+                executorBuilder.addConstructorParameter("int", Integer.valueOf(corePoolSize));
+                executorBuilder.addConstructorParameter("int", Integer.valueOf(maxPoolSize));
+                executorBuilder.addConstructorParameter("long", Long.valueOf(time));
+                executorBuilder.addConstructorParameter(TimeUnit.class.getName(), unit);
+                executorBuilder.addConstructorParameter(Queue.class.getName(), executorBuilder.createValue(queue));
+                executorBuilder.addConstructorParameter(ThreadFactory.class.getName(), executorBuilder.createInject(threadFactory));
+                executorBuilder.addConstructorParameter(RejectionPolicy.class.getName(), rejectionPolicy);
+                executorBuilder.addConstructorParameter(Executor.class.getName(), handoffExecutorValue);
+                if (metaData.isAllowCoreTimeout()) {
+                    executorBuilder.addPropertyMetaData("allowCoreTimeout", Boolean.TRUE);
+                }
+            } else {
+                // use ThreadPoolExecutor
+                executorBuilder = BeanMetaDataBuilder.createBuilder(JBossThreadPoolExecutor.class.getName());
+                final ValueMetaData policyValue;
+                if ("abort".equals(policyName)) {
+                    policyValue = executorBuilder.createValue(JBossExecutors.abortPolicy());
+                } else if ("block".equals(policyName)) {
+                    throw new IllegalStateException();
+                } else if ("caller-runs".equals(policyName)) {
+                    policyValue = executorBuilder.createValue(JBossExecutors.callerRunsPolicy());
+                } else if ("discard".equals(policyName)) {
+                    policyValue = executorBuilder.createValue(JBossExecutors.discardPolicy());
+                } else if ("discard-oldest".equals(policyName)) {
+                    policyValue = executorBuilder.createValue(JBossExecutors.discardOldestPolicy());
+                } else if ("handoff".equals(policyName)) {
+                    final BeanMetaDataBuilder policyBuilder = BeanMetaDataBuilder.createBuilder(RejectedExecutionHandler.class.getName());
+                    policyBuilder.setFactoryClass(JBossExecutors.class.getName());
+                    policyBuilder.setFactoryMethod("handoffPolicy");
+                    policyBuilder.addConstructorParameter(Executor.class.getName(), policyBuilder.createInject(rejectPolicyMetaData.getExecutorName()));
+                    policyValue = policyBuilder.getBeanMetaData();
+                } else {
+                    throw new IllegalStateException();
+                }
+                final BlockingQueue<Runnable> queue;
+                if (queueLength == null) {
+                    // todo: try LinkedTransferQueue
+                    queue = new LinkedBlockingQueue<Runnable>();
+                } else {
+                    queue = new ArrayBlockingQueue<Runnable>(queueLength.intValue());
+                }
+                executorBuilder.addConstructorParameter("int", Integer.valueOf(corePoolSize));
+                executorBuilder.addConstructorParameter("int", Integer.valueOf(maxPoolSize));
+                executorBuilder.addConstructorParameter("long", Long.valueOf(time));
+                executorBuilder.addConstructorParameter(TimeUnit.class.getName(), unit);
+                executorBuilder.addConstructorParameter(BlockingQueue.class.getName(), executorBuilder.createValue(queue));
+                executorBuilder.addConstructorParameter(ThreadFactory.class.getName(), executorBuilder.createInject(threadFactory));
+                executorBuilder.addConstructorParameter(RejectedExecutionHandler.class.getName(), policyValue);
+            }
+            executorBuilder.setMode(ControllerMode.ON_DEMAND);
+//            final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(name, ExecutorService.class.getName());
+//            builder.setFactoryClass(JBossExecutors.class.getName());
+//            builder.setFactoryMethod("protectedExecutorService");
+//            builder.addConstructorParameter(Executor.class.getName(), executorBuilder.getBeanMetaData());
+//            builder.setMode(ControllerMode.ON_DEMAND);
+//            beanMetaDataList.add(builder.getBeanMetaData());
+            executorBuilder.setName(name);
+            beanMetaDataList.add(executorBuilder.getBeanMetaData());
+        }
+        for (DirectExecutorMetaData metaData : directExecutors) {
+            final String name = metaData.getName();
+            final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(name, ExecutorService.class.getName());
+            builder.setFactoryClass(JBossExecutors.class.getName());
+            builder.setFactoryMethod("directExecutorService");
+            builder.setMode(ControllerMode.ON_DEMAND);
+            beanMetaDataList.add(builder.getBeanMetaData());
+        }
+        for (NotatingExecutorMetaData metaData : notatingExecutors) {
+            final String name = metaData.getName();
+            final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(name, DirectExecutor.class.getName());
+            builder.setMode(ControllerMode.ON_DEMAND);
+            builder.setFactoryClass(JBossExecutors.class.getName());
+            builder.setFactoryMethod("notatingExecutor");
+            builder.addConstructorParameter(Executor.class.getName(), builder.createInject(metaData.getParent()));
+            builder.addConstructorParameter(String.class.getName(), metaData.getNote());
+            beanMetaDataList.add(builder.getBeanMetaData());
+        }
+        return beanMetaDataList;
+    }
+
+    private static int calcPoolSize(PoolSizeMetaData poolSizeMetaData) {
+        float count = poolSizeMetaData.getCount();
+        float perCpu = poolSizeMetaData.getPerCpu();
+        if (Float.isNaN(count) || Float.isInfinite(count) || count < 0.0f) {
+            count = 0.0f;
+        }
+        if (Float.isNaN(perCpu) || Float.isInfinite(perCpu) || perCpu < 0.0f) {
+            perCpu = 0.0f;
+        }
+        return Math.round(count + ((float) Runtime.getRuntime().availableProcessors()) * perCpu);
+    }
+}

Added: projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/TimeMetaData.java
===================================================================
--- projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/TimeMetaData.java	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/src/main/java/org/jboss/threads/metadata/TimeMetaData.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads.metadata;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ *
+ */
+ at XmlType(name = "time")
+public final class TimeMetaData {
+    private String unit;
+    private long time;
+
+    public String getUnit() {
+        return unit;
+    }
+
+    @XmlAttribute
+    public void setUnit(final String unit) {
+        this.unit = unit;
+    }
+
+    public long getTime() {
+        return time;
+    }
+
+    @XmlAttribute(required = true)
+    public void setTime(final long time) {
+        this.time = time;
+    }
+}

Added: projects/jboss-threads/trunk/jbossmc/src/main/resources/META-INF/jboss-beans.xml
===================================================================
--- projects/jboss-threads/trunk/jbossmc/src/main/resources/META-INF/jboss-beans.xml	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/src/main/resources/META-INF/jboss-beans.xml	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+    <bean name="JBossThreadsMetaDataFactoryDeployer" class="org.jboss.deployers.vfs.deployer.kernel.BeanMetaDataFactoryDeployer">
+        <constructor>
+            <parameter>org.jboss.threads.metadata.ThreadsMetaData</parameter>
+        </constructor>
+    </bean>
+
+    <bean name="JBossThreadsMetaDataSchemaResolverDeployer" class="org.jboss.deployers.vfs.spi.deployer.SchemaResolverDeployer">
+        <constructor>
+            <parameter>org.jboss.threads.metadata.ThreadsMetaData</parameter>
+        </constructor>
+        <property name="name">jboss-threads.xml</property>
+        <property name="registerWithJBossXB">true</property>
+    </bean>
+
+    <classloading xmlns="urn:jboss:classloading:1.0" version="1.0.0.CR1" import-all="false">
+        <requirements>
+            <module name="jboss-threads" from="1.0.0.CR1" from-inclusive="true"/>
+            <package name="org.jboss.deployers.vfs.deployer.kernel"/>
+            <package name="org.jboss.deployers.vfs.spi.deployer"/>
+        </requirements>
+    </classloading>
+</deployment>

Added: projects/jboss-threads/trunk/jbossmc/src/main/resources/schema/jboss-threads_1_0.xsd
===================================================================
--- projects/jboss-threads/trunk/jbossmc/src/main/resources/schema/jboss-threads_1_0.xsd	                        (rev 0)
+++ projects/jboss-threads/trunk/jbossmc/src/main/resources/schema/jboss-threads_1_0.xsd	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:xhtml="http://www.w3.org/1999/xhtml"
+            targetNamespace="urn:jboss:threads:1.0"
+            xmlns="urn:jboss:threads:1.0"
+            elementFormDefault="qualified"
+            attributeFormDefault="unqualified"
+            version="1.0">
+
+    <xsd:element name="threads" type="threads"/>
+
+    <xsd:complexType name="threads">
+        <xsd:annotation>
+            <xsd:documentation>
+                The root threads deployment element.  Specify thread groups, thread factories, and executors within.
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+            <xsd:choice>
+                <xsd:element name="thread-group" type="thread-group"/>
+                <xsd:element name="thread-factory" type="thread-factory"/>
+                <xsd:element name="thread-pool-executor" type="thread-pool-executor"/>
+                <xsd:element name="direct-executor" type="direct-executor"/>
+                <xsd:element name="notating-executor" type="notating-executor"/>
+            </xsd:choice>
+        </xsd:sequence>
+    </xsd:complexType>
+
+    <xsd:complexType name="thread-group">
+        <xsd:annotation>
+            <xsd:documentation>
+                A thread group that can be referenced by a bean name.  The "name" attribute is the
+                bean name of the created thread group, used for injection.  The "group-name" attribute is
+                the JDK name of the thread group.  The optional "daemon" attribute specifies whether
+                threads should be forced to be daemon threads, or forced to be non-daemon threads (not
+                specifying this attribute will cause the thread group to inherit the daemon status from
+                its parent).  The optional "max-priority" attribute can be used to limit the priority of
+                threads within the group.  The optional "parent" attribute specifies the parent thread
+                group (by bean name).
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:attribute name="name" type="xsd:string" use="required"/>
+        <xsd:attribute name="group-name" type="xsd:string" use="required"/>
+        <xsd:attribute name="daemon" type="xsd:boolean" use="optional"/>
+        <xsd:attribute name="max-priority" type="priority" use="optional"/>
+        <xsd:attribute name="parent" type="xsd:string" use="optional"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="thread-factory">
+        <xsd:annotation>
+            <xsd:documentation>
+                A thread factory (implementing java.util.concurrent.ThreadFactory).  The "name" attribute is
+                the bean name of the created thread factory.  The "group" attribute specifies the thread group to
+                be used for threads created by this factory.  The optional "daemon" attribute specifies whether
+                threads created by this factory should be forced to be daemon threads, or forced to be non-daemon
+                threads (not specifying this attribute will cause the thread group to inherit the daemon status from
+                its group).  The optional "initial-priority" attribute may be used to specify the thread priority of
+                created threads.
+
+                One nested "exception-handler" tag may be used to specify an uncaught exception handler for the
+                thread factory.  One or more "interrupt-handler" tags may be used to specify beans which need to be
+                notified when a thread from this factory has been interrupted.
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="exception-handler" type="exception-handler" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="interrupt-handler" type="interrupt-handler" minOccurs="0" maxOccurs="unbounded"/>
+        </xsd:sequence>
+
+        <xsd:attribute name="name" type="xsd:string" use="required"/>
+        <xsd:attribute name="group" type="xsd:string" use="required"/>
+        <xsd:attribute name="daemon" type="xsd:boolean" use="optional"/>
+        <xsd:attribute name="thread-name-pattern" type="xsd:string" use="optional"/>
+        <xsd:attribute name="initial-priority" type="priority" use="optional"/>
+    </xsd:complexType>
+
+    <xsd:simpleType name="priority">
+        <xsd:annotation>
+            <xsd:documentation>
+                A priority which can range from 1 to 10 (inclusive).  See <xhtml:a href="http://java.sun.com/javase/6/docs/api/java/lang/Thread.html#setPriority(int)">Thread.setPriority(int)</xhtml:a> for more information.
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:restriction base="xsd:integer">
+            <xsd:minInclusive value="1"/>
+            <xsd:maxInclusive value="10"/>
+        </xsd:restriction>
+    </xsd:simpleType>
+
+    <xsd:complexType name="thread-pool-executor">
+        <xsd:annotation>
+            <xsd:documentation>
+                A thread pool executor.  The "name" attribute is the bean name of the created executor.  The
+                "thread-factory" attribute specifies the bean name of the thread factory to use to create worker
+                threads.  The nested "core-pool-size" element may be used to specify the core thread pool size.
+                The nested "max-pool-size" element may be used to specify the maximum thread pool size.  The nested
+                "keepalive-time" is used to specify the amount of time that threads beyond the core pool size should
+                be kept running when idle.  One of the "unbounded-queue", "bounded-queue", or "direct-queue" nested
+                elements may be specified to control the type of queue to use for tasks.  The nested "reject-policy"
+                element may be used to specify how rejected tasks are handled.
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="core-pool-size" type="pool-size" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="max-pool-size" type="pool-size" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="keepalive-time" type="time" minOccurs="0" maxOccurs="1"/>
+            <xsd:element name="reject-policy" type="reject-policy" minOccurs="0" maxOccurs="1"/>
+        </xsd:sequence>
+        <xsd:attribute name="name" use="required" type="xsd:string"/>
+        <xsd:attribute name="thread-factory" use="required" type="xsd:string"/>
+        <xsd:attribute name="allow-core-timeout" use="optional" type="xsd:boolean"/>
+        <xsd:attribute name="queue-length" use="optional" type="xsd:integer"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="direct-executor">
+        <xsd:annotation>
+            <xsd:documentation>
+                An executor that executes tasks in the caller's thread.  The "name" attribute is the bean name of
+                the executor.
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:attribute name="name" type="xsd:string" use="required"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="notating-executor">
+        <xsd:annotation>
+            <xsd:documentation>
+                An executor which wraps another executor, and adds a notation to the name of a thread while that thread
+                is executing a task.  The "name" attribute is the bean name of the created executor.  The "parent"
+                attribute is the bean name of the executor to delegate tasks to.  The "note" element specifies the text
+                that is to be added to the thread name while it executes the task.
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:attribute name="name" type="xsd:string" use="required"/>
+        <xsd:attribute name="parent" type="xsd:string" use="required"/>
+        <xsd:attribute name="note" type="xsd:string" use="required"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="exception-handler">
+        <xsd:annotation>
+            <xsd:documentation>
+                A reference to an exception handler for a thread or executor.  The referenced bean should implement
+                java.lang.Thread.UncaughtExceptionHandler.
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:attribute name="name" type="xsd:string" use="required"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="interrupt-handler">
+        <xsd:attribute name="name" type="xsd:string" use="required"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="pool-size">
+        <xsd:annotation>
+            <xsd:documentation>
+                A thread pool size designation.  The "count" attribute specifies a flat number of threads.  The
+                "per-cpu" attribute specifies a number of threads per CPU.  The numbers are added and rounded off
+                to an integer number of threads.
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:attribute name="count" type="xsd:float" use="optional"/>
+        <xsd:attribute name="per-cpu" type="xsd:float" use="optional"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="time">
+        <xsd:annotation>
+            <xsd:documentation>
+                An amount of time.  Comprised of a time value and a unit value.
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:attribute name="time" type="xsd:integer" use="required"/>
+        <xsd:attribute name="unit" type="time-unit-name" use="required"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="reject-policy">
+        <xsd:annotation>
+            <xsd:documentation>
+                Specify a task rejection policy for a thread pool executor.  This is the action that is taken when
+                all threads are busy and the task queue is full for an executor.  The "name" attribute specifies which
+                reject policy to use.  The "executor-name" attribute is used to specify a handoff executor
+                for policies that involve passing the task to another executor, and is required when the reject policy
+                is set to "handoff".
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:attribute name="name" type="reject-policy-name" use="required"/>
+        <xsd:attribute name="executor-name" type="xsd:string" use="optional"/>
+    </xsd:complexType>
+
+    <xsd:simpleType name="reject-policy-name">
+        <xsd:annotation>
+            <xsd:documentation>
+                The name of the policy.  Possible values are "abort", "block", "caller-runs", "discard", "discard-oldest",
+                and "handoff".
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="abort">
+                <xsd:annotation>
+                    <xsd:documentation>
+                        <![CDATA[When a task cannot be accepted, a RejectedExecutionException is thrown.]]>
+                    </xsd:documentation>
+                </xsd:annotation>
+            </xsd:enumeration>
+            <xsd:enumeration value="block">
+                <xsd:annotation>
+                    <xsd:documentation>
+                        <![CDATA[Block until a task can be accepted.  If the thread is interrupted while waiting, a RejectedExecutionException is thrown.]]>
+                    </xsd:documentation>
+                </xsd:annotation>
+            </xsd:enumeration>
+            <xsd:enumeration value="caller-runs">
+                <xsd:annotation>
+                    <xsd:documentation>
+                        <![CDATA[When a task connot be accepted, the calling thread runs the task.]]>
+                    </xsd:documentation>
+                </xsd:annotation>
+            </xsd:enumeration>
+            <xsd:enumeration value="discard">
+                <xsd:annotation>
+                    <xsd:documentation>
+                        <![CDATA[When a task cannot be accepted, the task is discarded.]]>
+                    </xsd:documentation>
+                </xsd:annotation>
+            </xsd:enumeration>
+            <xsd:enumeration value="discard-oldest">
+                <xsd:annotation>
+                    <xsd:documentation>
+                        <![CDATA[When a task cannot be accepted, the task which has been in the queue for the longest is discarded to make room.]]>
+                    </xsd:documentation>
+                </xsd:annotation>
+            </xsd:enumeration>
+            <xsd:enumeration value="handoff">
+                <xsd:annotation>
+                    <xsd:documentation>
+                        <![CDATA[When a task cannot be accepted, the task is handed off to another Executor whose name is given in the executor-name attribute.]]>
+                    </xsd:documentation>
+                </xsd:annotation>
+            </xsd:enumeration>
+        </xsd:restriction>
+    </xsd:simpleType>
+
+    <xsd:simpleType name="time-unit-name">
+        <xsd:annotation>
+            <xsd:documentation>
+                The name of a unit of time.
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:restriction base="xsd:string">
+
+            <xsd:enumeration value="s"/>
+            <xsd:enumeration value="sec"/>
+            <xsd:enumeration value="seconds"/>
+
+            <xsd:enumeration value="m"/>
+            <xsd:enumeration value="min"/>
+            <xsd:enumeration value="minutes"/>
+
+            <xsd:enumeration value="ms"/>
+            <xsd:enumeration value="milliseconds"/>
+
+            <xsd:enumeration value="ns"/>
+            <xsd:enumeration value="nanoseconds"/>
+
+            <xsd:enumeration value="h"/>
+            <xsd:enumeration value="hours"/>
+
+            <xsd:enumeration value="d"/>
+            <xsd:enumeration value="days"/>
+
+            <xsd:enumeration value="w"/>
+            <xsd:enumeration value="weeks"/>
+
+            <xsd:enumeration value="mon"/>
+            <xsd:enumeration value="months"/>
+
+        </xsd:restriction>
+    </xsd:simpleType>
+
+</xsd:schema>
\ No newline at end of file

Added: projects/jboss-threads/trunk/main/pom.xml
===================================================================
--- projects/jboss-threads/trunk/main/pom.xml	                        (rev 0)
+++ projects/jboss-threads/trunk/main/pom.xml	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,33 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.jboss.threads</groupId>
+    <artifactId>threads</artifactId>
+    <packaging>jar</packaging>
+    <version>1.0.0.CR1</version>
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>3.8.1</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>2.0.2</version>
+                <configuration>
+                    <source>1.5</source>
+                    <target>1.5</target>
+                </configuration>
+            </plugin>
+        </plugins>
+        <finalName>jboss-threads</finalName>
+    </build>
+</project>

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ArrayQueue.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ArrayQueue.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ArrayQueue.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,137 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.util.AbstractQueue;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+/**
+ * A simple array-backed queue with a fixed size.
+ */
+public final class ArrayQueue<E> extends AbstractQueue<E> implements Queue<E> {
+    private final E[] elements;
+    // elements are added at head
+    private int head;
+    // elements are removed at tail
+    private int tail;
+    private int modCnt;
+
+    @SuppressWarnings({ "unchecked" })
+    public ArrayQueue(final int capacity) {
+        elements = (E[]) new Object[capacity];
+    }
+
+    public Iterator<E> iterator() {
+        return new Iterator<E>() {
+            private int pos = 0;
+            private int size = size();
+            private final int modIdx = modCnt;
+
+            public boolean hasNext() {
+                if (modCnt != modIdx) {
+                    throw new ConcurrentModificationException();
+                }
+                return pos < size;
+            }
+
+            public E next() {
+                if (modCnt != modIdx) {
+                    throw new ConcurrentModificationException();
+                }
+                final int pos = this.pos;
+                if (pos >= size) {
+                    throw new NoSuchElementException();
+                }
+                final E[] elements = ArrayQueue.this.elements;
+                final E value = elements[(tail + pos) % elements.length];
+                this.pos = pos + 1;
+                return value;
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    public boolean isEmpty() {
+        return elements[tail] == null;
+    }
+
+    public int size() {
+        final int head = this.head;
+        final int tail = this.tail;
+        final E[] elements = this.elements;
+        if (elements[tail] == null) {
+            return 0;
+        } else if (head > tail) {
+            return head - tail;
+        } else {
+            return head + elements.length - tail;
+        }
+    }
+
+    public boolean offer(final E e) {
+        if (e == null) {
+            throw new NullPointerException("e is null");
+        }
+        final int head = this.head;
+        final E[] elements = this.elements;
+        final int len = elements.length;
+        if (elements[head] != null) {
+            return false;
+        } else {
+            elements[head] = e;
+            this.head = (head + 1) % len;
+            modCnt++;
+            return true;
+        }
+    }
+
+    public E poll() {
+        final int tail = this.tail;
+        final E[] elements = this.elements;
+        final E value = elements[tail];
+        if (value != null) {
+            modCnt++;
+            elements[tail] = null;
+            this.tail = (tail + 1) % elements.length;
+        }
+        return value;
+    }
+
+    public E peek() {
+        final int tail = this.tail;
+        return tail == -1 ? null : elements[tail];
+    }
+
+    public void clear() {
+        Arrays.fill(elements, null);
+        modCnt++;
+        tail = head = 0;
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/DirectExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/DirectExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/DirectExecutor.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.util.concurrent.Executor;
+
+/**
+ * A direct executor.  Such an executor is required to run the given task in the current thread rather than
+ * delegate to a thread pool.
+ */
+public interface DirectExecutor extends Executor {
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/DirectExecutorService.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/DirectExecutorService.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/DirectExecutorService.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.util.concurrent.ExecutorService;
+
+/**
+ * A direct executor service.  Such an executor service is required to run the given task in the current thread rather than
+ * delegate to a thread pool.
+ */
+public interface DirectExecutorService extends DirectExecutor, ExecutorService {
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/InterruptHandler.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/InterruptHandler.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/InterruptHandler.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,37 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+/**
+ * A thread interrupt handler.  Called when a thread's {@code interrupt()} method is invoked.  The handler should
+ * not throw an exception; otherwise user code might end up in an unexpected state.
+ */
+public interface InterruptHandler {
+
+    /**
+     * Handle an interrupt condition on the given thread.  This method should not throw an exception.
+     *
+     * @param thread the thread which was interrupted
+     */
+    void handleInterrupt(Thread thread);
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossExecutors.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossExecutors.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossExecutors.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,358 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadFactory;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.security.AccessControlContext;
+
+/**
+ *
+ */
+public final class JBossExecutors {
+
+    private JBossExecutors() {}
+
+    private static final DirectExecutor DIRECT_EXECUTOR = new DirectExecutor() {
+        public void execute(final Runnable command) {
+            command.run();
+        }
+    };
+
+    private static final DirectExecutor REJECTING_EXECUTOR = new DirectExecutor() {
+        public void execute(final Runnable command) {
+            throw new RejectedExecutionException();
+        }
+    };
+
+    private static final DirectExecutor DISCARDING_EXECUTOR = new DirectExecutor() {
+        public void execute(final Runnable command) {
+            // nothing
+        }
+    };
+
+    private static final DirectExecutorService DIRECT_EXECUTOR_SERVICE = new ProtectedDirectExecutorService(DIRECT_EXECUTOR);
+    private static final DirectExecutorService REJECTING_EXECUTOR_SERVICE = new ProtectedDirectExecutorService(REJECTING_EXECUTOR);
+    private static final DirectExecutorService DISCARDING_EXECUTOR_SERVICE = new ProtectedDirectExecutorService(DISCARDING_EXECUTOR);
+
+    /**
+     * Get the direct executor.  This executor will immediately run any task it is given, and propagate back any
+     * run-time exceptions thrown.
+     *
+     * @return the direct executor instance
+     */
+    public static DirectExecutor directExecutor() {
+        return DIRECT_EXECUTOR;
+    }
+
+    /**
+     * Get the direct executor service.  This executor will immediately run any task it is given, and propagate back any
+     * run-time exceptions thrown.  It cannot be shut down.
+     *
+     * @return the direct executor service instance
+     */
+    public static DirectExecutorService directExecutorService() {
+        return DIRECT_EXECUTOR_SERVICE;
+    }
+
+    /**
+     * Get the rejecting executor.  This executor will reject any task submitted to it.
+     *
+     * @return the rejecting executor instance
+     */
+    public static DirectExecutor rejectingExecutor() {
+        return REJECTING_EXECUTOR;
+    }
+
+    /**
+     * Get the rejecting executor service.  This executor will reject any task submitted to it.  It cannot be shut down.
+     *
+     * @return the rejecting executor service instance
+     */
+    public static DirectExecutorService rejectingExecutorService() {
+        return REJECTING_EXECUTOR_SERVICE;
+    }
+
+    /**
+     * Get the discarding executor.  This executor will silently discard any task submitted to it.
+     *
+     * @return the discarding executor instance
+     */
+    public static DirectExecutor discardingExecutor() {
+        return DISCARDING_EXECUTOR;
+    }
+
+    /**
+     * Get the discarding executor service.  This executor will silently discard any task submitted to it.  It cannot
+     * be shut down.
+     *
+     * @return the discarding executor service instance
+     */
+    public static DirectExecutorService discardingExecutorService() {
+        return DISCARDING_EXECUTOR_SERVICE;
+    }
+
+    /**
+     * Get a task that runs the given task through the given direct executor.
+     *
+     * @param executor the executor to run the task through
+     * @param task the task to run
+     * @return an encapsulating task
+     */
+    public static Runnable executorTask(final DirectExecutor executor, final Runnable task) {
+        return new Runnable() {
+            public void run() {
+                executor.execute(task);
+            }
+        };
+    }
+
+    /**
+     * An executor which delegates to another executor, wrapping each task in a task wrapper.
+     *
+     * @param delegate the delegate executor
+     * @param taskWrapper the task wrapper
+     * @return a wrapping executor
+     */
+    public static Executor wrappingExecutor(final Executor delegate, final DirectExecutor taskWrapper) {
+        return new Executor() {
+            public void execute(final Runnable command) {
+                delegate.execute(executorTask(taskWrapper, command));
+            }
+        };
+    }
+
+    /**
+     * Create a direct executor which runs with the privileges given by the supplied {@code AccessControlContext} instance.
+     *
+     * @param delegate the executor to delegate to at the privileged level
+     * @param context the {@code AccessControlContext} to use
+     * @return the new direct executor
+     */
+    public static DirectExecutor privilegedExecutor(final DirectExecutor delegate, final AccessControlContext context) {
+        return new DirectExecutor() {
+            public void execute(final Runnable command) {
+                final SecurityManager sm = System.getSecurityManager();
+                if (sm != null) {
+                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                        public Void run() {
+                            delegate.execute(command);
+                            return null;
+                        }
+                    }, context);
+                } else {
+                    delegate.execute(command);
+                }
+            }
+        };
+    }
+
+    /**
+     * Create a direct executor which runs tasks with the given context class loader.
+     *
+     * @param delegate the executor to delegate to
+     * @param taskClassLoader the context class loader to use
+     * @return the new direct executor
+     */
+    public static DirectExecutor contextClassLoaderExecutor(final DirectExecutor delegate, final ClassLoader taskClassLoader) {
+        return new DirectExecutor() {
+            public void execute(final Runnable command) {
+                final Thread thr = Thread.currentThread();
+                ClassLoader old = thr.getContextClassLoader();
+                thr.setContextClassLoader(taskClassLoader);
+                try {
+                    delegate.execute(command);
+                } finally {
+                    thr.setContextClassLoader(old);
+                }
+            }
+        };
+    }
+
+    /**
+     * Create a direct executor which changes the thread name for the duration of a task.
+     *
+     * @param delegate the executor to delegate to
+     * @param newName the thread name to use
+     * @return the new direct executor
+     */
+    public static DirectExecutor threadNameExecutor(final DirectExecutor delegate, final String newName) {
+        return new DirectExecutor() {
+            public void execute(final Runnable command) {
+                final Thread thr = Thread.currentThread();
+                final String oldName = thr.getName();
+                thr.setName(newName);
+                try {
+                    delegate.execute(command);
+                } finally {
+                    thr.setName(oldName);
+                }
+            }
+        };
+    }
+
+    /**
+     * Create a direct executor which adds a note to the thread name for the duration of a task.
+     *
+     * @param delegate the executor to delegate to
+     * @param notation the note to use
+     * @return the new direct executor
+     */
+    public static DirectExecutor threadNameNotateExecutor(final DirectExecutor delegate, final String notation) {
+        return new DirectExecutor() {
+            public void execute(final Runnable command) {
+                final Thread thr = Thread.currentThread();
+                final String oldName;
+                oldName = thr.getName();
+                thr.setName(oldName + " (" + notation + ')');
+                try {
+                    delegate.execute(command);
+                } finally {
+                    thr.setName(oldName);
+                }
+            }
+        };
+    }
+
+    /**
+     * Create a direct executor which consumes and logs errors that are thrown.
+     *
+     * @param delegate the executor to delegate to
+     * @param log the logger to which exceptions are written at the {@code error} level
+     * @return the new direct executor
+     */
+    public static DirectExecutor exceptionLoggingExecutor(final DirectExecutor delegate, final Object log) {
+        return new DirectExecutor() {
+            public void execute(final Runnable command) {
+                try {
+                    delegate.execute(command);
+                } catch (Throwable t) {
+                    // todo log it
+                    // log.error(t, "Exception thrown from thread task");
+                }
+            }
+        };
+    }
+
+    /**
+     * Create an executor that executes each task in a new thread.
+     *
+     * @param factory the thread factory to use
+     * @return the executor
+     */
+    public static Executor threadFactoryExecutor(final ThreadFactory factory) {
+        return new Executor() {
+            public void execute(final Runnable command) {
+                factory.newThread(command).start();
+            }
+        };
+    }
+
+    private static final RejectedExecutionHandler ABORT_POLICY = new ThreadPoolExecutor.AbortPolicy();
+    private static final RejectedExecutionHandler CALLER_RUNS_POLICY = new ThreadPoolExecutor.CallerRunsPolicy();
+    private static final RejectedExecutionHandler DISCARD_OLDEST_POLICY = new ThreadPoolExecutor.DiscardOldestPolicy();
+    private static final RejectedExecutionHandler DISCARD_POLICY = new ThreadPoolExecutor.DiscardPolicy();
+
+    /**
+     * Get the abort policy for a {@link java.util.concurrent.ThreadPoolExecutor}.
+     *
+     * @return the abort policy
+     * @see java.util.concurrent.ThreadPoolExecutor.AbortPolicy
+     */
+    public static RejectedExecutionHandler abortPolicy() {
+        return ABORT_POLICY;
+    }
+
+    /**
+     * Get the caller-runs policy for a {@link java.util.concurrent.ThreadPoolExecutor}.
+     *
+     * @return the caller-runs policy
+     * @see java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy
+     */
+    public static RejectedExecutionHandler callerRunsPolicy() {
+        return CALLER_RUNS_POLICY;
+    }
+
+    /**
+     * Get the discard-oldest policy for a {@link java.util.concurrent.ThreadPoolExecutor}.
+     *
+     * @return the discard-oldest policy
+     * @see java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy
+     */
+    public static RejectedExecutionHandler discardOldestPolicy() {
+        return DISCARD_OLDEST_POLICY;
+    }
+
+    /**
+     * Get the discard policy for a {@link java.util.concurrent.ThreadPoolExecutor}.
+     *
+     * @return the discard policy
+     * @see java.util.concurrent.ThreadPoolExecutor.DiscardPolicy
+     */
+    public static RejectedExecutionHandler discardPolicy() {
+        return DISCARD_POLICY;
+    }
+
+    /**
+     * Get a handoff policy for a {@link java.util.concurrent.ThreadPoolExecutor}.  The returned instance will
+     * delegate to another executor in the event that the task is rejected.
+     *
+     * @param target the target executor
+     * @return the new handoff policy implementation
+     */
+    public static RejectedExecutionHandler handoffPolicy(final Executor target) {
+        return new RejectedExecutionHandler() {
+            public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) {
+                target.execute(r);
+            }
+        };
+    }
+
+    /**
+     * Wrap an executor with an {@code ExecutorService} instance, which supports all the features of {@code ExecutorService}
+     * except for shutting down the executor.
+     *
+     * @param target the target executor
+     * @return the executor service
+     */
+    public static ExecutorService protectedExecutorService(final Executor target) {
+        return new ProtectedExecutorService(target);
+    }
+
+    /**
+     * Wrap a direct executor with an {@code DirectExecutorService} instance, which supports all the features of {@code ExecutorService}
+     * except for shutting down the executor.
+     *
+     * @param target the target executor
+     * @return the executor service
+     */
+    public static DirectExecutorService protectedDirectExecutorService(final DirectExecutor target) {
+        return new ProtectedDirectExecutorService(target);
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThread.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThread.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThread.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+/**
+ *
+ */
+public final class JBossThread extends Thread {
+    private final InterruptHandler[] interruptHandlers;
+
+    public JBossThread(final InterruptHandler[] handlers, final ThreadGroup group, final Runnable target, final String name, final long stackSize) {
+        super(group, target, name, stackSize);
+        interruptHandlers = handlers;
+    }
+
+    public JBossThread(final InterruptHandler[] handlers, final ThreadGroup group, final Runnable target, final String name) {
+        super(group, target, name);
+        interruptHandlers = handlers;
+    }
+
+    public void interrupt() {
+        try {
+            super.interrupt();
+        } finally {
+            if (interruptHandlers != null) {
+                for (InterruptHandler interruptHandler : interruptHandlers) try {
+                    interruptHandler.handleInterrupt(this);
+                } catch (Throwable t) {
+                    // must ignore
+                }
+            }
+        }
+    }
+
+    public void run() {
+        // todo log start
+        try {
+            super.run();
+        } finally {
+            // todo log end
+        }
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThreadFactory.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThreadFactory.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThreadFactory.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,215 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ *
+ */
+public final class JBossThreadFactory implements ThreadFactory {
+    private final ThreadGroup threadGroup;
+    private final Boolean daemon;
+    private final Integer initialPriority;
+    private final List<Appender> nameAppenderList;
+    private final InterruptHandler[] interruptHandlers;
+    private final Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
+    private final Long stackSize;
+
+    private final AtomicLong factoryThreadIndexSequence = new AtomicLong(1L);
+
+    private final long factoryIndex;
+
+    private static final AtomicLong globalThreadIndexSequence = new AtomicLong(1L);
+    private static final AtomicLong factoryIndexSequence = new AtomicLong(1L);
+
+    private static final Appender globalThreadIndexAppender = new Appender() {
+        public void appendTo(final StringBuilder target, final ThreadSequenceInfo info) {
+            target.append(info.getGlobalThreadNum());
+        }
+    };
+    private static final Appender factoryIndexAppender = new Appender() {
+        public void appendTo(final StringBuilder target, final ThreadSequenceInfo info) {
+            target.append(info.getFactoryNum());
+        }
+    };
+    private static final Appender perFactoryThreadIndexAppender = new Appender() {
+        public void appendTo(final StringBuilder target, final ThreadSequenceInfo info) {
+            target.append(info.getPerFactoryThreadNum());
+        }
+    };
+    private static final Appender percentAppender = new Appender() {
+        public void appendTo(final StringBuilder target, final ThreadSequenceInfo info) {
+            target.append('%');
+        }
+    };
+    private final Appender groupPathAppender;
+
+    private static void appendParent(ThreadGroup group, StringBuilder builder) {
+        final ThreadGroup parent = group.getParent();
+        if (parent != null) {
+            appendParent(parent, builder);
+            builder.append(':');
+        }
+        builder.append(group.getName());
+    }
+
+    public JBossThreadFactory(ThreadGroup threadGroup, final Boolean daemon, final Integer initialPriority, String namePattern, final InterruptHandler[] interruptHandlers, final Thread.UncaughtExceptionHandler uncaughtExceptionHandler, final Long stackSize) {
+        if (threadGroup == null) {
+            final SecurityManager sm = System.getSecurityManager();
+            threadGroup = sm != null ? sm.getThreadGroup() : Thread.currentThread().getThreadGroup();
+        }
+        this.threadGroup = threadGroup;
+        this.daemon = daemon;
+        this.initialPriority = initialPriority;
+        this.uncaughtExceptionHandler = uncaughtExceptionHandler;
+        this.interruptHandlers = interruptHandlers;
+        this.stackSize = stackSize;
+        final StringBuilder builder = new StringBuilder();
+        appendParent(threadGroup, builder);
+        final String groupPath = builder.toString();
+        groupPathAppender = new StringAppender(groupPath);
+
+        factoryIndex = factoryIndexSequence.getAndIncrement();
+        if (namePattern == null) {
+            namePattern = "pool-%f-thread-%t";
+        }
+        List<Appender> appenders = new ArrayList<Appender>();
+        final int len = namePattern.length();
+        for (int i = 0;; ) {
+            final int n = namePattern.indexOf('%', i);
+            if (n == -1) {
+                if (i < len) {
+                    appenders.add(new StringAppender(namePattern.substring(i)));
+                }
+                break;
+            }
+            if (n > i) {
+                appenders.add(new StringAppender(namePattern.substring(i, n)));
+            }
+            if (n >= len - 1) {
+                break;
+            }
+            final char c = namePattern.charAt(n + 1);
+            switch (c) {
+                case 't': {
+                    appenders.add(perFactoryThreadIndexAppender);
+                    break;
+                }
+                case 'g': {
+                    appenders.add(globalThreadIndexAppender);
+                    break;
+                }
+                case 'f': {
+                    appenders.add(factoryIndexAppender);
+                    break;
+                }
+                case 'p': {
+                    appenders.add(groupPathAppender);
+                    break;
+                }
+                case '%': {
+                    appenders.add(percentAppender);
+                    break;
+                }
+            }
+            i = n + 2;
+        }
+        nameAppenderList = appenders;
+    }
+
+    public Thread newThread(final Runnable target) {
+        return AccessController.doPrivileged(new ThreadCreateAction(target));
+    }
+
+    private final class ThreadCreateAction implements PrivilegedAction<Thread> {
+        private final Runnable target;
+
+        private ThreadCreateAction(final Runnable target) {
+            this.target = target;
+        }
+
+        public Thread run() {
+            final JBossThread thread;
+            final ThreadSequenceInfo info = new ThreadSequenceInfo(globalThreadIndexSequence.getAndIncrement(), factoryThreadIndexSequence.getAndIncrement(), factoryIndex);
+            final StringBuilder nameBuilder = new StringBuilder();
+            for (Appender appender : nameAppenderList) {
+                appender.appendTo(nameBuilder, info);
+            }
+            if (stackSize != null) {
+                thread = new JBossThread(interruptHandlers, threadGroup, target, nameBuilder.toString(), stackSize.longValue());
+            } else {
+                thread = new JBossThread(interruptHandlers, threadGroup, target, nameBuilder.toString());
+            }
+            if (initialPriority != null) thread.setPriority(initialPriority.intValue());
+            if (daemon != null) thread.setDaemon(daemon.booleanValue());
+            if (uncaughtExceptionHandler != null) thread.setUncaughtExceptionHandler(uncaughtExceptionHandler);
+            return thread;
+        }
+    }
+
+    private static final class StringAppender implements Appender {
+        private final String string;
+
+        private StringAppender(final String string) {
+            this.string = string;
+        }
+
+        public void appendTo(final StringBuilder target, final ThreadSequenceInfo info) {
+            target.append(string);
+        }
+    }
+
+    private static final class ThreadSequenceInfo {
+        private final long globalThreadNum;
+        private final long perFactoryThreadNum;
+        private final long factoryNum;
+
+        private ThreadSequenceInfo(final long globalThreadNum, final long perFactoryThreadNum, final long factoryNum) {
+            this.globalThreadNum = globalThreadNum;
+            this.perFactoryThreadNum = perFactoryThreadNum;
+            this.factoryNum = factoryNum;
+        }
+
+        public long getGlobalThreadNum() {
+            return globalThreadNum;
+        }
+
+        public long getPerFactoryThreadNum() {
+            return perFactoryThreadNum;
+        }
+
+        public long getFactoryNum() {
+            return factoryNum;
+        }
+    }
+
+    private interface Appender {
+        void appendTo(StringBuilder target, ThreadSequenceInfo info);
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThreadPoolExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThreadPoolExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThreadPoolExecutor.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,74 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.RejectedExecutionHandler;
+
+/**
+ *
+ */
+public final class JBossThreadPoolExecutor extends ThreadPoolExecutor {
+
+    public JBossThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
+        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
+    }
+
+    public JBossThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
+        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
+    }
+
+    public JBossThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
+        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
+    }
+
+    public JBossThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
+        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
+    }
+
+    public void stop() {
+        shutdown();
+        try {
+            awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
+            // todo log if fails?
+        } catch (InterruptedException e) {
+            // todo log it?
+            Thread.currentThread().interrupt();
+        }
+    }
+
+    public void destroy() {
+        // todo is this the right behavior?
+        shutdownNow();
+        try {
+            awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
+            // todo log if fails?
+        } catch (InterruptedException e) {
+            // todo log it?
+            Thread.currentThread().interrupt();
+        }
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/OrderedExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/OrderedExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/OrderedExecutor.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,183 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.Condition;
+
+/**
+ * An executor that always runs all tasks in queue order, using a delegate executor to run the tasks.
+ * <p/>
+ * More specifically, if a FIFO queue type is used, any call B to the {@link #execute(Runnable)} method that
+ * happens-after another call A to the same method, will result in B's task running after A's.
+ */
+public final class OrderedExecutor implements Executor {
+
+    private final Executor parent;
+    private final Runnable runner = new Runner();
+    private final Lock lock = new ReentrantLock();
+    private final Condition removeCondition = lock.newCondition();
+    // @protectedby lock
+    private final Queue<Runnable> queue;
+    // @protectedby lock
+    private boolean running;
+    // @protectedby lock
+    private RejectionPolicy policy;
+    // @protectedby lock
+    private Executor handoffExecutor;
+
+    /**
+     * Construct a new instance using an unbounded FIFO queue.  Since the queue is unbounded, tasks are never
+     * rejected.
+     *
+     * @param parent the parent to delegate tasks to
+     */
+    public OrderedExecutor(final Executor parent) {
+        this(parent, RejectionPolicy.BLOCK, null);
+    }
+
+    /**
+     * Construct a new instance using the given queue and a blocking reject policy.
+     *
+     * @param parent the parent to delegate tasks to
+     * @param queue the queue to use to hold tasks
+     */
+    public OrderedExecutor(final Executor parent, final Queue<Runnable> queue) {
+        this(parent, queue, RejectionPolicy.BLOCK, null);
+    }
+
+    /**
+     * Construct a new instance using an unbounded FIFO queue.
+     *
+     * @param parent the parent executor
+     * @param policy the task rejection policy
+     * @param handoffExecutor the executor to hand tasks to if the queue is full
+     */
+    public OrderedExecutor(final Executor parent, final RejectionPolicy policy, final Executor handoffExecutor) {
+        this(parent, new LinkedList<Runnable>(), policy, handoffExecutor);
+    }
+
+    /**
+     * Construct a new instance.
+     *
+     * @param parent the parent executor
+     * @param queue the task queue to use
+     * @param policy the task rejection policy
+     * @param handoffExecutor the executor to hand tasks to if the queue is full
+     */
+    public OrderedExecutor(final Executor parent, final Queue<Runnable> queue, final RejectionPolicy policy, final Executor handoffExecutor) {
+        if (parent == null) {
+            throw new NullPointerException("parent is null");
+        }
+        if (queue == null) {
+            throw new NullPointerException("queue is null");
+        }
+        if (policy == null) {
+            throw new NullPointerException("policy is null");
+        }
+        if (policy == RejectionPolicy.HANDOFF && handoffExecutor == null) {
+            throw new NullPointerException("handoffExecutor is null");
+        }
+        this.queue = queue;
+        this.parent = parent;
+        this.policy = policy;
+        this.handoffExecutor = handoffExecutor;
+    }
+
+    /**
+     * Run a task.
+     *
+     * @param command the task to run.
+     */
+    public void execute(Runnable command) {
+        try {
+            lock.lockInterruptibly();
+            try {
+                while (! queue.offer(command)) {
+                    switch (policy) {
+                        case ABORT:
+                            throw new RejectedExecutionException();
+                        case BLOCK:
+                            removeCondition.await();
+                            break;
+                        case DISCARD:
+                            return;
+                        case DISCARD_OLDEST:
+                            if (queue.poll() != null) {
+                                queue.add(command);
+                            }
+                            break;
+                        case HANDOFF:
+                            handoffExecutor.execute(command);
+                            return;
+                    }
+                }
+                if (! running) {
+                    running = true;
+                    boolean ok = false;
+                    try {
+                        parent.execute(runner);
+                        ok = true;
+                    } finally {
+                        if (! ok) {
+                            running = false;
+                        }
+                    }
+                }
+            } finally {
+                lock.unlock();
+            }
+        } catch (InterruptedException e) {
+            throw new RejectedExecutionException();
+        }
+    }
+
+    private class Runner implements Runnable {
+        public void run() {
+            for (;;) {
+                final Runnable task;
+                lock.lock();
+                try {
+                    task = queue.poll();
+                    removeCondition.signal();
+                    if (task == null) {
+                        running = false;
+                        return;
+                    }
+                } finally {
+                    lock.unlock();
+                }
+                try {
+                    task.run();
+                } catch (Throwable t) {
+                    // todo log?
+                }
+            }
+        }
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedDirectExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedDirectExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedDirectExecutor.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,34 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+/**
+ * A direct executor that simply delegates to another direct executor.  Use instances of this class to hide extra methods on
+ * another executor.
+ */
+public class ProtectedDirectExecutor extends ProtectedExecutor implements DirectExecutor {
+
+    public ProtectedDirectExecutor(final DirectExecutor delegate) {
+        super(delegate);
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedDirectExecutorService.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedDirectExecutorService.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedDirectExecutorService.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+/**
+ * A {@code DirectExecutor} version of {@code ProtectedExecutorService}.
+ */
+public class ProtectedDirectExecutorService extends ProtectedExecutorService implements DirectExecutorService {
+    public ProtectedDirectExecutorService(final DirectExecutor delegate) {
+        super(delegate);
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedExecutor.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.util.concurrent.Executor;
+
+/**
+ * An executor that simply delegates to another executor.  Use instances of this class to hide extra methods on
+ * another executor.
+ */
+public class ProtectedExecutor implements Executor {
+    private final Executor delegate;
+
+    public ProtectedExecutor(final Executor delegate) {
+        this.delegate = delegate;
+    }
+
+    /**
+     * Execute a task by passing it to the delegate executor.
+     *
+     * @param command the task
+     */
+    public void execute(final Runnable command) {
+        delegate.execute(command);
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedExecutorService.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedExecutorService.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedExecutorService.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,71 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.AbstractExecutorService;
+import java.util.concurrent.Executor;
+import java.util.List;
+
+/**
+ * An implementation of {@code ExecutorService} that delegates to the real executor, while disallowing termination.
+ */
+public class ProtectedExecutorService extends AbstractExecutorService implements ExecutorService {
+    private final Executor delegate;
+
+    public ProtectedExecutorService(final Executor delegate) {
+        this.delegate = delegate;
+    }
+
+    public void execute(final Runnable command) {
+        delegate.execute(command);
+    }
+
+    public boolean isShutdown() {
+        // container managed executors are never shut down from the application's perspective
+        return false;
+    }
+
+    public boolean isTerminated() {
+        // container managed executors are never shut down from the application's perspective
+        return false;
+    }
+
+    public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException {
+        unit.sleep(timeout);
+        return false;
+    }
+
+    public void shutdown() {
+        throw new SecurityException("shutdown() not allowed on container-managed executor");
+    }
+
+    public List<Runnable> shutdownNow() {
+        throw new SecurityException("shutdownNow() not allowed on container-managed executor");
+    }
+
+    public static ExecutorService directExecutorService() {
+        return new ProtectedExecutorService(JBossExecutors.directExecutor());
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/RejectionPolicy.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/RejectionPolicy.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/RejectionPolicy.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+/**
+ * Specify the way a task rejection should be handled.
+ */
+public enum RejectionPolicy {
+
+    /**
+     * Abort execution with an exception.
+     */
+    ABORT,
+    /**
+     * Wait until there is room in the queue, or the calling thread is interrupted.
+     */
+    BLOCK,
+    /**
+     * Discard the excess task silently.
+     */
+    DISCARD,
+    /**
+     * Discard the oldest task in the queue silently, and enqueue the new task.  If the queue has no capacity
+     * then the new task will be discarded.
+     */
+    DISCARD_OLDEST,
+    /**
+     * Hand off the task to another executor.
+     */
+    HANDOFF,
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/SimpleQueueExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/SimpleQueueExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/SimpleQueueExecutor.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,556 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.AbstractExecutorService;
+import java.util.concurrent.ExecutorService;
+import java.util.Queue;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * An executor which uses a regular queue to hold tasks.  The executor may be tuned at runtime in many ways.
+ */
+public final class SimpleQueueExecutor extends AbstractExecutorService implements ExecutorService {
+    private final Lock lock = new ReentrantLock();
+    // signal when a task is written to the queue
+    private final Condition enqueueCondition = lock.newCondition();
+    // signal when the queue is read
+    private final Condition removeCondition = lock.newCondition();
+    // signalled when threads terminate
+    private final Condition threadExitCondition = lock.newCondition();
+    private final ThreadFactory threadFactory;
+
+    // all protected by poolLock...
+    private int coreThreadLimit;
+    private int maxThreadLimit;
+    private boolean allowCoreThreadTimeout;
+    private long keepAliveTime;
+    private TimeUnit keepAliveTimeUnit;
+    private RejectionPolicy rejectionPolicy;
+    private Executor handoffExecutor;
+
+    private int threadCount;
+    private Set<Thread> workers = new HashSet<Thread>();
+
+    private boolean stop;
+    private boolean interrupt;
+
+    private Queue<Runnable> queue;
+
+    public SimpleQueueExecutor(final int coreThreadLimit, final int maxThreadLimit, final long keepAliveTime, final TimeUnit keepAliveTimeUnit, final Queue<Runnable> queue, final ThreadFactory threadFactory, final RejectionPolicy rejectionPolicy, final Executor handoffExecutor) {
+        if (threadFactory == null) {
+            throw new NullPointerException("threadFactory is null");
+        }
+        if (queue == null) {
+            throw new NullPointerException("queue is null");
+        }
+        if (keepAliveTimeUnit == null) {
+            throw new NullPointerException("keepAliveTimeUnit is null");
+        }
+        if (rejectionPolicy == null) {
+            throw new NullPointerException("rejectionPolicy is null");
+        }
+        if (rejectionPolicy == RejectionPolicy.HANDOFF && handoffExecutor == null) {
+            throw new NullPointerException("handoffExecutor is null");
+        }
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            this.threadFactory = threadFactory;
+            // configurable...
+            this.keepAliveTime = keepAliveTime;
+            this.keepAliveTimeUnit = keepAliveTimeUnit;
+            this.coreThreadLimit = coreThreadLimit;
+            this.maxThreadLimit = maxThreadLimit;
+            this.queue = queue;
+            this.rejectionPolicy = rejectionPolicy;
+            this.handoffExecutor = handoffExecutor;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public void execute(final Runnable task) throws RejectedExecutionException {
+        final Lock lock = this.lock;
+        try {
+            lock.lockInterruptibly();
+            try {
+                for (;;) {
+                    if (stop) {
+                        throw new RejectedExecutionException("Executor is stopped");
+                    }
+                    // Try core thread first, then queue, then extra thread
+                    final int count = threadCount;
+                    if (count < coreThreadLimit) {
+                        startNewThread(task);
+                        threadCount = count + 1;
+                        return;
+                    }
+                    // next queue...
+                    final Queue<Runnable> queue = this.queue;
+                    if (queue.offer(task)) {
+                        enqueueCondition.signal();
+                        return;
+                    }
+                    // extra threads?
+                    if (count < maxThreadLimit) {
+                        startNewThread(task);
+                        threadCount = count + 1;
+                        return;
+                    }
+                    // how to reject the task...
+                    switch (rejectionPolicy) {
+                        case ABORT:
+                            throw new RejectedExecutionException("Executor is busy");
+                        case BLOCK:
+                            removeCondition.await();
+                            break;
+                        case DISCARD:
+                            return;
+                        case DISCARD_OLDEST:
+                            if (queue.poll() != null) {
+                                queue.add(task);
+                                enqueueCondition.signal();
+                            }
+                            return;
+                        case HANDOFF:
+                            handoffExecutor.execute(task);
+                            return;
+                    }
+                }
+            } finally {
+                lock.unlock();
+            }
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new RejectedExecutionException("Thread interrupted");
+        }
+    }
+
+    public void shutdown() {
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            if (! stop) {
+                stop = true;
+                // wake up the whole town
+                removeCondition.signalAll();
+                enqueueCondition.signalAll();
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public List<Runnable> shutdownNow() {
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            stop = true;
+            interrupt = true;
+            removeCondition.signalAll();
+            enqueueCondition.signalAll();
+            for (Thread worker : workers) {
+                worker.interrupt();
+            }
+            final Queue<Runnable> queue = this.queue;
+            final ArrayList<Runnable> list = new ArrayList<Runnable>(queue);
+            queue.clear();
+            return list;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public boolean isShutdown() {
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            return stop;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public boolean isTerminated() {
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            return stop && threadCount == 0;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException {
+        final Lock lock = this.lock;
+        lock.lockInterruptibly();
+        try {
+            final long start = System.currentTimeMillis();
+            long elapsed = 0L;
+            while (! stop && threadCount > 0) {
+                final long remaining = timeout - elapsed;
+                if (remaining <= 0) {
+                    return false;
+                }
+                threadExitCondition.await(remaining, unit);
+                elapsed = unit.convert(System.currentTimeMillis() - start, TimeUnit.MILLISECONDS);
+            }
+            return true;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public boolean isAllowCoreThreadTimeout() {
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            return allowCoreThreadTimeout;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public void setAllowCoreThreadTimeout(boolean allowCoreThreadTimeout) {
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            this.allowCoreThreadTimeout = allowCoreThreadTimeout;
+            if (allowCoreThreadTimeout) {
+                // wake everyone up so core threads can time out
+                enqueueCondition.signalAll();
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public int getCoreThreadLimit() {
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            return coreThreadLimit;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public void setCoreThreadLimit(final int coreThreadLimit) {
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            final int oldLimit = this.coreThreadLimit;
+            if (maxThreadLimit < coreThreadLimit) {
+                // don't let the max thread limit be less than the core thread limit.
+                // the called method will signal as needed
+                setMaxThreadLimit(coreThreadLimit);
+            } else if (oldLimit < coreThreadLimit) {
+                // we're growing the number of core threads
+                // therefore signal anyone waiting to add tasks; there might be more threads to add
+                removeCondition.signalAll();
+            } else if (oldLimit > coreThreadLimit) {
+                // we're shrinking the number of core threads
+                // therefore signal anyone waiting to remove tasks so the pool can shrink properly
+                enqueueCondition.signalAll();
+            } else {
+                // we aren't changing anything...
+                return;
+            }
+            this.coreThreadLimit = coreThreadLimit;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public int getMaxThreadLimit() {
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            return maxThreadLimit;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public void setMaxThreadLimit(final int maxThreadLimit) {
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            final int oldLimit = this.maxThreadLimit;
+            if (maxThreadLimit < coreThreadLimit) {
+                // don't let the max thread limit be less than the core thread limit.
+                // the called method will signal as needed
+                setCoreThreadLimit(maxThreadLimit);
+            } else if (oldLimit < maxThreadLimit) {
+                // we're growing the number of extra threads
+                // therefore signal anyone waiting to add tasks; there might be more threads to add
+                removeCondition.signalAll();
+            } else if (oldLimit > maxThreadLimit) {
+                // we're shrinking the number of extra threads
+                // therefore signal anyone waiting to remove tasks so the pool can shrink properly
+                enqueueCondition.signalAll();
+            } else {
+                // we aren't changing anything...
+                return;
+            }
+            this.maxThreadLimit = maxThreadLimit;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public long getKeepAliveTime() {
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            return keepAliveTime;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public TimeUnit getKeepAliveTimeUnit() {
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            return keepAliveTimeUnit;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public void setKeepAliveTime(final long keepAliveTime, final TimeUnit keepAliveTimeUnit) {
+        if (keepAliveTimeUnit == null) {
+            throw new NullPointerException("keepAliveTimeUnit is null");
+        }
+        if (keepAliveTime < 0L) {
+            throw new IllegalArgumentException("keepAliveTime is less than zero");
+        }
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            this.keepAliveTime = keepAliveTime;
+            this.keepAliveTimeUnit = keepAliveTimeUnit;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public RejectionPolicy getRejectionPolicy() {
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            return rejectionPolicy;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public void setRejectionPolicy(final RejectionPolicy newPolicy, final Executor handoffExecutor) {
+        if (newPolicy == null) {
+            throw new NullPointerException("rejectionPolicy is null");
+        }
+        if (newPolicy == RejectionPolicy.HANDOFF && handoffExecutor == null) {
+            throw new NullPointerException("handoffExecutor is null");
+        }
+        final Lock lock = this.lock;
+        lock.lock();
+        try {
+            if (rejectionPolicy == RejectionPolicy.BLOCK && newPolicy != RejectionPolicy.BLOCK) {
+                // there could be blocking .execute() calls out there; give them a nudge
+                removeCondition.signalAll();
+            }
+            rejectionPolicy = newPolicy;
+            this.handoffExecutor = handoffExecutor;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    // container lifecycle methods
+    public void stop() {
+        shutdown();
+        try {
+            awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
+            // todo log if fails?
+        } catch (InterruptedException e) {
+            // todo log it?
+            Thread.currentThread().interrupt();
+        }
+    }
+
+    public void destroy() {
+        // todo is this the right behavior?
+        shutdownNow();
+        try {
+            awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
+            // todo log if fails?
+        } catch (InterruptedException e) {
+            // todo log it?
+            Thread.currentThread().interrupt();
+        }
+    }
+
+    // call with lock held!
+    private void startNewThread(final Runnable task) {
+        final Thread thread = threadFactory.newThread(new Worker(task));
+        workers.add(thread);
+        thread.start();
+    }
+
+    // call with lock held!
+    private Runnable pollTask() {
+        final Runnable task = queue.poll();
+        if (task != null) {
+            removeCondition.signal();
+            return task;
+        } else {
+            if (-- threadCount == 0) {
+                threadExitCondition.signalAll();
+            }
+            return null;
+        }
+    }
+
+    // call with lock held!
+    private Runnable takeTask() {
+        final Condition removeCondition = this.removeCondition;
+        Runnable task = queue.poll();
+        if (task != null) {
+            removeCondition.signal();
+            return task;
+        } else {
+            final Condition enqueueCondition = this.enqueueCondition;
+            final long start = System.currentTimeMillis();
+            boolean intr = Thread.interrupted();
+            try {
+                long elapsed = 0L;
+                for (;;) {
+                    // these parameters may change on each iteration
+                    final int threadCount = this.threadCount;
+                    final int coreThreadLimit = this.coreThreadLimit;
+                    final boolean allowCoreThreadTimeout = this.allowCoreThreadTimeout;
+                    if (stop || threadCount > maxThreadLimit) {
+                        // too many threads.  Handle a task if there is one, otherwise exit
+                        return pollTask();
+                    } else if (!allowCoreThreadTimeout && threadCount < coreThreadLimit) {
+                        // ignore timeout until we are not a core thread or until core threads are allowed to time out
+                        try {
+                            enqueueCondition.await();
+                        } catch (InterruptedException e) {
+                            intr = true;
+                        }
+                    } else {
+                        final TimeUnit timeUnit = keepAliveTimeUnit;
+                        final long time = keepAliveTime;
+                        final long remaining = time - timeUnit.convert(elapsed, TimeUnit.MILLISECONDS);
+                        if (remaining <= 0L && (allowCoreThreadTimeout || threadCount > coreThreadLimit)) {
+                            // the timeout has expired
+                            return pollTask();
+                        }
+                        try {
+                            enqueueCondition.await(remaining, timeUnit);
+                        } catch (InterruptedException e) {
+                            intr = true;
+                        }
+                    }
+                    task = queue.poll();
+                    if (task != null) {
+                        removeCondition.signal();
+                        return task;
+                    }
+                    elapsed = System.currentTimeMillis() - start;
+                }
+            } finally {
+                if (intr) {
+                    Thread.currentThread().interrupt();
+                }
+            }
+        }
+    }
+
+    private class Worker implements Runnable {
+
+        private Runnable first;
+
+        public Worker(final Runnable command) {
+            first = command;
+        }
+
+        public void run() {
+            final Lock lock = SimpleQueueExecutor.this.lock;
+            Runnable task = first;
+            // Release reference to task
+            first = null;
+            lock.lock();
+            try {
+                for (;;) {
+                    if (task != null) {
+                        try {
+                            if (interrupt) {
+                                Thread.currentThread().interrupt();
+                            }
+                            lock.unlock();
+                            try {
+                                task.run();
+                            } finally {
+                                // this is OK because it's in the finally block after lock.unlock()
+                                //noinspection LockAcquiredButNotSafelyReleased
+                                lock.lock();
+                            }
+                        } catch (Throwable t) {
+                            // todo - log the exception perhaps
+                        }
+                        // don't hang on to task while we possibly block down below
+                        task = null;
+                    }
+                    if (stop) {
+                        // drain queue
+                        if ((task = pollTask()) == null) {
+                            return;
+                        }
+                    } else {
+                        // get next task
+                        if ((task = takeTask()) == null) {
+                            return;
+                        }
+                    }
+                }
+            } finally {
+                workers.remove(Thread.currentThread());
+                lock.unlock();
+            }
+        }
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/resources/META-INF/jboss-classloading.xml
===================================================================
--- projects/jboss-threads/trunk/main/src/main/resources/META-INF/jboss-classloading.xml	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/resources/META-INF/jboss-classloading.xml	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<classloading xmlns="urn:jboss:classloading:1.0" import-all="false">
+    <capabilities>
+        <module name="jboss-threads" version="1.0.0.CR1"/>
+        <package name="org.jboss.threads" version="1.0.0.CR1"/>
+    </capabilities>
+    <requirements/>
+</classloading>

Added: projects/jboss-threads/trunk/main/src/test/java/org/jboss/threads/ArrayQueueTestCase.java
===================================================================
--- projects/jboss-threads/trunk/main/src/test/java/org/jboss/threads/ArrayQueueTestCase.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/test/java/org/jboss/threads/ArrayQueueTestCase.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,86 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import junit.framework.TestCase;
+
+/**
+ *
+ */
+public final class ArrayQueueTestCase extends TestCase {
+
+    public void testBasic() {
+        final int max = 40;
+        final ArrayQueue<Object> queue = new ArrayQueue<Object>(max);
+        for (int i = 0; i < max; i ++) {
+            assertEquals("Size mismatch, iteration " + i, i, queue.size());
+            assertTrue("Iteration " + i, queue.offer(new Object()));
+        }
+        assertFalse("Queue took extra element", queue.offer(new Object()));
+        for (int i = 0; i < max; i ++) {
+            assertNotNull("Queue missing elements", queue.poll());
+        }
+        assertNull("Queue has extra elements", queue.poll());
+    }
+
+    public void testContents() {
+        final int max = 40;
+        final ArrayQueue<Object> queue = new ArrayQueue<Object>(max);
+        for (int cnt = 1; cnt < max; cnt ++) {
+            for (int i = 0; i < cnt; i ++) {
+                assertEquals("Size mismatch, iteration " + i, i, queue.size());
+                assertTrue("Queue won't take element, iteration " + cnt + "/" + i, queue.offer(new Integer(i)));
+            }
+            for (int i = 0; i < cnt; i ++) {
+                assertTrue("Missing int value, iteration " + cnt + "/" + i, queue.contains(new Integer(i)));
+            }
+            for (int i = 0; i < cnt; i ++) {
+                assertEquals("Size mismatch, iteration " + i, cnt - i, queue.size());
+                assertEquals("Wrong object value, iteration " + cnt + "/" + i, new Integer(i), queue.poll());
+            }
+            assertNull("Extra value, iteration " + cnt, queue.poll());
+            for (int i = 0; i < cnt; i ++) {
+                assertFalse("Nonremoved value, iteration " + cnt + "/" + i, queue.contains(new Integer(i)));
+            }
+        }
+    }
+
+    public void testClear() {
+        final int max = 40;
+        final ArrayQueue<Object> queue = new ArrayQueue<Object>(max);
+        for (int cnt = 1; cnt < max; cnt ++) {
+            for (int i = 0; i < cnt; i ++) {
+                assertEquals("Size mismatch, iteration " + i, i, queue.size());
+                assertTrue("Queue won't take element, iteration " + cnt + "/" + i, queue.offer(new Integer(i)));
+            }
+            for (int i = 0; i < cnt; i ++) {
+                assertTrue("Missing int value, iteration " + cnt + "/" + i, queue.contains(new Integer(i)));
+            }
+            queue.clear();
+            assertNull("Extra value, iteration " + cnt, queue.poll());
+            for (int i = 0; i < cnt; i ++) {
+                assertFalse("Nonremoved value, iteration " + cnt + "/" + i, queue.contains(new Integer(i)));
+            }
+        }
+    }
+}

Added: projects/jboss-threads/trunk/main/src/test/java/org/jboss/threads/ThreadFactoryTestCase.java
===================================================================
--- projects/jboss-threads/trunk/main/src/test/java/org/jboss/threads/ThreadFactoryTestCase.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/test/java/org/jboss/threads/ThreadFactoryTestCase.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,126 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ *
+ */
+public final class ThreadFactoryTestCase extends TestCase {
+    private static final NullRunnable NULL_RUNNABLE = new NullRunnable();
+
+    private static class NullRunnable implements Runnable {
+        public void run() {
+        }
+    }
+
+    private static void doTestNamePattern(JBossThreadFactory threadFactory, int expectedPerFactoryId, int expectedGlobalId, int expectedFactoryId) {
+        final String name = threadFactory.newThread(NULL_RUNNABLE).getName();
+        assertTrue("Wrong thread name (" + name + ") ", name.matches("-([a-z]+:)*one:two:three-%-" + expectedPerFactoryId + "-" + expectedGlobalId + "-" + expectedFactoryId + "-"));
+    }
+
+    /**
+     * This MUST be the first test, otherwise the sequence numbers will be wrong.
+     */
+    public void testNamePattern() {
+        // TODO - skip test for now since it depends on order.
+        if (true) return;
+        final JBossThreadFactory threadFactory1 = new JBossThreadFactory(new ThreadGroup(new ThreadGroup(new ThreadGroup("one"), "two"), "three"), null,
+                null, "-%p-%%-%t-%g-%f-", null, null, null);
+        doTestNamePattern(threadFactory1, 1, 1, 1);
+        doTestNamePattern(threadFactory1, 2, 2, 1);
+        doTestNamePattern(threadFactory1, 3, 3, 1);
+        final JBossThreadFactory threadFactory2 = new JBossThreadFactory(new ThreadGroup(new ThreadGroup(new ThreadGroup("one"), "two"), "three"), null,
+                null, "-%p-%%-%t-%g-%f-", null, null, null);
+        doTestNamePattern(threadFactory2, 1, 4, 2);
+        doTestNamePattern(threadFactory2, 2, 5, 2);
+        doTestNamePattern(threadFactory2, 3, 6, 2);
+        doTestNamePattern(threadFactory2, 4, 7, 2);
+        // back to the first factory...
+        doTestNamePattern(threadFactory1, 4, 8, 1);
+    }
+
+    public void testDaemon() {
+        final JBossThreadFactory threadFactory1 = new JBossThreadFactory(null, Boolean.TRUE, null, "%t", null, null, null);
+        assertTrue("Thread is not a daemon thread", threadFactory1.newThread(NULL_RUNNABLE).isDaemon());
+        final JBossThreadFactory threadFactory2 = new JBossThreadFactory(null, Boolean.FALSE, null, "%t", null, null, null);
+        assertFalse("Thread should not be a daemon thread", threadFactory2.newThread(NULL_RUNNABLE).isDaemon());
+    }
+
+    public void testInterruptHandler() throws InterruptedException {
+        final AtomicBoolean wasInterrupted = new AtomicBoolean();
+        final AtomicBoolean called = new AtomicBoolean();
+        final JBossThreadFactory threadFactory = new JBossThreadFactory(null, null, null, null, new InterruptHandler[] {
+                new InterruptHandler() {
+                    public void handleInterrupt(final Thread thread) {
+                        called.set(true);
+                    }
+                }
+        }, null, null);
+        final Thread t = threadFactory.newThread(new Runnable() {
+            public void run() {
+                synchronized (this) {
+                    try {
+                        wait();
+                    } catch (InterruptedException e) {
+                        wasInterrupted.set(true);
+                    }
+                }
+            }
+        });
+        t.start();
+        t.interrupt();
+        t.join();
+        assertTrue("Was not interrupted", wasInterrupted.get());
+        assertTrue("Handler was not called", called.get());
+    }
+
+    public void testUncaughtHandler() throws InterruptedException {
+        final AtomicBoolean called = new AtomicBoolean();
+        final JBossThreadFactory factory = new JBossThreadFactory(null, null, null, null, null, new Thread.UncaughtExceptionHandler() {
+            public void uncaughtException(final Thread t, final Throwable e) {
+                called.set(true);
+            }
+        }, null);
+        final Thread t = factory.newThread(new Runnable() {
+            public void run() {
+                throw new RuntimeException("...");
+            }
+        });
+        t.start();
+        t.join();
+        assertTrue("Handler was not called", called.get());
+    }
+
+    public void testInitialPriority() {
+        assertEquals("Wrong initial thread priority", 1, new JBossThreadFactory(null, null, Integer.valueOf(1), null, null, null, null).newThread(NULL_RUNNABLE).getPriority());
+        assertEquals("Wrong initial thread priority", 2, new JBossThreadFactory(null, null, Integer.valueOf(2), null, null, null, null).newThread(NULL_RUNNABLE).getPriority());
+        final ThreadGroup grp = new ThreadGroup("blah");
+        grp.setMaxPriority(5);
+        assertEquals("Wrong initial thread priority", 5, new JBossThreadFactory(grp, null, Integer.valueOf(10), null, null, null, null).newThread(NULL_RUNNABLE).getPriority());
+        assertEquals("Wrong initial thread priority", 1, new JBossThreadFactory(grp, null, Integer.valueOf(1), null, null, null, null).newThread(NULL_RUNNABLE).getPriority());
+    }
+}

Added: projects/jboss-threads/trunk/main/src/test/java/org/jboss/threads/ThreadPoolTestCase.java
===================================================================
--- projects/jboss-threads/trunk/main/src/test/java/org/jboss/threads/ThreadPoolTestCase.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/test/java/org/jboss/threads/ThreadPoolTestCase.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,157 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import junit.framework.TestCase;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.LinkedList;
+
+/**
+ *
+ */
+public final class ThreadPoolTestCase extends TestCase {
+
+    private final JBossThreadFactory threadFactory = new JBossThreadFactory(null, null, null, "test thread %p %t", null, null, null);
+
+    private static final class SimpleTask implements Runnable {
+
+        private final CountDownLatch taskUnfreezer;
+        private final CountDownLatch taskFinishLine;
+
+        private SimpleTask(final CountDownLatch taskUnfreezer, final CountDownLatch taskFinishLine) {
+            this.taskUnfreezer = taskUnfreezer;
+            this.taskFinishLine = taskFinishLine;
+        }
+
+        public void run() {
+            try {
+                assertTrue(taskUnfreezer.await(800L, TimeUnit.MILLISECONDS));
+            } catch (InterruptedException e) {
+                fail("interrupted");
+            }
+            taskFinishLine.countDown();
+        }
+    }
+
+    public void testBasic() throws InterruptedException {
+        // Start some tasks, let them run, then shut down the executor
+        final int cnt = 100;
+        final CountDownLatch taskUnfreezer = new CountDownLatch(1);
+        final CountDownLatch taskFinishLine = new CountDownLatch(cnt);
+        final ExecutorService simpleQueueExecutor = new SimpleQueueExecutor(5, 5, 500L, TimeUnit.MILLISECONDS, new LinkedList<Runnable>(), threadFactory, RejectionPolicy.BLOCK, null);
+        for (int i = 0; i < cnt; i ++) {
+            simpleQueueExecutor.execute(new SimpleTask(taskUnfreezer, taskFinishLine));
+        }
+        taskUnfreezer.countDown();
+        final boolean finished = taskFinishLine.await(800L, TimeUnit.MILLISECONDS);
+        assertTrue(finished);
+        simpleQueueExecutor.shutdown();
+        try {
+            simpleQueueExecutor.execute(new Runnable() {
+                public void run() {
+                }
+            });
+            fail("Task not rejected after shutdown");
+        } catch (Throwable t) {
+            assertEquals(RejectedExecutionException.class, t.getClass());
+        }
+        assertTrue(simpleQueueExecutor.awaitTermination(800L, TimeUnit.MILLISECONDS));
+    }
+
+    public void testShutdownNow() throws InterruptedException {
+        final AtomicBoolean interrupted = new AtomicBoolean();
+        final AtomicBoolean ran = new AtomicBoolean();
+
+        final CountDownLatch startLatch = new CountDownLatch(1);
+        final ExecutorService simpleQueueExecutor = new SimpleQueueExecutor(5, 5, 500L, TimeUnit.MILLISECONDS, new LinkedList<Runnable>(), threadFactory, RejectionPolicy.BLOCK, null);
+        simpleQueueExecutor.execute(new Runnable() {
+            public void run() {
+                try {
+                    ran.set(true);
+                    startLatch.countDown();
+                    Thread.sleep(5000L);
+                } catch (InterruptedException e) {
+                    interrupted.set(true);
+                }
+            }
+        });
+        assertTrue("Task not started", startLatch.await(300L, TimeUnit.MILLISECONDS));
+        assertTrue("Task returned", simpleQueueExecutor.shutdownNow().isEmpty());
+        try {
+            simpleQueueExecutor.execute(new Runnable() {
+                public void run() {
+                }
+            });
+            fail("Task not rejected after shutdown");
+        } catch (RejectedExecutionException t) {
+        }
+        assertTrue("Executor not shut down in 800ms", simpleQueueExecutor.awaitTermination(800L, TimeUnit.MILLISECONDS));
+        assertTrue("Task wasn't run", ran.get());
+        assertTrue("Worker wasn't interrupted", interrupted.get());
+    }
+
+    public void testBlocking() throws InterruptedException {
+        final int queueSize = 20;
+        final int coreThreads = 5;
+        final int extraThreads = 5;
+        final int cnt = queueSize + coreThreads + extraThreads;
+        final CountDownLatch taskUnfreezer = new CountDownLatch(1);
+        final CountDownLatch taskFinishLine = new CountDownLatch(cnt);
+        final ExecutorService simpleQueueExecutor = new SimpleQueueExecutor(coreThreads, coreThreads + extraThreads, 500L, TimeUnit.MILLISECONDS, new ArrayQueue<Runnable>(queueSize), threadFactory, RejectionPolicy.BLOCK, null);
+        for (int i = 0; i < cnt; i ++) {
+            simpleQueueExecutor.execute(new SimpleTask(taskUnfreezer, taskFinishLine));
+        }
+        Thread.currentThread().interrupt();
+        try {
+            simpleQueueExecutor.execute(new Runnable() {
+                public void run() {
+                }
+            });
+            fail("Task was accepted");
+        } catch (RejectedExecutionException t) {
+        }
+        Thread.interrupted();
+        final CountDownLatch latch = new CountDownLatch(1);
+        final Thread otherThread = threadFactory.newThread(new Runnable() {
+            public void run() {
+                simpleQueueExecutor.execute(new Runnable() {
+                    public void run() {
+                        latch.countDown();
+                    }
+                });
+            }
+        });
+        otherThread.start();
+        assertFalse("Task executed without wait", latch.await(100L, TimeUnit.MILLISECONDS));
+        // safe to say the other thread is blocking...?
+        taskUnfreezer.countDown();
+        assertTrue("Task never ran", latch.await(800L, TimeUnit.MILLISECONDS));
+        otherThread.join(500L);
+        simpleQueueExecutor.shutdown();
+        assertTrue("Executor not shut down in 800ms", simpleQueueExecutor.awaitTermination(800L, TimeUnit.MILLISECONDS));
+    }
+}

Added: projects/jboss-threads/trunk/pom.xml
===================================================================
--- projects/jboss-threads/trunk/pom.xml	                        (rev 0)
+++ projects/jboss-threads/trunk/pom.xml	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,15 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.jboss.threads</groupId>
+    <artifactId>threads-all</artifactId>
+    <version>1.0.0.CR1</version>
+    <packaging>pom</packaging>
+    <modules>
+        <module>main</module>
+        <module>jbossmc</module>
+    </modules>
+</project>

Added: projects/jboss-threads/trunk/test-support/src/main/java/org/jboss/testsupport/LoggingHelper.java
===================================================================
--- projects/jboss-threads/trunk/test-support/src/main/java/org/jboss/testsupport/LoggingHelper.java	                        (rev 0)
+++ projects/jboss-threads/trunk/test-support/src/main/java/org/jboss/testsupport/LoggingHelper.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,117 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.testsupport;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.io.IOException;
+
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import java.util.logging.Handler;
+import java.util.logging.Formatter;
+import java.util.logging.LogRecord;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.FileHandler;
+
+/**
+ *
+ */
+public final class LoggingHelper {
+    private static final long startTime = System.currentTimeMillis();
+
+    private static final class Once {
+        static {
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                public Void run() {
+                    final Logger rootLogger = Logger.getLogger("");
+                    rootLogger.setLevel(Level.ALL);
+                    final Handler[] handlers = rootLogger.getHandlers();
+                    for (Handler handler : handlers) {
+                        rootLogger.removeHandler(handler);
+                    }
+                    final Formatter formatter = new Formatter() {
+                        public String format(final LogRecord record) {
+                            StringBuilder builder = new StringBuilder();
+                            long offs = record.getMillis() - startTime;
+                            final String sign = offs < 0 ? "-" : "+";
+                            offs = Math.abs(offs);
+                            int ms = (int) (offs % 1000L);
+                            long s = offs / 1000L;
+                            builder.append(String.format("%s%04d.%03d ", sign, Long.valueOf(s), Long.valueOf(ms)));
+                            builder.append(String.format("tid:%d ", Integer.valueOf(record.getThreadID())));
+                            builder.append(record.getLevel().toString());
+                            builder.append(" [").append(record.getLoggerName()).append("] ");
+                            builder.append(String.format(record.getMessage(), record.getParameters()));
+                            Throwable t = record.getThrown();
+                            while (t != null) {
+                                builder.append("\n    Caused by: ");
+                                builder.append(t.toString());
+                                for (StackTraceElement e : t.getStackTrace()) {
+                                    builder.append("\n        at ");
+                                    builder.append(e.getClassName()).append('.').append(e.getMethodName());
+                                    builder.append("(").append(e.getFileName()).append(':').append(e.getLineNumber()).append(')');
+                                }
+                                t = t.getCause();
+                            }
+                            builder.append('\n');
+                            return builder.toString();
+                        }
+                    };
+                    final Handler handler = new ConsoleHandler() {
+                        @Override
+                        public void publish(final LogRecord record) {
+                            super.publish(record);
+                            flush();
+                        }
+                    };
+                    handler.setFormatter(formatter);
+                    handler.setLevel(Level.ALL);
+                    rootLogger.addHandler(handler);
+                    if (false) try {
+                        final FileHandler fileHandler = new FileHandler("test-output.log", true) {
+                            @Override
+                            public void publish(final LogRecord record) {
+                                super.publish(record);
+                                flush();
+                            }
+                        };
+                        fileHandler.setFormatter(formatter);
+                        fileHandler.setLevel(Level.ALL);
+                        rootLogger.addHandler(fileHandler);
+                    } catch (IOException e) {
+                        // oh well
+                    }
+                    return null;
+                }
+            });
+        }
+    }
+
+    private LoggingHelper() {
+    }
+
+    public static void init() {
+        new Once();
+    }
+}

Added: projects/jboss-threads/trunk/test-support/src/main/java/org/jboss/testsupport/LoggingSecurityManager.java
===================================================================
--- projects/jboss-threads/trunk/test-support/src/main/java/org/jboss/testsupport/LoggingSecurityManager.java	                        (rev 0)
+++ projects/jboss-threads/trunk/test-support/src/main/java/org/jboss/testsupport/LoggingSecurityManager.java	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,295 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.testsupport;
+
+import java.security.Permission;
+import java.io.FileDescriptor;
+import java.net.InetAddress;
+
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+/**
+ *
+ */
+public final class LoggingSecurityManager extends SecurityManager {
+
+    private static final Logger log = Logger.getLogger("ACCESS_EXCEPTION");
+
+    public LoggingSecurityManager() {
+    }
+
+    private static <T extends Throwable> T logged(T se) {
+        log.log(Level.SEVERE, "Access violation!", se);
+        return se;
+    }
+
+    public void checkPermission(final Permission perm) {
+        try {
+            super.checkPermission(perm);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkPermission(final Permission perm, final Object context) {
+        try {
+            super.checkPermission(perm, context);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkCreateClassLoader() {
+        try {
+            super.checkCreateClassLoader();
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkAccess(final Thread t) {
+        try {
+            super.checkAccess(t);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkAccess(final ThreadGroup g) {
+        try {
+            super.checkAccess(g);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkExit(final int status) {
+        try {
+            super.checkExit(status);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkExec(final String cmd) {
+        try {
+            super.checkExec(cmd);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkLink(final String lib) {
+        try {
+            super.checkLink(lib);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkRead(final FileDescriptor fd) {
+        try {
+            super.checkRead(fd);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkRead(final String file) {
+        try {
+            super.checkRead(file);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkRead(final String file, final Object context) {
+        try {
+            super.checkRead(file, context);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkWrite(final FileDescriptor fd) {
+        try {
+            super.checkWrite(fd);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkWrite(final String file) {
+        try {
+            super.checkWrite(file);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkDelete(final String file) {
+        try {
+            super.checkDelete(file);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkConnect(final String host, final int port) {
+        try {
+            super.checkConnect(host, port);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkConnect(final String host, final int port, final Object context) {
+        try {
+            super.checkConnect(host, port, context);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkListen(final int port) {
+        try {
+            super.checkListen(port);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkAccept(final String host, final int port) {
+        try {
+            super.checkAccept(host, port);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkMulticast(final InetAddress maddr) {
+        try {
+            super.checkMulticast(maddr);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    @Deprecated
+    public void checkMulticast(final InetAddress maddr, final byte ttl) {
+        try {
+            super.checkMulticast(maddr, ttl);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkPropertiesAccess() {
+        try {
+            super.checkPropertiesAccess();
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkPropertyAccess(final String key) {
+        try {
+            super.checkPropertyAccess(key);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public boolean checkTopLevelWindow(final Object window) {
+        try {
+            return super.checkTopLevelWindow(window);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkPrintJobAccess() {
+        try {
+            super.checkPrintJobAccess();
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkSystemClipboardAccess() {
+        try {
+            super.checkSystemClipboardAccess();
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkAwtEventQueueAccess() {
+        try {
+            super.checkAwtEventQueueAccess();
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkPackageAccess(final String pkg) {
+        try {
+            super.checkPackageAccess(pkg);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkPackageDefinition(final String pkg) {
+        try {
+            super.checkPackageDefinition(pkg);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkSetFactory() {
+        try {
+            super.checkSetFactory();
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkMemberAccess(final Class<?> clazz, final int which) {
+        try {
+            super.checkMemberAccess(clazz, which);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+
+    public void checkSecurityAccess(final String target) {
+        try {
+            super.checkSecurityAccess(target);
+        } catch (SecurityException se) {
+            throw logged(se);
+        }
+    }
+}

Added: projects/jboss-threads/trunk/test-support/src/main/resources/testing.policy
===================================================================
--- projects/jboss-threads/trunk/test-support/src/main/resources/testing.policy	                        (rev 0)
+++ projects/jboss-threads/trunk/test-support/src/main/resources/testing.policy	2009-02-17 23:09:48 UTC (rev 84336)
@@ -0,0 +1,37 @@
+
+// Permissions to grant to modules
+
+grant codeBase "file:${build.home}/main/target/main/classes/-"
+{
+    permission java.lang.RuntimePermission "modifyThreadGroup";
+};
+
+// Permissions to run the main test suite
+
+grant codeBase "file:${build.home}/main/target/test/classes/-"
+{
+    permission java.lang.RuntimePermission "modifyThread";
+    permission java.lang.RuntimePermission "modifyThreadGroup";
+};
+
+// Support classes
+
+grant codeBase "file:${build.home}/test-support/target/main/classes/-"
+{
+    permission java.security.AllPermission;
+};
+
+grant codeBase "file:${idea.home}/lib/idea_rt.jar"
+{
+    permission java.security.AllPermission;
+};
+
+grant codeBase "file:${lib.junit.local}"
+{
+    permission java.security.AllPermission;
+};
+
+grant codeBase "file:${ant.library.dir}/-"
+{
+    permission java.security.AllPermission;
+};




More information about the jboss-cvs-commits mailing list