Browse Source

PSO Algorithm

Edgardo Palza 6 years ago
parent
commit
57c11100bf
100 changed files with 20056 additions and 0 deletions
  1. 502 0
      jars/jcommon-1.0.23/LICENSE
  2. 233 0
      jars/jcommon-1.0.23/README.md
  3. 54 0
      jars/jcommon-1.0.23/ant/build.properties
  4. 301 0
      jars/jcommon-1.0.23/ant/build.xml
  5. 28 0
      jars/jcommon-1.0.23/checkstyle/javadocs.xml
  6. 28 0
      jars/jcommon-1.0.23/checkstyle/lines.xml
  7. 6 0
      jars/jcommon-1.0.23/checkstyle/properties.txt
  8. 171 0
      jars/jcommon-1.0.23/checkstyle/style.xml
  9. 32 0
      jars/jcommon-1.0.23/checkstyle/whitespace.xml
  10. BIN
      jars/jcommon-1.0.23/jcommon-1.0.23.jar
  11. BIN
      jars/jcommon-1.0.23/jcommon-xml-1.0.23.jar
  12. BIN
      jars/jcommon-1.0.23/lib/junit.jar
  13. 260 0
      jars/jcommon-1.0.23/pom.xml
  14. 717 0
      jars/jcommon-1.0.23/src/main/java/com/keypoint/PngEncoder.java
  15. 6 0
      jars/jcommon-1.0.23/src/main/java/com/keypoint/package.html
  16. 81 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/JCommon.java
  17. 126 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/JCommonInfo.java
  18. 355 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/AbstractBoot.java
  19. 137 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/BaseBoot.java
  20. 288 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/BasicProjectInfo.java
  21. 179 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/BootableProjectInfo.java
  22. 83 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/ClassPathDebugger.java
  23. 202 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/Library.java
  24. 369 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/config/HierarchicalConfiguration.java
  25. 81 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/config/ModifiableConfiguration.java
  26. 141 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/config/PropertyFileConfiguration.java
  27. 131 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/config/SystemPropertyConfiguration.java
  28. 43 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/jcommon.properties
  29. 143 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/log/DefaultLog.java
  30. 103 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/log/DefaultLogModule.java
  31. 168 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/log/LogConfiguration.java
  32. 74 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/log/MemoryUsageMessage.java
  33. 93 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/log/PadMessage.java
  34. 14 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/log/module.properties
  35. 811 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/AbstractModule.java
  36. 260 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/DefaultModuleInfo.java
  37. 122 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/Module.java
  38. 88 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/ModuleInfo.java
  39. 85 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/ModuleInitializeException.java
  40. 64 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/ModuleInitializer.java
  41. 586 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/PackageManager.java
  42. 448 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/PackageSorter.java
  43. 263 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/PackageState.java
  44. 83 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/SubSystem.java
  45. 18 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/package.html
  46. 6 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/base/package.html
  47. 86 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/date/AnnualDateRule.java
  48. 100 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/date/DateUtilities.java
  49. 158 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/date/DayAndMonthRule.java
  50. 168 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/date/DayOfWeekInMonthRule.java
  51. 89 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/date/EasterSundayRule.java
  52. 91 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/date/MonthConstants.java
  53. 209 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/date/RelativeDayOfWeekRule.java
  54. 1035 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/date/SerialDate.java
  55. 388 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/date/SerialDateUtilities.java
  56. 461 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/date/SpreadsheetDate.java
  57. 6 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/date/package.html
  58. 78 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/demo/DateChooserPanelDemo.java
  59. 348 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/demo/DrawStringDemo.java
  60. 192 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/demo/DrawStringPanel.java
  61. 97 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/demo/TextBlockDemo.java
  62. 140 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/demo/TextBlockPanel.java
  63. 6 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/demo/package.html
  64. 103 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/io/FileUtilities.java
  65. 463 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/io/IOUtils.java
  66. 662 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/io/SerialUtilities.java
  67. 6 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/io/package.html
  68. 188 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/layout/CenterLayout.java
  69. 1045 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/layout/FormatLayout.java
  70. 278 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/layout/LCBLayout.java
  71. 311 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/layout/RadialLayout.java
  72. 6 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/layout/package.html
  73. 6 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/package.html
  74. 73 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/resources/JCommonResources.java
  75. 6 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/resources/package.html
  76. 88 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/text/G2TextMeasurer.java
  77. 353 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextBlock.java
  78. 192 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextBlockAnchor.java
  79. 448 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextBox.java
  80. 335 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextFragment.java
  81. 279 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextLine.java
  82. 64 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextMeasurer.java
  83. 853 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextUtilities.java
  84. 6 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/text/package.html
  85. 210 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/threads/ReaderWriterLock.java
  86. 6 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/threads/package.html
  87. 164 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/Align.java
  88. 135 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/ApplicationFrame.java
  89. 146 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/ArrowPanel.java
  90. 274 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/BevelArrowIcon.java
  91. 113 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/DateCellRenderer.java
  92. 553 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/DateChooserPanel.java
  93. 63 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/Drawable.java
  94. 191 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/DrawablePanel.java
  95. 68 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/ExtendedDrawable.java
  96. 105 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/ExtensionFileFilter.java
  97. 167 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/FilesystemFilter.java
  98. 209 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/FloatDimension.java
  99. 131 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/FloatingButtonEnabler.java
  100. 121 0
      jars/jcommon-1.0.23/src/main/java/org/jfree/ui/FontChooserDialog.java

+ 502 - 0
jars/jcommon-1.0.23/LICENSE

@@ -0,0 +1,502 @@
+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
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    JCommon class library (used by JFreeChart 1.0.x)
+    Copyright (C) 2013  David Gilbert
+
+    This library 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 library 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 library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  {signature of Ty Coon}, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!

+ 233 - 0
jars/jcommon-1.0.23/README.md

@@ -0,0 +1,233 @@
+THE JCOMMON CLASS LIBRARY: Version 1.0.23
+=========================================
+
+24 July 2014
+
+(C)opyright, 2000-2014, by Object Refinery Limited and Contributors.
+
+-----------------
+1.  INTRODUCTION
+-----------------
+JCommon is a free general purpose Java class library that is used in
+several projects including JFreeChart and Pentaho Reporting.
+
+*****
+SPECIAL NOTICE:  BOTH JFREECHART AND PENTAHO REPORTING ARE MOVING TOWARDS
+ELIMINATING THEIR DEPENDENCY ON JCOMMON.  AFTER THIS HAPPENS, JCOMMON WILL
+MOST LIKELY BE "RETIRED".
+*****
+
+JCommon is licensed, free of charge, under the terms of the GNU Lesser
+General Public Licence, version 2.1 or later.  A copy of the licence is 
+included in the download.
+
+The sources for this library are kept in a repo at GitHub:
+
+    https://github.com/jfree/jcommon
+
+If you have any comments, suggestions or bugs to report, please post a
+message in the JCommon forum.
+
+-----------------
+2.  CONTRIBUTORS
+-----------------
+Thanks to the following developers who have contributed code to this
+class library:  Anthony Boulestreau, Jeremy Bowman, J. David
+Eisenberg, Paul English, Brian Fischer, Hans-Jurgen Greiner, Martin Hoeller,
+Ryan Hirrlinger, Bill Kelemen, Arik Levin, Achilleus Mantzios, Thomas Meier,
+Thomas Morgner, Krzysztof Paz, Andrzej Porebski, Nabuo Tamemasa, Mark Watson
+and Hari.
+
+---------------
+3.  WHAT'S NEW
+---------------
+Changes in each version are listed here:
+
+1.0.23: (24-Jul-2014) Reorganised directories to align to Maven standard.
+                      Updated pom file.  Fixed Javadoc warnings for JDK 8.
+
+1.0.22: (28-Feb-2014) Fix for endless loop in TextUtilities.createTextBlock().
+
+1.0.21: (24-Oct-2013) Modified drawRotatedString() to call drawAlignedString()
+                      when the rotation angle is 0.0.  This provides benefits
+                      downstream for JFreeChart, JFreeSVG and OrsonPDF.
+
+1.0.20: (01-Sep-2013) Fixed TextFragment.draw() to respect TextAnchor argument.
+
+1.0.19: (30-Aug-2013) Updated Licences.java so that complete licence text is 
+                      loaded on demand only (bug #1118).
+
+1.0.18: (23-Sep-2012) Fixed PaintList.equals() bug, fixed line break issue in
+                      TextUtilities;
+
+1.0.17: (17-Oct-2011) Updated SerialUtilities to support serialisation of
+                      Composite instances;
+
+1.0.16: (17-Apr-2009) New release in conjunction with JFreeChart 1.0.13;
+
+1.0.15: (19-Dec-2008) New ResourceBundleWrapper class to enable applets to
+                      bypass codeBase lookup.  Updated Maven specs.
+
+1.0.14: (10-Sep-2008) Workaround added to PngEncoder, bug fix in ShapeList.
+
+1.0.13: (05-Jun-2008) Bug fixes for TextBox and ShapeUtilities.
+
+1.0.12: (02-Nov-2007) Made the resource-loading and classloader selection more
+        robust in cases where the jars were distributed over several
+        classloaders.
+
+1.0.11: (19-Oct-2007) BugFix in the KeyedComboBoxModel causing
+        NullPointerExceptions on MacOS-X; Make sure that all resource-streams
+        that get opened also get safely closed in case of errors.
+
+1.0.10: (21-May-2007) BugFix in the PackageSorter, Window positioning is now
+        multi-screen aware.
+
+1.0.9 : (23-Mar-2007) Serialization fix in TextFragment.
+
+1.0.8 : (11-Dec-2006) Minor bugfixes in the synchronization of the Booting code
+        and the FastStack.
+
+1.0.7 : (03-Dec-2006) Cosmetic fixes for the logging of the PackageManager,
+        ObjectTable implementation allows faster cloning of its contents,
+        minor improvements to the GUI classes.
+
+1.0.6 : (26-Sep-2006) BugFixes in the TextLayoutUtilities, SpreadSheetDate and
+        ResourceBundleSupport classes.
+
+1.0.5 : (29-Jun-2006) BugFixes in the boot code (synchronization added) and
+        WaitingImageObserver (possible deadlock fixed). ObjectUtilities
+		did not handle all cases where a ClassLoader could be null.
+
+1.0.4 : (30-Apr-2006) Date- and NumberCellRenderer did not handle null-values
+        properly.
+
+1.0.3 : (17-Apr-2006) More improvements in the boot process for dependent
+        library hierarchies.
+
+1.0.1 : (10-Feb-2006) This release adds new boot capabilities and fixes
+        some bugs in the XML classes. This version is required for
+        JFreeReport and it is fully backward compatible with the 1.0.x
+        branch.
+
+1.0.0 : (14-Nov-2005) This is the official 1.0.0 release.  All future
+        releases in the 1.0.x series will maintain backward compatibility
+        with the 1.0.0 API.
+
+1.0.0-rc1 : (01-Jun-2005) : Update to coincide with JFreeReport 0.8.5-5.
+        JavaDoc update and classloader handling changed.
+
+1.0.0-pre3 : (15-Apr-2005) : Some minor changes in the ResourceBundleSupport
+        to allow the explicit definition of a locale.
+
+1.0.0-pre2 : (04-Mar-2005) : Update to coincide with JFreeReport 0.8.5.
+        Separated the xml-support packages into an own jar file.
+        JFreeChart does not use these classes (except in experimental
+        non-release code). Therefore, JFreeChart needs both libs to
+        build, but only the jcommon.jar library to run.
+
+        The a more detailed list of changed please have a look at the
+        CHANGELOG.txt file.
+
+1.0.0-pre1 : (29-Nov-2004) : Update to coincide with JFreeChart 1.0.0-pre1.
+
+0.9.7 : (13-Oct-2004) Update to join JFreeReport with latest JFreeChart.
+
+0.9.6 : (10-Sep-2004) Update to coincide with JFreeChart 0.9.21.
+
+0.9.5 : (7-Jun-2004) Update to coincide with JFreeChart 0.9.20.
+
+0.9.4 : (28-May-2004) Update to coincide with JFreeChart 0.9.19.
+
+0.9.3 : (15-Apr-2004) Update to coincide with JFreeChart 0.9.18.
+
+0.9.2 : (26-Mar-2004) Update to coincide with JFreeChart 0.9.17.
+
+0.9.1 : (9-Jan-2004) Update to coincide with JFreeChart 0.9.16.
+
+0.9.0 : (28-Nov-2003) Update to coincide with JFreeChart 0.9.15.
+
+0.8.9 : (17-Nov-2003) Update to coincide with JFreeChart 0.9.14.
+
+0.8.8 : (26-Sep-2003) Update to coincide with JFreeChart 0.9.13.
+
+0.8.7 : (11-Sep-2003) Update to coincide with JFreeChart 0.9.12.
+
+0.8.6 : (8-Aug-2003) Update to coincide with JFreeChart 0.9.11.
+
+0.8.5 : (25-Jul-2003) Transferred some support classes from JFreeChart.
+
+0.8.3 : (16-Jun-2003) XML Parser: error locations are printed in the
+        parse exceptions to make debugging xml files easier.
+
+0.8.2a: (04-Jun-2003) xml parser: configuration interface modified.
+	+ Bugfixes ...
+
+0.8.2 : (26-May-2003) xml parser class factory bug fix
+
+0.8.1 : (09-May-2003) Added support for the xml parser and imported
+        some base classes from the JFreeReport project.
+
+0.8.0 : (24-Apr-2003) Renamed all packages from com.jrefinery.*
+        to org.jfree.*.
+
+0.7.3 : (11-Apr-2003) Added serialization for SerialDate and
+        SpreadsheetDate classes.  Added a SerialUtilities class.
+        Removed palette classes (now in JFreeChart).  Added an
+        attribute to control whether or not a workaround is used for
+        drawing rotated text.
+
+0.7.2 : (6-Feb-2003) Bug fixes and Javadoc updates, incorporated an
+        Ant script to recompile the source files and generate the
+        Javadocs.
+
+0.7.1 : (18-Oct-2002) Bug fixes and Javadoc updates.
+
+0.7.0 : (4-Sep-2002) Moved package (com.jrefinery.data) to JFreeChart
+        project. Bug fixes and Javadoc updates.
+
+0.6.4 : (27-Jun-2002) Added logo to about box. Minor bug fixes (plus
+        JUnit tests) and code tidy up.
+
+0.6.3 : (14-Jun-2002) Bug fixes and Javadoc updates.
+
+0.6.2 : (7-Jun-2002) Added GanttSeriesCollection and supporting
+        classes.  Added Polish resource bundle.  Minor bug fixes.
+
+0.6.1 : (5-Apr-2002) Added MeterDataset interface and
+        DefaultMeterDataset class. Resource bundles for French, German
+        and Spanish languages. Reinstated the Week class.  Minor bugfixes.
+
+0.6.0 : (22-Mar-2002) Changes to the API for the TimePeriod classes,
+        to improve methods that convert to java.util.Date.  New
+        DefaultHighLowDataset class.  New ResourceBundles for items
+        that require localisation.
+
+0.5.6 : (6-Mar-2002) Bug fix for combined datasets.  Additional
+        methods in the TimePeriod class to handle different
+        timezones. Updated About box classes moved to new package
+        com.jrefinery.ui.about.  Renamed Files.java -->
+        FileUtilities.java and SerialDates.java -->
+        SerialDateUtilities.java.  Added new domain name
+        (http://www.object-refinery.com) in the source headers.
+
+0.5.5 : (15-Feb-2002) Fixed bugs in the constructors for the
+        TimePeriod subclasses.  Reversed the order of the parameters
+        in the Month(int, int) constructor.  Added methods to
+        Datasets.java to handle stacked data ranges.  Fixed bug in
+        CombinedDataset.
+
+0.5.4 : (8-Feb-2002) New WindDataset interface and DefaultWindDataset
+        class.  Bug fix for DefaultCategoryDataset.
+
+0.5.3 : (25-Jan-2002) Bug fixes, some minor API changes.
+
+0.5.2 : (10-Dec-2001) Added new combination datasets by Bill Kelemen.
+        Added contributors table to the AboutFrame class.
+
+0.5.1 : (27-Nov-2001) AboutPanel and AboutFrame classes added.
+
+0.5.0 : (21-Nov-2001) PieDataset and DefaultPieDataset classes added.
+
+0.4.2 : (16-Nov-2001) New classes in the com.jrefinery.data.* package,
+        plus some new JUnit test cases.

+ 54 - 0
jars/jcommon-1.0.23/ant/build.properties

@@ -0,0 +1,54 @@
+###########################################################
+#
+#  Global settings ...
+jcommon.name=jcommon
+jcommon.version=1.0.23
+
+#
+# This defines the compiler settings. Optimizing would remove
+# the debug information, so we dont do that. This may be selfish,
+# but these settings guarantee better bug-reports :)
+build.debug=true
+build.optimize=false
+build.deprecation=true
+
+#
+# Make sure that JDK 1.6 compatible class files are generated
+build.target=1.6
+build.source=1.6
+
+#
+# All path settings are relative to the project root directory
+# (..)
+#
+libdir=lib
+junit-dir=lib
+
+#
+# If you specify a non-empty string, then dont forget the
+# trailing / here or your results wont fit your expectations...
+#
+targetdir=
+manifest-lib-prefix=lib/
+
+###########################################################
+#
+#  Used libraries ...
+
+# Used by: core libraries
+
+# Used by: module-misc-beanshell
+jaxp-jar-file=gnujaxp.jar
+servlet-jar-file=servlet.jar
+
+junit-jar-file=junit.jar
+
+
+##############################################################
+#
+# Generated files ...
+jcommon-jar-file=${jcommon.name}-${jcommon.version}.jar
+jcommon-bundle-file=${jcommon.name}-${jcommon.version}-bundle.jar
+jcommon-junit-jar-file=${jcommon.name}-${jcommon.version}-junit.jar
+jcommon-xml-jar-file=${jcommon.name}-xml-${jcommon.version}.jar
+jcommon-xml-bundle-file=${jcommon.name}-xml-${jcommon.version}-bundle.jar

+ 301 - 0
jars/jcommon-1.0.23/ant/build.xml

@@ -0,0 +1,301 @@
+<!-- An ANT build file for JCommon. -->
+
+<!-- Written by David Gilbert. -->
+<!-- 24-Jan-2003 -->
+
+<!-- This script has been tested with Ant version 1.8.2. -->
+
+<!-- Several temporary directories are created while the script is -->
+<!-- running: "../build" and "../distribution".  -->
+
+<!-- A "../javadoc" directory will be created for the Javadoc -->
+<!-- HTML pages. -->
+
+<!-- The script should work for the distribution and also the CVS -->
+<!-- repository (which is shared with the JFreeChart project in a -->
+<!-- slightly messy way). -->
+
+<project name="jcommon" default="all" basedir="..">
+
+  <!-- Initialisation. -->
+  <target name="initialise" description="Initialise required settings.">
+    <tstamp/>
+
+    <property name="builddir" value="build"/>
+
+    <dirname property="antfile.dir" file="${ant.file}"/>
+    <property file="${antfile.dir}/build.properties"/>
+
+    <path id="build-xml.classpath">
+      <pathelement location="${libdir}/${jaxp-jar-file}"/>
+      <pathelement location="${jcommon-jar-file}"/>
+    </path>
+
+    <path id="junit.classpath">
+      <pathelement location="${jcommon-jar-file}"/>
+      <pathelement location="${lib}/${jaxp-jar-file}"/>
+      <pathelement location="${junit-dir}/${junit-jar-file}"/>
+    </path>
+  </target>
+
+  <!-- Compile the JCommon classes -->
+  <target name="compile" depends="initialise"
+    description="Compile the JCommon source code.">
+
+    <!-- create a temp build directory -->
+    <mkdir dir="${builddir}"/>
+
+    <!-- compile the source -->
+    <javac srcdir="src/main/java"
+      destdir="${builddir}"
+      deprecation="${build.deprecation}" debug="${build.debug}"
+      optimize="${build.optimize}" target="${build.target}" source="${build.source}">
+      <include name="org/jfree/*"/>
+      <include name="org/jfree/base/**"/>
+      <include name="org/jfree/date/*"/>
+      <include name="org/jfree/io/*"/>
+      <include name="org/jfree/layout/*"/>
+      <include name="org/jfree/resources/*"/>
+      <include name="org/jfree/text/*"/>
+      <include name="org/jfree/threads/*"/>
+      <include name="org/jfree/ui/*"/>
+      <include name="org/jfree/ui/action/*"/>
+      <include name="org/jfree/ui/tabbedui/*"/>
+      <include name="org/jfree/ui/about/*"/>
+      <include name="org/jfree/ui/about/resources/*"/>
+      <include name="org/jfree/util/*"/>
+      <include name="com/keypoint/*"/>
+    </javac>
+
+    <!-- copy across .properties files -->
+    <copy todir="${builddir}/org/jfree/ui/">
+      <fileset dir="src/main/java/org/jfree/ui">
+        <include name="*.properties"/>
+      </fileset>
+    </copy>
+
+    <copy todir="${builddir}/org/jfree/ui/about/">
+      <fileset dir="src/main/java/org/jfree/ui/about">
+        <include name="*.txt"/>
+      </fileset>
+    </copy>
+
+    <!-- copy across .properties files -->
+    <copy todir="${builddir}/org/jfree/base/">
+      <fileset dir="src/main/java/org/jfree/base">
+        <include name="*.properties"/>
+      </fileset>
+    </copy>
+
+    <copy todir="${builddir}/org/jfree/base/log">
+      <fileset dir="src/main/java/org/jfree/base/log">
+        <include name="*.properties"/>
+      </fileset>
+    </copy>
+
+    <!-- make the jar -->
+    <jar jarfile="${jcommon-jar-file}" basedir="${builddir}"/>
+
+    <!-- delete the temp directory -->
+    <delete dir="${builddir}"/>
+
+  </target>
+
+
+  <!-- Compile the JCommon classes -->
+  <target name="compile-xml" depends="compile"
+    description="Compile the JCommon source code.">
+
+    <!-- create a temp build directory -->
+    <mkdir dir="${builddir}"/>
+
+    <!-- compile the source -->
+    <javac srcdir="src/main/java"
+      destdir="${builddir}"
+      deprecation="${build.deprecation}" debug="${build.debug}"
+      optimize="${build.optimize}" target="${build.target}" source="${build.source}">
+      <classpath refid="build-xml.classpath" />
+      <include name="org/jfree/xml/**"/>
+    </javac>
+
+    <!-- copy across .properties files -->
+    <copy todir="${builddir}/org/jfree/xml/">
+      <fileset dir="src/main/java/org/jfree/xml">
+        <include name="*.properties"/>
+        <include name="*.dtd"/>
+      </fileset>
+    </copy>
+
+
+    <!-- make the jar -->
+    <jar jarfile="${jcommon-xml-jar-file}" basedir="${builddir}"/>
+
+    <!-- delete the temp directory -->
+    <delete dir="${builddir}"/>
+
+  </target>
+
+  <!-- Generate the JCommon JavaDoc HTML pages -->
+  <target name="javadoc" depends="initialise">
+    <delete dir="javadoc"/>
+    <mkdir dir="javadoc"/>
+    <javadoc destdir="javadoc"
+      windowtitle="JCommon Class Library (version ${jcommon.version})"
+      overview="src/main/java/overview.html"
+      linksource="true">
+      <classpath refid="build-xml.classpath"/>
+      <packageset dir="src/main/java" defaultexcludes="yes">
+        <include name="org/jfree"/>
+        <include name="org/jfree/base"/>
+        <include name="org/jfree/date"/>
+        <include name="org/jfree/io"/>
+        <include name="org/jfree/layout"/>
+        <include name="org/jfree/resources"/>
+        <include name="org/jfree/text"/>
+        <include name="org/jfree/threads"/>
+        <include name="org/jfree/ui"/>
+        <include name="org/jfree/ui/action"/>
+        <include name="org/jfree/ui/tabbedui"/>
+        <include name="org/jfree/ui/about"/>
+        <include name="org/jfree/ui/about/resources"/>
+        <include name="org/jfree/util"/>
+        <include name="com/keypoint"/>
+        <include name="org/jfree/xml/**"/>
+      </packageset>
+    </javadoc>
+  </target>
+
+  <target name="fill-dist-dir">
+    <!-- copy across README -->
+    <copy file="README.md"
+      tofile="distribution/README.md" failonerror="false"/>
+
+    <!-- copy across LICENCE -->
+    <copy file="LICENSE"
+      tofile="distribution/LICENSE"/>
+
+    <!-- copy across runtime jar file -->
+    <copy file="${jcommon-jar-file}"
+      tofile="distribution/${jcommon-jar-file}"/>
+
+    <!-- copy across jcommon-xml jar file -->
+    <copy file="${jcommon-xml-jar-file}"
+      tofile="distribution/${jcommon-xml-jar-file}"/>
+
+    <!-- copy across maven xml files -->
+    <copy file="pom.xml" tofile="distribution/pom.xml"/>
+
+    <!-- copy across junit jar file -->
+    <copy file="${junit-dir}/${junit-jar-file}" tofile="distribution/lib/junit.jar"/>
+
+    <!-- copy across source files -->
+    <copy todir="distribution/src">
+      <fileset dir="src"/>
+    </copy>
+
+    <!-- copy across ant build file (this file) -->
+    <copy file="ant/build.xml"
+      tofile="distribution/ant/build.xml" failonerror="false"/>
+
+    <copy file="ant/build.properties"
+      tofile="distribution/ant/build.properties"/>
+
+    <!-- copy across checkstyle property file -->
+    <copy todir="distribution/checkstyle">
+      <fileset dir="checkstyle"/>
+    </copy>
+  </target>
+
+  <!-- Make .zip distribution for JCommon -->
+  <target name="zip" depends="compile-xml">
+
+    <!-- make a temporary distribution directory -->
+    <mkdir dir="distribution"/>
+
+    <antcall target="fill-dist-dir"/>
+
+    <!-- convert end-of-line characters in text files -->
+    <fixcrlf srcdir="distribution/src"
+      eol="crlf" eof="remove"/>
+
+    <!-- make the zip file -->
+    <zip zipfile="${jcommon.name}-${jcommon.version}.zip">
+      <zipfileset dir="distribution"
+        prefix="${jcommon.name}-${jcommon.version}"/>
+    </zip>
+
+    <!-- delete the temporary distribution directory -->
+    <delete dir="distribution"/>
+
+  </target>
+
+  <!-- Make .tar.gz distribution for JCommon -->
+  <target name="targz" depends="compile-xml">
+
+    <!-- make a temporary distribution directory -->
+    <mkdir dir="distribution"/>
+
+    <antcall target="fill-dist-dir"/>
+
+    <!-- convert end-of-line characters in text files -->
+    <fixcrlf srcdir="distribution/src"
+      eol="lf" eof="remove"/>
+
+    <!-- make the tar.gz file -->
+    <tar tarfile="${jcommon.name}-${jcommon.version}.tar">
+      <tarfileset dir="distribution"
+        prefix="${jcommon.name}-${jcommon.version}"/>
+    </tar>
+    <gzip zipfile="${jcommon.name}-${jcommon.version}.tar.gz"
+      src="${jcommon.name}-${jcommon.version}.tar"/>
+    <delete file="${jcommon.name}-${jcommon.version}.tar"/>
+
+    <!-- delete the temporary distribution directory -->
+    <delete dir="distribution"/>
+
+  </target>
+
+  <target name="maven-bundle" depends="zip" >
+    <!-- make a temporary distribution directory -->
+    <mkdir dir="distribution"/>
+    <!-- copy across LICENCE -->
+    <copy file="LICENSE" tofile="distribution/LICENSE"/>
+    
+    <filterchain id="version.filters">
+       <replacetokens>
+         <token key="VERSION" value="${jcommon.version}"/>
+       </replacetokens>
+    </filterchain>
+    
+    <!-- copy across runtime jar file -->
+    <copy file="${jcommon-jar-file}" tofile="distribution/${jcommon-jar-file}"/>
+
+    <!-- make the jar -->
+    <jar jarfile="${jcommon-bundle-file}" basedir="distribution"/>
+
+    <!-- delete the temporary distribution directory -->
+    <delete dir="distribution"/>
+
+    <!-- make a temporary distribution directory -->
+    <mkdir dir="distribution"/>
+    <!-- copy across LICENCE -->
+    <copy file="LICENSE" tofile="distribution/LICENSE"/>
+
+    <!-- copy across runtime jar file -->
+    <copy file="${jcommon-xml-jar-file}" tofile="distribution/${jcommon-xml-jar-file}"/>
+
+    <!-- make the jar -->
+    <jar jarfile="${jcommon-xml-bundle-file}" basedir="distribution"/>
+
+    <!-- delete the temporary distribution directory -->
+    <delete dir="distribution"/>
+  </target>
+
+
+  <!-- ALL -->
+  <target name="all"
+    depends="compile,compile-xml,javadoc,zip,targz,maven-bundle"
+    description="Compiles JCommon, builds the jar files, generates the Javadoc HTML pages and creates distribution files (.zip and .tar.gz).">
+  </target>
+
+</project>

+ 28 - 0
jars/jcommon-1.0.23/checkstyle/javadocs.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+    "-//Puppy Crawl//DTD Check Configuration 1.1//EN"
+    "http://www.puppycrawl.com/dtds/configuration_1_1.dtd">
+
+<!--
+
+  Checkstyle configuration for checking Javadocs
+ 
+-->
+
+<module name="Checker">
+
+    <!-- Checks that a package.html file exists for each package.     -->
+    <!-- See http://checkstyle.sf.net/config_javadoc.html#PackageHtml -->
+    <module name="PackageHtml"/>
+
+    <module name="TreeWalker">
+
+        <!-- Checks for Javadoc comments.                     -->
+        <!-- See http://checkstyle.sf.net/config_javadoc.html -->
+        <module name="JavadocMethod"/>
+        <module name="JavadocType"/>
+        <module name="JavadocVariable"/>
+
+    </module>
+
+</module>

+ 28 - 0
jars/jcommon-1.0.23/checkstyle/lines.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+    "-//Puppy Crawl//DTD Check Configuration 1.1//EN"
+    "http://www.puppycrawl.com/dtds/configuration_1_1.dtd">
+
+<!--
+  Just the whitespace checks...
+-->
+
+<module name="Checker">
+
+
+    <!-- Checks whether files end with a new line.                        -->
+    <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
+    <!-- <module name="NewlineAtEndOfFile"/> -->
+
+    <module name="TreeWalker">
+
+        <!-- Checks for Size Violations.                    -->
+        <!-- See http://checkstyle.sf.net/config_sizes.html -->
+        <module name="LineLength">
+            <property name="max" value="100"/>
+        </module>
+
+
+    </module>
+
+</module>

+ 6 - 0
jars/jcommon-1.0.23/checkstyle/properties.txt

@@ -0,0 +1,6 @@
+checkstyle.allow.tabs no
+checkstyle.maxlinelen 100
+checkstyle.maxparameters 20
+checkstyle.rcurly alone
+checkstyle.ignore.public.in.interface yes
+checkstyle.javadoc.checkUnusedThrows yes

+ 171 - 0
jars/jcommon-1.0.23/checkstyle/style.xml

@@ -0,0 +1,171 @@
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+    "-//Puppy Crawl//DTD Check Configuration 1.1//EN"
+    "http://www.puppycrawl.com/dtds/configuration_1_1.dtd">
+
+<!--
+
+  Checkstyle configuration that checks the sun coding conventions from:
+
+    - the Java Language Specification at
+      http://java.sun.com/docs/bookstore/jls/second_edition/html/index.html
+
+    - the Sun Code Conventions at http://java.sun.com/docs/codeconv/
+
+    - the Javadoc guidelines at
+      http://java.sun.com/j2se/javadoc/writingdoccomments/index.html
+
+    - the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html
+
+    - some best practices
+
+  Checkstyle is very configurable. Be sure to read the documentation at
+  http://checkstyle.sf.net (or in your downloaded distribution).
+
+  Most Checks are configurable, be sure to consult the documentation.
+
+  To completely disable a check, just comment it out or delete it from the file.
+
+  Finally, it is worth reading the documentation.
+
+-->
+
+<module name="Checker">
+
+    <!-- Checks that a package.html file exists for each package.     -->
+    <!-- See http://checkstyle.sf.net/config_javadoc.html#PackageHtml -->
+    <module name="PackageHtml"/>
+
+    <!-- Checks whether files end with a new line.                        -->
+    <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
+    <!-- <module name="NewlineAtEndOfFile"/> -->
+
+    <!-- Checks that property files contain the same keys.         -->
+    <!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
+    <module name="Translation"/>
+
+
+    <module name="TreeWalker">
+
+        <!-- Checks for Javadoc comments.                     -->
+        <!-- See http://checkstyle.sf.net/config_javadoc.html -->
+        <module name="JavadocMethod"/>
+        <module name="JavadocType"/>
+        <module name="JavadocVariable"/>
+
+
+        <!-- Checks for Naming Conventions.                  -->
+        <!-- See http://checkstyle.sf.net/config_naming.html -->
+        <module name="ConstantName"/>
+        <module name="LocalFinalVariableName"/>
+        <module name="LocalVariableName"/>
+        <module name="MemberName"/>
+        <module name="MethodName"/>
+        <module name="PackageName"/>
+        <module name="ParameterName"/>
+        <module name="StaticVariableName"/>
+        <module name="TypeName"/>
+
+
+        <!-- Checks for Headers                              -->
+        <!-- See http://checkstyle.sf.net/config_header.html -->
+ <!--       <module name="Header"> -->
+            <!-- The follow property value demonstrates the ability     -->
+            <!-- to have access to ANT properties. In this case it uses -->
+            <!-- the ${basedir} property to allow Checkstyle to be run  -->
+            <!-- from any directory within a project.                   -->
+<!--            <property name="headerFile" value="${basedir}/java.header"/> -->
+<!--        </module> -->
+
+        <!-- Following interprets the header file as regular expressions. -->
+        <!-- <module name="RegexpHeader"/>                                -->
+
+
+        <!-- Checks for imports                              -->
+        <!-- See http://checkstyle.sf.net/config_import.html -->
+        <module name="AvoidStarImport"/>
+        <module name="IllegalImport"/> <!-- defaults to sun.* packages -->
+        <module name="RedundantImport"/>
+        <module name="UnusedImports"/>
+
+
+        <!-- Checks for Size Violations.                    -->
+        <!-- See http://checkstyle.sf.net/config_sizes.html -->
+        <!-- <module name="FileLength"/>  -->
+        <module name="LineLength">
+            <property name="max" value="100"/>
+        </module>
+        <!-- <module name="MethodLength"/> -->
+        <module name="ParameterNumber">
+            <property name="max" value="12"/>
+        </module>
+
+        <!-- Checks for whitespace                               -->
+        <!-- See http://checkstyle.sf.net/config_whitespace.html -->
+        <module name="EmptyForIteratorPad"/>
+        <module name="NoWhitespaceAfter"/>
+        <module name="NoWhitespaceBefore"/>
+        <module name="OperatorWrap"/>
+        <module name="ParenPad"/>
+        <module name="TabCharacter"/>
+        <module name="WhitespaceAfter"/>
+        <module name="WhitespaceAround"/>
+
+
+        <!-- Modifier Checks                                    -->
+        <!-- See http://checkstyle.sf.net/config_modifiers.html -->
+        <module name="ModifierOrder"/>
+        <!-- <module name="RedundantModifier"/> -->
+
+
+        <!-- Checks for blocks. You know, those {}'s         -->
+        <!-- See http://checkstyle.sf.net/config_blocks.html -->
+        <module name="AvoidNestedBlocks"/>
+        <module name="EmptyBlock"/>
+        <module name="LeftCurly"/>
+        <module name="NeedBraces"/>
+        <module name="RightCurly">
+            <property name="option" value="alone"/>
+        </module>
+
+
+        <!-- Checks for common coding problems               -->
+        <!-- See http://checkstyle.sf.net/config_coding.html -->
+<!--        <module name="AvoidInlineConditionals"/> -->
+        <module name="DoubleCheckedLocking"/>    <!-- MY FAVOURITE -->
+        <module name="EmptyStatement"/>
+<!--        <module name="EqualsHashCode"/> -->
+        <module name="HiddenField">
+            <property name="tokens" value="VARIABLE_DEF"/>
+        </module>
+        <module name="IllegalInstantiation"/>
+        <module name="InnerAssignment"/>
+        <!-- <module name="MagicNumber"/> -->
+        <module name="MissingSwitchDefault"/>
+        <module name="RedundantThrows"/>
+        <module name="SimplifyBooleanExpression"/>
+        <module name="SimplifyBooleanReturn"/>
+
+        <!-- Checks for class design                         -->
+        <!-- See http://checkstyle.sf.net/config_design.html -->
+        <!--<module name="DesignForExtension"/> -->
+        <module name="FinalClass"/>
+        <module name="HideUtilityClassConstructor"/>
+        <module name="InterfaceIsType"/>
+        <module name="VisibilityModifier"/>
+
+
+        <!-- Miscellaneous other checks.                   -->
+        <!-- See http://checkstyle.sf.net/config_misc.html -->
+        <module name="ArrayTypeStyle"/>
+        <!-- <module name="FinalParameters"/> -->
+<!--        <module name="GenericIllegalRegexp"> -->
+<!--            <property name="format" value="\s+$"/> -->
+<!--            <property name="message" value="Line has trailing spaces."/> -->
+<!--        </module> -->
+        <module name="TodoComment"/>
+        <module name="UpperEll"/>
+
+    </module>
+
+</module>

+ 32 - 0
jars/jcommon-1.0.23/checkstyle/whitespace.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+    "-//Puppy Crawl//DTD Check Configuration 1.1//EN"
+    "http://www.puppycrawl.com/dtds/configuration_1_1.dtd">
+
+<!--
+  Just the whitespace checks...
+-->
+
+<module name="Checker">
+
+
+    <!-- Checks whether files end with a new line.                        -->
+    <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
+    <!-- <module name="NewlineAtEndOfFile"/> -->
+
+    <module name="TreeWalker">
+
+        <!-- Checks for whitespace                               -->
+        <!-- See http://checkstyle.sf.net/config_whitespace.html -->
+        <module name="EmptyForIteratorPad"/>
+        <module name="NoWhitespaceAfter"/>
+        <module name="NoWhitespaceBefore"/>
+        <module name="OperatorWrap"/>
+        <module name="ParenPad"/>
+        <module name="TabCharacter"/>
+        <module name="WhitespaceAfter"/>
+        <module name="WhitespaceAround"/>
+
+    </module>
+
+</module>

BIN
jars/jcommon-1.0.23/jcommon-1.0.23.jar


BIN
jars/jcommon-1.0.23/jcommon-xml-1.0.23.jar


BIN
jars/jcommon-1.0.23/lib/junit.jar


+ 260 - 0
jars/jcommon-1.0.23/pom.xml

@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <name>JCommon</name>
+
+    <artifactId>jcommon</artifactId>
+    <groupId>org.jfree</groupId>
+    <version>1.0.23</version>
+    <packaging>jar</packaging>
+
+    <!-- this is required to host it on Sonatype's OSSRH -->
+    <parent>
+        <groupId>org.sonatype.oss</groupId>
+        <artifactId>oss-parent</artifactId>
+        <version>9</version>
+    </parent>
+
+    <organization>
+        <name>JFree.org</name>
+        <url>http://www.jfree.org/</url>
+    </organization>
+    <inceptionYear>2001</inceptionYear>
+
+    <description>
+    JCommon is a free general purpose Java class library that is used in
+    several projects at www.jfree.org, including JFreeChart and
+    JFreeReport.
+    </description>
+
+    <url>http://www.jfree.org/jcommon/</url>
+    <issueManagement>
+        <url>http://sourceforge.net/tracker/?group_id=15494</url>
+    </issueManagement>
+    <scm>
+        <connection>scm:cvs:pserver:anonymous@cvs.sourceforge.net:/cvsroot/jfreechart:jcommon</connection>
+        <url>http://cvs.sourceforge.net/viewcvs.py/jfreechart/jcommon</url>
+    </scm>
+
+    <mailingLists>
+        <mailingList>
+            <name>JFreeChart Developer List</name>
+            <subscribe>
+        jfreechart-dev-request@lists.sourceforge.net?subject=subscribe
+            </subscribe>
+            <unsubscribe>
+        jfreechart-dev-request@lists.sourceforge.net?subject=unsubscribe
+            </unsubscribe>
+            <archive>
+        http://sourceforge.net/mailarchive/forum.php?forum=jfreechart-dev
+            </archive>
+        </mailingList>
+    </mailingLists>
+
+    <developers>
+    <!--
+    For an up to date list of developers and contributors have a look at
+    the project info implementations.
+    -->
+    </developers>
+    <licenses>
+        <license>
+            <name>GNU Lesser General Public Licence</name>
+            <url>http://www.gnu.org/licenses/lgpl.txt</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>3.8.2</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <distributionManagement>
+      <snapshotRepository>
+        <id>ossrh</id>
+        <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+      </snapshotRepository>
+    </distributionManagement>    
+    
+    <build>
+        <sourceDirectory>src/main/java</sourceDirectory>
+        <testSourceDirectory>src/test/java</testSourceDirectory>
+
+        <resources>
+            <resource>
+                <directory>src/main/java</directory>
+                <includes>
+                    <include>**/*.properties</include>
+                    <include>**/*.txt</include>
+                    <include>**/*.</include>
+                </includes>
+            </resource>
+        </resources>
+
+        <plugins>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>${project.source.level}</source>
+                    <target>${project.target.level}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                    <excludes>
+                      <exclude>org/jfree/demo/**</exclude>
+                      <exclude>org/jfree/xml/**</exclude>
+                    </excludes>                
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.10</version>
+                <configuration>
+                    <excludes>
+                        <exclude>**/JCommonTestSuite.java</exclude>
+                        <exclude>**/*PackageTests.java</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>2.6</version>
+                <configuration>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+
+            <plugin>
+              <groupId>org.apache.maven.plugins</groupId>
+              <artifactId>maven-gpg-plugin</artifactId>
+              <version>1.5</version>
+              <executions>
+                <execution>
+                  <id>sign-artifacts</id>
+                  <phase>verify</phase>
+                  <goals>
+                    <goal>sign</goal>
+                  </goals>
+                </execution>
+              </executions>
+            </plugin>
+
+            <plugin>
+              <groupId>org.sonatype.plugins</groupId>
+              <artifactId>nexus-staging-maven-plugin</artifactId>
+              <version>1.6.2</version>
+              <extensions>true</extensions>
+              <configuration>
+                <serverId>ossrh</serverId>
+                <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+                <autoReleaseAfterClose>false</autoReleaseAfterClose>
+              </configuration>
+            </plugin>            
+
+            <plugin>
+              <groupId>org.codehaus.mojo</groupId>
+              <artifactId>cobertura-maven-plugin</artifactId>
+              <version>2.5.1</version>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-site-plugin</artifactId>
+                <version>3.4</version>
+            </plugin>
+        </plugins>
+    </build>
+
+    <reporting>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>2.9.1</version>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-report-plugin</artifactId>
+                <version>2.8</version>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jxr-plugin</artifactId>
+                <version>2.3</version>
+            </plugin>
+
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>cobertura-maven-plugin</artifactId>
+                <version>2.5.1</version>
+            </plugin>
+        </plugins>
+    </reporting>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.source.level>1.6</project.source.level>
+        <project.target.level>1.6</project.target.level>
+    </properties>
+    
+  <profiles>
+    <profile> 
+      <id>release</id>
+      <build>
+        <plugins>
+          <plugin>
+            <inherited>true</inherited>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <version>2.9.1</version>
+            <executions>
+              <execution>
+                <id>attach-javadoc</id>
+                <goals>
+                  <goal>jar</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <sourceFileExcludes>
+                <exclude>org/jfree/demo/**</exclude>
+                <exclude>org/jfree/xml/**</exclude>
+              </sourceFileExcludes>
+            </configuration>
+          </plugin>
+
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-source-plugin</artifactId>
+            <version>2.2.1</version>
+            <executions>
+              <execution>
+                <id>attach-sources</id>
+                <goals>
+                  <goal>jar-no-fork</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>

+ 717 - 0
jars/jcommon-1.0.23/src/main/java/com/keypoint/PngEncoder.java

@@ -0,0 +1,717 @@
+package com.keypoint;
+
+import java.awt.Image;
+import java.awt.image.ImageObserver;
+import java.awt.image.PixelGrabber;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.zip.CRC32;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+
+/**
+ * PngEncoder takes a Java Image object and creates a byte string which can be
+ * saved as a PNG file.  The Image is presumed to use the DirectColorModel.
+ *
+ * <p>Thanks to Jay Denny at KeyPoint Software
+ *    http://www.keypoint.com/
+ * who let me develop this code on company time.</p>
+ *
+ * <p>You may contact me with (probably very-much-needed) improvements,
+ * comments, and bug fixes at:</p>
+ *
+ *   <p><code>david@catcode.com</code></p>
+ *
+ * <p>This library 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.</p>
+ *
+ * <p>This library 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.</p>
+ *
+ * <p>You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA. A copy of the GNU LGPL may be found at
+ * <code>http://www.gnu.org/copyleft/lesser.html</code></p>
+ *
+ * @author J. David Eisenberg
+ * @version 1.5, 19 Oct 2003
+ *
+ * CHANGES:
+ * --------
+ * 19-Nov-2002 : CODING STYLE CHANGES ONLY (by David Gilbert for Object
+ *               Refinery Limited);
+ * 19-Sep-2003 : Fix for platforms using EBCDIC (contributed by Paulo Soares);
+ * 19-Oct-2003 : Change private fields to protected fields so that
+ *               PngEncoderB can inherit them (JDE)
+ *               Fixed bug with calculation of nRows
+ * 15-Aug-2008 : Added scrunch.end() in writeImageData() method - see
+ *               JFreeChart bug report 2037930 (David Gilbert);
+ */
+
+public class PngEncoder {
+
+    /** Constant specifying that alpha channel should be encoded. */
+    public static final boolean ENCODE_ALPHA = true;
+
+    /** Constant specifying that alpha channel should not be encoded. */
+    public static final boolean NO_ALPHA = false;
+
+    /** Constants for filter (NONE). */
+    public static final int FILTER_NONE = 0;
+
+    /** Constants for filter (SUB). */
+    public static final int FILTER_SUB = 1;
+
+    /** Constants for filter (UP). */
+    public static final int FILTER_UP = 2;
+
+    /** Constants for filter (LAST). */
+    public static final int FILTER_LAST = 2;
+
+    /** IHDR tag. */
+    protected static final byte[] IHDR = {73, 72, 68, 82};
+
+    /** IDAT tag. */
+    protected static final byte[] IDAT = {73, 68, 65, 84};
+
+    /** IEND tag. */
+    protected static final byte[] IEND = {73, 69, 78, 68};
+
+    /** PHYS tag. */
+    protected static final byte[] PHYS = {(byte)'p', (byte)'H', (byte)'Y',
+        (byte)'s'};
+
+    /** The png bytes. */
+    protected byte[] pngBytes;
+
+    /** The prior row. */
+    protected byte[] priorRow;
+
+    /** The left bytes. */
+    protected byte[] leftBytes;
+
+    /** The image. */
+    protected Image image;
+
+    /** The width. */
+    protected int width;
+
+    /** The height. */
+    protected int height;
+
+    /** The byte position. */
+    protected int bytePos;
+
+    /** The maximum position. */
+    protected int maxPos;
+
+    /** CRC. */
+    protected CRC32 crc = new CRC32();
+
+    /** The CRC value. */
+    protected long crcValue;
+
+    /** Encode alpha? */
+    protected boolean encodeAlpha;
+
+    /** The filter type. */
+    protected int filter;
+
+    /** The bytes-per-pixel. */
+    protected int bytesPerPixel;
+
+    /** The physical pixel dimension : number of pixels per inch on the X axis. */
+    private int xDpi = 0;
+
+    /** The physical pixel dimension : number of pixels per inch on the Y axis. */
+    private int yDpi = 0;
+
+    /** Used for conversion of DPI to Pixels per Meter. */
+    static private float INCH_IN_METER_UNIT = 0.0254f;
+
+    /**
+     * The compression level (1 = best speed, 9 = best compression,
+     * 0 = no compression).
+     */
+    protected int compressionLevel;
+
+    /**
+     * Class constructor.
+     */
+    public PngEncoder() {
+        this(null, false, FILTER_NONE, 0);
+    }
+
+    /**
+     * Class constructor specifying Image to encode, with no alpha channel
+     * encoding.
+     *
+     * @param image A Java Image object which uses the DirectColorModel
+     * @see java.awt.Image
+     */
+    public PngEncoder(Image image) {
+        this(image, false, FILTER_NONE, 0);
+    }
+
+    /**
+     * Class constructor specifying Image to encode, and whether to encode
+     * alpha.
+     *
+     * @param image A Java Image object which uses the DirectColorModel
+     * @param encodeAlpha Encode the alpha channel? false=no; true=yes
+     * @see java.awt.Image
+     */
+    public PngEncoder(Image image, boolean encodeAlpha) {
+        this(image, encodeAlpha, FILTER_NONE, 0);
+    }
+
+    /**
+     * Class constructor specifying Image to encode, whether to encode alpha,
+     * and filter to use.
+     *
+     * @param image A Java Image object which uses the DirectColorModel
+     * @param encodeAlpha Encode the alpha channel? false=no; true=yes
+     * @param whichFilter 0=none, 1=sub, 2=up
+     * @see java.awt.Image
+     */
+    public PngEncoder(Image image, boolean encodeAlpha, int whichFilter) {
+        this(image, encodeAlpha, whichFilter, 0);
+    }
+
+
+    /**
+     * Class constructor specifying Image source to encode, whether to encode
+     * alpha, filter to use, and compression level.
+     *
+     * @param image A Java Image object
+     * @param encodeAlpha Encode the alpha channel? false=no; true=yes
+     * @param whichFilter 0=none, 1=sub, 2=up
+     * @param compLevel 0..9 (1 = best speed, 9 = best compression, 0 = no
+     *        compression)
+     * @see java.awt.Image
+     */
+    public PngEncoder(Image image, boolean encodeAlpha, int whichFilter,
+            int compLevel) {
+        this.image = image;
+        this.encodeAlpha = encodeAlpha;
+        setFilter(whichFilter);
+        if (compLevel >= 0 && compLevel <= 9) {
+            this.compressionLevel = compLevel;
+        }
+    }
+
+    /**
+     * Set the image to be encoded.
+     *
+     * @param image A Java Image object which uses the DirectColorModel
+     * @see java.awt.Image
+     * @see java.awt.image.DirectColorModel
+     */
+    public void setImage(Image image) {
+        this.image = image;
+        this.pngBytes = null;
+    }
+
+    /**
+     * Returns the image to be encoded.
+     *
+     * @return The image.
+     */
+    public Image getImage() {
+      return this.image;
+    }
+
+  /**
+     * Creates an array of bytes that is the PNG equivalent of the current
+     * image, specifying whether to encode alpha or not.
+     *
+     * @param encodeAlpha boolean false=no alpha, true=encode alpha
+     * @return an array of bytes, or null if there was a problem
+     */
+    public byte[] pngEncode(boolean encodeAlpha) {
+        byte[]  pngIdBytes = {-119, 80, 78, 71, 13, 10, 26, 10};
+
+        if (this.image == null) {
+            return null;
+        }
+        this.width = this.image.getWidth(null);
+        this.height = this.image.getHeight(null);
+
+        /*
+         * start with an array that is big enough to hold all the pixels
+         * (plus filter bytes), and an extra 200 bytes for header info
+         */
+        this.pngBytes = new byte[((this.width + 1) * this.height * 3) + 200];
+
+        /*
+         * keep track of largest byte written to the array
+         */
+        this.maxPos = 0;
+
+        this.bytePos = writeBytes(pngIdBytes, 0);
+        //hdrPos = bytePos;
+        writeHeader();
+        writeResolution();
+        //dataPos = bytePos;
+        if (writeImageData()) {
+            writeEnd();
+            this.pngBytes = resizeByteArray(this.pngBytes, this.maxPos);
+        }
+        else {
+            this.pngBytes = null;
+        }
+        return this.pngBytes;
+    }
+
+    /**
+     * Creates an array of bytes that is the PNG equivalent of the current
+     * image.  Alpha encoding is determined by its setting in the constructor.
+     *
+     * @return an array of bytes, or null if there was a problem
+     */
+    public byte[] pngEncode() {
+        return pngEncode(this.encodeAlpha);
+    }
+
+    /**
+     * Set the alpha encoding on or off.
+     *
+     * @param encodeAlpha  false=no, true=yes
+     */
+    public void setEncodeAlpha(boolean encodeAlpha) {
+        this.encodeAlpha = encodeAlpha;
+    }
+
+    /**
+     * Retrieve alpha encoding status.
+     *
+     * @return boolean false=no, true=yes
+     */
+    public boolean getEncodeAlpha() {
+        return this.encodeAlpha;
+    }
+
+    /**
+     * Set the filter to use.
+     *
+     * @param whichFilter from constant list
+     */
+    public void setFilter(int whichFilter) {
+        this.filter = FILTER_NONE;
+        if (whichFilter <= FILTER_LAST) {
+            this.filter = whichFilter;
+        }
+    }
+
+    /**
+     * Retrieve filtering scheme.
+     *
+     * @return int (see constant list)
+     */
+    public int getFilter() {
+        return this.filter;
+    }
+
+    /**
+     * Set the compression level to use.
+     *
+     * @param level the compression level (1 = best speed, 9 = best compression,
+     *        0 = no compression)
+     */
+    public void setCompressionLevel(int level) {
+        if (level >= 0 && level <= 9) {
+            this.compressionLevel = level;
+        }
+    }
+
+    /**
+     * Retrieve compression level.
+     *
+     * @return int (1 = best speed, 9 = best compression, 0 = no compression)
+     */
+    public int getCompressionLevel() {
+        return this.compressionLevel;
+    }
+
+    /**
+     * Increase or decrease the length of a byte array.
+     *
+     * @param array The original array.
+     * @param newLength The length you wish the new array to have.
+     * @return Array of newly desired length. If shorter than the
+     *         original, the trailing elements are truncated.
+     */
+    protected byte[] resizeByteArray(byte[] array, int newLength) {
+        byte[]  newArray = new byte[newLength];
+        int     oldLength = array.length;
+
+        System.arraycopy(array, 0, newArray, 0, Math.min(oldLength, newLength));
+        return newArray;
+    }
+
+    /**
+     * Write an array of bytes into the pngBytes array.
+     * Note: This routine has the side effect of updating
+     * maxPos, the largest element written in the array.
+     * The array is resized by 1000 bytes or the length
+     * of the data to be written, whichever is larger.
+     *
+     * @param data The data to be written into pngBytes.
+     * @param offset The starting point to write to.
+     * @return The next place to be written to in the pngBytes array.
+     */
+    protected int writeBytes(byte[] data, int offset) {
+        this.maxPos = Math.max(this.maxPos, offset + data.length);
+        if (data.length + offset > this.pngBytes.length) {
+            this.pngBytes = resizeByteArray(this.pngBytes, this.pngBytes.length
+                    + Math.max(1000, data.length));
+        }
+        System.arraycopy(data, 0, this.pngBytes, offset, data.length);
+        return offset + data.length;
+    }
+
+    /**
+     * Write an array of bytes into the pngBytes array, specifying number of
+     * bytes to write. Note: This routine has the side effect of updating
+     * maxPos, the largest element written in the array.
+     * The array is resized by 1000 bytes or the length
+     * of the data to be written, whichever is larger.
+     *
+     * @param data The data to be written into pngBytes.
+     * @param nBytes The number of bytes to be written.
+     * @param offset The starting point to write to.
+     * @return The next place to be written to in the pngBytes array.
+     */
+    protected int writeBytes(byte[] data, int nBytes, int offset) {
+        this.maxPos = Math.max(this.maxPos, offset + nBytes);
+        if (nBytes + offset > this.pngBytes.length) {
+            this.pngBytes = resizeByteArray(this.pngBytes, this.pngBytes.length
+                    + Math.max(1000, nBytes));
+        }
+        System.arraycopy(data, 0, this.pngBytes, offset, nBytes);
+        return offset + nBytes;
+    }
+
+    /**
+     * Write a two-byte integer into the pngBytes array at a given position.
+     *
+     * @param n The integer to be written into pngBytes.
+     * @param offset The starting point to write to.
+     * @return The next place to be written to in the pngBytes array.
+     */
+    protected int writeInt2(int n, int offset) {
+        byte[] temp = {(byte) ((n >> 8) & 0xff), (byte) (n & 0xff)};
+        return writeBytes(temp, offset);
+    }
+
+    /**
+     * Write a four-byte integer into the pngBytes array at a given position.
+     *
+     * @param n The integer to be written into pngBytes.
+     * @param offset The starting point to write to.
+     * @return The next place to be written to in the pngBytes array.
+     */
+    protected int writeInt4(int n, int offset) {
+        byte[] temp = {(byte) ((n >> 24) & 0xff),
+                       (byte) ((n >> 16) & 0xff),
+                       (byte) ((n >> 8) & 0xff),
+                       (byte) (n & 0xff)};
+        return writeBytes(temp, offset);
+    }
+
+    /**
+     * Write a single byte into the pngBytes array at a given position.
+     *
+     * @param b The integer to be written into pngBytes.
+     * @param offset The starting point to write to.
+     * @return The next place to be written to in the pngBytes array.
+     */
+    protected int writeByte(int b, int offset) {
+        byte[] temp = {(byte) b};
+        return writeBytes(temp, offset);
+    }
+
+    /**
+     * Write a PNG "IHDR" chunk into the pngBytes array.
+     */
+    protected void writeHeader() {
+
+        int startPos = this.bytePos = writeInt4(13, this.bytePos);
+        this.bytePos = writeBytes(IHDR, this.bytePos);
+        this.width = this.image.getWidth(null);
+        this.height = this.image.getHeight(null);
+        this.bytePos = writeInt4(this.width, this.bytePos);
+        this.bytePos = writeInt4(this.height, this.bytePos);
+        this.bytePos = writeByte(8, this.bytePos); // bit depth
+        this.bytePos = writeByte((this.encodeAlpha) ? 6 : 2, this.bytePos);
+            // direct model
+        this.bytePos = writeByte(0, this.bytePos); // compression method
+        this.bytePos = writeByte(0, this.bytePos); // filter method
+        this.bytePos = writeByte(0, this.bytePos); // no interlace
+        this.crc.reset();
+        this.crc.update(this.pngBytes, startPos, this.bytePos - startPos);
+        this.crcValue = this.crc.getValue();
+        this.bytePos = writeInt4((int) this.crcValue, this.bytePos);
+    }
+
+    /**
+     * Perform "sub" filtering on the given row.
+     * Uses temporary array leftBytes to store the original values
+     * of the previous pixels.  The array is 16 bytes long, which
+     * will easily hold two-byte samples plus two-byte alpha.
+     *
+     * @param pixels The array holding the scan lines being built
+     * @param startPos Starting position within pixels of bytes to be filtered.
+     * @param width Width of a scanline in pixels.
+     */
+    protected void filterSub(byte[] pixels, int startPos, int width) {
+        int offset = this.bytesPerPixel;
+        int actualStart = startPos + offset;
+        int nBytes = width * this.bytesPerPixel;
+        int leftInsert = offset;
+        int leftExtract = 0;
+
+        for (int i = actualStart; i < startPos + nBytes; i++) {
+            this.leftBytes[leftInsert] =  pixels[i];
+            pixels[i] = (byte) ((pixels[i] - this.leftBytes[leftExtract])
+                     % 256);
+            leftInsert = (leftInsert + 1) % 0x0f;
+            leftExtract = (leftExtract + 1) % 0x0f;
+        }
+    }
+
+    /**
+     * Perform "up" filtering on the given row.
+     * Side effect: refills the prior row with current row
+     *
+     * @param pixels The array holding the scan lines being built
+     * @param startPos Starting position within pixels of bytes to be filtered.
+     * @param width Width of a scanline in pixels.
+     */
+    protected void filterUp(byte[] pixels, int startPos, int width) {
+
+        final int nBytes = width * this.bytesPerPixel;
+
+        for (int i = 0; i < nBytes; i++) {
+            final byte currentByte = pixels[startPos + i];
+            pixels[startPos + i] = (byte) ((pixels[startPos  + i]
+                    - this.priorRow[i]) % 256);
+            this.priorRow[i] = currentByte;
+        }
+    }
+
+    /**
+     * Write the image data into the pngBytes array.
+     * This will write one or more PNG "IDAT" chunks. In order
+     * to conserve memory, this method grabs as many rows as will
+     * fit into 32K bytes, or the whole image; whichever is less.
+     *
+     *
+     * @return true if no errors; false if error grabbing pixels
+     */
+    protected boolean writeImageData() {
+        int rowsLeft = this.height;  // number of rows remaining to write
+        int startRow = 0;       // starting row to process this time through
+        int nRows;              // how many rows to grab at a time
+
+        byte[] scanLines;       // the scan lines to be compressed
+        int scanPos;            // where we are in the scan lines
+        int startPos;           // where this line's actual pixels start (used
+                                // for filtering)
+
+        byte[] compressedLines; // the resultant compressed lines
+        int nCompressed;        // how big is the compressed area?
+
+        //int depth;              // color depth ( handle only 8 or 32 )
+
+        PixelGrabber pg;
+
+        this.bytesPerPixel = (this.encodeAlpha) ? 4 : 3;
+
+        Deflater scrunch = new Deflater(this.compressionLevel);
+        ByteArrayOutputStream outBytes = new ByteArrayOutputStream(1024);
+
+        DeflaterOutputStream compBytes = new DeflaterOutputStream(outBytes,
+                scrunch);
+        try {
+            while (rowsLeft > 0) {
+                nRows = Math.min(32767 / (this.width
+                        * (this.bytesPerPixel + 1)), rowsLeft);
+                nRows = Math.max(nRows, 1);
+
+                int[] pixels = new int[this.width * nRows];
+
+                pg = new PixelGrabber(this.image, 0, startRow,
+                        this.width, nRows, pixels, 0, this.width);
+                try {
+                    pg.grabPixels();
+                }
+                catch (Exception e) {
+                    System.err.println("interrupted waiting for pixels!");
+                    return false;
+                }
+                if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
+                    System.err.println("image fetch aborted or errored");
+                    return false;
+                }
+
+                /*
+                 * Create a data chunk. scanLines adds "nRows" for
+                 * the filter bytes.
+                 */
+                scanLines = new byte[this.width * nRows * this.bytesPerPixel
+                                     + nRows];
+
+                if (this.filter == FILTER_SUB) {
+                    this.leftBytes = new byte[16];
+                }
+                if (this.filter == FILTER_UP) {
+                    this.priorRow = new byte[this.width * this.bytesPerPixel];
+                }
+
+                scanPos = 0;
+                startPos = 1;
+                for (int i = 0; i < this.width * nRows; i++) {
+                    if (i % this.width == 0) {
+                        scanLines[scanPos++] = (byte) this.filter;
+                        startPos = scanPos;
+                    }
+                    scanLines[scanPos++] = (byte) ((pixels[i] >> 16) & 0xff);
+                    scanLines[scanPos++] = (byte) ((pixels[i] >>  8) & 0xff);
+                    scanLines[scanPos++] = (byte) ((pixels[i]) & 0xff);
+                    if (this.encodeAlpha) {
+                        scanLines[scanPos++] = (byte) ((pixels[i] >> 24)
+                                & 0xff);
+                    }
+                    if ((i % this.width == this.width - 1)
+                            && (this.filter != FILTER_NONE)) {
+                        if (this.filter == FILTER_SUB) {
+                            filterSub(scanLines, startPos, this.width);
+                        }
+                        if (this.filter == FILTER_UP) {
+                            filterUp(scanLines, startPos, this.width);
+                        }
+                    }
+                }
+
+                /*
+                 * Write these lines to the output area
+                 */
+                compBytes.write(scanLines, 0, scanPos);
+
+                startRow += nRows;
+                rowsLeft -= nRows;
+            }
+            compBytes.close();
+
+            /*
+             * Write the compressed bytes
+             */
+            compressedLines = outBytes.toByteArray();
+            nCompressed = compressedLines.length;
+
+            this.crc.reset();
+            this.bytePos = writeInt4(nCompressed, this.bytePos);
+            this.bytePos = writeBytes(IDAT, this.bytePos);
+            this.crc.update(IDAT);
+            this.bytePos = writeBytes(compressedLines, nCompressed,
+                    this.bytePos);
+            this.crc.update(compressedLines, 0, nCompressed);
+
+            this.crcValue = this.crc.getValue();
+            this.bytePos = writeInt4((int) this.crcValue, this.bytePos);
+            scrunch.finish();
+            scrunch.end();
+            return true;
+        }
+        catch (IOException e) {
+            System.err.println(e.toString());
+            return false;
+        }
+    }
+
+    /**
+     * Write a PNG "IEND" chunk into the pngBytes array.
+     */
+    protected void writeEnd() {
+        this.bytePos = writeInt4(0, this.bytePos);
+        this.bytePos = writeBytes(IEND, this.bytePos);
+        this.crc.reset();
+        this.crc.update(IEND);
+        this.crcValue = this.crc.getValue();
+        this.bytePos = writeInt4((int) this.crcValue, this.bytePos);
+    }
+
+
+    /**
+     * Set the DPI for the X axis.
+     *
+     * @param xDpi  The number of dots per inch
+     */
+    public void setXDpi(int xDpi) {
+        this.xDpi = Math.round(xDpi / INCH_IN_METER_UNIT);
+
+    }
+
+    /**
+     * Get the DPI for the X axis.
+     *
+     * @return The number of dots per inch
+     */
+    public int getXDpi() {
+        return Math.round(this.xDpi * INCH_IN_METER_UNIT);
+    }
+
+    /**
+     * Set the DPI for the Y axis.
+     *
+     * @param yDpi  The number of dots per inch
+     */
+    public void setYDpi(int yDpi) {
+        this.yDpi = Math.round(yDpi / INCH_IN_METER_UNIT);
+    }
+
+    /**
+     * Get the DPI for the Y axis.
+     *
+     * @return The number of dots per inch
+     */
+    public int getYDpi() {
+        return Math.round(this.yDpi * INCH_IN_METER_UNIT);
+    }
+
+    /**
+     * Set the DPI resolution.
+     *
+     * @param xDpi  The number of dots per inch for the X axis.
+     * @param yDpi  The number of dots per inch for the Y axis.
+     */
+    public void setDpi(int xDpi, int yDpi) {
+        this.xDpi = Math.round(xDpi / INCH_IN_METER_UNIT);
+        this.yDpi = Math.round(yDpi / INCH_IN_METER_UNIT);
+    }
+
+    /**
+     * Write a PNG "pHYs" chunk into the pngBytes array.
+     */
+    protected void writeResolution() {
+        if (this.xDpi > 0 && this.yDpi > 0) {
+
+            final int startPos = this.bytePos = writeInt4(9, this.bytePos);
+            this.bytePos = writeBytes(PHYS, this.bytePos);
+            this.bytePos = writeInt4(this.xDpi, this.bytePos);
+            this.bytePos = writeInt4(this.yDpi, this.bytePos);
+            this.bytePos = writeByte(1, this.bytePos); // unit is the meter.
+
+            this.crc.reset();
+            this.crc.update(this.pngBytes, startPos, this.bytePos - startPos);
+            this.crcValue = this.crc.getValue();
+            this.bytePos = writeInt4((int) this.crcValue, this.bytePos);
+        }
+    }
+}

+ 6 - 0
jars/jcommon-1.0.23/src/main/java/com/keypoint/package.html

@@ -0,0 +1,6 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+A package containing the PNG encoder written by J David Eisenberg.
+</body>
+</html>

+ 81 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/JCommon.java

@@ -0,0 +1,81 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2011, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ *
+ * ------------
+ * JCommon.java
+ * ------------
+ * (C) Copyright 2002-2011, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: JCommon.java,v 1.6 2011/10/17 21:26:06 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 28-Feb-2002 : Version 1 (DG);
+ * 22-Mar-2002 : Changed version number to 0.6.0 (DG);
+ * 25-Mar-2002 : Moved the project info details into a class so that the text can be localised
+ *               more easily (DG);
+ * 04-Apr-2002 : Added Hari to contributors (DG);
+ * 19-Apr-2002 : Added Sam (oldman) to contributors (DG);
+ * 07-Jun-2002 : Added contributors (DG);
+ * 24-Jun-2002 : Removed unnecessary imports (DG);
+ * 27-Aug-2002 : Updated version number to 0.7.0 (DG);
+ *
+ */
+
+package org.jfree;
+
+import org.jfree.ui.about.ProjectInfo;
+
+/**
+ * This class contains static information about the JCommon class library.
+ *
+ * @author David Gilbert
+ */
+public final class JCommon {
+
+    /** Information about the project. */
+    public static final ProjectInfo INFO = JCommonInfo.getInstance();
+    
+    /**
+     * Hidden constructor.
+     */
+    private JCommon() {
+        super();
+    }
+    
+    /**
+     * Prints information about JCommon to standard output.
+     *
+     * @param args  no arguments are honored.
+     */
+    public static void main(final String[] args) {
+        System.out.println(JCommon.INFO.toString());
+    }
+
+}

+ 126 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/JCommonInfo.java

@@ -0,0 +1,126 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2011, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * ----------------
+ * JCommonInfo.java
+ * ----------------
+ * (C)opyright 2003-2011, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   Thomas Morgner;
+ *
+ * $Id: JCommonInfo.java,v 1.9 2011/10/17 21:26:06 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jun-2004 : Added JCommon header (DG);
+ * 18-Dec-2008 : Use ResourceBundleWrapper - see JFreeChart patch 1607918 by
+ *               Jess Thrysoee (DG);
+ *
+ */
+
+package org.jfree;
+
+import java.util.Arrays;
+import java.util.ResourceBundle;
+
+import org.jfree.base.BaseBoot;
+import org.jfree.base.Library;
+import org.jfree.ui.about.Contributor;
+import org.jfree.ui.about.Licences;
+import org.jfree.ui.about.ProjectInfo;
+import org.jfree.util.ResourceBundleWrapper;
+
+/**
+ * Information about the JCommon project.  One instance of this class is
+ * assigned to JCommon.INFO.
+ *
+ * @author David Gilbert
+ */
+public class JCommonInfo extends ProjectInfo {
+
+    /** The singleton instance of the project info object. */
+    private static JCommonInfo singleton;
+
+    /**
+     * Returns the single instance of this class.
+     *
+     * @return The single instance of information about the JCommon library.
+     */
+    public static synchronized JCommonInfo getInstance() {
+        if (singleton == null) {
+            singleton = new JCommonInfo();
+        }
+        return singleton;
+    }
+
+    /**
+     * Creates a new instance.
+     */
+    private JCommonInfo() {
+
+        // get a locale-specific resource bundle...
+        final String baseResourceClass = "org.jfree.resources.JCommonResources";
+        final ResourceBundle resources = ResourceBundleWrapper.getBundle(
+                baseResourceClass);
+
+        setName(resources.getString("project.name"));
+        setVersion(resources.getString("project.version"));
+        setInfo(resources.getString("project.info"));
+        setCopyright(resources.getString("project.copyright"));
+
+        setLicenceName("LGPL");
+        setLicenceText(Licences.getInstance().getLGPL());
+
+        setContributors(Arrays.asList(
+            new Contributor[] {
+                new Contributor("Anthony Boulestreau", "-"),
+                new Contributor("Jeremy Bowman", "-"),
+                new Contributor("J. David Eisenberg", "-"),
+                new Contributor("Paul English", "-"),
+                new Contributor("David Gilbert",
+                        "david.gilbert@object-refinery.com"),
+                new Contributor("Hans-Jurgen Greiner", "-"),
+                new Contributor("Arik Levin", "-"),
+                new Contributor("Achilleus Mantzios", "-"),
+                new Contributor("Thomas Meier", "-"),
+                new Contributor("Aaron Metzger", "-"),
+                new Contributor("Thomas Morgner", "-"),
+                new Contributor("Krzysztof Paz", "-"),
+                new Contributor("Nabuo Tamemasa", "-"),
+                new Contributor("Mark Watson", "-"),
+                new Contributor("Matthew Wright", "-"),
+                new Contributor("Hari", "-"),
+                new Contributor("Sam (oldman)", "-")
+            }
+        ));
+
+        addOptionalLibrary(new Library("JUnit", "3.8", "IBM Public Licence",
+                "http://www.junit.org/"));
+
+        setBootClass(BaseBoot.class.getName());
+    }
+}

+ 355 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/AbstractBoot.java

@@ -0,0 +1,355 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * -----------------
+ * AbstractBoot.java
+ * -----------------
+ * (C)opyright 2004, 2005, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: AbstractBoot.java,v 1.21 2008/09/10 09:22:57 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jun-2004 : Added source headers (DG);
+ * 18-Aug-2005 : Added casts to suppress compiler warnings, as suggested in
+ *               patch 1260622 (DG);
+ *
+ */
+
+package org.jfree.base;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import org.jfree.base.config.HierarchicalConfiguration;
+import org.jfree.base.config.PropertyFileConfiguration;
+import org.jfree.base.config.SystemPropertyConfiguration;
+import org.jfree.base.modules.PackageManager;
+import org.jfree.base.modules.SubSystem;
+import org.jfree.util.Configuration;
+import org.jfree.util.ExtendedConfiguration;
+import org.jfree.util.ExtendedConfigurationWrapper;
+import org.jfree.util.Log;
+import org.jfree.util.ObjectUtilities;
+
+/**
+ * The common base for all Boot classes.
+ * <p>
+ * This initializes the subsystem and all dependent subsystems.
+ * Implementors of this class have to provide a public static
+ * getInstance() method which returns a singleton instance of the
+ * booter implementation.
+ * <p>
+ * Further creation of Boot object should be prevented using
+ * protected or private constructors in that class, or proper
+ * initialzation cannot be guaranteed.
+ *
+ * @author Thomas Morgner
+ */
+public abstract class AbstractBoot implements SubSystem {
+
+    /** The configuration wrapper around the plain configuration. */
+    private ExtendedConfigurationWrapper extWrapper;
+
+    /** A packageManager instance of the package manager. */
+    private PackageManager packageManager;
+
+    /** Global configuration. */
+    private Configuration globalConfig;
+
+    /** A flag indicating whether the booting is currenly in progress. */
+    private boolean bootInProgress;
+
+    /** A flag indicating whether the booting is complete. */
+    private boolean bootDone;
+
+    /**
+     * Default constructor.
+     */
+    protected AbstractBoot() {
+    }
+
+    /**
+     * Returns the packageManager instance of the package manager.
+     *
+     * @return The package manager.
+     */
+    public synchronized PackageManager getPackageManager() {
+        if (this.packageManager == null) {
+            this.packageManager = PackageManager.createInstance(this);
+        }
+        return this.packageManager;
+    }
+
+    /**
+     * Returns the global configuration.
+     *
+     * @return The global configuration.
+     */
+    public synchronized Configuration getGlobalConfig() {
+        if (this.globalConfig == null) {
+            this.globalConfig = loadConfiguration();
+        }
+        return this.globalConfig;
+    }
+
+    /**
+     * Checks, whether the booting is in progress.
+     *
+     * @return true, if the booting is in progress, false otherwise.
+     */
+    public final synchronized boolean isBootInProgress() {
+        return this.bootInProgress;
+    }
+
+    /**
+     * Checks, whether the booting is complete.
+     *
+     * @return true, if the booting is complete, false otherwise.
+     */
+    public final synchronized boolean isBootDone() {
+        return this.bootDone;
+    }
+
+    /**
+     * Loads the configuration. This will be called exactly once.
+     *
+     * @return The configuration.
+     */
+    protected abstract Configuration loadConfiguration();
+
+    /**
+     * Starts the boot process.
+     */
+    public final void start() {
+
+        synchronized (this) {
+            if (isBootDone()) {
+                return;
+            }
+            while (isBootInProgress()) {
+              try {
+                wait();
+              }
+              catch (InterruptedException e) {
+                // ignore ..
+              }
+            }
+            if (isBootDone()) {
+                return;
+            }
+            this.bootInProgress = true;
+        }
+
+        // boot dependent libraries ...
+        final BootableProjectInfo info = getProjectInfo();
+        if (info != null) {
+            final BootableProjectInfo[] childs = info.getDependencies();
+            for (int i = 0; i < childs.length; i++) {
+                final AbstractBoot boot = loadBooter(childs[i].getBootClass());
+                if (boot != null) {
+                    // but we're waiting until the booting is complete ...
+                    synchronized(boot) {
+                      boot.start();
+                      while (boot.isBootDone() == false) {
+                        try {
+                          boot.wait();
+                        }
+                        catch (InterruptedException e) {
+                          // ignore it ..
+                        }
+                      }
+                    }
+                }
+            }
+        }
+
+        performBoot();
+        if (info != null)
+        {
+          Log.info (info.getName() + " " + info.getVersion() + " started.");
+        }
+        else
+        {
+          Log.info (getClass() + " started.");
+        }
+
+        synchronized (this) {
+            this.bootInProgress = false;
+            this.bootDone = true;
+            notifyAll();
+        }
+    }
+
+    /**
+     * Performs the boot.
+     */
+    protected abstract void performBoot();
+
+    /**
+     * Returns the project info.
+     *
+     * @return The project info.
+     */
+    protected abstract BootableProjectInfo getProjectInfo();
+
+    /**
+     * Loads the specified booter implementation.
+     *
+     * @param classname  the class name.
+     *
+     * @return The boot class.
+     */
+    protected AbstractBoot loadBooter(final String classname) {
+        if (classname == null) {
+            return null;
+        }
+        try {
+            final Class c = ObjectUtilities.getClassLoader(
+                    getClass()).loadClass(classname);
+            final Method m = c.getMethod("getInstance", (Class[]) null);
+            return (AbstractBoot) m.invoke(null, (Object[]) null);
+        }
+        catch (Exception e) {
+            Log.info ("Unable to boot dependent class: " + classname);
+            return null;
+        }
+    }
+
+    /**
+     * Creates a default configuration setup, which loads its settings from
+     * the static configuration (defaults provided by the developers of the
+     * library) and the user configuration (settings provided by the deployer).
+     * The deployer's settings override the developer's settings.
+     *
+     * If the parameter <code>addSysProps</code> is set to true, the system
+     * properties will be added as third configuration layer. The system
+     * properties configuration allows to override all other settings.
+     *
+     * @param staticConfig the resource name of the developers configuration
+     * @param userConfig the resource name of the deployers configuration
+     * @param addSysProps a flag defining whether to include the system
+     *                    properties into the configuration.
+     * @return the configured Configuration instance.
+     */
+    protected Configuration createDefaultHierarchicalConfiguration
+        (final String staticConfig, final String userConfig,
+                final boolean addSysProps)
+    {
+      return createDefaultHierarchicalConfiguration
+          (staticConfig, userConfig, addSysProps, PropertyFileConfiguration.class);
+    }
+
+    /**
+     * Creates a default hierarchical configuration.
+     *
+     * @param staticConfig  the static configuration.
+     * @param userConfig  the user configuration.
+     * @param addSysProps  additional system properties.
+     * @param source  the source.
+     *
+     * @return The configuration.
+     */
+    protected Configuration createDefaultHierarchicalConfiguration
+        (final String staticConfig, final String userConfig,
+         final boolean addSysProps, final Class source)
+    {
+        final HierarchicalConfiguration globalConfig
+            = new HierarchicalConfiguration();
+
+        if (staticConfig != null) {
+          final PropertyFileConfiguration rootProperty
+              = new PropertyFileConfiguration();
+          rootProperty.load(staticConfig, getClass());
+          globalConfig.insertConfiguration(rootProperty);
+          globalConfig.insertConfiguration(
+                  getPackageManager().getPackageConfiguration());
+        }
+        if (userConfig != null) {
+          String userConfigStripped;
+          if (userConfig.startsWith("/")) {
+            userConfigStripped = userConfig.substring(1);
+          }
+          else {
+            userConfigStripped = userConfig;
+          }
+          try {
+            final Enumeration userConfigs = ObjectUtilities.getClassLoader
+                            (getClass()).getResources(userConfigStripped);
+            final ArrayList configs = new ArrayList();
+            while (userConfigs.hasMoreElements()) {
+              final URL url = (URL) userConfigs.nextElement();
+              try {
+                final PropertyFileConfiguration baseProperty =
+                        new PropertyFileConfiguration();
+                final InputStream in = url.openStream();
+                baseProperty.load(in);
+                in.close();
+                configs.add(baseProperty);
+              }
+              catch(IOException ioe) {
+                Log.warn ("Failed to load the user configuration at " + url, ioe);
+              }
+            }
+
+            for (int i = configs.size() - 1; i >= 0; i--) {
+              final PropertyFileConfiguration baseProperty =
+                      (PropertyFileConfiguration) configs.get(i);
+              globalConfig.insertConfiguration(baseProperty);
+            }
+          }
+          catch (IOException e) {
+            Log.warn ("Failed to lookup the user configurations.", e);
+          }
+        }
+        if (addSysProps) {
+          final SystemPropertyConfiguration systemConfig
+              = new SystemPropertyConfiguration();
+          globalConfig.insertConfiguration(systemConfig);
+        }
+        return globalConfig;
+    }
+
+    /**
+     * Returns the global configuration as extended configuration.
+     *
+     * @return the extended configuration.
+     */
+    public synchronized ExtendedConfiguration getExtendedConfig ()
+    {
+      if (this.extWrapper == null) {
+          this.extWrapper = new ExtendedConfigurationWrapper(getGlobalConfig());
+      }
+      return this.extWrapper;
+    }
+}

+ 137 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/BaseBoot.java

@@ -0,0 +1,137 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * -------------
+ * BaseBoot.java
+ * -------------
+ * (C)opyright 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: BaseBoot.java,v 1.11 2007/11/02 17:50:34 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jun-2004 : Added source headers (DG);
+ *
+ */
+
+package org.jfree.base;
+
+import org.jfree.JCommon;
+import org.jfree.base.config.ModifiableConfiguration;
+import org.jfree.base.log.DefaultLogModule;
+import org.jfree.util.Configuration;
+import org.jfree.util.ObjectUtilities;
+
+/**
+ * The base boot class. This initializes the services provided by
+ * JCommon.
+ *
+ * @author Thomas Morgner
+ */
+public class BaseBoot extends AbstractBoot {
+
+    /**
+     * Singleton instance.
+     */
+    private static BaseBoot singleton;
+
+    /**
+     * The project info.
+     */
+    private BootableProjectInfo bootableProjectInfo;
+
+    /**
+     * Default constructor (private).
+     */
+    private BaseBoot() {
+        this.bootableProjectInfo = JCommon.INFO;
+    }
+
+    /**
+     * Returns the global configuration as modifiable configuration reference.
+     *
+     * @return the global configuration
+     */
+    public static ModifiableConfiguration getConfiguration() {
+        return (ModifiableConfiguration) getInstance().getGlobalConfig();
+    }
+
+    /**
+     * Returns the global configuration for JFreeReport.
+     * <p>
+     * In the current implementation, the configuration has no properties defined, but
+     * references a parent configuration that:</p> 
+     * <ul> <li>copies across all the
+     * <code>System</code> properties to use as report configuration properties (obviously
+     * the majority of them will not apply to reports);</li> <li>itself references a parent
+     * configuration that reads its properties from a file <code>jfreereport.properties</code>.
+     * </ul>
+     *
+     * @return the global configuration.
+     */
+    protected synchronized Configuration loadConfiguration() {
+        return createDefaultHierarchicalConfiguration
+            ("/org/jfree/base/jcommon.properties",
+             "/jcommon.properties", true, BaseBoot.class);
+    }
+
+    /**
+     * Returns the boot instance.
+     *
+     * @return The boot instance.
+     */
+    public static synchronized AbstractBoot getInstance() {
+        if (singleton == null) {
+            singleton = new BaseBoot();
+        }
+        return singleton;
+    }
+
+    /**
+     * Performs the boot process.
+     */
+    protected void performBoot() {
+        // configure the classloader from the properties-file.
+        ObjectUtilities.setClassLoaderSource
+                (getConfiguration().getConfigProperty("org.jfree.ClassLoader"));
+
+        getPackageManager().addModule(DefaultLogModule.class.getName());
+        getPackageManager().load("org.jfree.jcommon.modules.");
+        getPackageManager().initializeModules();
+    }
+
+    /**
+     * Returns the project info.
+     *
+     * @return The project info.
+     */
+    protected BootableProjectInfo getProjectInfo() {
+        return this.bootableProjectInfo;
+    }
+}

+ 288 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/BasicProjectInfo.java

@@ -0,0 +1,288 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * ---------------------
+ * BasicProjectInfo.java
+ * ---------------------
+ * (C)opyright 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: BasicProjectInfo.java,v 1.10 2008/09/10 09:23:34 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jun-2004 : Added source headers (DG);
+ *
+ */
+
+package org.jfree.base;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jfree.util.ObjectUtilities;
+
+/**
+ * Basic project info.
+ *
+ * @author Thomas Morgner
+ */
+public class BasicProjectInfo extends Library {
+    /**
+     * A helper class, which simplifies the loading of optional library
+     * implementations.
+     */
+    private static class OptionalLibraryHolder {
+        private String libraryClass;
+        private transient Library library;
+
+        public OptionalLibraryHolder(final String libraryClass) {
+            if (libraryClass == null) {
+                throw new NullPointerException("LibraryClass must not be null.");
+            }
+            this.libraryClass = libraryClass;
+        }
+
+        public OptionalLibraryHolder(final Library library) {
+          if (library == null) {
+              throw new NullPointerException("Library must not be null.");
+          }
+          this.library = library;
+          this.libraryClass = library.getClass().getName();
+        }
+
+        public String getLibraryClass() {
+            return this.libraryClass;
+        }
+
+        public Library getLibrary() {
+            if (this.library == null) {
+                this.library = loadLibrary(this.libraryClass);
+            }
+            return this.library;
+        }
+
+        protected Library loadLibrary(final String classname) {
+            if (classname == null) {
+                return null;
+            }
+            try {
+                final Class c = ObjectUtilities.getClassLoader(
+                        getClass()).loadClass(classname);
+                try {
+                    final Method m = c.getMethod("getInstance", (Class[]) null);
+                    return (Library) m.invoke(null, (Object[]) null);
+                }
+                catch(Exception e) {
+                    // ok, fall back ...
+                }
+                return (Library) c.newInstance();
+            }
+            catch (Exception e) {
+                // ok, this library has no 'getInstance()' method. Check the
+                // default constructor ...
+                return null;
+            }
+        }
+
+    }
+
+    /** The project copyright statement. */
+    private String copyright;
+
+    /** A list of libraries used by the project. */
+    private List libraries;
+
+    private List optionalLibraries;
+
+    /**
+     * Default constructor.
+     */
+    public BasicProjectInfo() {
+        this.libraries = new ArrayList();
+        this.optionalLibraries = new ArrayList();
+    }
+
+    /**
+     * Creates a new library reference.
+     *
+     * @param name    the name.
+     * @param version the version.
+     * @param licence the licence.
+     * @param info    the web address or other info.
+     */
+    public BasicProjectInfo(final String name, final String version,
+                            final String licence, final String info) {
+        this();
+        setName(name);
+        setVersion(version);
+        setLicenceName(licence);
+        setInfo(info);
+    }
+
+    /**
+     * Creates a new project info instance.
+     *
+     * @param name  the project name.
+     * @param version  the project version.
+     * @param info  the project info (web site for example).
+     * @param copyright  the copyright statement.
+     * @param licenceName  the license name.
+     */
+    public BasicProjectInfo(final String name, final String version,
+                            final String info, final String copyright,
+                            final String licenceName) {
+        this(name, version, licenceName, info);
+        setCopyright(copyright);
+    }
+
+    /**
+     * Returns the copyright statement.
+     *
+     * @return The copyright statement.
+     */
+    public String getCopyright() {
+        return this.copyright;
+    }
+
+    /**
+     * Sets the project copyright statement.
+     *
+     * @param copyright  the project copyright statement.
+     */
+    public void setCopyright(final String copyright) {
+        this.copyright = copyright;
+    }
+
+    /**
+     * Sets the project info string (for example, this could be the project URL).
+     *
+     * @param info  the info string.
+     */
+    public void setInfo(final String info) {
+        super.setInfo(info);
+    }
+
+    /**
+     * Sets the license name.
+     *
+     * @param licence  the license name.
+     */
+    public void setLicenceName(final String licence) {
+        super.setLicenceName(licence);
+    }
+
+    /**
+     * Sets the project name.
+     *
+     * @param name  the project name.
+     */
+    public void setName(final String name) {
+        super.setName(name);
+    }
+
+    /**
+     * Sets the project version number.
+     *
+     * @param version  the version number.
+     */
+    public void setVersion(final String version) {
+        super.setVersion(version);
+    }
+
+    /**
+     * Returns a list of libraries used by the project.
+     *
+     * @return the list of libraries.
+     */
+    public Library[] getLibraries() {
+        return (Library[]) this.libraries.toArray
+                (new Library[this.libraries.size()]);
+    }
+
+    /**
+     * Adds a library.
+     *
+     * @param library  the library.
+     */
+    public void addLibrary (final Library library) {
+        if (library == null) {
+            throw new NullPointerException();
+        }
+        this.libraries.add(library);
+    }
+
+    /**
+     * Returns a list of optional libraries used by the project.
+     *
+     * @return the list of libraries.
+     */
+    public Library[] getOptionalLibraries() {
+        final ArrayList libraries = new ArrayList();
+        for (int i = 0; i < this.optionalLibraries.size(); i++) {
+          OptionalLibraryHolder holder =
+                  (OptionalLibraryHolder) this.optionalLibraries.get(i);
+          Library l = holder.getLibrary();
+          if (l != null) {
+              libraries.add(l);
+          }
+        }
+        return (Library[]) libraries.toArray(new Library[libraries.size()]);
+    }
+
+    /**
+     * Adds an optional library. These libraries will be booted, if they define
+     * a boot class. A missing class is considered non-fatal and it is assumed
+     * that the programm knows how to handle that.
+     *
+     * @param libraryClass  the library.
+     */
+    public void addOptionalLibrary (final String libraryClass) {
+        if (libraryClass == null) {
+            throw new NullPointerException("Library classname must be given.");
+        }
+        this.optionalLibraries.add
+                (new OptionalLibraryHolder(libraryClass));
+    }
+
+
+    /**
+     * Adds an optional library. These libraries will be booted, if they define
+     * a boot class. A missing class is considered non-fatal and it is assumed
+     * that the programm knows how to handle that.
+     *
+     * @param library  the library.
+     */
+    public void addOptionalLibrary (final Library library) {
+      if (library == null) {
+          throw new NullPointerException("Library must be given.");
+      }
+      this.optionalLibraries.add(new OptionalLibraryHolder(library));
+  }
+}

+ 179 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/BootableProjectInfo.java

@@ -0,0 +1,179 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ------------------------
+ * BootableProjectInfo.java
+ * ------------------------
+ * (C)opyright 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: BootableProjectInfo.java,v 1.4 2006/03/23 19:47:05 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jun-2004 : Added source headers (DG);
+ *
+ */
+
+package org.jfree.base;
+
+import java.util.ArrayList;
+
+/**
+ * Project info for a bootable project. A bootable project provides a controlled
+ * way of initalizing all subsystems by providing a Boot loader implementation.
+ *
+ * @author Thomas Morgner
+ */
+public class BootableProjectInfo extends BasicProjectInfo {
+
+    /** The boot class. */
+    private String bootClass;
+
+    /** The auto-boot flag. */
+    private boolean autoBoot;
+
+    /**
+     * Creates a new instance.
+     */
+    public BootableProjectInfo() {
+        this.autoBoot = true;
+    }
+
+    /**
+     * Creates a new library reference.
+     *
+     * @param name    the name.
+     * @param version the version.
+     * @param licence the licence.
+     * @param info    the web address or other info.
+     */
+    public BootableProjectInfo(final String name, final String version,
+                               final String licence, final String info) {
+        this();
+        setName(name);
+        setVersion(version);
+        setLicenceName(licence);
+        setInfo(info);
+    }
+
+    /**
+     * Creates a new library reference.
+     *
+     * @param name    the name.
+     * @param version the version.
+     * @param info  the info (for example, the project URL).
+     * @param copyright  the copyright statement.
+     * @param licenceName the license name.
+     */
+    public BootableProjectInfo(final String name, final String version, final String info,
+                               final String copyright, final String licenceName) {
+        this();
+        setName(name);
+        setVersion(version);
+        setLicenceName(licenceName);
+        setInfo(info);
+        setCopyright(copyright);
+    }
+
+    /**
+     * Returns the dependencies.
+     * 
+     * @return The dependencies.
+     */
+    public BootableProjectInfo[] getDependencies() {
+        final ArrayList dependencies = new ArrayList();
+        final Library[] libraries = getLibraries();
+        for (int i = 0; i < libraries.length; i++) {
+          Library lib = libraries[i];
+          if (lib instanceof BootableProjectInfo) {
+              dependencies.add(lib);
+          }
+        }
+
+        final Library[] optionalLibraries = getOptionalLibraries();
+        for (int i = 0; i < optionalLibraries.length; i++) {
+          Library lib = optionalLibraries[i];
+          if (lib instanceof BootableProjectInfo) {
+              dependencies.add(lib);
+          }
+        }
+        return (BootableProjectInfo[]) dependencies.toArray
+            (new BootableProjectInfo[dependencies.size()]);
+    }
+
+    /**
+     * Adds a dependency.
+     * 
+     * @param projectInfo  the project.
+     * @deprecated use 'addLibrary' instead.
+     */
+    public void addDependency(final BootableProjectInfo projectInfo) {
+        if (projectInfo == null) {
+            throw new NullPointerException();
+        }
+        addLibrary(projectInfo);
+    }
+
+    /**
+     * Returns the name of the boot class.
+     * 
+     * @return The name of the boot class.
+     */
+    public String getBootClass() {
+        return this.bootClass;
+    }
+
+    /**
+     * Sets the boot class name.
+     * 
+     * @param bootClass  the boot class name.
+     */
+    public void setBootClass(final String bootClass) {
+        this.bootClass = bootClass;
+    }
+
+    /**
+     * Returns, whether the project should be booted automaticly.
+     * 
+     * @return The auto-boot flag.
+     */
+    public boolean isAutoBoot() {
+        return this.autoBoot;
+    }
+
+    /**
+     * Sets the auto boot flag.
+     *
+     * @param autoBoot true, if the project should be booted automaticly, false otherwise.
+     */
+    public void setAutoBoot(final boolean autoBoot) {
+        this.autoBoot = autoBoot;
+    }
+
+}

+ 83 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/ClassPathDebugger.java

@@ -0,0 +1,83 @@
+/**
+ * ========================================
+ * JCommon : a free Java report library
+ * ========================================
+ *
+ * Project Info:  http://www.jfree.org/jcommon/
+ *
+ * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
+ *
+ * This library 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 library 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
+ * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * ------------
+ * $Id: ClassPathDebugger.java,v 1.2 2008/09/10 09:23:34 mungady Exp $
+ * ------------
+ * (C) Copyright 2002-2006, by Object Refinery Limited.
+ */
+
+package org.jfree.base;
+
+import java.util.Enumeration;
+
+import org.jfree.util.ObjectUtilities;
+
+/**
+ * Creation-Date: 02.11.2007, 18:42:27
+ *
+ * @author Thomas Morgner
+ */
+public class ClassPathDebugger
+{
+  /**
+   * Entry point.
+   *
+   * @param args  command line arguments.
+   */
+  public static void main(String[] args)
+  {
+    System.out.println ("Listing the various classloaders:");
+    System.out.println ("Defined classloader source: " + ObjectUtilities.getClassLoaderSource());
+    System.out.println ("User classloader: " + ObjectUtilities.getClassLoader());
+    System.out.println ("Classloader for ObjectUtilities.class: " + ObjectUtilities.getClassLoader(ObjectUtilities.class));
+    System.out.println ("Classloader for String.class: " + ObjectUtilities.getClassLoader(String.class));
+    System.out.println ("Thread-Context Classloader: " + Thread.currentThread().getContextClassLoader());
+    System.out.println ("Defined System classloader: " + ClassLoader.getSystemClassLoader());
+    System.out.println();
+    try
+    {
+      System.out.println ("Listing sources for '/jcommon.properties':");
+      Enumeration resources = ObjectUtilities.getClassLoader
+          (ObjectUtilities.class).getResources("jcommon.properties");
+      while (resources.hasMoreElements())
+      {
+        System.out.println (" " + resources.nextElement());
+      }
+      System.out.println();
+      System.out.println ("Listing sources for 'org/jfree/JCommonInfo.class':");
+      resources = ObjectUtilities.getClassLoader
+          (ObjectUtilities.class).getResources("org/jfree/JCommonInfo.class");
+      while (resources.hasMoreElements())
+      {
+        System.out.println (" " + resources.nextElement());
+      }
+    }
+    catch (Exception e)
+    {
+      e.printStackTrace();
+    }
+
+  }
+}

+ 202 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/Library.java

@@ -0,0 +1,202 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * ------------
+ * Library.java
+ * ------------
+ * (C) Copyright 2002-2004, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: Library.java,v 1.7 2008/09/10 09:23:34 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 21-Feb-2002 : Version 1 (DG);
+ * 25-Mar-2002 : Added a new constructor (DG);
+ * 02-Nov-2005 : Minor API doc updates (DG);
+ *
+ */
+
+package org.jfree.base;
+
+import org.jfree.ui.about.AboutFrame;
+
+/**
+ * A simple class representing a library in a software project.  For use in
+ * the {@link AboutFrame} class.
+ *
+ * @author David Gilbert
+ */
+public class Library {
+
+    /** The name. */
+    private String name;
+
+    /** The version. */
+    private String version;
+
+    /** The licenceName. */
+    private String licenceName;
+
+    /** The version. */
+    private String info;
+
+    /**
+     * Creates a new library reference.
+     *
+     * @param name  the name.
+     * @param version  the version.
+     * @param licence  the licenceName.
+     * @param info  the web address or other info.
+     */
+    public Library(final String name, final String version,
+                   final String licence, final String info) {
+
+        this.name = name;
+        this.version = version;
+        this.licenceName = licence;
+        this.info = info;
+    }
+
+    /**
+     * Creates a new library reference.
+     */
+    protected Library() {
+        // nothing required
+    }
+
+    /**
+     * Returns the library name.
+     *
+     * @return the library name.
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * Returns the library version.
+     *
+     * @return the library version.
+     */
+    public String getVersion() {
+        return this.version;
+    }
+
+    /**
+     * Returns the licenceName text.
+     *
+     * @return the licenceName text.
+     */
+    public String getLicenceName() {
+        return this.licenceName;
+    }
+
+    /**
+     * Returns the project info for the library.
+     *
+     * @return the project info.
+     */
+    public String getInfo() {
+        return this.info;
+    }
+
+    /**
+     * Sets the project info.
+     *
+     * @param info  the project info.
+     */
+    protected void setInfo(final String info) {
+        this.info = info;
+    }
+
+    /**
+     * Sets the licence name.
+     *
+     * @param licenceName  the licence name.
+     */
+    protected void setLicenceName(final String licenceName) {
+        this.licenceName = licenceName;
+    }
+
+    /**
+     * Sets the project name.
+     *
+     * @param name  the project name.
+     */
+    protected void setName(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * Sets the version identifier.
+     *
+     * @param version  the version identifier.
+     */
+    protected void setVersion(final String version) {
+        this.version = version;
+    }
+
+    /**
+     * Tests this object for equality with an arbitrary object.
+     *
+     * @param o  the object.
+     *
+     * @return A boolean.
+     */
+    public boolean equals(final Object o)
+    {
+      if (this == o)
+      {
+        return true;
+      }
+      if (o == null || getClass() != o.getClass())
+      {
+        return false;
+      }
+
+      final Library library = (Library) o;
+
+      if (this.name != null ? !this.name.equals(library.name) : library.name != null)
+      {
+        return false;
+      }
+
+      return true;
+    }
+
+    /**
+     * Returns a hash code for this instance.
+     *
+     * @return A hash code.
+     */
+    public int hashCode()
+    {
+      return (this.name != null ? this.name.hashCode() : 0);
+    }
+}

+ 369 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/config/HierarchicalConfiguration.java

@@ -0,0 +1,369 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * ------------------------------
+ * HierarchicalConfiguration.java
+ * ------------------------------
+ * (C) Copyright 2004, by Object Refinery Limited.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: HierarchicalConfiguration.java,v 1.8 2008/09/10 09:17:28 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jun-2004 : Added JCommon header (DG);
+ * 29-Jul-2004 : Replaced 'enum' variable name (reserved word in JDK 1.5) (DG);
+ *
+ */
+
+package org.jfree.base.config;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.TreeSet;
+
+import org.jfree.util.Configuration;
+import org.jfree.util.PublicCloneable;
+
+/**
+ * A hierarchical configuration. Such a configuration can have one or more
+ * parent configurations providing usefull default values.
+ *
+ * @author Thomas Morgner
+ */
+public class HierarchicalConfiguration
+    implements ModifiableConfiguration, PublicCloneable
+{
+
+  /**
+   * The instance configuration properties.
+   */
+  private Properties configuration;
+
+  /**
+   * The parent configuration (null if this is the root configuration).
+   */
+  private transient Configuration parentConfiguration;
+
+  /**
+   * Creates a new configuration.
+   */
+  public HierarchicalConfiguration()
+  {
+    this.configuration = new Properties();
+  }
+
+  /**
+   * Creates a new configuration.
+   *
+   * @param parentConfiguration the parent configuration.
+   */
+  public HierarchicalConfiguration(final Configuration parentConfiguration)
+  {
+    this();
+    this.parentConfiguration = parentConfiguration;
+  }
+
+  /**
+   * Returns the configuration property with the specified key.
+   *
+   * @param key the property key.
+   * @return the property value.
+   */
+  public String getConfigProperty(final String key)
+  {
+    return getConfigProperty(key, null);
+  }
+
+  /**
+   * Returns the configuration property with the specified key (or the
+   * specified default value if there is no such property).
+   * <p>
+   * If the property is not defined in this configuration, the code will
+   * lookup the property in the parent configuration.</p>
+   *
+   * @param key          the property key.
+   * @param defaultValue the default value.
+   * @return the property value.
+   */
+  public String getConfigProperty(final String key, final String defaultValue)
+  {
+    String value = this.configuration.getProperty(key);
+    if (value == null)
+    {
+      if (isRootConfig())
+      {
+        value = defaultValue;
+      }
+      else
+      {
+        value = this.parentConfiguration.getConfigProperty(key, defaultValue);
+      }
+    }
+    return value;
+  }
+
+  /**
+   * Sets a configuration property.
+   *
+   * @param key   the property key.
+   * @param value the property value.
+   */
+  public void setConfigProperty(final String key, final String value)
+  {
+    if (key == null)
+    {
+      throw new NullPointerException();
+    }
+
+    if (value == null)
+    {
+      this.configuration.remove(key);
+    }
+    else
+    {
+      this.configuration.setProperty(key, value);
+    }
+  }
+
+  /**
+   * Returns true if this object has no parent.
+   *
+   * @return true, if this report is the root configuration, false otherwise.
+   */
+  private boolean isRootConfig()
+  {
+    return this.parentConfiguration == null;
+  }
+
+  /**
+   * Checks, whether the given key is localy defined in this instance or
+   * whether the key's value is inherited.
+   *
+   * @param key the key that should be checked.
+   * @return true, if the key is defined locally, false otherwise.
+   */
+  public boolean isLocallyDefined(final String key)
+  {
+    return this.configuration.containsKey(key);
+  }
+
+  /**
+   * Returns the collection of properties for the configuration.
+   *
+   * @return the properties.
+   */
+  protected Properties getConfiguration()
+  {
+    return this.configuration;
+  }
+
+  /**
+   * The new configuartion will be inserted into the list of report
+   * configuration, so that this configuration has the given report
+   * configuration instance as parent.
+   *
+   * @param config the new report configuration.
+   */
+  public void insertConfiguration(final HierarchicalConfiguration config)
+  {
+    config.setParentConfig(getParentConfig());
+    setParentConfig(config);
+  }
+
+  /**
+   * Set the parent configuration. The parent configuration is queried, if the
+   * requested configuration values was not found in this report
+   * configuration.
+   *
+   * @param config the parent configuration.
+   */
+  protected void setParentConfig(final Configuration config)
+  {
+    if (this.parentConfiguration == this)
+    {
+      throw new IllegalArgumentException("Cannot add myself as parent configuration.");
+    }
+    this.parentConfiguration = config;
+  }
+
+  /**
+   * Returns the parent configuration. The parent configuration is queried, if
+   * the requested configuration values was not found in this report
+   * configuration.
+   *
+   * @return the parent configuration.
+   */
+  protected Configuration getParentConfig()
+  {
+    return this.parentConfiguration;
+  }
+
+  /**
+   * Returns all defined configuration properties for the report. The
+   * enumeration contains all keys of the changed properties, properties set
+   * from files or the system properties are not included.
+   *
+   * @return all defined configuration properties for the report.
+   */
+  public Enumeration getConfigProperties()
+  {
+    return this.configuration.keys();
+  }
+
+  /**
+   * Searches all property keys that start with a given prefix.
+   *
+   * @param prefix the prefix that all selected property keys should share
+   * @return the properties as iterator.
+   */
+  public Iterator findPropertyKeys(final String prefix)
+  {
+    final TreeSet keys = new TreeSet();
+    collectPropertyKeys(prefix, this, keys);
+    return Collections.unmodifiableSet(keys).iterator();
+  }
+
+  /**
+   * Collects property keys from this and all parent report configurations,
+   * which start with the given prefix.
+   *
+   * @param prefix    the prefix, that selects the property keys.
+   * @param config    the currently processed report configuration.
+   * @param collector the target list, that should receive all valid keys.
+   */
+  private void collectPropertyKeys(final String prefix,
+                                   final Configuration config,
+                                   final TreeSet collector)
+  {
+    final Enumeration enum1 = config.getConfigProperties();
+    while (enum1.hasMoreElements())
+    {
+      final String key = (String) enum1.nextElement();
+      if (key.startsWith(prefix))
+      {
+        if (collector.contains(key) == false)
+        {
+          collector.add(key);
+        }
+      }
+    }
+
+    if (config instanceof HierarchicalConfiguration)
+    {
+      final HierarchicalConfiguration hconfig = (HierarchicalConfiguration) config;
+      if (hconfig.parentConfiguration != null)
+      {
+        collectPropertyKeys(prefix, hconfig.parentConfiguration, collector);
+      }
+    }
+  }
+
+  /**
+   * Checks, whether the parent configuration can be serialized. Usually the
+   * global configuration is not serialized and should return false here.
+   *
+   * @return true, if the parent config can be serialized, false otherwise.
+   */
+  protected boolean isParentSaved()
+  {
+    return true;
+  }
+
+  /**
+   * A callback method to reconnect this configuration with the global
+   * configuration after deserialization.
+   */
+  protected void configurationLoaded()
+  {
+  }
+
+  /**
+   * Helper method for serialization.
+   *
+   * @param out the output stream where to write the object.
+   * @throws java.io.IOException if errors occur while writing the stream.
+   */
+  private void writeObject(final ObjectOutputStream out)
+      throws IOException
+  {
+    out.defaultWriteObject();
+    if (isParentSaved() == false)
+    {
+      out.writeBoolean(false);
+    }
+    else
+    {
+      out.writeBoolean(true);
+      out.writeObject(this.parentConfiguration);
+    }
+  }
+
+  /**
+   * Helper method for serialization.
+   *
+   * @param in the input stream from where to read the serialized object.
+   * @throws IOException            when reading the stream fails.
+   * @throws ClassNotFoundException if a class definition for a serialized
+   *                                object could not be found.
+   */
+  private void readObject(final ObjectInputStream in)
+      throws IOException, ClassNotFoundException
+  {
+    in.defaultReadObject();
+    final boolean readParent = in.readBoolean();
+    if (readParent)
+    {
+        this.parentConfiguration = (ModifiableConfiguration) in.readObject();
+    }
+    else
+    {
+        this.parentConfiguration = null;
+    }
+    configurationLoaded();
+  }
+
+  /**
+   * Returns a clone of this instance.
+   *
+   * @return A clone.
+   *
+   * @throws CloneNotSupportedException if there is a problem cloning.
+   */
+  public Object clone() throws CloneNotSupportedException
+  {
+    HierarchicalConfiguration config = (HierarchicalConfiguration) super.clone();
+    config.configuration = (Properties) this.configuration.clone();
+    return config;
+  }
+}

+ 81 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/config/ModifiableConfiguration.java

@@ -0,0 +1,81 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ----------------------------
+ * ModifiableConfiguration.java
+ * ----------------------------
+ * (C)opyright 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   Thomas Morgner;
+ *
+ * $Id: ModifiableConfiguration.java,v 1.3 2005/10/18 13:14:12 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jun-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.base.config;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import org.jfree.util.Configuration;
+
+/**
+ * A modifiable configuration.
+ *
+ * @author Thomas Morgner
+ */
+public interface ModifiableConfiguration extends Configuration {
+ 
+    /**
+     * Sets the value of a configuration property.
+     * 
+     * @param key  the property key.
+     * @param value  the property value.
+     */
+    public void setConfigProperty(final String key, final String value);
+  
+    /**
+     * Returns the configuration properties.
+     * 
+     * @return The configuration properties.
+     */
+    public Enumeration getConfigProperties();
+  
+    /**
+     * Returns an iterator for the keys beginning with the specified prefix.
+     * 
+     * @param prefix  the prefix.
+     * 
+     * @return The iterator.
+     */
+    public Iterator findPropertyKeys(final String prefix);
+
+}

+ 141 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/config/PropertyFileConfiguration.java

@@ -0,0 +1,141 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * ------------------------------------
+ * PropertyFileReportConfiguration.java
+ * ------------------------------------
+ * (C)opyright 2003, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: PropertyFileConfiguration.java,v 1.10 2008/09/10 09:17:28 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 14-Jan-2003 : Initial version
+ */
+package org.jfree.base.config;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.jfree.util.Log;
+import org.jfree.util.ObjectUtilities;
+
+/**
+ * A report configuration that reads its values from an arbitary property file.
+ *
+ * @author Thomas Morgner
+ */
+public class PropertyFileConfiguration extends HierarchicalConfiguration
+{
+  /**
+   * Default constructor.
+   */
+  public PropertyFileConfiguration() {
+      // nothing required
+  }
+
+  /**
+   * Load the properties in the given file.
+   *
+   * @param resourceName  the file name.
+   */
+  public void load(final String resourceName)
+  {
+    load(resourceName, PropertyFileConfiguration.class);
+  }
+
+  /**
+   * Loads the properties stored in the given file. This method does nothing if
+   * the file does not exist or is unreadable. Appends the contents of the loaded
+   * properties to the already stored contents.
+   *
+   * @param resourceName the file name of the stored properties.
+   * @param resourceSource ?
+   */
+  public void load(final String resourceName, final Class resourceSource)
+  {
+    final InputStream in = ObjectUtilities.getResourceRelativeAsStream
+            (resourceName, resourceSource);
+    if (in != null)
+    {
+      try
+      {
+        load(in);
+      }
+      finally
+      {
+        try
+        {
+          in.close();
+        }
+        catch (IOException e)
+        {
+          // ignore
+        }
+      }
+    }
+    else
+    {
+      Log.debug ("Configuration file not found in the classpath: " + resourceName);
+    }
+
+  }
+
+  /**
+   * Loads the properties stored in the given file. This method does nothing if
+   * the file does not exist or is unreadable. Appends the contents of the loaded
+   * properties to the already stored contents.
+   *
+   * @param in the input stream used to read the properties.
+   */
+  public void load(final InputStream in)
+  {
+    if (in == null)
+    {
+      throw new NullPointerException();
+    }
+
+    try
+    {
+      final BufferedInputStream bin = new BufferedInputStream(in);
+      final Properties p = new Properties();
+      p.load(bin);
+      this.getConfiguration().putAll(p);
+      bin.close();
+    }
+    catch (IOException ioe)
+    {
+      Log.warn("Unable to read configuration", ioe);
+    }
+
+  }
+
+}

+ 131 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/config/SystemPropertyConfiguration.java

@@ -0,0 +1,131 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * --------------------------------
+ * SystemPropertyConfiguration.java
+ * --------------------------------
+ * (C)opyright 2002-2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner
+ * Contributor(s):   Stefan Prange;
+ *
+ * $Id: SystemPropertyConfiguration.java,v 1.3 2005/10/18 13:14:12 mungady Exp $
+ *
+ * Changes (from 8-Feb-2002)
+ * -------------------------
+ * 14-Jan-2003 : Initial Version, moved from inner class of ReportConfiguration
+ * 05-Feb-2003 : This implementation now handles SecurityExceptions.
+ * 
+ */
+
+package org.jfree.base.config;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * A property configuration based on system properties.
+ *
+ * @author Thomas Morgner
+ */
+public class SystemPropertyConfiguration extends HierarchicalConfiguration {
+
+    /**
+     * Creates a report configuration that includes all the system properties (whether they are
+     * related to reports or not).  The parent configuration is a
+     * <code>PropertyFileConfiguration</code>.
+     */
+    public SystemPropertyConfiguration() {
+    }
+
+    /**
+     * Sets a configuration property.
+     *
+     * @param key  the property key.
+     * @param value  the property value.
+     */
+    public void setConfigProperty(final String key, final String value) {
+        throw new UnsupportedOperationException("The SystemPropertyConfiguration is readOnly");
+    }
+
+    /**
+     * Returns the configuration property with the specified key (or the specified default value
+     * if there is no such property).
+     * <p>
+     * If the property is not defined in this configuration, the code will lookup the property in
+     * the parent configuration.
+     *
+     * @param key  the property key.
+     * @param defaultValue  the default value.
+     *
+     * @return the property value.
+     */
+    public String getConfigProperty(final String key, final String defaultValue) {
+        try {
+            final String value = System.getProperty(key);
+            if (value != null) {
+               return value;
+            }
+        }
+        catch (SecurityException se) {
+            // ignore security exceptions, continue as if the property was not set..
+        }
+        return super.getConfigProperty(key, defaultValue);
+    }
+
+    /**
+     * Checks, whether the given key is locally defined in the system properties.
+     * @see HierarchicalConfiguration#isLocallyDefined(java.lang.String)
+     *
+     * @param key the key that should be checked.
+     * @return true, if the key is defined in the system properties, false otherwise.
+     */
+    public boolean isLocallyDefined(final String key) {
+        try {
+            return System.getProperties().containsKey(key);
+        }
+        catch (SecurityException se) {
+            return false;
+        }
+    }
+
+    /**
+     * Returns all defined configuration properties for the report. The enumeration
+     * contains all keys of the changed properties, properties set from files or
+     * the system properties are not included.
+     *
+     * @return all defined configuration properties for the report.
+     */
+    public Enumeration getConfigProperties() {
+        try {
+            return System.getProperties().keys();
+        }
+        catch (SecurityException se) {
+            // should return an empty enumeration ...
+            return new Vector().elements();
+        }
+    }
+}

+ 43 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/jcommon.properties

@@ -0,0 +1,43 @@
+#
+# The minimum loglevel that is logged
+org.jfree.base.LogLevel=Debug
+
+#
+# Where to log. Give a classname of a  valid LogTarget implementation.
+# If the name is invalid, no logging is done.
+org.jfree.base.LogTarget=*none*
+
+#
+# Do not initialize the logging.
+org.jfree.base.LogAutoInit=false
+
+#
+# Should the debugging system be disabled by default. This option will suppress all
+# output, no single line of debug information will be printed. If you want to remove
+# System.out-debugging on the server side, try to switch to a Log4J-LogTarget instead.
+org.jfree.base.NoDefaultDebug=false
+
+#
+# Which ClassLoader to use for loading external resources and classes.
+# One of "ThreadContext" or "CallerContext".
+org.jfree.ClassLoader=ThreadContext
+
+#
+# Applies a workaround to fix a JDK bug. When the value is set to auto,
+# This is enabled if the JDK is not version 1.4 or higher.
+org.jfree.text.UseDrawRotatedStringWorkaround=auto
+
+#
+# Applies a workaround to fix a JDK bug. When the value is set to auto,
+# This is disabled if the JDK is not version 1.4 or higher.
+org.jfree.text.UseFontMetricsGetStringBounds=auto
+
+
+#
+# Known extra modules. Do not edit and do not delete the following lines.
+#
+# That module loading mechanism is not really extensible. A better
+# implementation might solve that at a later time.  
+org.jfree.jcommon.modules.logger.Log4J.Module=org.jfree.logger.java14.Java14LogModule
+org.jfree.jcommon.modules.logger.Java14Logging.Module=org.jfree.logger.log4j.Log4JLogModule
+org.jfree.jcommon.modules.logger.JakartaLogging.Module=org.jfree.logger.jcl.JakartaLogModule

+ 143 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/log/DefaultLog.java

@@ -0,0 +1,143 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ---------------
+ * DefaultLog.java
+ * ---------------
+ * (C) Copyright 2004, by Object Refinery Limited.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: DefaultLog.java,v 1.9 2006/02/19 21:10:48 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jun-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.base.log;
+
+import org.jfree.util.Log;
+import org.jfree.util.LogTarget;
+import org.jfree.util.PrintStreamLogTarget;
+
+/**
+ * A default log implementation. The Log class defines how to create Logger-contexts
+ * and how to forward messages to the logtargets.
+ *
+ * @author Thomas Morgner
+ */
+public class DefaultLog extends Log {
+
+    /** The default log target. */
+    private static final PrintStreamLogTarget DEFAULT_LOG_TARGET =
+          new PrintStreamLogTarget();
+
+    /** The default log instance. */
+    private static final DefaultLog defaultLogInstance;
+
+    /**
+     * Creates a new log.
+     */
+    protected DefaultLog () {
+        // nothing required
+    }
+
+    static {
+        defaultLogInstance = new DefaultLog();
+        defaultLogInstance.addTarget(DEFAULT_LOG_TARGET);
+        try {
+            // check the system property. This is the developers backdoor to activate
+            // debug output as soon as possible.
+          final String property = System.getProperty("org.jfree.DebugDefault", "false");
+          if (Boolean.valueOf(property).booleanValue()) {
+              defaultLogInstance.setDebuglevel(LogTarget.DEBUG);
+          }
+          else {
+              defaultLogInstance.setDebuglevel(LogTarget.WARN);
+          }
+        }
+        catch (SecurityException se) {
+            defaultLogInstance.setDebuglevel(LogTarget.WARN);
+        }
+    }
+
+    /**
+     * Initializes the log system after the log module was loaded and a log target
+     * was defined. This is the second step of the log initialisation.
+     */
+    public void init() {
+        removeTarget(DEFAULT_LOG_TARGET);
+        final String logLevel = LogConfiguration.getLogLevel();
+        if (logLevel.equalsIgnoreCase("error")) {
+            setDebuglevel(LogTarget.ERROR);
+        }
+        else if (logLevel.equalsIgnoreCase("warn")) {
+            setDebuglevel(LogTarget.WARN);
+        }
+        else if (logLevel.equalsIgnoreCase("info")) {
+            setDebuglevel(LogTarget.INFO);
+        }
+        else if (logLevel.equalsIgnoreCase("debug")) {
+            setDebuglevel(LogTarget.DEBUG);
+        }
+    }
+
+    /**
+     * Adds a log target to this facility. Log targets get informed, via the
+     * LogTarget interface, whenever a message is logged with this class.
+     *
+     * @param target the target.
+     */
+    public synchronized void addTarget(final LogTarget target)
+    {
+      super.addTarget(target);
+      // as soon as there is a real log target added, we do no longer need
+      // the default logging. This was only installed to be able to send messages
+      // if the deepest basic logging failed.
+      if (target != DEFAULT_LOG_TARGET) {
+          removeTarget(DEFAULT_LOG_TARGET);
+      }
+    }
+
+  /**
+     * Returns the default log.
+     * 
+     * @return The default log.
+     */
+    public static DefaultLog getDefaultLog() {
+        return defaultLogInstance;
+    }
+
+    /**
+     * Makes this implementation the default instance.
+     */
+    public static void installDefaultLog () {
+      Log.defineLog(defaultLogInstance);
+    }
+}

+ 103 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/log/DefaultLogModule.java

@@ -0,0 +1,103 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ---------------------
+ * DefaultLogModule.java
+ * ---------------------
+ * (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: DefaultLogModule.java,v 1.8 2005/12/18 23:29:18 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 11-Jul-2003 : Initial version
+ * 07-Jun-2004 : Added JCommon header (DG);
+ * 25-Nov-2005 : The initialization was overly complicated. There is only
+ *               one logtarget here, and additional targets should create
+ *               an dependent module.
+ */
+
+package org.jfree.base.log;
+
+import org.jfree.base.modules.AbstractModule;
+import org.jfree.base.modules.ModuleInitializeException;
+import org.jfree.base.modules.SubSystem;
+import org.jfree.util.Log;
+import org.jfree.util.PrintStreamLogTarget;
+
+/**
+ * The module definition for the System.out-Logging. This is the default log
+ * implementation and is provided to insert the logging initialisation in the
+ * module loading process.
+ *
+ * @author Thomas Morgner
+ */
+public class DefaultLogModule extends AbstractModule
+{
+  /**
+   * DefaultConstructor. Loads the module specification.
+   *
+   * @throws ModuleInitializeException if an error occured.
+   */
+  public DefaultLogModule() throws ModuleInitializeException
+  {
+    loadModuleInfo();
+  }
+
+  /**
+   * Initalizes the module. This method initializes the logging system, if the
+   * System.out logtarget is selected.
+   *
+   * @param subSystem the sub-system.
+   * @throws ModuleInitializeException if an error occured.
+   */
+  public void initialize(final SubSystem subSystem)
+          throws ModuleInitializeException
+  {
+    if (LogConfiguration.isDisableLogging())
+    {
+      return;
+    }
+
+    if (LogConfiguration.getLogTarget().equals
+            (PrintStreamLogTarget.class.getName()))
+    {
+      DefaultLog.installDefaultLog();
+      Log.getInstance().addTarget(new PrintStreamLogTarget());
+
+      if ("true".equals(subSystem.getGlobalConfig().getConfigProperty
+              ("org.jfree.base.LogAutoInit")))
+      {
+        Log.getInstance().init();
+      }
+      Log.info("Default log target started ... previous log messages " +
+              "could have been ignored.");
+    }
+  }
+}

+ 168 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/log/LogConfiguration.java

@@ -0,0 +1,168 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ---------------------
+ * LogConfiguration.java
+ * ---------------------
+ * (C) Copyright 2004, by Object Refinery Limited.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: LogConfiguration.java,v 1.6 2005/12/18 23:29:18 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jun-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.base.log;
+
+import org.jfree.base.BaseBoot;
+import org.jfree.util.PrintStreamLogTarget;
+
+/**
+ * A log configuration class. This implementation is a simple frontend
+ * to the global configuration.
+ *
+ * @author Thomas Morgner
+ */
+public class LogConfiguration {
+  /** The default 'disable logging' property value. */
+  public static final String DISABLE_LOGGING_DEFAULT = "false";
+
+  /** The 'log level' property key. */
+  public static final String LOGLEVEL = "org.jfree.base.LogLevel";
+
+  /** The default 'log level' property value. */
+  public static final String LOGLEVEL_DEFAULT = "Info";
+
+  /** The 'log target' property key. */
+  public static final String LOGTARGET = "org.jfree.base.LogTarget";
+
+  /** The default 'log target' property value. */
+  public static final String LOGTARGET_DEFAULT =
+          PrintStreamLogTarget.class.getName();
+
+  /** The 'disable logging' property key. */
+  public static final String DISABLE_LOGGING = "org.jfree.base.NoDefaultDebug"; 
+
+  /**
+   * Default constructor.
+   */
+  private LogConfiguration() {
+      // nothing required.
+  }
+
+  /**
+   * Returns the current log target.
+   *
+   * @return the log target.
+   */
+  public static String getLogTarget()
+  {
+    return BaseBoot.getInstance().getGlobalConfig().getConfigProperty
+            (LOGTARGET, LOGTARGET_DEFAULT);
+  }
+
+  /**
+   * Sets the log target.
+   *
+   * @param logTarget  the new log target.
+   */
+  public static void setLogTarget(final String logTarget)
+  {
+      BaseBoot.getConfiguration().setConfigProperty (LOGTARGET, logTarget);
+  }
+
+  /**
+   * Returns the log level.
+   *
+   * @return the log level.
+   */
+  public static String getLogLevel()
+  {
+    return BaseBoot.getInstance().getGlobalConfig().getConfigProperty
+            (LOGLEVEL, LOGLEVEL_DEFAULT);
+  }
+
+  /**
+   * Sets the log level, which is read from the global report configuration at
+   * the point that the classloader loads the {@link org.jfree.util.Log} class.
+   * <p>
+   * Valid log levels are:
+   *
+   * <ul>
+   * <li><code>"Error"</code> - error messages;</li>
+   * <li><code>"Warn"</code> - warning messages;</li>
+   * <li><code>"Info"</code> - information messages;</li>
+   * <li><code>"Debug"</code> - debug messages;</li>
+   * </ul>
+   *
+   * Notes:
+   * <ul>
+   * <li>the setting is not case sensitive.</li>
+   * <li>changing the log level after the {@link org.jfree.util.Log} class has been
+   * loaded will have no effect.</li>
+   * <li>to turn of logging altogether, use the {@link #setDisableLogging} method.</li>
+   * </ul>
+   *
+   * @param level  the new log level.
+   */
+  public static void setLogLevel(final String level)
+  {
+    BaseBoot.getConfiguration().setConfigProperty(LOGLEVEL, level);
+  }
+
+  /**
+   * Returns <code>true</code> if logging is disabled, and <code>false</code> otherwise.
+   *
+   * @return true, if logging is completly disabled, false otherwise.
+   */
+  public static boolean isDisableLogging()
+  {
+    return BaseBoot.getInstance().getGlobalConfig().getConfigProperty
+        (DISABLE_LOGGING, DISABLE_LOGGING_DEFAULT).equalsIgnoreCase("true");
+  }
+
+  /**
+   * Sets the flag that disables logging.
+   * <p>
+   * To switch off logging globally, you can use the following code:
+   * <p>
+   * <code>ReportConfiguration.getGlobalConfig().setDisableLogging(true);</code>
+   *
+   * @param disableLogging  the flag.
+   */
+  public static void setDisableLogging(final boolean disableLogging)
+  {
+    BaseBoot.getConfiguration().setConfigProperty
+            (DISABLE_LOGGING, String.valueOf(disableLogging));
+  }
+
+
+}

+ 74 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/log/MemoryUsageMessage.java

@@ -0,0 +1,74 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -----------------------
+ * MemoryUsageMessage.java
+ * -----------------------
+ * (C) Copyright 2004, by Object Refinery Limited.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: MemoryUsageMessage.java,v 1.3 2005/10/18 13:14:33 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 15-Jul-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.base.log;
+
+/**
+ * A helper class to print memory usage message if needed.
+ *
+ * @author Thomas Morgner
+ */
+public class MemoryUsageMessage {
+
+    /** The message. */
+    private final String message;
+
+    /**
+     * Creates a new message.
+     *
+     * @param message  the message.
+     */
+    public MemoryUsageMessage(final String message) {
+        this.message = message;
+    }
+
+    /**
+     * Returns a string representation of the message (useful for debugging).
+     *
+     * @return the string.
+     */
+    public String toString() {
+        return this.message + "Free: " + Runtime.getRuntime().freeMemory() + "; "
+            + "Total: " + Runtime.getRuntime().totalMemory();
+    }
+    
+}

+ 93 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/log/PadMessage.java

@@ -0,0 +1,93 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ---------------
+ * PadMessage.java
+ * ---------------
+ * (C) Copyright 2004, by Object Refinery Limited.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: PadMessage.java,v 1.4 2005/10/18 13:14:33 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 15-Jul-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.base.log;
+
+import java.util.Arrays;
+
+/**
+ * A message object that pads the output if the text is shorter than
+ * the given length. This is usefull when concating multiple messages,
+ * which should appear in a table like style.
+ *
+ * @author Thomas Morgner
+ */
+public class PadMessage {
+
+    /**
+     * The message.
+     */
+    private final Object text;
+  
+    /**
+     * The padding size.
+     */
+    private final int length;
+
+    /**
+     * Creates a new message.
+     *
+     * @param message the message.
+     * @param length  the padding size.
+     */
+    public PadMessage(final Object message, final int length) {
+        this.text = message;
+        this.length = length;
+    }
+
+    /**
+     * Returns a string representation of the message.
+     *
+     * @return the string.
+     */
+    public String toString() {
+        final StringBuffer b = new StringBuffer();
+        b.append(this.text);
+        if (b.length() < this.length) {
+            final char[] pad = new char[this.length - b.length()];
+            Arrays.fill(pad, ' ');
+            b.append(pad);
+        }
+        return b.toString();
+    }
+    
+}

+ 14 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/log/module.properties

@@ -0,0 +1,14 @@
+#
+# Support for logging.
+#
+
+module-info:
+  name: base-logging-module
+  producer: The JFreeChart project - www.jfree.org/jcommon
+  description: Initialializer to configure the log system and to provide
+               a facility for logging to the System.out stream.
+  version.major: 1
+  version.minor: 0
+  version.patchlevel: 0
+  subsystem: logging
+

+ 811 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/AbstractModule.java

@@ -0,0 +1,811 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * -------------------
+ * AbstractModule.java
+ * -------------------
+ * (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: AbstractModule.java,v 1.7 2008/09/10 09:16:54 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 05-Jul-2003 : Initial version
+ * 07-Jun-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.base.modules;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+
+import org.jfree.util.ObjectUtilities;
+
+
+/**
+ * The abstract module provides a default implementation of the module interface.
+ * <p>
+ * The module can be specified in an external property file. The file name of this
+ * specification defaults to "module.properties". This file is no real property file,
+ * it follows a more complex rule set.</p>
+ * <p>
+ * Lines starting with '#' are considered comments.
+ * Section headers start at the beginning of the line, section properties
+ * are indented with at least one whitespace.</p>
+ * <p>
+ * The first section is always the module info and contains the basic module
+ * properties like name, version and a short description.</p>
+ * 
+ * <pre>
+ * module-info:
+ *   name: xls-export-gui
+ *   producer: The JFreeReport project - www.jfree.org/jfreereport
+ *   description: A dialog component for the Excel table export.
+ *   version.major: 0
+ *   version.minor: 84
+ *   version.patchlevel: 0
+ * </pre>
+ * The properties name, producer and description are simple strings. They may
+ * span multiple lines, but may not contain a colon (':').
+ * The version properties are integer values.
+ * <p>
+ * This section may be followed by one or more "depends" sections. These
+ * sections describe the base modules that are required to be active to make this
+ * module work. The package manager will enforce this policy and will deactivate this
+ * module if one of the base modules is missing.</p>
+ * 
+ * <pre>
+ * depends:
+ *   module: org.jfree.report.modules.output.table.xls.XLSTableModule
+ *   version.major: 0
+ *   version.minor: 84
+ * </pre>
+ * <p>
+ * The property module references to the module implementation of the module package.
+ *
+ * @author Thomas Morgner
+ */
+public abstract class AbstractModule extends DefaultModuleInfo implements Module
+{
+  /**
+   * The reader helper provides a pushback interface for the reader to read and
+   * buffer  complete lines.
+   * @author Thomas Morgner
+   */
+  private static class ReaderHelper
+  {
+    /** The line buffer containing the last line read. */
+    private String buffer;
+    /** The reader from which to read the text. */
+    private final BufferedReader reader;
+
+    /**
+     * Creates a new reader helper for the given buffered reader.
+     *
+     * @param reader the buffered reader that is the source of the text.
+     */
+    protected ReaderHelper(final BufferedReader reader)
+    {
+      this.reader = reader;
+    }
+
+    /**
+     * Checks, whether the reader contains a next line. Returns false if the end
+     * of the stream has been reached.
+     *
+     * @return true, if there is a next line to read, false otherwise.
+     * @throws IOException if an error occures.
+     */
+    public boolean hasNext() throws IOException
+    {
+      if (this.buffer == null)
+      {
+        this.buffer = readLine();
+      }
+      return this.buffer != null;
+    }
+
+    /**
+     * Returns the next line.
+     *
+     * @return the next line.
+     */
+    public String next()
+    {
+      final String line = this.buffer;
+      this.buffer = null;
+      return line;
+    }
+
+    /**
+     * Pushes the given line back into the buffer. Only one line can be contained in
+     * the buffer at one time.
+     *
+     * @param line the line that should be pushed back into the buffer.
+     */
+    public void pushBack(final String line)
+    {
+      this.buffer = line;
+    }
+
+    /**
+     * Reads the next line skipping all comment lines.
+     *
+     * @return the next line, or null if no line can be read.
+     * @throws IOException if an IO error occures.
+     */
+    protected String readLine() throws IOException
+    {
+      String line = this.reader.readLine();
+      while (line != null && (line.length() == 0 || line.startsWith("#")))
+      {
+        // empty line or comment is ignored
+        line = this.reader.readLine();
+      }
+      return line;
+    }
+
+    /**
+     * Closes the reader.
+     *
+     * @throws IOException if an IOError occurs.
+     */
+    public void close() throws IOException
+    {
+      this.reader.close();
+    }
+  }
+
+  /** The list of required modules. */
+  private ModuleInfo[] requiredModules;
+  /** The list of optional modules. */
+  private ModuleInfo[] optionalModules;
+
+  /** The name of the module. */
+  private String name;
+  /** A short description of the module. */
+  private String description;
+  /** The name of the module producer. */
+  private String producer;
+  /** The modules subsystem. */
+  private String subsystem;
+
+  /**
+   * Default Constructor.
+   */
+  public AbstractModule()
+  {
+    setModuleClass(this.getClass().getName());
+  }
+
+  /**
+   * Loads the default module description from the file "module.properties". This file
+   * must be in the same package as the implementing class.
+   *
+   * @throws ModuleInitializeException if an error occurs.
+   */
+  protected void loadModuleInfo() throws ModuleInitializeException
+  {
+    final InputStream in = ObjectUtilities.getResourceRelativeAsStream
+            ("module.properties", getClass());
+    if (in == null)
+    {
+      throw new ModuleInitializeException
+          ("File 'module.properties' not found in module package.");
+    }
+
+    loadModuleInfo(in);
+  }
+
+  /**
+   * Loads the module descriptiong from the given input stream. The module description
+   * must conform to the rules define in the class description. The file must be encoded
+   * with "ISO-8859-1" (like property files).
+   *
+   * @param in the input stream from where to read the file
+   * @throws ModuleInitializeException if an error occurs.
+   */
+  protected void loadModuleInfo(final InputStream in) throws ModuleInitializeException
+  {
+    if (in == null)
+    {
+      throw new NullPointerException
+          ("Given InputStream is null.");
+    }
+
+    try
+    {
+      final ArrayList optionalModules = new ArrayList();
+      final ArrayList dependendModules = new ArrayList();
+      final ReaderHelper rh = new ReaderHelper(new BufferedReader
+          (new InputStreamReader(in, "ISO-8859-1")));
+      try
+      {
+        while (rh.hasNext())
+        {
+          final String lastLineRead = rh.next();
+          if (lastLineRead.startsWith("module-info:"))
+          {
+            readModuleInfo(rh);
+          }
+          else if (lastLineRead.startsWith("depends:"))
+          {
+            dependendModules.add(readExternalModule(rh));
+          }
+          else if (lastLineRead.startsWith("optional:"))
+          {
+            optionalModules.add(readExternalModule(rh));
+          }
+          else
+          {
+            // we dont understand the current line, so we skip it ...
+            // should we throw a parse exception instead?
+          }
+        }
+      }
+      finally
+      {
+        rh.close();
+      }
+
+      this.optionalModules = (ModuleInfo[])
+          optionalModules.toArray(new ModuleInfo[optionalModules.size()]);
+
+      this.requiredModules = (ModuleInfo[])
+          dependendModules.toArray(new ModuleInfo[dependendModules.size()]);
+    }
+    catch (IOException ioe)
+    {
+      throw new ModuleInitializeException("Failed to load properties", ioe);
+    }
+  }
+
+  /**
+   * Reads a multiline value the stream. This will read the stream until
+   * a new key is found or the end of the file is reached.
+   *
+   * @param reader the reader from where to read.
+   * @param firstLine the first line (which was read elsewhere).
+   * @return the complete value, never null
+   * @throws IOException if an IO error occurs.
+   */
+  private String readValue(final ReaderHelper reader, String firstLine) throws IOException
+  {
+    final StringBuffer b = new StringBuffer(firstLine.trim());
+    boolean newLine = true;
+    while (isNextLineValueLine(reader))
+    {
+      firstLine = reader.next();
+      final String trimedLine = firstLine.trim();
+      if (trimedLine.length() == 0 && (newLine == false))
+      {
+        b.append ("\n");
+        newLine = true;
+      }
+      else
+      {
+        if (newLine == false)
+        {
+          b.append(" ");
+        }
+        b.append(parseValue(trimedLine));
+        newLine = false;
+      }
+    }
+    return b.toString();
+  }
+
+  /**
+   * Checks, whether the next line in the reader is a value line.
+   *
+   * @param reader from where to read the lines.
+   * @return true, if the next line is a value line, false otherwise.
+   * @throws IOException if an IO error occurs.
+   */
+  private boolean isNextLineValueLine (final ReaderHelper reader) throws IOException
+  {
+    if (reader.hasNext() == false)
+    {
+      return false;
+    }
+    final String firstLine = reader.next();
+    if (firstLine == null)
+    {
+      return false;
+    }
+    if (parseKey(firstLine) != null)
+    {
+      reader.pushBack(firstLine);
+      return false;
+    }
+    reader.pushBack(firstLine);
+    return true;
+  }
+
+  /**
+   * Reads the module definition header. This header contains information about
+   * the module itself.
+   *
+   * @param reader the reader from where to read the content.
+   * @throws IOException if an error occures
+   */
+  private void readModuleInfo(final ReaderHelper reader) throws IOException
+  {
+    while (reader.hasNext())
+    {
+      final String lastLineRead = reader.next();
+
+      if (Character.isWhitespace(lastLineRead.charAt(0)) == false)
+      {
+        // break if the current character is no whitespace ...
+        reader.pushBack(lastLineRead);
+        return;
+      }
+
+      final String line = lastLineRead.trim();
+      final String key = parseKey(line);
+      if (key != null)
+      {
+        // parse error: Non data line does not contain a colon
+        final String b = readValue(reader, parseValue(line.trim()));
+
+        if ("name".equals(key))
+        {
+          setName(b);
+        }
+        else if ("producer".equals(key))
+        {
+          setProducer(b);
+        }
+        else if ("description".equals(key))
+        {
+          setDescription(b);
+        }
+        else if ("subsystem".equals(key))
+        {
+          setSubSystem(b);
+        }
+        else if ("version.major".equals(key))
+        {
+          setMajorVersion(b);
+        }
+        else if ("version.minor".equals(key))
+        {
+          setMinorVersion(b);
+        }
+        else if ("version.patchlevel".equals(key))
+        {
+          setPatchLevel(b);
+        }
+      }
+    }
+  }
+
+  /**
+   * Parses an string to find the key section of the line. This section ends with
+   * an colon.
+   *
+   * @param line the line which to parse
+   * @return the key or null if no key is found.
+   */
+  private String parseKey(final String line)
+  {
+    final int idx = line.indexOf(':');
+    if (idx == -1)
+    {
+      return null;
+    }
+    return line.substring(0, idx);
+  }
+
+  /**
+   * Parses the value section of the given line.
+   *
+   * @param line the line that should be parsed
+   * @return the value, never null
+   */
+  private String parseValue(final String line)
+  {
+    final int idx = line.indexOf(':');
+    if (idx == -1)
+    {
+      return line;
+    }
+    if ((idx + 1) == line.length())
+    {
+      return "";
+    }
+    return line.substring(idx + 1);
+  }
+
+  /**
+   * Reads an external module description. This describes either an optional or
+   * a required module.
+   *
+   * @param reader the reader from where to read the module
+   * @return the read module, never null
+   * @throws IOException if an error occures.
+   */
+  private DefaultModuleInfo readExternalModule(final ReaderHelper reader)
+      throws IOException
+  {
+    final DefaultModuleInfo mi = new DefaultModuleInfo();
+
+    while (reader.hasNext())
+    {
+      final String lastLineRead = reader.next();
+
+      if (Character.isWhitespace(lastLineRead.charAt(0)) == false)
+      {
+        // break if the current character is no whitespace ...
+        reader.pushBack(lastLineRead);
+        return mi;
+      }
+
+      final String line = lastLineRead.trim();
+      final String key = parseKey(line);
+      if (key != null)
+      {
+        final String b = readValue(reader, parseValue(line));
+        if ("module".equals(key))
+        {
+          mi.setModuleClass(b);
+        }
+        else if ("version.major".equals(key))
+        {
+          mi.setMajorVersion(b);
+        }
+        else if ("version.minor".equals(key))
+        {
+          mi.setMinorVersion(b);
+        }
+        else if ("version.patchlevel".equals(key))
+        {
+          mi.setPatchLevel(b);
+        }
+      }
+    }
+    return mi;
+  }
+
+  /**
+   * Returns the name of this module.
+   *
+   * @see Module#getName()
+   *
+   * @return the module name
+   */
+  public String getName()
+  {
+    return this.name;
+  }
+
+  /**
+   * Defines the name of the module.
+   *
+   * @param name the module name.
+   */
+  protected void setName(final String name)
+  {
+    this.name = name;
+  }
+
+  /**
+   * Returns the module description.
+   * @see Module#getDescription()
+   *
+   * @return the description of the module.
+   */
+  public String getDescription()
+  {
+    return this.description;
+  }
+
+  /**
+   * Defines the description of the module.
+   *
+   * @param description the module's desciption.
+   */
+  protected void setDescription(final String description)
+  {
+    this.description = description;
+  }
+
+  /**
+   * Returns the producer of the module.
+   *
+   * @see Module#getProducer()
+   *
+   * @return the producer.
+   */
+  public String getProducer()
+  {
+    return this.producer;
+  }
+
+  /**
+   * Defines the producer of the module.
+   *
+   * @param producer the producer.
+   */
+  protected void setProducer(final String producer)
+  {
+    this.producer = producer;
+  }
+
+  /**
+   * Returns a copy of the required modules array. This array contains all
+   * description of the modules that need to be present to make this module work.
+   * @see Module#getRequiredModules()
+   *
+   * @return an array of all required modules.
+   */
+  public ModuleInfo[] getRequiredModules()
+  {
+    final ModuleInfo[] retval = new ModuleInfo[this.requiredModules.length];
+    System.arraycopy(this.requiredModules, 0, retval, 0, this.requiredModules.length);
+    return retval;
+  }
+
+  /**
+   * Returns a copy of the required modules array. This array contains all
+   * description of the optional modules that may improve the modules functonality.
+   * @see Module#getRequiredModules()
+   *
+   * @return an array of all required modules.
+   */
+  public ModuleInfo[] getOptionalModules()
+  {
+    final ModuleInfo[] retval = new ModuleInfo[this.optionalModules.length];
+    System.arraycopy(this.optionalModules, 0, retval, 0, this.optionalModules.length);
+    return retval;
+  }
+
+  /**
+   * Defines the required module descriptions for this module.
+   *
+   * @param requiredModules the required modules.
+   */
+  protected void setRequiredModules(final ModuleInfo[] requiredModules)
+  {
+    this.requiredModules = new ModuleInfo[requiredModules.length];
+    System.arraycopy(requiredModules, 0, this.requiredModules, 0, requiredModules.length);
+  }
+
+  /**
+   * Defines the optional module descriptions for this module.
+   *
+   * @param optionalModules the optional modules.
+   */
+  public void setOptionalModules(final ModuleInfo[] optionalModules)
+  {
+    this.optionalModules = new ModuleInfo[optionalModules.length];
+    System.arraycopy(optionalModules, 0, this.optionalModules, 0, optionalModules.length);
+  }
+
+  /**
+   * Returns a string representation of this module.
+   * @see java.lang.Object#toString()
+   *
+   * @return the string representation of this module for debugging purposes.
+   */
+  public String toString()
+  {
+    final StringBuffer buffer = new StringBuffer();
+    buffer.append("Module : ");
+    buffer.append(getName());
+    buffer.append("\n");
+    buffer.append("ModuleClass : ");
+    buffer.append(getModuleClass());
+    buffer.append("\n");
+    buffer.append("Version: ");
+    buffer.append(getMajorVersion());
+    buffer.append(".");
+    buffer.append(getMinorVersion());
+    buffer.append(".");
+    buffer.append(getPatchLevel());
+    buffer.append("\n");
+    buffer.append("Producer: ");
+    buffer.append(getProducer());
+    buffer.append("\n");
+    buffer.append("Description: ");
+    buffer.append(getDescription());
+    buffer.append("\n");
+    return buffer.toString();
+  }
+
+  /**
+   * Tries to load a class to indirectly check for the existence
+   * of a certain library.
+   *
+   * @param name the name of the library class.
+   * @return true, if the class could be loaded, false otherwise.
+   * @deprecated use the method that passes in a context-class.
+   */
+  protected static boolean isClassLoadable(final String name)
+  {
+    try
+    {
+      final ClassLoader loader = ObjectUtilities.getClassLoader(AbstractModule.class);
+      if (loader == null)
+      {
+        // this should not happen .. If it happens, it measn we dont even have a system-classloader.
+        return false;
+      }
+      loader.loadClass(name);
+      return true;
+    }
+    catch (Exception e)
+    {
+      return false;
+    }
+  }
+
+  /**
+   * Tries to load a class to indirectly check for the existence
+   * of a certain library.
+   *
+   * @param name the name of the library class.
+   * @param context the context class to get a classloader from.
+   * @return true, if the class could be loaded, false otherwise.
+   */
+  protected static boolean isClassLoadable(final String name, final Class context)
+  {
+    try
+    {
+      ObjectUtilities.getClassLoader(context).loadClass(name);
+      return true;
+    }
+    catch (Exception e)
+    {
+      return false;
+    }
+  }
+
+  /**
+   * Configures the module by loading the configuration properties and
+   * adding them to the package configuration.
+   *
+   * @param subSystem  the subsystem.
+   */
+  public void configure(final SubSystem subSystem)
+  {
+    final InputStream in = ObjectUtilities.getResourceRelativeAsStream
+            ("configuration.properties", getClass());
+    if (in == null)
+    {
+      return;
+    }
+    try
+    {
+      subSystem.getPackageManager().getPackageConfiguration().load(in);
+    }
+    finally
+    {
+      try
+      {
+        in.close();
+      }
+      catch (IOException e)
+      {
+        // can be ignored ...
+      }
+    }
+  }
+
+  /**
+   * Tries to load an module initializer and uses this initializer to initialize
+   * the module.
+   *
+   * @param classname the class name of the initializer.
+   * @throws ModuleInitializeException if an error occures
+   * @deprecated Use the method that provides a class-context instead.
+   */
+  protected void performExternalInitialize(final String classname)
+      throws ModuleInitializeException
+  {
+    try
+    {
+      final ModuleInitializer mi =
+          (ModuleInitializer) ObjectUtilities.loadAndInstantiate(classname, AbstractModule.class, ModuleInitializer.class);
+      if (mi == null)
+      {
+        throw new ModuleInitializeException("Failed to load specified initializer class.");
+      }
+      mi.performInit();
+    }
+    catch (ModuleInitializeException mie)
+    {
+      throw mie;
+    }
+    catch (Exception e)
+    {
+      throw new ModuleInitializeException("Failed to load specified initializer class.", e);
+    }
+  }
+
+  /**
+   * ???.
+   *
+   * @param classname ?
+   * @param context ?
+   * @throws ModuleInitializeException if there is an initialisation error.
+   */
+  protected void performExternalInitialize(final String classname, final Class context)
+      throws ModuleInitializeException
+  {
+    try
+    {
+      final ModuleInitializer mi =
+          (ModuleInitializer) ObjectUtilities.loadAndInstantiate(classname, context, ModuleInitializer.class);
+      if (mi == null)
+      {
+        throw new ModuleInitializeException("Failed to load specified initializer class.");
+      }
+      mi.performInit();
+    }
+    catch (ModuleInitializeException mie)
+    {
+      throw mie;
+    }
+    catch (Exception e)
+    {
+      throw new ModuleInitializeException("Failed to load specified initializer class.", e);
+    }
+  }
+
+  /**
+   * Returns the modules subsystem. If this module is not part of an subsystem
+   * then return the modules name, but never null.
+   *
+   * @return the name of the subsystem.
+   */
+  public String getSubSystem()
+  {
+    if (this.subsystem == null)
+    {
+      return getName();
+    }
+    return this.subsystem;
+  }
+
+  /**
+   * Defines the subsystem name for this module.
+   *
+   * @param name the new name of the subsystem.
+   */
+  protected void setSubSystem (final String name)
+  {
+    this.subsystem = name;
+  }
+}

+ 260 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/DefaultModuleInfo.java

@@ -0,0 +1,260 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ----------------------
+ * DefaultModuleInfo.java
+ * ----------------------
+ * (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: DefaultModuleInfo.java,v 1.2 2005/10/18 13:14:50 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 05-Jul-2003 : Initial version
+ * 07-Jun-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.base.modules;
+
+/**
+ * Provides a default implementation of the module info interface.
+ *
+ * @author Thomas Morgner
+ */
+public class DefaultModuleInfo implements ModuleInfo
+{
+  /** The name of the module class. */
+  private String moduleClass;
+  /** The major version of the described module. */
+  private String majorVersion;
+  /** The minor version of the described module. */
+  private String minorVersion;
+  /** The patchlevel version of the described module. */
+  private String patchLevel;
+
+  /**
+   * DefaultConstructor.
+   */
+  public DefaultModuleInfo() {
+    // nothing required
+  }
+
+  /**
+   * Creates a new module info an initalizes it with the given values.
+   *
+   * @param moduleClass the class name of the module implementation holding the module
+   * description.
+   * @param majorVersion the modules major version.
+   * @param minorVersion the modules minor version.
+   * @param patchLevel the modules patchlevel.
+   * @throws NullPointerException if the moduleClass is null.
+   */
+  public DefaultModuleInfo(final String moduleClass, final String majorVersion,
+                           final String minorVersion, final String patchLevel)
+  {
+    if (moduleClass == null)
+    {
+      throw new NullPointerException("Module class must not be null.");
+    }
+    this.moduleClass = moduleClass;
+    this.majorVersion = majorVersion;
+    this.minorVersion = minorVersion;
+    this.patchLevel = patchLevel;
+  }
+
+  /**
+   * Returns the class name of the module described implementation.
+   *
+   * @see ModuleInfo#getModuleClass()
+   *
+   * @return the module class name.
+   */
+  public String getModuleClass()
+  {
+    return this.moduleClass;
+  }
+
+  /**
+   * Defines the module class name.
+   *
+   * @param moduleClass the class name of the module implementation.
+   */
+  public void setModuleClass(final String moduleClass)
+  {
+    if (moduleClass == null)
+    {
+      throw new NullPointerException();
+    }
+    this.moduleClass = moduleClass;
+  }
+
+  /**
+   * Returns the major version of the module. This property may be
+   * null to indicate that the module version is not specified.
+   * @see ModuleInfo#getMajorVersion()
+   *
+   * @return the major version.
+   */
+  public String getMajorVersion()
+  {
+    return this.majorVersion;
+  }
+
+  /**
+   * Defines the major version of the module. This property may be
+   * null to indicate that the module version is not specified.
+   * @see ModuleInfo#getMajorVersion()
+   *
+   * @param majorVersion the major version.
+   */
+  public void setMajorVersion(final String majorVersion)
+  {
+    this.majorVersion = majorVersion;
+  }
+
+  /**
+   * Returns the minor version of the module. This property may be
+   * null to indicate that the module version is not specified.
+   * @see ModuleInfo#getMajorVersion()
+   *
+   * @return the minor version.
+   */
+  public String getMinorVersion()
+  {
+    return this.minorVersion;
+  }
+
+  /**
+   * Defines the minor version of the module. This property may be
+   * null to indicate that the module version is not specified.
+   * @see ModuleInfo#getMajorVersion()
+   *
+   * @param minorVersion the minor version.
+   */
+  public void setMinorVersion(final String minorVersion)
+  {
+    this.minorVersion = minorVersion;
+  }
+
+  /**
+   * Returns the patch level version of the module. This property may be
+   * null to indicate that the module version is not specified.
+   * @see ModuleInfo#getMajorVersion()
+   *
+   * @return the patch level version.
+   */
+  public String getPatchLevel()
+  {
+    return this.patchLevel;
+  }
+
+  /**
+   * Defines the patch level version of the module. This property may be
+   * null to indicate that the module version is not specified.
+   * @see ModuleInfo#getMajorVersion()
+   *
+   * @param patchLevel the patch level version.
+   */
+  public void setPatchLevel(final String patchLevel)
+  {
+    this.patchLevel = patchLevel;
+  }
+
+  /**
+   * Two moduleinfos are equal,if they have the same module class.
+   *
+   * @param o the other object to compare.
+   * @return true, if the module points to the same module, false otherwise.
+   */
+  public boolean equals(final Object o)
+  {
+    if (this == o)
+    {
+      return true;
+    }
+    if (!(o instanceof DefaultModuleInfo))
+    {
+      return false;
+    }
+
+    final ModuleInfo defaultModuleInfo = (ModuleInfo) o;
+
+    if (!this.moduleClass.equals(defaultModuleInfo.getModuleClass()))
+    {
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Computes an hashcode for this module information.
+   * @see java.lang.Object#hashCode()
+   *
+   * @return the hashcode.
+   */
+  public int hashCode()
+  {
+    final int result;
+    result = this.moduleClass.hashCode();
+    return result;
+  }
+
+  /**
+   * Returns a string representation of this module information.
+   *
+   * @see java.lang.Object#toString()
+   *
+   * @return a string describing this class.
+   */
+  public String toString()
+  {
+    final StringBuffer buffer = new StringBuffer();
+    buffer.append(getClass().getName());
+    buffer.append("={ModuleClass=");
+    buffer.append(getModuleClass());
+    if (getMajorVersion() != null)
+    {
+      buffer.append("; Version=");
+      buffer.append(getMajorVersion());
+      if (getMinorVersion() != null)
+      {
+        buffer.append("-");
+        buffer.append(getMinorVersion());
+        if (getPatchLevel() != null)
+        {
+          buffer.append("_");
+          buffer.append(getPatchLevel());
+        }
+      }
+    }
+    buffer.append("}");
+    return buffer.toString();
+  }
+}

+ 122 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/Module.java

@@ -0,0 +1,122 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -----------
+ * Module.java
+ * -----------
+ * (C)opyright 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: Module.java,v 1.3 2005/10/18 13:14:50 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jun-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.base.modules;
+
+/**
+ * A module encapsulates optional functionality within a project. Modules can
+ * be used as an easy way to make projects more configurable.
+ * <p>
+ * The module system provides a controled way to check dependencies and to initialize
+ * the modules in a controlled way.
+ *
+ * @author Thomas Morgner 
+ */
+public interface Module extends ModuleInfo
+{
+  /**
+   * Returns an array of all required modules. If one of these modules is missing
+   * or cannot be initialized, the module itself will be not available.
+   *
+   * @return an array of the required modules.
+   */
+  public ModuleInfo[] getRequiredModules();
+
+  /**
+   * Returns an array of optional modules. Missing or invalid modules are non fatal
+   * and will not harm the module itself.
+   *
+   * @return an array of optional module specifications.
+   */
+  public ModuleInfo[] getOptionalModules();
+
+  /**
+   * Initializes the module. Use this method to perform all initial setup operations.
+   * This method is called only once in a modules lifetime. If the initializing cannot
+   * be completed, throw a ModuleInitializeException to indicate the error,. The module
+   * will not be available to the system.
+   *
+   * @param subSystem  the subSystem.
+   * 
+   * @throws ModuleInitializeException if an error ocurred while initializing the module.
+   */
+  public void initialize(SubSystem subSystem) throws ModuleInitializeException;
+
+  /**
+   * Configures the module. This should load the default settings of the module.
+   *
+   * @param subSystem  the subSystem.
+   */
+  public void configure(SubSystem subSystem);
+
+  /**
+   * Returns a short description of the modules functionality.
+   *
+   * @return a module description.
+   */
+  public String getDescription();
+
+  /**
+   * Returns the name of the module producer.
+   *
+   * @return the producer name
+   */
+  public String getProducer();
+
+  /**
+   * Returns the module name. This name should be a short descriptive handle of the
+   * module.
+   *
+   * @return the module name
+   */
+  public String getName();
+
+  /**
+   * Returns the modules subsystem. If this module is not part of an subsystem
+   * then return the modules name, but never null.
+   *
+   * @return the name of the subsystem.
+   */
+  public String getSubSystem ();
+
+
+}

+ 88 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/ModuleInfo.java

@@ -0,0 +1,88 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ---------------
+ * ModuleInfo.java
+ * ---------------
+ * (C)opyright 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: ModuleInfo.java,v 1.3 2005/10/18 13:14:50 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jun-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.base.modules;
+
+/**
+ * The Module info class encapsulates metadata about a given module. It holds the
+ * list of dependencies and the module version and description.
+ *
+ * @author Thomas Morgner
+ */
+public interface ModuleInfo {
+
+    /**
+     * Returns the module class of the desired base module.
+     *
+     * @return The module class.
+     */
+    public String getModuleClass();
+
+    /**
+     * Returns the major version of the base module. The string should
+     * contain a compareable character sequence so that higher versions
+     * of the module are considered greater than lower versions.
+     *
+     * @return The major version of the module.
+     */
+    public String getMajorVersion();
+
+    /**
+     * Returns the minor version of the base module. The string should
+     * contain a compareable character sequence so that higher versions
+     * of the module are considered greater than lower versions.
+     *
+     * @return The minor version of the module.
+     */
+    public String getMinorVersion();
+
+    /**
+     * Returns the patchlevel version of the base module. The patch level
+     * should be used to mark bugfixes. The string should
+     * contain a compareable character sequence so that higher versions
+     * of the module are considered greater than lower versions.
+     *
+     * @return The patch level version of the module.
+     */
+    public String getPatchLevel();
+  
+}

+ 85 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/ModuleInitializeException.java

@@ -0,0 +1,85 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ------------------------------
+ * ModuleInitializeException.java
+ * ------------------------------
+ * (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: ModuleInitializeException.java,v 1.2 2005/10/18 13:14:50 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 05-Jul-2003 : Initial version
+ * 07-Jun-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.base.modules;
+
+import org.jfree.util.StackableException;
+
+/**
+ * This exception is thrown when the module initialization encountered an
+ * unrecoverable error which prevents the module from being used.
+ *
+ * @author Thomas Morgner
+ */
+public class ModuleInitializeException extends StackableException {
+
+    /**
+     * Creates a ModuleInitializeException with no message and no base
+     * exception.
+     */
+    public ModuleInitializeException() {
+        // nothing required
+    }
+
+    /**
+     * Creates a ModuleInitializeException with the given message and base
+     * exception.
+     *
+     * @param s the message
+     * @param e the root exception
+     */
+    public ModuleInitializeException(final String s, final Exception e) {
+        super(s, e);
+    }
+
+    /**
+     * Creates a ModuleInitializeException with the given message and no base
+     * exception.
+     *
+     * @param s the exception message
+     */
+    public ModuleInitializeException(final String s) {
+        super(s);
+    }
+    
+}

+ 64 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/ModuleInitializer.java

@@ -0,0 +1,64 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ----------------------
+ * ModuleInitializer.java
+ * ----------------------
+ * (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: ModuleInitializer.java,v 1.2 2005/10/18 13:14:50 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 14-Jul-2003 : Initial version
+ * 07-Jun-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.base.modules;
+
+/**
+ * The module initializer is used to separate the initialization process from
+ * the module definition. An invalid classpath setup or an missing base module
+ * may throw an ClassCastException if the module class references this missing
+ * resource. Separating them is the best way to make sure that the classloader
+ * does not interrupt the module loading process.
+ *
+ * @author Thomas Morgner
+ */
+public interface ModuleInitializer {
+    
+    /**
+     * Performs the initalization of the module.
+     *
+     * @throws ModuleInitializeException if an error occurs which prevents the module
+     * from being usable.
+     */
+    public void performInit() throws ModuleInitializeException;
+}

+ 586 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/PackageManager.java

@@ -0,0 +1,586 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -------------------
+ * PackageManager.java
+ * -------------------
+ * (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: PackageManager.java,v 1.10 2006/11/02 13:10:35 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 26-Jun-2003 : Initial version
+ * 07-Jun-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.base.modules;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.jfree.base.AbstractBoot;
+import org.jfree.base.config.HierarchicalConfiguration;
+import org.jfree.base.config.PropertyFileConfiguration;
+import org.jfree.base.log.PadMessage;
+import org.jfree.util.Configuration;
+import org.jfree.util.Log;
+import org.jfree.util.ObjectUtilities;
+
+/**
+ * The PackageManager is used to load and configure the modules of JFreeReport.
+ * Modules are used to extend the basic capabilities of JFreeReport by providing
+ * a simple plugin-interface.
+ * <p>
+ * Modules provide a simple capability to remove unneeded functionality from the
+ * JFreeReport system and to reduce the overall code size. The modularisation provides
+ * a very strict way of removing unnecessary dependencies between the various packages.</p>
+ * <p>
+ * The package manager can be used to add new modules to the system or to check
+ * the existence and state of installed modules.</p>
+ *
+ * @author Thomas Morgner
+ */
+public final class PackageManager {
+    /**
+     * The PackageConfiguration handles the module level configuration.
+     *
+     * @author Thomas Morgner
+     */
+    public static class PackageConfiguration extends PropertyFileConfiguration {
+        /**
+         * DefaultConstructor. Creates a new package configuration.
+         */
+        public PackageConfiguration() {
+            // nothing required
+        }
+
+        /**
+         * The new configuartion will be inserted into the list of report configuration,
+         * so that this configuration has the given report configuration instance as parent.
+         *
+         * @param config the new report configuration.
+         */
+        public void insertConfiguration(final HierarchicalConfiguration config) {
+            super.insertConfiguration(config);
+        }
+    }
+
+
+    /**
+     * An internal constant declaring that the specified module was already loaded.
+     */
+    private static final int RETURN_MODULE_LOADED = 0;
+    /**
+     * An internal constant declaring that the specified module is not known.
+     */
+    private static final int RETURN_MODULE_UNKNOWN = 1;
+    /**
+     * An internal constant declaring that the specified module produced an error while loading.
+     */
+    private static final int RETURN_MODULE_ERROR = 2;
+
+
+    /**
+     * The module configuration instance that should be used to store module
+     * properties. This separates the user defined properties from the implementation
+     * defined properties.
+     */
+    private final PackageConfiguration packageConfiguration;
+
+    /**
+     * A list of all defined modules.
+     */
+    private final ArrayList modules;
+    /**
+     * A list of module name definitions.
+     */
+    private final ArrayList initSections;
+
+    /** The boot implementation for which the modules are managed. */
+    private AbstractBoot booter;
+
+    /** The instances of all modules for all booters. */
+    private static HashMap instances;
+
+    /**
+     * Creates a package manager instance.
+     *
+     * @param booter the booter.
+     * @return A package manager.
+     */
+    public static PackageManager createInstance(final AbstractBoot booter) {
+        PackageManager manager;
+        if (instances == null) {
+            instances = new HashMap();
+            manager = new PackageManager(booter);
+            instances.put(booter, manager);
+            return manager;
+        }
+        manager = (PackageManager) instances.get(booter);
+        if (manager == null) {
+            manager = new PackageManager(booter);
+            instances.put(booter, manager);
+        }
+        return manager;
+    }
+
+    /**
+     * Creates a new package manager.
+     *
+     * @param booter the booter (<code>null</code> not permitted).
+     */
+    private PackageManager(final AbstractBoot booter) {
+        if (booter == null) {
+            throw new NullPointerException();
+        }
+        this.booter = booter;
+        this.packageConfiguration = new PackageConfiguration();
+        this.modules = new ArrayList();
+        this.initSections = new ArrayList();
+    }
+
+    /**
+     * Checks, whether a certain module is available.
+     *
+     * @param moduleDescription the module description of the desired module.
+     * @return true, if the module is available and the version of the module
+     *         is compatible, false otherwise.
+     */
+    public boolean isModuleAvailable(final ModuleInfo moduleDescription) {
+        final PackageState[] packageStates =
+            (PackageState[]) this.modules.toArray(new PackageState[this.modules.size()]);
+        for (int i = 0; i < packageStates.length; i++) {
+            final PackageState state = packageStates[i];
+            if (state.getModule().getModuleClass().equals(moduleDescription.getModuleClass())) {
+                return (state.getState() == PackageState.STATE_INITIALIZED);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Loads all modules mentioned in the report configuration starting with
+     * the given prefix. This method is used during the boot process of
+     * JFreeReport. You should never need to call this method directly.
+     *
+     * @param modulePrefix the module prefix.
+     */
+    public void load(final String modulePrefix) {
+        if (this.initSections.contains(modulePrefix)) {
+            return;
+        }
+        this.initSections.add(modulePrefix);
+
+        final Configuration config = this.booter.getGlobalConfig();
+        final Iterator it = config.findPropertyKeys(modulePrefix);
+        int count = 0;
+        while (it.hasNext()) {
+            final String key = (String) it.next();
+            if (key.endsWith(".Module")) {
+                final String moduleClass = config.getConfigProperty(key);
+                if (moduleClass != null && moduleClass.length() > 0) {
+                    addModule(moduleClass);
+                    count++;
+                }
+            }
+        }
+        Log.debug("Loaded a total of " + count + " modules under prefix: " + modulePrefix);
+    }
+
+    /**
+     * Initializes all previously uninitialized modules. Once a module is initialized,
+     * it is not re-initialized a second time.
+     */
+    public synchronized void initializeModules() {
+        // sort by subsystems and dependency
+        PackageSorter.sort(this.modules);
+
+        for (int i = 0; i < this.modules.size(); i++) {
+            final PackageState mod = (PackageState) this.modules.get(i);
+            if (mod.configure(this.booter)) {
+                Log.debug(new Log.SimpleMessage("Conf: ",
+                    new PadMessage(mod.getModule().getModuleClass(), 70),
+                    " [", mod.getModule().getSubSystem(), "]"));
+            }
+        }
+
+        for (int i = 0; i < this.modules.size(); i++) {
+            final PackageState mod = (PackageState) this.modules.get(i);
+            if (mod.initialize(this.booter)) {
+                Log.debug(new Log.SimpleMessage("Init: ",
+                    new PadMessage(mod.getModule().getModuleClass(), 70),
+                    " [", mod.getModule().getSubSystem(), "]"));
+            }
+        }
+    }
+
+    /**
+     * Adds a module to the package manager.
+     * Once all modules are added, you have to call initializeModules()
+     * to configure and initialize the new modules.
+     *
+     * @param modClass the module class
+     */
+    public synchronized void addModule(final String modClass) {
+        final ArrayList loadModules = new ArrayList();
+        final ModuleInfo modInfo = new DefaultModuleInfo
+            (modClass, null, null, null);
+        if (loadModule(modInfo, new ArrayList(), loadModules, false)) {
+            for (int i = 0; i < loadModules.size(); i++) {
+                final Module mod = (Module) loadModules.get(i);
+                this.modules.add(new PackageState(mod));
+            }
+        }
+    }
+
+    /**
+     * Checks, whether the given module is already loaded in either the given
+     * tempModules list or the global package registry. If tmpModules is null,
+     * only the previously installed modules are checked.
+     *
+     * @param tempModules a list of previously loaded modules.
+     * @param module      the module specification that is checked.
+     * @return true, if the module is already loaded, false otherwise.
+     */
+    private int containsModule(final ArrayList tempModules, final ModuleInfo module) {
+        if (tempModules != null) {
+            final ModuleInfo[] mods = (ModuleInfo[])
+                tempModules.toArray(new ModuleInfo[tempModules.size()]);
+            for (int i = 0; i < mods.length; i++) {
+                if (mods[i].getModuleClass().equals(module.getModuleClass())) {
+                    return RETURN_MODULE_LOADED;
+                }
+            }
+        }
+
+        final PackageState[] packageStates =
+            (PackageState[]) this.modules.toArray(new PackageState[this.modules.size()]);
+        for (int i = 0; i < packageStates.length; i++) {
+            if (packageStates[i].getModule().getModuleClass().equals(module.getModuleClass())) {
+                if (packageStates[i].getState() == PackageState.STATE_ERROR) {
+                    return RETURN_MODULE_ERROR;
+                }
+                else {
+                    return RETURN_MODULE_LOADED;
+                }
+            }
+        }
+        return RETURN_MODULE_UNKNOWN;
+    }
+
+    /**
+     * A utility method that collects all failed modules. Such an module caused
+     * an error while being loaded, and is now cached in case it is referenced
+     * elsewhere.
+     *
+     * @param state the failed module.
+     */
+    private void dropFailedModule(final PackageState state) {
+        if (this.modules.contains(state) == false) {
+            this.modules.add(state);
+        }
+    }
+
+    /**
+     * Tries to load a given module and all dependent modules. If the dependency check
+     * fails for that module (or for one of the dependent modules), the loaded modules
+     * are discarded and no action is taken.
+     *
+     * @param moduleInfo        the module info of the module that should be loaded.
+     * @param incompleteModules a list of incompletly loaded modules. This are module
+     *                          specifications which depend on the current module and wait for the module to
+     *                          be completly loaded.
+     * @param modules           the list of previously loaded modules for this module.
+     * @param fatal             a flag that states, whether the failure of loading a module should
+     *                          be considered an error. Root-modules load errors are never fatal, as we try
+     *                          to load all known modules, regardless whether they are active or not.
+     * @return true, if the module was loaded successfully, false otherwise.
+     */
+    private boolean loadModule(final ModuleInfo moduleInfo, final ArrayList incompleteModules,
+                               final ArrayList modules, final boolean fatal) {
+        try {
+
+            final Class c = ObjectUtilities.getClassLoader(getClass()).loadClass(moduleInfo.getModuleClass());
+            final Module module = (Module) c.newInstance();
+
+            if (acceptVersion(moduleInfo, module) == false) {
+                // module conflict!
+                Log.warn("Module " + module.getName() + ": required version: " 
+                        + moduleInfo + ", but found Version: \n" + module);
+                final PackageState state = new PackageState(module, PackageState.STATE_ERROR);
+                dropFailedModule(state);
+                return false;
+            }
+
+            final int moduleContained = containsModule(modules, module);
+            if (moduleContained == RETURN_MODULE_ERROR) {
+                // the module caused harm before ...
+                Log.debug("Indicated failure for module: " + module.getModuleClass());
+                final PackageState state = new PackageState(module, PackageState.STATE_ERROR);
+                dropFailedModule(state);
+                return false;
+            }
+            else if (moduleContained == RETURN_MODULE_UNKNOWN) {
+                if (incompleteModules.contains(module)) {
+                    // we assume that loading will continue ...
+                    Log.error(new Log.SimpleMessage
+                        ("Circular module reference: This module definition is invalid: ",
+                            module.getClass()));
+                    final PackageState state = new PackageState(module, PackageState.STATE_ERROR);
+                    dropFailedModule(state);
+                    return false;
+                }
+                incompleteModules.add(module);
+                final ModuleInfo[] required = module.getRequiredModules();
+                for (int i = 0; i < required.length; i++) {
+                    if (loadModule(required[i], incompleteModules, modules, true) == false) {
+                        Log.debug("Indicated failure for module: " + module.getModuleClass());
+                        final PackageState state = new PackageState(module, PackageState.STATE_ERROR);
+                        dropFailedModule(state);
+                        return false;
+                    }
+                }
+
+                final ModuleInfo[] optional = module.getOptionalModules();
+                for (int i = 0; i < optional.length; i++) {
+                    if (loadModule(optional[i], incompleteModules, modules, true) == false) {
+                        Log.debug(new Log.SimpleMessage("Optional module: ",
+                            optional[i].getModuleClass(), " was not loaded."));
+                    }
+                }
+                // maybe a dependent module defined the same base module ...
+                if (containsModule(modules, module) == RETURN_MODULE_UNKNOWN) {
+                    modules.add(module);
+                }
+                incompleteModules.remove(module);
+            }
+            return true;
+        }
+        catch (ClassNotFoundException cnfe) {
+            if (fatal) {
+                Log.warn(new Log.SimpleMessage
+                    ("Unresolved dependency for package: ", moduleInfo.getModuleClass()));
+            }
+            Log.debug(new Log.SimpleMessage("ClassNotFound: ", cnfe.getMessage()));
+            return false;
+        }
+        catch (Exception e) {
+            Log.warn(new Log.SimpleMessage("Exception while loading module: ", moduleInfo), e);
+            return false;
+        }
+    }
+
+    /**
+     * Checks, whether the given module meets the requirements defined in the module
+     * information.
+     *
+     * @param moduleRequirement the required module specification.
+     * @param module            the module that should be checked against the specification.
+     * @return true, if the module meets the given specifications, false otherwise.
+     */
+    private boolean acceptVersion(final ModuleInfo moduleRequirement, final Module module) {
+        if (moduleRequirement.getMajorVersion() == null) {
+            return true;
+        }
+        if (module.getMajorVersion() == null) {
+            Log.warn("Module " + module.getName() + " does not define a major version.");
+        }
+        else {
+            final int compare = acceptVersion(moduleRequirement.getMajorVersion(),
+                module.getMajorVersion());
+            if (compare > 0) {
+                return false;
+            }
+            else if (compare < 0) {
+                return true;
+            }
+        }
+
+        if (moduleRequirement.getMinorVersion() == null) {
+            return true;
+        }
+        if (module.getMinorVersion() == null) {
+            Log.warn("Module " + module.getName() + " does not define a minor version.");
+        }
+        else {
+            final int compare = acceptVersion(moduleRequirement.getMinorVersion(),
+                module.getMinorVersion());
+            if (compare > 0) {
+                return false;
+            }
+            else if (compare < 0) {
+                return true;
+            }
+        }
+
+        if (moduleRequirement.getPatchLevel() == null) {
+            return true;
+        }
+        if (module.getPatchLevel() == null) {
+            Log.debug("Module " + module.getName() + " does not define a patch level.");
+        }
+        else {
+            if (acceptVersion(moduleRequirement.getPatchLevel(),
+                module.getPatchLevel()) > 0) {
+                Log.debug("Did not accept patchlevel: " 
+                        + moduleRequirement.getPatchLevel() + " - " 
+                        + module.getPatchLevel());
+                return false;
+            }
+        }
+        return true;
+
+    }
+
+    /**
+     * Compare the version strings. If the strings have a different length,
+     * the shorter string is padded with spaces to make them compareable.
+     *
+     * @param modVer    the version string of the module
+     * @param depModVer the version string of the dependent or optional module
+     * @return 0, if the dependent module version is equal tothe module's required
+     *         version, a negative number if the dependent module is newer or a positive
+     *         number if the dependent module is older and does not fit.
+     */
+    private int acceptVersion(final String modVer, final String depModVer) {
+        final int mLength = Math.max(modVer.length(), depModVer.length());
+        final char[] modVerArray;
+        final char[] depVerArray;
+        if (modVer.length() > depModVer.length()) {
+            modVerArray = modVer.toCharArray();
+            depVerArray = new char[mLength];
+            final int delta = modVer.length() - depModVer.length();
+            Arrays.fill(depVerArray, 0, delta, ' ');
+            System.arraycopy(depVerArray, delta, depModVer.toCharArray(), 0, depModVer.length());
+        }
+        else if (modVer.length() < depModVer.length()) {
+            depVerArray = depModVer.toCharArray();
+            modVerArray = new char[mLength];
+            final char[] b1 = new char[mLength];
+            final int delta = depModVer.length() - modVer.length();
+            Arrays.fill(b1, 0, delta, ' ');
+            System.arraycopy(b1, delta, modVer.toCharArray(), 0, modVer.length());
+        }
+        else {
+            depVerArray = depModVer.toCharArray();
+            modVerArray = modVer.toCharArray();
+        }
+        return new String(modVerArray).compareTo(new String(depVerArray));
+    }
+
+    /**
+     * Returns the default package configuration. Private report configuration
+     * instances may be inserted here. These inserted configuration can never override
+     * the settings from this package configuration.
+     *
+     * @return the package configuration.
+     */
+    public PackageConfiguration getPackageConfiguration() {
+        return this.packageConfiguration;
+    }
+
+    /**
+     * Returns an array of the currently active modules. The module definition
+     * returned contain all known modules, including buggy and unconfigured
+     * instances.
+     *
+     * @return the modules.
+     */
+    public Module[] getAllModules() {
+        final Module[] mods = new Module[this.modules.size()];
+        for (int i = 0; i < this.modules.size(); i++) {
+            final PackageState state = (PackageState) this.modules.get(i);
+            mods[i] = state.getModule();
+        }
+        return mods;
+    }
+
+    /**
+     * Returns all active modules. This array does only contain modules
+     * which were successfully configured and initialized.
+     *
+     * @return the list of all active modules.
+     */
+    public Module[] getActiveModules() {
+        final ArrayList mods = new ArrayList();
+        for (int i = 0; i < this.modules.size(); i++) {
+            final PackageState state = (PackageState) this.modules.get(i);
+            if (state.getState() == PackageState.STATE_INITIALIZED) {
+                mods.add(state.getModule());
+            }
+        }
+        return (Module[]) mods.toArray(new Module[mods.size()]);
+    }
+
+    /**
+     * Prints the modules that are used.
+     *
+     * @param p the print stream.
+     */
+    public void printUsedModules(final PrintStream p) {
+        final Module[] allMods = getAllModules();
+        final ArrayList activeModules = new ArrayList();
+        final ArrayList failedModules = new ArrayList();
+
+        for (int i = 0; i < allMods.length; i++) {
+            if (isModuleAvailable(allMods[i])) {
+                activeModules.add(allMods[i]);
+            }
+            else {
+                failedModules.add(allMods[i]);
+            }
+        }
+
+        p.print("Active modules: ");
+        p.println(activeModules.size());
+        p.println("----------------------------------------------------------");
+        for (int i = 0; i < activeModules.size(); i++) {
+            final Module mod = (Module) activeModules.get(i);
+            p.print(new PadMessage(mod.getModuleClass(), 70));
+            p.print(" [");
+            p.print(mod.getSubSystem());
+            p.println("]");
+            p.print("  Version: ");
+            p.print(mod.getMajorVersion());
+            p.print("-");
+            p.print(mod.getMinorVersion());
+            p.print("-");
+            p.print(mod.getPatchLevel());
+            p.print(" Producer: ");
+            p.println(mod.getProducer());
+            p.print("  Description: ");
+            p.println(mod.getDescription());
+        }
+    }
+}

+ 448 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/PackageSorter.java

@@ -0,0 +1,448 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * ------------------
+ * PackageSorter.java
+ * ------------------
+ * (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: PackageSorter.java,v 1.3 2007/05/15 12:32:15 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 02-Sep-2003 : Initial version
+ * 07-Jun-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.base.modules;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jfree.util.Log;
+
+/**
+ * Compares two modules for order. A module is considered less than an other
+ * module if the module is a required module of the compared module. Modules
+ * are considered equal if they have no relation.
+ * <p>
+ * When sorting, we match this modules position against all dependent
+ * modules until all positions are stable. Circular references are evil
+ * and are filtered during the module loading process in the package manager.
+ *
+ * @author Thomas Morgner
+ */
+public final class PackageSorter
+{
+  /**
+   * An Internal wrapper class which collects additional information
+   * on the given module. Every module has a position, which is heigher
+   * than the position of all dependent modules.
+   *
+   * @author Thomas Morgner
+   */
+  private static class SortModule implements Comparable
+  {
+    /** stores the relative position of the module in the global list. */
+    private int position;
+    /** The package state of the to be matched module. */
+    private final PackageState state;
+    /** A list of all directly dependent subsystems. */
+    private ArrayList dependSubsystems;
+    // direct dependencies, indirect ones are handled by the
+    // dependent classes ...
+
+    /**
+     * Creates a new SortModule for the given package state.
+     *
+     * @param state the package state object, that should be wrapped up
+     * by this class.
+     */
+    public SortModule(final PackageState state)
+    {
+      this.position = -1;
+      this.state = state;
+    }
+
+    /**
+     * Returns the list of all dependent subsystems. The list gets defined
+     * when the sorting is started.
+     *
+     * @return the list of all dependent subsystems.
+     */
+    public ArrayList getDependSubsystems()
+    {
+      return this.dependSubsystems;
+    }
+
+    /**
+     * Defines a list of dependent subsystems for this module. The list contains
+     * the names of the dependent subsystems as strings.
+     *
+     * @param dependSubsystems a list of all dependent subsystems.
+     */
+    public void setDependSubsystems(final ArrayList dependSubsystems)
+    {
+      this.dependSubsystems = dependSubsystems;
+    }
+
+    /**
+     * Returns the current position of this module in the global list.
+     * The position is computed by comparing all positions of all dependent
+     * subsystem modules.
+     *
+     * @return the current module position.
+     */
+    public int getPosition()
+    {
+      return this.position;
+    }
+
+    /**
+     * Defines the position of this module in the global list of all
+     * known modules.
+     *
+     * @param position the position.
+     */
+    public void setPosition(final int position)
+    {
+      this.position = position;
+    }
+
+    /**
+     * Returns the package state contained in this SortModule.
+     *
+     * @return the package state of this module.
+     */
+    public PackageState getState()
+    {
+      return this.state;
+    }
+
+    /**
+     * Returns a basic string representation of this SortModule. This
+     * should be used for debugging purposes only.
+     * @see java.lang.Object#toString()
+     *
+     * @return a string representation of this module.
+     */
+    public String toString ()
+    {
+      final StringBuffer buffer = new StringBuffer();
+      buffer.append("SortModule: ");
+      buffer.append(this.position);
+      buffer.append(" ");
+      buffer.append(this.state.getModule().getName());
+      buffer.append(" ");
+      buffer.append(this.state.getModule().getModuleClass());
+      return buffer.toString();
+    }
+
+    /**
+     * Compares this module against an other sort module.
+     *
+     * @see java.lang.Comparable#compareTo(java.lang.Object)
+     *
+     * @param o the other sort module instance.
+     * @return -1 if the other's module position is less than
+     * this modules position, +1 if this module is less than the
+     * other module or 0 if both modules have an equal position in
+     * the list.
+     */
+    public int compareTo(final Object o)
+    {
+      final SortModule otherModule = (SortModule) o;
+      if (this.position > otherModule.position)
+      {
+        return +1;
+      }
+      if (this.position < otherModule.position)
+      {
+        return -1;
+      }
+      return 0;
+    }
+  }
+
+  /**
+   * DefaultConstructor.
+   */
+  private PackageSorter() {
+      // nothing required.
+  }
+
+  /**
+   * Sorts the given list of package states. The packages
+   * are sorted by their dependencies in a way so that all
+   * dependent packages are placed on lower positions than
+   * the packages which declared the dependency.
+   *
+   * @param modules the list of modules.
+   */
+  public static void sort (final List modules)
+  {
+    final HashMap moduleMap = new HashMap();
+    final ArrayList errorModules = new ArrayList();
+    final ArrayList weightModules = new ArrayList();
+
+    for (int i = 0; i < modules.size(); i++)
+    {
+      final PackageState state = (PackageState) modules.get(i);
+      if (state.getState() == PackageState.STATE_ERROR)
+      {
+        errorModules.add (state);
+      }
+      else
+      {
+        final SortModule mod = new SortModule(state);
+        weightModules.add (mod);
+        moduleMap.put(state.getModule().getModuleClass(), mod);
+      }
+    }
+
+    final SortModule[] weigths = (SortModule[])
+        weightModules.toArray(new SortModule[weightModules.size()]);
+
+    for (int i = 0; i < weigths.length; i++)
+    {
+      final SortModule sortMod = weigths[i];
+      sortMod.setDependSubsystems
+          (collectSubsystemModules(sortMod.getState().getModule(),
+              moduleMap));
+    }
+
+
+    // repeat the computation until all modules have a matching
+    // position. This is not the best algorithm, but it works
+    // and is relativly simple. It will need some optimizations
+    // in the future, but as this is only executed once, we don't
+    // have to care much about it.
+    boolean doneWork = true;
+    while (doneWork)
+    {
+      doneWork = false;
+      for (int i = 0; i < weigths.length; i++)
+      {
+        final SortModule mod = weigths[i];
+        final int position = searchModulePosition(mod, moduleMap);
+        if (position != mod.getPosition())
+        {
+          mod.setPosition(position);
+          doneWork = true;
+        }
+      }
+    }
+
+    Arrays.sort(weigths);
+    modules.clear();
+    for (int i = 0; i < weigths.length; i++)
+    {
+      modules.add (weigths[i].getState());
+    }
+    for (int i = 0; i < errorModules.size(); i++)
+    {
+      modules.add (errorModules.get(i));
+    }
+  }
+
+  /**
+   * Computes the new module position. This position is computed
+   * according to the dependent modules and subsystems. The returned
+   * position will be higher than the highest dependent module position.
+   *
+   * @param smodule the sort module for that we compute the new positon.
+   * @param moduleMap the map with all modules.
+   * @return the new positon.
+   */
+  private static int searchModulePosition
+      (final SortModule smodule, final HashMap moduleMap)
+  {
+    final Module module = smodule.getState().getModule();
+    int position = 0;
+
+    // check the required modules. Increase our level to at least
+    // one point over the highest dependent module
+    // ignore missing modules.
+    ModuleInfo[] modInfo = module.getOptionalModules();
+    for (int modPos = 0; modPos < modInfo.length; modPos++)
+    {
+      final String moduleName = modInfo[modPos].getModuleClass();
+      final SortModule reqMod = (SortModule) moduleMap.get(moduleName);
+      if (reqMod == null)
+      {
+        continue;
+      }
+      if (reqMod.getPosition() >= position)
+      {
+        position = reqMod.getPosition() + 1;
+      }
+    }
+
+    // check the required modules. Increase our level to at least
+    // one point over the highest dependent module
+    // there are no missing modules here (or the package manager
+    // is invalid)
+    modInfo = module.getRequiredModules();
+    for (int modPos = 0; modPos < modInfo.length; modPos++)
+    {
+      final String moduleName = modInfo[modPos].getModuleClass();
+      final SortModule reqMod = (SortModule) moduleMap.get(moduleName);
+      if (reqMod == null)
+      {
+        Log.warn ("Invalid state: Required dependency of '" + moduleName + "' had an error.");
+        continue;
+      }
+      if (reqMod.getPosition() >= position)
+      {
+        position = reqMod.getPosition() + 1;
+      }
+    }
+
+    // check the subsystem dependencies. This way we make sure
+    // that subsystems are fully initialized before we try to use
+    // them.
+    final String subSystem = module.getSubSystem();
+    final Iterator it = moduleMap.values().iterator();
+    while (it.hasNext())
+    {
+      final SortModule mod = (SortModule) it.next();
+      // it is evil to compute values on ourself...
+      if (mod.getState().getModule() == module)
+      {
+        // same module ...
+        continue;
+      }
+      final Module subSysMod = mod.getState().getModule();
+      // if the module we check is part of the same subsystem as
+      // we are, then we dont do anything. Within the same subsystem
+      // the dependencies are computed solely by the direct references.
+      if (subSystem.equals(subSysMod.getSubSystem()))
+      {
+        // same subsystem ... ignore
+        continue;
+      }
+
+      // does the module from the global list <mod> depend on the
+      // subsystem we are part of?
+      //
+      // if yes, we have a relation and may need to adjust the level...
+      if (smodule.getDependSubsystems().contains(subSysMod.getSubSystem()))
+      {
+        // check whether the module is a base module of the given
+        // subsystem. We will not adjust our position in that case,
+        // as this would lead to an infinite loop
+        if (isBaseModule(subSysMod, module) == false)
+        {
+          if (mod.getPosition() >= position)
+          {
+            position = mod.getPosition() + 1;
+          }
+        }
+      }
+    }
+    return position;
+  }
+
+  /**
+   * Checks, whether a module is a base module of an given module.
+   *
+   * @param mod the module which to check
+   * @param mi the module info of the suspected base module.
+   * @return true, if the given module info describes a base module of the
+   * given module, false otherwise.
+   */
+  private static boolean isBaseModule(final Module mod, final ModuleInfo mi)
+  {
+    ModuleInfo[] info = mod.getRequiredModules();
+    for (int i = 0; i < info.length; i++)
+    {
+      if (info[i].getModuleClass().equals(mi.getModuleClass()))
+      {
+        return true;
+      }
+    }
+    info = mod.getOptionalModules();
+    for (int i = 0; i < info.length; i++)
+    {
+      if (info[i].getModuleClass().equals(mi.getModuleClass()))
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
+
+  /**
+   * Collects all directly dependent subsystems.
+   *
+   * @param childMod the module which to check
+   * @param moduleMap the map of all other modules, keyed by module class.
+   * @return the list of all dependent subsystems.
+   */
+  private static ArrayList collectSubsystemModules
+      (final Module childMod, final HashMap moduleMap)
+  {
+    final ArrayList collector = new ArrayList();
+    ModuleInfo[] info = childMod.getRequiredModules();
+    for (int i = 0; i < info.length; i++)
+    {
+      final SortModule dependentModule = (SortModule)
+          moduleMap.get(info[i].getModuleClass());
+      if (dependentModule == null)
+      {
+        Log.warn
+          (new Log.SimpleMessage
+            ("A dependent module was not found in the list of known modules.",
+            info[i].getModuleClass()));
+        continue;
+      }
+
+      collector.add (dependentModule.getState().getModule().getSubSystem());
+    }
+
+    info = childMod.getOptionalModules();
+    for (int i = 0; i < info.length; i++)
+    {
+      final Module dependentModule = (Module)
+          moduleMap.get(info[i].getModuleClass());
+      if (dependentModule == null)
+      {
+        Log.warn ("A dependent module was not found in the list of known modules.");
+        continue;
+      }
+      collector.add (dependentModule.getSubSystem());
+    }
+    return collector;
+  }
+}

+ 263 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/PackageState.java

@@ -0,0 +1,263 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -----------------
+ * PackageState.java
+ * -----------------
+ * (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: PackageState.java,v 1.4 2006/04/14 13:00:56 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 10-Jul-2003 : Initial version
+ * 07-Jun-2004 : Added JCommon header (DG);
+ * 
+ */
+
+package org.jfree.base.modules;
+
+import org.jfree.util.Log;
+
+/**
+ * The package state class is used by the package manager to keep track of
+ * the activation level of the installed or errornous packages.
+ *
+ * @author Thomas Morgner
+ */
+public class PackageState
+{
+  /** A constant defining that the package is new. */
+  public static final int STATE_NEW = 0;
+  
+  /** A constant defining that the package has been loaded and configured. */
+  public static final int STATE_CONFIGURED = 1;
+  
+  /** A constant defining that the package was initialized and is ready to use. */
+  public static final int STATE_INITIALIZED = 2;
+  
+  /** A constant defining that the package produced an error and is not available. */
+  public static final int STATE_ERROR = -2;
+
+  /** The module class that contains the package information. */
+  private final Module module;
+  /** The state of the module. */
+  private int state;
+
+  /**
+   * Creates a new package state for the given module. The module state will
+   * be initialized to STATE_NEW.
+   *
+   * @param module the module.
+   */
+  public PackageState(final Module module)
+  {
+    this (module, STATE_NEW);
+  }
+
+  /**
+   * Creates a new package state for the given module. The module state will
+   * be initialized to the given initial state.
+   *
+   * @param module the module.
+   * @param state the initial state
+   */
+  public PackageState(final Module module, final int state)
+  {
+    if (module == null)
+    {
+      throw new NullPointerException("Module must not be null.");
+    }
+    if (state != STATE_CONFIGURED && state != STATE_ERROR 
+            && state != STATE_INITIALIZED && state != STATE_NEW)
+    {
+      throw new IllegalArgumentException("State is not valid");
+    }
+    this.module = module;
+    this.state = state;
+  }
+
+  /**
+   * Configures the module and raises the state to STATE_CONFIGURED if the
+   * module is not yet configured.
+   *
+   * @param subSystem  the sub-system.
+   * 
+   * @return true, if the module was configured, false otherwise.
+   */
+  public boolean configure(final SubSystem subSystem)
+  {
+    if (this.state == STATE_NEW)
+    {
+      try
+      {
+        this.module.configure(subSystem);
+        this.state = STATE_CONFIGURED;
+        return true;
+      }
+      catch (NoClassDefFoundError noClassDef)
+      {
+        Log.warn (new Log.SimpleMessage("Unable to load module classes for ",
+                this.module.getName(), ":", noClassDef.getMessage()));
+        this.state = STATE_ERROR;
+      }
+      catch (Exception e)
+      {
+        if (Log.isDebugEnabled())
+        {
+          // its still worth a warning, but now we are more verbose ...
+          Log.warn("Unable to configure the module " + this.module.getName(), e);
+        }
+        else if (Log.isWarningEnabled())
+        {
+          Log.warn("Unable to configure the module " + this.module.getName());
+        }
+        this.state = STATE_ERROR;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Returns the module managed by this state implementation.
+   *
+   * @return the module.
+   */
+  public Module getModule()
+  {
+    return this.module;
+  }
+
+  /**
+   * Returns the current state of the module. This method returns either
+   * STATE_NEW, STATE_CONFIGURED, STATE_INITIALIZED or STATE_ERROR.
+   *
+   * @return the module state.
+   */
+  public int getState()
+  {
+    return this.state;
+  }
+
+  /**
+   * Initializes the contained module and raises the set of the module to
+   * STATE_INITIALIZED, if the module was not yet initialized. In case of an
+   * error, the module state will be set to STATE_ERROR and the module will
+   * not be available.
+   *
+   * @param subSystem  the sub-system.
+   * 
+   * @return true, if the module was successfully initialized, false otherwise.
+   */
+  public boolean initialize(final SubSystem subSystem)
+  {
+    if (this.state == STATE_CONFIGURED)
+    {
+      try
+      {
+          this.module.initialize(subSystem);
+          this.state = STATE_INITIALIZED;
+          return true;
+      }
+      catch (NoClassDefFoundError noClassDef)
+      {
+        Log.warn (new Log.SimpleMessage("Unable to load module classes for ",
+                this.module.getName(), ":", noClassDef.getMessage()));
+        this.state = STATE_ERROR;
+      }
+      catch (ModuleInitializeException me)
+      {
+        if (Log.isDebugEnabled())
+        {
+          // its still worth a warning, but now we are more verbose ...
+          Log.warn("Unable to initialize the module " + this.module.getName(), me);
+        }
+        else if (Log.isWarningEnabled())
+        {
+          Log.warn("Unable to initialize the module " + this.module.getName());
+        }
+        this.state = STATE_ERROR;
+      }
+      catch (Exception e)
+      {
+        if (Log.isDebugEnabled())
+        {
+          // its still worth a warning, but now we are more verbose ...
+          Log.warn("Unable to initialize the module " + this.module.getName(), e);
+        }
+        else if (Log.isWarningEnabled())
+        {
+          Log.warn("Unable to initialize the module " + this.module.getName());
+        }
+        this.state = STATE_ERROR;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Compares this object with the given other object for equality. 
+   * @see java.lang.Object#equals(java.lang.Object)
+   * 
+   * @param o the other object to be compared
+   * @return true, if the other object is also a PackageState containing
+   * the same module, false otherwise. 
+   */
+  public boolean equals(final Object o)
+  {
+    if (this == o)
+    {
+      return true;
+    }
+    if (!(o instanceof PackageState))
+    {
+      return false;
+    }
+
+    final PackageState packageState = (PackageState) o;
+
+    if (!this.module.getModuleClass().equals(packageState.module.getModuleClass()))
+    {
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * Computes a hashcode for this package state. 
+   * @see java.lang.Object#hashCode()
+   * 
+   * @return the hashcode.
+   */
+  public int hashCode()
+  {
+    return this.module.hashCode();
+  }
+}

+ 83 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/SubSystem.java

@@ -0,0 +1,83 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * --------------
+ * SubSystem.java
+ * --------------
+ * (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: SubSystem.java,v 1.5 2005/10/18 13:14:50 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 10-Jul-2003 : Initial version
+ * 07-Jun-2004 : Added JCommon header (DG);
+ * 
+ */
+
+package org.jfree.base.modules;
+
+import org.jfree.util.Configuration;
+import org.jfree.util.ExtendedConfiguration;
+
+/**
+ * A sub-system holds a separate collection of modules.
+ * <p>
+ * On a simple level, subsystems can be just libraries.
+ * Libraries offering services need a controlled way to
+ * initialize these services before dependent code starts
+ * using the library. This can be achived by embedding the
+ * library services into an own subsystem.
+ *
+ * @author Thomas Morgner
+ */
+public interface SubSystem {
+
+    /**
+     * Returns the global configuration.
+     * 
+     * @return The global configuration.
+     */
+    public Configuration getGlobalConfig();
+
+    /**
+     * Returns the global configuration as ExtendedConfiguration instance.
+     *
+     * @return the extended configuration.
+     */
+    public ExtendedConfiguration getExtendedConfig ();
+
+    /**
+     * Returns the package manager.
+     * 
+     * @return The package manager.
+     */
+    public PackageManager getPackageManager();
+
+}

+ 18 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/modules/package.html

@@ -0,0 +1,18 @@
+<html>
+<body>
+Module definitions:
+<p>
+By default the JFreeReport base package and JCommon are included.
+Additionally the J2SDK package exists in the system by default.
+A module that requires a specific java version should create a
+dependency to the module "J2SDK" and set the required version
+numbers.
+<p>
+Known modules:
+org.jfree.report.modules.output.csv.CSVModule
+org.jfree.report.modules.output.xml.XMLModule
+org.jfree.report.modules.output.base.OutputBaseModule
+org.jfree.report.modules.output.csv.CSVModule
+
+</body>
+</html>

+ 6 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/base/package.html

@@ -0,0 +1,6 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+Base level classes.
+</body>
+</html>

+ 86 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/date/AnnualDateRule.java

@@ -0,0 +1,86 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ *
+ * -------------------
+ * AnnualDateRule.java
+ * -------------------
+ * (C) Copyright 2000-2003, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: AnnualDateRule.java,v 1.4 2005/11/16 15:58:40 taqua Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 26-Oct-2001 : Changed package to com.jrefinery.date.* (DG);
+ * 12-Nov-2001 : Javadoc comments updated (DG);
+ * 03-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ *
+ */
+
+package org.jfree.date;
+
+/**
+ * The base class for all 'annual' date rules: that is, rules for generating
+ * one date for any given year.
+ * <P>
+ * One example is Easter Sunday (which can be calculated using published algorithms).
+ *
+ * @author David Gilbert
+ */
+public abstract class AnnualDateRule implements Cloneable {
+
+    /**
+     * Default constructor.
+     */
+    protected AnnualDateRule() {
+    }
+
+    /**
+     * Returns the date for this rule, given the year.
+     *
+     * @param year  the year (1900 &lt;= year &lt;= 9999).
+     *
+     * @return the date for this rule, given the year.
+     */
+    public abstract SerialDate getDate(int year);
+
+    /**
+     * Returns a clone of the rule.
+     * <P>
+     * You should refer to the documentation of the clone() method in each
+     * subclass for exact details.
+     *
+     * @return a clone of the rule.
+     *
+     * @throws CloneNotSupportedException if the rule is not clonable.
+     */
+    public Object clone() throws CloneNotSupportedException {
+        return super.clone();
+    }
+
+}

+ 100 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/date/DateUtilities.java

@@ -0,0 +1,100 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ *
+ * ------------------
+ * DateUtilities.java
+ * ------------------
+ * (C) Copyright 2002, 2003, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: DateUtilities.java,v 1.4 2005/11/16 15:58:40 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 11-Oct-2002 : Version 1 (DG);
+ * 03-Apr-2003 : Added clear() method call (DG)
+ *
+ */
+
+package org.jfree.date;
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * Some useful date methods.
+ *
+ * @author David Gilbert.
+ */
+public class DateUtilities {
+
+    /**
+     * Private constructor to prevent object creation.
+     */
+    private DateUtilities() {
+    }
+
+    /** A working calendar. */
+    private static final Calendar CALENDAR = Calendar.getInstance();
+
+    /**
+     * Creates a date.
+     *
+     * @param yyyy  the year.
+     * @param month  the month (1 - 12).
+     * @param day  the day.
+     *
+     * @return a date.
+     */
+    public static synchronized Date createDate(final int yyyy, final int month, final int day) {
+        CALENDAR.clear();
+        CALENDAR.set(yyyy, month - 1, day);
+        return CALENDAR.getTime();
+    }
+
+    /**
+     * Creates a date.
+     *
+     * @param yyyy  the year.
+     * @param month  the month (1 - 12).
+     * @param day  the day.
+     * @param hour  the hour.
+     * @param min  the minute.
+     *
+     * @return a date.
+     */
+    public static synchronized Date createDate(final int yyyy, final int month, final int day, final int hour, final int min) {
+
+        CALENDAR.clear();
+        CALENDAR.set(yyyy, month - 1, day, hour, min);
+        return CALENDAR.getTime();
+
+    }
+
+
+}

+ 158 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/date/DayAndMonthRule.java

@@ -0,0 +1,158 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ *
+ * --------------------
+ * DayAndMonthRule.java
+ * --------------------
+ * (C) Copyright 2000-2003, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: DayAndMonthRule.java,v 1.6 2005/11/16 15:58:40 taqua Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 26-Oct-2001 : Changed package to com.jrefinery.date.* (DG);
+ * 12-Nov-2001 : Added some argument checks (DG);
+ * 03-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ * 01-Jun-2005 : Removed the explicit clonable declaration, it is declared
+ *               in the super class.
+ */
+
+package org.jfree.date;
+
+/**
+ * An annual date rule where the generated date always falls on the same day
+ * and month each year.
+ * <P>
+ * An example is ANZAC Day in Australia and New Zealand: it is observed on
+ * 25 April of every year.
+ *
+ * @author David Gilbert
+ */
+public class DayAndMonthRule extends AnnualDateRule {
+
+    /** The day of the month. */
+    private int dayOfMonth;
+
+    /** The month (uses 1 to 12 in the obvious way). */
+    private int month;
+
+    /**
+     * Default constructor: builds a DayAndMonthRule for 1 January.
+     */
+    public DayAndMonthRule() {
+        this(1, MonthConstants.JANUARY);
+    }
+
+    /**
+     * Standard constructor: builds a DayAndMonthRule for the given
+     * day-of-the-month and month.
+     * <P>
+     * For the month parameter, use SerialDate.JANUARY, etc. Note that there
+     * are no checks to prevent you from entering an invalid combination (such
+     * as 31 February).
+     *
+     * @param dayOfMonth  the day of the month (in the range 1 to 31).
+     * @param month  the month (use SerialDate.JANUARY, SerialDate.FEBRUARY etc.);
+     */
+    public DayAndMonthRule(final int dayOfMonth, final int month) {
+
+        // check arguments delegated to setter methods...
+        setMonth(month);
+        setDayOfMonth(dayOfMonth);
+
+    }
+
+    /**
+     * Returns the day of the month.
+     *
+     * @return the day of the month.
+     */
+    public int getDayOfMonth() {
+        return this.dayOfMonth;
+    }
+
+    /**
+     * Sets the day-of-the-month for this rule.
+     *
+     * @param dayOfMonth  the day-of-the-month.
+     */
+    public void setDayOfMonth(final int dayOfMonth) {
+
+        // check arguments...
+        if ((dayOfMonth < 1) || (dayOfMonth > SerialDate.LAST_DAY_OF_MONTH[this.month])) {
+            throw new IllegalArgumentException(
+                "DayAndMonthRule(): dayOfMonth outside valid range.");
+        }
+
+        // make the change...
+        this.dayOfMonth = dayOfMonth;
+
+    }
+
+    /**
+     * Returns an integer code representing the month.
+     * <P>
+     * The codes JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST,
+     * SEPTEMBER, OCTOBER, NOVEMBER and DECEMBER are defined in the SerialDate
+     * class.
+     *
+     * @return an integer code representing the month.
+     */
+    public int getMonth() {
+        return this.month;
+    }
+
+    /**
+     * Sets the month for this rule.
+     *
+     * @param month  the month for this rule.
+     */
+    public void setMonth(final int month) {
+
+        // check arguments...
+        if (!SerialDate.isValidMonthCode(month)) {
+            throw new IllegalArgumentException("DayAndMonthRule(): month code not valid.");
+        }
+
+        // make the change...
+        this.month = month;
+
+    }
+
+    /**
+     * Returns the date, given the year.
+     *
+     * @param yyyy  the year.
+     *
+     * @return the date generated by this rule for the specified year (null permitted).
+     */
+    public SerialDate getDate(final int yyyy) {
+        return SerialDate.createInstance(this.dayOfMonth, this.month, yyyy);
+    }
+}

+ 168 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/date/DayOfWeekInMonthRule.java

@@ -0,0 +1,168 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ *
+ * -------------------------
+ * DayOfWeekInMonthRule.java
+ * -------------------------
+ * (C) Copyright 2000-2003, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: DayOfWeekInMonthRule.java,v 1.5 2005/11/16 15:58:40 taqua Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 26-Oct-2001 : Changed package to com.jrefinery.date.*;
+ * 03-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ * 01-Jun-2005 : Removed the explicit clonable declaration, it is declared
+ *               in the super class.
+ */
+
+package org.jfree.date;
+
+/**
+ * An annual date rule that specifies the nth day of the week in a given month
+ * (for example, the third Wednesday in June, or the last Friday in November).
+ *
+ * @author David Gilbert
+ */
+public class DayOfWeekInMonthRule extends AnnualDateRule {
+
+    /** FIRST, SECOND, THIRD, FOURTH or LAST. */
+    private int count;
+
+    /** The day of the week (SerialDate.MONDAY, SerialDate.TUESDAY...). */
+    private int dayOfWeek;
+
+    /** The month (1 to 12, or SerialDate.JANUARY, SerialDate.FEBRUARY...). */
+    private int month;
+
+    /**
+     * Default constructor: builds a rule for the first Monday in January by default.
+     */
+    public DayOfWeekInMonthRule() {
+        this(1, SerialDate.MONDAY, MonthConstants.JANUARY);
+    }
+
+    /**
+     * Standard constructor: builds a rule with the specified attributes.
+     *
+     * @param count  one of: FIRST, SECOND, THIRD, FOURTH or LAST.
+     * @param dayOfWeek  the day-of-the-week (SerialDate.MONDAY, SerialDate.TUESDAY, etc.).
+     * @param month  the month (SerialDate.JANUARY, SerialDate.FEBRUARY, etc.).
+     */
+    public DayOfWeekInMonthRule(final int count, final int dayOfWeek, final int month) {
+        this.count = count;
+        this.dayOfWeek = dayOfWeek;
+        this.month = month;
+    }
+
+    /**
+     * Returns the 'count' for this rule (one of FIRST, SECOND, THIRD, FOURTH and LAST).
+     *
+     * @return the 'count'.
+     */
+    public int getCount() {
+        return this.count;
+    }
+
+    /**
+     * Sets the 'count' for this rule (one of FIRST, SECOND, THIRD, FOURTH and LAST).
+     *
+     * @param count the 'count'.
+     */
+    public void setCount(final int count) {
+        this.count = count;
+    }
+
+    /**
+     * Returns the day-of-the-week for this rule (SerialDate.MONDAY, SerialDate.TUESDAY, etc.).
+     *
+     * @return the day-of-the-week.
+     */
+    public int getDayOfWeek() {
+        return this.dayOfWeek;
+    }
+
+    /**
+     * Sets the day-of-the-week for this rule.
+     *
+     * @param dayOfWeek  the day-of-the-week.
+     */
+    public void setDayOfWeek(final int dayOfWeek) {
+        this.dayOfWeek = dayOfWeek;
+    }
+
+    /**
+     * Returns the month for this rule.
+     *
+     * @return the month.
+     */
+    public int getMonth() {
+        return this.month;
+    }
+
+    /**
+     * Sets the month for this rule.
+     *
+     * @param month  the month (SerialDate.JANUARY, SerialDate.FEBRUARY, etc.).
+     */
+    public void setMonth(final int month) {
+        this.month = month;
+    }
+
+    /**
+     * Return the date for this rule, given the year.
+     *
+     * @param year  the year.
+     *
+     * @return the date generated by the rule for the given year.
+     */
+    public SerialDate getDate(final int year) {
+        SerialDate result;
+        if (this.count != SerialDate.LAST_WEEK_IN_MONTH) {
+            // start at the beginning of the month
+            result = SerialDate.createInstance(1, this.month, year);
+            while (result.getDayOfWeek() != this.dayOfWeek) {
+                result = SerialDate.addDays(1, result);
+            }
+            result = SerialDate.addDays(7 * (this.count - 1), result);
+
+        }
+        else {
+            // start at the end of the month and work backwards...
+            result = SerialDate.createInstance(1, this.month, year);
+            result = result.getEndOfCurrentMonth(result);
+            while (result.getDayOfWeek() != this.dayOfWeek) {
+                result = SerialDate.addDays(-1, result);
+            }
+
+        }
+        return result;
+    }
+
+}

+ 89 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/date/EasterSundayRule.java

@@ -0,0 +1,89 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ *
+ * ---------------------
+ * EasterSundayRule.java
+ * ---------------------
+ * (C) Copyright 2000-2003, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: EasterSundayRule.java,v 1.4 2005/11/16 15:58:40 taqua Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 26-Oct-2001 : Changed package to com.jrefinery.date.*;
+ * 03-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ * 01-Jun-2005 : Removed the explicit clonable declaration, it is declared
+ *               in the super class.
+ */
+
+package org.jfree.date;
+
+/**
+ * An annual date rule for Easter (Sunday).  The algorithm used here was
+ * obtained from a Calendar FAQ which can be found at:
+ * <P>
+ * <a href="http://www.tondering.dk/claus/calendar.html"
+ *     >http://www.tondering.dk/claus/calendar.html</a>.
+ * <P>
+ * It is based on an algorithm by Oudin (1940) and quoted in "Explanatory Supplement to the
+ * Astronomical Almanac", P. Kenneth Seidelmann, editor.
+ *
+ * @author David Gilbert
+ */
+public class EasterSundayRule extends AnnualDateRule {
+
+    /**
+     * Default constructor.
+     */
+    public EasterSundayRule() {
+    }
+
+    /**
+     * Returns the date of Easter Sunday for the given year.  See the class
+     * description for the source of the algorithm.
+     * <P>
+     * This method supports the AnnualDateRule interface.
+     *
+     * @param year  the year to check.
+     *
+     * @return the date of Easter Sunday for the given year.
+     */
+    public SerialDate getDate(final int year) {
+        final int g = year % 19;
+        final int c = year / 100;
+        final int h = (c - c / 4 - (8 * c + 13) / 25 + 19 * g + 15) % 30;
+        final int i = h - h / 28 * (1 - h / 28 * 29 / (h + 1) * (21 - g) / 11);
+        final int j = (year + year / 4 + i + 2 - c + c / 4) % 7;
+        final int l = i - j;
+        final int month = 3 + (l + 40) / 44;
+        final int day = l + 28 - 31 * (month / 4);
+        return SerialDate.createInstance(day, month, year);
+    }
+
+}

+ 91 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/date/MonthConstants.java

@@ -0,0 +1,91 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ *
+ * -------------------
+ * MonthConstants.java
+ * -------------------
+ * (C) Copyright 2002, 2003, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: MonthConstants.java,v 1.4 2005/11/16 15:58:40 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 29-May-2002 : Version 1 (code moved from SerialDate class) (DG);
+ *
+ */
+
+package org.jfree.date;
+
+/**
+ * Useful constants for months.  Note that these are NOT equivalent to the
+ * constants defined by java.util.Calendar (where JANUARY=0 and DECEMBER=11).
+ * <P>
+ * Used by the SerialDate and RegularTimePeriod classes.
+ *
+ * @author David Gilbert
+ */
+public interface MonthConstants {
+
+    /** Constant for January. */
+    public static final int JANUARY = 1;
+
+    /** Constant for February. */
+    public static final int FEBRUARY = 2;
+
+    /** Constant for March. */
+    public static final int MARCH = 3;
+
+    /** Constant for April. */
+    public static final int APRIL = 4;
+
+    /** Constant for May. */
+    public static final int MAY = 5;
+
+    /** Constant for June. */
+    public static final int JUNE = 6;
+
+    /** Constant for July. */
+    public static final int JULY = 7;
+
+    /** Constant for August. */
+    public static final int AUGUST = 8;
+
+    /** Constant for September. */
+    public static final int SEPTEMBER = 9;
+
+    /** Constant for October. */
+    public static final int OCTOBER = 10;
+
+    /** Constant for November. */
+    public static final int NOVEMBER = 11;
+
+    /** Constant for December. */
+    public static final int DECEMBER = 12;
+
+}

+ 209 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/date/RelativeDayOfWeekRule.java

@@ -0,0 +1,209 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ *
+ * --------------------------
+ * RelativeDayOfWeekRule.java
+ * --------------------------
+ * (C) Copyright 2000-2003, by Object Refinery Limited and Contributors.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: RelativeDayOfWeekRule.java,v 1.6 2005/11/16 15:58:40 taqua Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 26-Oct-2001 : Changed package to com.jrefinery.date.*;
+ * 03-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ *
+ */
+
+package org.jfree.date;
+
+/**
+ * An annual date rule that returns a date for each year based on (a) a
+ * reference rule; (b) a day of the week; and (c) a selection parameter
+ * (SerialDate.PRECEDING, SerialDate.NEAREST, SerialDate.FOLLOWING).
+ * <P>
+ * For example, Good Friday can be specified as 'the Friday PRECEDING Easter 
+ * Sunday'.
+ *
+ * @author David Gilbert
+ */
+public class RelativeDayOfWeekRule extends AnnualDateRule {
+
+    /** A reference to the annual date rule on which this rule is based. */
+    private AnnualDateRule subrule;
+
+    /** 
+     * The day of the week (SerialDate.MONDAY, SerialDate.TUESDAY, and so on). 
+     */
+    private int dayOfWeek;
+
+    /** Specifies which day of the week (PRECEDING, NEAREST or FOLLOWING). */
+    private int relative;
+
+    /**
+     * Default constructor - builds a rule for the Monday following 1 January.
+     */
+    public RelativeDayOfWeekRule() {
+        this(new DayAndMonthRule(), SerialDate.MONDAY, SerialDate.FOLLOWING);
+    }
+
+    /**
+     * Standard constructor - builds rule based on the supplied sub-rule.
+     *
+     * @param subrule  the rule that determines the reference date.
+     * @param dayOfWeek  the day-of-the-week relative to the reference date.
+     * @param relative  indicates *which* day-of-the-week (preceding, nearest 
+     *                  or following).
+     */
+    public RelativeDayOfWeekRule(final AnnualDateRule subrule, 
+            final int dayOfWeek, final int relative) {
+        this.subrule = subrule;
+        this.dayOfWeek = dayOfWeek;
+        this.relative = relative;
+    }
+
+    /**
+     * Returns the sub-rule (also called the reference rule).
+     *
+     * @return The annual date rule that determines the reference date for this 
+     *         rule.
+     */
+    public AnnualDateRule getSubrule() {
+        return this.subrule;
+    }
+
+    /**
+     * Sets the sub-rule.
+     *
+     * @param subrule  the annual date rule that determines the reference date 
+     *                 for this rule.
+     */
+    public void setSubrule(final AnnualDateRule subrule) {
+        this.subrule = subrule;
+    }
+
+    /**
+     * Returns the day-of-the-week for this rule.
+     *
+     * @return the day-of-the-week for this rule.
+     */
+    public int getDayOfWeek() {
+        return this.dayOfWeek;
+    }
+
+    /**
+     * Sets the day-of-the-week for this rule.
+     *
+     * @param dayOfWeek  the day-of-the-week (SerialDate.MONDAY, 
+     *                   SerialDate.TUESDAY, and so on).
+     */
+    public void setDayOfWeek(final int dayOfWeek) {
+        this.dayOfWeek = dayOfWeek;
+    }
+
+    /**
+     * Returns the 'relative' attribute, that determines *which* 
+     * day-of-the-week we are interested in (SerialDate.PRECEDING, 
+     * SerialDate.NEAREST or SerialDate.FOLLOWING).
+     *
+     * @return The 'relative' attribute.
+     */
+    public int getRelative() {
+        return this.relative;
+    }
+
+    /**
+     * Sets the 'relative' attribute (SerialDate.PRECEDING, SerialDate.NEAREST,
+     * SerialDate.FOLLOWING).
+     *
+     * @param relative  determines *which* day-of-the-week is selected by this 
+     *                  rule.
+     */
+    public void setRelative(final int relative) {
+        this.relative = relative;
+    }
+
+    /**
+     * Creates a clone of this rule.
+     *
+     * @return a clone of this rule.
+     *
+     * @throws CloneNotSupportedException this should never happen.
+     */
+    public Object clone() throws CloneNotSupportedException {
+        final RelativeDayOfWeekRule duplicate 
+            = (RelativeDayOfWeekRule) super.clone();
+        duplicate.subrule = (AnnualDateRule) duplicate.getSubrule().clone();
+        return duplicate;
+    }
+
+    /**
+     * Returns the date generated by this rule, for the specified year.
+     *
+     * @param year  the year (1900 &lt;= year &lt;= 9999).
+     *
+     * @return The date generated by the rule for the given year (possibly 
+     *         <code>null</code>).
+     */
+    public SerialDate getDate(final int year) {
+
+        // check argument...
+        if ((year < SerialDate.MINIMUM_YEAR_SUPPORTED)
+            || (year > SerialDate.MAXIMUM_YEAR_SUPPORTED)) {
+            throw new IllegalArgumentException(
+                "RelativeDayOfWeekRule.getDate(): year outside valid range.");
+        }
+
+        // calculate the date...
+        SerialDate result = null;
+        final SerialDate base = this.subrule.getDate(year);
+
+        if (base != null) {
+            switch (this.relative) {
+                case(SerialDate.PRECEDING):
+                    result = SerialDate.getPreviousDayOfWeek(this.dayOfWeek, 
+                            base);
+                    break;
+                case(SerialDate.NEAREST):
+                    result = SerialDate.getNearestDayOfWeek(this.dayOfWeek, 
+                            base);
+                    break;
+                case(SerialDate.FOLLOWING):
+                    result = SerialDate.getFollowingDayOfWeek(this.dayOfWeek, 
+                            base);
+                    break;
+                default:
+                    break;
+            }
+        }
+        return result;
+
+    }
+
+}

+ 1035 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/date/SerialDate.java

@@ -0,0 +1,1035 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ *
+ * ---------------
+ * SerialDate.java
+ * ---------------
+ * (C) Copyright 2001-2006, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: SerialDate.java,v 1.9 2011/10/17 20:08:22 mungady Exp $
+ *
+ * Changes (from 11-Oct-2001)
+ * --------------------------
+ * 11-Oct-2001 : Re-organised the class and moved it to new package 
+ *               com.jrefinery.date (DG);
+ * 05-Nov-2001 : Added a getDescription() method, and eliminated NotableDate 
+ *               class (DG);
+ * 12-Nov-2001 : IBD requires setDescription() method, now that NotableDate 
+ *               class is gone (DG);  Changed getPreviousDayOfWeek(), 
+ *               getFollowingDayOfWeek() and getNearestDayOfWeek() to correct 
+ *               bugs (DG);
+ * 05-Dec-2001 : Fixed bug in SpreadsheetDate class (DG);
+ * 29-May-2002 : Moved the month constants into a separate interface 
+ *               (MonthConstants) (DG);
+ * 27-Aug-2002 : Fixed bug in addMonths() method, thanks to N???levka Petr (DG);
+ * 03-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ * 13-Mar-2003 : Implemented Serializable (DG);
+ * 29-May-2003 : Fixed bug in addMonths method (DG);
+ * 04-Sep-2003 : Implemented Comparable.  Updated the isInRange javadocs (DG);
+ * 05-Jan-2005 : Fixed bug in addYears() method (1096282) (DG);
+ * 
+ */
+
+package org.jfree.date;
+
+import java.io.Serializable;
+import java.text.DateFormatSymbols;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+/**
+ *  An abstract class that defines our requirements for manipulating dates,
+ *  without tying down a particular implementation.
+ *  <P>
+ *  Requirement 1 : match at least what Excel does for dates;
+ *  Requirement 2 : the date represented by the class is immutable;
+ *  <P>
+ *  Why not just use java.util.Date?  We will, when it makes sense.  At times,
+ *  java.util.Date can be *too* precise - it represents an instant in time,
+ *  accurate to 1/1000th of a second (with the date itself depending on the
+ *  time-zone).  Sometimes we just want to represent a particular day (e.g. 21
+ *  January 2015) without concerning ourselves about the time of day, or the
+ *  time-zone, or anything else.  That's what we've defined SerialDate for.
+ *  <P>
+ *  You can call getInstance() to get a concrete subclass of SerialDate,
+ *  without worrying about the exact implementation.
+ *
+ * @author David Gilbert
+ */
+public abstract class SerialDate implements Comparable, 
+                                            Serializable, 
+                                            MonthConstants {
+
+    /** For serialization. */
+    private static final long serialVersionUID = -293716040467423637L;
+    
+    /** Date format symbols. */
+    public static final DateFormatSymbols
+        DATE_FORMAT_SYMBOLS = new SimpleDateFormat().getDateFormatSymbols();
+
+    /** The serial number for 1 January 1900. */
+    public static final int SERIAL_LOWER_BOUND = 2;
+
+    /** The serial number for 31 December 9999. */
+    public static final int SERIAL_UPPER_BOUND = 2958465;
+
+    /** The lowest year value supported by this date format. */
+    public static final int MINIMUM_YEAR_SUPPORTED = 1900;
+
+    /** The highest year value supported by this date format. */
+    public static final int MAXIMUM_YEAR_SUPPORTED = 9999;
+
+    /** Useful constant for Monday. Equivalent to java.util.Calendar.MONDAY. */
+    public static final int MONDAY = Calendar.MONDAY;
+
+    /** 
+     * Useful constant for Tuesday. Equivalent to java.util.Calendar.TUESDAY. 
+     */
+    public static final int TUESDAY = Calendar.TUESDAY;
+
+    /** 
+     * Useful constant for Wednesday. Equivalent to 
+     * java.util.Calendar.WEDNESDAY. 
+     */
+    public static final int WEDNESDAY = Calendar.WEDNESDAY;
+
+    /** 
+     * Useful constant for Thrusday. Equivalent to java.util.Calendar.THURSDAY. 
+     */
+    public static final int THURSDAY = Calendar.THURSDAY;
+
+    /** Useful constant for Friday. Equivalent to java.util.Calendar.FRIDAY. */
+    public static final int FRIDAY = Calendar.FRIDAY;
+
+    /** 
+     * Useful constant for Saturday. Equivalent to java.util.Calendar.SATURDAY.
+     */
+    public static final int SATURDAY = Calendar.SATURDAY;
+
+    /** Useful constant for Sunday. Equivalent to java.util.Calendar.SUNDAY. */
+    public static final int SUNDAY = Calendar.SUNDAY;
+
+    /** The number of days in each month in non leap years. */
+    static final int[] LAST_DAY_OF_MONTH =
+        {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+    /** The number of days in a (non-leap) year up to the end of each month. */
+    static final int[] AGGREGATE_DAYS_TO_END_OF_MONTH =
+        {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
+
+    /** The number of days in a year up to the end of the preceding month. */
+    static final int[] AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH =
+        {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
+
+    /** The number of days in a leap year up to the end of each month. */
+    static final int[] LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_MONTH =
+        {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
+
+    /** 
+     * The number of days in a leap year up to the end of the preceding month. 
+     */
+    static final int[] 
+        LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH =
+            {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
+
+    /** A useful constant for referring to the first week in a month. */
+    public static final int FIRST_WEEK_IN_MONTH = 1;
+
+    /** A useful constant for referring to the second week in a month. */
+    public static final int SECOND_WEEK_IN_MONTH = 2;
+
+    /** A useful constant for referring to the third week in a month. */
+    public static final int THIRD_WEEK_IN_MONTH = 3;
+
+    /** A useful constant for referring to the fourth week in a month. */
+    public static final int FOURTH_WEEK_IN_MONTH = 4;
+
+    /** A useful constant for referring to the last week in a month. */
+    public static final int LAST_WEEK_IN_MONTH = 0;
+
+    /** Useful range constant. */
+    public static final int INCLUDE_NONE = 0;
+
+    /** Useful range constant. */
+    public static final int INCLUDE_FIRST = 1;
+
+    /** Useful range constant. */
+    public static final int INCLUDE_SECOND = 2;
+
+    /** Useful range constant. */
+    public static final int INCLUDE_BOTH = 3;
+
+    /** 
+     * Useful constant for specifying a day of the week relative to a fixed 
+     * date. 
+     */
+    public static final int PRECEDING = -1;
+
+    /** 
+     * Useful constant for specifying a day of the week relative to a fixed 
+     * date. 
+     */
+    public static final int NEAREST = 0;
+
+    /** 
+     * Useful constant for specifying a day of the week relative to a fixed 
+     * date. 
+     */
+    public static final int FOLLOWING = 1;
+
+    /** A description for the date. */
+    private String description;
+
+    /**
+     * Default constructor.
+     */
+    protected SerialDate() {
+    }
+
+    /**
+     * Returns <code>true</code> if the supplied integer code represents a 
+     * valid day-of-the-week, and <code>false</code> otherwise.
+     *
+     * @param code  the code being checked for validity.
+     *
+     * @return <code>true</code> if the supplied integer code represents a 
+     *         valid day-of-the-week, and <code>false</code> otherwise.
+     */
+    public static boolean isValidWeekdayCode(final int code) {
+
+        switch(code) {
+            case SUNDAY: 
+            case MONDAY: 
+            case TUESDAY: 
+            case WEDNESDAY: 
+            case THURSDAY: 
+            case FRIDAY: 
+            case SATURDAY: 
+                return true;
+            default: 
+                return false;
+        }
+
+    }
+
+    /**
+     * Converts the supplied string to a day of the week.
+     *
+     * @param s  a string representing the day of the week.
+     *
+     * @return <code>-1</code> if the string is not convertable, the day of 
+     *         the week otherwise.
+     */
+    public static int stringToWeekdayCode(String s) {
+
+        final String[] shortWeekdayNames 
+            = DATE_FORMAT_SYMBOLS.getShortWeekdays();
+        final String[] weekDayNames = DATE_FORMAT_SYMBOLS.getWeekdays();
+
+        int result = -1;
+        s = s.trim();
+        for (int i = 0; i < weekDayNames.length; i++) {
+            if (s.equals(shortWeekdayNames[i])) {
+                result = i;
+                break;
+            }
+            if (s.equals(weekDayNames[i])) {
+                result = i;
+                break;
+            }
+        }
+        return result;
+
+    }
+
+    /**
+     * Returns a string representing the supplied day-of-the-week.
+     * <P>
+     * Need to find a better approach.
+     *
+     * @param weekday  the day of the week.
+     *
+     * @return a string representing the supplied day-of-the-week.
+     */
+    public static String weekdayCodeToString(final int weekday) {
+
+        final String[] weekdays = DATE_FORMAT_SYMBOLS.getWeekdays();
+        return weekdays[weekday];
+
+    }
+
+    /**
+     * Returns an array of month names.
+     *
+     * @return an array of month names.
+     */
+    public static String[] getMonths() {
+
+        return getMonths(false);
+
+    }
+
+    /**
+     * Returns an array of month names.
+     *
+     * @param shortened  a flag indicating that shortened month names should 
+     *                   be returned.
+     *
+     * @return an array of month names.
+     */
+    public static String[] getMonths(final boolean shortened) {
+
+        if (shortened) {
+            return DATE_FORMAT_SYMBOLS.getShortMonths();
+        }
+        else {
+            return DATE_FORMAT_SYMBOLS.getMonths();
+        }
+
+    }
+
+    /**
+     * Returns true if the supplied integer code represents a valid month.
+     *
+     * @param code  the code being checked for validity.
+     *
+     * @return <code>true</code> if the supplied integer code represents a 
+     *         valid month.
+     */
+    public static boolean isValidMonthCode(final int code) {
+
+        switch(code) {
+            case JANUARY: 
+            case FEBRUARY: 
+            case MARCH: 
+            case APRIL: 
+            case MAY: 
+            case JUNE: 
+            case JULY: 
+            case AUGUST: 
+            case SEPTEMBER: 
+            case OCTOBER: 
+            case NOVEMBER: 
+            case DECEMBER: 
+                return true;
+            default: 
+                return false;
+        }
+
+    }
+
+    /**
+     * Returns the quarter for the specified month.
+     *
+     * @param code  the month code (1-12).
+     *
+     * @return the quarter that the month belongs to.
+     */
+    public static int monthCodeToQuarter(final int code) {
+
+        switch(code) {
+            case JANUARY: 
+            case FEBRUARY: 
+            case MARCH: return 1;
+            case APRIL: 
+            case MAY: 
+            case JUNE: return 2;
+            case JULY: 
+            case AUGUST: 
+            case SEPTEMBER: return 3;
+            case OCTOBER: 
+            case NOVEMBER: 
+            case DECEMBER: return 4;
+            default: throw new IllegalArgumentException(
+                "SerialDate.monthCodeToQuarter: invalid month code.");
+        }
+
+    }
+
+    /**
+     * Returns a string representing the supplied month.
+     * <P>
+     * The string returned is the long form of the month name taken from the 
+     * default locale.
+     *
+     * @param month  the month.
+     *
+     * @return a string representing the supplied month.
+     */
+    public static String monthCodeToString(final int month) {
+
+        return monthCodeToString(month, false);
+
+    }
+
+    /**
+     * Returns a string representing the supplied month.
+     * <P>
+     * The string returned is the long or short form of the month name taken 
+     * from the default locale.
+     *
+     * @param month  the month.
+     * @param shortened  if <code>true</code> return the abbreviation of the 
+     *                   month.
+     *
+     * @return a string representing the supplied month.
+     */
+    public static String monthCodeToString(final int month, 
+                                           final boolean shortened) {
+
+        // check arguments...
+        if (!isValidMonthCode(month)) {
+            throw new IllegalArgumentException(
+                "SerialDate.monthCodeToString: month outside valid range.");
+        }
+
+        final String[] months;
+
+        if (shortened) {
+            months = DATE_FORMAT_SYMBOLS.getShortMonths();
+        }
+        else {
+            months = DATE_FORMAT_SYMBOLS.getMonths();
+        }
+
+        return months[month - 1];
+
+    }
+
+    /**
+     * Converts a string to a month code.
+     * <P>
+     * This method will return one of the constants JANUARY, FEBRUARY, ..., 
+     * DECEMBER that corresponds to the string.  If the string is not 
+     * recognised, this method returns -1.
+     *
+     * @param s  the string to parse.
+     *
+     * @return <code>-1</code> if the string is not parseable, the month of the
+     *         year otherwise.
+     */
+    public static int stringToMonthCode(String s) {
+
+        final String[] shortMonthNames = DATE_FORMAT_SYMBOLS.getShortMonths();
+        final String[] monthNames = DATE_FORMAT_SYMBOLS.getMonths();
+
+        int result = -1;
+        s = s.trim();
+
+        // first try parsing the string as an integer (1-12)...
+        try {
+            result = Integer.parseInt(s);
+        }
+        catch (NumberFormatException e) {
+            // suppress
+        }
+
+        // now search through the month names...
+        if ((result < 1) || (result > 12)) {
+            for (int i = 0; i < monthNames.length; i++) {
+                if (s.equals(shortMonthNames[i])) {
+                    result = i + 1;
+                    break;
+                }
+                if (s.equals(monthNames[i])) {
+                    result = i + 1;
+                    break;
+                }
+            }
+        }
+
+        return result;
+
+    }
+
+    /**
+     * Returns true if the supplied integer code represents a valid 
+     * week-in-the-month, and false otherwise.
+     *
+     * @param code  the code being checked for validity.
+     * @return <code>true</code> if the supplied integer code represents a 
+     *         valid week-in-the-month.
+     */
+    public static boolean isValidWeekInMonthCode(final int code) {
+
+        switch(code) {
+            case FIRST_WEEK_IN_MONTH: 
+            case SECOND_WEEK_IN_MONTH: 
+            case THIRD_WEEK_IN_MONTH: 
+            case FOURTH_WEEK_IN_MONTH: 
+            case LAST_WEEK_IN_MONTH: return true;
+            default: return false;
+        }
+
+    }
+
+    /**
+     * Determines whether or not the specified year is a leap year.
+     *
+     * @param yyyy  the year (in the range 1900 to 9999).
+     *
+     * @return <code>true</code> if the specified year is a leap year.
+     */
+    public static boolean isLeapYear(final int yyyy) {
+
+        if ((yyyy % 4) != 0) {
+            return false;
+        }
+        else if ((yyyy % 400) == 0) {
+            return true;
+        }
+        else if ((yyyy % 100) == 0) {
+            return false;
+        }
+        else {
+            return true;
+        }
+
+    }
+
+    /**
+     * Returns the number of leap years from 1900 to the specified year 
+     * INCLUSIVE.
+     * <P>
+     * Note that 1900 is not a leap year.
+     *
+     * @param yyyy  the year (in the range 1900 to 9999).
+     *
+     * @return the number of leap years from 1900 to the specified year.
+     */
+    public static int leapYearCount(final int yyyy) {
+
+        final int leap4 = (yyyy - 1896) / 4;
+        final int leap100 = (yyyy - 1800) / 100;
+        final int leap400 = (yyyy - 1600) / 400;
+        return leap4 - leap100 + leap400;
+
+    }
+
+    /**
+     * Returns the number of the last day of the month, taking into account 
+     * leap years.
+     *
+     * @param month  the month.
+     * @param yyyy  the year (in the range 1900 to 9999).
+     *
+     * @return the number of the last day of the month.
+     */
+    public static int lastDayOfMonth(final int month, final int yyyy) {
+
+        final int result = LAST_DAY_OF_MONTH[month];
+        if (month != FEBRUARY) {
+            return result;
+        }
+        else if (isLeapYear(yyyy)) {
+            return result + 1;
+        }
+        else {
+            return result;
+        }
+
+    }
+
+    /**
+     * Creates a new date by adding the specified number of days to the base 
+     * date.
+     *
+     * @param days  the number of days to add (can be negative).
+     * @param base  the base date.
+     *
+     * @return a new date.
+     */
+    public static SerialDate addDays(final int days, final SerialDate base) {
+
+        final int serialDayNumber = base.toSerial() + days;
+        return SerialDate.createInstance(serialDayNumber);
+
+    }
+
+    /**
+     * Creates a new date by adding the specified number of months to the base 
+     * date.
+     * <P>
+     * If the base date is close to the end of the month, the day on the result
+     * may be adjusted slightly:  31 May + 1 month = 30 June.
+     *
+     * @param months  the number of months to add (can be negative).
+     * @param base  the base date.
+     *
+     * @return a new date.
+     */
+    public static SerialDate addMonths(final int months, 
+                                       final SerialDate base) {
+
+        final int yy = (12 * base.getYYYY() + base.getMonth() + months - 1) 
+                       / 12;
+        final int mm = (12 * base.getYYYY() + base.getMonth() + months - 1) 
+                       % 12 + 1;
+        final int dd = Math.min(
+            base.getDayOfMonth(), SerialDate.lastDayOfMonth(mm, yy)
+        );
+        return SerialDate.createInstance(dd, mm, yy);
+
+    }
+
+    /**
+     * Creates a new date by adding the specified number of years to the base 
+     * date.
+     *
+     * @param years  the number of years to add (can be negative).
+     * @param base  the base date.
+     *
+     * @return A new date.
+     */
+    public static SerialDate addYears(final int years, final SerialDate base) {
+
+        final int baseY = base.getYYYY();
+        final int baseM = base.getMonth();
+        final int baseD = base.getDayOfMonth();
+
+        final int targetY = baseY + years;
+        final int targetD = Math.min(
+            baseD, SerialDate.lastDayOfMonth(baseM, targetY)
+        );
+
+        return SerialDate.createInstance(targetD, baseM, targetY);
+
+    }
+
+    /**
+     * Returns the latest date that falls on the specified day-of-the-week and 
+     * is BEFORE the base date.
+     *
+     * @param targetWeekday  a code for the target day-of-the-week.
+     * @param base  the base date.
+     *
+     * @return the latest date that falls on the specified day-of-the-week and 
+     *         is BEFORE the base date.
+     */
+    public static SerialDate getPreviousDayOfWeek(final int targetWeekday, 
+                                                  final SerialDate base) {
+
+        // check arguments...
+        if (!SerialDate.isValidWeekdayCode(targetWeekday)) {
+            throw new IllegalArgumentException(
+                "Invalid day-of-the-week code."
+            );
+        }
+
+        // find the date...
+        final int adjust;
+        final int baseDOW = base.getDayOfWeek();
+        if (baseDOW > targetWeekday) {
+            adjust = Math.min(0, targetWeekday - baseDOW);
+        }
+        else {
+            adjust = -7 + Math.max(0, targetWeekday - baseDOW);
+        }
+
+        return SerialDate.addDays(adjust, base);
+
+    }
+
+    /**
+     * Returns the earliest date that falls on the specified day-of-the-week
+     * and is AFTER the base date.
+     *
+     * @param targetWeekday  a code for the target day-of-the-week.
+     * @param base  the base date.
+     *
+     * @return the earliest date that falls on the specified day-of-the-week 
+     *         and is AFTER the base date.
+     */
+    public static SerialDate getFollowingDayOfWeek(final int targetWeekday, 
+                                                   final SerialDate base) {
+
+        // check arguments...
+        if (!SerialDate.isValidWeekdayCode(targetWeekday)) {
+            throw new IllegalArgumentException(
+                "Invalid day-of-the-week code."
+            );
+        }
+
+        // find the date...
+        final int adjust;
+        final int baseDOW = base.getDayOfWeek();
+        if (baseDOW > targetWeekday) {
+            adjust = 7 + Math.min(0, targetWeekday - baseDOW);
+        }
+        else {
+            adjust = Math.max(0, targetWeekday - baseDOW);
+        }
+
+        return SerialDate.addDays(adjust, base);
+    }
+
+    /**
+     * Returns the date that falls on the specified day-of-the-week and is
+     * CLOSEST to the base date.
+     *
+     * @param targetDOW  a code for the target day-of-the-week.
+     * @param base  the base date.
+     *
+     * @return the date that falls on the specified day-of-the-week and is 
+     *         CLOSEST to the base date.
+     */
+    public static SerialDate getNearestDayOfWeek(final int targetDOW,  
+                                                 final SerialDate base) {
+
+        // check arguments...
+        if (!SerialDate.isValidWeekdayCode(targetDOW)) {
+            throw new IllegalArgumentException(
+                "Invalid day-of-the-week code."
+            );
+        }
+
+        // find the date...
+        final int baseDOW = base.getDayOfWeek();
+        int adjust = -Math.abs(targetDOW - baseDOW);
+        if (adjust >= 4) {
+            adjust = 7 - adjust;
+        }
+        if (adjust <= -4) {
+            adjust = 7 + adjust;
+        }
+        return SerialDate.addDays(adjust, base);
+
+    }
+
+    /**
+     * Rolls the date forward to the last day of the month.
+     *
+     * @param base  the base date.
+     *
+     * @return a new serial date.
+     */
+    public SerialDate getEndOfCurrentMonth(final SerialDate base) {
+        final int last = SerialDate.lastDayOfMonth(
+            base.getMonth(), base.getYYYY()
+        );
+        return SerialDate.createInstance(last, base.getMonth(), base.getYYYY());
+    }
+
+    /**
+     * Returns a string corresponding to the week-in-the-month code.
+     * <P>
+     * Need to find a better approach.
+     *
+     * @param count  an integer code representing the week-in-the-month.
+     *
+     * @return a string corresponding to the week-in-the-month code.
+     */
+    public static String weekInMonthToString(final int count) {
+
+        switch (count) {
+            case SerialDate.FIRST_WEEK_IN_MONTH : return "First";
+            case SerialDate.SECOND_WEEK_IN_MONTH : return "Second";
+            case SerialDate.THIRD_WEEK_IN_MONTH : return "Third";
+            case SerialDate.FOURTH_WEEK_IN_MONTH : return "Fourth";
+            case SerialDate.LAST_WEEK_IN_MONTH : return "Last";
+            default :
+                return "SerialDate.weekInMonthToString(): invalid code.";
+        }
+
+    }
+
+    /**
+     * Returns a string representing the supplied 'relative'.
+     * <P>
+     * Need to find a better approach.
+     *
+     * @param relative  a constant representing the 'relative'.
+     *
+     * @return a string representing the supplied 'relative'.
+     */
+    public static String relativeToString(final int relative) {
+
+        switch (relative) {
+            case SerialDate.PRECEDING : return "Preceding";
+            case SerialDate.NEAREST : return "Nearest";
+            case SerialDate.FOLLOWING : return "Following";
+            default : return "ERROR : Relative To String";
+        }
+
+    }
+
+    /**
+     * Factory method that returns an instance of some concrete subclass of 
+     * {@link SerialDate}.
+     *
+     * @param day  the day (1-31).
+     * @param month  the month (1-12).
+     * @param yyyy  the year (in the range 1900 to 9999).
+     *
+     * @return An instance of {@link SerialDate}.
+     */
+    public static SerialDate createInstance(final int day, final int month, 
+                                            final int yyyy) {
+        return new SpreadsheetDate(day, month, yyyy);
+    }
+
+    /**
+     * Factory method that returns an instance of some concrete subclass of 
+     * {@link SerialDate}.
+     *
+     * @param serial  the serial number for the day (1 January 1900 = 2).
+     *
+     * @return a instance of SerialDate.
+     */
+    public static SerialDate createInstance(final int serial) {
+        return new SpreadsheetDate(serial);
+    }
+
+    /**
+     * Factory method that returns an instance of a subclass of SerialDate.
+     *
+     * @param date  A Java date object.
+     *
+     * @return a instance of SerialDate.
+     */
+    public static SerialDate createInstance(final java.util.Date date) {
+
+        final GregorianCalendar calendar = new GregorianCalendar();
+        calendar.setTime(date);
+        return new SpreadsheetDate(calendar.get(Calendar.DATE),
+                                   calendar.get(Calendar.MONTH) + 1,
+                                   calendar.get(Calendar.YEAR));
+
+    }
+
+    /**
+     * Returns the serial number for the date, where 1 January 1900 = 2 (this
+     * corresponds, almost, to the numbering system used in Microsoft Excel for
+     * Windows and Lotus 1-2-3).
+     *
+     * @return the serial number for the date.
+     */
+    public abstract int toSerial();
+
+    /**
+     * Returns a java.util.Date.  Since java.util.Date has more precision than
+     * SerialDate, we need to define a convention for the 'time of day'.
+     *
+     * @return this as <code>java.util.Date</code>.
+     */
+    public abstract java.util.Date toDate();
+
+    /**
+     * Returns the description that is attached to the date.  It is not 
+     * required that a date have a description, but for some applications it 
+     * is useful.
+     *
+     * @return The description (possibly <code>null</code>).
+     */
+    public String getDescription() {
+        return this.description;
+    }
+
+    /**
+     * Sets the description for the date.
+     *
+     * @param description  the description for this date (<code>null</code> 
+     *                     permitted).
+     */
+    public void setDescription(final String description) {
+        this.description = description;
+    }
+
+    /**
+     * Converts the date to a string.
+     *
+     * @return  a string representation of the date.
+     */
+    public String toString() {
+        return getDayOfMonth() + "-" + SerialDate.monthCodeToString(getMonth())
+                               + "-" + getYYYY();
+    }
+
+    /**
+     * Returns the year (assume a valid range of 1900 to 9999).
+     *
+     * @return the year.
+     */
+    public abstract int getYYYY();
+
+    /**
+     * Returns the month (January = 1, February = 2, March = 3).
+     *
+     * @return the month of the year.
+     */
+    public abstract int getMonth();
+
+    /**
+     * Returns the day of the month.
+     *
+     * @return the day of the month.
+     */
+    public abstract int getDayOfMonth();
+
+    /**
+     * Returns the day of the week.
+     *
+     * @return the day of the week.
+     */
+    public abstract int getDayOfWeek();
+
+    /**
+     * Returns the difference (in days) between this date and the specified 
+     * 'other' date.
+     * <P>
+     * The result is positive if this date is after the 'other' date and
+     * negative if it is before the 'other' date.
+     *
+     * @param other  the date being compared to.
+     *
+     * @return the difference between this and the other date.
+     */
+    public abstract int compare(SerialDate other);
+
+    /**
+     * Returns true if this SerialDate represents the same date as the 
+     * specified SerialDate.
+     *
+     * @param other  the date being compared to.
+     *
+     * @return <code>true</code> if this SerialDate represents the same date as 
+     *         the specified SerialDate.
+     */
+    public abstract boolean isOn(SerialDate other);
+
+    /**
+     * Returns true if this SerialDate represents an earlier date compared to
+     * the specified SerialDate.
+     *
+     * @param other  The date being compared to.
+     *
+     * @return <code>true</code> if this SerialDate represents an earlier date 
+     *         compared to the specified SerialDate.
+     */
+    public abstract boolean isBefore(SerialDate other);
+
+    /**
+     * Returns true if this SerialDate represents the same date as the 
+     * specified SerialDate.
+     *
+     * @param other  the date being compared to.
+     *
+     * @return <code>true</code> if this SerialDate represents the same date
+     *         as the specified SerialDate.
+     */
+    public abstract boolean isOnOrBefore(SerialDate other);
+
+    /**
+     * Returns true if this SerialDate represents the same date as the 
+     * specified SerialDate.
+     *
+     * @param other  the date being compared to.
+     *
+     * @return <code>true</code> if this SerialDate represents the same date
+     *         as the specified SerialDate.
+     */
+    public abstract boolean isAfter(SerialDate other);
+
+    /**
+     * Returns true if this SerialDate represents the same date as the 
+     * specified SerialDate.
+     *
+     * @param other  the date being compared to.
+     *
+     * @return <code>true</code> if this SerialDate represents the same date
+     *         as the specified SerialDate.
+     */
+    public abstract boolean isOnOrAfter(SerialDate other);
+
+    /**
+     * Returns <code>true</code> if this {@link SerialDate} is within the 
+     * specified range (INCLUSIVE).  The date order of d1 and d2 is not 
+     * important.
+     *
+     * @param d1  a boundary date for the range.
+     * @param d2  the other boundary date for the range.
+     *
+     * @return A boolean.
+     */
+    public abstract boolean isInRange(SerialDate d1, SerialDate d2);
+
+    /**
+     * Returns <code>true</code> if this {@link SerialDate} is within the 
+     * specified range (caller specifies whether or not the end-points are 
+     * included).  The date order of d1 and d2 is not important.
+     *
+     * @param d1  a boundary date for the range.
+     * @param d2  the other boundary date for the range.
+     * @param include  a code that controls whether or not the start and end 
+     *                 dates are included in the range.
+     *
+     * @return A boolean.
+     */
+    public abstract boolean isInRange(SerialDate d1, SerialDate d2, 
+                                      int include);
+
+    /**
+     * Returns the latest date that falls on the specified day-of-the-week and
+     * is BEFORE this date.
+     *
+     * @param targetDOW  a code for the target day-of-the-week.
+     *
+     * @return the latest date that falls on the specified day-of-the-week and
+     *         is BEFORE this date.
+     */
+    public SerialDate getPreviousDayOfWeek(final int targetDOW) {
+        return getPreviousDayOfWeek(targetDOW, this);
+    }
+
+    /**
+     * Returns the earliest date that falls on the specified day-of-the-week
+     * and is AFTER this date.
+     *
+     * @param targetDOW  a code for the target day-of-the-week.
+     *
+     * @return the earliest date that falls on the specified day-of-the-week
+     *         and is AFTER this date.
+     */
+    public SerialDate getFollowingDayOfWeek(final int targetDOW) {
+        return getFollowingDayOfWeek(targetDOW, this);
+    }
+
+    /**
+     * Returns the nearest date that falls on the specified day-of-the-week.
+     *
+     * @param targetDOW  a code for the target day-of-the-week.
+     *
+     * @return the nearest date that falls on the specified day-of-the-week.
+     */
+    public SerialDate getNearestDayOfWeek(final int targetDOW) {
+        return getNearestDayOfWeek(targetDOW, this);
+    }
+
+}

+ 388 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/date/SerialDateUtilities.java

@@ -0,0 +1,388 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ *
+ * ------------------------
+ * SerialDateUtilities.java
+ * ------------------------
+ * (C) Copyright 2001-2003, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: SerialDateUtilities.java,v 1.6 2005/11/16 15:58:40 taqua Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 26-Oct-2001 : Changed package to com.jrefinery.date.*;
+ * 08-Dec-2001 : Dropped isLeapYear() method (DG);
+ * 04-Mar-2002 : Renamed SerialDates.java --> SerialDateUtilities.java (DG);
+ * 25-Jun-2002 : Fixed a bug in the dayCountActual() method (DG);
+ * 03-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ *
+ */
+
+package org.jfree.date;
+
+import java.text.DateFormatSymbols;
+import java.util.Calendar;
+
+/**
+ * A utility class that provides a number of useful methods (some static).
+ * Many of these are used in the implementation of the day-count convention
+ * classes.  I recognise some limitations in this implementation:
+ * <p>
+ * [1] some of the methods assume that the default Calendar is a
+ * GregorianCalendar (used mostly to determine leap years) - so the code
+ * won&rsquo;t work if some other Calendar is the default.  I'm not sure how
+ * to handle this properly?
+ * <p>
+ * [2] a whole bunch of static methods isn't very object-oriented - but I couldn't think of a good
+ * way to extend the Date and Calendar classes to add the functions I required,
+ * so static methods are doing the job for now.
+ *
+ * @author David Gilbert
+ */
+public class SerialDateUtilities {
+
+    /** The default date format symbols. */
+    private DateFormatSymbols dateFormatSymbols;
+
+    /** Strings representing the weekdays. */
+    private String[] weekdays;
+
+    /** Strings representing the months. */
+    private String[] months;
+
+    /**
+     * Creates a new utility class for the default locale.
+     */
+    public SerialDateUtilities() {
+        this.dateFormatSymbols = new DateFormatSymbols();
+        this.weekdays = this.dateFormatSymbols.getWeekdays();
+        this.months = this.dateFormatSymbols.getMonths();
+    }
+
+    /**
+     * Returns an array of strings representing the days-of-the-week.
+     *
+     * @return an array of strings representing the days-of-the-week.
+     */
+    public String[] getWeekdays() {
+        return this.weekdays;
+    }
+
+    /**
+     * Returns an array of strings representing the months.
+     *
+     * @return an array of strings representing the months.
+     */
+    public String[] getMonths() {
+        return this.months;
+    }
+
+    /**
+     * Converts the specified string to a weekday, using the default locale.
+     *
+     * @param s  a string representing the day-of-the-week.
+     *
+     * @return an integer representing the day-of-the-week.
+     */
+    public int stringToWeekday(final String s) {
+
+        if (s.equals(this.weekdays[Calendar.SATURDAY])) {
+            return SerialDate.SATURDAY;
+        }
+        else if (s.equals(this.weekdays[Calendar.SUNDAY])) {
+            return SerialDate.SUNDAY;
+        }
+        else if (s.equals(this.weekdays[Calendar.MONDAY])) {
+            return SerialDate.MONDAY;
+        }
+        else if (s.equals(this.weekdays[Calendar.TUESDAY])) {
+            return SerialDate.TUESDAY;
+        }
+        else if (s.equals(this.weekdays[Calendar.WEDNESDAY])) {
+            return SerialDate.WEDNESDAY;
+        }
+        else if (s.equals(this.weekdays[Calendar.THURSDAY])) {
+            return SerialDate.THURSDAY;
+        }
+        else {
+            return SerialDate.FRIDAY;
+        }
+
+    }
+
+    /**
+     * Returns the actual number of days between two dates.
+     *
+     * @param start  the start date.
+     * @param end  the end date.
+     *
+     * @return the number of days between the start date and the end date.
+     */
+    public static int dayCountActual(final SerialDate start, final SerialDate end) {
+        return end.compare(start);
+    }
+
+    /**
+     * Returns the number of days between the specified start and end dates,
+     * assuming that there are thirty days in every month (that is,
+     * corresponding to the 30/360 day-count convention).
+     * <P>
+     * The method handles cases where the start date is before the end date (by
+     * switching the dates and returning a negative result).
+     *
+     * @param start  the start date.
+     * @param end  the end date.
+     *
+     * @return the number of days between the two dates, assuming the 30/360 day-count convention.
+     */
+    public static int dayCount30(final SerialDate start, final SerialDate end) {
+        final int d1;
+        final int m1;
+        final int y1;
+        final int d2;
+        final int m2;
+        final int y2;
+        if (start.isBefore(end)) {  // check the order of the dates
+            d1 = start.getDayOfMonth();
+            m1 = start.getMonth();
+            y1 = start.getYYYY();
+            d2 = end.getDayOfMonth();
+            m2 = end.getMonth();
+            y2 = end.getYYYY();
+            return 360 * (y2 - y1) + 30 * (m2 - m1) + (d2 - d1);
+        }
+        else {
+            return -dayCount30(end, start);
+        }
+    }
+
+    /**
+     * Returns the number of days between the specified start and end dates,
+     * assuming that there are thirty days in every month, and applying the
+     * ISDA adjustments (that is, corresponding to the 30/360 (ISDA) day-count
+     * convention).
+     * <P>
+     * The method handles cases where the start date is before the end date (by
+     * switching the dates around and returning a negative result).
+     *
+     * @param start  the start date.
+     * @param end  the end date.
+     *
+     * @return The number of days between the two dates, assuming the 30/360
+     *      (ISDA) day-count convention.
+     */
+    public static int dayCount30ISDA(final SerialDate start, final SerialDate end) {
+        int d1;
+        final int m1;
+        final int y1;
+        int d2;
+        final int m2;
+        final int y2;
+        if (start.isBefore(end)) {
+            d1 = start.getDayOfMonth();
+            m1 = start.getMonth();
+            y1 = start.getYYYY();
+            if (d1 == 31) {  // first ISDA adjustment
+                d1 = 30;
+            }
+            d2 = end.getDayOfMonth();
+            m2 = end.getMonth();
+            y2 = end.getYYYY();
+            if ((d2 == 31) && (d1 == 30)) {  // second ISDA adjustment
+                d2 = 30;
+            }
+            return 360 * (y2 - y1) + 30 * (m2 - m1) + (d2 - d1);
+        }
+        else if (start.isAfter(end)) {
+            return -dayCount30ISDA(end, start);
+        }
+        else {
+            return 0;
+        }
+    }
+
+    /**
+     * Returns the number of days between the specified start and end dates,
+     * assuming that there are thirty days in every month, and applying the PSA
+     * adjustments (that is, corresponding to the 30/360 (PSA) day-count convention).
+     * The method handles cases where the start date is before the end date (by
+     * switching the dates around and returning a negative result).
+     *
+     * @param start  the start date.
+     * @param end  the end date.
+     *
+     * @return The number of days between the two dates, assuming the 30/360
+     *      (PSA) day-count convention.
+     */
+    public static int dayCount30PSA(final SerialDate start, final SerialDate end) {
+        int d1;
+        final int m1;
+        final int y1;
+        int d2;
+        final int m2;
+        final int y2;
+
+        if (start.isOnOrBefore(end)) { // check the order of the dates
+            d1 = start.getDayOfMonth();
+            m1 = start.getMonth();
+            y1 = start.getYYYY();
+
+            if (SerialDateUtilities.isLastDayOfFebruary(start)) {
+                d1 = 30;
+            }
+            if ((d1 == 31) || SerialDateUtilities.isLastDayOfFebruary(start)) {
+                // first PSA adjustment
+                d1 = 30;
+            }
+            d2 = end.getDayOfMonth();
+            m2 = end.getMonth();
+            y2 = end.getYYYY();
+            if ((d2 == 31) && (d1 == 30)) {  // second PSA adjustment
+                d2 = 30;
+            }
+            return 360 * (y2 - y1) + 30 * (m2 - m1) + (d2 - d1);
+        }
+        else {
+            return -dayCount30PSA(end, start);
+        }
+    }
+
+    /**
+     * Returns the number of days between the specified start and end dates,
+     * assuming that there are thirty days in every month, and applying the
+     * European adjustment (that is, corresponding to the 30E/360 day-count
+     * convention).
+     * <P>
+     * The method handles cases where the start date is before the end date (by
+     * switching the dates around and returning a negative result).
+     *
+     * @param start  the start date.
+     * @param end  the end date.
+     *
+     * @return the number of days between the two dates, assuming the 30E/360
+     *      day-count convention.
+     */
+    public static int dayCount30E(final SerialDate start, final SerialDate end) {
+        int d1;
+        final int m1;
+        final int y1;
+        int d2;
+        final int m2;
+        final int y2;
+        if (start.isBefore(end)) {
+            d1 = start.getDayOfMonth();
+            m1 = start.getMonth();
+            y1 = start.getYYYY();
+            if (d1 == 31) {  // first European adjustment
+                d1 = 30;
+            }
+            d2 = end.getDayOfMonth();
+            m2 = end.getMonth();
+            y2 = end.getYYYY();
+            if (d2 == 31) {  // first European adjustment
+                d2 = 30;
+            }
+            return 360 * (y2 - y1) + 30 * (m2 - m1) + (d2 - d1);
+        }
+        else if (start.isAfter(end)) {
+            return -dayCount30E(end, start);
+        }
+        else {
+            return 0;
+        }
+    }
+
+    /**
+     * Returns true if the specified date is the last day in February (that is, the
+     * 28th in non-leap years, and the 29th in leap years).
+     *
+     * @param d  the date to be tested.
+     *
+     * @return a boolean that indicates whether or not the specified date is
+     *      the last day of February.
+     */
+    public static boolean isLastDayOfFebruary(final SerialDate d) {
+
+        final int dom;
+        if (d.getMonth() == MonthConstants.FEBRUARY) {
+            dom = d.getDayOfMonth();
+            if (SerialDate.isLeapYear(d.getYYYY())) {
+                return (dom == 29);
+            }
+            else {
+                return (dom == 28);
+            }
+        }
+        else { // not even February
+            return false;
+        }
+
+    }
+
+    /**
+     * Returns the number of times that February 29 falls within the specified
+     * date range.  The result needs to correspond to the ACT/365 (Japanese)
+     * day-count convention. The difficult cases are where the start or the
+     * end date is Feb 29 (include or not?).  Need to find out how JGBs do this
+     * (since this is where the ACT/365 (Japanese) convention comes from ...
+     *
+     * @param start  the start date.
+     * @param end  the end date.
+     *
+     * @return the number of times that February 29 occurs within the date
+     *      range.
+     */
+    public static int countFeb29s(final SerialDate start, final SerialDate end) {
+        int count = 0;
+        SerialDate feb29;
+        final int y1;
+        final int y2;
+        int year;
+
+        // check the order of the dates
+        if (start.isBefore(end)) {
+
+            y1 = start.getYYYY();
+            y2 = end.getYYYY();
+            for (year = y1; year == y2; year++) {
+                if (SerialDate.isLeapYear(year)) {
+                    feb29 = SerialDate.createInstance(29, MonthConstants.FEBRUARY, year);
+                    if (feb29.isInRange(start, end, SerialDate.INCLUDE_SECOND)) {
+                        count++;
+                    }
+                }
+            }
+            return count;
+        }
+        else {
+            return countFeb29s(end, start);
+        }
+    }
+
+}

+ 461 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/date/SpreadsheetDate.java

@@ -0,0 +1,461 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ *
+ * --------------------
+ * SpreadsheetDate.java
+ * --------------------
+ * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: SpreadsheetDate.java,v 1.10 2006/08/29 13:59:30 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 11-Oct-2001 : Version 1 (DG);
+ * 05-Nov-2001 : Added getDescription() and setDescription() methods (DG);
+ * 12-Nov-2001 : Changed name from ExcelDate.java to SpreadsheetDate.java (DG);
+ *               Fixed a bug in calculating day, month and year from serial 
+ *               number (DG);
+ * 24-Jan-2002 : Fixed a bug in calculating the serial number from the day, 
+ *               month and year.  Thanks to Trevor Hills for the report (DG);
+ * 29-May-2002 : Added equals(Object) method (SourceForge ID 558850) (DG);
+ * 03-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ * 13-Mar-2003 : Implemented Serializable (DG);
+ * 04-Sep-2003 : Completed isInRange() methods (DG);
+ * 05-Sep-2003 : Implemented Comparable (DG);
+ * 21-Oct-2003 : Added hashCode() method (DG);
+ * 29-Aug-2006 : Removed redundant description attribute (DG);
+ *
+ */
+
+package org.jfree.date;
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * Represents a date using an integer, in a similar fashion to the
+ * implementation in Microsoft Excel.  The range of dates supported is
+ * 1-Jan-1900 to 31-Dec-9999.
+ * <P>
+ * Be aware that there is a deliberate bug in Excel that recognises the year
+ * 1900 as a leap year when in fact it is not a leap year. You can find more
+ * information on the Microsoft website in article Q181370:
+ * <P>
+ * http://support.microsoft.com/support/kb/articles/Q181/3/70.asp
+ * <P>
+ * Excel uses the convention that 1-Jan-1900 = 1.  This class uses the
+ * convention 1-Jan-1900 = 2.
+ * The result is that the day number in this class will be different to the
+ * Excel figure for January and February 1900...but then Excel adds in an extra
+ * day (29-Feb-1900 which does not actually exist!) and from that point forward
+ * the day numbers will match.
+ *
+ * @author David Gilbert
+ */
+public class SpreadsheetDate extends SerialDate {
+
+    /** For serialization. */
+    private static final long serialVersionUID = -2039586705374454461L;
+    
+    /** 
+     * The day number (1-Jan-1900 = 2, 2-Jan-1900 = 3, ..., 31-Dec-9999 = 
+     * 2958465). 
+     */
+    private final int serial;
+
+    /** The day of the month (1 to 28, 29, 30 or 31 depending on the month). */
+    private final int day;
+
+    /** The month of the year (1 to 12). */
+    private final int month;
+
+    /** The year (1900 to 9999). */
+    private final int year;
+
+    /**
+     * Creates a new date instance.
+     *
+     * @param day  the day (in the range 1 to 28/29/30/31).
+     * @param month  the month (in the range 1 to 12).
+     * @param year  the year (in the range 1900 to 9999).
+     */
+    public SpreadsheetDate(final int day, final int month, final int year) {
+
+        if ((year >= 1900) && (year <= 9999)) {
+            this.year = year;
+        }
+        else {
+            throw new IllegalArgumentException(
+                "The 'year' argument must be in range 1900 to 9999."
+            );
+        }
+
+        if ((month >= MonthConstants.JANUARY) 
+                && (month <= MonthConstants.DECEMBER)) {
+            this.month = month;
+        }
+        else {
+            throw new IllegalArgumentException(
+                "The 'month' argument must be in the range 1 to 12."
+            );
+        }
+
+        if ((day >= 1) && (day <= SerialDate.lastDayOfMonth(month, year))) {
+            this.day = day;
+        }
+        else {
+            throw new IllegalArgumentException("Invalid 'day' argument.");
+        }
+
+        // the serial number needs to be synchronised with the day-month-year...
+        this.serial = calcSerial(day, month, year);
+
+    }
+
+    /**
+     * Standard constructor - creates a new date object representing the
+     * specified day number (which should be in the range 2 to 2958465.
+     *
+     * @param serial  the serial number for the day (range: 2 to 2958465).
+     */
+    public SpreadsheetDate(final int serial) {
+
+        if ((serial >= SERIAL_LOWER_BOUND) && (serial <= SERIAL_UPPER_BOUND)) {
+            this.serial = serial;
+        }
+        else {
+            throw new IllegalArgumentException(
+                "SpreadsheetDate: Serial must be in range 2 to 2958465.");
+        }
+
+        // the day-month-year needs to be synchronised with the serial number...
+      // get the year from the serial date
+      final int days = this.serial - SERIAL_LOWER_BOUND;
+      // overestimated because we ignored leap days
+      final int overestimatedYYYY = 1900 + (days / 365);
+      final int leaps = SerialDate.leapYearCount(overestimatedYYYY);
+      final int nonleapdays = days - leaps;
+      // underestimated because we overestimated years
+      int underestimatedYYYY = 1900 + (nonleapdays / 365);
+
+      if (underestimatedYYYY == overestimatedYYYY) {
+          this.year = underestimatedYYYY;
+      }
+      else {
+          int ss1 = calcSerial(1, 1, underestimatedYYYY);
+          while (ss1 <= this.serial) {
+              underestimatedYYYY = underestimatedYYYY + 1;
+              ss1 = calcSerial(1, 1, underestimatedYYYY);
+          }
+          this.year = underestimatedYYYY - 1;
+      }
+
+      final int ss2 = calcSerial(1, 1, this.year);
+
+      int[] daysToEndOfPrecedingMonth 
+          = AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH;
+
+      if (isLeapYear(this.year)) {
+          daysToEndOfPrecedingMonth 
+              = LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH;
+      }
+
+      // get the month from the serial date
+      int mm = 1;
+      int sss = ss2 + daysToEndOfPrecedingMonth[mm] - 1;
+      while (sss < this.serial) {
+          mm = mm + 1;
+          sss = ss2 + daysToEndOfPrecedingMonth[mm] - 1;
+      }
+      this.month = mm - 1;
+
+      // what's left is d(+1);
+      this.day = this.serial - ss2 
+                 - daysToEndOfPrecedingMonth[this.month] + 1;
+
+    }
+
+    /**
+     * Returns the serial number for the date, where 1 January 1900 = 2
+     * (this corresponds, almost, to the numbering system used in Microsoft
+     * Excel for Windows and Lotus 1-2-3).
+     *
+     * @return The serial number of this date.
+     */
+    public int toSerial() {
+        return this.serial;
+    }
+
+    /**
+     * Returns a <code>java.util.Date</code> equivalent to this date.
+     *
+     * @return The date.
+     */
+    public Date toDate() {
+        final Calendar calendar = Calendar.getInstance();
+        calendar.set(getYYYY(), getMonth() - 1, getDayOfMonth(), 0, 0, 0);
+        return calendar.getTime();
+    }
+
+    /**
+     * Returns the year (assume a valid range of 1900 to 9999).
+     *
+     * @return The year.
+     */
+    public int getYYYY() {
+        return this.year;
+    }
+
+    /**
+     * Returns the month (January = 1, February = 2, March = 3).
+     *
+     * @return The month of the year.
+     */
+    public int getMonth() {
+        return this.month;
+    }
+
+    /**
+     * Returns the day of the month.
+     *
+     * @return The day of the month.
+     */
+    public int getDayOfMonth() {
+        return this.day;
+    }
+
+    /**
+     * Returns a code representing the day of the week.
+     * <P>
+     * The codes are defined in the {@link SerialDate} class as: 
+     * <code>SUNDAY</code>, <code>MONDAY</code>, <code>TUESDAY</code>, 
+     * <code>WEDNESDAY</code>, <code>THURSDAY</code>, <code>FRIDAY</code>, and 
+     * <code>SATURDAY</code>.
+     *
+     * @return A code representing the day of the week.
+     */
+    public int getDayOfWeek() {
+        return (this.serial + 6) % 7 + 1;
+    }
+
+    /**
+     * Tests the equality of this date with an arbitrary object.
+     * <P>
+     * This method will return true ONLY if the object is an instance of the
+     * {@link SerialDate} base class, and it represents the same day as this
+     * {@link SpreadsheetDate}.
+     *
+     * @param object  the object to compare (<code>null</code> permitted).
+     *
+     * @return A boolean.
+     */
+    public boolean equals(final Object object) {
+
+        if (object instanceof SerialDate) {
+            final SerialDate s = (SerialDate) object;
+            return (s.toSerial() == this.toSerial());
+        }
+        else {
+            return false;
+        }
+
+    }
+
+    /**
+     * Returns a hash code for this object instance.
+     * 
+     * @return A hash code.
+     */
+    public int hashCode() {
+        return toSerial();
+    }
+
+    /**
+     * Returns the difference (in days) between this date and the specified 
+     * 'other' date.
+     *
+     * @param other  the date being compared to.
+     *
+     * @return The difference (in days) between this date and the specified 
+     *         'other' date.
+     */
+    public int compare(final SerialDate other) {
+        return this.serial - other.toSerial();
+    }
+
+    /**
+     * Implements the method required by the Comparable interface.
+     * 
+     * @param other  the other object (usually another SerialDate).
+     * 
+     * @return A negative integer, zero, or a positive integer as this object 
+     *         is less than, equal to, or greater than the specified object.
+     */
+    public int compareTo(final Object other) {
+        return compare((SerialDate) other);    
+    }
+    
+    /**
+     * Returns true if this SerialDate represents the same date as the
+     * specified SerialDate.
+     *
+     * @param other  the date being compared to.
+     *
+     * @return <code>true</code> if this SerialDate represents the same date as
+     *         the specified SerialDate.
+     */
+    public boolean isOn(final SerialDate other) {
+        return (this.serial == other.toSerial());
+    }
+
+    /**
+     * Returns true if this SerialDate represents an earlier date compared to
+     * the specified SerialDate.
+     *
+     * @param other  the date being compared to.
+     *
+     * @return <code>true</code> if this SerialDate represents an earlier date
+     *         compared to the specified SerialDate.
+     */
+    public boolean isBefore(final SerialDate other) {
+        return (this.serial < other.toSerial());
+    }
+
+    /**
+     * Returns true if this SerialDate represents the same date as the
+     * specified SerialDate.
+     *
+     * @param other  the date being compared to.
+     *
+     * @return <code>true</code> if this SerialDate represents the same date
+     *         as the specified SerialDate.
+     */
+    public boolean isOnOrBefore(final SerialDate other) {
+        return (this.serial <= other.toSerial());
+    }
+
+    /**
+     * Returns true if this SerialDate represents the same date as the
+     * specified SerialDate.
+     *
+     * @param other  the date being compared to.
+     *
+     * @return <code>true</code> if this SerialDate represents the same date
+     *         as the specified SerialDate.
+     */
+    public boolean isAfter(final SerialDate other) {
+        return (this.serial > other.toSerial());
+    }
+
+    /**
+     * Returns true if this SerialDate represents the same date as the
+     * specified SerialDate.
+     *
+     * @param other  the date being compared to.
+     *
+     * @return <code>true</code> if this SerialDate represents the same date as
+     *         the specified SerialDate.
+     */
+    public boolean isOnOrAfter(final SerialDate other) {
+        return (this.serial >= other.toSerial());
+    }
+
+    /**
+     * Returns <code>true</code> if this {@link SerialDate} is within the 
+     * specified range (INCLUSIVE).  The date order of d1 and d2 is not 
+     * important.
+     *
+     * @param d1  a boundary date for the range.
+     * @param d2  the other boundary date for the range.
+     *
+     * @return A boolean.
+     */
+    public boolean isInRange(final SerialDate d1, final SerialDate d2) {
+        return isInRange(d1, d2, SerialDate.INCLUDE_BOTH);
+    }
+
+    /**
+     * Returns true if this SerialDate is within the specified range (caller
+     * specifies whether or not the end-points are included).  The order of d1
+     * and d2 is not important.
+     *
+     * @param d1  one boundary date for the range.
+     * @param d2  a second boundary date for the range.
+     * @param include  a code that controls whether or not the start and end 
+     *                 dates are included in the range.
+     *
+     * @return <code>true</code> if this SerialDate is within the specified 
+     *         range.
+     */
+    public boolean isInRange(final SerialDate d1, final SerialDate d2, 
+                             final int include) {
+        final int s1 = d1.toSerial();
+        final int s2 = d2.toSerial();
+        final int start = Math.min(s1, s2);
+        final int end = Math.max(s1, s2);
+        
+        final int s = toSerial();
+        if (include == SerialDate.INCLUDE_BOTH) {
+            return (s >= start && s <= end);
+        }
+        else if (include == SerialDate.INCLUDE_FIRST) {
+            return (s >= start && s < end);            
+        }
+        else if (include == SerialDate.INCLUDE_SECOND) {
+            return (s > start && s <= end);            
+        }
+        else {
+            return (s > start && s < end);            
+        }    
+    }
+
+    /**
+     * Calculate the serial number from the day, month and year.
+     * <P>
+     * 1-Jan-1900 = 2.
+     *
+     * @param d  the day.
+     * @param m  the month.
+     * @param y  the year.
+     *
+     * @return the serial number from the day, month and year.
+     */
+    private int calcSerial(final int d, final int m, final int y) {
+        final int yy = ((y - 1900) * 365) + SerialDate.leapYearCount(y - 1);
+        int mm = SerialDate.AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH[m];
+        if (m > MonthConstants.FEBRUARY) {
+            if (SerialDate.isLeapYear(y)) {
+                mm = mm + 1;
+            }
+        }
+        final int dd = d;
+        return yy + mm + dd + 1;
+    }
+
+}

+ 6 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/date/package.html

@@ -0,0 +1,6 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+Date classes.
+</body>
+</html>

+ 78 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/demo/DateChooserPanelDemo.java

@@ -0,0 +1,78 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -------------------------
+ * DateChooserPanelDemo.java
+ * -------------------------
+ * (C) Copyright 2005, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: DateChooserPanelDemo.java,v 1.1 2005/11/02 14:11:22 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 02-Nov-2005 : Version 1;
+ *
+ */
+
+
+package org.jfree.demo;
+
+import org.jfree.ui.ApplicationFrame;
+import org.jfree.ui.DateChooserPanel;
+import org.jfree.ui.RefineryUtilities;
+
+/**
+ * A simple demo showing the {@link DateChooserPanel}.
+ */
+public class DateChooserPanelDemo extends ApplicationFrame {
+
+    /**
+     * Creates a new demo.
+     *
+     * @param title  the frame title.
+     */
+    public DateChooserPanelDemo(String title) {
+        super(title);
+        setContentPane(new DateChooserPanel());
+    }
+    
+    /**
+     * Starting point for the demonstration application.
+     *
+     * @param args  ignored.
+     */
+    public static void main(String[] args) {
+        DateChooserPanelDemo demo = new DateChooserPanelDemo(
+            "DateChooserPanel Demo");
+        demo.pack();
+        RefineryUtilities.centerFrameOnScreen(demo);
+        demo.setVisible(true);
+    }
+
+}

+ 348 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/demo/DrawStringDemo.java

@@ -0,0 +1,348 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * -------------------
+ * DrawStringDemo.java
+ * -------------------
+ * (C) Copyright 2003-2005, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: DrawStringDemo.java,v 1.6 2008/09/10 09:14:22 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 10-Jun-2003 : Version 1;
+ *
+ */
+
+package org.jfree.demo;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingConstants;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import org.jfree.ui.ApplicationFrame;
+import org.jfree.ui.FontChooserPanel;
+import org.jfree.ui.RefineryUtilities;
+import org.jfree.ui.TextAnchor;
+
+/**
+ * A demo of some of the string drawing methods in the JCommon class library.
+ */
+public class DrawStringDemo extends ApplicationFrame
+                            implements ActionListener, ChangeListener {
+
+    /** The alignment anchor for the first panel. */
+    private JComboBox combo1;
+
+    /** The alignment anchor for the second panel. */
+    private JComboBox combo2;
+
+    /** The rotation anchor for the second panel. */
+    private JComboBox combo3;
+
+    /** A slider for the second panel - controls the angle of rotation. */
+    private JSlider slider;
+
+    /** String panel 1. */
+    private DrawStringPanel drawStringPanel1;
+
+    /** String panel 2. */
+    private DrawStringPanel drawStringPanel2;
+
+    /**
+     * Creates a new demo instance.
+     *
+     * @param title  the frame title.
+     */
+    public DrawStringDemo(final String title) {
+        super(title);
+        setContentPane(createContentPane());
+    }
+
+    /**
+     * Receives action events.
+     *
+     * @param event  the event.
+     */
+    public void actionPerformed(final ActionEvent event) {
+        if (event.getActionCommand().equals("fontButton.clicked")) {
+            displayFontDialog();
+        }
+        if (event.getActionCommand().equals("combo1.changed")) {
+            handleCombo1Change();
+        }
+        if (event.getActionCommand().equals("combo2.changed")) {
+            handleCombo2Change();
+        }
+        if (event.getActionCommand().equals("combo3.changed")) {
+            handleCombo3Change();
+        }
+    }
+
+    /**
+     * Receives change event notification from the slider.
+     *
+     * @param event  the event.
+     */
+    public void stateChanged(ChangeEvent event) {
+        int r = this.slider.getValue();
+        double angle = Math.PI * 2.0 * (r / 360.0);
+        this.drawStringPanel2.setAngle(angle);
+        this.drawStringPanel2.invalidate();
+        this.drawStringPanel2.repaint();
+    }
+
+    /**
+     * Updates the display when combo 1 is updated.
+     */
+    private void handleCombo1Change() {
+        final String text = this.combo1.getSelectedItem().toString();
+        this.drawStringPanel1.setAnchor(convertStringToAnchor(text));
+        this.drawStringPanel1.invalidate();
+        this.drawStringPanel1.repaint();
+    }
+
+    /**
+     * Updates the display when combo 2 is updated.
+     */
+    private void handleCombo2Change() {
+        final String text = this.combo2.getSelectedItem().toString();
+        this.drawStringPanel2.setAnchor(convertStringToAnchor(text));
+        this.drawStringPanel2.invalidate();
+        this.drawStringPanel2.repaint();
+    }
+
+    /**
+     * Updates the display when combo 3 is updated.
+     */
+    private void handleCombo3Change() {
+        final String text = this.combo3.getSelectedItem().toString();
+        this.drawStringPanel2.setRotationAnchor(convertStringToAnchor(text));
+        this.drawStringPanel2.invalidate();
+        this.drawStringPanel2.repaint();
+    }
+
+    /**
+     * Creates the content pane for the demo frame.
+     *
+     * @return The content pane.
+     */
+    private JPanel createContentPane() {
+        final JPanel content = new JPanel(new BorderLayout());
+        final JTabbedPane tabs = new JTabbedPane();
+        tabs.add("Alignment", createTab1Content());
+        tabs.add("Rotation", createTab2Content());
+        content.add(tabs);
+        return content;
+    }
+
+    /**
+     * Creates the content for tab 1.
+     *
+     * @return The content panel.
+     */
+    private JPanel createTab1Content() {
+        final JPanel content = new JPanel(new BorderLayout());
+        this.combo1 = new JComboBox();
+        this.combo1.setActionCommand("combo1.changed");
+        populateTextAnchorCombo(this.combo1);
+        this.combo1.addActionListener(this);
+
+        final JPanel controls = new JPanel();
+        controls.add(this.combo1);
+
+        final JButton fontButton = new JButton("Select Font...");
+        fontButton.setActionCommand("fontButton.clicked");
+        fontButton.addActionListener(this);
+        controls.add(fontButton);
+        content.add(controls, BorderLayout.NORTH);
+        this.drawStringPanel1 = new DrawStringPanel("0123456789", false);
+        content.add(this.drawStringPanel1);
+        return content;
+    }
+
+    /**
+     * Creates the content for tab 2.
+     *
+     * @return The content panel.
+     */
+    private JPanel createTab2Content() {
+        JPanel content = new JPanel(new BorderLayout());
+        JPanel controls = new JPanel();
+        controls.add(new JLabel("Text anchor: "));
+        this.combo2 = new JComboBox();
+        populateTextAnchorCombo(this.combo2);
+        this.combo2.setActionCommand("combo2.changed");
+        this.combo2.addActionListener(this);
+        controls.add(this.combo2);
+        controls.add(new JLabel("Rotation anchor: "));
+        this.combo3 = new JComboBox();
+        populateTextAnchorCombo(this.combo3);
+        this.combo3.setActionCommand("combo3.changed");
+        this.combo3.addActionListener(this);
+        controls.add(this.combo3);
+        this.slider = new JSlider(SwingConstants.VERTICAL, 0, 360, 0);
+        this.slider.setMajorTickSpacing(45);
+        this.slider.setMinorTickSpacing(5);
+        this.slider.setPaintLabels(true);
+        this.slider.setPaintTicks(true);
+        this.slider.setPaintTrack(true);
+        this.slider.addChangeListener(this);
+        content.add(controls, BorderLayout.NORTH);
+        content.add(this.slider, BorderLayout.WEST);
+        this.drawStringPanel2 = new DrawStringPanel("Rotated Text", true);
+        content.add(this.drawStringPanel2);
+        return content;
+    }
+
+    /**
+     * Displays a primitive font chooser dialog to allow the user to change the font.
+     */
+    private void displayFontDialog() {
+
+        final FontChooserPanel panel = new FontChooserPanel(this.drawStringPanel1.getFont());
+        final int result = JOptionPane.showConfirmDialog(this, panel, "Font Selection",
+                                                   JOptionPane.OK_CANCEL_OPTION,
+                                                   JOptionPane.PLAIN_MESSAGE);
+
+        if (result == JOptionPane.OK_OPTION) {
+            this.drawStringPanel1.setFont(panel.getSelectedFont());
+            this.drawStringPanel2.setFont(panel.getSelectedFont());
+        }
+
+    }
+
+    /**
+     * Populates a combo box with the available {@link TextAnchor} options.
+     *
+     * @param combo  the combo box.
+     */
+    private void populateTextAnchorCombo(final JComboBox combo) {
+        combo.addItem("TextAnchor.TOP_LEFT");
+        combo.addItem("TextAnchor.TOP_CENTER");
+        combo.addItem("TextAnchor.TOP_RIGHT");
+        combo.addItem("TextAnchor.HALF_ASCENT_LEFT");
+        combo.addItem("TextAnchor.HALF_ASCENT_CENTER");
+        combo.addItem("TextAnchor.HALF_ASCENT_RIGHT");
+        combo.addItem("TextAnchor.CENTER_LEFT");
+        combo.addItem("TextAnchor.CENTER");
+        combo.addItem("TextAnchor.CENTER_RIGHT");
+        combo.addItem("TextAnchor.BASELINE_LEFT");
+        combo.addItem("TextAnchor.BASELINE_CENTER");
+        combo.addItem("TextAnchor.BASELINE_RIGHT");
+        combo.addItem("TextAnchor.BOTTOM_LEFT");
+        combo.addItem("TextAnchor.BOTTOM_CENTER");
+        combo.addItem("TextAnchor.BOTTOM_RIGHT");
+    }
+
+    /**
+     * Converts a string to a corresponding {@link TextAnchor} instance.
+     *
+     * @param text  the text.
+     *
+     * @return The anchor.
+     */
+    private TextAnchor convertStringToAnchor(final String text) {
+
+        if (text.equals("TextAnchor.TOP_LEFT")) {
+            return TextAnchor.TOP_LEFT;
+        }
+        else if (text.equals("TextAnchor.TOP_CENTER")) {
+            return TextAnchor.TOP_CENTER;
+        }
+        else if (text.equals("TextAnchor.TOP_RIGHT")) {
+            return TextAnchor.TOP_RIGHT;
+        }
+        else if (text.equals("TextAnchor.CENTER_LEFT")) {
+            return TextAnchor.CENTER_LEFT;
+        }
+        else if (text.equals("TextAnchor.CENTER")) {
+            return TextAnchor.CENTER;
+        }
+        else if (text.equals("TextAnchor.CENTER_RIGHT")) {
+            return TextAnchor.CENTER_RIGHT;
+        }
+        else if (text.equals("TextAnchor.HALF_ASCENT_LEFT")) {
+            return TextAnchor.HALF_ASCENT_LEFT;
+        }
+        else if (text.equals("TextAnchor.HALF_ASCENT_CENTER")) {
+            return TextAnchor.HALF_ASCENT_CENTER;
+        }
+        else if (text.equals("TextAnchor.HALF_ASCENT_RIGHT")) {
+            return TextAnchor.HALF_ASCENT_RIGHT;
+        }
+        else if (text.equals("TextAnchor.BASELINE_LEFT")) {
+            return TextAnchor.BASELINE_LEFT;
+        }
+        else if (text.equals("TextAnchor.BASELINE_CENTER")) {
+            return TextAnchor.BASELINE_CENTER;
+        }
+        else if (text.equals("TextAnchor.BASELINE_RIGHT")) {
+            return TextAnchor.BASELINE_RIGHT;
+        }
+        else if (text.equals("TextAnchor.BOTTOM_LEFT")) {
+            return TextAnchor.BOTTOM_LEFT;
+        }
+        else if (text.equals("TextAnchor.BOTTOM_CENTER")) {
+            return TextAnchor.BOTTOM_CENTER;
+        }
+        else if (text.equals("TextAnchor.BOTTOM_RIGHT")) {
+            return TextAnchor.BOTTOM_RIGHT;
+        }
+        else {
+            return null;
+        }
+
+    }
+
+    /**
+     * The starting point for the demo.
+     *
+     * @param args  ignored.
+     */
+    public static void main(final String[] args) {
+
+        final DrawStringDemo demo = new DrawStringDemo("DrawString Demo");
+        demo.pack();
+        RefineryUtilities.centerFrameOnScreen(demo);
+        demo.setVisible(true);
+
+    }
+
+}

+ 192 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/demo/DrawStringPanel.java

@@ -0,0 +1,192 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * --------------------
+ * DrawStringPanel.java
+ * --------------------
+ * (C) Copyright 2003, 2004, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: DrawStringPanel.java,v 1.6 2007/11/02 17:50:35 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 10-Jun-2003 : Version 1;
+ * 30-Sep-2004 : Moved drawRotatedString() from RefineryUtilities --> TextUtilities (DG);
+ *
+ */
+package org.jfree.demo;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Insets;
+import java.awt.geom.Line2D;
+import java.awt.geom.Rectangle2D;
+import javax.swing.JPanel;
+
+import org.jfree.text.TextUtilities;
+import org.jfree.ui.TextAnchor;
+
+/**
+ * A panel used by the {@link DrawStringDemo} class.
+ * 
+ * @author David Gilbert
+ */
+public class DrawStringPanel extends JPanel {
+
+    /** The preferred size for the panel. */
+    private static final Dimension PREFERRED_SIZE = new Dimension(500, 300);
+
+    /** Is the text rotated. */
+    private boolean rotate;
+
+    /** The text to display. */
+    private String text = "Hello World";
+
+    /** The text anchor. */
+    private TextAnchor anchor = TextAnchor.TOP_LEFT;
+
+    /** The rotation anchor. */
+    private TextAnchor rotationAnchor = TextAnchor.TOP_LEFT;
+
+    /** The font. */
+    private Font font = new Font("Serif", Font.PLAIN, 12);
+
+    /** The rotation angle. */
+    private double angle;
+
+    /**
+     * Creates a new panel.
+     *
+     * @param text  the text.
+     * @param rotate  a flag that controls whether or not the text is rotated.
+     */
+    public DrawStringPanel(final String text, final boolean rotate) {
+        this.text = text;
+        this.rotate = rotate;
+    }
+
+    /**
+     * Returns the preferred size for the panel.
+     *
+     * @return The preferred size.
+     */
+    public Dimension getPreferredSize() {
+        return PREFERRED_SIZE;
+    }
+
+    /**
+     * Sets the text anchor.
+     *
+     * @param anchor  the text anchor.
+     */
+    public void setAnchor(final TextAnchor anchor) {
+        this.anchor = anchor;
+    }
+
+    /**
+     * Sets the rotation anchor.
+     *
+     * @param anchor  the rotation anchor.
+     */
+    public void setRotationAnchor(final TextAnchor anchor) {
+        this.rotationAnchor = anchor;
+    }
+
+    /**
+     * Sets the rotation angle.
+     *
+     * @param angle  the rotation angle.
+     */
+    public void setAngle(final double angle) {
+        this.angle = angle;
+    }
+
+    /**
+     * Returns the font.
+     *
+     * @return The font.
+     */
+    public Font getFont() {
+        return this.font;
+    }
+
+    /**
+     * Sets the font.
+     *
+     * @param font  the font.
+     */
+    public void setFont(final Font font) {
+        this.font = font;
+    }
+
+    /**
+     * Paints the panel.
+     *
+     * @param g  the graphics device.
+     */
+    public void paintComponent(final Graphics g) {
+
+        super.paintComponent(g);
+        final Graphics2D g2 = (Graphics2D) g;
+
+        final Dimension size = getSize();
+        final Insets insets = getInsets();
+        final Rectangle2D available = new Rectangle2D.Double(
+            insets.left, insets.top,
+            size.getWidth() - insets.left - insets.right,
+            size.getHeight() - insets.top - insets.bottom
+        );
+
+        final double x = available.getCenterX();
+        final double y = available.getCenterY();
+
+        final Line2D line1 = new Line2D.Double(x - 2.0, y + 2.0, x + 2.0, y - 2.0);
+        final Line2D line2 = new Line2D.Double(x - 2.0, y - 2.0, x + 2.0, y + 2.0);
+        g2.setPaint(Color.red);
+        g2.draw(line1);
+        g2.draw(line2);
+
+        g2.setFont(this.font);
+        g2.setPaint(Color.black);
+        if (this.rotate) {
+            TextUtilities.drawRotatedString(
+                this.text, g2, (float) x, (float) y,
+                this.anchor, this.angle, this.rotationAnchor
+            );
+        }
+        else {
+            TextUtilities.drawAlignedString(this.text, g2, (float) x, (float) y, this.anchor);
+        }
+
+    }
+
+}

+ 97 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/demo/TextBlockDemo.java

@@ -0,0 +1,97 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ------------------
+ * TextBlockDemo.java
+ * ------------------
+ * (C) Copyright 2004, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: TextBlockDemo.java,v 1.4 2007/11/02 17:50:35 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jan-2004 : Version 1 (DG);
+ *
+ */
+
+package org.jfree.demo;
+
+import java.awt.Font;
+import javax.swing.JPanel;
+
+import org.jfree.ui.ApplicationFrame;
+import org.jfree.ui.RefineryUtilities;
+
+/**
+ * A demo of the TextBlock class.
+ *
+ * @author David Gilbert
+ */
+public class TextBlockDemo extends ApplicationFrame {
+
+    /**
+     * Creates a new demo instance.
+     *
+     * @param title  the frame title.
+     */
+    public TextBlockDemo(final String title) {
+        super(title);
+        setContentPane(createContentPane());
+    }
+
+
+    /**
+     * Creates the content pane for the demo frame.
+     *
+     * @return The content pane.
+     */
+    private JPanel createContentPane() {
+        final JPanel content = new TextBlockPanel("This is some really long text that we will use "
+            + "for testing purposes.  You'll need to resize the window to see how the TextBlock "
+            + "is dynamically updated.  Also note what happens when there is a really long "
+            + "word like ABCDEFGHIJKLMNOPQRSTUVWXYZ (OK, that's not really a word).", 
+            new Font("Serif", Font.PLAIN, 14));
+        return content;
+    }
+
+    /**
+     * The starting point for the demo.
+     *
+     * @param args  ignored.
+     */
+    public static void main(final String[] args) {
+
+        final TextBlockDemo demo = new TextBlockDemo("TextBlock Demo");
+        demo.pack();
+        RefineryUtilities.centerFrameOnScreen(demo);
+        demo.setVisible(true);
+
+    }
+
+}

+ 140 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/demo/TextBlockPanel.java

@@ -0,0 +1,140 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -------------------
+ * TextBlockPanel.java
+ * -------------------
+ * (C) Copyright 2004, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: TextBlockPanel.java,v 1.4 2007/11/02 17:50:35 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jan-2004 : Version 1;
+ *
+ */
+
+package org.jfree.demo;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Insets;
+import java.awt.geom.Rectangle2D;
+import javax.swing.JPanel;
+
+import org.jfree.text.G2TextMeasurer;
+import org.jfree.text.TextBlock;
+import org.jfree.text.TextBlockAnchor;
+import org.jfree.text.TextUtilities;
+
+/**
+ * A panel used by the {@link DrawStringDemo} class.
+ *
+ * @author David Gilbert
+ */
+public class TextBlockPanel extends JPanel {
+
+    /** The preferred size for the panel. */
+    private static final Dimension PREFERRED_SIZE = new Dimension(500, 300);
+
+    /** The text to display. */
+    private String text;
+    
+    /** The font to use. */
+    private Font font;
+
+    /**
+     * Creates a new panel.
+     *
+     * @param text  the text.
+     * @param font  the font.
+     */
+    public TextBlockPanel(final String text, final Font font) {
+        this.text = text;
+        this.font = font;
+    }
+
+    /**
+     * Returns the preferred size for the panel.
+     *
+     * @return The preferred size.
+     */
+    public Dimension getPreferredSize() {
+        return PREFERRED_SIZE;
+    }
+
+    /**
+     * Returns the font.
+     *
+     * @return The font.
+     */
+    public Font getFont() {
+        return this.font;
+    }
+
+    /**
+     * Sets the font.
+     *
+     * @param font  the font.
+     */
+    public void setFont(final Font font) {
+        this.font = font;
+    }
+
+    /**
+     * Paints the panel.
+     *
+     * @param g  the graphics device.
+     */
+    public void paintComponent(final Graphics g) {
+
+        super.paintComponent(g);
+        final Graphics2D g2 = (Graphics2D) g;
+
+        final Dimension size = getSize();
+        final Insets insets = getInsets();
+        final Rectangle2D available = new Rectangle2D.Double(insets.left, insets.top,
+                                      size.getWidth() - insets.left - insets.right,
+                                      size.getHeight() - insets.top - insets.bottom);
+
+        final double x = available.getX();
+        final double y = available.getY();
+        final float width = (float) available.getWidth();
+        final TextBlock block = TextUtilities.createTextBlock(
+            this.text, this.font, Color.black, width, new G2TextMeasurer(g2)
+        );
+        g2.setPaint(Color.black);
+        block.draw(g2, (float) x, (float) y, TextBlockAnchor.TOP_LEFT, 0.0f, 0.0f, 0.0);
+
+    }
+
+}

+ 6 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/demo/package.html

@@ -0,0 +1,6 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+Demo code for the JCommon class library.
+</body>
+</html>

+ 103 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/io/FileUtilities.java

@@ -0,0 +1,103 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ------------------
+ * FileUtilities.java
+ * ------------------
+ * (C) Copyright 2000-2004, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: FileUtilities.java,v 1.5 2005/10/18 13:16:02 mungady Exp $
+ *
+ * Changes (from 5-Nov-2001)
+ * -------------------------
+ * 05-Nov-2001 : Changed package to com.jrefinery.io.* (DG);
+ * 04-Mar-2002 : Renamed Files.java --> FileUtilities.java (DG);
+ * 10-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ *
+ */
+
+package org.jfree.io;
+
+import java.io.File;
+import java.util.StringTokenizer;
+
+/**
+ * A class containing useful utility methods relating to files.
+ *
+ * @author David Gilbert
+ */
+public class FileUtilities {
+
+    /**
+     * To prevent unnecessary instantiation.
+     */
+    private FileUtilities() {
+    }
+
+    /**
+     * Returns a reference to a file with the specified name that is located
+     * somewhere on the classpath.  The code for this method is an adaptation
+     * of code supplied by Dave Postill.
+     *
+     * @param name  the filename.
+     *
+     * @return a reference to a file or <code>null</code> if no file could be found.
+     */
+    public static File findFileOnClassPath(final String name) {
+
+        final String classpath = System.getProperty("java.class.path");
+        final String pathSeparator = System.getProperty("path.separator");
+
+        final StringTokenizer tokenizer = new StringTokenizer(classpath, pathSeparator);
+
+        while (tokenizer.hasMoreTokens()) {
+            final String pathElement = tokenizer.nextToken();
+
+            final File directoryOrJar = new File(pathElement);
+            final File absoluteDirectoryOrJar = directoryOrJar.getAbsoluteFile();
+
+            if (absoluteDirectoryOrJar.isFile()) {
+                final File target = new File(absoluteDirectoryOrJar.getParent(), name);
+                if (target.exists()) {
+                    return target;
+                }
+            }
+            else {
+                final File target = new File(directoryOrJar, name);
+                if (target.exists()) {
+                    return target;
+                }
+            }
+
+        }
+        return null;
+
+    }
+
+}

+ 463 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/io/IOUtils.java

@@ -0,0 +1,463 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ------------
+ * IOUtils.java
+ * ------------
+ * (C)opyright 2002-2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: IOUtils.java,v 1.8 2009/01/22 08:34:58 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 26-Jan-2003 : Initial version
+ * 23-Feb-2003 : Documentation
+ * 25-Feb-2003 : Fixed Checkstyle issues (DG);
+ * 29-Apr-2003 : Moved to jcommon
+ * 04-Jan-2004 : Fixed JDK 1.2.2 issues with createRelativeURL;
+ *               added support for query strings within these urls (TM);
+ */
+
+package org.jfree.io;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * The IOUtils provide some IO related helper methods.
+ *
+ * @author Thomas Morgner.
+ */
+public class IOUtils {
+
+    /** the singleton instance of the utility package. */
+    private static IOUtils instance;
+
+    /**
+     * DefaultConstructor.
+     */
+    private IOUtils() {
+    }
+
+    /**
+     * Gets the singleton instance of the utility package.
+     *
+     * @return the singleton instance.
+     */
+    public static IOUtils getInstance() {
+        if (instance == null) {
+            instance = new IOUtils();
+        }
+        return instance;
+    }
+
+    /**
+     * Checks, whether the URL uses a file based protocol.
+     *
+     * @param url the url.
+     * @return true, if the url is file based.
+     */
+    private boolean isFileStyleProtocol(final URL url) {
+        if (url.getProtocol().equals("http")) {
+            return true;
+        }
+        if (url.getProtocol().equals("https")) {
+            return true;
+        }
+        if (url.getProtocol().equals("ftp")) {
+            return true;
+        }
+        if (url.getProtocol().equals("file")) {
+            return true;
+        }
+        if (url.getProtocol().equals("jar")) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Parses the given name and returns the name elements as List of Strings.
+     *
+     * @param name the name, that should be parsed.
+     * @return the parsed name.
+     */
+    private List parseName(final String name) {
+        final ArrayList list = new ArrayList();
+        final StringTokenizer strTok = new StringTokenizer(name, "/");
+        while (strTok.hasMoreElements()) {
+            final String s = (String) strTok.nextElement();
+            if (s.length() != 0) {
+                list.add(s);
+            }
+        }
+        return list;
+    }
+
+    /**
+     * Transforms the name list back into a single string, separated with "/".
+     *
+     * @param name the name list.
+     * @param query the (optional) query for the URL.
+     * @return the constructed name.
+     */
+    private String formatName(final List name, final String query) {
+        final StringBuffer b = new StringBuffer();
+        final Iterator it = name.iterator();
+        while (it.hasNext()) {
+            b.append(it.next());
+            if (it.hasNext()) {
+                b.append("/");
+            }
+        }
+        if (query != null) {
+            b.append('?');
+            b.append(query);
+        }
+        return b.toString();
+    }
+
+    /**
+     * Compares both name lists, and returns the last common index shared 
+     * between the two lists.
+     *
+     * @param baseName the name created using the base url.
+     * @param urlName  the target url name.
+     * @return the number of shared elements.
+     */
+    private int startsWithUntil(final List baseName, final List urlName) {
+        final int minIdx = Math.min(urlName.size(), baseName.size());
+        for (int i = 0; i < minIdx; i++) {
+            final String baseToken = (String) baseName.get(i);
+            final String urlToken = (String) urlName.get(i);
+            if (!baseToken.equals(urlToken)) {
+                return i;
+            }
+        }
+        return minIdx;
+    }
+
+    /**
+     * Checks, whether the URL points to the same service. A service is equal
+     * if the protocol, host and port are equal.
+     *
+     * @param url a url
+     * @param baseUrl an other url, that should be compared.
+     * @return true, if the urls point to the same host and port and use the 
+     *         same protocol, false otherwise.
+     */
+    private boolean isSameService(final URL url, final URL baseUrl) {
+        if (!url.getProtocol().equals(baseUrl.getProtocol())) {
+            return false;
+        }
+        if (!url.getHost().equals(baseUrl.getHost())) {
+            return false;
+        }
+        if (url.getPort() != baseUrl.getPort()) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Creates a relative url by stripping the common parts of the the url.
+     *
+     * @param url the to be stripped url
+     * @param baseURL the base url, to which the <code>url</code> is relative 
+     *                to.
+     * @return the relative url, or the url unchanged, if there is no relation
+     * beween both URLs.
+     */
+    public String createRelativeURL(final URL url, final URL baseURL) {
+        if (url == null) {
+            throw new NullPointerException("content url must not be null.");
+        }
+        if (baseURL == null) {
+            throw new NullPointerException("baseURL must not be null.");
+        }
+        if (isFileStyleProtocol(url) && isSameService(url, baseURL)) {
+
+            // If the URL contains a query, ignore that URL; do not
+            // attemp to modify it...
+            final List urlName = parseName(getPath(url));
+            final List baseName = parseName(getPath(baseURL));
+            final String query = getQuery(url);
+
+            if (!isPath(baseURL)) {
+                baseName.remove(baseName.size() - 1);
+            }
+
+            // if both urls are identical, then return the plain file name... 
+            if (url.equals(baseURL)) {
+                return (String) urlName.get(urlName.size() - 1);
+            }
+
+            int commonIndex = startsWithUntil(urlName, baseName);
+            if (commonIndex == 0) {
+                return url.toExternalForm();
+            }
+
+            if (commonIndex == urlName.size()) {
+                // correct the base index if there is some weird mapping 
+                // detected,
+                // fi. the file url is fully included in the base url:
+                //
+                // base: /file/test/funnybase
+                // file: /file/test
+                //
+                // this could be a valid configuration whereever virtual 
+                // mappings are allowed.
+                commonIndex -= 1;
+            }
+
+            final ArrayList retval = new ArrayList();
+            if (baseName.size() >= urlName.size()) {
+                final int levels = baseName.size() - commonIndex;
+                for (int i = 0; i < levels; i++) {
+                    retval.add("..");
+                }
+            }
+
+            retval.addAll(urlName.subList(commonIndex, urlName.size()));
+            return formatName(retval, query);
+        }
+        return url.toExternalForm();
+    }
+
+    /**
+     * Returns <code>true</code> if the URL represents a path, and 
+     * <code>false</code> otherwise.
+     * 
+     * @param baseURL  the URL.
+     * 
+     * @return A boolean.
+     */
+    private boolean isPath(final URL baseURL) {
+        if (getPath(baseURL).endsWith("/")) {
+            return true;
+        }
+        else if (baseURL.getProtocol().equals("file")) {
+            final File f = new File(getPath(baseURL));
+            try {
+                if (f.isDirectory()) {
+                    return true;
+                }
+            }
+            catch (SecurityException se) {
+                // ignored ...
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Implements the JDK 1.3 method URL.getPath(). The path is defined
+     * as URL.getFile() minus the (optional) query.
+     *
+     * @param url the URL
+     * @return the path
+     */
+    private String getQuery (final URL url) {
+        final String file = url.getFile();
+        final int queryIndex = file.indexOf('?');
+        if (queryIndex == -1) {
+            return null;
+        }
+        return file.substring(queryIndex + 1);
+    }
+
+    /**
+     * Implements the JDK 1.3 method URL.getPath(). The path is defined
+     * as URL.getFile() minus the (optional) query.
+     *
+     * @param url the URL
+     * @return the path
+     */
+    private String getPath (final URL url) {
+        final String file = url.getFile();
+        final int queryIndex = file.indexOf('?');
+        if (queryIndex == -1) {
+            return file;
+        }
+        return file.substring(0, queryIndex);
+    }
+
+    /**
+     * Copies the InputStream into the OutputStream, until the end of the stream
+     * has been reached. This method uses a buffer of 4096 kbyte.
+     *
+     * @param in the inputstream from which to read.
+     * @param out the outputstream where the data is written to.
+     * @throws IOException if a IOError occurs.
+     */
+    public void copyStreams(final InputStream in, final OutputStream out)
+        throws IOException {
+        copyStreams(in, out, 4096);
+    }
+
+    /**
+     * Copies the InputStream into the OutputStream, until the end of the stream
+     * has been reached.
+     *
+     * @param in the inputstream from which to read.
+     * @param out the outputstream where the data is written to.
+     * @param buffersize the buffer size.
+     * @throws IOException if a IOError occurs.
+     */
+    public void copyStreams(final InputStream in, final OutputStream out, 
+            final int buffersize) throws IOException {
+        // create a 4kbyte buffer to read the file
+        final byte[] bytes = new byte[buffersize];
+
+        // the input stream does not supply accurate available() data
+        // the zip entry does not know the size of the data
+        int bytesRead = in.read(bytes);
+        while (bytesRead > -1) {
+            out.write(bytes, 0, bytesRead);
+            bytesRead = in.read(bytes);
+        }
+    }
+
+    /**
+     * Copies the contents of the Reader into the Writer, until the end of the 
+     * stream has been reached. This method uses a buffer of 4096 kbyte.
+     *
+     * @param in the reader from which to read.
+     * @param out the writer where the data is written to.
+     * @throws IOException if a IOError occurs.
+     */
+    public void copyWriter(final Reader in, final Writer out)
+        throws IOException {
+        copyWriter(in, out, 4096);
+    }
+
+    /**
+     * Copies the contents of the Reader into the Writer, until the end of the 
+     * stream has been reached.
+     *
+     * @param in  the reader from which to read.
+     * @param out  the writer where the data is written to.
+     * @param buffersize  the buffer size.
+     *
+     * @throws IOException if a IOError occurs.
+     */
+    public void copyWriter(final Reader in, final Writer out, 
+            final int buffersize)
+        throws IOException {
+        // create a 4kbyte buffer to read the file
+        final char[] bytes = new char[buffersize];
+
+        // the input stream does not supply accurate available() data
+        // the zip entry does not know the size of the data
+        int bytesRead = in.read(bytes);
+        while (bytesRead > -1) {
+            out.write(bytes, 0, bytesRead);
+            bytesRead = in.read(bytes);
+        }
+    }
+
+    /**
+     * Extracts the file name from the URL.
+     *
+     * @param url the url.
+     * @return the extracted filename.
+     */
+    public String getFileName(final URL url) {
+        final String file = getPath(url);
+        final int last = file.lastIndexOf("/");
+        if (last < 0) {
+            return file;
+        }
+        return file.substring(last + 1);
+    }
+
+    /**
+     * Removes the file extension from the given file name.
+     *
+     * @param file the file name.
+     * @return the file name without the file extension.
+     */
+    public String stripFileExtension(final String file) {
+        final int idx = file.lastIndexOf(".");
+        // handles unix hidden files and files without an extension.
+        if (idx < 1) {
+            return file;
+        }
+        return file.substring(0, idx);
+    }
+
+    /**
+     * Returns the file extension of the given file name.
+     * The returned value will contain the dot.
+     *
+     * @param file the file name.
+     * @return the file extension.
+     */
+    public String getFileExtension(final String file) {
+        final int idx = file.lastIndexOf(".");
+        // handles unix hidden files and files without an extension.
+        if (idx < 1) {
+            return "";
+        }
+        return file.substring(idx);
+    }
+
+    /**
+     * Checks, whether the child directory is a subdirectory of the base 
+     * directory.
+     *
+     * @param base the base directory.
+     * @param child the suspected child directory.
+     * @return true, if the child is a subdirectory of the base directory.
+     * @throws IOException if an IOError occured during the test.
+     */
+    public boolean isSubDirectory(File base, File child)
+        throws IOException {
+        base = base.getCanonicalFile();
+        child = child.getCanonicalFile();
+
+        File parentFile = child;
+        while (parentFile != null) {
+            if (base.equals(parentFile)) {
+                return true;
+            }
+            parentFile = parentFile.getParentFile();
+        }
+        return false;
+    }
+}

+ 662 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/io/SerialUtilities.java

@@ -0,0 +1,662 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * --------------------
+ * SerialUtilities.java
+ * --------------------
+ * (C) Copyright 2000-2005, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   Arik Levin;
+ *
+ * $Id: SerialUtilities.java,v 1.15 2011/10/11 12:45:02 matinh Exp $
+ *
+ * Changes
+ * -------
+ * 25-Mar-2003 : Version 1 (DG);
+ * 18-Sep-2003 : Added capability to serialize GradientPaint (DG);
+ * 26-Apr-2004 : Added read/writePoint2D() methods (DG);
+ * 22-Feb-2005 : Added support for Arc2D - see patch 1147035 by Arik Levin (DG);
+ * 29-Jul-2005 : Added support for AttributedString (DG);
+ * 10-Oct-2011 : Added support for AlphaComposite instances (MH);
+ *
+ */
+
+package org.jfree.io;
+
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.GradientPaint;
+import java.awt.Paint;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.geom.Arc2D;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Line2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.text.CharacterIterator;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A class containing useful utility methods relating to serialization.
+ *
+ * @author David Gilbert
+ */
+public class SerialUtilities {
+
+    /**
+     * Private constructor prevents object creation.
+     */
+    private SerialUtilities() {
+    }
+
+    /**
+     * Returns <code>true</code> if a class implements <code>Serializable</code>
+     * and <code>false</code> otherwise.
+     *
+     * @param c  the class.
+     *
+     * @return A boolean.
+     */
+    public static boolean isSerializable(final Class c) {
+        /**
+        final Class[] interfaces = c.getInterfaces();
+        for (int i = 0; i < interfaces.length; i++) {
+            if (interfaces[i].equals(Serializable.class)) {
+                return true;
+            }
+        }
+        Class cc = c.getSuperclass();
+        if (cc != null) {
+            return isSerializable(cc);
+        }
+         */
+        return (Serializable.class.isAssignableFrom(c));
+    }
+
+    /**
+     * Reads a <code>Paint</code> object that has been serialised by the
+     * {@link SerialUtilities#writePaint(Paint, ObjectOutputStream)} method.
+     *
+     * @param stream  the input stream (<code>null</code> not permitted).
+     *
+     * @return The paint object (possibly <code>null</code>).
+     *
+     * @throws IOException  if there is an I/O problem.
+     * @throws ClassNotFoundException  if there is a problem loading a class.
+     */
+    public static Paint readPaint(final ObjectInputStream stream)
+        throws IOException, ClassNotFoundException {
+
+        if (stream == null) {
+            throw new IllegalArgumentException("Null 'stream' argument.");
+        }
+        Paint result = null;
+        final boolean isNull = stream.readBoolean();
+        if (!isNull) {
+            final Class c = (Class) stream.readObject();
+            if (isSerializable(c)) {
+                result = (Paint) stream.readObject();
+            }
+            else if (c.equals(GradientPaint.class)) {
+                final float x1 = stream.readFloat();
+                final float y1 = stream.readFloat();
+                final Color c1 = (Color) stream.readObject();
+                final float x2 = stream.readFloat();
+                final float y2 = stream.readFloat();
+                final Color c2 = (Color) stream.readObject();
+                final boolean isCyclic = stream.readBoolean();
+                result = new GradientPaint(x1, y1, c1, x2, y2, c2, isCyclic);
+            }
+        }
+        return result;
+
+    }
+
+    /**
+     * Serialises a <code>Paint</code> object.
+     *
+     * @param paint  the paint object (<code>null</code> permitted).
+     * @param stream  the output stream (<code>null</code> not permitted).
+     *
+     * @throws IOException if there is an I/O error.
+     */
+    public static void writePaint(final Paint paint,
+                                  final ObjectOutputStream stream)
+        throws IOException {
+
+        if (stream == null) {
+            throw new IllegalArgumentException("Null 'stream' argument.");
+        }
+        if (paint != null) {
+            stream.writeBoolean(false);
+            stream.writeObject(paint.getClass());
+            if (paint instanceof Serializable) {
+                stream.writeObject(paint);
+            }
+            else if (paint instanceof GradientPaint) {
+                final GradientPaint gp = (GradientPaint) paint;
+                stream.writeFloat((float) gp.getPoint1().getX());
+                stream.writeFloat((float) gp.getPoint1().getY());
+                stream.writeObject(gp.getColor1());
+                stream.writeFloat((float) gp.getPoint2().getX());
+                stream.writeFloat((float) gp.getPoint2().getY());
+                stream.writeObject(gp.getColor2());
+                stream.writeBoolean(gp.isCyclic());
+            }
+        }
+        else {
+            stream.writeBoolean(true);
+        }
+
+    }
+
+    /**
+     * Reads a <code>Stroke</code> object that has been serialised by the
+     * {@link SerialUtilities#writeStroke(Stroke, ObjectOutputStream)} method.
+     *
+     * @param stream  the input stream (<code>null</code> not permitted).
+     *
+     * @return The stroke object (possibly <code>null</code>).
+     *
+     * @throws IOException  if there is an I/O problem.
+     * @throws ClassNotFoundException  if there is a problem loading a class.
+     */
+    public static Stroke readStroke(final ObjectInputStream stream)
+        throws IOException, ClassNotFoundException {
+
+        if (stream == null) {
+            throw new IllegalArgumentException("Null 'stream' argument.");
+        }
+        Stroke result = null;
+        final boolean isNull = stream.readBoolean();
+        if (!isNull) {
+            final Class c = (Class) stream.readObject();
+            if (c.equals(BasicStroke.class)) {
+                final float width = stream.readFloat();
+                final int cap = stream.readInt();
+                final int join = stream.readInt();
+                final float miterLimit = stream.readFloat();
+                final float[] dash = (float[]) stream.readObject();
+                final float dashPhase = stream.readFloat();
+                result = new BasicStroke(
+                    width, cap, join, miterLimit, dash, dashPhase
+                );
+            }
+            else {
+                result = (Stroke) stream.readObject();
+            }
+        }
+        return result;
+
+    }
+
+    /**
+     * Serialises a <code>Stroke</code> object.  This code handles the
+     * <code>BasicStroke</code> class which is the only <code>Stroke</code>
+     * implementation provided by the JDK (and isn't directly
+     * <code>Serializable</code>).
+     *
+     * @param stroke  the stroke object (<code>null</code> permitted).
+     * @param stream  the output stream (<code>null</code> not permitted).
+     *
+     * @throws IOException if there is an I/O error.
+     */
+    public static void writeStroke(final Stroke stroke,
+                                   final ObjectOutputStream stream)
+        throws IOException {
+
+        if (stream == null) {
+            throw new IllegalArgumentException("Null 'stream' argument.");
+        }
+        if (stroke != null) {
+            stream.writeBoolean(false);
+            if (stroke instanceof BasicStroke) {
+                final BasicStroke s = (BasicStroke) stroke;
+                stream.writeObject(BasicStroke.class);
+                stream.writeFloat(s.getLineWidth());
+                stream.writeInt(s.getEndCap());
+                stream.writeInt(s.getLineJoin());
+                stream.writeFloat(s.getMiterLimit());
+                stream.writeObject(s.getDashArray());
+                stream.writeFloat(s.getDashPhase());
+            }
+            else {
+                stream.writeObject(stroke.getClass());
+                stream.writeObject(stroke);
+            }
+        }
+        else {
+            stream.writeBoolean(true);
+        }
+    }
+
+    /**
+     * Reads a <code>Composite</code> object that has been serialised by the
+     * {@link SerialUtilities#writeComposite(Composite, ObjectOutputStream)}
+     * method.
+     *
+     * @param stream  the input stream (<code>null</code> not permitted).
+     *
+     * @return The composite object (possibly <code>null</code>).
+     *
+     * @throws IOException  if there is an I/O problem.
+     * @throws ClassNotFoundException  if there is a problem loading a class.
+     * 
+     * @since 1.0.17
+     */
+    public static Composite readComposite(final ObjectInputStream stream)
+        throws IOException, ClassNotFoundException {
+
+        if (stream == null) {
+            throw new IllegalArgumentException("Null 'stream' argument.");
+        }
+        Composite result = null;
+        final boolean isNull = stream.readBoolean();
+        if (!isNull) {
+            final Class c = (Class) stream.readObject();
+            if (isSerializable(c)) {
+                result = (Composite) stream.readObject();
+            }
+            else if (c.equals(AlphaComposite.class)) {
+                final int rule = stream.readInt();
+                final float alpha = stream.readFloat();
+                result = AlphaComposite.getInstance(rule, alpha);
+            }
+        }
+        return result;
+
+    }
+
+    /**
+     * Serialises a <code>Composite</code> object.
+     *
+     * @param composite  the composite object (<code>null</code> permitted).
+     * @param stream  the output stream (<code>null</code> not permitted).
+     *
+     * @throws IOException if there is an I/O error.
+     * 
+     * @since 1.0.17
+     */
+    public static void writeComposite(final Composite composite,
+                                      final ObjectOutputStream stream)
+        throws IOException {
+
+        if (stream == null) {
+            throw new IllegalArgumentException("Null 'stream' argument.");
+        }
+        if (composite != null) {
+            stream.writeBoolean(false);
+            stream.writeObject(composite.getClass());
+            if (composite instanceof Serializable) {
+                stream.writeObject(composite);
+            }
+            else if (composite instanceof AlphaComposite) {
+                final AlphaComposite ac = (AlphaComposite) composite;
+                stream.writeInt(ac.getRule());
+                stream.writeFloat(ac.getAlpha());
+            }
+        }
+        else {
+            stream.writeBoolean(true);
+        }
+    }
+
+    /**
+     * Reads a <code>Shape</code> object that has been serialised by the
+     * {@link #writeShape(Shape, ObjectOutputStream)} method.
+     *
+     * @param stream  the input stream (<code>null</code> not permitted).
+     *
+     * @return The shape object (possibly <code>null</code>).
+     *
+     * @throws IOException  if there is an I/O problem.
+     * @throws ClassNotFoundException  if there is a problem loading a class.
+     */
+    public static Shape readShape(final ObjectInputStream stream)
+        throws IOException, ClassNotFoundException {
+
+        if (stream == null) {
+            throw new IllegalArgumentException("Null 'stream' argument.");
+        }
+        Shape result = null;
+        final boolean isNull = stream.readBoolean();
+        if (!isNull) {
+            final Class c = (Class) stream.readObject();
+            if (c.equals(Line2D.class)) {
+                final double x1 = stream.readDouble();
+                final double y1 = stream.readDouble();
+                final double x2 = stream.readDouble();
+                final double y2 = stream.readDouble();
+                result = new Line2D.Double(x1, y1, x2, y2);
+            }
+            else if (c.equals(Rectangle2D.class)) {
+                final double x = stream.readDouble();
+                final double y = stream.readDouble();
+                final double w = stream.readDouble();
+                final double h = stream.readDouble();
+                result = new Rectangle2D.Double(x, y, w, h);
+            }
+            else if (c.equals(Ellipse2D.class)) {
+                final double x = stream.readDouble();
+                final double y = stream.readDouble();
+                final double w = stream.readDouble();
+                final double h = stream.readDouble();
+                result = new Ellipse2D.Double(x, y, w, h);
+            }
+            else if (c.equals(Arc2D.class)) {
+                final double x = stream.readDouble();
+                final double y = stream.readDouble();
+                final double w = stream.readDouble();
+                final double h = stream.readDouble();
+                final double as = stream.readDouble(); // Angle Start
+                final double ae = stream.readDouble(); // Angle Extent
+                final int at = stream.readInt();       // Arc type
+                result = new Arc2D.Double(x, y, w, h, as, ae, at);
+            }
+            else if (c.equals(GeneralPath.class)) {
+                final GeneralPath gp = new GeneralPath();
+                final float[] args = new float[6];
+                boolean hasNext = stream.readBoolean();
+                while (!hasNext) {
+                    final int type = stream.readInt();
+                    for (int i = 0; i < 6; i++) {
+                        args[i] = stream.readFloat();
+                    }
+                    switch (type) {
+                        case PathIterator.SEG_MOVETO :
+                            gp.moveTo(args[0], args[1]);
+                            break;
+                        case PathIterator.SEG_LINETO :
+                            gp.lineTo(args[0], args[1]);
+                            break;
+                        case PathIterator.SEG_CUBICTO :
+                            gp.curveTo(args[0], args[1], args[2],
+                                    args[3], args[4], args[5]);
+                            break;
+                        case PathIterator.SEG_QUADTO :
+                            gp.quadTo(args[0], args[1], args[2], args[3]);
+                            break;
+                        case PathIterator.SEG_CLOSE :
+                            gp.closePath();
+                            break;
+                        default :
+                            throw new RuntimeException(
+                                    "JFreeChart - No path exists");
+                    }
+                    gp.setWindingRule(stream.readInt());
+                    hasNext = stream.readBoolean();
+                }
+                result = gp;
+            }
+            else {
+                result = (Shape) stream.readObject();
+            }
+        }
+        return result;
+
+    }
+
+    /**
+     * Serialises a <code>Shape</code> object.
+     *
+     * @param shape  the shape object (<code>null</code> permitted).
+     * @param stream  the output stream (<code>null</code> not permitted).
+     *
+     * @throws IOException if there is an I/O error.
+     */
+    public static void writeShape(final Shape shape,
+                                  final ObjectOutputStream stream)
+        throws IOException {
+
+        if (stream == null) {
+            throw new IllegalArgumentException("Null 'stream' argument.");
+        }
+        if (shape != null) {
+            stream.writeBoolean(false);
+            if (shape instanceof Line2D) {
+                final Line2D line = (Line2D) shape;
+                stream.writeObject(Line2D.class);
+                stream.writeDouble(line.getX1());
+                stream.writeDouble(line.getY1());
+                stream.writeDouble(line.getX2());
+                stream.writeDouble(line.getY2());
+            }
+            else if (shape instanceof Rectangle2D) {
+                final Rectangle2D rectangle = (Rectangle2D) shape;
+                stream.writeObject(Rectangle2D.class);
+                stream.writeDouble(rectangle.getX());
+                stream.writeDouble(rectangle.getY());
+                stream.writeDouble(rectangle.getWidth());
+                stream.writeDouble(rectangle.getHeight());
+            }
+            else if (shape instanceof Ellipse2D) {
+                final Ellipse2D ellipse = (Ellipse2D) shape;
+                stream.writeObject(Ellipse2D.class);
+                stream.writeDouble(ellipse.getX());
+                stream.writeDouble(ellipse.getY());
+                stream.writeDouble(ellipse.getWidth());
+                stream.writeDouble(ellipse.getHeight());
+            }
+            else if (shape instanceof Arc2D) {
+                final Arc2D arc = (Arc2D) shape;
+                stream.writeObject(Arc2D.class);
+                stream.writeDouble(arc.getX());
+                stream.writeDouble(arc.getY());
+                stream.writeDouble(arc.getWidth());
+                stream.writeDouble(arc.getHeight());
+                stream.writeDouble(arc.getAngleStart());
+                stream.writeDouble(arc.getAngleExtent());
+                stream.writeInt(arc.getArcType());
+            }
+            else if (shape instanceof GeneralPath) {
+                stream.writeObject(GeneralPath.class);
+                final PathIterator pi = shape.getPathIterator(null);
+                final float[] args = new float[6];
+                stream.writeBoolean(pi.isDone());
+                while (!pi.isDone()) {
+                    final int type = pi.currentSegment(args);
+                    stream.writeInt(type);
+                    // TODO: could write this to only stream the values
+                    // required for the segment type
+                    for (int i = 0; i < 6; i++) {
+                        stream.writeFloat(args[i]);
+                    }
+                    stream.writeInt(pi.getWindingRule());
+                    pi.next();
+                    stream.writeBoolean(pi.isDone());
+                }
+            }
+            else {
+                stream.writeObject(shape.getClass());
+                stream.writeObject(shape);
+            }
+        }
+        else {
+            stream.writeBoolean(true);
+        }
+    }
+
+    /**
+     * Reads a <code>Point2D</code> object that has been serialised by the
+     * {@link #writePoint2D(Point2D, ObjectOutputStream)} method.
+     *
+     * @param stream  the input stream (<code>null</code> not permitted).
+     *
+     * @return The point object (possibly <code>null</code>).
+     *
+     * @throws IOException  if there is an I/O problem.
+     */
+    public static Point2D readPoint2D(final ObjectInputStream stream)
+        throws IOException {
+
+        if (stream == null) {
+            throw new IllegalArgumentException("Null 'stream' argument.");
+        }
+        Point2D result = null;
+        final boolean isNull = stream.readBoolean();
+        if (!isNull) {
+            final double x = stream.readDouble();
+            final double y = stream.readDouble();
+            result = new Point2D.Double(x, y);
+        }
+        return result;
+
+    }
+
+    /**
+     * Serialises a <code>Point2D</code> object.
+     *
+     * @param p  the point object (<code>null</code> permitted).
+     * @param stream  the output stream (<code>null</code> not permitted).
+     *
+     * @throws IOException if there is an I/O error.
+     */
+    public static void writePoint2D(final Point2D p,
+                                    final ObjectOutputStream stream)
+        throws IOException {
+
+        if (stream == null) {
+            throw new IllegalArgumentException("Null 'stream' argument.");
+        }
+        if (p != null) {
+            stream.writeBoolean(false);
+            stream.writeDouble(p.getX());
+            stream.writeDouble(p.getY());
+        }
+        else {
+            stream.writeBoolean(true);
+        }
+    }
+
+    /**
+     * Reads a <code>AttributedString</code> object that has been serialised by
+     * the {@link SerialUtilities#writeAttributedString(AttributedString,
+     * ObjectOutputStream)} method.
+     *
+     * @param stream  the input stream (<code>null</code> not permitted).
+     *
+     * @return The attributed string object (possibly <code>null</code>).
+     *
+     * @throws IOException  if there is an I/O problem.
+     * @throws ClassNotFoundException  if there is a problem loading a class.
+     */
+    public static AttributedString readAttributedString(
+            ObjectInputStream stream)
+            throws IOException, ClassNotFoundException {
+
+        if (stream == null) {
+            throw new IllegalArgumentException("Null 'stream' argument.");
+        }
+        AttributedString result = null;
+        final boolean isNull = stream.readBoolean();
+        if (!isNull) {
+            // read string and attributes then create result
+            String plainStr = (String) stream.readObject();
+            result = new AttributedString(plainStr);
+            char c = stream.readChar();
+            int start = 0;
+            while (c != CharacterIterator.DONE) {
+                int limit = stream.readInt();
+                Map atts = (Map) stream.readObject();
+                result.addAttributes(atts, start, limit);
+                start = limit;
+                c = stream.readChar();
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Serialises an <code>AttributedString</code> object.
+     *
+     * @param as  the attributed string object (<code>null</code> permitted).
+     * @param stream  the output stream (<code>null</code> not permitted).
+     *
+     * @throws IOException if there is an I/O error.
+     */
+    public static void writeAttributedString(AttributedString as,
+            ObjectOutputStream stream) throws IOException {
+
+        if (stream == null) {
+            throw new IllegalArgumentException("Null 'stream' argument.");
+        }
+        if (as != null) {
+            stream.writeBoolean(false);
+            AttributedCharacterIterator aci = as.getIterator();
+            // build a plain string from aci
+            // then write the string
+            StringBuffer plainStr = new StringBuffer();
+            char current = aci.first();
+            while (current != CharacterIterator.DONE) {
+                plainStr = plainStr.append(current);
+                current = aci.next();
+            }
+            stream.writeObject(plainStr.toString());
+
+            // then write the attributes and limits for each run
+            current = aci.first();
+            int begin = aci.getBeginIndex();
+            while (current != CharacterIterator.DONE) {
+                // write the current character - when the reader sees that this
+                // is not CharacterIterator.DONE, it will know to read the
+                // run limits and attributes
+                stream.writeChar(current);
+
+                // now write the limit, adjusted as if beginIndex is zero
+                int limit = aci.getRunLimit();
+                stream.writeInt(limit - begin);
+
+                // now write the attribute set
+                Map atts = new HashMap(aci.getAttributes());
+                stream.writeObject(atts);
+                current = aci.setIndex(limit);
+            }
+            // write a character that signals to the reader that all runs
+            // are done...
+            stream.writeChar(CharacterIterator.DONE);
+        }
+        else {
+            // write a flag that indicates a null
+            stream.writeBoolean(true);
+        }
+
+    }
+
+}
+

+ 6 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/io/package.html

@@ -0,0 +1,6 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+Input/output related classes.
+</body>
+</html>

+ 188 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/layout/CenterLayout.java

@@ -0,0 +1,188 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -----------------
+ * CenterLayout.java
+ * -----------------
+ * (C) Copyright 2000-2005, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: CenterLayout.java,v 1.6 2005/11/16 15:58:40 taqua Exp $
+ *
+ * Changes (from 5-Nov-2001)
+ * -------------------------
+ * 05-Nov-2001 : Changed package to com.jrefinery.layout.* (DG);
+ * 10-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ *
+ */
+
+package org.jfree.layout;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.io.Serializable;
+
+/**
+ * A layout manager that displays a single component in the center of its 
+ * container.
+ *
+ * @author David Gilbert
+ */
+public class CenterLayout implements LayoutManager, Serializable {
+
+    /** For serialization. */
+    private static final long serialVersionUID = 469319532333015042L;
+    
+    /**
+     * Creates a new layout manager.
+     */
+    public CenterLayout() {
+    }
+
+    /**
+     * Returns the preferred size.
+     *
+     * @param parent  the parent.
+     *
+     * @return the preferred size.
+     */
+    public Dimension preferredLayoutSize(final Container parent) {
+
+        synchronized (parent.getTreeLock()) {
+            final Insets insets = parent.getInsets();
+            if (parent.getComponentCount() > 0) {
+                final Component component = parent.getComponent(0);
+                final Dimension d = component.getPreferredSize();
+                return new Dimension(
+                    (int) d.getWidth() + insets.left + insets.right,
+                    (int) d.getHeight() + insets.top + insets.bottom
+                );
+            }
+            else {
+                return new Dimension(
+                    insets.left + insets.right, insets.top + insets.bottom
+                );
+            }
+        }
+
+    }
+
+    /**
+     * Returns the minimum size.
+     *
+     * @param parent  the parent.
+     *
+     * @return the minimum size.
+     */
+    public Dimension minimumLayoutSize(final Container parent) {
+
+        synchronized (parent.getTreeLock()) {
+            final Insets insets = parent.getInsets();
+            if (parent.getComponentCount() > 0) {
+                final Component component = parent.getComponent(0);
+                final Dimension d = component.getMinimumSize();
+                return new Dimension(d.width + insets.left + insets.right,
+                                 d.height + insets.top + insets.bottom);
+            }
+            else {
+              return new Dimension(insets.left + insets.right,
+                                   insets.top + insets.bottom);
+            }
+        }
+
+    }
+
+    /**
+     * Lays out the components.
+     *
+     * @param parent  the parent.
+     */
+    public void layoutContainer(final Container parent) {
+
+        synchronized (parent.getTreeLock()) {
+            if (parent.getComponentCount() > 0) {
+                final Insets insets = parent.getInsets();
+                final Dimension parentSize = parent.getSize();
+                final Component component = parent.getComponent(0);
+                final Dimension componentSize = component.getPreferredSize();
+                final int xx = insets.left + (
+                    Math.max((parentSize.width - insets.left - insets.right
+                                      - componentSize.width) / 2, 0)
+                );
+                final int yy = insets.top + (
+                    Math.max((parentSize.height - insets.top - insets.bottom
+                                      - componentSize.height) / 2, 0));
+                component.setBounds(xx, yy, componentSize.width, 
+                        componentSize.height);
+            }
+        }
+
+    }
+
+    /**
+     * Not used.
+     *
+     * @param comp  the component.
+     */
+    public void addLayoutComponent(final Component comp) {
+        // not used.
+    }
+
+    /**
+     * Not used.
+     *
+     * @param comp  the component.
+     */
+    public void removeLayoutComponent(final Component comp) {
+        // not used
+    }
+
+    /**
+     * Not used.
+     *
+     * @param name  the component name.
+     * @param comp  the component.
+     */
+    public void addLayoutComponent(final String name, final Component comp) {
+        // not used
+    }
+
+    /**
+     * Not used.
+     *
+     * @param name  the component name.
+     * @param comp  the component.
+     */
+    public void removeLayoutComponent(final String name, final Component comp) {
+        // not used
+    }
+
+}

+ 1045 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/layout/FormatLayout.java

@@ -0,0 +1,1045 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -----------------
+ * FormatLayout.java
+ * -----------------
+ * (C) Copyright 2000-2005, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: FormatLayout.java,v 1.4 2005/10/18 13:16:50 mungady Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 26-Oct-2001 : Changed package to com.jrefinery.layout.* (DG);
+ * 26-Jun-2002 : Removed redundant code (DG);
+ * 10-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ *
+ */
+
+package org.jfree.layout;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.io.Serializable;
+
+/**
+ * A layout manager that spaces components over six columns in seven different 
+ * formats.
+ *
+ * @author David Gilbert
+ */
+public class FormatLayout implements LayoutManager, Serializable {
+
+    /** For serialization. */
+    private static final long serialVersionUID = 2866692886323930722L;
+    
+    /** A useful constant representing layout format 1. */
+    public static final int C = 1;
+
+    /** A useful constant representing layout format 2. */
+    public static final int LC = 2;
+
+    /** A useful constant representing layout format 3. */
+    public static final int LCB = 3;
+
+    /** A useful constant representing layout format 4. */
+    public static final int LCLC = 4;
+
+    /** A useful constant representing layout format 5. */
+    public static final int LCLCB = 5;
+
+    /** A useful constant representing layout format 6. */
+    public static final int LCBLC = 6;
+
+    /** A useful constant representing layout format 7. */
+    public static final int LCBLCB = 7;
+
+    /** The layout format for each row. */
+    private int[] rowFormats;
+
+    /** The gap between the rows. */
+    private int rowGap;
+
+    /** 
+     * The gaps between the columns (gap[0] is the gap following column zero). 
+     */
+    private int[] columnGaps;
+
+    /** Working array for recording the height of each row. */
+    private int[] rowHeights;
+
+    /** The total height of the layout. */
+    private int totalHeight;
+
+    /** Working array for recording the width of each column. */
+    private int[] columnWidths;
+
+    /** The total width of the layout. */
+    private int totalWidth;
+
+    /** Combined width of columns 1 and 2. */
+    private int columns1and2Width;
+
+    /** Combined width of columns 4 and 5. */
+    private int columns4and5Width;
+
+    /** Combined width of columns 1 to 4. */
+    private int columns1to4Width;
+
+    /** Combined width of columns 1 to 5. */
+    private int columns1to5Width;
+
+    /** Combined width of columns 0 to 5. */
+    private int columns0to5Width;
+
+    /**
+     * Constructs a new layout manager that can be used to create input forms.  
+     * The layout manager works by arranging components in rows using six 
+     * columns (some components will use more than one column).
+     * <P>
+     * Any component can be added, but I think of them in terms of Labels,
+     * Components, and Buttons.
+     * The formats available are:  C, LC, LCB, LCLC, LCLCB, LCBLC or LCBLCB.
+     * <table summary="layout options" >
+     * <tr>
+     * <td>C</td>
+     * <td>1 component in this row (spread across all six columns).</td>
+     * </tr>
+     * <tr>
+     * <td>LC</td>
+     * <td>2 components, a label in the 1st column, and a component using the
+     *      remaining 5 columns).</td>
+     * </tr>
+     * <tr>
+     * <td>LCB</td>
+     * <td>3 components, a label in the 1st column, a component spread across
+     *      the next 4, and a button in the last column.</td>
+     * </tr>
+     * <tr>
+     * <td>LCLC</td>
+     * <td>4 components, a label in column 1, a component in 2-3, a label in
+     *       4 and a component in 5-6.</td>
+     * </tr>
+     * <tr>
+     * <td>LCLCB</td>
+     * <td>5 components, a label in column 1, a component in 2-3, a label
+     *      in 4, a component in 5 and a button in 6.</td>
+     * </tr>
+     * <tr>
+     * <td>LCBLC</td>
+     * <td>5 components, a label in column 1, a component in 2, a button in 3,
+     *  a label in 4, a component in 5-6.</td>
+     * </tr>
+     * <tr>
+     * <td>LCBLCB</td>
+     * <td>6 components, one in each column.</td>
+     * </tr>
+     * </table>
+     * <P>
+     * Columns 1 and 4 expand to accommodate the widest label, and 3 and 6 to
+     * accommodate the widest button.
+     * <P>
+     * Each row will contain the number of components indicated by the format.  
+     * Be sure to specify enough row formats to cover all the components you 
+     * add to the layout.
+     *
+     * @param rowCount  the number of rows.
+     * @param rowFormats  the row formats.
+     */
+    public FormatLayout(final int rowCount, final int[] rowFormats) {
+
+        this.rowFormats = rowFormats;
+        this.rowGap = 2;
+        this.columnGaps = new int[5];
+        this.columnGaps[0] = 10;
+        this.columnGaps[1] = 5;
+        this.columnGaps[2] = 5;
+        this.columnGaps[3] = 10;
+        this.columnGaps[4] = 5;
+
+        // working structures...
+        this.rowHeights = new int[rowCount];
+        this.columnWidths = new int[6];
+    }
+
+    /**
+     * Returns the preferred size of the component using this layout manager.
+     *
+     * @param parent  the parent.
+     *
+     * @return the preferred size of the component.
+     */
+    public Dimension preferredLayoutSize(final Container parent) {
+
+        Component c0, c1, c2, c3, c4, c5;
+
+        synchronized (parent.getTreeLock()) {
+            final Insets insets = parent.getInsets();
+            int componentIndex = 0;
+            final int rowCount = this.rowHeights.length;
+            for (int i = 0; i < this.columnWidths.length; i++) {
+                this.columnWidths[i] = 0;
+            }
+            this.columns1and2Width = 0;
+            this.columns4and5Width = 0;
+            this.columns1to4Width = 0;
+            this.columns1to5Width = 0;
+            this.columns0to5Width = 0;
+
+            this.totalHeight = 0;
+            for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
+            final int format 
+                = this.rowFormats[rowIndex % this.rowFormats.length];
+                switch (format) {
+                    case FormatLayout.C:
+                        c0 = parent.getComponent(componentIndex);
+                        updateC(rowIndex, c0.getPreferredSize());
+                        componentIndex = componentIndex + 1;
+                        break;
+                    case FormatLayout.LC:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        updateLC(rowIndex, c0.getPreferredSize(), 
+                                c1.getPreferredSize());
+                        componentIndex = componentIndex + 2;
+                        break;
+                    case FormatLayout.LCB:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        updateLCB(rowIndex,
+                                  c0.getPreferredSize(),
+                                  c1.getPreferredSize(),
+                                  c2.getPreferredSize());
+                        componentIndex = componentIndex + 3;
+                        break;
+                    case FormatLayout.LCLC:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        c3 = parent.getComponent(componentIndex + 3);
+                        updateLCLC(rowIndex,
+                                   c0.getPreferredSize(),
+                                   c1.getPreferredSize(),
+                                   c2.getPreferredSize(),
+                                   c3.getPreferredSize());
+                        componentIndex = componentIndex + 4;
+                        break;
+                    case FormatLayout.LCBLC:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        c3 = parent.getComponent(componentIndex + 3);
+                        c4 = parent.getComponent(componentIndex + 4);
+                        updateLCBLC(rowIndex,
+                                    c0.getPreferredSize(),
+                                    c1.getPreferredSize(),
+                                    c2.getPreferredSize(),
+                                    c3.getPreferredSize(),
+                                    c4.getPreferredSize());
+                        componentIndex = componentIndex + 5;
+                        break;
+                    case FormatLayout.LCLCB:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        c3 = parent.getComponent(componentIndex + 3);
+                        c4 = parent.getComponent(componentIndex + 4);
+                        updateLCLCB(rowIndex,
+                                    c0.getPreferredSize(),
+                                    c1.getPreferredSize(),
+                                    c2.getPreferredSize(),
+                                    c3.getPreferredSize(),
+                                    c4.getPreferredSize());
+                        componentIndex = componentIndex + 5;
+                        break;
+                    case FormatLayout.LCBLCB:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        c3 = parent.getComponent(componentIndex + 3);
+                        c4 = parent.getComponent(componentIndex + 4);
+                        c5 = parent.getComponent(componentIndex + 5);
+                        updateLCBLCB(rowIndex,
+                                     c0.getPreferredSize(),
+                                     c1.getPreferredSize(),
+                                     c2.getPreferredSize(),
+                                     c3.getPreferredSize(),
+                                     c4.getPreferredSize(),
+                                     c5.getPreferredSize());
+                        componentIndex = componentIndex + 6;
+                        break;
+                }
+            }
+            complete();
+            return new Dimension(this.totalWidth + insets.left + insets.right,
+                    this.totalHeight + (rowCount - 1) * this.rowGap
+                                 + insets.top + insets.bottom);
+        }
+    }
+
+    /**
+     * Returns the minimum size of the component using this layout manager.
+     *
+     * @param parent  the parent.
+     *
+     * @return the minimum size of the component
+     */
+    public Dimension minimumLayoutSize(final Container parent) {
+
+        Component c0, c1, c2, c3, c4, c5;
+
+        synchronized (parent.getTreeLock()) {
+            final Insets insets = parent.getInsets();
+            int componentIndex = 0;
+            final int rowCount = this.rowHeights.length;
+            for (int i = 0; i < this.columnWidths.length; i++) {
+                this.columnWidths[i] = 0;
+            }
+            this.columns1and2Width = 0;
+            this.columns4and5Width = 0;
+            this.columns1to4Width = 0;
+            this.columns1to5Width = 0;
+            this.columns0to5Width = 0;
+            final int totalHeight = 0;
+            for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
+
+                final int format 
+                    = this.rowFormats[rowIndex % this.rowFormats.length];
+
+                switch (format) {
+                    case FormatLayout.C:
+                        c0 = parent.getComponent(componentIndex);
+                        this.columns0to5Width = Math.max(
+                            this.columns0to5Width, c0.getMinimumSize().width
+                        );
+                        componentIndex = componentIndex + 1;
+                        break;
+                    case FormatLayout.LC:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        updateLC(rowIndex,
+                                 c0.getMinimumSize(),
+                                 c1.getMinimumSize());
+                        componentIndex = componentIndex + 2;
+                        break;
+                    case FormatLayout.LCB:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        updateLCB(rowIndex,
+                                  c0.getMinimumSize(),
+                                  c1.getMinimumSize(),
+                                  c2.getMinimumSize());
+                        componentIndex = componentIndex + 3;
+                        break;
+                    case FormatLayout.LCLC:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        c3 = parent.getComponent(componentIndex + 3);
+                        updateLCLC(rowIndex,
+                                   c0.getMinimumSize(),
+                                   c1.getMinimumSize(),
+                                   c2.getMinimumSize(),
+                                   c3.getMinimumSize());
+                        componentIndex = componentIndex + 3;
+                        break;
+                    case FormatLayout.LCBLC:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        c3 = parent.getComponent(componentIndex + 3);
+                        c4 = parent.getComponent(componentIndex + 4);
+                        updateLCBLC(rowIndex,
+                                    c0.getMinimumSize(),
+                                    c1.getMinimumSize(),
+                                    c2.getMinimumSize(),
+                                    c3.getMinimumSize(),
+                                    c4.getMinimumSize());
+                        componentIndex = componentIndex + 4;
+                        break;
+                    case FormatLayout.LCLCB:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        c3 = parent.getComponent(componentIndex + 3);
+                        c4 = parent.getComponent(componentIndex + 4);
+                        updateLCLCB(rowIndex,
+                                    c0.getMinimumSize(),
+                                    c1.getMinimumSize(),
+                                    c2.getMinimumSize(),
+                                    c3.getMinimumSize(),
+                                    c4.getMinimumSize());
+                        componentIndex = componentIndex + 4;
+                        break;
+                    case FormatLayout.LCBLCB:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        c3 = parent.getComponent(componentIndex + 3);
+                        c4 = parent.getComponent(componentIndex + 4);
+                        c5 = parent.getComponent(componentIndex + 5);
+                        updateLCBLCB(rowIndex,
+                                     c0.getMinimumSize(),
+                                     c1.getMinimumSize(),
+                                     c2.getMinimumSize(),
+                                     c3.getMinimumSize(),
+                                     c4.getMinimumSize(),
+                                     c5.getMinimumSize());
+                        componentIndex = componentIndex + 5;
+                        break;
+                }
+            }
+            complete();
+            return new Dimension(this.totalWidth + insets.left + insets.right,
+                                 totalHeight + (rowCount - 1) * this.rowGap
+                                 + insets.top + insets.bottom);
+        }
+    }
+
+    /**
+     * Performs the layout of the container.
+     *
+     * @param parent  the parent.
+     */
+    public void layoutContainer(final Container parent) {
+        Component c0, c1, c2, c3, c4, c5;
+
+        synchronized (parent.getTreeLock()) {
+            final Insets insets = parent.getInsets();
+            int componentIndex = 0;
+            final int rowCount = this.rowHeights.length;
+            for (int i = 0; i < this.columnWidths.length; i++) {
+                this.columnWidths[i] = 0;
+            }
+            this.columns1and2Width = 0;
+            this.columns4and5Width = 0;
+            this.columns1to4Width = 0;
+            this.columns1to5Width = 0;
+            this.columns0to5Width 
+                = parent.getBounds().width - insets.left - insets.right;
+
+            this.totalHeight = 0;
+            for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
+                final int format 
+                    = this.rowFormats[rowIndex % this.rowFormats.length];
+                switch (format) {
+                    case FormatLayout.C:
+                        c0 = parent.getComponent(componentIndex);
+                        updateC(rowIndex, c0.getPreferredSize());
+                        componentIndex = componentIndex + 1;
+                        break;
+                    case FormatLayout.LC:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        updateLC(rowIndex, c0.getPreferredSize(), 
+                                c1.getPreferredSize());
+                        componentIndex = componentIndex + 2;
+                        break;
+                    case FormatLayout.LCB:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        updateLCB(rowIndex,
+                                  c0.getPreferredSize(),
+                                  c1.getPreferredSize(),
+                                  c2.getPreferredSize());
+                        componentIndex = componentIndex + 3;
+                        break;
+                    case FormatLayout.LCLC:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        c3 = parent.getComponent(componentIndex + 3);
+                        updateLCLC(rowIndex,
+                                   c0.getPreferredSize(),
+                                   c1.getPreferredSize(),
+                                   c2.getPreferredSize(),
+                                   c3.getPreferredSize());
+                        componentIndex = componentIndex + 4;
+                        break;
+                    case FormatLayout.LCBLC:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        c3 = parent.getComponent(componentIndex + 3);
+                        c4 = parent.getComponent(componentIndex + 4);
+                        updateLCBLC(rowIndex,
+                                    c0.getPreferredSize(),
+                                    c1.getPreferredSize(),
+                                    c2.getPreferredSize(),
+                                    c3.getPreferredSize(),
+                                    c4.getPreferredSize());
+                        componentIndex = componentIndex + 5;
+                        break;
+                    case FormatLayout.LCLCB:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        c3 = parent.getComponent(componentIndex + 3);
+                        c4 = parent.getComponent(componentIndex + 4);
+                        updateLCLCB(rowIndex,
+                                    c0.getPreferredSize(),
+                                    c1.getPreferredSize(),
+                                    c2.getPreferredSize(),
+                                    c3.getPreferredSize(),
+                                    c4.getPreferredSize());
+                        componentIndex = componentIndex + 5;
+                        break;
+                    case FormatLayout.LCBLCB:
+                        c0 = parent.getComponent(componentIndex);
+                        c1 = parent.getComponent(componentIndex + 1);
+                        c2 = parent.getComponent(componentIndex + 2);
+                        c3 = parent.getComponent(componentIndex + 3);
+                        c4 = parent.getComponent(componentIndex + 4);
+                        c5 = parent.getComponent(componentIndex + 5);
+                        updateLCBLCB(rowIndex,
+                                     c0.getPreferredSize(),
+                                     c1.getPreferredSize(),
+                                     c2.getPreferredSize(),
+                                     c3.getPreferredSize(),
+                                     c4.getPreferredSize(),
+                                     c5.getPreferredSize());
+                        componentIndex = componentIndex + 6;
+                        break;
+                }
+            }
+            complete();
+
+            componentIndex = 0;
+            int rowY = insets.top;
+            final int[] rowX = new int[6];
+            rowX[0] = insets.left;
+            rowX[1] = rowX[0] + this.columnWidths[0] + this.columnGaps[0];
+            rowX[2] = rowX[1] + this.columnWidths[1] + this.columnGaps[1];
+            rowX[3] = rowX[2] + this.columnWidths[2] + this.columnGaps[2];
+            rowX[4] = rowX[3] + this.columnWidths[3] + this.columnGaps[3];
+            rowX[5] = rowX[4] + this.columnWidths[4] + this.columnGaps[4];
+            final int w1to2 = this.columnWidths[1] + this.columnGaps[1] 
+                              + this.columnWidths[2];
+            final int w4to5 = this.columnWidths[4] + this.columnGaps[4] 
+                              + this.columnWidths[5];
+            final int w1to4 = w1to2 + this.columnGaps[2] + this.columnWidths[3]
+                        + this.columnGaps[3] + this.columnWidths[4];
+            final int w1to5 = w1to4 + this.columnGaps[4] + this.columnWidths[5];
+            final int w0to5 = w1to5 + this.columnWidths[0] + this.columnGaps[0];
+            for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
+                final int format 
+                    = this.rowFormats[rowIndex % this.rowFormats.length];
+
+                switch (format) {
+                case FormatLayout.C:
+                    c0 = parent.getComponent(componentIndex);
+                    c0.setBounds(rowX[0], rowY, w0to5, 
+                            c0.getPreferredSize().height);
+                    componentIndex = componentIndex + 1;
+                    break;
+                case FormatLayout.LC:
+                    c0 = parent.getComponent(componentIndex);
+                    c0.setBounds(
+                        rowX[0],
+                        rowY + (this.rowHeights[rowIndex] 
+                                     - c0.getPreferredSize().height) / 2,
+                        this.columnWidths[0], c0.getPreferredSize().height
+                    );
+                    c1 = parent.getComponent(componentIndex + 1);
+                    c1.setBounds(
+                        rowX[1],
+                        rowY + (this.rowHeights[rowIndex] 
+                                     - c1.getPreferredSize().height) / 2,
+                        w1to5, c1.getPreferredSize().height
+                    );
+                    componentIndex = componentIndex + 2;
+                    break;
+                case FormatLayout.LCB:
+                    c0 = parent.getComponent(componentIndex);
+                    c0.setBounds(
+                        rowX[0],
+                        rowY + (this.rowHeights[rowIndex] 
+                                     - c0.getPreferredSize().height) / 2,
+                        this.columnWidths[0], c0.getPreferredSize().height
+                    );
+                    c1 = parent.getComponent(componentIndex + 1);
+                    c1.setBounds(
+                        rowX[1],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c1.getPreferredSize().height) / 2,
+                        w1to4, c1.getPreferredSize().height
+                    );
+                    c2 = parent.getComponent(componentIndex + 2);
+                    c2.setBounds(
+                        rowX[5],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c2.getPreferredSize().height) / 2,
+                        this.columnWidths[5], c2.getPreferredSize().height
+                    );
+                    componentIndex = componentIndex + 3;
+                    break;
+                case FormatLayout.LCLC:
+                    c0 = parent.getComponent(componentIndex);
+                    c0.setBounds(
+                        rowX[0],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c0.getPreferredSize().height) / 2,
+                        this.columnWidths[0], c0.getPreferredSize().height
+                    );
+                    c1 = parent.getComponent(componentIndex + 1);
+                    c1.setBounds(
+                        rowX[1],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c1.getPreferredSize().height) / 2,
+                        w1to2, c1.getPreferredSize().height
+                    );
+                    c2 = parent.getComponent(componentIndex + 2);
+                    c2.setBounds(
+                        rowX[3],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c2.getPreferredSize().height) / 2,
+                        this.columnWidths[3], c2.getPreferredSize().height
+                    );
+                    c3 = parent.getComponent(componentIndex + 3);
+                    c3.setBounds(
+                        rowX[4],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c3.getPreferredSize().height) / 2,
+                        w4to5, c3.getPreferredSize().height
+                    );
+                    componentIndex = componentIndex + 4;
+                    break;
+                case FormatLayout.LCBLC:
+                    c0 = parent.getComponent(componentIndex);
+                    c0.setBounds(
+                        rowX[0],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c0.getPreferredSize().height) / 2,
+                        this.columnWidths[0], c0.getPreferredSize().height
+                    );
+                    c1 = parent.getComponent(componentIndex + 1);
+                    c1.setBounds(
+                        rowX[1],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c1.getPreferredSize().height) / 2,
+                        this.columnWidths[1], c1.getPreferredSize().height
+                    );
+                    c2 = parent.getComponent(componentIndex + 2);
+                    c2.setBounds(
+                        rowX[2],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c2.getPreferredSize().height) / 2,
+                        this.columnWidths[2], c2.getPreferredSize().height
+                    );
+                    c3 = parent.getComponent(componentIndex + 3);
+                    c3.setBounds(
+                        rowX[3],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c3.getPreferredSize().height) / 2,
+                        this.columnWidths[3], c3.getPreferredSize().height
+                    );
+                    c4 = parent.getComponent(componentIndex + 4);
+                    c4.setBounds(
+                        rowX[4],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c4.getPreferredSize().height) / 2,
+                        w4to5, c4.getPreferredSize().height
+                    );
+                    componentIndex = componentIndex + 5;
+                    break;
+                case FormatLayout.LCLCB:
+                    c0 = parent.getComponent(componentIndex);
+                    c0.setBounds(
+                        rowX[0],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c0.getPreferredSize().height) / 2,
+                        this.columnWidths[0], c0.getPreferredSize().height
+                    );
+                    c1 = parent.getComponent(componentIndex + 1);
+                    c1.setBounds(
+                        rowX[1],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c1.getPreferredSize().height) / 2,
+                        w1to2, c1.getPreferredSize().height
+                    );
+                    c2 = parent.getComponent(componentIndex + 2);
+                    c2.setBounds(
+                        rowX[3],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c2.getPreferredSize().height) / 2,
+                        this.columnWidths[3], c2.getPreferredSize().height
+                    );
+                    c3 = parent.getComponent(componentIndex + 3);
+                    c3.setBounds(
+                        rowX[4],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c3.getPreferredSize().height) / 2,
+                        this.columnWidths[4], c3.getPreferredSize().height
+                    );
+                    c4 = parent.getComponent(componentIndex + 4);
+                    c4.setBounds(
+                        rowX[5],
+                        rowY + (this.rowHeights[rowIndex] 
+                                    - c4.getPreferredSize().height) / 2,
+                        this.columnWidths[5], c4.getPreferredSize().height
+                    );
+                    componentIndex = componentIndex + 5;
+                    break;
+                case FormatLayout.LCBLCB:
+                    c0 = parent.getComponent(componentIndex);
+                    c0.setBounds(
+                        rowX[0],
+                        rowY + (this.rowHeights[rowIndex] 
+                                     - c0.getPreferredSize().height) / 2,
+                        this.columnWidths[0], c0.getPreferredSize().height
+                    );
+                    c1 = parent.getComponent(componentIndex + 1);
+                    c1.setBounds(
+                        rowX[1],
+                        rowY + (this.rowHeights[rowIndex] 
+                                     - c1.getPreferredSize().height) / 2,
+                        this.columnWidths[1], c1.getPreferredSize().height
+                    );
+                    c2 = parent.getComponent(componentIndex + 2);
+                    c2.setBounds(
+                        rowX[2],
+                        rowY + (this.rowHeights[rowIndex] 
+                                     - c2.getPreferredSize().height) / 2,
+                        this.columnWidths[2], c2.getPreferredSize().height
+                    );
+                    c3 = parent.getComponent(componentIndex + 3);
+                    c3.setBounds(
+                        rowX[3],
+                        rowY + (this.rowHeights[rowIndex] 
+                                     - c3.getPreferredSize().height) / 2,
+                        this.columnWidths[3], c3.getPreferredSize().height
+                    );
+                    c4 = parent.getComponent(componentIndex + 4);
+                    c4.setBounds(
+                        rowX[4],
+                        rowY + (this.rowHeights[rowIndex] 
+                                     - c4.getPreferredSize().height) / 2,
+                        this.columnWidths[4], c4.getPreferredSize().height
+                    );
+                    c5 = parent.getComponent(componentIndex + 5);
+                    c5.setBounds(
+                        rowX[5],
+                        rowY + (this.rowHeights[rowIndex] 
+                                     - c5.getPreferredSize().height) / 2,
+                        this.columnWidths[5], c5.getPreferredSize().height
+                    );
+                    componentIndex = componentIndex + 6;
+                    break;
+                    }
+                rowY = rowY + this.rowHeights[rowIndex] + this.rowGap;
+            }
+        }
+    }
+
+    /**
+     * Processes a row in 'C' format.
+     *
+     * @param rowIndex  the row index.
+     * @param d0  dimension 0.
+     */
+    protected void updateC(final int rowIndex, final Dimension d0) {
+        this.rowHeights[rowIndex] = d0.height;
+        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
+        this.columns0to5Width = Math.max(this.columns0to5Width, d0.width);
+    }
+
+    /**
+     * Processes a row in 'LC' format.
+     *
+     * @param rowIndex  the row index.
+     * @param d0  dimension 0.
+     * @param d1  dimension 1.
+     */
+    protected void updateLC(final int rowIndex, final Dimension d0, 
+                            final Dimension d1) {
+
+        this.rowHeights[rowIndex] = Math.max(d0.height, d1.height);
+        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
+        this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
+        this.columns1to5Width = Math.max(this.columns1to5Width, d1.width);
+
+    }
+
+    /**
+     * Processes a row in 'LCB' format.
+     *
+     * @param rowIndex  the row index.
+     * @param d0  dimension 0.
+     * @param d1  dimension 1.
+     * @param d2  dimension 2.
+     */
+    protected void updateLCB(final int rowIndex,
+                             final Dimension d0, final Dimension d1, 
+                             final Dimension d2) {
+
+        this.rowHeights[rowIndex] 
+               = Math.max(d0.height, Math.max(d1.height, d2.height));
+        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
+        this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
+        this.columns1to4Width = Math.max(this.columns1to4Width, d1.width);
+        this.columnWidths[5] = Math.max(this.columnWidths[5], d2.width);
+
+    }
+
+    /**
+     * Processes a row in 'LCLC' format.
+     *
+     * @param rowIndex  the row index.
+     * @param d0  dimension 0.
+     * @param d1  dimension 1.
+     * @param d2  dimension 2.
+     * @param d3  dimension 3.
+     */
+    protected void updateLCLC(final int rowIndex, final Dimension d0, 
+                              final Dimension d1, final Dimension d2, 
+                              final Dimension d3) {
+
+        this.rowHeights[rowIndex] = Math.max(Math.max(d0.height, d1.height),
+                                        Math.max(d2.height, d3.height));
+        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
+        this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
+        this.columns1and2Width = Math.max(this.columns1and2Width, d1.width);
+        this.columnWidths[3] = Math.max(this.columnWidths[3], d2.width);
+        this.columns4and5Width = Math.max(this.columns4and5Width, d3.width);
+    }
+
+    /**
+     * Processes a row in 'LCBLC' format.
+     *
+     * @param rowIndex  the row index.
+     * @param d0  dimension 0.
+     * @param d1  dimension 1.
+     * @param d2  dimension 2.
+     * @param d3  dimension 3.
+     * @param d4  dimension 4.
+     */
+    protected void updateLCBLC(final int rowIndex, final Dimension d0, 
+                               final Dimension d1, final Dimension d2, 
+                               final Dimension d3, final Dimension d4) {
+
+        this.rowHeights[rowIndex] = (Math.max(
+            d0.height,
+            Math.max(Math.max(d1.height, d2.height),
+            Math.max(d3.height, d4.height)))
+        );
+        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
+        this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
+        this.columnWidths[1] = Math.max(this.columnWidths[1], d1.width);
+        this.columnWidths[2] = Math.max(this.columnWidths[2], d2.width);
+        this.columnWidths[3] = Math.max(this.columnWidths[3], d3.width);
+        this.columns4and5Width = Math.max(this.columns4and5Width, d4.width);
+
+    }
+
+    /**
+     * Processes a row in 'LCLCB' format.
+     *
+     * @param rowIndex  the row index.
+     * @param d0  dimension 0.
+     * @param d1  dimension 1.
+     * @param d2  dimension 2.
+     * @param d3  dimension 3.
+     * @param d4  dimension 4.
+     */
+    protected void updateLCLCB(final int rowIndex, final Dimension d0, 
+                               final Dimension d1, final Dimension d2,
+                               final Dimension d3, final Dimension d4) {
+
+        this.rowHeights[rowIndex] = (Math.max(d0.height,
+                                     Math.max(Math.max(d1.height, d2.height),
+                                              Math.max(d3.height, d4.height))));
+        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
+        this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
+        this.columns1and2Width = Math.max(this.columns1and2Width, d1.width);
+        this.columnWidths[3] = Math.max(this.columnWidths[3], d2.width);
+        this.columnWidths[4] = Math.max(this.columnWidths[4], d3.width);
+        this.columnWidths[5] = Math.max(this.columnWidths[5], d4.width);
+
+    }
+
+    /**
+     * Processes a row in 'LCBLCB' format.
+     *
+     * @param rowIndex  the row index.
+     * @param d0  dimension 0.
+     * @param d1  dimension 1.
+     * @param d2  dimension 2.
+     * @param d3  dimension 3.
+     * @param d4  dimension 4.
+     * @param d5  dimension 5.
+     */
+    protected void updateLCBLCB(final int rowIndex,
+                                final Dimension d0, final Dimension d1, 
+                                final Dimension d2,
+                                final Dimension d3, final Dimension d4, 
+                                final Dimension d5) {
+
+        this.rowHeights[rowIndex] = Math.max(
+            Math.max(d0.height, d1.height),
+            Math.max(Math.max(d2.height, d3.height),
+                     Math.max(d4.height, d5.height))
+        );
+        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
+        this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
+        this.columnWidths[1] = Math.max(this.columnWidths[1], d1.width);
+        this.columnWidths[2] = Math.max(this.columnWidths[2], d2.width);
+        this.columnWidths[3] = Math.max(this.columnWidths[3], d3.width);
+        this.columnWidths[4] = Math.max(this.columnWidths[4], d4.width);
+        this.columnWidths[5] = Math.max(this.columnWidths[5], d5.width);
+
+    }
+
+    /**
+     * Finishes of the processing.
+     */
+    public void complete() {
+
+        this.columnWidths[1] = Math.max(
+             this.columnWidths[1],
+             this.columns1and2Width - this.columnGaps[1] - this.columnWidths[2]
+        );
+
+        this.columnWidths[4] = Math.max(
+            this.columnWidths[4],
+            Math.max(
+                this.columns4and5Width - this.columnGaps[4] 
+                - this.columnWidths[5],
+                Math.max(
+                    this.columns1to4Width - this.columnGaps[1] 
+                        - this.columnGaps[2] - this.columnGaps[3] 
+                        - this.columnWidths[1] - this.columnWidths[2] 
+                        - this.columnWidths[3],
+                    this.columns1to5Width - this.columnGaps[1] 
+                        - this.columnGaps[2] - this.columnGaps[3] 
+                        - this.columnWidths[1] - this.columnWidths[2] 
+                        - this.columnWidths[3] - this.columnGaps[4]
+                )
+            )
+        );
+
+        int leftWidth = this.columnWidths[0] + this.columnGaps[0]
+                      + this.columnWidths[1] + this.columnGaps[1] 
+                      + this.columnWidths[2];
+
+        int rightWidth = this.columnWidths[3] + this.columnGaps[3]
+                       + this.columnWidths[4] + this.columnGaps[4] 
+                       + this.columnWidths[5];
+
+        if (splitLayout()) {
+            if (leftWidth > rightWidth) {
+                final int mismatch = leftWidth - rightWidth;
+                this.columnWidths[4] = this.columnWidths[4] + mismatch;
+                rightWidth = rightWidth + mismatch;
+            }
+            else {
+                final int mismatch = rightWidth - leftWidth;
+                this.columnWidths[1] = this.columnWidths[1] + mismatch;
+                leftWidth = leftWidth + mismatch;
+            }
+        }
+
+        this.totalWidth = leftWidth + this.columnGaps[2] + rightWidth;
+
+        if (this.columns0to5Width > this.totalWidth) {
+            final int spaceToAdd = (this.columns0to5Width - this.totalWidth);
+            if (splitLayout()) {
+                final int halfSpaceToAdd = spaceToAdd / 2;
+                this.columnWidths[1] = this.columnWidths[1] + halfSpaceToAdd;
+                this.columnWidths[4] = this.columnWidths[4] + spaceToAdd 
+                    - halfSpaceToAdd;
+                this.totalWidth = this.totalWidth + spaceToAdd;
+            }
+            else {
+                this.columnWidths[1] = this.columnWidths[1] + spaceToAdd;
+                this.totalWidth = this.totalWidth + spaceToAdd;
+            }
+        }
+
+    }
+
+    /**
+     * Returns true if this layout involves a split into two sections.
+     *
+     * @return <code>true</code> if this layout involves a split into two 
+     *         sections.
+     */
+    private boolean splitLayout() {
+        for (int i = 0; i < this.rowFormats.length; i++) {
+            if (this.rowFormats[i] > FormatLayout.LCB) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Not used.
+     *
+     * @param comp  the component.
+     */
+    public void addLayoutComponent(final Component comp) {
+        // not used
+    }
+
+    /**
+     * Not used.
+     *
+     * @param comp  the component.
+     */
+    public void removeLayoutComponent(final Component comp) {
+        // not used
+    }
+
+    /**
+     * Not used.
+     *
+     * @param name  the component name.
+     * @param comp  the component.
+     */
+    public void addLayoutComponent(final String name, final Component comp) {
+        // not used
+    }
+
+    /**
+     * Not used.
+     *
+     * @param name  the component name.
+     * @param comp  the component.
+     */
+    public void removeLayoutComponent(final String name, final Component comp) {
+        // not used
+    }
+
+}

+ 278 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/layout/LCBLayout.java

@@ -0,0 +1,278 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * --------------
+ * LCBLayout.java
+ * --------------
+ * (C) Copyright 2000-2005, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: LCBLayout.java,v 1.5 2005/11/16 15:58:40 taqua Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 26-Oct-2001 : Changed package to com.jrefinery.layout.* (DG);
+ * 10-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ */
+
+package org.jfree.layout;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.io.Serializable;
+
+/**
+ * Specialised layout manager for a grid of components.
+ *
+ * @author David Gilbert
+ */
+public class LCBLayout implements LayoutManager, Serializable {
+
+    /** For serialization. */
+    private static final long serialVersionUID = -2531780832406163833L;
+    
+    /** A constant for the number of columns in the layout. */
+    private static final int COLUMNS = 3;
+
+    /** Tracks the column widths. */
+    private int[] colWidth;
+
+    /** Tracks the row heights. */
+    private int[] rowHeight;
+
+    /** The gap between each label and component. */
+    private int labelGap;
+
+    /** The gap between each component and button. */
+    private int buttonGap;
+
+    /** The gap between rows. */
+    private int vGap;
+
+    /**
+     * Creates a new LCBLayout with the specified maximum number of rows.
+     *
+     * @param maxrows  the maximum number of rows.
+     */
+    public LCBLayout(final int maxrows) {
+        this.labelGap = 10;
+        this.buttonGap = 6;
+        this.vGap = 2;
+        this.colWidth = new int[COLUMNS];
+        this.rowHeight = new int[maxrows];
+    }
+
+    /**
+     * Returns the preferred size using this layout manager.
+     *
+     * @param parent  the parent.
+     *
+     * @return the preferred size using this layout manager.
+    */
+    public Dimension preferredLayoutSize(final Container parent) {
+
+        synchronized (parent.getTreeLock()) {
+            final Insets insets = parent.getInsets();
+            final int ncomponents = parent.getComponentCount();
+            final int nrows = ncomponents / COLUMNS;
+            for (int c = 0; c < COLUMNS; c++) {
+                for (int r = 0; r < nrows; r++) {
+                    final Component component 
+                        = parent.getComponent(r * COLUMNS + c);
+                    final Dimension d = component.getPreferredSize();
+                    if (this.colWidth[c] < d.width) {
+                        this.colWidth[c] = d.width;
+                    }
+                    if (this.rowHeight[r] < d.height) {
+                        this.rowHeight[r] = d.height;
+                    }
+                }
+            }
+            int totalHeight = this.vGap * (nrows - 1);
+            for (int r = 0; r < nrows; r++) {
+                totalHeight = totalHeight + this.rowHeight[r];
+            }
+            final int totalWidth = this.colWidth[0] + this.labelGap 
+                + this.colWidth[1] + this.buttonGap + this.colWidth[2];
+            return new Dimension(
+                insets.left + insets.right + totalWidth + this.labelGap 
+                    + this.buttonGap,
+                insets.top + insets.bottom + totalHeight + this.vGap
+            );
+        }
+
+    }
+
+    /**
+     * Returns the minimum size using this layout manager.
+     *
+     * @param parent  the parent.
+     *
+     * @return the minimum size using this layout manager.
+     */
+    public Dimension minimumLayoutSize(final Container parent) {
+
+        synchronized (parent.getTreeLock()) {
+            final Insets insets = parent.getInsets();
+            final int ncomponents = parent.getComponentCount();
+            final int nrows = ncomponents / COLUMNS;
+            for (int c = 0; c < COLUMNS; c++) {
+                for (int r = 0; r < nrows; r++) {
+                    final Component component 
+                        = parent.getComponent(r * COLUMNS + c);
+                    final Dimension d = component.getMinimumSize();
+                    if (this.colWidth[c] < d.width) {
+                        this.colWidth[c] = d.width;
+                    }
+                    if (this.rowHeight[r] < d.height) {
+                        this.rowHeight[r] = d.height;
+                    }
+                }
+            }
+            int totalHeight = this.vGap * (nrows - 1);
+            for (int r = 0; r < nrows; r++) {
+                totalHeight = totalHeight + this.rowHeight[r];
+            }
+            final int totalWidth = this.colWidth[0] + this.labelGap 
+                + this.colWidth[1] + this.buttonGap + this.colWidth[2];
+            return new Dimension(
+                insets.left + insets.right + totalWidth + this.labelGap 
+                + this.buttonGap,
+                insets.top + insets.bottom + totalHeight + this.vGap
+            );
+        }
+
+    }
+
+    /**
+     * Lays out the components.
+     *
+     * @param parent  the parent.
+     */
+    public void layoutContainer(final Container parent) {
+
+        synchronized (parent.getTreeLock()) {
+            final Insets insets = parent.getInsets();
+            final int ncomponents = parent.getComponentCount();
+            final int nrows = ncomponents / COLUMNS;
+            for (int c = 0; c < COLUMNS; c++) {
+                for (int r = 0; r < nrows; r++) {
+                    final Component component 
+                        = parent.getComponent(r * COLUMNS + c);
+                    final Dimension d = component.getPreferredSize();
+                    if (this.colWidth[c] < d.width) {
+                        this.colWidth[c] = d.width;
+                    }
+                    if (this.rowHeight[r] < d.height) {
+                        this.rowHeight[r] = d.height;
+                    }
+                }
+            }
+            int totalHeight = this.vGap * (nrows - 1);
+            for (int r = 0; r < nrows; r++) {
+                totalHeight = totalHeight + this.rowHeight[r];
+            }
+            final int totalWidth = this.colWidth[0] + this.colWidth[1] 
+                                                    + this.colWidth[2];
+
+            // adjust the width of the second column to use up all of parent
+            final int available = parent.getWidth() - insets.left 
+                - insets.right - this.labelGap - this.buttonGap;
+            this.colWidth[1] = this.colWidth[1] + (available - totalWidth);
+
+            // *** DO THE LAYOUT ***
+            int x = insets.left;
+            for (int c = 0; c < COLUMNS; c++) {
+                int y = insets.top;
+                for (int r = 0; r < nrows; r++) {
+                    final int i = r * COLUMNS + c;
+                    if (i < ncomponents) {
+                        final Component component = parent.getComponent(i);
+                        final Dimension d = component.getPreferredSize();
+                        final int h = d.height;
+                        final int adjust = (this.rowHeight[r] - h) / 2;
+                        parent.getComponent(i).setBounds(x, y + adjust, 
+                                this.colWidth[c], h);
+                    }
+                    y = y + this.rowHeight[r] + this.vGap;
+                }
+                x = x + this.colWidth[c];
+                if (c == 0) {
+                    x = x + this.labelGap;
+                }
+                if (c == 1) {
+                    x = x + this.buttonGap;
+                }
+            }
+
+        }
+
+    }
+
+    /**
+     * Not used.
+     *
+     * @param comp  the component.
+     */
+    public void addLayoutComponent(final Component comp) {
+        // not used
+    }
+
+    /**
+     * Not used.
+     *
+     * @param comp  the component.
+     */
+    public void removeLayoutComponent(final Component comp) {
+        // not used
+    }
+
+    /**
+     * Not used.
+     *
+     * @param name  the component name.
+     * @param comp  the component.
+     */
+    public void addLayoutComponent(final String name, final Component comp) {
+        // not used
+    }
+
+    /**
+     * Not used.
+     *
+     * @param name  the component name.
+     * @param comp  the component.
+     */
+    public void removeLayoutComponent(final String name, final Component comp) {
+        // not used
+    }
+
+}

+ 311 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/layout/RadialLayout.java

@@ -0,0 +1,311 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -----------------
+ * RadialLayout.java
+ * -----------------
+ * (C) Copyright 2003, 2004, by Bryan Scott (for Australian Antarctic Division).
+ *
+ * Original Author:  Bryan Scott (for Australian Antarctic Division);
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ *
+ * Changes:
+ * --------
+ * 30-Jun-2003 : Version 1 (BS);
+ * 24-Jul-2003 : Completed missing Javadocs (DG);
+ *
+ */
+
+package org.jfree.layout;
+
+import java.awt.Checkbox;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.awt.Panel;
+import java.io.Serializable;
+
+/**
+ * RadialLayout is a component layout manager.  Compents are laid out in a
+ * circle. If only one component is contained in the layout it is positioned
+ * centrally, otherwise components are evenly spaced around the centre with
+ * the first component placed to the North.
+ *<P>
+ * This code was developed to display CTD rosette firing control
+ *
+ * WARNING: Not thoughly tested, use at own risk.
+ * 
+ * @author Bryan Scott (for Australian Antarctic Division)
+ */
+
+public class RadialLayout implements LayoutManager, Serializable {
+    
+    /** For serialization. */
+    private static final long serialVersionUID = -7582156799248315534L;
+    
+    /** The minimum width. */
+    private int minWidth = 0;
+    
+    /** The minimum height. */
+    private int minHeight = 0;
+    
+    /** The maximum component width. */
+    private int maxCompWidth = 0;
+    
+    /** The maximum component height. */
+    private int maxCompHeight = 0;
+    
+    /** The preferred width. */
+    private int preferredWidth = 0;
+    
+    /** The preferred height. */
+    private int preferredHeight = 0;
+    
+    /** Size unknown flag. */
+    private boolean sizeUnknown = true;
+
+    /** 
+     * Constructs this layout manager with default properties. 
+     */
+    public RadialLayout() {
+        super();
+    }
+
+    /**
+     * Not used.
+     *
+     * @param comp  the component.
+     */
+    public void addLayoutComponent(final Component comp) {
+        // not used
+    }
+
+    /**
+     * Not used.
+     *
+     * @param comp  the component.
+     */
+    public void removeLayoutComponent(final Component comp) {
+        // not used
+    }
+
+    /**
+     * Not used.
+     *
+     * @param name  the component name.
+     * @param comp  the component.
+     */
+    public void addLayoutComponent(final String name, final Component comp) {
+        // not used
+    }
+
+    /**
+     * Not used.
+     *
+     * @param name  the component name.
+     * @param comp  the component.
+     */
+    public void removeLayoutComponent(final String name, final Component comp) {
+        // not used
+    }
+
+    /**
+     * Sets the sizes attribute of the RadialLayout object.
+     *
+     * @param  parent  the parent.
+     * 
+     * @see LayoutManager
+     */
+    private void setSizes(final Container parent) {
+        final int nComps = parent.getComponentCount();
+        //Reset preferred/minimum width and height.
+        this.preferredWidth = 0;
+        this.preferredHeight = 0;
+        this.minWidth = 0;
+        this.minHeight = 0;
+        for (int i = 0; i < nComps; i++) {
+            final Component c = parent.getComponent(i);
+            if (c.isVisible()) {
+                final Dimension d = c.getPreferredSize();
+                if (this.maxCompWidth < d.width) {
+                    this.maxCompWidth = d.width;
+                }
+                if (this.maxCompHeight < d.height) {
+                    this.maxCompHeight = d.height;
+                }
+                this.preferredWidth += d.width;
+                this.preferredHeight += d.height;
+            }
+        }
+        this.preferredWidth  = this.preferredWidth / 2;
+        this.preferredHeight = this.preferredHeight / 2;
+        this.minWidth = this.preferredWidth;
+        this.minHeight = this.preferredHeight;
+    }
+
+    /**
+     * Returns the preferred size.
+     *
+     * @param parent  the parent.
+     *
+     * @return The preferred size.
+     * @see LayoutManager
+     */
+    public Dimension preferredLayoutSize(final Container parent) {
+        final Dimension dim = new Dimension(0, 0);
+        setSizes(parent);
+
+        //Always add the container's insets!
+        final Insets insets = parent.getInsets();
+        dim.width = this.preferredWidth + insets.left + insets.right;
+        dim.height = this.preferredHeight + insets.top + insets.bottom;
+
+        this.sizeUnknown = false;
+        return dim;
+    }
+
+    /**
+     * Returns the minimum size.
+     *
+     * @param parent  the parent.
+     *
+     * @return The minimum size.
+     * @see LayoutManager
+     */
+    public Dimension minimumLayoutSize(final Container parent) {
+        final Dimension dim = new Dimension(0, 0);
+
+        //Always add the container's insets!
+        final Insets insets = parent.getInsets();
+        dim.width = this.minWidth + insets.left + insets.right;
+        dim.height = this.minHeight + insets.top + insets.bottom;
+
+        this.sizeUnknown = false;
+        return dim;
+    }
+
+   /**
+    * This is called when the panel is first displayed, and every time its size
+    * changes.
+    * Note: You CAN'T assume preferredLayoutSize or minimumLayoutSize will be
+    * called -- in the case of applets, at least, they probably won't be.
+    *
+    * @param  parent  the parent.
+    * @see LayoutManager
+    */
+    public void layoutContainer(final Container parent) {
+        final Insets insets = parent.getInsets();
+        final int maxWidth = parent.getSize().width 
+            - (insets.left + insets.right);
+        final int maxHeight = parent.getSize().height 
+            - (insets.top + insets.bottom);
+        final int nComps = parent.getComponentCount();
+        int x = 0;
+        int y = 0;
+
+        // Go through the components' sizes, if neither preferredLayoutSize nor
+        // minimumLayoutSize has been called.
+        if (this.sizeUnknown) {
+            setSizes(parent);
+        }
+
+        if (nComps < 2) {
+            final Component c = parent.getComponent(0);
+            if (c.isVisible()) {
+                final Dimension d = c.getPreferredSize();
+                c.setBounds(x, y, d.width, d.height);
+            }
+        } 
+        else {
+            double radialCurrent = Math.toRadians(90);
+            final double radialIncrement = 2 * Math.PI / nComps;
+            final int midX = maxWidth / 2;
+            final int midY = maxHeight / 2;
+            final int a = midX - this.maxCompWidth;
+            final int b = midY - this.maxCompHeight;
+            for (int i = 0; i < nComps; i++) {
+                final Component c = parent.getComponent(i);
+                if (c.isVisible()) {
+                    final Dimension d = c.getPreferredSize();
+                    x = (int) (midX
+                               - (a * Math.cos(radialCurrent))
+                               - (d.getWidth() / 2)
+                               + insets.left);
+                    y = (int) (midY
+                               - (b * Math.sin(radialCurrent))
+                               - (d.getHeight() / 2)
+                               + insets.top);
+
+                    // Set the component's size and position.
+                    c.setBounds(x, y, d.width, d.height);
+                }
+                radialCurrent += radialIncrement;
+            }
+        }
+    }
+
+    /**
+     * Returns the class name.
+     * 
+     * @return The class name.
+     */
+    public String toString() {
+        return getClass().getName();
+    }
+
+    /**
+     * Run a demonstration.
+     *
+     * @param args  ignored.
+     * 
+     * @throws Exception when an error occurs.
+     */
+    public static void main(final String[] args) throws Exception {
+        final Frame frame = new Frame();
+        final Panel panel = new Panel();
+        panel.setLayout(new RadialLayout());
+
+        panel.add(new Checkbox("One"));
+        panel.add(new Checkbox("Two"));
+        panel.add(new Checkbox("Three"));
+        panel.add(new Checkbox("Four"));
+        panel.add(new Checkbox("Five"));
+        panel.add(new Checkbox("One"));
+        panel.add(new Checkbox("Two"));
+        panel.add(new Checkbox("Three"));
+        panel.add(new Checkbox("Four"));
+        panel.add(new Checkbox("Five"));
+
+        frame.add(panel);
+        frame.setSize(300, 500);
+        frame.setVisible(true);
+    }
+
+}

+ 6 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/layout/package.html

@@ -0,0 +1,6 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+Custom layout managers.
+</body>
+</html>

+ 6 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/package.html

@@ -0,0 +1,6 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+The root package for the JCommon class library.
+</body>
+</html>

+ 73 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/resources/JCommonResources.java

@@ -0,0 +1,73 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2014, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * ---------------------
+ * JCommonResources.java
+ * ---------------------
+ * (C) Copyright 2002-2014, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ */
+
+package org.jfree.resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ * Localised resources for the JCommon Class Library.
+ */
+public class JCommonResources extends ListResourceBundle {
+
+    /**
+     * Default constructor.
+     */
+    public JCommonResources() {
+        // nothing to do
+    }
+
+    /**
+     * Returns the array of strings in the resource bundle.
+     *
+     * @return The resources.
+     */
+    @Override
+    public Object[][] getContents() {
+        return CONTENTS;
+    }
+
+    /** The resources to be localised. */
+    private static final Object[][] CONTENTS = {
+        { "project.name", "JCommon" },
+        { "project.version", "1.0.22"},
+        { "project.info", "http://www.jfree.org/jcommon/" },
+        { "project.copyright",
+            "(C)opyright 2000-2014, by Object Refinery Limited and Contributors"}
+
+    };
+
+}

+ 6 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/resources/package.html

@@ -0,0 +1,6 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+General localised resources for the JCommon class library.
+</body>
+</html>

+ 88 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/text/G2TextMeasurer.java

@@ -0,0 +1,88 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -------------------
+ * G2TextMeasurer.java
+ * -------------------
+ * (C) Copyright 2004, 2005, by Object Refinery Limited and Contributors.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: G2TextMeasurer.java,v 1.4 2005/10/18 13:17:16 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jan-2004 : Version 1 (DG);
+ *
+ */
+ 
+package org.jfree.text;
+
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * A {@link TextMeasurer} based on a {@link Graphics2D}.
+ *
+ * @author David Gilbert
+ */
+public class G2TextMeasurer implements TextMeasurer {
+
+    /** The graphics device. */
+    private Graphics2D g2;
+    
+    /**
+     * Creates a new text measurer.
+     * 
+     * @param g2  the graphics device.
+     */
+    public G2TextMeasurer(final Graphics2D g2) {
+        this.g2 = g2;
+    }
+
+    /**
+     * Returns the string width.
+     * 
+     * @param text  the text.
+     * @param start  the index of the first character to measure.
+     * @param end  the index of the last character to measure.
+     * 
+     * @return The string width.
+     */
+    public float getStringWidth(final String text, 
+                                final int start, final int end) {
+        final FontMetrics fm = this.g2.getFontMetrics();
+        final Rectangle2D bounds = TextUtilities.getTextBounds(
+            text.substring(start, end), this.g2, fm
+        );
+        final float result = (float) bounds.getWidth();
+        return result;
+    }
+    
+}
+

+ 353 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextBlock.java

@@ -0,0 +1,353 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * --------------
+ * TextBlock.java
+ * --------------
+ * (C) Copyright 2003, 2004, by Object Refinery Limited and Contributors.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: TextBlock.java,v 1.15 2007/11/02 17:50:35 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 07-Nov-2003 : Version 1 (DG);
+ * 22-Dec-2003 : Added workaround for Java bug 4245442 (DG);
+ * 09-Jan-2004 : Added an extra draw() method for no rotation case (DG);
+ * 25-Feb-2004 : Added getLines() method (DG);
+ * 22-Mar-2004 : Added equals() method and implemented Serializable (DG);
+ * 24-Mar-2004 : Added 'paint' argument to addLine() method (DG);
+ * 01-Apr-2004 : Changed java.awt.geom.Dimension2D to org.jfree.ui.Size2D 
+ *               because of JDK bug 4976448 which persists on JDK 1.3.1 (DG);
+ * 04-Oct-2004 : Renamed ShapeUtils --> ShapeUtilities (DG);
+ *
+ */
+ 
+package org.jfree.text;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Shape;
+import java.awt.geom.Rectangle2D;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jfree.ui.HorizontalAlignment;
+import org.jfree.ui.Size2D;
+import org.jfree.ui.TextAnchor;
+import org.jfree.util.ShapeUtilities;
+
+/**
+ * A list of {@link TextLine} objects that form a block of text.
+ * 
+ * @see TextUtilities#createTextBlock(String, Font, Paint)
+ *
+ * @author David Gilbert
+ */
+public class TextBlock implements Serializable {
+
+    /** For serialization. */
+    private static final long serialVersionUID = -4333175719424385526L;
+    
+    /** Storage for the lines of text. */
+    private List lines;
+    
+    /** The alignment of the lines. */
+    private HorizontalAlignment lineAlignment;
+
+    /**
+     * Creates a new empty text block.
+     */
+    public TextBlock() {
+        this.lines = new java.util.ArrayList();
+        this.lineAlignment = HorizontalAlignment.CENTER;
+    }
+    
+    /**
+     * Returns the alignment of the lines of text within the block.
+     * 
+     * @return The alignment (never <code>null</code>).
+     */
+    public HorizontalAlignment getLineAlignment() {
+        return this.lineAlignment;   
+    }
+    
+    /**
+     * Sets the alignment of the lines of text within the block.
+     * 
+     * @param alignment  the alignment (<code>null</code> not permitted).
+     */
+    public void setLineAlignment(HorizontalAlignment alignment) {
+        if (alignment == null) {
+            throw new IllegalArgumentException("Null 'alignment' argument.");
+        }
+        this.lineAlignment = alignment;   
+    }
+    
+    /**
+     * Adds a line of text that will be displayed using the specified font.
+     * 
+     * @param text  the text.
+     * @param font  the font.
+     * @param paint  the paint.
+     */
+    public void addLine(final String text, final Font font, final Paint paint) {
+        addLine(new TextLine(text, font, paint));
+    }
+    
+    /**
+     * Adds a {@link TextLine} to the block.
+     * 
+     * @param line  the line.
+     */
+    public void addLine(final TextLine line) {
+        this.lines.add(line);    
+    }
+    
+    /**
+     * Returns the last line in the block.
+     * 
+     * @return The last line in the block.
+     */
+    public TextLine getLastLine() {
+        TextLine last = null;
+        final int index = this.lines.size() - 1;
+        if (index >= 0) {
+            last = (TextLine) this.lines.get(index);
+        }
+        return last;
+    }
+    
+    /**
+     * Returns an unmodifiable list containing the lines for the text block.
+     *
+     * @return A list of {@link TextLine} objects.
+     */
+    public List getLines() {
+        return Collections.unmodifiableList(this.lines);
+    }
+    
+    /**
+     * Returns the width and height of the text block.
+     * 
+     * @param g2  the graphics device.
+     * 
+     * @return The width and height.
+     */
+    public Size2D calculateDimensions(final Graphics2D g2) {
+        double width = 0.0;
+        double height = 0.0;
+        final Iterator iterator = this.lines.iterator();
+        while (iterator.hasNext()) {
+            final TextLine line = (TextLine) iterator.next();
+            final Size2D dimension = line.calculateDimensions(g2);
+            width = Math.max(width, dimension.getWidth());
+            height = height + dimension.getHeight();
+        }
+        return new Size2D(width, height);
+    }
+    
+    /**
+     * Returns the bounds of the text block.
+     * 
+     * @param g2  the graphics device (<code>null</code> not permitted).
+     * @param anchorX  the x-coordinate for the anchor point.
+     * @param anchorY  the y-coordinate for the anchor point.
+     * @param anchor  the text block anchor (<code>null</code> not permitted).
+     * @param rotateX  the x-coordinate for the rotation point.
+     * @param rotateY  the y-coordinate for the rotation point.
+     * @param angle  the rotation angle.
+     * 
+     * @return The bounds.
+     */
+    public Shape calculateBounds(final Graphics2D g2,
+                                 final float anchorX, final float anchorY, 
+                                 final TextBlockAnchor anchor,
+                                 final float rotateX, final float rotateY, 
+                                 final double angle) {
+        
+        final Size2D d = calculateDimensions(g2);
+        final float[] offsets = calculateOffsets(
+            anchor, d.getWidth(), d.getHeight()
+        );
+        final Rectangle2D bounds = new Rectangle2D.Double(
+            anchorX + offsets[0], anchorY + offsets[1], 
+            d.getWidth(), d.getHeight()
+        );
+        final Shape rotatedBounds = ShapeUtilities.rotateShape(
+            bounds, angle, rotateX, rotateY
+        );
+        return rotatedBounds;   
+        
+    }
+    
+    /**
+     * Draws the text block at a specific location.
+     * 
+     * @param g2  the graphics device.
+     * @param x  the x-coordinate for the anchor point.
+     * @param y  the y-coordinate for the anchor point.
+     * @param anchor  the anchor point.
+     */
+    public void draw(final Graphics2D g2, final float x, final float y, 
+                     final TextBlockAnchor anchor) {
+        draw(g2, x, y, anchor, 0.0f, 0.0f, 0.0);
+    }
+    
+    /**
+     * Draws the text block, aligning it with the specified anchor point and 
+     * rotating it about the specified rotation point.
+     * 
+     * @param g2  the graphics device.
+     * @param anchorX  the x-coordinate for the anchor point.
+     * @param anchorY  the y-coordinate for the anchor point.
+     * @param anchor  the point on the text block that is aligned to the 
+     *                anchor point.
+     * @param rotateX  the x-coordinate for the rotation point.
+     * @param rotateY  the x-coordinate for the rotation point.
+     * @param angle  the rotation (in radians).
+     */
+    public void draw(final Graphics2D g2,
+                     final float anchorX, final float anchorY, 
+                     final TextBlockAnchor anchor,
+                     final float rotateX, final float rotateY, 
+                     final double angle) {
+    
+        final Size2D d = calculateDimensions(g2);
+        final float[] offsets = calculateOffsets(anchor, d.getWidth(), 
+                d.getHeight());
+        final Iterator iterator = this.lines.iterator();
+        float yCursor = 0.0f;
+        while (iterator.hasNext()) {
+            TextLine line = (TextLine) iterator.next();
+            Size2D dimension = line.calculateDimensions(g2);
+            float lineOffset = 0.0f;
+            if (this.lineAlignment == HorizontalAlignment.CENTER) {
+                lineOffset = (float) (d.getWidth() - dimension.getWidth()) 
+                    / 2.0f;   
+            }
+            else if (this.lineAlignment == HorizontalAlignment.RIGHT) {
+                lineOffset = (float) (d.getWidth() - dimension.getWidth());   
+            }
+            line.draw(
+                g2, anchorX + offsets[0] + lineOffset, anchorY + offsets[1] + yCursor,
+                TextAnchor.TOP_LEFT, rotateX, rotateY, angle
+            );
+            yCursor = yCursor + (float) dimension.getHeight();
+        }
+        
+    }
+ 
+    /**
+     * Calculates the x and y offsets required to align the text block with the
+     * specified anchor point.  This assumes that the top left of the text 
+     * block is at (0.0, 0.0).
+     * 
+     * @param anchor  the anchor position.
+     * @param width  the width of the text block.
+     * @param height  the height of the text block.
+     * 
+     * @return The offsets (float[0] = x offset, float[1] = y offset).
+     */
+    private float[] calculateOffsets(final TextBlockAnchor anchor, 
+                                     final double width, final double height) {
+        final float[] result = new float[2];
+        float xAdj = 0.0f;
+        float yAdj = 0.0f;
+
+        if (anchor == TextBlockAnchor.TOP_CENTER
+                || anchor == TextBlockAnchor.CENTER
+                || anchor == TextBlockAnchor.BOTTOM_CENTER) {
+                    
+            xAdj = (float) -width / 2.0f;
+            
+        }
+        else if (anchor == TextBlockAnchor.TOP_RIGHT
+                || anchor == TextBlockAnchor.CENTER_RIGHT
+                || anchor == TextBlockAnchor.BOTTOM_RIGHT) {
+                    
+            xAdj = (float) -width;
+            
+        }
+
+        if (anchor == TextBlockAnchor.TOP_LEFT
+                || anchor == TextBlockAnchor.TOP_CENTER
+                || anchor == TextBlockAnchor.TOP_RIGHT) {
+                    
+            yAdj = 0.0f;
+            
+        }
+        else if (anchor == TextBlockAnchor.CENTER_LEFT
+                || anchor == TextBlockAnchor.CENTER
+                || anchor == TextBlockAnchor.CENTER_RIGHT) {
+                    
+            yAdj = (float) -height / 2.0f;
+            
+        }
+        else if (anchor == TextBlockAnchor.BOTTOM_LEFT
+                || anchor == TextBlockAnchor.BOTTOM_CENTER
+                || anchor == TextBlockAnchor.BOTTOM_RIGHT) {
+                    
+            yAdj = (float) -height;
+            
+        }
+        result[0] = xAdj;
+        result[1] = yAdj;
+        return result;
+    }   
+    
+    /**
+     * Tests this object for equality with an arbitrary object.
+     * 
+     * @param obj  the object to test against (<code>null</code> permitted).
+     * 
+     * @return A boolean.
+     */
+    public boolean equals(final Object obj) {
+        if (obj == this) {
+            return true;   
+        }
+        if (obj instanceof TextBlock) {
+            final TextBlock block = (TextBlock) obj;
+            return this.lines.equals(block.lines);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a hash code for this object.
+     * 
+     * @return A hash code.
+     */
+    public int hashCode() {
+        return (this.lines != null ? this.lines.hashCode() : 0);
+    }
+}

+ 192 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextBlockAnchor.java

@@ -0,0 +1,192 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * --------------------
+ * TextBlockAnchor.java
+ * --------------------
+ * (C) Copyright 2003-2005, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: TextBlockAnchor.java,v 1.4 2005/10/18 13:17:16 mungady Exp $
+ *
+ * Changes:
+ * --------
+ * 06-Nov-2003 : Version 1 (DG);
+ * 22-Mar-2004 : Added readResolve() method (DG); 
+ * 
+ */
+
+package org.jfree.text;
+
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
+/**
+ * Used to indicate the position of an anchor point for a text block.
+ *
+ * @author David Gilbert
+ */
+public final class TextBlockAnchor implements Serializable {
+
+    /** For serialization. */
+    private static final long serialVersionUID = -3045058380983401544L;
+    
+    /** Top/left. */
+    public static final TextBlockAnchor TOP_LEFT 
+        = new TextBlockAnchor("TextBlockAnchor.TOP_LEFT");
+
+    /** Top/center. */
+    public static final TextBlockAnchor TOP_CENTER = new TextBlockAnchor(
+        "TextBlockAnchor.TOP_CENTER"
+    );
+
+    /** Top/right. */
+    public static final TextBlockAnchor TOP_RIGHT = new TextBlockAnchor(
+       "TextBlockAnchor.TOP_RIGHT"
+    );
+
+    /** Middle/left. */
+    public static final TextBlockAnchor CENTER_LEFT = new TextBlockAnchor(
+        "TextBlockAnchor.CENTER_LEFT"
+    );
+
+    /** Middle/center. */
+    public static final TextBlockAnchor CENTER 
+        = new TextBlockAnchor("TextBlockAnchor.CENTER");
+
+    /** Middle/right. */
+    public static final TextBlockAnchor CENTER_RIGHT = new TextBlockAnchor(
+        "TextBlockAnchor.CENTER_RIGHT"
+    );
+
+    /** Bottom/left. */
+    public static final TextBlockAnchor BOTTOM_LEFT 
+        = new TextBlockAnchor("TextBlockAnchor.BOTTOM_LEFT");
+
+    /** Bottom/center. */
+    public static final TextBlockAnchor BOTTOM_CENTER 
+        = new TextBlockAnchor("TextBlockAnchor.BOTTOM_CENTER");
+
+    /** Bottom/right. */
+    public static final TextBlockAnchor BOTTOM_RIGHT 
+        = new TextBlockAnchor("TextBlockAnchor.BOTTOM_RIGHT");
+
+    /** The name. */
+    private String name;
+
+    /**
+     * Private constructor.
+     *
+     * @param name  the name.
+     */
+    private TextBlockAnchor(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * Returns a string representing the object.
+     *
+     * @return The string.
+     */
+    public String toString() {
+        return this.name;
+    }
+
+    /**
+     * Returns <code>true</code> if this object is equal to the specified 
+     * object, and <code>false</code> otherwise.
+     *
+     * @param o  the other object.
+     *
+     * @return A boolean.
+     */
+    public boolean equals(final Object o) {
+
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof TextBlockAnchor)) {
+            return false;
+        }
+
+        final TextBlockAnchor other = (TextBlockAnchor) o;
+        if (!this.name.equals(other.name)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns a hash code value for the object.
+     *
+     * @return the hashcode
+     */
+    public int hashCode() {
+        return this.name.hashCode();
+    }
+
+    /**
+     * Ensures that serialization returns the unique instances.
+     * 
+     * @return The object.
+     * 
+     * @throws ObjectStreamException if there is a problem.
+     */
+    private Object readResolve() throws ObjectStreamException {
+        if (this.equals(TextBlockAnchor.TOP_CENTER)) {
+            return TextBlockAnchor.TOP_CENTER;
+        }
+        else if (this.equals(TextBlockAnchor.TOP_LEFT)) {
+            return TextBlockAnchor.TOP_LEFT;
+        }
+        else if (this.equals(TextBlockAnchor.TOP_RIGHT)) {
+            return TextBlockAnchor.TOP_RIGHT;
+        }
+        else if (this.equals(TextBlockAnchor.CENTER)) {
+            return TextBlockAnchor.CENTER;
+        }
+        else if (this.equals(TextBlockAnchor.CENTER_LEFT)) {
+            return TextBlockAnchor.CENTER_LEFT;
+        }
+        else if (this.equals(TextBlockAnchor.CENTER_RIGHT)) {
+            return TextBlockAnchor.CENTER_RIGHT;
+        }
+        else if (this.equals(TextBlockAnchor.BOTTOM_CENTER)) {
+            return TextBlockAnchor.BOTTOM_CENTER;
+        }
+        else if (this.equals(TextBlockAnchor.BOTTOM_LEFT)) {
+            return TextBlockAnchor.BOTTOM_LEFT;
+        }
+        else if (this.equals(TextBlockAnchor.BOTTOM_RIGHT)) {
+            return TextBlockAnchor.BOTTOM_RIGHT;
+        }
+        return null;
+    }
+
+}

+ 448 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextBox.java

@@ -0,0 +1,448 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * ------------
+ * TextBox.java
+ * ------------
+ * (C) Copyright 2004, 2008, by Object Refinery Limited and Contributors.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: TextBox.java,v 1.14 2008/09/01 16:00:42 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 09-Mar-2004 : Version 1 (DG);
+ * 22-Mar-2004 : Added equals() method and implemented Serializable (DG);
+ * 09-Nov-2004 : Renamed getAdjustedHeight() --> calculateExtendedHeight() in
+ *               Spacer class (DG);
+ * 22-Feb-2005 : Replaced Spacer with RectangleInsets (DG);
+ * 14-Feb-2008 : Fixed alignment of text content with respect to insets (DG);
+ *
+ */
+
+package org.jfree.text;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Stroke;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import org.jfree.io.SerialUtilities;
+import org.jfree.ui.RectangleAnchor;
+import org.jfree.ui.RectangleInsets;
+import org.jfree.ui.Size2D;
+import org.jfree.util.ObjectUtilities;
+
+/**
+ * A box containing a text block.
+ *
+ * @author David Gilbert
+ */
+public class TextBox implements Serializable {
+
+    /** For serialization. */
+    private static final long serialVersionUID = 3360220213180203706L;
+
+    /** The outline paint. */
+    private transient Paint outlinePaint;
+
+    /** The outline stroke. */
+    private transient Stroke outlineStroke;
+
+    /** The interior space. */
+    private RectangleInsets interiorGap;
+
+    /** The background paint. */
+    private transient Paint backgroundPaint;
+
+    /** The shadow paint. */
+    private transient Paint shadowPaint;
+
+    /** The shadow x-offset. */
+    private double shadowXOffset = 2.0;
+
+    /** The shadow y-offset. */
+    private double shadowYOffset = 2.0;
+
+    /** The text block. */
+    private TextBlock textBlock;
+
+    /**
+     * Creates an empty text box.
+     */
+    public TextBox() {
+        this((TextBlock) null);
+    }
+
+    /**
+     * Creates a text box.
+     *
+     * @param text  the text.
+     */
+    public TextBox(final String text) {
+        this((TextBlock) null);
+        if (text != null) {
+            this.textBlock = new TextBlock();
+            this.textBlock.addLine(
+                text, new Font("SansSerif", Font.PLAIN, 10),
+                Color.black
+            );
+        }
+    }
+
+    /**
+     * Creates a new text box.
+     *
+     * @param block  the text block.
+     */
+    public TextBox(final TextBlock block) {
+        this.outlinePaint = Color.black;
+        this.outlineStroke = new BasicStroke(1.0f);
+        this.interiorGap = new RectangleInsets(1.0, 3.0, 1.0, 3.0);
+        this.backgroundPaint = new Color(255, 255, 192);
+        this.shadowPaint = Color.gray;
+        this.shadowXOffset = 2.0;
+        this.shadowYOffset = 2.0;
+        this.textBlock = block;
+    }
+
+    /**
+     * Returns the outline paint.
+     *
+     * @return The outline paint.
+     */
+    public Paint getOutlinePaint() {
+        return this.outlinePaint;
+    }
+
+    /**
+     * Sets the outline paint.
+     *
+     * @param paint  the paint.
+     */
+    public void setOutlinePaint(final Paint paint) {
+        this.outlinePaint = paint;
+    }
+
+    /**
+     * Returns the outline stroke.
+     *
+     * @return The outline stroke.
+     */
+    public Stroke getOutlineStroke() {
+        return this.outlineStroke;
+    }
+
+    /**
+     * Sets the outline stroke.
+     *
+     * @param stroke  the stroke.
+     */
+    public void setOutlineStroke(final Stroke stroke) {
+        this.outlineStroke = stroke;
+    }
+
+    /**
+     * Returns the interior gap.
+     *
+     * @return The interior gap.
+     */
+    public RectangleInsets getInteriorGap() {
+        return this.interiorGap;
+    }
+
+    /**
+     * Sets the interior gap.
+     *
+     * @param gap  the gap.
+     */
+    public void setInteriorGap(final RectangleInsets gap) {
+        this.interiorGap = gap;
+    }
+
+    /**
+     * Returns the background paint.
+     *
+     * @return The background paint.
+     */
+    public Paint getBackgroundPaint() {
+        return this.backgroundPaint;
+    }
+
+    /**
+     * Sets the background paint.
+     *
+     * @param paint  the paint.
+     */
+    public void setBackgroundPaint(final Paint paint) {
+        this.backgroundPaint = paint;
+    }
+
+    /**
+     * Returns the shadow paint.
+     *
+     * @return The shadow paint.
+     */
+    public Paint getShadowPaint() {
+        return this.shadowPaint;
+    }
+
+    /**
+     * Sets the shadow paint.
+     *
+     * @param paint  the paint.
+     */
+    public void setShadowPaint(final Paint paint) {
+        this.shadowPaint = paint;
+    }
+
+    /**
+     * Returns the x-offset for the shadow effect.
+     *
+     * @return The offset.
+     */
+    public double getShadowXOffset() {
+        return this.shadowXOffset;
+    }
+
+    /**
+     * Sets the x-offset for the shadow effect.
+     *
+     * @param offset  the offset (in Java2D units).
+     */
+    public void setShadowXOffset(final double offset) {
+        this.shadowXOffset = offset;
+    }
+
+    /**
+     * Returns the y-offset for the shadow effect.
+     *
+     * @return The offset.
+     */
+    public double getShadowYOffset() {
+        return this.shadowYOffset;
+    }
+
+    /**
+     * Sets the y-offset for the shadow effect.
+     *
+     * @param offset  the offset (in Java2D units).
+     */
+    public void setShadowYOffset(final double offset) {
+        this.shadowYOffset = offset;
+    }
+
+    /**
+     * Returns the text block.
+     *
+     * @return The text block.
+     */
+    public TextBlock getTextBlock() {
+        return this.textBlock;
+    }
+
+    /**
+     * Sets the text block.
+     *
+     * @param block  the block.
+     */
+    public void setTextBlock(final TextBlock block) {
+        this.textBlock = block;
+    }
+
+    /**
+     * Draws the text box.
+     *
+     * @param g2  the graphics device.
+     * @param x  the x-coordinate.
+     * @param y  the y-coordinate.
+     * @param anchor  the anchor point.
+     */
+    public void draw(final Graphics2D g2,
+                     final float x, final float y,
+                     final RectangleAnchor anchor) {
+        final Size2D d1 = this.textBlock.calculateDimensions(g2);
+        final double w = this.interiorGap.extendWidth(d1.getWidth());
+        final double h = this.interiorGap.extendHeight(d1.getHeight());
+        final Size2D d2 = new Size2D(w, h);
+        final Rectangle2D bounds
+                = RectangleAnchor.createRectangle(d2, x, y, anchor);
+        double xx = bounds.getX();
+        double yy = bounds.getY();
+
+        if (this.shadowPaint != null) {
+            final Rectangle2D shadow = new Rectangle2D.Double(
+                xx + this.shadowXOffset, yy + this.shadowYOffset,
+                bounds.getWidth(), bounds.getHeight());
+            g2.setPaint(this.shadowPaint);
+            g2.fill(shadow);
+        }
+        if (this.backgroundPaint != null) {
+            g2.setPaint(this.backgroundPaint);
+            g2.fill(bounds);
+        }
+
+        if (this.outlinePaint != null && this.outlineStroke != null) {
+            g2.setPaint(this.outlinePaint);
+            g2.setStroke(this.outlineStroke);
+            g2.draw(bounds);
+        }
+
+        this.textBlock.draw(g2,
+                (float) (xx + this.interiorGap.calculateLeftInset(w)),
+                (float) (yy + this.interiorGap.calculateTopInset(h)),
+                TextBlockAnchor.TOP_LEFT);
+
+    }
+
+    /**
+     * Returns the height of the text box.
+     *
+     * @param g2  the graphics device.
+     *
+     * @return The height (in Java2D units).
+     */
+    public double getHeight(final Graphics2D g2) {
+        final Size2D d = this.textBlock.calculateDimensions(g2);
+        return this.interiorGap.extendHeight(d.getHeight());
+    }
+
+    /**
+     * Tests this object for equality with an arbitrary object.
+     *
+     * @param obj  the object to test against (<code>null</code> permitted).
+     *
+     * @return A boolean.
+     */
+    public boolean equals(final Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (!(obj instanceof TextBox)) {
+            return false;
+        }
+        final TextBox that = (TextBox) obj;
+        if (!ObjectUtilities.equal(this.outlinePaint, that.outlinePaint)) {
+            return false;
+        }
+        if (!ObjectUtilities.equal(this.outlineStroke, that.outlineStroke)) {
+            return false;
+        }
+        if (!ObjectUtilities.equal(this.interiorGap, that.interiorGap)) {
+            return false;
+        }
+        if (!ObjectUtilities.equal(this.backgroundPaint,
+                that.backgroundPaint)) {
+            return false;
+        }
+        if (!ObjectUtilities.equal(this.shadowPaint, that.shadowPaint)) {
+            return false;
+        }
+        if (this.shadowXOffset != that.shadowXOffset) {
+            return false;
+        }
+        if (this.shadowYOffset != that.shadowYOffset) {
+            return false;
+        }
+        if (!ObjectUtilities.equal(this.textBlock, that.textBlock)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns a hash code for this object.
+     *
+     * @return A hash code.
+     */
+    public int hashCode() {
+        int result;
+        long temp;
+        result = (this.outlinePaint != null ? this.outlinePaint.hashCode() : 0);
+        result = 29 * result + (this.outlineStroke != null
+                ? this.outlineStroke.hashCode() : 0);
+        result = 29 * result + (this.interiorGap != null
+                ? this.interiorGap.hashCode() : 0);
+        result = 29 * result + (this.backgroundPaint != null
+                ? this.backgroundPaint.hashCode() : 0);
+        result = 29 * result + (this.shadowPaint != null
+                ? this.shadowPaint.hashCode() : 0);
+        temp = this.shadowXOffset != +0.0d
+                ? Double.doubleToLongBits(this.shadowXOffset) : 0L;
+        result = 29 * result + (int) (temp ^ (temp >>> 32));
+        temp = this.shadowYOffset != +0.0d
+                ? Double.doubleToLongBits(this.shadowYOffset) : 0L;
+        result = 29 * result + (int) (temp ^ (temp >>> 32));
+        result = 29 * result + (this.textBlock != null
+                ? this.textBlock.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Provides serialization support.
+     *
+     * @param stream  the output stream.
+     *
+     * @throws IOException  if there is an I/O error.
+     */
+    private void writeObject(final ObjectOutputStream stream)
+            throws IOException {
+        stream.defaultWriteObject();
+        SerialUtilities.writePaint(this.outlinePaint, stream);
+        SerialUtilities.writeStroke(this.outlineStroke, stream);
+        SerialUtilities.writePaint(this.backgroundPaint, stream);
+        SerialUtilities.writePaint(this.shadowPaint, stream);
+    }
+
+    /**
+     * Provides serialization support.
+     *
+     * @param stream  the input stream.
+     *
+     * @throws IOException  if there is an I/O error.
+     * @throws ClassNotFoundException  if there is a classpath problem.
+     */
+    private void readObject(final ObjectInputStream stream)
+        throws IOException, ClassNotFoundException {
+        stream.defaultReadObject();
+        this.outlinePaint = SerialUtilities.readPaint(stream);
+        this.outlineStroke = SerialUtilities.readStroke(stream);
+        this.backgroundPaint = SerialUtilities.readPaint(stream);
+        this.shadowPaint = SerialUtilities.readPaint(stream);
+    }
+
+
+}

+ 335 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextFragment.java

@@ -0,0 +1,335 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2013, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -----------------
+ * TextFragment.java
+ * -----------------
+ * (C) Copyright 2003-2013, by Object Refinery Limited and Contributors.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: TextFragment.java,v 1.13 2007/03/16 10:25:58 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 07-Nov-2003 : Version 1 (DG);
+ * 25-Nov-2003 : Fixed bug in the dimension calculation (DG);
+ * 22-Dec-2003 : Added workaround for Java bug 4245442 (DG);
+ * 29-Jan-2004 : Added paint attribute (DG);
+ * 22-Mar-2004 : Added equals() method and implemented Serializable (DG);
+ * 01-Apr-2004 : Changed java.awt.geom.Dimension2D to org.jfree.ui.Size2D 
+ *               because of JDK bug 4976448 which persists on JDK 1.3.1 (DG);
+ * 30-Sep-2004 : Moved drawRotatedString() from RefineryUtilities 
+ *               --> TextUtilities (DG);
+ * 16-Mar-2007 : Fixed serialization for GradientPaint (DG);
+ * 01-Sep-2013 : Take into account all TextAnchor offsets (DG);
+ * 
+ */
+ 
+package org.jfree.text;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.font.LineMetrics;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import org.jfree.io.SerialUtilities;
+import org.jfree.ui.Size2D;
+import org.jfree.ui.TextAnchor;
+import org.jfree.util.Log;
+import org.jfree.util.LogContext;
+
+/**
+ * A text item, with an associated font, that fits on a single line (see 
+ * {@link TextLine}).  Instances of the class are immutable.
+ */
+public class TextFragment implements Serializable {
+
+    /** For serialization. */
+    private static final long serialVersionUID = 4465945952903143262L;
+    
+    /** The default font. */
+    public static final Font DEFAULT_FONT = new Font("Serif", Font.PLAIN, 12);
+    
+    /** The default text color. */
+    public static final Paint DEFAULT_PAINT = Color.black;
+    
+    /** The text. */
+    private String text;
+    
+    /** The font. */
+    private Font font;
+    
+    /** The text color. */
+    private transient Paint paint;
+    
+    /** 
+     * The baseline offset (can be used to simulate subscripts and 
+     * superscripts). 
+     */
+    private float baselineOffset;
+    
+    /** Access to logging facilities. */
+    protected static final LogContext logger = Log.createContext(
+            TextFragment.class);
+    
+    /**
+     * Creates a new text fragment.
+     * 
+     * @param text  the text (<code>null</code> not permitted).
+     */
+    public TextFragment(final String text) {
+        this(text, DEFAULT_FONT, DEFAULT_PAINT);
+    }
+    
+    /**
+     * Creates a new text fragment.
+     * 
+     * @param text  the text (<code>null</code> not permitted).
+     * @param font  the font (<code>null</code> not permitted).
+     */
+    public TextFragment(final String text, final Font font) {
+        this(text, font, DEFAULT_PAINT);
+    }
+
+    /**
+     * Creates a new text fragment.
+     * 
+     * @param text  the text (<code>null</code> not permitted).
+     * @param font  the font (<code>null</code> not permitted).
+     * @param paint  the text color (<code>null</code> not permitted).
+     */
+    public TextFragment(final String text, final Font font, final Paint paint) {
+        this(text, font, paint, 0.0f);
+    }
+
+    /**
+     * Creates a new text fragment.
+     * 
+     * @param text  the text (<code>null</code> not permitted).
+     * @param font  the font (<code>null</code> not permitted).
+     * @param paint  the text color (<code>null</code> not permitted).
+     * @param baselineOffset  the baseline offset.
+     */
+    public TextFragment(final String text, final Font font, final Paint paint,
+                        final float baselineOffset) {
+        if (text == null) {
+            throw new IllegalArgumentException("Null 'text' argument.");  
+        }
+        if (font == null) {
+            throw new IllegalArgumentException("Null 'font' argument.");
+        }
+        if (paint == null) {
+            throw new IllegalArgumentException("Null 'paint' argument.");
+        }
+        this.text = text;
+        this.font = font;
+        this.paint = paint;
+        this.baselineOffset = baselineOffset;
+    }
+
+    /**
+     * Returns the text.
+     * 
+     * @return The text (possibly <code>null</code>).
+     */
+    public String getText() {
+        return this.text;
+    }
+    
+    /**
+     * Returns the font.
+     * 
+     * @return The font (never <code>null</code>).
+     */
+    public Font getFont() {
+        return this.font;
+    }
+    
+    /**
+     * Returns the text paint.
+     * 
+     * @return The text paint (never <code>null</code>).
+     */
+    public Paint getPaint() {
+        return this.paint;
+    }
+    
+    /**
+     * Returns the baseline offset.
+     * 
+     * @return The baseline offset.
+     */
+    public float getBaselineOffset() {
+        return this.baselineOffset;   
+    }
+    
+    /**
+     * Draws the text fragment.
+     * 
+     * @param g2  the graphics device.
+     * @param anchorX  the x-coordinate of the anchor point.
+     * @param anchorY  the y-coordinate of the anchor point.
+     * @param anchor  the location of the text that is aligned to the anchor 
+     *                point.
+     * @param rotateX  the x-coordinate of the rotation point.
+     * @param rotateY  the y-coordinate of the rotation point.
+     * @param angle  the angle.
+     */
+    public void draw(final Graphics2D g2, final float anchorX, 
+                     final float anchorY, final TextAnchor anchor,
+                     final float rotateX, final float rotateY, 
+                     final double angle) {
+    
+        g2.setFont(this.font);
+        g2.setPaint(this.paint);
+        TextUtilities.drawRotatedString(this.text, g2, anchorX, anchorY 
+                + this.baselineOffset, anchor, angle, rotateX, rotateY);
+    
+    }
+    
+    /**
+     * Calculates the dimensions of the text fragment.
+     * 
+     * @param g2  the graphics device.
+     * 
+     * @return The width and height of the text.
+     */
+    public Size2D calculateDimensions(final Graphics2D g2) {
+        final FontMetrics fm = g2.getFontMetrics(this.font);
+        final Rectangle2D bounds = TextUtilities.getTextBounds(this.text, g2, 
+                fm);
+        final Size2D result = new Size2D(bounds.getWidth(), bounds.getHeight());
+        return result;
+    }
+    
+    /**
+     * Calculates the vertical offset between the baseline and the specified 
+     * text anchor.
+     * 
+     * @param g2  the graphics device.
+     * @param anchor  the anchor.
+     * 
+     * @return the offset.
+     */
+    public float calculateBaselineOffset(Graphics2D g2, TextAnchor anchor) {
+        float result = 0.0f;
+        final FontMetrics fm = g2.getFontMetrics(this.font);
+        final LineMetrics lm = fm.getLineMetrics("ABCxyz", g2);
+        if (anchor.isTop()) {
+            result = lm.getAscent();
+        }
+        else if (anchor.isHalfAscent()) {
+            result = lm.getAscent() / 2.0f;
+        }
+        else if (anchor.isVerticalCenter()) {
+            result = lm.getAscent() / 2.0f - lm.getDescent() / 2.0f;
+        }
+        else if (anchor.isBottom()) {
+            result = -lm.getDescent() - lm.getLeading();
+        }
+        return result;                                             
+    }
+    
+    /**
+     * Tests this instance for equality with an arbitrary object.
+     * 
+     * @param obj  the object to test against (<code>null</code> permitted).
+     * 
+     * @return A boolean.
+     */
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;   
+        }
+        if (obj == this) {
+            return true;   
+        }
+        if (obj instanceof TextFragment) {
+            final TextFragment tf = (TextFragment) obj;
+            if (!this.text.equals(tf.text)) {
+                return false;   
+            }
+            if (!this.font.equals(tf.font)) {
+                return false;   
+            }
+            if (!this.paint.equals(tf.paint)) {
+                return false;   
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns a hash code for this object.
+     * 
+     * @return A hash code.
+     */
+    public int hashCode() {
+        int result;
+        result = (this.text != null ? this.text.hashCode() : 0);
+        result = 29 * result + (this.font != null ? this.font.hashCode() : 0);
+        result = 29 * result + (this.paint != null ? this.paint.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Provides serialization support.
+     *
+     * @param stream  the output stream.
+     *
+     * @throws IOException  if there is an I/O error.
+     */
+    private void writeObject(final ObjectOutputStream stream) 
+        throws IOException {
+        stream.defaultWriteObject();
+        SerialUtilities.writePaint(this.paint, stream);
+    }
+
+    /**
+     * Provides serialization support.
+     *
+     * @param stream  the input stream.
+     *
+     * @throws IOException  if there is an I/O error.
+     * @throws ClassNotFoundException  if there is a classpath problem.
+     */
+    private void readObject(final ObjectInputStream stream) 
+        throws IOException, ClassNotFoundException {
+        stream.defaultReadObject();
+        this.paint = SerialUtilities.readPaint(stream);
+    }
+   
+}

+ 279 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextLine.java

@@ -0,0 +1,279 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2013, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -------------
+ * TextLine.java
+ * -------------
+ * (C) Copyright 2003-2013, by Object Refinery Limited and Contributors.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: TextLine.java,v 1.13 2007/11/02 17:50:35 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 07-Nov-2003 : Version 1 (DG);
+ * 22-Dec-2003 : Added workaround for Java bug 4245442 (DG);
+ * 29-Jan-2004 : Added new constructor (DG);
+ * 22-Mar-2004 : Added equals() method and implemented Serializable (DG);
+ * 01-Apr-2004 : Changed java.awt.geom.Dimension2D to org.jfree.ui.Size2D 
+ *               because of JDK bug 4976448 which persists on JDK 1.3.1 (DG);
+ * 03-Sep-2004 : Added a method to remove a fragment (DG);
+ * 08-Jul-2005 : Fixed bug in calculateBaselineOffset() (DG);
+ * 01-Sep-2013 : Updated draw() method to take into account the textAnchor (DG);
+ *
+ */
+
+package org.jfree.text;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jfree.ui.Size2D;
+import org.jfree.ui.TextAnchor;
+
+/**
+ * A sequence of {@link TextFragment} objects that together form a line of 
+ * text.  A sequence of text lines is managed by the {@link TextBlock} class.
+ *
+ * @author David Gilbert
+ */
+public class TextLine implements Serializable {
+
+    /** For serialization. */
+    private static final long serialVersionUID = 7100085690160465444L;
+    
+    /** Storage for the text fragments that make up the line. */
+    private List fragments;
+
+    /**
+     * Creates a new empty line.
+     */
+    public TextLine() {
+        this.fragments = new java.util.ArrayList();
+    }
+    
+    /**
+     * Creates a new text line using the default font.
+     * 
+     * @param text  the text (<code>null</code> not permitted).
+     */
+    public TextLine(final String text) {
+        this(text, TextFragment.DEFAULT_FONT);   
+    }
+    
+    /**
+     * Creates a new text line.
+     * 
+     * @param text  the text (<code>null</code> not permitted).
+     * @param font  the text font (<code>null</code> not permitted).
+     */
+    public TextLine(final String text, final Font font) {
+        this.fragments = new java.util.ArrayList();
+        final TextFragment fragment = new TextFragment(text, font);
+        this.fragments.add(fragment);
+    }
+    
+    /**
+     * Creates a new text line.
+     * 
+     * @param text  the text (<code>null</code> not permitted).
+     * @param font  the text font (<code>null</code> not permitted).
+     * @param paint  the text color (<code>null</code> not permitted).
+     */
+    public TextLine(final String text, final Font font, final Paint paint) {
+        if (text == null) {
+            throw new IllegalArgumentException("Null 'text' argument.");   
+        }
+        if (font == null) {
+            throw new IllegalArgumentException("Null 'font' argument.");   
+        }
+        if (paint == null) {
+            throw new IllegalArgumentException("Null 'paint' argument.");   
+        }
+        this.fragments = new java.util.ArrayList();
+        final TextFragment fragment = new TextFragment(text, font, paint);
+        this.fragments.add(fragment);
+    }
+    
+    /**
+     * Adds a text fragment to the text line.
+     * 
+     * @param fragment  the text fragment (<code>null</code> not permitted).
+     */
+    public void addFragment(final TextFragment fragment) {
+        this.fragments.add(fragment);        
+    }
+    
+    /**
+     * Removes a fragment from the line.
+     * 
+     * @param fragment  the fragment to remove.
+     */
+    public void removeFragment(final TextFragment fragment) {
+        this.fragments.remove(fragment);
+    }
+    
+    /**
+     * Draws the text line.
+     * 
+     * @param g2  the graphics device.
+     * @param anchorX  the x-coordinate for the anchor point.
+     * @param anchorY  the y-coordinate for the anchor point.
+     * @param anchor  the point on the text line that is aligned to the anchor 
+     *                point.
+     * @param rotateX  the x-coordinate for the rotation point.
+     * @param rotateY  the y-coordinate for the rotation point.
+     * @param angle  the rotation angle (in radians).
+     */
+    public void draw(Graphics2D g2, float anchorX, float anchorY, 
+            TextAnchor anchor, float rotateX,  float rotateY, double angle) {
+    
+        Size2D dim = calculateDimensions(g2);
+        float xAdj = 0.0f;
+        if (anchor.isHorizontalCenter()) {
+            xAdj = (float) -dim.getWidth() / 2.0f;
+        }
+        else if (anchor.isRight()) {
+            xAdj = (float) -dim.getWidth();
+        }
+        float x = anchorX + xAdj;
+        final float yOffset = calculateBaselineOffset(g2, anchor);
+        final Iterator iterator = this.fragments.iterator();
+        while (iterator.hasNext()) {
+            final TextFragment fragment = (TextFragment) iterator.next();
+            final Size2D d = fragment.calculateDimensions(g2);
+            fragment.draw(g2, x, anchorY + yOffset, TextAnchor.BASELINE_LEFT, 
+                    rotateX, rotateY, angle);
+            x = x + (float) d.getWidth();
+        }
+    
+    }
+    
+    /**
+     * Calculates the width and height of the text line.
+     * 
+     * @param g2  the graphics device.
+     * 
+     * @return The width and height.
+     */
+    public Size2D calculateDimensions(final Graphics2D g2) {
+        double width = 0.0;
+        double height = 0.0;
+        final Iterator iterator = this.fragments.iterator();
+        while (iterator.hasNext()) {
+            final TextFragment fragment = (TextFragment) iterator.next();
+            final Size2D dimension = fragment.calculateDimensions(g2);
+            width = width + dimension.getWidth();
+            height = Math.max(height, dimension.getHeight());
+        }
+        return new Size2D(width, height);
+    }
+    
+    /**
+     * Returns the first text fragment in the line.
+     * 
+     * @return The first text fragment in the line.
+     */
+    public TextFragment getFirstTextFragment() {
+        TextFragment result = null;
+        if (this.fragments.size() > 0) {
+            result = (TextFragment) this.fragments.get(0);
+        }    
+        return result;
+    }
+    
+    /**
+     * Returns the last text fragment in the line.
+     * 
+     * @return The last text fragment in the line.
+     */
+    public TextFragment getLastTextFragment() {
+        TextFragment result = null;
+        if (this.fragments.size() > 0) {
+            result = (TextFragment) this.fragments.get(this.fragments.size() 
+                    - 1);
+        }    
+        return result;
+    }
+    
+    /**
+     * Calculate the offsets required to translate from the specified anchor 
+     * position to the left baseline position.
+     * 
+     * @param g2  the graphics device.
+     * @param anchor  the anchor position.
+     * 
+     * @return The offsets.
+     */
+    private float calculateBaselineOffset(final Graphics2D g2, 
+                                          final TextAnchor anchor) {
+        float result = 0.0f;
+        Iterator iterator = this.fragments.iterator();
+        while (iterator.hasNext()) {
+            TextFragment fragment = (TextFragment) iterator.next();
+            result = Math.max(result, 
+                    fragment.calculateBaselineOffset(g2, anchor));
+        }
+        return result;
+    }
+    
+    /**
+     * Tests this object for equality with an arbitrary object.
+     * 
+     * @param obj  the object to test against (<code>null</code> permitted).
+     * 
+     * @return A boolean.
+     */
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (obj == this) {
+            return true;   
+        }
+        if (obj instanceof TextLine) {
+            final TextLine line = (TextLine) obj;
+            return this.fragments.equals(line.fragments);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a hash code for this object.
+     * 
+     * @return A hash code.
+     */
+    public int hashCode() {
+        return (this.fragments != null ? this.fragments.hashCode() : 0);
+    }
+
+}

+ 64 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextMeasurer.java

@@ -0,0 +1,64 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -----------------
+ * TextMeasurer.java
+ * -----------------
+ * (C) Copyright 2004, 2005, by Object Refinery Limited and Contributors.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: TextMeasurer.java,v 1.4 2005/10/18 13:17:16 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jan-2004 : Version 1 (DG);
+ *
+ */
+
+package org.jfree.text;
+
+/**
+ * An object that can measure text.
+ *
+ * @author David Gilbert
+ */
+public interface TextMeasurer {
+
+    /**
+     * Calculates the width of a <code>String</code> in the current 
+     * <code>Graphics</code> context.
+     *
+     * @param text  the text.
+     * @param start  the start position of the substring to be measured.
+     * @param end  the position of the last character to be measured.
+     *
+     * @return The width of the string in Java2D units.
+     */
+    public float getStringWidth(String text, int start, int end);
+    
+}

+ 853 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/text/TextUtilities.java

@@ -0,0 +1,853 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2014, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * ------------------
+ * TextUtilities.java
+ * ------------------
+ * (C) Copyright 2004-2014, by Object Refinery Limited and Contributors.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   Brian Fischer;
+ *
+ * $Id: TextUtilities.java,v 1.27 2011/12/14 20:25:40 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jan-2004 : Version 1 (DG);
+ * 24-Mar-2004 : Added 'paint' argument to createTextBlock() method (DG);
+ * 07-Apr-2004 : Added getTextBounds() method and useFontMetricsGetStringBounds
+ *               flag (DG);
+ * 08-Apr-2004 : Changed word break iterator to line break iterator in the
+ *               createTextBlock() method - see bug report 926074 (DG);
+ * 03-Sep-2004 : Updated createTextBlock() method to add ellipses when limit
+ *               is reached (DG);
+ * 30-Sep-2004 : Modified bounds returned by drawAlignedString() method (DG);
+ * 10-Nov-2004 : Added new createTextBlock() method that works with
+ *               newlines (DG);
+ * 19-Apr-2005 : Changed default value of useFontMetricsGetStringBounds (DG);
+ * 17-May-2005 : createTextBlock() now recognises '\n' (DG);
+ * 27-Jun-2005 : Added code to getTextBounds() method to work around Sun's bug
+ *               parade item 6183356 (DG);
+ * 06-Jan-2006 : Reformatted (DG);
+ * 27-Apr-2009 : Fix text wrapping with new lines (DG);
+ * 27-Jul-2009 : Use AttributedString in drawRotatedString() (DG);
+ * 14-Dec-2011 : Fix for nextLineBreak() method - thanks to Brian Fischer (DG);
+ * 24-Oct-2013 : Update drawRotatedString() to use drawAlignedString() when 
+ *               the rotation angle is 0.0 (DG);
+ * 25-Oct-2013 : Added drawStringsWithFontAttributes flag (DG);
+ * 28-Feb-2014 : Fix endless loop in createTextBlock() (DG);
+ *
+ */
+
+package org.jfree.text;
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Shape;
+import java.awt.font.FontRenderContext;
+import java.awt.font.LineMetrics;
+import java.awt.font.TextLayout;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.text.AttributedString;
+import java.text.BreakIterator;
+
+import org.jfree.base.BaseBoot;
+import org.jfree.ui.TextAnchor;
+import org.jfree.util.Log;
+import org.jfree.util.LogContext;
+import org.jfree.util.ObjectUtilities;
+
+/**
+ * Some utility methods for working with text in Java2D.
+ */
+public class TextUtilities {
+
+    /** Access to logging facilities. */
+    protected static final LogContext logger = Log.createContext(
+            TextUtilities.class);
+
+    /**
+     * When this flag is set to <code>true</code>, strings will be drawn
+     * as attributed strings with the attributes taken from the current font.
+     * This allows for underlining, strike-out etc, but it means that
+     * TextLayout will be used to render the text:
+     * 
+     * http://www.jfree.org/phpBB2/viewtopic.php?p=45459&highlight=#45459
+     */
+    private static boolean drawStringsWithFontAttributes = false;
+    
+    /**
+     * A flag that controls whether or not the rotated string workaround is
+     * used.
+     */
+    private static boolean useDrawRotatedStringWorkaround;
+
+    /**
+     * A flag that controls whether the FontMetrics.getStringBounds() method
+     * is used or a workaround is applied.
+     */
+    private static boolean useFontMetricsGetStringBounds;
+
+    static {
+        try {
+            boolean isJava14 = ObjectUtilities.isJDK14();
+
+            String configRotatedStringWorkaround = BaseBoot.getInstance()
+                    .getGlobalConfig().getConfigProperty(
+                    "org.jfree.text.UseDrawRotatedStringWorkaround", "auto");
+            if (configRotatedStringWorkaround.equals("auto")) {
+                useDrawRotatedStringWorkaround = !isJava14;
+            }
+            else {
+                useDrawRotatedStringWorkaround
+                        = configRotatedStringWorkaround.equals("true");
+            }
+
+            String configFontMetricsStringBounds = BaseBoot.getInstance()
+                    .getGlobalConfig().getConfigProperty(
+                    "org.jfree.text.UseFontMetricsGetStringBounds", "auto");
+            if (configFontMetricsStringBounds.equals("auto")) {
+                useFontMetricsGetStringBounds = isJava14;
+            } else {
+               useFontMetricsGetStringBounds
+                      = configFontMetricsStringBounds.equals("true");
+            }
+        }
+        catch (Exception e) {
+            // ignore everything.
+            useDrawRotatedStringWorkaround = true;
+            useFontMetricsGetStringBounds = true;
+        }
+    }
+
+    /**
+     * Private constructor prevents object creation.
+     */
+    private TextUtilities() {
+        // prevent instantiation
+    }
+
+    /**
+     * Creates a {@link TextBlock} from a <code>String</code>.  Line breaks
+     * are added where the <code>String</code> contains '\n' characters.
+     *
+     * @param text  the text.
+     * @param font  the font.
+     * @param paint  the paint.
+     *
+     * @return A text block.
+     */
+    public static TextBlock createTextBlock(String text, Font font, 
+            Paint paint) {
+        if (text == null) {
+            throw new IllegalArgumentException("Null 'text' argument.");
+        }
+        TextBlock result = new TextBlock();
+        String input = text;
+        boolean moreInputToProcess = (text.length() > 0);
+        int start = 0;
+        while (moreInputToProcess) {
+            int index = input.indexOf("\n");
+            if (index > start) {
+                String line = input.substring(start, index);
+                if (index < input.length() - 1) {
+                    result.addLine(line, font, paint);
+                    input = input.substring(index + 1);
+                }
+                else {
+                    moreInputToProcess = false;
+                }
+            }
+            else if (index == start) {
+                if (index < input.length() - 1) {
+                    input = input.substring(index + 1);
+                }
+                else {
+                    moreInputToProcess = false;
+                }
+            }
+            else {
+                result.addLine(input, font, paint);
+                moreInputToProcess = false;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Creates a new text block from the given string, breaking the
+     * text into lines so that the <code>maxWidth</code> value is
+     * respected.
+     *
+     * @param text  the text.
+     * @param font  the font.
+     * @param paint  the paint.
+     * @param maxWidth  the maximum width for each line.
+     * @param measurer  the text measurer.
+     *
+     * @return A text block.
+     */
+    public static TextBlock createTextBlock(String text, Font font,
+            Paint paint, float maxWidth, TextMeasurer measurer) {
+
+        return createTextBlock(text, font, paint, maxWidth, Integer.MAX_VALUE,
+                measurer);
+    }
+
+    /**
+     * Creates a new text block from the given string, breaking the
+     * text into lines so that the <code>maxWidth</code> value is
+     * respected.
+     *
+     * @param text  the text.
+     * @param font  the font.
+     * @param paint  the paint.
+     * @param maxWidth  the maximum width for each line.
+     * @param maxLines  the maximum number of lines.
+     * @param measurer  the text measurer.
+     *
+     * @return A text block.
+     */
+    public static TextBlock createTextBlock(String text, Font font,
+            Paint paint, float maxWidth, int maxLines, TextMeasurer measurer) {
+
+        TextBlock result = new TextBlock();
+        BreakIterator iterator = BreakIterator.getLineInstance();
+        iterator.setText(text);
+        int current = 0;
+        int lines = 0;
+        int length = text.length();
+        while (current < length && lines < maxLines) {
+            int next = nextLineBreak(text, current, maxWidth, iterator,
+                    measurer);
+            if (next == BreakIterator.DONE) {
+                result.addLine(text.substring(current), font, paint);
+                return result;
+            } else if (next == current) {
+                next++; // we must take one more character or we'll loop forever
+            }
+            result.addLine(text.substring(current, next), font, paint);
+            lines++;
+            current = next;
+            while (current < text.length()&& text.charAt(current) == '\n') {
+                current++;
+            }
+        }
+        if (current < length) {
+            TextLine lastLine = result.getLastLine();
+            TextFragment lastFragment = lastLine.getLastTextFragment();
+            String oldStr = lastFragment.getText();
+            String newStr = "...";
+            if (oldStr.length() > 3) {
+                newStr = oldStr.substring(0, oldStr.length() - 3) + "...";
+            }
+
+            lastLine.removeFragment(lastFragment);
+            TextFragment newFragment = new TextFragment(newStr,
+                    lastFragment.getFont(), lastFragment.getPaint());
+            lastLine.addFragment(newFragment);
+        }
+        return result;
+    }
+
+    /**
+     * Returns the character index of the next line break.  If the next
+     * character is wider than <code>width</code> this method will return
+     * <code>start</code> - the caller should check for this case.
+     *
+     * @param text  the text (<code>null</code> not permitted).
+     * @param start  the start index.
+     * @param width  the target display width.
+     * @param iterator  the word break iterator.
+     * @param measurer  the text measurer.
+     *
+     * @return The index of the next line break.
+     */
+    private static int nextLineBreak(String text, int start, float width, 
+            BreakIterator iterator, TextMeasurer measurer) {
+
+        // this method is (loosely) based on code in JFreeReport's
+        // TextParagraph class
+        int current = start;
+        int end;
+        float x = 0.0f;
+        boolean firstWord = true;
+        int newline = text.indexOf('\n', start);
+        if (newline < 0) {
+            newline = Integer.MAX_VALUE;
+        }
+        while (((end = iterator.following(current)) != BreakIterator.DONE)) {
+            x += measurer.getStringWidth(text, current, end);
+            if (x > width) {
+                if (firstWord) {
+                    while (measurer.getStringWidth(text, start, end) > width) {
+                        end--;
+                        if (end <= start) {
+                            return end;
+                        }
+                    }
+                    return end;
+                }
+                else {
+                    end = iterator.previous();
+                    return end;
+                }
+            }
+            else {
+                if (end > newline) {
+                    return newline;
+                }
+            }
+            // we found at least one word that fits ...
+            firstWord = false;
+            current = end;
+        }
+        return BreakIterator.DONE;
+    }
+
+    /**
+     * Returns the bounds for the specified text.
+     *
+     * @param text  the text (<code>null</code> permitted).
+     * @param g2  the graphics context (not <code>null</code>).
+     * @param fm  the font metrics (not <code>null</code>).
+     *
+     * @return The text bounds (<code>null</code> if the <code>text</code>
+     *         argument is <code>null</code>).
+     */
+    public static Rectangle2D getTextBounds(String text, Graphics2D g2, 
+            FontMetrics fm) {
+
+        Rectangle2D bounds;
+        if (TextUtilities.useFontMetricsGetStringBounds) {
+            bounds = fm.getStringBounds(text, g2);
+            // getStringBounds() can return incorrect height for some Unicode
+            // characters...see bug parade 6183356, let's replace it with
+            // something correct
+            LineMetrics lm = fm.getFont().getLineMetrics(text,
+                    g2.getFontRenderContext());
+            bounds.setRect(bounds.getX(), bounds.getY(), bounds.getWidth(),
+                    lm.getHeight());
+        }
+        else {
+            double width = fm.stringWidth(text);
+            double height = fm.getHeight();
+            if (logger.isDebugEnabled()) {
+                logger.debug("Height = " + height);
+            }
+            bounds = new Rectangle2D.Double(0.0, -fm.getAscent(), width,
+                    height);
+        }
+        return bounds;
+    }
+
+    /**
+     * Draws a string such that the specified anchor point is aligned to the
+     * given (x, y) location.
+     *
+     * @param text  the text.
+     * @param g2  the graphics device.
+     * @param x  the x coordinate (Java 2D).
+     * @param y  the y coordinate (Java 2D).
+     * @param anchor  the anchor location.
+     *
+     * @return The text bounds (adjusted for the text position).
+     */
+    public static Rectangle2D drawAlignedString(String text, Graphics2D g2, 
+            float x, float y, TextAnchor anchor) {
+
+        Rectangle2D textBounds = new Rectangle2D.Double();
+        float[] adjust = deriveTextBoundsAnchorOffsets(g2, text, anchor,
+                textBounds);
+        // adjust text bounds to match string position
+        textBounds.setRect(x + adjust[0], y + adjust[1] + adjust[2],
+            textBounds.getWidth(), textBounds.getHeight());
+        if (!drawStringsWithFontAttributes) {
+            g2.drawString(text, x + adjust[0], y + adjust[1]);
+        } else {
+            AttributedString as = new AttributedString(text, 
+                    g2.getFont().getAttributes());
+            g2.drawString(as.getIterator(), x + adjust[0], y + adjust[1]);
+        }
+        return textBounds;
+    }
+
+    /**
+     * A utility method that calculates the anchor offsets for a string.
+     * Normally, the (x, y) coordinate for drawing text is a point on the
+     * baseline at the left of the text string.  If you add these offsets to
+     * (x, y) and draw the string, then the anchor point should coincide with
+     * the (x, y) point.
+     *
+     * @param g2  the graphics device (not <code>null</code>).
+     * @param text  the text.
+     * @param anchor  the anchor point.
+     * @param textBounds  the text bounds (if not <code>null</code>, this
+     *                    object will be updated by this method to match the
+     *                    string bounds).
+     *
+     * @return  The offsets.
+     */
+    private static float[] deriveTextBoundsAnchorOffsets(Graphics2D g2,
+            String text, TextAnchor anchor, Rectangle2D textBounds) {
+
+        float[] result = new float[3];
+        FontRenderContext frc = g2.getFontRenderContext();
+        Font f = g2.getFont();
+        FontMetrics fm = g2.getFontMetrics(f);
+        Rectangle2D bounds = TextUtilities.getTextBounds(text, g2, fm);
+        LineMetrics metrics = f.getLineMetrics(text, frc);
+        float ascent = metrics.getAscent();
+        result[2] = -ascent;
+        float halfAscent = ascent / 2.0f;
+        float descent = metrics.getDescent();
+        float leading = metrics.getLeading();
+        float xAdj = 0.0f;
+        float yAdj = 0.0f;
+
+        if (anchor.isHorizontalCenter()) {
+            xAdj = (float) -bounds.getWidth() / 2.0f;
+        }
+        else if (anchor.isRight()) {
+            xAdj = (float) -bounds.getWidth();
+        }
+
+        if (anchor.isTop()) {
+            yAdj = -descent - leading + (float) bounds.getHeight();
+        }
+        else if (anchor.isHalfAscent()) {
+            yAdj = halfAscent;
+        }
+        else if (anchor.isVerticalCenter()) {
+            yAdj = -descent - leading + (float) (bounds.getHeight() / 2.0);
+        }
+        else if (anchor.isBaseline()) {
+            yAdj = 0.0f;
+        }
+        else if (anchor.isBottom()) {
+            yAdj = -metrics.getDescent() - metrics.getLeading();
+        }
+        if (textBounds != null) {
+            textBounds.setRect(bounds);
+        }
+        result[0] = xAdj;
+        result[1] = yAdj;
+        return result;
+
+    }
+
+    /**
+     * A utility method for drawing rotated text.
+     * <P>
+     * A common rotation is -Math.PI/2 which draws text 'vertically' (with the
+     * top of the characters on the left).
+     *
+     * @param text  the text.
+     * @param g2  the graphics device.
+     * @param angle  the angle of the (clockwise) rotation (in radians).
+     * @param x  the x-coordinate.
+     * @param y  the y-coordinate.
+     */
+    public static void drawRotatedString(String text, Graphics2D g2,
+            double angle, float x, float y) {
+        drawRotatedString(text, g2, x, y, angle, x, y);
+    }
+
+    /**
+     * A utility method for drawing rotated text.
+     * <P>
+     * A common rotation is -Math.PI/2 which draws text 'vertically' (with the
+     * top of the characters on the left).
+     *
+     * @param text  the text.
+     * @param g2  the graphics device.
+     * @param textX  the x-coordinate for the text (before rotation).
+     * @param textY  the y-coordinate for the text (before rotation).
+     * @param angle  the angle of the (clockwise) rotation (in radians).
+     * @param rotateX  the point about which the text is rotated.
+     * @param rotateY  the point about which the text is rotated.
+     */
+    public static void drawRotatedString(String text, Graphics2D g2,
+            float textX, float textY, 
+            double angle, float rotateX, float rotateY) {
+
+        if ((text == null) || (text.equals(""))) {
+            return;
+        }
+        if (angle == 0.0) {
+            drawAlignedString(text, g2, textY, textY, TextAnchor.BASELINE_LEFT);
+            return;
+        }
+        
+        AffineTransform saved = g2.getTransform();
+        AffineTransform rotate = AffineTransform.getRotateInstance(
+                angle, rotateX, rotateY);
+        g2.transform(rotate);
+
+        if (useDrawRotatedStringWorkaround) {
+            // workaround for JDC bug ID 4312117 and others...
+            TextLayout tl = new TextLayout(text, g2.getFont(),
+                    g2.getFontRenderContext());
+            tl.draw(g2, textX, textY);
+        }
+        else {
+            if (!drawStringsWithFontAttributes) {
+                g2.drawString(text, textX, textY);
+            } else {
+                AttributedString as = new AttributedString(text, 
+                        g2.getFont().getAttributes());
+                g2.drawString(as.getIterator(), textX, textY);
+            }
+        }
+        g2.setTransform(saved);
+
+    }
+
+    /**
+     * Draws a string that is aligned by one anchor point and rotated about
+     * another anchor point.
+     *
+     * @param text  the text.
+     * @param g2  the graphics device.
+     * @param x  the x-coordinate for positioning the text.
+     * @param y  the y-coordinate for positioning the text.
+     * @param textAnchor  the text anchor.
+     * @param angle  the rotation angle.
+     * @param rotationX  the x-coordinate for the rotation anchor point.
+     * @param rotationY  the y-coordinate for the rotation anchor point.
+     */
+    public static void drawRotatedString(String text, Graphics2D g2, 
+            float x, float y, TextAnchor textAnchor, 
+            double angle, float rotationX, float rotationY) {
+
+        if (text == null || text.equals("")) {
+            return;
+        }
+        if (angle == 0.0) {
+            drawAlignedString(text, g2, x, y, textAnchor);
+        } else {
+            float[] textAdj = deriveTextBoundsAnchorOffsets(g2, text, 
+                    textAnchor);
+            drawRotatedString(text, g2, x + textAdj[0], y + textAdj[1], angle,
+                    rotationX, rotationY);
+        }
+    }
+
+    /**
+     * Draws a string that is aligned by one anchor point and rotated about
+     * another anchor point.
+     *
+     * @param text  the text.
+     * @param g2  the graphics device.
+     * @param x  the x-coordinate for positioning the text.
+     * @param y  the y-coordinate for positioning the text.
+     * @param textAnchor  the text anchor.
+     * @param angle  the rotation angle (in radians).
+     * @param rotationAnchor  the rotation anchor.
+     */
+    public static void drawRotatedString(String text, Graphics2D g2, 
+            float x, float y, TextAnchor textAnchor, 
+            double angle, TextAnchor rotationAnchor) {
+
+        if (text == null || text.equals("")) {
+            return;
+        }
+        if (angle == 0.0) {
+            drawAlignedString(text, g2, x, y, textAnchor);
+        } else {
+            float[] textAdj = deriveTextBoundsAnchorOffsets(g2, text, 
+                    textAnchor);
+            float[] rotateAdj = deriveRotationAnchorOffsets(g2, text, 
+                    rotationAnchor);
+            drawRotatedString(text, g2, x + textAdj[0], y + textAdj[1],
+                    angle, x + textAdj[0] + rotateAdj[0],
+                    y + textAdj[1] + rotateAdj[1]);
+        }
+    }
+
+    /**
+     * Returns a shape that represents the bounds of the string after the
+     * specified rotation has been applied.
+     *
+     * @param text  the text (<code>null</code> permitted).
+     * @param g2  the graphics device.
+     * @param x  the x coordinate for the anchor point.
+     * @param y  the y coordinate for the anchor point.
+     * @param textAnchor  the text anchor.
+     * @param angle  the angle.
+     * @param rotationAnchor  the rotation anchor.
+     *
+     * @return The bounds (possibly <code>null</code>).
+     */
+    public static Shape calculateRotatedStringBounds(String text, Graphics2D g2, 
+            float x, float y, TextAnchor textAnchor, 
+            double angle, TextAnchor rotationAnchor) {
+
+        if (text == null || text.equals("")) {
+            return null;
+        }
+        float[] textAdj = deriveTextBoundsAnchorOffsets(g2, text, textAnchor);
+        if (logger.isDebugEnabled()) {
+            logger.debug("TextBoundsAnchorOffsets = " + textAdj[0] + ", "
+                    + textAdj[1]);
+        }
+        float[] rotateAdj = deriveRotationAnchorOffsets(g2, text, 
+                rotationAnchor);
+        if (logger.isDebugEnabled()) {
+            logger.debug("RotationAnchorOffsets = " + rotateAdj[0] + ", "
+                    + rotateAdj[1]);
+        }
+        Shape result = calculateRotatedStringBounds(text, g2,
+                x + textAdj[0], y + textAdj[1], angle,
+                x + textAdj[0] + rotateAdj[0], y + textAdj[1] + rotateAdj[1]);
+        return result;
+        
+    }
+
+    /**
+     * A utility method that calculates the anchor offsets for a string.
+     * Normally, the (x, y) coordinate for drawing text is a point on the
+     * baseline at the left of the text string.  If you add these offsets to
+     * (x, y) and draw the string, then the anchor point should coincide with
+     * the (x, y) point.
+     *
+     * @param g2  the graphics device (not <code>null</code>).
+     * @param text  the text.
+     * @param anchor  the anchor point.
+     *
+     * @return  The offsets.
+     */
+    private static float[] deriveTextBoundsAnchorOffsets(Graphics2D g2,
+            String text, TextAnchor anchor) {
+
+        float[] result = new float[2];
+        FontRenderContext frc = g2.getFontRenderContext();
+        Font f = g2.getFont();
+        FontMetrics fm = g2.getFontMetrics(f);
+        Rectangle2D bounds = TextUtilities.getTextBounds(text, g2, fm);
+        LineMetrics metrics = f.getLineMetrics(text, frc);
+        float ascent = metrics.getAscent();
+        float halfAscent = ascent / 2.0f;
+        float descent = metrics.getDescent();
+        float leading = metrics.getLeading();
+        float xAdj = 0.0f;
+        float yAdj = 0.0f;
+
+        if (anchor.isHorizontalCenter()) {
+            xAdj = (float) -bounds.getWidth() / 2.0f;
+        }
+        else if (anchor.isRight()) {
+            xAdj = (float) -bounds.getWidth();
+        }
+
+        if (anchor.isTop()) {
+            yAdj = -descent - leading + (float) bounds.getHeight();
+        }
+        else if (anchor.isHalfAscent()) {
+            yAdj = halfAscent;
+        }
+        else if (anchor.isVerticalCenter()) {
+            yAdj = -descent - leading + (float) (bounds.getHeight() / 2.0);
+        }
+        else if (anchor.isBaseline()) {
+            yAdj = 0.0f;
+        }
+        else if (anchor.isBottom()) {
+            yAdj = -metrics.getDescent() - metrics.getLeading();
+        }
+        result[0] = xAdj;
+        result[1] = yAdj;
+        return result;
+
+    }
+
+    /**
+     * A utility method that calculates the rotation anchor offsets for a
+     * string.  These offsets are relative to the text starting coordinate
+     * (<code>BASELINE_LEFT</code>).
+     *
+     * @param g2  the graphics device.
+     * @param text  the text.
+     * @param anchor  the anchor point.
+     *
+     * @return The offsets.
+     */
+    private static float[] deriveRotationAnchorOffsets(Graphics2D g2,
+            String text, TextAnchor anchor) {
+
+        float[] result = new float[2];
+        FontRenderContext frc = g2.getFontRenderContext();
+        LineMetrics metrics = g2.getFont().getLineMetrics(text, frc);
+        FontMetrics fm = g2.getFontMetrics();
+        Rectangle2D bounds = TextUtilities.getTextBounds(text, g2, fm);
+        float ascent = metrics.getAscent();
+        float halfAscent = ascent / 2.0f;
+        float descent = metrics.getDescent();
+        float leading = metrics.getLeading();
+        float xAdj = 0.0f;
+        float yAdj = 0.0f;
+
+        if (anchor.isLeft()) {
+            xAdj = 0.0f;
+        }
+        else if (anchor.isHorizontalCenter()) {
+            xAdj = (float) bounds.getWidth() / 2.0f;
+        }
+        else if (anchor.isRight()) {
+            xAdj = (float) bounds.getWidth();
+        }
+
+        if (anchor.isTop()) {
+            yAdj = descent + leading - (float) bounds.getHeight();
+        }
+        else if (anchor.isVerticalCenter()) {
+            yAdj = descent + leading - (float) (bounds.getHeight() / 2.0);
+        }
+        else if (anchor.isHalfAscent()) {
+            yAdj = -halfAscent;
+        }
+        else if (anchor.isBaseline()) {
+            yAdj = 0.0f;
+        }
+        else if (anchor.isBottom()) {
+            yAdj = metrics.getDescent() + metrics.getLeading();
+        }
+        result[0] = xAdj;
+        result[1] = yAdj;
+        return result;
+
+    }
+
+    /**
+     * Returns a shape that represents the bounds of the string after the
+     * specified rotation has been applied.
+     *
+     * @param text  the text (<code>null</code> permitted).
+     * @param g2  the graphics device.
+     * @param textX  the x coordinate for the text.
+     * @param textY  the y coordinate for the text.
+     * @param angle  the angle.
+     * @param rotateX  the x coordinate for the rotation point.
+     * @param rotateY  the y coordinate for the rotation point.
+     *
+     * @return The bounds (<code>null</code> if <code>text</code> is
+     *         <code>null</code> or has zero length).
+     */
+    public static Shape calculateRotatedStringBounds(String text, Graphics2D g2,
+            float textX, float textY, double angle, float rotateX, 
+            float rotateY) {
+
+        if ((text == null) || (text.equals(""))) {
+            return null;
+        }
+        FontMetrics fm = g2.getFontMetrics();
+        Rectangle2D bounds = TextUtilities.getTextBounds(text, g2, fm);
+        AffineTransform translate = AffineTransform.getTranslateInstance(
+                textX, textY);
+        Shape translatedBounds = translate.createTransformedShape(bounds);
+        AffineTransform rotate = AffineTransform.getRotateInstance(
+                angle, rotateX, rotateY);
+        Shape result = rotate.createTransformedShape(translatedBounds);
+        return result;
+
+    }
+
+    /**
+     * Returns the flag that controls whether the FontMetrics.getStringBounds()
+     * method is used or not.  If you are having trouble with label alignment
+     * or positioning, try changing the value of this flag.
+     *
+     * @return A boolean.
+     */
+    public static boolean getUseFontMetricsGetStringBounds() {
+        return useFontMetricsGetStringBounds;
+    }
+
+    /**
+     * Sets the flag that controls whether the FontMetrics.getStringBounds()
+     * method is used or not.  If you are having trouble with label alignment
+     * or positioning, try changing the value of this flag.
+     *
+     * @param use  the flag.
+     */
+    public static void setUseFontMetricsGetStringBounds(boolean use) {
+        useFontMetricsGetStringBounds = use;
+    }
+
+    /**
+     * Returns the flag that controls whether or not a workaround is used for
+     * drawing rotated strings.
+     *
+     * @return A boolean.
+     */
+    public static boolean isUseDrawRotatedStringWorkaround() {
+        return useDrawRotatedStringWorkaround;
+    }
+ 
+    /**
+     * Sets the flag that controls whether or not a workaround is used for
+     * drawing rotated strings.  The related bug is on Sun's bug parade
+     * (id 4312117) and the workaround involves using a <code>TextLayout</code>
+     * instance to draw the text instead of calling the
+     * <code>drawString()</code> method in the <code>Graphics2D</code> class.
+     *
+     * @param use  the new flag value.
+     */
+    public static void setUseDrawRotatedStringWorkaround(boolean use) {
+        TextUtilities.useDrawRotatedStringWorkaround = use;
+    }
+    
+    /**
+     * Returns the flag that controls whether or not strings are drawn using
+     * the current font attributes (such as underlining, strikethrough etc).
+     * The default value is <code>false</code>.
+     * 
+     * @return A boolean. 
+     * 
+     * @since 1.0.21
+     */
+    public static boolean getDrawStringsWithFontAttributes() {
+        return TextUtilities.drawStringsWithFontAttributes;
+    }
+    
+    /**
+     * Sets the flag that controls whether or not strings are drawn using the
+     * current font attributes.  This is a hack to allow underlining of titles
+     * without big changes to the API.  See:
+     * http://www.jfree.org/phpBB2/viewtopic.php?p=45459&amp;highlight=#45459
+     * 
+     * @param b  the new flag value.
+     * 
+     * @since 1.0.21
+     */
+    public static void setDrawStringsWithFontAttributes(boolean b) {
+        TextUtilities.drawStringsWithFontAttributes = b;
+    }
+
+}

+ 6 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/text/package.html

@@ -0,0 +1,6 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+Utility classes relating to text.
+</body>
+</html>

+ 210 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/threads/ReaderWriterLock.java

@@ -0,0 +1,210 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ---------------------
+ * ReaderWriterLock.java
+ * ---------------------
+ *
+ * $Id: ReaderWriterLock.java,v 1.3 2005/10/18 13:18:34 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 29-Jan-2003 : Added standard header (DG);
+ *
+ */
+
+package org.jfree.threads;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * A reader-writer lock from "Java Threads" by Scott Oak and Henry Wong.
+ *
+ * @author Scott Oak and Henry Wong
+ */
+public class ReaderWriterLock {
+
+    /**
+     * A node for the waiting list.
+     *
+     * @author Scott Oak and Henry Wong
+     */
+    private static class ReaderWriterNode {
+
+        /** A reader. */
+        protected static final int READER = 0;
+
+        /** A writer. */
+        protected static final int WRITER = 1;
+
+        /** The thread. */
+        protected Thread t;
+
+        /** The state. */
+        protected int state;
+
+        /** The number of acquires.*/
+        protected int nAcquires;
+
+        /**
+         * Creates a new node.
+         *
+         * @param t  the thread.
+         * @param state  the state.
+         */
+        private ReaderWriterNode(final Thread t, final int state) {
+            this.t = t;
+            this.state = state;
+            this.nAcquires = 0;
+        }
+
+    }
+
+    /** The waiting threads. */
+    private ArrayList waiters;
+
+    /**
+     * Default constructor.
+     */
+    public ReaderWriterLock() {
+        this.waiters = new ArrayList();
+    }
+
+    /**
+     * Grab the read lock.
+     */
+    public synchronized void lockRead() {
+        final ReaderWriterNode node;
+        final Thread me = Thread.currentThread();
+        final int index = getIndex(me);
+        if (index == -1) {
+            node = new ReaderWriterNode(me, ReaderWriterNode.READER);
+            this.waiters.add(node);
+        }
+        else {
+            node = (ReaderWriterNode) this.waiters.get(index);
+        }
+        while (getIndex(me) > firstWriter()) {
+            try {
+                wait();
+            }
+            catch (Exception e) {
+                System.err.println("ReaderWriterLock.lockRead(): exception.");
+                System.err.print(e.getMessage());
+            }
+        }
+        node.nAcquires++;
+    }
+
+    /**
+     * Grab the write lock.
+     */
+    public synchronized void lockWrite() {
+        final ReaderWriterNode node;
+        final Thread me = Thread.currentThread();
+        final int index = getIndex(me);
+        if (index == -1) {
+            node = new ReaderWriterNode(me, ReaderWriterNode.WRITER);
+            this.waiters.add(node);
+        }
+        else {
+            node = (ReaderWriterNode) this.waiters.get(index);
+            if (node.state == ReaderWriterNode.READER) {
+                throw new IllegalArgumentException("Upgrade lock");
+            }
+            node.state = ReaderWriterNode.WRITER;
+        }
+        while (getIndex(me) != 0) {
+            try {
+                wait();
+            }
+            catch (Exception e) {
+                System.err.println("ReaderWriterLock.lockWrite(): exception.");
+                System.err.print(e.getMessage());
+            }
+        }
+        node.nAcquires++;
+    }
+
+    /**
+     * Unlock.
+     */
+    public synchronized void unlock() {
+
+        final ReaderWriterNode node;
+        final Thread me = Thread.currentThread();
+        final int index = getIndex(me);
+        if (index > firstWriter()) {
+            throw new IllegalArgumentException("Lock not held");
+        }
+        node = (ReaderWriterNode) this.waiters.get(index);
+        node.nAcquires--;
+        if (node.nAcquires == 0) {
+            this.waiters.remove(index);
+        }
+        notifyAll();
+    }
+
+    /**
+     * Returns the index of the first waiting writer.
+     *
+     * @return The index.
+     */
+    private int firstWriter() {
+        final Iterator e = this.waiters.iterator();
+        int index = 0;
+        while (e.hasNext()) {
+            final ReaderWriterNode node = (ReaderWriterNode) e.next();
+            if (node.state == ReaderWriterNode.WRITER) {
+                return index;
+            }
+            index += 1;
+        }
+        return Integer.MAX_VALUE;
+    }
+
+    /**
+     * Returns the index of a thread.
+     *
+     * @param t  the thread.
+     *
+     * @return The index.
+     */
+    private int getIndex(final Thread t) {
+        final Iterator e = this.waiters.iterator();
+        int index = 0;
+        while (e.hasNext()) {
+            final ReaderWriterNode node = (ReaderWriterNode) e.next();
+            if (node.t == t) {
+                return index;
+            }
+            index += 1;
+        }
+        return -1;
+    }
+
+}

+ 6 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/threads/package.html

@@ -0,0 +1,6 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+Additional support for multi-threaded programs.
+</body>
+</html>

+ 164 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/Align.java

@@ -0,0 +1,164 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ----------
+ * Align.java
+ * ----------
+ * (C) Copyright 2000-2004, by Object Refinery Limited and Contributors.
+ *
+ * Original Author:  Christian W. Zuckschwerdt;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: Align.java,v 1.5 2005/10/18 13:18:34 mungady Exp $
+ *
+ * Changes (from 30-May-2002)
+ * --------------------------
+ * 30-May-2002 : Added title (DG);
+ * 13-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ *
+ */
+
+package org.jfree.ui;
+
+import java.awt.geom.Rectangle2D;
+
+/**
+ * A utility class for aligning rectangles.
+ *
+ * @author David Gilbert
+ */
+public final class Align {
+
+    /** Center alignment. */
+    public static final int CENTER = 0x00;
+
+    /** Top alignment. */
+    public static final int TOP = 0x01;
+
+    /** Bottom alignment. */
+    public static final int BOTTOM = 0x02;
+
+    /** Left alignment. */
+    public static final int LEFT = 0x04;
+
+    /** Right alignment. */
+    public static final int RIGHT = 0x08;
+
+    /** Top/Left alignment. */
+    public static final int TOP_LEFT = TOP | LEFT;
+
+    /** Top/Right alignment. */
+    public static final int TOP_RIGHT = TOP | RIGHT;
+
+    /** Bottom/Left alignment. */
+    public static final int BOTTOM_LEFT = BOTTOM | LEFT;
+
+    /** Bottom/Right alignment. */
+    public static final int BOTTOM_RIGHT = BOTTOM | RIGHT;
+
+    /** Horizontal fit. */
+    public static final int FIT_HORIZONTAL = LEFT | RIGHT;
+
+    /** Vertical fit. */
+    public static final int FIT_VERTICAL = TOP | BOTTOM;
+
+    /** Complete fit. */
+    public static final int FIT = FIT_HORIZONTAL | FIT_VERTICAL;
+
+    /** North alignment (same as TOP). */
+    public static final int NORTH = TOP;
+
+    /** South alignment (same as BOTTOM). */
+    public static final int SOUTH = BOTTOM;
+
+    /** West alignment (same as LEFT). */
+    public static final int WEST = LEFT;
+
+    /** East alignment (same as RIGHT). */
+    public static final int EAST = RIGHT;
+
+    /** North/West alignment (same as TOP_LEFT). */
+    public static final int NORTH_WEST = NORTH | WEST;
+
+    /** North/East alignment (same as TOP_RIGHT). */
+    public static final int NORTH_EAST = NORTH | EAST;
+
+    /** South/West alignment (same as BOTTOM_LEFT). */
+    public static final int SOUTH_WEST = SOUTH | WEST;
+
+    /** South/East alignment (same as BOTTOM_RIGHT). */
+    public static final int SOUTH_EAST = SOUTH | EAST;
+
+    /**
+     * Private constructor.
+     */
+    private Align() { 
+        super();
+    }
+    
+    /**
+     * Aligns one rectangle (<code>rect</code>) relative to another rectangle (<code>frame</code>).
+     *
+     * @param rect  the rectangle to be aligned (<code>null</code> not permitted).
+     * @param frame  the reference frame (<code>null</code> not permitted).
+     * @param align  the alignment code.
+     */
+    public static void align(final Rectangle2D rect, final Rectangle2D frame, final int align) {
+
+        double x = frame.getCenterX() - rect.getWidth() / 2.0;
+        double y = frame.getCenterY() - rect.getHeight() / 2.0;
+        double w = rect.getWidth();
+        double h = rect.getHeight();
+
+        if ((align & FIT_VERTICAL) == FIT_VERTICAL) {
+            h = frame.getHeight();
+        }
+
+        if ((align & FIT_HORIZONTAL) == FIT_HORIZONTAL) {
+            w = frame.getWidth();
+        }
+
+        if ((align & TOP) == TOP) {
+            y = frame.getMinY();
+        }
+
+        if ((align & BOTTOM) == BOTTOM) {
+            y = frame.getMaxY() - h;
+        }
+
+        if ((align & LEFT) == LEFT) {
+            x = frame.getX();
+        }
+
+        if ((align & RIGHT) == RIGHT) {
+            x = frame.getMaxX() - w;
+        }
+
+        rect.setRect(x, y, w, h);
+
+    }
+
+}

+ 135 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/ApplicationFrame.java

@@ -0,0 +1,135 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ---------------------
+ * ApplicationFrame.java
+ * ---------------------
+ * (C) Copyright 2000-2004, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: ApplicationFrame.java,v 1.5 2007/11/02 17:50:36 taqua Exp $
+ *
+ * Changes (from 30-May-2002)
+ * --------------------------
+ * 30-May-2002 : Added title (DG);
+ * 13-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ *
+ */
+
+package org.jfree.ui;
+
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import javax.swing.JFrame;
+
+/**
+ * A base class for creating the main frame for simple applications.  The frame listens for
+ * window closing events, and responds by shutting down the JVM.  This is OK for small demo
+ * applications...for more serious applications, you'll want to use something more robust.
+ *
+ * @author David Gilbert
+ */
+public class ApplicationFrame extends JFrame implements WindowListener {
+
+    /**
+     * Constructs a new application frame.
+     *
+     * @param title  the frame title.
+     */
+    public ApplicationFrame(final String title) {
+        super(title);
+        addWindowListener(this);
+    }
+
+    /**
+     * Listens for the main window closing, and shuts down the application.
+     *
+     * @param event  information about the window event.
+     */
+    public void windowClosing(final WindowEvent event) {
+        if (event.getWindow() == this) {
+            dispose();
+            System.exit(0);
+        }
+    }
+
+    /**
+     * Required for WindowListener interface, but not used by this class.
+     *
+     * @param event  information about the window event.
+     */
+    public void windowClosed(final WindowEvent event) {
+        // ignore
+    }
+
+    /**
+     * Required for WindowListener interface, but not used by this class.
+     *
+     * @param event  information about the window event.
+     */
+    public void windowActivated(final WindowEvent event) {
+        // ignore
+    }
+
+    /**
+     * Required for WindowListener interface, but not used by this class.
+     *
+     * @param event  information about the window event.
+     */
+    public void windowDeactivated(final WindowEvent event) {
+        // ignore
+    }
+
+    /**
+     * Required for WindowListener interface, but not used by this class.
+     *
+     * @param event  information about the window event.
+     */
+    public void windowDeiconified(final WindowEvent event) {
+        // ignore
+    }
+
+    /**
+     * Required for WindowListener interface, but not used by this class.
+     *
+     * @param event  information about the window event.
+     */
+    public void windowIconified(final WindowEvent event) {
+        // ignore
+    }
+
+    /**
+     * Required for WindowListener interface, but not used by this class.
+     *
+     * @param event  information about the window event.
+     */
+    public void windowOpened(final WindowEvent event) {
+        // ignore
+    }
+
+}

+ 146 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/ArrowPanel.java

@@ -0,0 +1,146 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ---------------
+ * ArrowPanel.java
+ * ---------------
+ * (C) Copyright 2002-2004, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: ArrowPanel.java,v 1.6 2007/11/02 17:50:36 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 25-Sep-2002 : Version 1 (DG);
+ * 13-Oct-2002 : Added Javadocs (DG);
+ *
+ */
+
+package org.jfree.ui;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Insets;
+import java.awt.Polygon;
+import java.awt.Shape;
+import java.awt.geom.Rectangle2D;
+import javax.swing.JPanel;
+
+/**
+ * A basic panel that displays a small up or down arrow.
+ *
+ * @author David Gilbert
+ */
+public class ArrowPanel extends JPanel {
+
+    /** A constant for the up arrow. */
+    public static final int UP = 0;
+
+    /** A constant for the down arrow. */
+    public static final int DOWN = 1;
+
+    /** The arrow type. */
+    private int type = UP;
+
+    /** The available area. */
+    private Rectangle2D available = new Rectangle2D.Float();
+
+    /**
+     * Creates a new arrow panel.
+     *
+     * @param type  the arrow type.
+     */
+    public ArrowPanel(final int type) {
+        this.type = type;
+        setPreferredSize(new Dimension(14, 9));
+    }
+
+    /**
+     * Paints the arrow panel.
+     *
+     * @param g  the graphics device for drawing on.
+     */
+    public void paintComponent(final Graphics g) {
+
+        super.paintComponent(g);
+        final Graphics2D g2 = (Graphics2D) g;
+
+        // first determine the size of the drawing area...
+        final Dimension size = getSize();
+        final Insets insets = getInsets();
+        this.available.setRect(insets.left, insets.top,
+                               size.getWidth() - insets.left - insets.right,
+                               size.getHeight() - insets.top - insets.bottom);
+        g2.translate(insets.left, insets.top);
+        g2.fill(getArrow(this.type));
+
+    }
+
+    /**
+     * Returns a shape for the arrow.
+     *
+     * @param t  the arrow type.
+     *
+     * @return the arrow shape.
+     */
+    private Shape getArrow(final int t) {
+        switch (t) {
+            case UP : return getUpArrow();
+            case DOWN : return getDownArrow();
+            default : return getUpArrow();
+        }
+    }
+
+    /**
+     * Returns an up arrow.
+     *
+     * @return an up arrow.
+     */
+    private Shape getUpArrow() {
+        final Polygon result = new Polygon();
+        result.addPoint(7, 2);
+        result.addPoint(2, 7);
+        result.addPoint(12, 7);
+        return result;
+    }
+
+    /**
+     * Returns a down arrow.
+     *
+     * @return a down arrow.
+     */
+    private Shape getDownArrow() {
+        final Polygon result = new Polygon();
+        result.addPoint(7, 7);
+        result.addPoint(2, 2);
+        result.addPoint(12, 2);
+        return result;
+    }
+
+}

+ 274 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/BevelArrowIcon.java

@@ -0,0 +1,274 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -------------------
+ * BevelArrowIcon.java
+ * -------------------
+ * (C) Copyright 2000-2004, by Nobuo Tamemasa and Contributors.
+ *
+ * Original Author:  Nobuo Tamemasa;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: BevelArrowIcon.java,v 1.5 2007/11/02 17:50:36 taqua Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 26-Oct-2001 : Changed package to com.jrefinery.ui.*;
+ * 13-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ *
+ */
+
+package org.jfree.ui;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import javax.swing.Icon;
+import javax.swing.UIManager;
+
+/**
+ * An arrow icon that can point up or down (usually used to indicate the sort direction in a table).
+ * <P>
+ * This class (and also SortButtonRenderer) is based on original code by Nobuo Tamemasa (version
+ * 1.0, 26-Feb-1999) posted on www.codeguru.com.
+ *
+ * @author Nobuo Tamemasa
+ */
+public class BevelArrowIcon implements Icon {
+
+    /** Constant indicating that the arrow is pointing up. */
+    public static final int UP = 0;
+
+    /** Constant indicating that the arrow is pointing down. */
+    public static final int DOWN = 1;
+
+    /** The default arrow size. */
+    private static final int DEFAULT_SIZE = 11;
+
+    /** Edge color 1. */
+    private Color edge1;
+
+    /** Edge color 2. */
+    private Color edge2;
+
+    /** The fill color for the arrow icon. */
+    private Color fill;
+
+    /** The size of the icon. */
+    private int size;
+
+    /** The direction that the arrow is pointing (UP or DOWN). */
+    private int direction;
+
+    /**
+     * Standard constructor - builds an icon with the specified attributes.
+     *
+     * @param direction .
+     * @param isRaisedView .
+     * @param isPressedView .
+     */
+    public BevelArrowIcon(final int direction, 
+                          final boolean isRaisedView, 
+                          final boolean isPressedView) {
+        if (isRaisedView) {
+            if (isPressedView) {
+                init(UIManager.getColor("controlLtHighlight"),
+                     UIManager.getColor("controlDkShadow"),
+                     UIManager.getColor("controlShadow"),
+                     DEFAULT_SIZE, direction);
+            }
+            else {
+                init(UIManager.getColor("controlHighlight"),
+                     UIManager.getColor("controlShadow"),
+                     UIManager.getColor("control"),
+                     DEFAULT_SIZE, direction);
+            }
+        }
+        else {
+            if (isPressedView) {
+                init(UIManager.getColor("controlDkShadow"),
+                     UIManager.getColor("controlLtHighlight"),
+                     UIManager.getColor("controlShadow"),
+                     DEFAULT_SIZE, direction);
+            }
+            else {
+                init(UIManager.getColor("controlShadow"),
+                     UIManager.getColor("controlHighlight"),
+                     UIManager.getColor("control"),
+                     DEFAULT_SIZE, direction);
+            }
+        }
+    }
+
+    /**
+     * Standard constructor - builds an icon with the specified attributes.
+     *
+     * @param edge1  the color of edge1.
+     * @param edge2  the color of edge2.
+     * @param fill  the fill color.
+     * @param size  the size of the arrow icon.
+     * @param direction  the direction that the arrow points.
+     */
+    public BevelArrowIcon(final Color edge1, 
+                          final Color edge2, 
+                          final Color fill, 
+                          final int size, 
+                          final int direction) {
+        init(edge1, edge2, fill, size, direction);
+    }
+
+    /**
+     * Paints the icon at the specified position.  Supports the Icon interface.
+     *
+     * @param c .
+     * @param g .
+     * @param x .
+     * @param y .
+     */
+    public void paintIcon(final Component c, 
+                          final Graphics g, 
+                          final int x, 
+                          final int y) {
+        switch (this.direction) {
+            case DOWN: drawDownArrow(g, x, y); break;
+            case   UP: drawUpArrow(g, x, y);   break;
+        }
+    }
+
+    /**
+     * Returns the width of the icon.  Supports the Icon interface.
+     *
+     * @return the icon width.
+     */
+    public int getIconWidth() {
+        return this.size;
+    }
+
+    /**
+     * Returns the height of the icon.  Supports the Icon interface.
+     * @return the icon height.
+     */
+    public int getIconHeight() {
+        return this.size;
+    }
+
+    /**
+     * Initialises the attributes of the arrow icon.
+     *
+     * @param edge1  the color of edge1.
+     * @param edge2  the color of edge2.
+     * @param fill  the fill color.
+     * @param size  the size of the arrow icon.
+     * @param direction  the direction that the arrow points.
+     */
+    private void init(final Color edge1, 
+                      final Color edge2, 
+                      final Color fill, 
+                      final int size, 
+                      final int direction) {
+        this.edge1 = edge1;
+        this.edge2 = edge2;
+        this.fill = fill;
+        this.size = size;
+        this.direction = direction;
+    }
+
+    /**
+     * Draws the arrow pointing down.
+     *
+     * @param g  the graphics device.
+     * @param xo  ??
+     * @param yo  ??
+     */
+    private void drawDownArrow(final Graphics g, final int xo, final int yo) {
+        g.setColor(this.edge1);
+        g.drawLine(xo, yo,   xo + this.size - 1, yo);
+        g.drawLine(xo, yo + 1, xo + this.size - 3, yo + 1);
+        g.setColor(this.edge2);
+        g.drawLine(xo + this.size - 2, yo + 1, xo + this.size - 1, yo + 1);
+        int x = xo + 1;
+        int y = yo + 2;
+        int dx = this.size - 6;
+        while (y + 1 < yo + this.size) {
+            g.setColor(this.edge1);
+            g.drawLine(x, y,   x + 1, y);
+            g.drawLine(x, y + 1, x + 1, y + 1);
+            if (0 < dx) {
+                g.setColor(this.fill);
+                g.drawLine(x + 2, y,   x + 1 + dx, y);
+                g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
+            }
+            g.setColor(this.edge2);
+            g.drawLine(x + dx + 2, y,   x + dx + 3, y);
+            g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
+            x += 1;
+            y += 2;
+            dx -= 2;
+        }
+        g.setColor(this.edge1);
+        g.drawLine(
+            xo + (this.size / 2), yo + this.size - 1, xo + (this.size / 2), yo + this.size - 1
+        );
+    }
+
+    /**
+     * Draws the arrow pointing up.
+     *
+     * @param g  the graphics device.
+     * @param xo  ??
+     * @param yo  ??
+     */
+    private void drawUpArrow(final Graphics g, final int xo, final int yo) {
+        g.setColor(this.edge1);
+        int x = xo + (this.size / 2);
+        g.drawLine(x, yo, x, yo);
+        x--;
+        int y = yo + 1;
+        int dx = 0;
+        while (y + 3 < yo + this.size) {
+            g.setColor(this.edge1);
+            g.drawLine(x, y,   x + 1, y);
+            g.drawLine(x, y + 1, x + 1, y + 1);
+            if (0 < dx) {
+                g.setColor(this.fill);
+                g.drawLine(x + 2, y,   x + 1 + dx, y);
+                g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
+            }
+            g.setColor(this.edge2);
+            g.drawLine(x + dx + 2, y,   x + dx + 3, y);
+            g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
+            x -= 1;
+            y += 2;
+            dx += 2;
+        }
+        g.setColor(this.edge1);
+        g.drawLine(xo, yo + this.size - 3,   xo + 1, yo + this.size - 3);
+        g.setColor(this.edge2);
+        g.drawLine(xo + 2, yo + this.size - 2, xo + this.size - 1, yo + this.size - 2);
+        g.drawLine(xo, yo + this.size - 1, xo + this.size, yo + this.size - 1);
+    }
+
+}

+ 113 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/DateCellRenderer.java

@@ -0,0 +1,113 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ---------------------
+ * DateCellRenderer.java
+ * ---------------------
+ * (C) Copyright 2003, 2004, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: DateCellRenderer.java,v 1.7 2007/11/02 17:50:36 taqua Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 24-Jul-2003 : Version 1 (DG);
+ *
+ */
+
+package org.jfree.ui;
+
+import java.awt.Component;
+import java.text.DateFormat;
+import javax.swing.JTable;
+import javax.swing.SwingConstants;
+import javax.swing.table.DefaultTableCellRenderer;
+
+/**
+ * A table cell renderer that formats dates.
+ *
+ * @author David Gilbert
+ */
+public class DateCellRenderer extends DefaultTableCellRenderer {
+
+    /** The formatter. */
+    private DateFormat formatter;
+    
+    /**
+     * Default constructor.
+     */
+    public DateCellRenderer() {
+        this(DateFormat.getDateTimeInstance());
+    }
+    
+    /**
+     * Creates a new renderer.
+     * 
+     * @param formatter  the formatter.
+     */
+    public DateCellRenderer(final DateFormat formatter) {
+        super();
+        this.formatter = formatter;
+        setHorizontalAlignment(SwingConstants.CENTER);
+    }
+
+    /**
+     * Returns itself as the renderer. Supports the TableCellRenderer interface.
+     *
+     * @param table  the table.
+     * @param value  the data to be rendered.
+     * @param isSelected  a boolean that indicates whether or not the cell is 
+     *                    selected.
+     * @param hasFocus  a boolean that indicates whether or not the cell has 
+     *                  the focus.
+     * @param row  the (zero-based) row index.
+     * @param column  the (zero-based) column index.
+     *
+     * @return the component that can render the contents of the cell.
+     */
+    public Component getTableCellRendererComponent(final JTable table, 
+            final Object value, final boolean isSelected, 
+            final boolean hasFocus, final int row, final int column) {
+
+        setFont(null);
+        if (value != null) {
+          setText(this.formatter.format(value));
+        }
+        else {
+          setText("");
+        }
+        if (isSelected) {
+            setBackground(table.getSelectionBackground());
+        }
+        else {
+            setBackground(null);
+        }
+        return this;
+    }
+
+}

+ 553 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/DateChooserPanel.java

@@ -0,0 +1,553 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ---------------------
+ * DateChooserPanel.java
+ * ---------------------
+ * (C) Copyright 2000-2004, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: DateChooserPanel.java,v 1.11 2007/11/02 17:50:36 taqua Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 26-Oct-2001 : Changed package to com.jrefinery.ui.* (DG);
+ * 08-Dec-2001 : Dropped the getMonths() method (DG);
+ * 13-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ * 02-Nov-2005 : Fixed a bug where the current day-of-the-month is past
+ *               the end of the newly selected month when the month or year
+ *               combo boxes are changed - see bug id 1344319 (DG);
+ *
+ */
+
+package org.jfree.ui;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.text.DateFormatSymbols;
+import java.util.Calendar;
+import java.util.Date;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
+
+import org.jfree.date.SerialDate;
+
+/**
+ * A panel that allows the user to select a date.
+ *
+ * @author David Gilbert
+ */
+public class DateChooserPanel extends JPanel implements ActionListener {
+
+    /**
+     * The date selected in the panel.
+     */
+    private Calendar chosenDate;
+
+    /**
+     * The color for the selected date.
+     */
+    private Color chosenDateButtonColor;
+
+    /**
+     * The color for dates in the current month.
+     */
+    private Color chosenMonthButtonColor;
+
+    /**
+     * The color for dates that are visible, but not in the current month.
+     */
+    private Color chosenOtherButtonColor;
+
+    /**
+     * The first day-of-the-week.
+     */
+    private int firstDayOfWeek;
+
+    /**
+     * The range used for selecting years.
+     */
+    private int yearSelectionRange = 20;
+
+    /**
+     * The font used to display the date.
+     */
+    private Font dateFont = new Font("SansSerif", Font.PLAIN, 10);
+
+    /**
+     * A combo for selecting the month.
+     */
+    private JComboBox monthSelector;
+
+    /**
+     * A combo for selecting the year.
+     */
+    private JComboBox yearSelector;
+
+    /**
+     * A button for selecting today's date.
+     */
+    private JButton todayButton;
+
+    /**
+     * An array of buttons used to display the days-of-the-month.
+     */
+    private JButton[] buttons;
+
+    /**
+     * A flag that indicates whether or not we are currently refreshing the 
+     * buttons.
+     */
+    private boolean refreshing = false;
+
+    /**
+     * The ordered set of all seven days of a week,
+     * beginning with the 'firstDayOfWeek'.
+     */
+    private int[] WEEK_DAYS;
+
+    /**
+     * Constructs a new date chooser panel, using today's date as the initial 
+     * selection.
+     */
+    public DateChooserPanel() {
+        this(Calendar.getInstance(), false);
+    }
+
+    /**
+     * Constructs a new date chooser panel.
+     *
+     * @param calendar     the calendar controlling the date.
+     * @param controlPanel a flag that indicates whether or not the 'today' 
+     *                     button should appear on the panel.
+     */
+    public DateChooserPanel(final Calendar calendar, 
+                            final boolean controlPanel) {
+
+        super(new BorderLayout());
+
+        this.chosenDateButtonColor = UIManager.getColor("textHighlight");
+        this.chosenMonthButtonColor = UIManager.getColor("control");
+        this.chosenOtherButtonColor = UIManager.getColor("controlShadow");
+
+        // the default date is today...
+        this.chosenDate = calendar;
+        this.firstDayOfWeek = calendar.getFirstDayOfWeek();
+        this.WEEK_DAYS = new int[7];
+        for (int i = 0; i < 7; i++) {
+            this.WEEK_DAYS[i] = ((this.firstDayOfWeek + i - 1) % 7) + 1;
+        }
+
+        add(constructSelectionPanel(), BorderLayout.NORTH);
+        add(getCalendarPanel(), BorderLayout.CENTER);
+        if (controlPanel) {
+            add(constructControlPanel(), BorderLayout.SOUTH);
+        }
+        setDate(calendar.getTime());
+    }
+
+    /**
+     * Sets the date chosen in the panel.
+     *
+     * @param theDate the new date.
+     */
+    public void setDate(final Date theDate) {
+
+        this.chosenDate.setTime(theDate);
+        this.monthSelector.setSelectedIndex(this.chosenDate.get(
+                Calendar.MONTH));
+        refreshYearSelector();
+        refreshButtons();
+
+    }
+
+    /**
+     * Returns the date selected in the panel.
+     *
+     * @return the selected date.
+     */
+    public Date getDate() {
+        return this.chosenDate.getTime();
+    }
+
+    /**
+     * Handles action-events from the date panel.
+     *
+     * @param e information about the event that occurred.
+     */
+    public void actionPerformed(final ActionEvent e) {
+
+        if (e.getActionCommand().equals("monthSelectionChanged")) {
+            final JComboBox c = (JComboBox) e.getSource();
+            
+            // In most cases, changing the month will not change the selected
+            // day.  But if the selected day is 29, 30 or 31 and the newly
+            // selected month doesn't have that many days, we revert to the 
+            // last day of the newly selected month...
+            int dayOfMonth = this.chosenDate.get(Calendar.DAY_OF_MONTH);
+            this.chosenDate.set(Calendar.DAY_OF_MONTH, 1);
+            this.chosenDate.set(Calendar.MONTH, c.getSelectedIndex());
+            int maxDayOfMonth = this.chosenDate.getActualMaximum(
+                    Calendar.DAY_OF_MONTH);
+            this.chosenDate.set(Calendar.DAY_OF_MONTH, Math.min(dayOfMonth, 
+                    maxDayOfMonth));
+            refreshButtons();
+        }
+        else if (e.getActionCommand().equals("yearSelectionChanged")) {
+            if (!this.refreshing) {
+                final JComboBox c = (JComboBox) e.getSource();
+                final Integer y = (Integer) c.getSelectedItem();
+                
+                // in most cases, changing the year will not change the 
+                // selected day.  But if the selected day is Feb 29, and the
+                // newly selected year is not a leap year, we revert to 
+                // Feb 28...
+                int dayOfMonth = this.chosenDate.get(Calendar.DAY_OF_MONTH);
+                this.chosenDate.set(Calendar.DAY_OF_MONTH, 1);
+                this.chosenDate.set(Calendar.YEAR, y.intValue());
+                int maxDayOfMonth = this.chosenDate.getActualMaximum(
+                    Calendar.DAY_OF_MONTH);
+                this.chosenDate.set(Calendar.DAY_OF_MONTH, Math.min(dayOfMonth, 
+                    maxDayOfMonth));
+                refreshYearSelector();
+                refreshButtons();
+            }
+        }
+        else if (e.getActionCommand().equals("todayButtonClicked")) {
+            setDate(new Date());
+        }
+        else if (e.getActionCommand().equals("dateButtonClicked")) {
+            final JButton b = (JButton) e.getSource();
+            final int i = Integer.parseInt(b.getName());
+            final Calendar cal = getFirstVisibleDate();
+            cal.add(Calendar.DATE, i);
+            setDate(cal.getTime());
+        }
+    }
+
+    /**
+     * Returns a panel of buttons, each button representing a day in the month.
+     * This is a sub-component of the DatePanel.
+     *
+     * @return the panel.
+     */
+    private JPanel getCalendarPanel() {
+
+        final JPanel p = new JPanel(new GridLayout(7, 7));
+        final DateFormatSymbols dateFormatSymbols = new DateFormatSymbols();
+        final String[] weekDays = dateFormatSymbols.getShortWeekdays();
+
+        for (int i = 0; i < this.WEEK_DAYS.length; i++) {
+            p.add(new JLabel(weekDays[this.WEEK_DAYS[i]], 
+                    SwingConstants.CENTER));
+        }
+
+        this.buttons = new JButton[42];
+        for (int i = 0; i < 42; i++) {
+            final JButton b = new JButton("");
+            b.setMargin(new Insets(1, 1, 1, 1));
+            b.setName(Integer.toString(i));
+            b.setFont(this.dateFont);
+            b.setFocusPainted(false);
+            b.setActionCommand("dateButtonClicked");
+            b.addActionListener(this);
+            this.buttons[i] = b;
+            p.add(b);
+        }
+        return p;
+
+    }
+
+    /**
+     * Returns the button color according to the specified date.
+     *
+     * @param theDate the date.
+     * @return the color.
+     */
+    private Color getButtonColor(final Calendar theDate) {
+        if (equalDates(theDate, this.chosenDate)) {
+            return this.chosenDateButtonColor;
+        }
+        else if (theDate.get(Calendar.MONTH) == this.chosenDate.get(
+                Calendar.MONTH)) {
+            return this.chosenMonthButtonColor;
+        }
+        else {
+            return this.chosenOtherButtonColor;
+        }
+    }
+
+    /**
+     * Returns true if the two dates are equal (time of day is ignored).
+     *
+     * @param c1 the first date.
+     * @param c2 the second date.
+     * @return boolean.
+     */
+    private boolean equalDates(final Calendar c1, final Calendar c2) {
+        if ((c1.get(Calendar.DATE) == c2.get(Calendar.DATE))
+            && (c1.get(Calendar.MONTH) == c2.get(Calendar.MONTH))
+            && (c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR))) {
+            return true;
+        }
+        else {
+            return false;
+        }
+    }
+
+    /**
+     * Returns the first date that is visible in the grid.  This should always 
+     * be in the month preceding the month of the selected date.
+     *
+     * @return the date.
+     */
+    private Calendar getFirstVisibleDate() {
+        final Calendar c = Calendar.getInstance();
+        c.set(this.chosenDate.get(Calendar.YEAR), this.chosenDate.get(
+                Calendar.MONTH), 1);
+        c.add(Calendar.DATE, -1);
+        while (c.get(Calendar.DAY_OF_WEEK) != getFirstDayOfWeek()) {
+            c.add(Calendar.DATE, -1);
+        }
+        return c;
+    }
+
+    /**
+     * Returns the first day of the week (controls the labels in the date 
+     * panel).
+     *
+     * @return the first day of the week.
+     */
+    private int getFirstDayOfWeek() {
+        return this.firstDayOfWeek;
+    }
+
+    /**
+     * Update the button labels and colors to reflect date selection.
+     */
+    private void refreshButtons() {
+        final Calendar c = getFirstVisibleDate();
+        for (int i = 0; i < 42; i++) {
+            final JButton b = this.buttons[i];
+            b.setText(Integer.toString(c.get(Calendar.DATE)));
+            b.setBackground(getButtonColor(c));
+            c.add(Calendar.DATE, 1);
+        }
+    }
+
+    /**
+     * Changes the contents of the year selection JComboBox to reflect the 
+     * chosen date and the year range.
+     */
+    private void refreshYearSelector() {
+        if (!this.refreshing) {
+            this.refreshing = true;
+            this.yearSelector.removeAllItems();
+            final Integer[] years = getYears(this.chosenDate.get(
+                    Calendar.YEAR));
+            for (int i = 0; i < years.length; i++) {
+                this.yearSelector.addItem(years[i]);
+            }
+            this.yearSelector.setSelectedItem(new Integer(this.chosenDate.get(
+                    Calendar.YEAR)));
+            this.refreshing = false;
+        }
+    }
+
+    /**
+     * Returns a vector of years preceding and following the specified year.  
+     * The number of years preceding and following is determined by the 
+     * yearSelectionRange attribute.
+     *
+     * @param chosenYear the selected year.
+     * @return a vector of years.
+     */
+    private Integer[] getYears(final int chosenYear) {
+        final int size = this.yearSelectionRange * 2 + 1;
+        final int start = chosenYear - this.yearSelectionRange;
+
+        final Integer[] years = new Integer[size];
+        for (int i = 0; i < size; i++) {
+            years[i] = new Integer(i + start);
+        }
+        return years;
+    }
+
+    /**
+     * Constructs a panel containing two JComboBoxes (for the month and year) 
+     * and a button (to reset the date to TODAY).
+     *
+     * @return the panel.
+     */
+    private JPanel constructSelectionPanel() {
+        final JPanel p = new JPanel();
+
+        final int minMonth = this.chosenDate.getMinimum(Calendar.MONTH);
+        final int maxMonth = this.chosenDate.getMaximum(Calendar.MONTH);
+        final String[] months = new String[maxMonth - minMonth + 1];
+        System.arraycopy(SerialDate.getMonths(), minMonth, months, 0, 
+                months.length);
+
+        this.monthSelector = new JComboBox(months);
+        this.monthSelector.addActionListener(this);
+        this.monthSelector.setActionCommand("monthSelectionChanged");
+        p.add(this.monthSelector);
+
+        this.yearSelector = new JComboBox(getYears(0));
+        this.yearSelector.addActionListener(this);
+        this.yearSelector.setActionCommand("yearSelectionChanged");
+        p.add(this.yearSelector);
+
+        return p;
+    }
+
+    /**
+     * Returns a panel that appears at the bottom of the calendar panel - 
+     * contains a button for selecting today's date.
+     *
+     * @return the panel.
+     */
+    private JPanel constructControlPanel() {
+
+        final JPanel p = new JPanel();
+        p.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
+        this.todayButton = new JButton("Today");
+        this.todayButton.addActionListener(this);
+        this.todayButton.setActionCommand("todayButtonClicked");
+        p.add(this.todayButton);
+        return p;
+
+    }
+
+    /**
+     * Returns the color for the currently selected date.
+     *
+     * @return a color.
+     */
+    public Color getChosenDateButtonColor() {
+        return this.chosenDateButtonColor;
+    }
+
+    /**
+     * Redefines the color for the currently selected date.
+     *
+     * @param chosenDateButtonColor the new color
+     */
+    public void setChosenDateButtonColor(final Color chosenDateButtonColor) {
+        if (chosenDateButtonColor == null) {
+            throw new NullPointerException("UIColor must not be null.");
+        }
+        final Color oldValue = this.chosenDateButtonColor;
+        this.chosenDateButtonColor = chosenDateButtonColor;
+        refreshButtons();
+        firePropertyChange("chosenDateButtonColor", oldValue, 
+                chosenDateButtonColor);
+    }
+
+    /**
+     * Returns the color for the buttons representing the current month.
+     *
+     * @return the color for the current month.
+     */
+    public Color getChosenMonthButtonColor() {
+        return this.chosenMonthButtonColor;
+    }
+
+    /**
+     * Defines the color for the buttons representing the current month.
+     *
+     * @param chosenMonthButtonColor the color for the current month.
+     */
+    public void setChosenMonthButtonColor(final Color chosenMonthButtonColor) {
+        if (chosenMonthButtonColor == null) {
+            throw new NullPointerException("UIColor must not be null.");
+        }
+        final Color oldValue = this.chosenMonthButtonColor;
+        this.chosenMonthButtonColor = chosenMonthButtonColor;
+        refreshButtons();
+        firePropertyChange("chosenMonthButtonColor", oldValue, 
+                chosenMonthButtonColor);
+    }
+
+    /**
+     * Returns the color for the buttons representing the other months.
+     *
+     * @return a color.
+     */
+    public Color getChosenOtherButtonColor() {
+        return this.chosenOtherButtonColor;
+    }
+
+    /**
+     * Redefines the color for the buttons representing the other months.
+     *
+     * @param chosenOtherButtonColor a color.
+     */
+    public void setChosenOtherButtonColor(final Color chosenOtherButtonColor) {
+        if (chosenOtherButtonColor == null) {
+            throw new NullPointerException("UIColor must not be null.");
+        }
+        final Color oldValue = this.chosenOtherButtonColor;
+        this.chosenOtherButtonColor = chosenOtherButtonColor;
+        refreshButtons();
+        firePropertyChange("chosenOtherButtonColor", oldValue, 
+                chosenOtherButtonColor);
+    }
+
+    /**
+     * Returns the range of years available for selection (defaults to 20).
+     * 
+     * @return The range.
+     */
+    public int getYearSelectionRange() {
+        return this.yearSelectionRange;
+    }
+
+    /**
+     * Sets the range of years available for selection.
+     * 
+     * @param yearSelectionRange  the range.
+     */
+    public void setYearSelectionRange(final int yearSelectionRange) {
+        final int oldYearSelectionRange = this.yearSelectionRange;
+        this.yearSelectionRange = yearSelectionRange;
+        refreshYearSelector();
+        firePropertyChange("yearSelectionRange", oldYearSelectionRange, 
+                yearSelectionRange);
+    }
+}

+ 63 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/Drawable.java

@@ -0,0 +1,63 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -------------
+ * Drawable.java
+ * -------------
+ * (C) Copyright 2002-2004, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: Drawable.java,v 1.4 2005/11/16 15:58:41 taqua Exp $
+ *
+ * Changes (from 30-May-2002)
+ * --------------------------
+ * 25-Jun-2002 : Version 1 (DG);
+ *
+ */
+
+package org.jfree.ui;
+
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * An interface for an object that can draw itself within an area on a Graphics2D.
+ *
+ * @author David Gilbert
+ */
+public interface Drawable {
+
+    /**
+     * Draws the object.
+     *
+     * @param g2  the graphics device.
+     * @param area  the area inside which the object should be drawn.
+     */
+    public void draw(Graphics2D g2, Rectangle2D area);
+
+}

+ 191 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/DrawablePanel.java

@@ -0,0 +1,191 @@
+/**
+ * ========================================
+ * JCommon : a free Java report library
+ * ========================================
+ *
+ * Project Info:  http://www.jfree.org/jcommon/
+ * Project Lead:  Thomas Morgner;
+ *
+ * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
+ *
+ * This library 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 library 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
+ * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * ------------
+ * DrawablePanel.java
+ * ------------
+ * (C) Copyright 2002-2006, by Object Refinery Limited.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   -;
+ *
+ * $Id: DrawablePanel.java,v 1.4 2008/09/10 09:25:09 mungady Exp $
+ *
+ * Changes
+ * -------
+ *
+ *
+ */
+package org.jfree.ui;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+import javax.swing.JPanel;
+
+/**
+ * A component, that accepts a drawable and which draws that drawable.
+ *
+ * @author Thomas Morgner
+ */
+public class DrawablePanel extends JPanel
+{
+  private Drawable drawable;
+
+  /**
+   * Creates a new instance.
+   */
+  public DrawablePanel()
+  {
+    setOpaque(false);
+  }
+
+  /**
+   * Returns the drawable item.
+   *
+   * @return The drawable item.
+   */
+  public Drawable getDrawable()
+  {
+    return this.drawable;
+  }
+
+  /**
+   * Sets the drawable item.
+   *
+   * @param drawable  the drawable item.
+   */
+  public void setDrawable(final Drawable drawable)
+  {
+    this.drawable = drawable;
+    revalidate();
+    repaint();
+  }
+
+  /**
+   * If the <code>preferredSize</code> has been set to a non-<code>null</code>
+   * value just returns it. If the UI delegate's <code>getPreferredSize</code>
+   * method returns a non <code>null</code> value then return that; otherwise
+   * defer to the component's layout manager.
+   *
+   * @return the value of the <code>preferredSize</code> property
+   * @see #setPreferredSize
+   * @see javax.swing.plaf.ComponentUI
+   */
+  public Dimension getPreferredSize()
+  {
+    if (this.drawable instanceof ExtendedDrawable)
+    {
+      final ExtendedDrawable ed = (ExtendedDrawable) this.drawable;
+      return ed.getPreferredSize();
+    }
+    return super.getPreferredSize();
+  }
+
+  /**
+   * If the minimum size has been set to a non-<code>null</code> value just
+   * returns it.  If the UI delegate's <code>getMinimumSize</code> method
+   * returns a non-<code>null</code> value then return that; otherwise defer to
+   * the component's layout manager.
+   *
+   * @return the value of the <code>minimumSize</code> property
+   * @see #setMinimumSize
+   * @see javax.swing.plaf.ComponentUI
+   */
+  public Dimension getMinimumSize()
+  {
+    if (this.drawable instanceof ExtendedDrawable)
+    {
+      final ExtendedDrawable ed = (ExtendedDrawable) this.drawable;
+      return ed.getPreferredSize();
+    }
+    return super.getMinimumSize();
+  }
+
+  /**
+   * Returns true if this component is completely opaque.
+   * <p>
+   * An opaque component paints every pixel within its rectangular bounds. A
+   * non-opaque component paints only a subset of its pixels or none at all,
+   * allowing the pixels underneath it to "show through".  Therefore, a
+   * component that does not fully paint its pixels provides a degree of
+   * transparency.</p>
+   * <p>
+   * Subclasses that guarantee to always completely paint their contents should
+   * override this method and return true.</p>
+   *
+   * @return true if this component is completely opaque
+   * @see #setOpaque
+   */
+  public boolean isOpaque()
+  {
+    if (this.drawable == null)
+    {
+      return false;
+    }
+    return super.isOpaque();
+  }
+
+  /**
+   * Calls the UI delegate's paint method, if the UI delegate is
+   * non-<code>null</code>.  We pass the delegate a copy of the
+   * <code>Graphics</code> object to protect the rest of the paint code from
+   * irrevocable changes (for example, <code>Graphics.translate</code>).
+   * <p>
+   * If you override this in a subclass you should not make permanent changes to
+   * the passed in <code>Graphics</code>. For example, you should not alter the
+   * clip <code>Rectangle</code> or modify the transform. If you need to do
+   * these operations you may find it easier to create a new
+   * <code>Graphics</code> from the passed in <code>Graphics</code> and
+   * manipulate it. Further, if you do not invoker super's implementation you
+   * must honor the opaque property, that is if this component is opaque, you
+   * must completely fill in the background in a non-opaque color. If you do not
+   * honor the opaque property you will likely see visual artifacts.</p>
+   * <p>
+   * The passed in <code>Graphics</code> object might have a transform other
+   * than the identify transform installed on it.  In this case, you might get
+   * unexpected results if you cumulatively apply another transform.</p>
+   *
+   * @param g the <code>Graphics</code> object to protect
+   * @see #paint
+   * @see javax.swing.plaf.ComponentUI
+   */
+  protected void paintComponent(Graphics g)
+  {
+    super.paintComponent(g);
+    if (this.drawable == null)
+    {
+      return;
+    }
+
+    final Graphics2D g2 = (Graphics2D) g.create
+            (0, 0, getWidth(), getHeight());
+
+    this.drawable.draw(g2, new Rectangle2D.Double(0, 0, getWidth(), getHeight()));
+    g2.dispose();
+  }
+
+}

+ 68 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/ExtendedDrawable.java

@@ -0,0 +1,68 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ *
+ * ---------------------
+ * ExtendedDrawable.java
+ * ---------------------
+ * (C) Copyright 2002-2005, by Object Refinery Limited.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   -;
+ *
+ * $Id: ExtendedDrawable.java,v 1.4 2005/10/18 13:18:34 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 27-Apr-2005: Initial version.
+ *
+ */
+package org.jfree.ui;
+
+import java.awt.Dimension;
+
+/**
+ * A drawable that has a preferred size and aspect ratio. Implement this interface to gain
+ * some control over the rendering and layouting process for the drawable.
+ *
+ * @author Thomas Morgner
+ */
+public interface ExtendedDrawable extends Drawable
+{
+  /**
+   * Returns the preferred size of the drawable. If the drawable is aspect ratio aware,
+   * these bounds should be used to compute the preferred aspect ratio for this drawable.
+   *
+   * @return the preferred size.
+   */
+  public Dimension getPreferredSize ();
+
+  /**
+   * Returns true, if this drawable will preserve an aspect ratio during the drawing.
+   *
+   * @return true, if an aspect ratio is preserved, false otherwise.
+   */
+  public boolean isPreserveAspectRatio ();
+}

+ 105 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/ExtensionFileFilter.java

@@ -0,0 +1,105 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ------------------------
+ * ExtensionFileFilter.java
+ * ------------------------
+ * (C) Copyright 2000-2004, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: ExtensionFileFilter.java,v 1.5 2007/11/02 17:50:36 taqua Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 26-Oct-2001 : Changed package to com.jrefinery.ui.* (DG);
+ * 26-Jun-2002 : Updated imports (DG);
+ * 14-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ *
+ */
+package org.jfree.ui;
+
+import java.io.File;
+import javax.swing.filechooser.FileFilter;
+
+/**
+ * A filter for JFileChooser that filters files by extension.
+ *
+ * @author David Gilbert
+ */
+public class ExtensionFileFilter extends FileFilter {
+
+    /** A description for the file type. */
+    private String description;
+
+    /** The extension (for example, "png" for *.png files). */
+    private String extension;
+
+    /**
+     * Standard constructor.
+     *
+     * @param description  a description of the file type;
+     * @param extension  the file extension;
+     */
+    public ExtensionFileFilter(final String description, final String extension) {
+        this.description = description;
+        this.extension = extension;
+    }
+
+    /**
+     * Returns true if the file ends with the specified extension.
+     *
+     * @param file  the file to test.
+     *
+     * @return A boolean that indicates whether or not the file is accepted by the filter.
+     */
+    public boolean accept(final File file) {
+
+        if (file.isDirectory()) {
+            return true;
+        }
+
+        final String name = file.getName().toLowerCase();
+        if (name.endsWith(this.extension)) {
+            return true;
+        }
+        else {
+            return false;
+        }
+
+    }
+
+    /**
+     * Returns the description of the filter.
+     *
+     * @return a description of the filter.
+     */
+    public String getDescription() {
+        return this.description;
+    }
+
+}

+ 167 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/FilesystemFilter.java

@@ -0,0 +1,167 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ *
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
+ * in the United States and other countries.]
+ *
+ * ------------------------
+ * ExtensionFileFilter.java
+ * ------------------------
+ * (C) Copyright 2000-2004, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: FilesystemFilter.java,v 1.6 2008/09/10 09:26:11 mungady Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 01-Jun-2005 : Updated javadoc.
+ */
+package org.jfree.ui;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import javax.swing.filechooser.FileFilter;
+
+/**
+ * A filesystem filter.
+ *
+ * @author David Gilbert
+ */
+public class FilesystemFilter extends FileFilter implements FilenameFilter {
+
+    /** The file extension, which should be accepted. */
+    private String[] fileext;
+    /** The filter description. */
+    private String descr;
+    /** A flag indicating whether to accept directories. */
+    private boolean accDirs;
+
+    /**
+     * Creates a new filter.
+     *
+     * @param fileext the file extension.
+     * @param descr   the description.
+     */
+    public FilesystemFilter(final String fileext, final String descr) {
+        this(fileext, descr, true);
+    }
+
+    /**
+     * Creates a new filter.
+     *
+     * @param fileext the file extension.
+     * @param descr   the description.
+     * @param accDirs accept directories?
+     */
+    public FilesystemFilter(final String fileext, final String descr,
+                            final boolean accDirs) {
+        this(new String[]{fileext}, descr, accDirs);
+    }
+
+    /**
+     * Creates a new filter.
+     *
+     * @param fileext the file extension.
+     * @param descr   the description.
+     * @param accDirs accept directories?
+     * @throws NullPointerException if the file extensions are null.
+     */
+    public FilesystemFilter(final String[] fileext, final String descr,
+                            final boolean accDirs) {
+        this.fileext = (String[]) fileext.clone();
+        this.descr = descr;
+        this.accDirs = accDirs;
+    }
+
+
+    /**
+     * Returns <code>true</code> if the file is accepted, and <code>false</code> otherwise.
+     *
+     * @param dir  the directory.
+     * @param name the file name.
+     * @return A boolean.
+     */
+    public boolean accept(final File dir, final String name) {
+        final File f = new File(dir, name);
+        if (f.isDirectory() && acceptsDirectories()) {
+            return true;
+        }
+
+        for (int i = 0; i < this.fileext.length; i++) {
+            if (name.endsWith(this.fileext[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns <code>true</code> if the specified file matches the requirements of this
+     * filter, and <code>false</code> otherwise.
+     *
+     * @param dir the file or directory.
+     * @return A boolean.
+     */
+    public boolean accept(final File dir) {
+        if (dir.isDirectory() && acceptsDirectories()) {
+            return true;
+        }
+
+        for (int i = 0; i < this.fileext.length; i++) {
+            if (dir.getName().endsWith(this.fileext[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns the filter description.
+     *
+     * @return The filter description.
+     */
+    public String getDescription() {
+        return this.descr;
+    }
+
+    /**
+     * Sets the flag that controls whether or not the filter accepts directories.
+     *
+     * @param b a boolean.
+     */
+    public void acceptDirectories(final boolean b) {
+        this.accDirs = b;
+    }
+
+    /**
+     * Returns the flag that indicates whether or not the filter accepts directories.
+     *
+     * @return A boolean.
+     */
+    public boolean acceptsDirectories() {
+        return this.accDirs;
+    }
+
+}

+ 209 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/FloatDimension.java

@@ -0,0 +1,209 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -------------------
+ * FloatDimension.java
+ * -------------------
+ * (C)opyright 2002-2005, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: FloatDimension.java,v 1.4 2005/11/03 09:26:51 mungady Exp $
+ *
+ * Changes
+ * -------
+ * 05-Dec-2002 : Updated Javadocs (DG);
+ * 29-Apr-2003 : Moved to JCommon
+ * 
+ */
+
+package org.jfree.ui;
+
+import java.awt.geom.Dimension2D;
+import java.io.Serializable;
+
+/**
+ * A dimension object specified using <code>float</code> values.
+ *
+ * @author Thomas Morgner
+ */
+public class FloatDimension extends Dimension2D 
+                            implements Serializable {
+
+    /** For serialization. */
+    private static final long serialVersionUID = 5367882923248086744L;
+    
+    /** The width. */
+    private float width;
+
+    /** The height. */
+    private float height;
+
+    /**
+     * Creates a new dimension object with width and height set to zero.
+     */
+    public FloatDimension() {
+        this.width = 0.0f;
+        this.height = 0.0f;
+    }
+
+    /**
+     * Creates a new dimension that is a copy of another dimension.
+     *
+     * @param fd  the dimension to copy.
+     */
+    public FloatDimension(final FloatDimension fd) {
+        this.width = fd.width;
+        this.height = fd.height;
+    }
+
+    /**
+     * Creates a new dimension.
+     *
+     * @param width  the width.
+     * @param height  the height.
+     */
+    public FloatDimension(final float width, final float height) {
+        this.width = width;
+        this.height = height;
+    }
+
+    /**
+     * Returns the width.
+     *
+     * @return the width.
+     */
+    public double getWidth() {
+        return this.width;
+    }
+
+    /**
+     * Returns the height.
+     *
+     * @return the height.
+     */
+    public double getHeight() {
+        return this.height;
+    }
+
+    /**
+     * Sets the width.
+     *
+     * @param width  the width.
+     */
+    public void setWidth(final double width) {
+        this.width = (float) width;
+    }
+
+    /**
+     * Sets the height.
+     *
+     * @param height  the height.
+     */
+    public void setHeight(final double height) {
+        this.height = (float) height;
+    }
+
+    /**
+     * Sets the size of this <code>Dimension</code> object to the specified 
+     * width and height.  This method is included for completeness, to parallel
+     * the {@link java.awt.Component#getSize() getSize} method of
+     * {@link java.awt.Component}.
+     * 
+     * @param width  the new width for the <code>Dimension</code> object
+     * @param height  the new height for the <code>Dimension</code> object
+     */
+    public void setSize(final double width, final double height) {
+        setHeight((float) height);
+        setWidth((float) width);
+    }
+
+    /**
+     * Creates and returns a copy of this object.
+     *
+     * @return     a clone of this instance.
+     * @see        java.lang.Cloneable
+     */
+    public Object clone() {
+        return super.clone();
+    }
+
+    /**
+     * Returns a string representation of the object. In general, the
+     * <code>toString</code> method returns a string that
+     * "textually represents" this object. The result should
+     * be a concise but informative representation that is easy for a
+     * person to read.
+     * <p>
+     *
+     * @return  a string representation of the object.
+     */
+    public String toString() {
+        return getClass().getName() + ":={width=" + getWidth() + ", height=" 
+                + getHeight() + "}";
+    }
+
+    /**
+     * Tests this object for equality with another object.
+     *
+     * @param o  the other object.
+     *
+     * @return <code>true</code> or <code>false</code>.
+     */
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof FloatDimension)) {
+            return false;
+        }
+
+        final FloatDimension floatDimension = (FloatDimension) o;
+
+        if (this.height != floatDimension.height) {
+            return false;
+        }
+        if (this.width != floatDimension.width) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns a hash code.
+     *
+     * @return A hash code.
+     */
+    public int hashCode() {
+        int result;
+        result = Float.floatToIntBits(this.width);
+        result = 29 * result + Float.floatToIntBits(this.height);
+        return result;
+    }
+}
+

+ 131 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/FloatingButtonEnabler.java

@@ -0,0 +1,131 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * -----------------
+ * DetailEditor.java
+ * -----------------
+ * (C) Copyright 2004, by Thomas Morgner and Contributors.
+ *
+ * Original Author:  Thomas Morgner;
+ * Contributor(s):   David Gilbert (for Object Refinery Limited);
+ *
+ * $Id: FloatingButtonEnabler.java,v 1.4 2007/11/02 17:50:36 taqua Exp $
+ *
+ * Changes
+ * -------
+ * 07-Jun-2004 : Added JCommon header (DG);
+ *
+ */
+
+package org.jfree.ui;
+
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import javax.swing.AbstractButton;
+
+/**
+ * Enables a button to have a simple floating effect. The border of the button is only visible,
+ * when the mouse pointer is floating over the button.
+ *
+ * @author Thomas Morgner
+ */
+public final class FloatingButtonEnabler extends MouseAdapter {
+  
+    /** A single instance. */
+    private static FloatingButtonEnabler singleton;
+
+    /**
+     * Default constructor.
+     */
+    private FloatingButtonEnabler() {
+        // nothing required
+    }
+
+    /**
+     * Returns a default instance of this enabler.
+     *
+     * @return a shared instance of this class.
+     */
+    public static FloatingButtonEnabler getInstance() {
+        if (singleton == null) {
+            singleton = new FloatingButtonEnabler();
+        }
+        return singleton;
+    }
+
+    /**
+     * Adds a button to this enabler.
+     *
+     * @param button  the button.
+     */
+    public void addButton(final AbstractButton button) {
+        button.addMouseListener(this);
+        button.setBorderPainted(false);
+    }
+
+    /**
+     * Removes a button from the enabler.
+     *
+     * @param button  the button.
+     */
+    public void removeButton(final AbstractButton button) {
+        button.addMouseListener(this);
+        button.setBorderPainted(true);
+    }
+
+    /**
+     * Triggers the drawing of the border when the mouse entered the button area.
+     *
+     * @param e  the mouse event.
+     */
+    public void mouseEntered(final MouseEvent e) {
+        if (e.getSource() instanceof AbstractButton) {
+            final AbstractButton button = (AbstractButton) e.getSource();
+            if (button.isEnabled()) {
+                button.setBorderPainted(true);
+            }
+        }
+    }
+
+    /**
+     * Disables the drawing of the border when the mouse leaves the button area.
+     *
+     * @param e  the mouse event.
+     */
+    public void mouseExited(final MouseEvent e) {
+        if (e.getSource() instanceof AbstractButton) {
+            final AbstractButton button = (AbstractButton) e.getSource();
+            button.setBorderPainted(false);
+            if (button.getParent() != null)
+            {
+//                button.getParent().repaint(button.getX(), button.getY(),
+//                    button.getWidth(), button.getHeight());
+                button.getParent().repaint();
+            }
+        }
+    }
+
+}

+ 121 - 0
jars/jcommon-1.0.23/src/main/java/org/jfree/ui/FontChooserDialog.java

@@ -0,0 +1,121 @@
+/* ========================================================================
+ * JCommon : a free general purpose class library for the Java(tm) platform
+ * ========================================================================
+ *
+ * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
+ * 
+ * Project Info:  http://www.jfree.org/jcommon/index.html
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * USA.  
+ *
+ * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
+ * in the United States and other countries.]
+ * 
+ * ----------------------
+ * FontChooserDialog.java
+ * ----------------------
+ * (C) Copyright 2000-2004, by Object Refinery Limited.
+ *
+ * Original Author:  David Gilbert (for Object Refinery Limited);
+ * Contributor(s):   -;
+ *
+ * $Id: FontChooserDialog.java,v 1.5 2007/11/02 17:50:36 taqua Exp $
+ *
+ * Changes (from 26-Oct-2001)
+ * --------------------------
+ * 26-Oct-2001 : Changed package to com.jrefinery.ui.*;
+ * 14-Oct-2002 : Fixed errors reported by Checkstyle (DG);
+ *
+ */
+
+package org.jfree.ui;
+
+import java.awt.BorderLayout;
+import java.awt.Dialog;
+import java.awt.Font;
+import java.awt.Frame;
+import javax.swing.BorderFactory;
+import javax.swing.JPanel;
+
+/**
+ * A dialog for choosing a font from the available system fonts.
+ *
+ * @author David Gilbert
+ */
+public class FontChooserDialog extends StandardDialog {
+
+    /** The panel within the dialog that contains the font selection controls. */
+    private FontChooserPanel fontChooserPanel;
+
+    /**
+     * Standard constructor - builds a font chooser dialog owned by another dialog.
+     *
+     * @param owner  the dialog that 'owns' this dialog.
+     * @param title  the title for the dialog.
+     * @param modal  a boolean that indicates whether or not the dialog is modal.
+     * @param font  the initial font displayed.
+     */
+    public FontChooserDialog(final Dialog owner, final String title, final boolean modal, final Font font) {
+        super(owner, title, modal);
+        setContentPane(createContent(font));
+    }
+
+    /**
+     * Standard constructor - builds a font chooser dialog owned by a frame.
+     *
+     * @param owner  the frame that 'owns' this dialog.
+     * @param title  the title for the dialog.
+     * @param modal  a boolean that indicates whether or not the dialog is modal.
+     * @param font  the initial font displayed.
+     */
+    public FontChooserDialog(final Frame owner, final String title, final boolean modal, final Font font) {
+        super(owner, title, modal);
+        setContentPane(createContent(font));
+    }
+
+    /**
+     * Returns the selected font.
+     *
+     * @return the font.
+     */
+    public Font getSelectedFont() {
+        return this.fontChooserPanel.getSelectedFont();
+    }
+
+    /**
+     * Returns the panel that is the user interface.
+     *
+     * @param font  the font.
+     *
+     * @return the panel.
+     */
+    private JPanel createContent(Font font) {
+        final JPanel content = new JPanel(new BorderLayout());
+        content.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
+        if (font == null) {
+            font = new Font("Dialog", 10, Font.PLAIN);
+        }
+        this.fontChooserPanel = new FontChooserPanel(font);
+        content.add(this.fontChooserPanel);
+
+        final JPanel buttons = createButtonPanel();
+        buttons.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0));
+        content.add(buttons, BorderLayout.SOUTH);
+
+        return content;
+    }
+
+}

Some files were not shown because too many files changed in this diff