changeset 1431:79e96b23cdd3

Merge with IcedTea6. 2008-11-17 Andrew John Hughes <ahughes@redhat.com> Merge with IcedTea6. * .hgignore, * .hgtags, * ChangeLog, * HACKING, * IcedTeaPlugin.cc, * Makefile.am, * contrib/mixtec-hacks.patch, * fsg.sh, * overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt, * overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioPusher.java, * overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftFilter.java, * overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java, * overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java, * overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftVoice.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java, * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AccessWarningPane.java, * patches/icedtea-6761856-freetypescaler.patch, * patches/icedtea-alsa-default-device.patch, * patches/icedtea-cc-interp-no-fer.patch, * patches/icedtea-display-mode-changer.patch, * patches/icedtea-f2i-overflow.patch: Merged. * patches/icedtea-linker-libs-order.patch: Rebuilt. * patches/icedtea-testenv.patch: Converted to work against TestUtil. * patches/icedtea-uname.patch, * patches/icedtea-visualvm.patch, * plugin/icedtea/sun/applet/PluginAppletViewer.java, * ports/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.inline.hpp, * ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp, * ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp, * ports/hotspot/src/cpu/zero/vm/frame_zero.cpp, * ports/hotspot/src/cpu/zero/vm/globals_zero.hpp, * ports/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp, * ports/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp, * ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp, * ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp, * ports/hotspot/src/share/vm/shark/sharkBlock.cpp, * ports/hotspot/src/share/vm/shark/sharkBlock.hpp, * ports/hotspot/src/share/vm/shark/sharkRuntime.cpp, * ports/hotspot/src/share/vm/shark/sharkRuntime.hpp, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Debug.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Operation.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixerProvider.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/SecurityWrapper.java, * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java, * pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c, * pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java, * test/jtreg/README, * test/jtreg/com/sun/javatest/diff/Diff.java, * test/jtreg/com/sun/javatest/diff/Fault.java, * test/jtreg/com/sun/javatest/diff/HTMLReporter.java, * test/jtreg/com/sun/javatest/diff/HTMLWriter.java, * test/jtreg/com/sun/javatest/diff/Main.java, * test/jtreg/com/sun/javatest/diff/MultiMap.java, * test/jtreg/com/sun/javatest/diff/ReportReader.java, * test/jtreg/com/sun/javatest/diff/StandardDiff.java, * test/jtreg/com/sun/javatest/diff/SuperDiff.java, * test/jtreg/com/sun/javatest/diff/WorkDirectoryReader.java, * test/jtreg/com/sun/javatest/diff/i18n.properties, * test/jtreg/com/sun/javatest/regtest/Main.java, * test/jtreg/com/sun/javatest/regtest/MainAction.java, * test/jtreg/com/sun/javatest/regtest/RegressionSecurityManager.java, * test/jtreg/com/sun/javatest/regtest/RegressionTestFinder.java, * test/jtreg/com/sun/javatest/regtest/i18n.properties: Merged.
author Andrew John Hughes <gnu_andrew@member.fsf.org>
date Mon, 17 Nov 2008 15:26:51 +0000
parents 4e8f60cd59d0 (current diff) 3d0cabbaa2b3 (diff)
children 79d3c8c363dc
files .hgignore .hgtags ChangeLog HACKING IcedTeaPlugin.cc Makefile.am NEWS acinclude.m4 configure.ac fsg.sh overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AccessWarningPane.java patches/icedtea-copy-plugs.patch patches/icedtea-linker-libs-order.patch patches/icedtea-testenv.patch patches/icedtea-version.patch ports/hotspot/src/cpu/zero/vm/frame_zero.cpp ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
diffstat 72 files changed, 3618 insertions(+), 857 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Nov 17 12:41:07 2008 +0000
+++ b/.hgignore	Mon Nov 17 15:26:51 2008 +0000
@@ -38,6 +38,7 @@
 test/langtools
 test/jtreg.jar
 test/jtreg/classes
+test/check-.*log
 rt/com/sun/jdi/AbsentInformationException.java
 rt/com/sun/jdi/Accessible.java
 rt/com/sun/jdi/ArrayReference.java
--- a/.hgtags	Mon Nov 17 12:41:07 2008 +0000
+++ b/.hgtags	Mon Nov 17 15:26:51 2008 +0000
@@ -10,3 +10,4 @@
 871b70407a139c6bd42c200762ee1d302b31168f icedtea6-1.2
 8bbc4ffe2c7c542f9aa7d26f823e50f0dd036ce9 icedtea-1.7
 3ef9c9c4e70b8204b73fa9b88243f49f59c2a23f icedtea6-1.3
+be368b1e3c7dca9b4dfe8e8f40be794ecfbef22e icedtea6-1.3.1
--- a/ChangeLog	Mon Nov 17 12:41:07 2008 +0000
+++ b/ChangeLog	Mon Nov 17 15:26:51 2008 +0000
@@ -1,5 +1,81 @@
-2008-11-14  Andrew John Hughes  <ahughes@redhat.com>
-
+2008-11-17  Andrew John Hughes  <ahughes@redhat.com>
+
+	Merge with IcedTea6.
+	* .hgignore,
+	* .hgtags,
+	* ChangeLog,
+	* HACKING,
+	* IcedTeaPlugin.cc,
+	* Makefile.am,
+	* contrib/mixtec-hacks.patch,
+	* fsg.sh,
+	* overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt,
+	* overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioPusher.java,
+	* overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftFilter.java,
+	* overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java,
+	* overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java,
+	* overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftVoice.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java,
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AccessWarningPane.java,
+	* patches/icedtea-6761856-freetypescaler.patch,
+	* patches/icedtea-alsa-default-device.patch,
+	* patches/icedtea-cc-interp-no-fer.patch,
+	* patches/icedtea-display-mode-changer.patch,
+	* patches/icedtea-f2i-overflow.patch: Merged.
+	* patches/icedtea-linker-libs-order.patch: Rebuilt.
+	* patches/icedtea-testenv.patch: Converted to work against TestUtil.
+	* patches/icedtea-uname.patch,
+	* patches/icedtea-visualvm.patch,
+	* plugin/icedtea/sun/applet/PluginAppletViewer.java,
+	* ports/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.inline.hpp,
+	* ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp,
+	* ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp,
+	* ports/hotspot/src/cpu/zero/vm/frame_zero.cpp,
+	* ports/hotspot/src/cpu/zero/vm/globals_zero.hpp,
+	* ports/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp,
+	* ports/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp,
+	* ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp,
+	* ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp,
+	* ports/hotspot/src/share/vm/shark/sharkBlock.cpp,
+	* ports/hotspot/src/share/vm/shark/sharkBlock.hpp,
+	* ports/hotspot/src/share/vm/shark/sharkRuntime.cpp,
+	* ports/hotspot/src/share/vm/shark/sharkRuntime.hpp,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Debug.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Operation.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixerProvider.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/SecurityWrapper.java,
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java,
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c,
+	* pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java,
+	* test/jtreg/README,
+	* test/jtreg/com/sun/javatest/diff/Diff.java,
+	* test/jtreg/com/sun/javatest/diff/Fault.java,
+	* test/jtreg/com/sun/javatest/diff/HTMLReporter.java,
+	* test/jtreg/com/sun/javatest/diff/HTMLWriter.java,
+	* test/jtreg/com/sun/javatest/diff/Main.java,
+	* test/jtreg/com/sun/javatest/diff/MultiMap.java,
+	* test/jtreg/com/sun/javatest/diff/ReportReader.java,
+	* test/jtreg/com/sun/javatest/diff/StandardDiff.java,
+	* test/jtreg/com/sun/javatest/diff/SuperDiff.java,
+	* test/jtreg/com/sun/javatest/diff/WorkDirectoryReader.java,
+	* test/jtreg/com/sun/javatest/diff/i18n.properties,
+	* test/jtreg/com/sun/javatest/regtest/Main.java,
+	* test/jtreg/com/sun/javatest/regtest/MainAction.java,
+	* test/jtreg/com/sun/javatest/regtest/RegressionSecurityManager.java,
+	* test/jtreg/com/sun/javatest/regtest/RegressionTestFinder.java,
+	* test/jtreg/com/sun/javatest/regtest/i18n.properties: Merged.
+
+2008-11-17  Andrew John Hughes  <ahughes@redhat.com>
+	
 	* Makefile.am:
 	Expand generated and pulseaudio.  Lock
 	patches to $(top_srcdir).  Run jtreg with
@@ -13,6 +89,16 @@
 	* test/jtreg/excludelist.langtools.jtx:
 	Exclude broken tests.
 
+2008-11-17  Matthias Klose  <doko@ubuntu.com>
+
+	* fsg.sh: Don't remove xml-stylesheet files.
+
+2008-11-15  Mark Wielaard  <mark@klomp.org>
+
+	* patches/icedtea-testenv.patch: New patch.
+	* Makefile.am (ICEDTEA_PATCHES): Add new patch.
+	* HACKING: Document new patch.
+
 2008-11-14  Andrew John Hughes  <ahughes@redhat.com>
 
 	* overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider,
@@ -28,6 +114,32 @@
 	* overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/services/windows-ia64/javax.sound.sampled.spi.MixerProvider:
 	Add property files missed by hg.
 
+2008-11-15  Mark Wielaard  <mark@klomp.org>
+
+	* patches/icedtea-display-mode-changer.patch: New patch.
+	* Makefile.am (ICEDTEA_PATCHES): Add new patch.
+	* HACKING: Document new patch.
+
+2008-11-14  Omair Majid  <omajid@redhat.com>
+
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java
+	Removed useless SuppressWarnings.
+	(static): Delegate the loading of native libraries to SecurityWrapper.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Operation.java
+	(static): Likewise.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java
+	(static): Likewise.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java
+	(static): Likewise.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java 
+	(static): Likewise.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java
+	(static): Likewise.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/SecurityWrapper.java
+	New class.
+	(loadNativeLibrary): Loads libpulse-java.so in a privileged operation to
+	work when a security manager is installed.
+
 2008-11-14  Andrew John Hughes  <ahughes@redhat.com>
 
 	* HACKING: List new plugs patches.
@@ -78,28 +190,151 @@
 	* javac.in:
 	Convert to Perl script to avoid
 	quoting errors.
-	
+
+2008-11-11  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp
+	(os::atomic_copy64): New method.
+	* ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
+	(_Copy_conjoint_jlongs_atomic): Use the above.
+	* ports/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp
+	(OrderAccess::load_acquire): Likewise.
+	(OrderAccess::release_store): Likewise.
+	(OrderAccess::store_fence): Likewise.
+	(OrderAccess::release_store_fence): Likewise.
+
+2008-11-11  Matthias Klose  <doko@ubuntu.com>
+
+	* patches/icedtea-uname.patch: Fix ARCH on powerpc-linux-gnu
+
 2008-11-10  Andrew John Hughes  <ahughes@redhat.com>
 
 	* Makefile.am: Fix make dist.
 
+2008-11-10  Omair Majid  <omajid@redhat.com>
+
+		* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Debug.java
+	New class containing debugging functions.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java
+	(run): Print some debugging info.
+	(update): Likewise.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java
+	(ClipThread.writeFrames): Likewise.
+	(close): Likewise.
+	(open): Likewise.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java
+	(PulseAudioMixer): Likewise.
+	(getLine): Likewise.
+	(close): Likewise.
+	(open): Likewise.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixerProvider.java
+	(PulseAudioMixerProvider): Initialize Debug class.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java
+	(open): Print some debug info.
+	(close): Likewise.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java
+	(open): Likewise.
+	(close): Likewise.
+	
+2008-11-10  Omair Majid  <omajid@redhat.com>
+
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java
+	(close): Dont check for permission to play audio. Always granted.
+	Infact, checking it causes an AccessControlException for untrusted
+	applets. The ALSA based backend doesnt check this permission at all.
+	(open): Likewise.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java
+	(getLine): Likewise.
+	(getSourceLines): Likewise.
+	(close): Likewise.
+	(open): Likewise.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java
+	(open): Likewise.
+	(close): Likewise.
+	* pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java
+	(open): Likewise.
+	(close): Likewise.
+
+2008-11-10  Omair Majid  <omajid@redhat.com>
+
+	* pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c
+	(Java_org_classpath_icedtea_pulseaudio_EventLoop_native_1set_1sink_1volume):
+	Deallocate unused memory.
+
+2008-11-10  Mark Wielaard  <mark@klomp.org>
+
+	* overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/
+	CHANGES.txt,SoftAudioPusher.java,SoftFilter.java,
+	SoftJitterCorrector.java,SoftMainMixer.java,SoftVoice.java:
+	Updated to new Gervill CVS.
+
 2008-11-09  Andrew John Hughes  <ahughes@redhat.com>
 
 	* Makefile.am: Bump to b39.
 	* patches/icedtea-hotspot-use-idx_t.patch,
 	* patches/icedtea-security-updates.patch:
 	Remove parts applied/changed in b39.
-	
-2008-11-07  Omair Majid  <omajid@redhat.com>
-
-	* patches/icedtea-jsoundhs.patch: Added two more diffs to remove all uses 
-	of jsoundhs and Headspace libraries.
+
+2008-11-09  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (check-langtools): Run jtreg with -samevm.
+
+2008-11-09  Mark Wielaard  <mark@klomp.org>
+
+	* test/jtreg/README,
+	test/jtreg/com/sun/javatest/diff/HTMLReporter.java,
+	test/jtreg/com/sun/javatest/diff/Main.java,
+	test/jtreg/com/sun/javatest/diff/MultiMap.java,
+	test/jtreg/com/sun/javatest/diff/ReportReader.java,
+	test/jtreg/com/sun/javatest/diff/WorkDirectoryReader.java,
+	test/jtreg/com/sun/javatest/diff/i18n.properties,
+	test/jtreg/com/sun/javatest/regtest/Main.java,
+	test/jtreg/com/sun/javatest/regtest/MainAction.java,
+	test/jtreg/com/sun/javatest/regtest/RegressionSecurityManager.java,
+	test/jtreg/com/sun/javatest/regtest/RegressionTestFinder.java,
+	test/jtreg/com/sun/javatest/regtest/i18n.properties,
+	test/jtreg/com/sun/javatest/diff/Diff.java,
+	test/jtreg/com/sun/javatest/diff/Fault.java,
+	test/jtreg/com/sun/javatest/diff/HTMLWriter.java,
+	test/jtreg/com/sun/javatest/diff/StandardDiff.java,
+	test/jtreg/com/sun/javatest/diff/SuperDiff.java,
+	Upgrade to jtreg-4_0-src-b02-15_oct_2008.
+
+2008-11-09  Mark Wielaard  <mark@klomp.org>
+
+	* .hgignore: Add test/check-.*log.
+
+2008-11-08  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (ICEDTEA_ENV): Set MILESTONE to fcs.
+	* patches/icedtea-version.patch: Remove special casing of
+	MILESTONE in hotspot build, add special casing of milestone in
+	langtools build.
+
+2008-11-08  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (OPENJDK_MD5SUM): Fixed value.
+
+2008-11-08  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (OPENJDK_DATE, OPENJDK_MD5SUM, OPENJDK_VERSION):
+	Update for b13.
+	(ICEDTEA_PATCHES): Removed patches 6616825, 6651382, 6756202.
+	* patches/icedtea-6open-6616825.patch: Removed.
+	* patches/icedtea-6open-6651382.patch: Removed.
+	* patches/icedtea-6open-6756202.patch: Removed.
+	* NEWS: Add integration of b13.
 
 2008-11-07  Andrew John Hughes  <ahughes@redhat.com>
 
 	* Makefile.am: Use 'node|short' instead of 'rev'
 	for Mercurial revision number.
 
+2008-11-07  Omair Majid  <omajid@redhat.com>
+
+	* patches/icedtea-jsoundhs.patch: Added two more diffs to remove all uses 
+	of jsoundhs and Headspace libraries.
+
 2008-11-07  Andrew John Hughes  <ahughes@redhat.com>
 
 	* Makefile.am: Remove unneeded citypeflow fix,
@@ -114,6 +349,165 @@
 	* ports/hotspot/src/cpu/zero/vm/relocInfo_zero.cpp:
 	Updated for HotSpot 14 b05.
 
+2008-11-07  Gary Benson  <gbenson@redhat.com>
+
+	* patches/icedtea-cc-interp-no-fer.patch: New file.
+	* Makefile.am (ICEDTEA_PATCHES): Apply the above.
+	* HACKING: Document the above.
+
+2008-11-07  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp
+	(Atomic::store_ptr): Implemented.
+
+2008-11-07  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/cpu/zero/vm/frame_zero.cpp
+	(frame::interpreter_frame_result): Implemented.
+
+2008-11-06  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
+	(JVM_handle_linux_signal): Added signal chaining,
+	abort_if_unrecognised, and stack overflow recognition.
+
+2008-11-06  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/cpu/zero/vm/globals_zero.hpp
+	(StackShadowPages): Increase for debug builds.
+
+2008-11-06  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
+	(CppInterpreter::native_entry): Unwind correctly if an
+	exception is thrown while setting up the call.
+
+2008-11-06  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
+	(CppInterpreter::native_entry): Add stack overflow check.
+
+2008-11-06  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp
+	(CppInterpreter::stack_overflow_imminent): New method.
+
+	* ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
+	(CppInterpreter::stack_overflow_imminent): New method.
+	(CppInterpreter::normal_entry): Add stack overflow check.
+
+2008-11-05  Deepak Bhole  <dbhole@redhat.com>
+
+	* patches/icedtea-copy-plugs.patch: Add netscape.* classes to rt.jar when
+	building with an alternate jar application.
+
+2008-11-05  Deepak Bhole  <dbhole@redhat.com>
+
+	* rt/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Correct
+	indentation from last commit, remove debug output.
+
+2008-11-05  Andrew Haley  <aph@redhat.com>
+	    Gary Benson  <gbenson@redhat.com>
+
+	* contrib/mixtec-hacks.patch: new file.
+
+2008-11-04  Deepak Bhole  <dbhole@redhat.com>
+
+	* rt/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Dynamically load
+	files from the index.
+
+2008-11-04  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/share/vm/shark/sharkRuntime.hpp
+	(SharkRuntime::_f2i): New constant.
+	(SharkRuntime::_f2l): Likewise.
+	(SharkRuntime::_d2i): Likewise.
+	(SharkRuntime::_d2l): Likewise.
+	(SharkRuntime::f2i): New accessor.
+	(SharkRuntime::f2l): Likewise.
+	(SharkRuntime::d2i): Likewise.
+	(SharkRuntime::d2l): Likewise.
+	* ports/hotspot/src/share/vm/shark/sharkRuntime.cpp
+	(SharkRuntime::_f2i): New constant.
+	(SharkRuntime::_f2l): Likewise.
+	(SharkRuntime::_d2i): Likewise.
+	(SharkRuntime::_d2l): Likewise.
+	(SharkRuntime::initialize): Initialize the above.
+	* ports/hotspot/src/share/vm/shark/sharkBlock.hpp
+	(SharkBlock::call_vm_leaf): New method.
+	* ports/hotspot/src/share/vm/shark/sharkBlock.cpp
+	(SharkBlock::parse): Use runtime calls for f2i, f2l, d2i and d2l.
+
+2008-11-04  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am (stamps/pulse-java.stamp): Link in libpulse.so after all
+	the object files that use it.
+	* pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java
+	(testWriteIntegralNumberFrames): New function. Tests that a SourceDataLine
+	will only write an integral number of frames.
+	(testWriteNegativeLength): New function. Tests that a
+	SourceDataLine.write() wont accept a negative length.
+	(testWriteNegativeOffset): New function. Tests that a
+	SourceDataLine.write() will not accept a negative offset.
+	(testWriteMoreThanArrayLength): New function. Tests that
+	SourceDataLine.write() wont write more than the length of the array.
+	(testWriteMoreThanArrayLength2): Likewise.
+	(testWriteWithoutStart): Added a check to avoid throwing an
+	IllegalStateException.
+
+2008-11-04  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/share/vm/shark/sharkBlock.cpp
+	(SharkBlock::parse): Fix syntax errors.
+
+2008-11-04  Gary Benson  <gbenson@redhat.com>
+
+	PR icedtea/244:
+	* patches/icedtea-f2i-overflow.patch: New file.
+	* Makefile.am (ICEDTEA_PATCHES): Apply the above.
+	* HACKING: Document the above.
+
+2008-11-03 Nix  <nix@esperi.org.uk>
+		   Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am (ICEDTEA_PATCHES): Added icedtea-linker-libs-order.patch.
+	* patches/icedtea-linker-libs-order.patch: Fixes icedtea bug#237.
+
+2008-11-03  Omair Majid  <omajid@redhat.com>
+
+	* patches/icedtea-alsa-default-device.patch: New patch. Use the ALSA 
+	'default' device if possible. Makes Java play nice with PulseAudio.
+
+2008-11-03  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/share/vm/shark/sharkBlock.cpp
+	(SharkBlock::parse): Fix shift instructions to use only the
+	lower order bits of the second argument.
+
+2008-11-03  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.inline.hpp
+	(BytecodeInterpreter::VMintShl): Only shift by the lower five bits.
+	(BytecodeInterpreter::VMintShr): Likewise.
+	(BytecodeInterpreter::VMintUshr): Likewise.
+
+2008-10-31  Deepak Bhole  <dbhole@redhat.com>
+
+	* IcedTeaPlugin.cc: Fix potential DoS issue when dealing with very long
+	URL/target addresses.
+	* plugin/icedtea/sun/applet/PluginAppletViewer.java: Decode param values
+	correctly.
+	* rt/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java: Bypass
+	authentication check when origin matches.
+	* rt/net/sourceforge/jnlp/security/AccessWarningPane.java: Show proper
+	Name/Publisher/Origin values when no certificate is associated.
+
+
+2008-10-31  Lillian Angel  <langel@redhat.com>
+
+	* Makefile.am: Updated for new visualvm 1.0.1.
+	* patches/icedtea-visualvm.patch: Updated.
+
 2008-10-30  Andrew John Hughes  <ahughes@redhat.com>
 
 	* Makefile.am: Add bootstrap-directory-symlink
@@ -142,6 +536,23 @@
 	* pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java:
 	Merged.
 
+2008-10-29  Mark Wielaard  <mark@klomp.org>
+
+	* patches/icedtea-6761856-freetypescaler.patch: New patch.
+	* Makefile.am (ICEDTEA_PATCHES): Add new patch.
+	* HACKING: Document new patch.
+
+2008-10-29  Gary Benson  <gbenson@redhat.com>
+
+	PR icedtea/238:
+	* ports/hotspot/src/share/vm/shark/sharkBlock.cpp
+	(SharkBlock::parse): Fix copy-and-paste error in f2l.
+
+2008-10-27  Deepak Bhole  <dbhole@redhat.com>
+
+	* rt/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java: Act on window
+	close events (Bug# 215)
+
 2008-10-27  Andrew John Hughes  <ahughes@redhat.com>
 
 	* acinclude.m4:
@@ -153,6 +564,10 @@
 
 2008-10-27  Lillian Angel  <langel@redhat.com>
 
+	* configure.ac: Updated version to 1.4.
+
+2008-10-27  Lillian Angel  <langel@redhat.com>
+
 	* NEWS: Updated for 1.3.1 release.
 
 2008-10-27  Andrew John Hughes  <ahughes@redhat.com>
--- a/HACKING	Mon Nov 17 12:41:07 2008 +0000
+++ b/HACKING	Mon Nov 17 15:26:51 2008 +0000
@@ -63,8 +63,13 @@
 * icedtea-arch.patch: Add support for additional architectures.
 * icedtea-alt-jar.patch: Add support for using an alternate jar tool in JDK building. 
 * icedtea-hotspot7-tests.patch: Adds hotspot compiler tests from jdk7 tree.
-* patches/icedtea-renderer-crossing.patch: Check whether crossing is
-  initialized in Pisces Renderer.
+* icedtea-renderer-crossing.patch: Check whether crossing is initialized in Pisces Renderer.
+* icedtea-f2i-overflow.patch: Replaces the code used by [fd]2[il] bytecodes to correctly handle overflows. (PR244)
+* icedtea-cc-interp-no-fer.patch: Report that we cannot force early returns with the C++ interpreter.
+* icedtea-6761856-freetypescaler.patch: Fix IcedTea bug #227, OpenJDK bug
+  #6761856, swing TextLayout.getBounds() returns shifted bounds.
+* icedtea-display-mode-changer.patch: Add extra test class.
+* icedtea-testenv.patch: Provide public reachable machines for net/nio tests.
 
 The following patches are only applied to OpenJDK6 in IcedTea6:
 
--- a/IcedTeaPlugin.cc	Mon Nov 17 12:41:07 2008 +0000
+++ b/IcedTeaPlugin.cc	Mon Nov 17 15:26:51 2008 +0000
@@ -1409,19 +1409,19 @@
   NS_DECL_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
-  GetURLRunnable (nsIPluginInstancePeer* peer, const char* url, const char* target);
+  GetURLRunnable (nsIPluginInstancePeer* peer, nsCString url, nsCString target);
 
   ~GetURLRunnable ();
 
 private:
   nsIPluginInstancePeer* peer;
-  const char* url;
-  const char* target;
+  nsCString url;
+  nsCString target;
 };
 
 NS_IMPL_ISUPPORTS1 (GetURLRunnable, nsIRunnable)
 
-GetURLRunnable::GetURLRunnable (nsIPluginInstancePeer* peer, const char* url, const char* target)
+GetURLRunnable::GetURLRunnable (nsIPluginInstancePeer* peer, nsCString url, nsCString target)
 : peer(peer),
   url(url),
   target(target)
@@ -1442,7 +1442,7 @@
    nsIPluginInstanceOwner* owner = nsnull;
    ownerGetter->GetOwner (&owner);
 
-   return owner->GetURL ((const char*) url, (const char*) target,
+   return owner->GetURL ((const char*) url.get(), (const char*) target.get(),
                          nsnull, 0, nsnull, 0);
 }
 
@@ -2869,8 +2869,8 @@
               ownerGetter->GetOwner (&owner);
 			  PLUGIN_DEBUG_2ARG ("Calling GetURL with %s and %s\n", nsCString (url).get (), nsCString (target).get ());
               nsCOMPtr<nsIRunnable> event = new GetURLRunnable (instance->peer,
-													 nsCString (url).get (),
-													 nsCString (target).get ());
+													 nsCString (url),
+													 nsCString (target));
               current->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
             }
         }
@@ -4062,7 +4062,11 @@
     {
       if (!factory->js_cleared_handles.Get(javascript_identifier, NULL))
 	  {
-        PLUGIN_DEBUG_2ARG ("Calling Eval: %d, %d\n", javascript_identifier, strSize);
+	    nsCString evStr("");
+		for (int i=0; i < strSize; i++)
+			evStr += nameString[i];
+
+        PLUGIN_DEBUG_2ARG ("Calling Eval: %d, %s\n", javascript_identifier, evStr.get());
         result = liveconnect->Eval(proxyEnv,
                                    javascript_identifier,
                                    nameString, strSize,
--- a/Makefile.am	Mon Nov 17 12:41:07 2008 +0000
+++ b/Makefile.am	Mon Nov 17 15:26:51 2008 +0000
@@ -1393,6 +1393,7 @@
         "BUILD_NUMBER=$(OPENJDK_VERSION)" \
 	"JDK_UPDATE_VERSION=$(JDK_UPDATE_VERSION)" \
         "JRE_RELEASE_VERSION=1.7.0_$(COMBINED_VERSION)" \
+	"MILESTONE=fcs" \
 	"LANG=C" \
 	"PATH=$(abs_top_builddir)/bootstrap/jdk1.6.0/bin:/usr/bin:/bin:/usr/sbin:/sbin" \
 	"ALT_BOOTDIR=$(ICEDTEA_BOOT_DIR)" \
@@ -1462,6 +1463,7 @@
 	"BUILD_NUMBER=$(OPENJDK_VERSION)" \
 	"JDK_UPDATE_VERSION=$(JDK_UPDATE_VERSION)" \
         "JRE_RELEASE_VERSION=1.7.0_$(COMBINED_VERSION)" \
+	"MILESTONE=fcs" \
 	"LANG=C" \
 	"PATH=$(abs_top_builddir)/bootstrap/jdk1.6.0/bin:/usr/bin:/bin:/usr/sbin:/sbin" \
 	"ALT_BOOTDIR=$(ICEDTEA_BOOT_DIR)" \
@@ -1584,7 +1586,7 @@
 if USE_ALT_VISUALVM_SRC_ZIP
   VISUALVM_SRC_ZIP = $(ALT_VISUALVM_SRC_ZIP)
 else
-  VISUALVM_SRC_ZIP = visualvm-20080728-src.tar.gz
+  VISUALVM_SRC_ZIP = visualvm-20081031-src.tar.gz
 endif
 
 stamps/download.stamp: stamps/hgforest.stamp
@@ -1839,6 +1841,13 @@
 	patches/icedtea-snmp.patch \
 	patches/icedtea-sound.patch \
 	patches/icedtea-tests-jdk.patch \
+	patches/icedtea-alsa-default-device.patch \
+	patches/icedtea-linker-libs-order.patch \
+	patches/icedtea-f2i-overflow.patch \
+	patches/icedtea-cc-interp-no-fer.patch \
+	patches/icedtea-6761856-freetypescaler.patch \
+	patches/icedtea-display-mode-changer.patch \
+	patches/icedtea-testenv.patch \
 	$(ZERO_PATCHES_COND)
 
 if WITH_RHINO
@@ -2825,7 +2834,7 @@
 	$(CC) $(LIBPULSE_CFLAGS) $(CFLAGS) -fPIC -c -I$(ICEDTEA_BOOT_DIR)/include/linux -I$(ICEDTEA_BOOT_DIR)/include $(PULSE_JAVA_NATIVE_SRCDIR)/org_classpath_icedtea_pulseaudio_Stream.c
 	$(CC) $(LIBPULSE_CFLAGS) $(CFLAGS) -fPIC -c -I$(ICEDTEA_BOOT_DIR)/include/linux -I$(ICEDTEA_BOOT_DIR)/include $(PULSE_JAVA_NATIVE_SRCDIR)/org_classpath_icedtea_pulseaudio_PulseAudioSourcePort.c 
 	$(CC) $(LIBPULSE_CFLAGS) $(CFLAGS) -fPIC -c -I$(ICEDTEA_BOOT_DIR)/include/linux -I$(ICEDTEA_BOOT_DIR)/include $(PULSE_JAVA_NATIVE_SRCDIR)/org_classpath_icedtea_pulseaudio_PulseAudioTargetPort.c
-	$(CC) $(LDFLAGS) -shared $(LIBPULSE_LIBS) -o libpulse-java.so org_*pulseaudio*.o jni-common.o
+	$(CC) $(LDFLAGS) -shared org_*pulseaudio*.o jni-common.o $(LIBPULSE_LIBS) -o libpulse-java.so 
 	mv org_classpath_icedtea_pulseaudio_*.o $(PULSE_JAVA_CLASS_DIR)
 	mv jni-common.o $(PULSE_JAVA_CLASS_DIR)
 endif
@@ -2935,7 +2944,7 @@
 	mkdir -p test/langtools/JTwork test/langtools/JTreport
 	$(ICEDTEA_BOOT_DIR)/bin/java -jar test/jtreg.jar -v1 -a -ignore:quiet \
 		-w:test/langtools/JTwork -r:test/langtools/JTreport \
-		-jdk:`pwd`/$(BUILD_OUTPUT_DIR)/j2sdk-image \
+		-s -jdk:`pwd`/$(BUILD_OUTPUT_DIR)/j2sdk-image \
 		-exclude:$(abs_top_srcdir)/test/jtreg/excludelist.langtools.jtx \
 		`pwd`/openjdk/langtools/test \
 	    | tee test/$@.log
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/mixtec-hacks.patch	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,104 @@
+diff -r 4f4d268762d7 Makefile.am
+--- a/Makefile.am	Wed Aug 20 04:24:45 2008 -0400
++++ b/Makefile.am	Thu Aug 28 03:53:35 2008 -0400
+@@ -442,6 +442,13 @@
+ endif
+ 
+ ICEDTEA_FSG_PATCHES =
++
++# Build with assertions and lowered optimization
++DISTRIBUTION_PATCHES = \
++	patches/mixtec-assertions.patch \
++	patches/mixtec-no-log-vm-output.patch \
++	patches/mixtec-no-print-vm-options.patch \
++	patches/mixtec-optimization.patch
+ 
+ ICEDTEA_PATCHES = \
+ 	$(ZERO_PATCHES_COND) \
+diff -r 4f4d268762d7 patches/mixtec-assertions.patch
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/patches/mixtec-assertions.patch	Thu Aug 28 03:53:35 2008 -0400
+@@ -0,0 +1,14 @@
++diff -r d384f5a5bd0c hotspot/build/linux/makefiles/product.make
++--- openjdk/hotspot/build/linux/makefiles/product.make	Mon Aug 06 13:11:51 2007 +0100
+++++ openjdk/hotspot/build/linux/makefiles/product.make	Fri Sep 14 09:58:33 2007 +0100
++@@ -41,8 +41,8 @@ MAPFILE = $(GAMMADIR)/build/linux/makefi
++ MAPFILE = $(GAMMADIR)/build/linux/makefiles/mapfile-vers-product
++ 
++ G_SUFFIX =
++-SYSDEFS += -DPRODUCT
++-VERSION = optimized
+++SYSDEFS += -DASSERT
+++VERSION = mixtec
++ 
++ # use -g to strip library as -x will discard its symbol table; -x is fine for
++ # executables.
+diff -r 4f4d268762d7 patches/mixtec-no-log-vm-output.patch
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/patches/mixtec-no-log-vm-output.patch	Thu Aug 28 03:53:35 2008 -0400
+@@ -0,0 +1,11 @@
++--- openjdk-ecj/hotspot/src/share/vm/runtime/globals.hpp	2007-11-13 09:19:54.000000000 -0500
+++++ openjdk/hotspot/src/share/vm/runtime/globals.hpp	2007-11-13 17:13:24.000000000 -0500
++@@ -2081,7 +2081,7 @@
++   diagnostic(bool, DisplayVMOutput, true,                                   \
++          "Display all VM output on the tty, independently of LogVMOutput")  \
++                                                                             \
++-  diagnostic(bool, LogVMOutput, trueInDebug,                                \
+++  diagnostic(bool, LogVMOutput, false,                                      \
++          "Save VM output to hotspot.log, or to LogFile")                    \
++                                                                             \
++   diagnostic(ccstr, LogFile, NULL,                                          \
+diff -r 4f4d268762d7 patches/mixtec-no-print-vm-options.patch
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/patches/mixtec-no-print-vm-options.patch	Thu Aug 28 03:53:35 2008 -0400
+@@ -0,0 +1,12 @@
++diff -r c5904941581b openjdk-ecj/hotspot/src/share/vm/runtime/globals.hpp
++--- openjdk/hotspot/src/share/vm/runtime/globals.hpp	Tue Nov 13 14:09:56 2007 +0000
+++++ openjdk/hotspot/src/share/vm/runtime/globals.hpp	Tue Nov 13 14:19:54 2007 +0000
++@@ -2072,7 +2072,7 @@ class CommandLineFlags {
++   diagnostic(bool, DebugInlinedCalls, true,                                 \
++          "If false, restricts profiled locations to the root method only")  \
++                                                                             \
++-  product(bool, PrintVMOptions, trueInDebug,                                \
+++  product(bool, PrintVMOptions, false,                                      \
++          "print VM flag settings")                                          \
++                                                                             \
++   diagnostic(bool, SerializeVMOutput, true,                                 \
+diff -r 4f4d268762d7 patches/mixtec-optimization.patch
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/patches/mixtec-optimization.patch	Thu Aug 28 03:53:35 2008 -0400
+@@ -0,0 +1,34 @@
++diff -urN openjdk.orig/hotspot/build/linux/makefiles/gcc.make openjdk/hotspot/build/linux/makefiles/gcc.make
++--- openjdk.orig/hotspot/build/linux/makefiles/gcc.make	2007-10-12 03:46:25.000000000 -0400
+++++ openjdk/hotspot/build/linux/makefiles/gcc.make	2007-10-12 17:41:02.000000000 -0400
++@@ -111,7 +111,7 @@
++ CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@)) 
++ 
++ # The flags to use for an Optimized g++ build
++-OPT_CFLAGS += -O3
+++OPT_CFLAGS += -O0
++ 
++ # Hotspot uses very unstrict aliasing turn this optimization off
++ OPT_CFLAGS += -fno-strict-aliasing
++diff -urN openjdk.orig/j2se/make/common/Defs-linux.gmk openjdk/j2se/make/common/Defs-linux.gmk
++--- openjdk.orig/jdk/make/common/Defs-linux.gmk	2007-10-12 03:54:05.000000000 -0400
+++++ openjdk/jdk/make/common/Defs-linux.gmk	2007-10-12 17:41:02.000000000 -0400
++@@ -97,6 +97,7 @@
++     _OPT = $(CC_LOWER_OPT)
++     CPPFLAGS_DBG    += -DLOGGING 
++ endif
+++_OPT = -O0
++ 
++ # For all platforms, do not omit the frame pointer register usage. 
++ #    We need this frame pointer to make it easy to walk the stacks.
++diff -r e847abdac6f6 openjdk/corba/make/common/Defs-linux.gmk
++--- openjdk/corba/make/common/Defs-linux.gmk	Thu Nov 22 08:57:34 2007 +0000
+++++ openjdk/corba/make/common/Defs-linux.gmk	Thu Nov 22 08:59:18 2007 +0000
++@@ -87,6 +87,7 @@ else
++     _OPT = $(CC_LOWER_OPT)
++     CPPFLAGS_DBG    += -DLOGGING 
++ endif
+++_OPT = -O0
++ 
++ # For all platforms, do not omit the frame pointer register usage. 
++ #    We need this frame pointer to make it easy to walk the stacks.
--- a/fsg.sh	Mon Nov 17 12:41:07 2008 +0000
+++ b/fsg.sh	Mon Nov 17 15:26:51 2008 +0000
@@ -82,11 +82,6 @@
 rm -f \
   openjdk/jdk/test/sun/net/idn/nfscis.spp
 
-# has w3c copyright. license to be checked / needs checking after decoding
-rm -f \
-  openjdk/jdk/test/javax/xml/crypto/dsig/data/xml-stylesheet \
-  openjdk/jdk/test/javax/xml/crypto/dsig/data/xml-stylesheet.b64
-
 # TODO
 #$ find openjdk -name '*.jar' -o -name '*.class'|grep -v test
 
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt	Mon Nov 17 12:41:07 2008 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt	Mon Nov 17 15:26:51 2008 +0000
@@ -1,3 +1,14 @@
+  - Fix: Throw IllegalArgumentException Exception on
+         invalid soundbank to:
+         SoftSynthesizer.unloadAllInstruments(Soundbank soundbank)
+         SoftSynthesizer.unloadInstruments(Soundbank soundbank, Patch[] patchList)
+         just like done in:
+         SoftSynthesizer.unloadInstrument(Instrument instrument).
+  - Change: SoftMainMixer, SoftVoice optimized for mono voices.
+  - Change: SoftFilter optimized. 
+  - Fix: Turn SoftJitterCorrector, SoftAudioPusher threads into a daemon threads.
+         These threads prevented the VM to exit when synthesizer was open.
+         See: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=213 
   - Add: More JTreg tests added:
            EmergencySoundbank
            SoftFilter
@@ -6,6 +17,8 @@
   - Fix: ModelByteBuffer.skip called super.skip
          instead to call to RandomAccessFile directly.
          JTreg tests added: ModelByteBuffer/RandomFileInputStream/*.java
+         
+Version 1.0.2 (released in OpenJDK 6 b12)   
   - Fix: ModelByteBuffer.len was being modified in inner
          class RandomFileInputStream. The variable was made final
          and RandomFileInputStream.read methods where fixed.
@@ -13,7 +26,7 @@
          Keys array was to small, it couldn't
          hold all possible midi notes (0..127).
 
-Version 1.0.1
+Version 1.0.1 (released as 1.0)
   - Fix: Created dummy SourceDataline so that following 
          jtreg test can be tested without using
          a real Audio Device SourceDataLine.  
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioPusher.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioPusher.java	Mon Nov 17 15:26:51 2008 +0000
@@ -54,6 +54,7 @@
             return;
         active = true;
         audiothread = new Thread(this);
+        audiothread.setDaemon(true);
         audiothread.setPriority(Thread.MAX_PRIORITY);
         audiothread.start();
     }
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftFilter.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftFilter.java	Mon Nov 17 15:26:51 2008 +0000
@@ -543,8 +543,6 @@
 
     public void filter1(SoftAudioBuffer sbuffer) {
 
-        float[] buffer = sbuffer.array();
-
         if (dirty) {
             filter1calc();
             dirty = false;
@@ -559,6 +557,7 @@
 
         if (wet > 0 || last_wet > 0) {
 
+            float[] buffer = sbuffer.array();
             int len = buffer.length;
             float a0 = this.last_a0;
             float q = this.last_q;
@@ -577,14 +576,16 @@
                     q += q_delta;
                     gain += gain_delta;
                     wet += wet_delta;
-                    y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i];
-                    y2 = (1 - q * a0) * y2 + (a0) * y1;
+                    float ga0 = (1 - q * a0);
+                    y1 = ga0 * y1 + (a0) * (buffer[i] - y2);
+                    y2 = ga0 * y2 + (a0) * y1;
                     buffer[i] = y2 * gain * wet + buffer[i] * (1 - wet);
                 }
             } else if (a0_delta == 0 && q_delta == 0) {
+                float ga0 = (1 - q * a0);
                 for (int i = 0; i < len; i++) {
-                    y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i];
-                    y2 = (1 - q * a0) * y2 + (a0) * y1;
+                    y1 = ga0 * y1 + (a0) * (buffer[i] - y2);
+                    y2 = ga0 * y2 + (a0) * y1;
                     buffer[i] = y2 * gain;
                 }
             } else {
@@ -592,8 +593,9 @@
                     a0 += a0_delta;
                     q += q_delta;
                     gain += gain_delta;
-                    y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i];
-                    y2 = (1 - q * a0) * y2 + (a0) * y1;
+                    float ga0 = (1 - q * a0);
+                    y1 = ga0 * y1 + (a0) * (buffer[i] - y2);
+                    y2 = ga0 * y2 + (a0) * y1;
                     buffer[i] = y2 * gain;
                 }
             }
@@ -611,4 +613,4 @@
         this.last_gain = this.gain;
         this.last_wet = this.wet;
     }
-}
+}
\ No newline at end of file
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java	Mon Nov 17 15:26:51 2008 +0000
@@ -216,6 +216,7 @@
             };
 
             thread = new Thread(runnable);
+            thread.setDaemon(true);
             thread.setPriority(Thread.MAX_PRIORITY);
             thread.start();
         }
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java	Mon Nov 17 15:26:51 2008 +0000
@@ -48,16 +48,18 @@
 
     public final static int CHANNEL_LEFT = 0;
     public final static int CHANNEL_RIGHT = 1;
-    public final static int CHANNEL_EFFECT1 = 2;
-    public final static int CHANNEL_EFFECT2 = 3;
-    public final static int CHANNEL_EFFECT3 = 4;
-    public final static int CHANNEL_EFFECT4 = 5;
+    public final static int CHANNEL_MONO = 2;
+    public final static int CHANNEL_EFFECT1 = 3;
+    public final static int CHANNEL_EFFECT2 = 4;
+    public final static int CHANNEL_EFFECT3 = 5;
+    public final static int CHANNEL_EFFECT4 = 6;
     public final static int CHANNEL_LEFT_DRY = 10;
     public final static int CHANNEL_RIGHT_DRY = 11;
     public final static int CHANNEL_SCRATCH1 = 12;
     public final static int CHANNEL_SCRATCH2 = 13;
     public final static int CHANNEL_CHANNELMIXER_LEFT = 14;
     public final static int CHANNEL_CHANNELMIXER_RIGHT = 15;
+    public final static int CHANNEL_CHANNELMIXER_MONO = 16;
     protected boolean active_sensing_on = false;
     private long msec_last_activity = -1;
     private boolean pusher_silent = false;
@@ -485,8 +487,10 @@
             // to channelmixer left,right input/output
             SoftAudioBuffer leftbak = buffers[CHANNEL_LEFT];
             SoftAudioBuffer rightbak = buffers[CHANNEL_RIGHT];
+            SoftAudioBuffer monobak = buffers[CHANNEL_MONO];
             buffers[CHANNEL_LEFT] = buffers[CHANNEL_CHANNELMIXER_LEFT];
-            buffers[CHANNEL_RIGHT] = buffers[CHANNEL_CHANNELMIXER_LEFT];
+            buffers[CHANNEL_RIGHT] = buffers[CHANNEL_CHANNELMIXER_RIGHT];
+            buffers[CHANNEL_MONO] = buffers[CHANNEL_CHANNELMIXER_MONO];
 
             int bufferlen = buffers[CHANNEL_LEFT].getSize();
 
@@ -503,6 +507,7 @@
             for (ModelChannelMixer cmixer : act_registeredMixers) {
                 for (int i = 0; i < cbuffer.length; i++)
                     Arrays.fill(cbuffer[i], 0);
+                buffers[CHANNEL_MONO].clear();
                 boolean hasactivevoices = false;
                 for (int i = 0; i < voicestatus.length; i++)
                     if (voicestatus[i].active)
@@ -516,6 +521,26 @@
                         cur_registeredMixers = null;
                     }
                 }
+                
+                if(!buffers[CHANNEL_MONO].isSilent())
+                {
+                    float[] mono = buffers[CHANNEL_MONO].array();
+                    float[] left = buffers[CHANNEL_LEFT].array();            
+                    if (nrofchannels != 1) {
+                        float[] right = buffers[CHANNEL_RIGHT].array();
+                        for (int i = 0; i < bufferlen; i++) {
+                            float v = mono[i];
+                            left[i] += v;
+                            right[i] += v;
+                        }                
+                    }
+                    else
+                    {
+                        for (int i = 0; i < bufferlen; i++) {
+                            left[i] += mono[i];
+                        }                                
+                    }                              
+                }                
 
                 for (int i = 0; i < cbuffer.length; i++) {
                     float[] cbuff = cbuffer[i];
@@ -539,6 +564,7 @@
 
             buffers[CHANNEL_LEFT] = leftbak;
             buffers[CHANNEL_RIGHT] = rightbak;
+            buffers[CHANNEL_MONO] = monobak;
 
         }
 
@@ -546,6 +572,27 @@
             if (voicestatus[i].active)
                 if (voicestatus[i].channelmixer == null)
                     voicestatus[i].processAudioLogic(buffers);
+        
+        if(!buffers[CHANNEL_MONO].isSilent())
+        {
+            float[] mono = buffers[CHANNEL_MONO].array();
+            float[] left = buffers[CHANNEL_LEFT].array();            
+            int bufferlen = buffers[CHANNEL_LEFT].getSize();
+            if (nrofchannels != 1) {
+                float[] right = buffers[CHANNEL_RIGHT].array();
+                for (int i = 0; i < bufferlen; i++) {
+                    float v = mono[i];
+                    left[i] += v;
+                    right[i] += v;
+                }                
+            }
+            else
+            {
+                for (int i = 0; i < bufferlen; i++) {
+                    left[i] += mono[i];
+                }                                
+            }            
+        }
 
         // Run effects
         if (synth.chorus_on)
@@ -665,7 +712,7 @@
                                 / synth.getControlRate());
 
         control_mutex = synth.control_mutex;
-        buffers = new SoftAudioBuffer[16];
+        buffers = new SoftAudioBuffer[17];
         for (int i = 0; i < buffers.length; i++) {
             buffers[i] = new SoftAudioBuffer(buffersize, synth.getFormat());
         }
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftVoice.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftVoice.java	Mon Nov 17 15:26:51 2008 +0000
@@ -782,6 +782,7 @@
 
         SoftAudioBuffer left = buffer[SoftMainMixer.CHANNEL_LEFT];
         SoftAudioBuffer right = buffer[SoftMainMixer.CHANNEL_RIGHT];
+        SoftAudioBuffer mono = buffer[SoftMainMixer.CHANNEL_MONO];
         SoftAudioBuffer eff1 = buffer[SoftMainMixer.CHANNEL_EFFECT1];
         SoftAudioBuffer eff2 = buffer[SoftMainMixer.CHANNEL_EFFECT2];
         SoftAudioBuffer leftdry = buffer[SoftMainMixer.CHANNEL_LEFT_DRY];
@@ -802,17 +803,26 @@
             if (rightdry != null)
                 mixAudioStream(rightdry, left, last_out_mixer_left,
                         out_mixer_left);
-        } else {
-            mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left);
-            if (rightdry != null)
-                mixAudioStream(rightdry, right, last_out_mixer_right,
+        } else {            
+            if(rightdry == null && 
+                    last_out_mixer_left == last_out_mixer_right &&
+                    out_mixer_left == out_mixer_right)
+            {
+                mixAudioStream(leftdry, mono, last_out_mixer_left, out_mixer_left);
+            }
+            else
+            {
+                mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left);
+                if (rightdry != null)
+                    mixAudioStream(rightdry, right, last_out_mixer_right,
                         out_mixer_right);
-            else
-                mixAudioStream(leftdry, right, last_out_mixer_right,
+                else
+                    mixAudioStream(leftdry, right, last_out_mixer_right,
                         out_mixer_right);
+            }
         }
 
-        if (rightdry == null) {
+        if (rightdry == null) {            
             mixAudioStream(leftdry, eff1, last_out_mixer_effect1,
                     out_mixer_effect1);
             mixAudioStream(leftdry, eff2, last_out_mixer_effect2,
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Mon Nov 17 15:26:51 2008 +0000
@@ -17,24 +17,44 @@
 
 package net.sourceforge.jnlp.runtime;
 
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.jar.*;
-import java.security.*;
-import java.lang.reflect.*;
-import javax.jnlp.*;
-import javax.swing.JOptionPane;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Vector;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
 
-
-import java.security.cert.Certificate;
-
-import net.sourceforge.jnlp.*;
-import net.sourceforge.jnlp.cache.*;
-import net.sourceforge.jnlp.security.*;
-import net.sourceforge.jnlp.services.*;
+import net.sourceforge.jnlp.ExtensionDesc;
+import net.sourceforge.jnlp.JARDesc;
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.LaunchException;
+import net.sourceforge.jnlp.ParseException;
+import net.sourceforge.jnlp.PluginBridge;
+import net.sourceforge.jnlp.ResourcesDesc;
+import net.sourceforge.jnlp.SecurityDesc;
+import net.sourceforge.jnlp.cache.CacheUtil;
+import net.sourceforge.jnlp.cache.ResourceTracker;
+import net.sourceforge.jnlp.cache.UpdatePolicy;
+import net.sourceforge.jnlp.security.SecurityWarningDialog;
 import net.sourceforge.jnlp.tools.JarSigner;
-import net.sourceforge.jnlp.tools.KeyTool;
+import sun.misc.JarIndex;
 
 /**
  * Classloader that takes it's resources from a JNLP file.  If the
@@ -109,6 +129,8 @@
 	private JarSigner js = null;
 
 	private boolean signing = false;
+	
+	private ArrayList<JarIndex> jarIndexes = new ArrayList<JarIndex>();
 
     /**
      * Create a new JNLPClassLoader from the specified file.
@@ -469,6 +491,11 @@
 
                         addURL(location);
 
+                        // there is currently no mechanism to cache files per 
+                        // instance.. so only index cached files
+                        if (localFile != null)
+                        	jarIndexes.add(JarIndex.getJarIndex(new JarFile(localFile.getAbsolutePath()), null));
+
                         if (JNLPRuntime.isDebug())
                             System.err.println("Activate jar: "+location);
                     }
@@ -635,6 +662,7 @@
      * extensions.
      */
     public Class loadClass(String name) throws ClassNotFoundException {
+
         Class result = findLoadedClassAll(name);
 
         // try parent classloader
@@ -654,7 +682,60 @@
 
         // search this and the extension loaders
         if (result == null)
-            result = loadClassExt(name);
+            try {
+                result = loadClassExt(name);
+            } catch (ClassNotFoundException cnfe) {
+
+                // Not found in external loader either. As a last resort, look in any available indexes
+
+                // Currently this loads jars directly from the site. We cannot cache it because this 
+                // call is initiated from within the applet, which does not have disk read/write permissions
+                for (JarIndex index: jarIndexes) {
+                    LinkedList<String> jarList = index.get(name.replace('.', '/'));
+
+                    if (jarList != null) {
+                        for (String jarName: jarList) {
+                            JARDesc desc;
+                            try {
+                                desc = new JARDesc(new URL(file.getCodeBase(), jarName),
+                                        null, null, false, true, false);
+                            } catch (MalformedURLException mfe) {
+                                throw new ClassNotFoundException(name);
+                            }
+
+                            available.add(desc);
+
+                            tracker.addResource(desc.getLocation(), 
+                                    desc.getVersion(), 
+                                    JNLPRuntime.getDefaultUpdatePolicy()
+                            );
+
+                            URL remoteURL;
+                            try {
+                                remoteURL = new URL(file.getCodeBase() + jarName);
+                            } catch (MalformedURLException mfe) {
+                                throw new ClassNotFoundException(name);
+                            }
+
+                            URL u;
+
+                            try {
+                                u = tracker.getCacheURL(remoteURL);
+                                System.out.println("URL = " + u);
+                            } catch (Exception e) {
+                                throw new ClassNotFoundException(name);
+                            }
+
+                            if (u != null)
+                                addURL(u);
+
+                        }
+
+                        // If it still fails, let it error out
+                        result = loadClassExt(name);
+                    }
+                }
+            }
 
         return result;
     }
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java	Mon Nov 17 15:26:51 2008 +0000
@@ -17,20 +17,24 @@
 
 package net.sourceforge.jnlp.runtime;
 
-import java.awt.*;
-import java.awt.event.*;
-import java.lang.ref.*;
-import javax.swing.*;
-import java.security.*;
+import java.awt.Frame;
+import java.awt.Window;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.lang.ref.WeakReference;
+import java.net.SocketPermission;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
 
+import javax.swing.JWindow;
+
+import net.sourceforge.jnlp.JNLPFile;
 import net.sourceforge.jnlp.security.SecurityWarningDialog;
 import net.sourceforge.jnlp.services.ServiceUtil;
-import net.sourceforge.jnlp.util.*;
-
+import net.sourceforge.jnlp.util.WeakList;
 import sun.security.util.SecurityConstants;
 
-import java.net.SocketPermission;
-
 /**
  * Security manager for JNLP environment.  This security manager
  * cannot be replaced as it always denies attempts to replace the
@@ -122,6 +126,11 @@
         public void windowDeactivated(WindowEvent e) {
             activeApplication = null;
         }
+        
+        public void windowClosing(WindowEvent e) {
+        	System.err.println("Disposing window");
+        	e.getWindow().dispose();
+        }
     };
 
 
@@ -278,6 +287,46 @@
 				if (perm instanceof SocketPermission) {
 					tmpPerm = new SocketPermission(perm.getName(), 
 							SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION);
+					
+					// before proceeding, check if we are trying to connect to same origin
+					ApplicationInstance app = getApplication();
+					JNLPFile file = app.getJNLPFile();
+
+					String srcHost =  file.getSourceLocation().getAuthority();
+					String destHost = name;
+					
+					// host = abc.xyz.com or abc.xyz.com:<port> 
+					if (destHost.indexOf(':') >= 0)
+						destHost = destHost.substring(0, destHost.indexOf(':'));
+					
+					// host = abc.xyz.com
+					String[] hostComponents = destHost.split("\\.");
+					
+					int length = hostComponents.length;
+					if (length >= 2) {
+						
+						// address is in xxx.xxx.xxx format
+						destHost = hostComponents[length -2] + "." + hostComponents[length -1];
+					
+						// host = xyz.com i.e. origin
+						boolean isDestHostName = false;
+
+						// make sure that it is not an ip address
+						try {
+							Integer.parseInt(hostComponents[length -1]);
+						} catch (NumberFormatException e) {
+							isDestHostName = true;
+						}
+
+						if (isDestHostName) {
+							// okay, destination is hostname. Now figure out if it is a subset of origin
+							if (srcHost.endsWith(destHost)) {
+								addPermission(tmpPerm);
+								return;
+							}
+						}
+					}
+
 				} else
 					tmpPerm = perm;
 				
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AccessWarningPane.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/security/AccessWarningPane.java	Mon Nov 17 15:26:51 2008 +0000
@@ -84,18 +84,19 @@
 		//We don't worry about exceptions when trying to fill in
 		//these strings -- we just want to fill in as many as possible.
 		try {
-			name = file.getInformation().getTitle();
+			name = file.getInformation().getTitle() != null ? file.getInformation().getTitle() : "<no associated certificate>";
 		} catch (Exception e) {
 		}
 
 		try {
-			publisher = file.getInformation().getVendor();
+			publisher = file.getInformation().getVendor() != null ? file.getInformation().getVendor() : "<no associated certificate>";
 		} catch (Exception e) {
 		}
 
 		try {
-			from = file.getInformation().getHomepage().toString();
+			from = !file.getInformation().getHomepage().toString().equals("") ? file.getInformation().getHomepage().toString() : file.getSourceLocation().getAuthority();
 		} catch (Exception e) {
+			from = file.getSourceLocation().getAuthority();
 		}
 
 		//Top label
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-6761856-freetypescaler.patch	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,47 @@
+# User igor
+# Date 1225234342 -10800
+# Node ID 9cdababf6179bd03270d881740fbb5dcc405854f
+# Parent 594c52582b21063bdbc36b38d9f73a3c46abe041
+6761856: OpenJDK: vertical text metrics may be significanly different from those returned by Sun JDK
+Reviewed-by: bae, prr
+
+--- openjdk.orig/jdk/src/share/native/sun/font/freetypeScaler.c	Tue Oct 28 14:47:14 2008 -0700
++++ openjdk/jdk/src/share/native/sun/font/freetypeScaler.c	Wed Oct 29 01:52:22 2008 +0300
+@@ -1281,7 +1281,7 @@ Java_sun_font_FreetypeFontScaler_getGlyp
+                                    sunFontIDs.rect2DFloatClass,
+                                    sunFontIDs.rect2DFloatCtr4,
+                                    F26Dot6ToFloat(bbox.xMin),
+-                                   F26Dot6ToFloat(bbox.yMax),
++                                   F26Dot6ToFloat(-bbox.yMax),
+                                    F26Dot6ToFloat(bbox.xMax-bbox.xMin),
+                                    F26Dot6ToFloat(bbox.yMax-bbox.yMin));
+     }
+--- openjdk.orig/jdk/test/java/awt/font/TextLayout/TextLayoutBounds.java	Tue Oct 28 14:47:14 2008 -0700
++++ openjdk/jdk/test/java/awt/font/TextLayout/TextLayoutBounds.java	Wed Oct 29 01:52:22 2008 +0300
+@@ -22,7 +22,7 @@
+  */
+ /* @test
+  * @summary verify TextLayout.getBounds() return visual bounds
+- * @bug 6323611
++ * @bug 6323611 6761856
+  */
+ 
+ import java.awt.*;
+@@ -39,10 +39,15 @@ public class TextLayoutBounds {
+        Rectangle2D tlBounds = tl.getBounds();
+        GlyphVector gv = f.createGlyphVector(frc, s);
+        Rectangle2D gvvBounds = gv.getVisualBounds();
++       Rectangle2D oBounds = tl.getOutline(null).getBounds2D();
+        System.out.println("tlbounds="+tlBounds);
+        System.out.println("gvbounds="+gvvBounds);
++       System.out.println("outlineBounds="+oBounds);
+        if (!gvvBounds.equals(tlBounds)) {
+-          throw new RuntimeException("Bounds differ");
++          throw new RuntimeException("Bounds differ [gvv != tl]");
++       }
++       if (!tlBounds.equals(oBounds)) {
++          throw new RuntimeException("Bounds differ [tl != outline]");
+        }
+     }
+ }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-alsa-default-device.patch	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,17 @@
+diff -uNr openjdk-orig/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCM.c openjdk/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCM.c
+--- openjdk-orig/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCM.c	2008-11-03 15:02:16.000000000 -0500
++++ openjdk/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCM.c	2008-11-03 15:08:07.000000000 -0500
+@@ -143,8 +143,12 @@
+             ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
+         } else {
+             ret = snd_pcm_hw_params_any(handle, hwParams);
+-            if (ret != 0) {
++            /* snd_pcm_hw_params_any can return a positive value on success too */
++            if (ret < 0) {
+                 ERROR1("snd_pcm_hw_params_any returned error %d\n", ret);
++            } else {
++                /* for the logic following this code, set ret to 0 to indicate success */
++                ret = 0;
+             }
+         }
+         snd_pcm_hw_params_get_format_mask(hwParams, formatMask);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-cc-interp-no-fer.patch	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,15 @@
+diff -r 11b9bdd4bbd3 openjdk/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp
+--- openjdk/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp	Fri Nov 07 10:53:57 2008 +0000
++++ openjdk/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp	Fri Nov 07 11:29:34 2008 +0000
+@@ -116,7 +116,11 @@ jvmtiCapabilities JvmtiManageCapabilitie
+   
+   memset(&jc, 0, sizeof(jc));
+   jc.can_pop_frame = 1;
++#ifdef CC_INTERP
++  jc.can_force_early_return = 0;
++#else
+   jc.can_force_early_return = 1;
++#endif // CC_INTERP
+   jc.can_get_source_debug_extension = 1;
+   jc.can_access_local_variables = 1;
+   jc.can_maintain_original_method_order = 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-display-mode-changer.patch	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,100 @@
+6733718: test /java/awt/FullScreen/UninitializedDisplayModeChangeTest/ fails
+Reviewed-by: igor
+
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ openjdk/jdk/test/java/awt/FullScreen/UninitializedDisplayModeChangeTest/DisplayModeChanger.java	Tue Aug 05 09:37:03 2008 -0700
+@@ -0,0 +1,93 @@
++/*
++ * Copyright 2006-2008 Sun Microsystems, Inc.  All Rights Reserved.
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * This code is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 only, as
++ * published by the Free Software Foundation.
++ *
++ * This code 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 General Public License
++ * version 2 for more details (a copy is included in the LICENSE file that
++ * accompanied this code).
++ *
++ * You should have received a copy of the GNU General Public License version
++ * 2 along with this work; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
++ * CA 95054 USA or visit www.sun.com if you need additional information or
++ * have any questions.
++ */
++
++import java.awt.DisplayMode;
++import java.awt.EventQueue;
++import java.awt.Frame;
++import java.awt.GraphicsDevice;
++import java.awt.GraphicsEnvironment;
++import java.lang.reflect.InvocationTargetException;
++
++/**
++ * Used by the UninitializedDisplayModeChangeTest to change the
++ * display mode.
++ */
++public class DisplayModeChanger {
++
++    public static void main(String[] args)
++        throws InterruptedException, InvocationTargetException
++    {
++        final GraphicsDevice gd =
++            GraphicsEnvironment.getLocalGraphicsEnvironment().
++                getDefaultScreenDevice();
++
++        EventQueue.invokeAndWait(new Runnable() {
++            public void run() {
++                Frame f = null;
++                if (gd.isFullScreenSupported()) {
++                    try {
++                        f = new Frame("DisplayChanger Frame");
++                        gd.setFullScreenWindow(f);
++                        if (gd.isDisplayChangeSupported()) {
++                            DisplayMode dm = findDisplayMode(gd);
++                            if (gd != null) {
++                                gd.setDisplayMode(dm);
++                            }
++                        }
++                        try {
++                            Thread.sleep(1000);
++                        } catch (InterruptedException ex) {
++                            ex.printStackTrace();
++                        }
++                        gd.setFullScreenWindow(null);
++                    } finally {
++                        if (f != null) {
++                            f.dispose();
++                        }
++                    }
++                }
++            }
++        });
++    }
++
++    /**
++     * Finds a display mode that is different from the current display
++     * mode and is likely to cause a display change event.
++     */
++    private static DisplayMode findDisplayMode(GraphicsDevice gd) {
++        DisplayMode dms[] = gd.getDisplayModes();
++        DisplayMode currentDM = gd.getDisplayMode();
++        for (DisplayMode dm : dms) {
++            if (!dm.equals(currentDM) &&
++                 dm.getRefreshRate() == currentDM.getRefreshRate())
++            {
++                // different from the current dm and refresh rate is the same
++                // means that something else is different => more likely to
++                // cause a DM change event
++                return dm;
++            }
++        }
++        return null;
++    }
++
++}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-f2i-overflow.patch	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,96 @@
+diff -r dcb49b482348 -r f63a8dee04ae openjdk/hotspot/src/share/vm/runtime/sharedRuntime.cpp
+--- openjdk/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Mon Nov 03 14:00:57 2008 +0000
++++ openjdk/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Mon Nov 03 15:56:17 2008 +0000
+@@ -173,64 +173,46 @@ JRT_END
+ 
+ 
+ JRT_LEAF(jint, SharedRuntime::f2i(jfloat  x))
+-  if (g_isnan(x)) {return 0;}
+-  jlong lltmp = (jlong)x;
+-  jint ltmp   = (jint)lltmp;
+-  if (ltmp == lltmp) {
+-    return ltmp;
+-  } else {
+-    if (x < 0) {
+-      return min_jint;
+-    } else {
+-      return max_jint;
+-    }
+-  }
++  if (g_isnan(x))
++    return 0;
++  if (x >= (jfloat) max_jint)
++    return max_jint;
++  if (x <= (jfloat) min_jint)
++    return min_jint;
++  return (jint) x;
+ JRT_END
+ 
+ 
+ JRT_LEAF(jlong, SharedRuntime::f2l(jfloat  x))  
+-  if (g_isnan(x)) {return 0;}
+-  jlong lltmp = (jlong)x;
+-  if (lltmp != min_jlong) {
+-    return lltmp;
+-  } else {
+-    if (x < 0) {
+-      return min_jlong;
+-    } else {
+-      return max_jlong;
+-    }
+-  }
++  if (g_isnan(x))
++    return 0;
++  if (x >= (jfloat) max_jlong)
++    return max_jlong;
++  if (x <= (jfloat) min_jlong)
++    return min_jlong;
++  return (jlong) x;
+ JRT_END
+ 
+ 
+ JRT_LEAF(jint, SharedRuntime::d2i(jdouble x))
+-  if (g_isnan(x)) {return 0;}
+-  jlong lltmp = (jlong)x;
+-  jint ltmp   = (jint)lltmp;
+-  if (ltmp == lltmp) {
+-    return ltmp;
+-  } else {
+-    if (x < 0) {
+-      return min_jint;
+-    } else {
+-      return max_jint;
+-    }
+-  }
++  if (g_isnan(x))
++    return 0;
++  if (x >= (jdouble) max_jint)
++    return max_jint;
++  if (x <= (jdouble) min_jint)
++    return min_jint;
++  return (jint) x;
+ JRT_END
+ 
+ 
+ JRT_LEAF(jlong, SharedRuntime::d2l(jdouble x))
+-  if (g_isnan(x)) {return 0;}
+-  jlong lltmp = (jlong)x;
+-  if (lltmp != min_jlong) {
+-    return lltmp;
+-  } else {
+-    if (x < 0) {
+-      return min_jlong;
+-    } else {
+-      return max_jlong;
+-    }
+-  }
++  if (g_isnan(x))
++    return 0;
++  if (x >= (jdouble) max_jlong)
++    return max_jlong;
++  if (x <= (jdouble) min_jlong)
++    return min_jlong;
++  return (jlong) x;
+ JRT_END
+ 
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-linker-libs-order.patch	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,66 @@
+diff -Nru openjdk.orig/jdk/make/com/sun/java/pack/Makefile openjdk/jdk/make/com/sun/java/pack/Makefile
+--- openjdk.orig/jdk/make/com/sun/java/pack/Makefile	2008-11-17 13:13:17.000000000 +0000
++++ openjdk/jdk/make/com/sun/java/pack/Makefile	2008-11-17 14:25:44.000000000 +0000
+@@ -75,12 +75,12 @@
+ 	     $(ZIPOBJDIR)/infutil.$(OBJECT_SUFFIX) \
+ 	     $(ZIPOBJDIR)/inffast.$(OBJECT_SUFFIX)
+ 
+-  OTHER_LDLIBS += -lz
+ else
+   OTHER_CXXFLAGS += -DNO_ZLIB -DUNPACK_JNI
+-  OTHER_LDLIBS += -lz $(JVMLIB)
++  OTHER_LDLIBS += $(JVMLIB)
+ endif
+ 
++OTHER_LDLIBS += -lz
+ CXXFLAGS_DBG += -DFULL
+ CXXFLAGS_OPT += -DPRODUCT
+ CXXFLAGS_COMMON += -DFULL
+@@ -97,12 +97,11 @@
+   RES = $(OBJDIR)/$(PGRM).res
+ else
+   LDOUTPUT = -o #Have a space 
+-  LDDFLAGS += -lz -lc
+-  OTHER_LDLIBS  += $(LIBCXX)
++  OTHER_LDLIBS += $(LIBCXX) -lc
+ # setup the list of libraries to link in...
+ ifeq ($(PLATFORM), linux)
+ ifeq ("$(CC_VER_MAJOR)", "3")
+-  OTHER_LDLIBS  += -lz -Wl,-Bstatic -lgcc_eh -Wl,-Bdynamic
++  OTHER_LDLIBS  += -Wl,-Bstatic -lgcc_eh -Wl,-Bdynamic
+ endif
+ endif #LINUX
+ endif #PLATFORM
+@@ -139,7 +138,7 @@
+ 
+ $(UNPACK_EXE): $(UNPACK_EXE_FILES_o) winres 
+ 	$(prep-target)
+-	$(LINKER)  $(LDDFLAGS) $(UNPACK_EXE_FILES_o) $(RES) $(LIBCXX) $(LDOUTPUT)$(TEMPDIR)/unpack200$(EXE_SUFFIX)
++	$(LINKER)  $(LDDFLAGS) $(UNPACK_EXE_FILES_o) $(RES) $(OTHER_LDLIBS) $(LIBCXX) $(LDOUTPUT)$(TEMPDIR)/unpack200$(EXE_SUFFIX)
+ 	$(CP) $(TEMPDIR)/unpack200$(EXE_SUFFIX) $(UNPACK_EXE)
+ 
+ 
+diff -Nru openjdk.orig/jdk/make/common/shared/Sanity.gmk openjdk/jdk/make/common/shared/Sanity.gmk
+--- openjdk.orig/jdk/make/common/shared/Sanity.gmk	2008-11-06 08:44:09.000000000 +0000
++++ openjdk/jdk/make/common/shared/Sanity.gmk	2008-11-17 14:25:44.000000000 +0000
+@@ -1345,7 +1345,7 @@
+ ifdef ALSA_VERSION_CHECK
+ $(ALSA_VERSION_CHECK): $(ALSA_VERSION_CHECK).c
+ 	@$(prep-target)
+-	@$(CC) -lasound -o $@ $<
++	@$(CC) -o $@ $< -lasound
+ 
+ $(ALSA_VERSION_CHECK).c:
+ 	@$(prep-target)
+diff -Nru openjdk.orig/jdk/make/javax/sound/jsoundalsa/Makefile openjdk/jdk/make/javax/sound/jsoundalsa/Makefile
+--- openjdk.orig/jdk/make/javax/sound/jsoundalsa/Makefile	2008-11-06 08:44:10.000000000 +0000
++++ openjdk/jdk/make/javax/sound/jsoundalsa/Makefile	2008-11-17 14:25:44.000000000 +0000
+@@ -65,7 +65,7 @@
+ 	$(MIDIFILES_export) \
+ 	$(PORTFILES_export)
+ 
+-LDFLAGS += -lasound
++OTHER_LDLIBS += -lasound
+ 
+ CPPFLAGS += \
+ 	-DUSE_DAUDIO=TRUE \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-testenv.patch	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,60 @@
+diff -Nru openjdk.orig/jdk/test/java/nio/channels/SocketChannel/LocalAddress.java openjdk/jdk/test/java/nio/channels/SocketChannel/LocalAddress.java
+--- openjdk.orig/jdk/test/java/nio/channels/SocketChannel/LocalAddress.java	2008-11-06 08:45:01.000000000 +0000
++++ openjdk/jdk/test/java/nio/channels/SocketChannel/LocalAddress.java	2008-11-17 14:46:05.000000000 +0000
+@@ -40,7 +40,7 @@
+         InetAddress bogus = InetAddress.getByName("0.0.0.0");
+         SocketChannel sc = SocketChannel.open();
+         InetSocketAddress saddr = new InetSocketAddress(
+-            InetAddress.getByName(TestUtil.HOST), 23);
++            InetAddress.getByName(TestUtil.HOST), 7);
+ 
+         //Test1: connect only
+         sc.connect(saddr);
+diff -Nru openjdk.orig/jdk/test/java/nio/channels/SocketChannel/Shutdown.java openjdk/jdk/test/java/nio/channels/SocketChannel/Shutdown.java
+--- openjdk.orig/jdk/test/java/nio/channels/SocketChannel/Shutdown.java	2008-11-06 08:45:01.000000000 +0000
++++ openjdk/jdk/test/java/nio/channels/SocketChannel/Shutdown.java	2008-11-17 14:45:53.000000000 +0000
+@@ -35,7 +35,7 @@
+ 
+     public static void main(String args[]) throws Exception {
+         InetSocketAddress sa = new InetSocketAddress(
+-                                InetAddress.getByName(TestUtil.HOST), 23);
++                                InetAddress.getByName(TestUtil.HOST), 7);
+         SocketChannel sc = SocketChannel.open(sa);
+         boolean before = sc.socket().isInputShutdown();
+         sc.socket().shutdownInput();
+diff -Nru openjdk.orig/jdk/test/java/nio/channels/TestUtil.java openjdk/jdk/test/java/nio/channels/TestUtil.java
+--- openjdk.orig/jdk/test/java/nio/channels/TestUtil.java	2008-11-17 14:43:22.000000000 +0000
++++ openjdk/jdk/test/java/nio/channels/TestUtil.java	2008-11-17 14:44:24.000000000 +0000
+@@ -36,9 +36,9 @@
+ 
+     // Test hosts used by the channels tests - change these when
+     // executing in a different network.
+-    public static final String HOST = "javaweb.sfbay.sun.com";
+-    public static final String REFUSING_HOST = "jano1.sfbay.sun.com";
+-    public static final String FAR_HOST = "irejano.ireland.sun.com";
++    public static final String HOST = "icedtea.classpath.org";
++    public static final String REFUSING_HOST = "ns1.gnu.org";
++    public static final String FAR_HOST = "developer.classpath.org";
+     public static final String UNRESOLVABLE_HOST = "blah-blah.blah-blah.blah";
+ 
+     private TestUtil() { }
+diff -Nru openjdk.orig/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh openjdk/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh
+--- openjdk.orig/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh	2008-11-06 08:45:08.000000000 +0000
++++ openjdk/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh	2008-11-17 14:48:52.000000000 +0000
+@@ -26,14 +26,14 @@
+ 
+ # @test
+ # @bug 4763315
+-# @build CanonicalName Lookup 
++# @build CanonicalName Lookup
+ # @run shell/timeout=120 cname.sh
+ # @summary Test DNS provider's handling of CNAME records
+ 
+ 
+ # The host that we try to resolve
+ 
+-HOST=webcache.sfbay.sun.com
++HOST=developer.classpath.org
+ 
+ # fail gracefully if DNS is not configured or there 
+ # isn't a CNAME record.
--- a/patches/icedtea-uname.patch	Mon Nov 17 12:41:07 2008 +0000
+++ b/patches/icedtea-uname.patch	Mon Nov 17 15:26:51 2008 +0000
@@ -5,7 +5,7 @@
    # Arch and OS name/version
    mach := $(shell uname -m)
 +  ifneq (,$(wildcard /usr/bin/dpkg-architecture))
-+    mach := $(shell dpkg-architecture -qDEB_BUILD_ARCH_CPU 2>/dev/null || echo $(mach))
++    mach := $(shell (dpkg-architecture -qDEB_BUILD_ARCH_CPU 2>/dev/null || echo $(mach)) | sed 's/powerpc$$/ppc/')
 +  endif
    archExpr = case "$(mach)" in \
                  i[3-9]86) \
@@ -27,7 +27,7 @@
    # Arch and OS name/version
    mach := $(shell uname -m)
 +  ifneq (,$(wildcard /usr/bin/dpkg-architecture))
-+    mach := $(shell dpkg-architecture -qDEB_BUILD_ARCH_CPU 2>/dev/null || echo $(mach))
++    mach := $(shell (dpkg-architecture -qDEB_BUILD_ARCH_CPU 2>/dev/null || echo $(mach)) | sed 's/powerpc$$/ppc/')
 +  endif
    archExpr = case "$(mach)" in \
                  i[3-9]86) \
--- a/patches/icedtea-visualvm.patch	Mon Nov 17 12:41:07 2008 +0000
+++ b/patches/icedtea-visualvm.patch	Mon Nov 17 15:26:51 2008 +0000
@@ -1,5 +1,5 @@
---- oldplatform.properties	2008-09-29 13:52:36.000000000 -0400
-+++ visualvm/visualvm/jvm/nbproject/platform.properties	2008-09-29 13:53:33.000000000 -0400
+--- pp	2008-10-31 11:24:42.000000000 -0400
++++ visualvm/visualvm/jvm/nbproject/platform.properties	2008-10-31 11:24:48.000000000 -0400
 @@ -16,8 +16,8 @@
      org.openide.compat,\
      org.openide.util.enumerations
@@ -8,12 +8,12 @@
 -    profiler2
 +    platform8,\
 +    profiler3
- nbjdk.active=Java_HotSpot_TM__Client_VM_1.6.0-b88-17-release
+ nbjdk.active=default
  nbplatform.active=NetBeans_Platform_Dev_(Build_200711261600)
  suite.dir=${basedir}
---- oldplatform.properties1	2008-09-29 13:52:46.000000000 -0400
-+++ visualvm/visualvm/nbproject/platform.properties	2008-09-29 13:53:41.000000000 -0400
-@@ -15,8 +15,8 @@
+--- pp2	2008-10-31 11:50:40.000000000 -0400
++++ visualvm/visualvm/nbproject/platform.properties	2008-10-31 11:50:47.000000000 -0400
+@@ -14,8 +14,8 @@
      org.openide.compat,\
      org.openide.util.enumerations
  enabled.clusters=\
--- a/plugin/icedtea/sun/applet/PluginAppletViewer.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/plugin/icedtea/sun/applet/PluginAppletViewer.java	Mon Nov 17 15:26:51 2008 +0000
@@ -1265,6 +1265,10 @@
  		skipSpace(in);
  		val = buf.toString();
  	    }
+
+        val = val.replace("&gt;", ">");
+        val = val.replace("&lt;", "<");
+        val = val.replace("&amp;", "&");
  	    PluginDebug.debug("PUT " + att + " = '" + val + "'");
  	    atts.put(att.toLowerCase(java.util.Locale.ENGLISH), val);
              while (true) {
--- a/ports/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.inline.hpp	Mon Nov 17 12:41:07 2008 +0000
+++ b/ports/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.inline.hpp	Mon Nov 17 15:26:51 2008 +0000
@@ -82,7 +82,6 @@
 }
 
 inline jlong BytecodeInterpreter::VMlongUshr(jlong op1, jint op2) {
-  // CVM did this 0x3f mask, is the really needed??? QQQ
   return ((unsigned long long) op1) >> (op2 & 0x3F);
 }
 
@@ -237,11 +236,11 @@
 }
 
 inline jint BytecodeInterpreter::VMintShl(jint op1, jint op2) {
-  return op1 <<  op2;
+  return op1 << (op2 & 0x1F);
 }
 
 inline jint BytecodeInterpreter::VMintShr(jint op1, jint op2) {
-  return op1 >>  op2; // QQ op2 & 0x1f??
+  return op1 >> (op2 & 0x1F);
 }
 
 inline jint BytecodeInterpreter::VMintSub(jint op1, jint op2) {
@@ -249,7 +248,7 @@
 }
 
 inline jint BytecodeInterpreter::VMintUshr(jint op1, jint op2) {
-  return ((juint) op1) >> op2; // QQ op2 & 0x1f??
+  return ((juint) op1) >> (op2 & 0x1F);
 }
 
 inline jint BytecodeInterpreter::VMintXor(jint op1, jint op2) {
--- a/ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp	Mon Nov 17 12:41:07 2008 +0000
+++ b/ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp	Mon Nov 17 15:26:51 2008 +0000
@@ -77,6 +77,13 @@
 
   intptr_t *result = NULL;
   int result_slots = 0;
+
+  // Check we're not about to run out of stack
+  if (stack_overflow_imminent(thread)) {
+    CALL_VM_NOCHECK(InterpreterRuntime::throw_StackOverflowError(thread));
+    goto unwind_and_return;
+  }
+
   while (true) {
     // We can set up the frame anchor with everything we want at
     // this point as we are thread_in_Java and no safepoints can
@@ -151,6 +158,8 @@
     }
   }
 
+ unwind_and_return:
+
   // Unwind the current frame
   thread->pop_zero_frame();
 
@@ -164,6 +173,9 @@
 
 void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS)
 {
+  // Make sure method is native and not abstract
+  assert(method->is_native() && !method->is_abstract(), "should be");
+
   JavaThread *thread = (JavaThread *) THREAD;
   ZeroStack *stack = thread->zero_stack();
 
@@ -173,11 +185,15 @@
   interpreterState istate = frame->interpreter_state();
   intptr_t *locals = istate->locals();
 
-  // Make sure method is native and not abstract
-  assert(method->is_native() && !method->is_abstract(), "should be");
+  // Check we're not about to run out of stack
+  if (stack_overflow_imminent(thread)) {
+    CALL_VM_NOCHECK(InterpreterRuntime::throw_StackOverflowError(thread));
+    goto unwind_and_return;
+  }
 
   // Lock if necessary
-  BasicObjectLock *monitor = NULL;
+  BasicObjectLock *monitor;
+  monitor = NULL;
   if (method->is_synchronized()) {
     monitor = (BasicObjectLock*) istate->stack_base();
     oop lockee = monitor->obj();
@@ -190,81 +206,83 @@
       }
       else {
         CALL_VM_NOCHECK(InterpreterRuntime::monitorenter(thread, monitor));
-        if (HAS_PENDING_EXCEPTION) {
-          thread->pop_zero_frame();
-          return;
-        }
+        if (HAS_PENDING_EXCEPTION)
+          goto unwind_and_return;
       }
     }
   }
 
   // Get the signature handler
-  address handlerAddr = method->signature_handler();
-  if (handlerAddr == NULL) {
-    CALL_VM_NOCHECK(InterpreterRuntime::prepare_native_call(thread, method));
-    if (HAS_PENDING_EXCEPTION) {
-      thread->pop_zero_frame();
-      return;
+  InterpreterRuntime::SignatureHandler *handler;
+  {
+    address handlerAddr = method->signature_handler();
+    if (handlerAddr == NULL) {
+      CALL_VM_NOCHECK(InterpreterRuntime::prepare_native_call(thread, method));
+      if (HAS_PENDING_EXCEPTION)
+        goto unwind_and_return;
+
+      handlerAddr = method->signature_handler();
+      assert(handlerAddr != NULL, "eh?");
     }
-    handlerAddr = method->signature_handler();
-    assert(handlerAddr != NULL, "eh?");
+    if (handlerAddr == (address) InterpreterRuntime::slow_signature_handler) {
+      CALL_VM_NOCHECK(handlerAddr =
+        InterpreterRuntime::slow_signature_handler(thread, method, NULL,NULL));
+      if (HAS_PENDING_EXCEPTION)
+        goto unwind_and_return;
+    }
+    handler = \
+      InterpreterRuntime::SignatureHandler::from_handlerAddr(handlerAddr);
   }
-  if (handlerAddr == (address) InterpreterRuntime::slow_signature_handler) {
-    CALL_VM_NOCHECK(handlerAddr =
-      InterpreterRuntime::slow_signature_handler(thread, method, NULL, NULL));
-    if (HAS_PENDING_EXCEPTION) {
-      thread->pop_zero_frame();
-      return;
-    }
-  }
-  InterpreterRuntime::SignatureHandler *handler =
-    InterpreterRuntime::SignatureHandler::from_handlerAddr(handlerAddr);
 
   // Get the native function entry point
-  address function = method->native_function();
+  address function;
+  function = method->native_function();
   assert(function != NULL, "should be set if signature handler is");
 
   // Build the argument list
   if (handler->argument_count() * 2 > stack->available_words()) {
     Unimplemented();
   }
-  void **arguments =
-    (void **) stack->alloc(handler->argument_count() * sizeof(void **));
-  void **dst = arguments;
-
-  void *env = thread->jni_environment();
-  *(dst++) = &env;
-
-  void *mirror = NULL;
-  if (method->is_static()) {
-    istate->set_oop_temp(
-      method->constants()->pool_holder()->klass_part()->java_mirror());
-    mirror = istate->oop_temp_addr();
-    *(dst++) = &mirror;
-  }
-
-  intptr_t *src = locals;
-  for (int i = dst - arguments; i < handler->argument_count(); i++) {
-    ffi_type *type = handler->argument_type(i);
-    if (type == &ffi_type_pointer) {
-      if (*src) {
-        stack->push((intptr_t) src);
-        *(dst++) = stack->sp();
+  void **arguments;
+  {
+    arguments =
+      (void **) stack->alloc(handler->argument_count() * sizeof(void **));
+    void **dst = arguments;
+  
+    void *env = thread->jni_environment();
+    *(dst++) = &env;
+  
+    void *mirror = NULL;
+    if (method->is_static()) {
+      istate->set_oop_temp(
+        method->constants()->pool_holder()->klass_part()->java_mirror());
+      mirror = istate->oop_temp_addr();
+      *(dst++) = &mirror;
+    }
+  
+    intptr_t *src = locals;
+    for (int i = dst - arguments; i < handler->argument_count(); i++) {
+      ffi_type *type = handler->argument_type(i);
+      if (type == &ffi_type_pointer) {
+        if (*src) {
+          stack->push((intptr_t) src);
+          *(dst++) = stack->sp();
+        }
+        else {
+          *(dst++) = src;
+        }
+        src--;
+      }
+      else if (type->size == 4) {
+        *(dst++) = src--;
+      }
+      else if (type->size == 8) {
+        src--;
+        *(dst++) = src--;
       }
       else {
-        *(dst++) = src;
+        ShouldNotReachHere();
       }
-      src--;
-    }
-    else if (type->size == 4) {
-      *(dst++) = src--;
-    }
-    else if (type->size == 8) {
-      src--;
-      *(dst++) = src--;
-    }
-    else {
-      ShouldNotReachHere();
     }
   }
 
@@ -318,6 +336,8 @@
     }
   }
 
+ unwind_and_return:
+
   // Unwind the current activation
   thread->pop_zero_frame();
 
@@ -536,6 +556,30 @@
   stack->set_sp(stack->sp() + method->size_of_parameters());
 }
 
+bool CppInterpreter::stack_overflow_imminent(JavaThread *thread)
+{
+  // How is the ABI stack?
+  address stack_top = thread->stack_base() - thread->stack_size();
+  int free_stack = os::current_stack_pointer() - stack_top;
+  if (free_stack < StackShadowPages * os::vm_page_size()) {
+    return true;
+  }
+
+  // How is the Zero stack?
+  // Throwing a StackOverflowError involves a VM call, which means
+  // we need a frame on the stack.  We should be checking here to
+  // ensure that methods we call have enough room to install the
+  // largest possible frame, but that's more than twice the size
+  // of the entire Zero stack we get by default, so we just check
+  // we have *some* space instead...
+  free_stack = thread->zero_stack()->available_words() * wordSize;
+  if (free_stack < StackShadowPages * os::vm_page_size()) {
+    return true;
+  }
+  
+  return false;
+}
+
 InterpreterFrame *InterpreterFrame::build(ZeroStack*       stack,
                                           const methodOop  method,
                                           JavaThread*      thread)
--- a/ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp	Mon Nov 17 12:41:07 2008 +0000
+++ b/ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp	Mon Nov 17 15:26:51 2008 +0000
@@ -38,3 +38,7 @@
  public:
   // Main loop of normal_entry
   static void main_loop(int recurse, TRAPS);
+
+ private:
+  // Stack overflow checks
+  static bool stack_overflow_imminent(JavaThread *thread);
--- a/ports/hotspot/src/cpu/zero/vm/frame_zero.cpp	Mon Nov 17 12:41:07 2008 +0000
+++ b/ports/hotspot/src/cpu/zero/vm/frame_zero.cpp	Mon Nov 17 15:26:51 2008 +0000
@@ -133,7 +133,58 @@
 BasicType frame::interpreter_frame_result(oop* oop_result,
                                           jvalue* value_result)
 {
-  Unimplemented();
+  assert(is_interpreted_frame(), "interpreted frame expected");
+  methodOop method = interpreter_frame_method();
+  BasicType type = method->result_type();
+  intptr_t* tos_addr = (intptr_t *) interpreter_frame_tos_address();
+  oop obj;
+
+  switch (type) {
+  case T_VOID:
+    break;
+  case T_BOOLEAN:
+    value_result->z = *(jboolean *) tos_addr;
+    break;
+  case T_BYTE:
+    value_result->b = *(jbyte *) tos_addr;
+    break;
+  case T_CHAR:
+    value_result->c = *(jchar *) tos_addr;
+    break;
+  case T_SHORT:
+    value_result->s = *(jshort *) tos_addr;
+    break;
+  case T_INT:
+    value_result->i = *(jint *) tos_addr;
+    break;
+  case T_LONG:
+    value_result->j = *(jlong *) tos_addr;
+    break;
+  case T_FLOAT:
+    value_result->f = *(jfloat *) tos_addr;
+    break;
+  case T_DOUBLE:
+    value_result->d = *(jdouble *) tos_addr;
+    break;
+
+  case T_OBJECT: 
+  case T_ARRAY:
+    if (method->is_native()) {
+      obj = get_interpreterState()->oop_temp();
+    }
+    else {
+      oop* obj_p = (oop *) tos_addr;
+      obj = (obj_p == NULL) ? (oop) NULL : *obj_p;
+    }
+    assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check");
+    *oop_result = obj;
+    break;
+
+  default:
+    ShouldNotReachHere();
+  }
+
+  return type;
 }
 
 int frame::frame_size() const
--- a/ports/hotspot/src/cpu/zero/vm/globals_zero.hpp	Mon Nov 17 12:41:07 2008 +0000
+++ b/ports/hotspot/src/cpu/zero/vm/globals_zero.hpp	Mon Nov 17 15:26:51 2008 +0000
@@ -48,7 +48,7 @@
 
 define_pd_global(intx,  StackYellowPages,         2);
 define_pd_global(intx,  StackRedPages,            1);
-define_pd_global(intx,  StackShadowPages,         3 DEBUG_ONLY(+1));
+define_pd_global(intx,  StackShadowPages,         3 DEBUG_ONLY(+3));
 
 define_pd_global(bool,  RewriteBytecodes,         true);
 define_pd_global(bool,  RewriteFrequentPairs,     true);
--- a/ports/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp	Mon Nov 17 12:41:07 2008 +0000
+++ b/ports/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp	Mon Nov 17 15:26:51 2008 +0000
@@ -174,7 +174,7 @@
 
 inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest)
 {
-  Unimplemented();
+  *dest = store_value;
 }
 
 inline jint Atomic::add(jint add_value, volatile jint* dest)
--- a/ports/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp	Mon Nov 17 12:41:07 2008 +0000
+++ b/ports/hotspot/src/os_cpu/linux_zero/vm/orderAccess_linux_zero.inline.hpp	Mon Nov 17 15:26:51 2008 +0000
@@ -46,13 +46,28 @@
 inline jbyte    OrderAccess::load_acquire(volatile jbyte*   p) { return *p; }
 inline jshort   OrderAccess::load_acquire(volatile jshort*  p) { return *p; }
 inline jint     OrderAccess::load_acquire(volatile jint*    p) { return *p; }
-inline jlong    OrderAccess::load_acquire(volatile jlong*   p) { return *p; }
+inline jlong    OrderAccess::load_acquire(volatile jlong*   p)
+{
+  jlong tmp;
+  os::atomic_copy64(p, &tmp);
+  return tmp;
+}
 inline jubyte   OrderAccess::load_acquire(volatile jubyte*  p) { return *p; }
 inline jushort  OrderAccess::load_acquire(volatile jushort* p) { return *p; }
 inline juint    OrderAccess::load_acquire(volatile juint*   p) { return *p; }
-inline julong   OrderAccess::load_acquire(volatile julong*  p) { return *p; }
+inline julong   OrderAccess::load_acquire(volatile julong*  p)
+{
+  julong tmp;
+  os::atomic_copy64(p, &tmp);
+  return tmp;
+}
 inline jfloat   OrderAccess::load_acquire(volatile jfloat*  p) { return *p; }
-inline jdouble  OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
+inline jdouble  OrderAccess::load_acquire(volatile jdouble* p)
+{
+  jdouble tmp;
+  os::atomic_copy64(p, &tmp);
+  return tmp;
+}
 
 inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t*   p) { return *p; }
 inline void*    OrderAccess::load_ptr_acquire(volatile void*       p) { return *(void* volatile *)p; }
@@ -61,13 +76,13 @@
 inline void     OrderAccess::release_store(volatile jbyte*   p, jbyte   v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jshort*  p, jshort  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jint*    p, jint    v) { *p = v; }
-inline void     OrderAccess::release_store(volatile jlong*   p, jlong   v) { *p = v; }
+inline void     OrderAccess::release_store(volatile jlong*   p, jlong   v) { os::atomic_copy64(&v, p); }
 inline void     OrderAccess::release_store(volatile jubyte*  p, jubyte  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
 inline void     OrderAccess::release_store(volatile juint*   p, juint   v) { *p = v; }
-inline void     OrderAccess::release_store(volatile julong*  p, julong  v) { *p = v; }
+inline void     OrderAccess::release_store(volatile julong*  p, julong  v) { os::atomic_copy64(&v, p); }
 inline void     OrderAccess::release_store(volatile jfloat*  p, jfloat  v) { *p = v; }
-inline void     OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
+inline void     OrderAccess::release_store(volatile jdouble* p, jdouble v) { os::atomic_copy64(&v, p); }
 
 inline void     OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; }
 inline void     OrderAccess::release_store_ptr(volatile void*     p, void*    v) { *(void* volatile *)p = v; }
@@ -75,27 +90,27 @@
 inline void     OrderAccess::store_fence(jbyte*   p, jbyte   v) { *p = v; fence(); }
 inline void     OrderAccess::store_fence(jshort*  p, jshort  v) { *p = v; fence(); }
 inline void     OrderAccess::store_fence(jint*    p, jint    v) { *p = v; fence(); }
-inline void     OrderAccess::store_fence(jlong*   p, jlong   v) { *p = v; fence(); }
+inline void     OrderAccess::store_fence(jlong*   p, jlong   v) { os::atomic_copy64(&v, p); fence(); }
 inline void     OrderAccess::store_fence(jubyte*  p, jubyte  v) { *p = v; fence(); }
 inline void     OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); }
 inline void     OrderAccess::store_fence(juint*   p, juint   v) { *p = v; fence(); }
-inline void     OrderAccess::store_fence(julong*  p, julong  v) { *p = v; fence(); }
+inline void     OrderAccess::store_fence(julong*  p, julong  v) { os::atomic_copy64(&v, p); fence(); }
 inline void     OrderAccess::store_fence(jfloat*  p, jfloat  v) { *p = v; fence(); }
-inline void     OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); }
+inline void     OrderAccess::store_fence(jdouble* p, jdouble v) { os::atomic_copy64(&v, p); fence(); }
 
 inline void     OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); }
 inline void     OrderAccess::store_ptr_fence(void**    p, void*    v) { *p = v; fence(); }
 
-inline void     OrderAccess::release_store_fence(volatile jbyte*   p, jbyte   v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile jshort*  p, jshort  v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile jint*    p, jint    v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile jlong*   p, jlong   v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile jubyte*  p, jubyte  v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile juint*   p, juint   v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile julong*  p, julong  v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile jfloat*  p, jfloat  v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); }
+inline void     OrderAccess::release_store_fence(volatile jbyte*   p, jbyte   v) { release_store(p, v); fence(); }
+inline void     OrderAccess::release_store_fence(volatile jshort*  p, jshort  v) { release_store(p, v); fence(); }
+inline void     OrderAccess::release_store_fence(volatile jint*    p, jint    v) { release_store(p, v); fence(); }
+inline void     OrderAccess::release_store_fence(volatile jlong*   p, jlong   v) { release_store(p, v); fence(); }
+inline void     OrderAccess::release_store_fence(volatile jubyte*  p, jubyte  v) { release_store(p, v); fence(); }
+inline void     OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store(p, v); fence(); }
+inline void     OrderAccess::release_store_fence(volatile juint*   p, juint   v) { release_store(p, v); fence(); }
+inline void     OrderAccess::release_store_fence(volatile julong*  p, julong  v) { release_store(p, v); fence(); }
+inline void     OrderAccess::release_store_fence(volatile jfloat*  p, jfloat  v) { release_store(p, v); fence(); }
+inline void     OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store(p, v); fence(); }
 
-inline void     OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_ptr_fence(volatile void*     p, void*    v) { *(void* volatile *)p = v; fence(); }
+inline void     OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { release_store_ptr(p, v); fence(); }
+inline void     OrderAccess::release_store_ptr_fence(volatile void*     p, void*    v) { release_store_ptr(p, v); fence(); }
--- a/ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp	Mon Nov 17 12:41:07 2008 +0000
+++ b/ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp	Mon Nov 17 15:26:51 2008 +0000
@@ -126,6 +126,60 @@
   }
 
   if (info != NULL && thread != NULL) {
+    // Handle ALL stack overflow variations here
+    if (sig == SIGSEGV) {
+      address addr = (address) info->si_addr;
+
+      // check if fault address is within thread stack
+      if (addr < thread->stack_base() &&
+          addr >= thread->stack_base() - thread->stack_size()) {
+        // stack overflow
+        if (thread->in_stack_yellow_zone(addr)) {
+          thread->disable_stack_yellow_zone();
+          Unimplemented();
+        }
+        else if (thread->in_stack_red_zone(addr)) {
+          thread->disable_stack_red_zone();
+          Unimplemented();
+        }
+        else {
+          // Accessing stack address below sp may cause SEGV if
+          // current thread has MAP_GROWSDOWN stack. This should
+          // only happen when current thread was created by user
+          // code with MAP_GROWSDOWN flag and then attached to VM.
+          // See notes in os_linux.cpp.
+          if (thread->osthread()->expanding_stack() == 0) {
+            thread->osthread()->set_expanding_stack();
+            if (os::Linux::manually_expand_stack(thread, addr)) {
+              thread->osthread()->clear_expanding_stack();
+              return true;
+            }
+            thread->osthread()->clear_expanding_stack();
+          }
+          else {
+            fatal("recursive segv. expanding stack.");
+          }
+        } 
+      }
+    }
+
+    /*if (thread->thread_state() == _thread_in_Java) {
+      Unimplemented();
+    }
+    else*/ if (thread->thread_state() == _thread_in_vm &&
+               sig == SIGBUS && thread->doing_unsafe_access()) {
+      Unimplemented();
+    }
+
+    // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC
+    // kicks in and the heap gets shrunk before the field access.
+    /*if (sig == SIGSEGV || sig == SIGBUS) {
+      address addr = JNI_FastGetField::find_slowcase_pc(pc);
+      if (addr != (address)-1) {
+        stub = addr;
+      }
+    }*/
+
     // Check to see if we caught the safepoint code in the process
     // of write protecting the memory serialization page.  It write
     // enables the page immediately after protecting it so we can
@@ -138,6 +192,16 @@
     }
   }
 
+  // signal-chaining
+  if (os::Linux::chained_handler(sig, info, ucVoid)) {
+     return true;
+  }
+
+  if (!abort_if_unrecognized) {
+    // caller wants another chance, so give it to him
+    return false;
+  }
+
 #ifndef PRODUCT
   if (sig == SIGSEGV) {
     fatal("\n#"
@@ -341,14 +405,14 @@
     if (from > to) {
       jlong *end = from + count;
       while (from < end)
-        *(to++) = *(from++);
+        os::atomic_copy64(from++, to++);
     }
     else if (from < to) {
       jlong *end = from;
       from += count - 1;
       to   += count - 1;
       while (from >= end)
-        *(to--) = *(from--);
+        os::atomic_copy64(from--, to--);
     }
   }
 
--- a/ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp	Mon Nov 17 12:41:07 2008 +0000
+++ b/ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp	Mon Nov 17 15:26:51 2008 +0000
@@ -29,3 +29,16 @@
   // Note: Currently only used in 64 bit Windows implementations
   static bool register_code_area(char *low, char *high) { return true; }
 
+  // Atomically copy 64 bits of data
+  static void atomic_copy64(volatile void *src, volatile void *dst)
+  {
+#if defined(PPC) && !defined(_LP64)
+    double tmp;
+    asm volatile ("lfd  %0, 0(%1)\n"
+                  "stfd %0, 0(%2)\n"
+                  : "=f"(tmp)
+                  : "b"(src), "b"(dst));
+#else
+    *(jlong *) dst = *(jlong *) src;
+#endif // PPC && !_LP64
+  }
--- a/ports/hotspot/src/share/vm/shark/sharkBlock.cpp	Mon Nov 17 12:41:07 2008 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkBlock.cpp	Mon Nov 17 15:26:51 2008 +0000
@@ -486,19 +486,28 @@
       b = pop();
       a = pop();
       push(SharkValue::create_jint(
-        builder()->CreateShl(a->jint_value(), b->jint_value())));
+        builder()->CreateShl(
+          a->jint_value(),
+          builder()->CreateAnd(
+            b->jint_value(), LLVMValue::jint_constant(0x1f)))));
       break;
     case Bytecodes::_ishr:
       b = pop();
       a = pop();
       push(SharkValue::create_jint(
-        builder()->CreateAShr(a->jint_value(), b->jint_value())));
+        builder()->CreateAShr(
+          a->jint_value(),
+          builder()->CreateAnd(
+            b->jint_value(), LLVMValue::jint_constant(0x1f)))));
       break;
     case Bytecodes::_iushr:
       b = pop();
       a = pop();
       push(SharkValue::create_jint(
-        builder()->CreateLShr(a->jint_value(), b->jint_value())));
+        builder()->CreateLShr(
+          a->jint_value(),
+          builder()->CreateAnd(
+            b->jint_value(), LLVMValue::jint_constant(0x1f)))));
       break;
     case Bytecodes::_iand:
       b = pop();
@@ -555,7 +564,9 @@
         builder()->CreateShl(
           a->jlong_value(),
           builder()->CreateIntCast(
-            b->jint_value(), SharkType::jlong_type(), true))));
+            builder()->CreateAnd(
+              b->jint_value(), LLVMValue::jint_constant(0x3f)),
+            SharkType::jlong_type(), true))));
       break;
     case Bytecodes::_lshr:
       b = pop();
@@ -564,7 +575,9 @@
         builder()->CreateAShr(
           a->jlong_value(),
           builder()->CreateIntCast(
-            b->jint_value(), SharkType::jlong_type(), true))));
+            builder()->CreateAnd(
+              b->jint_value(), LLVMValue::jint_constant(0x3f)),
+            SharkType::jlong_type(), true))));
       break;
     case Bytecodes::_lushr:
       b = pop();
@@ -573,7 +586,9 @@
         builder()->CreateLShr(
           a->jlong_value(),
           builder()->CreateIntCast(
-            b->jint_value(), SharkType::jlong_type(), true))));
+            builder()->CreateAnd(
+              b->jint_value(), LLVMValue::jint_constant(0x3f)),
+            SharkType::jlong_type(), true))));
       break;
     case Bytecodes::_land:
       b = pop();
@@ -727,13 +742,11 @@
 
     case Bytecodes::_f2i:
       push(SharkValue::create_jint(
-        builder()->CreateFPToSI(
-          pop()->jfloat_value(), SharkType::jint_type())));
+        call_vm_leaf(SharkRuntime::f2i(), pop()->jfloat_value())));
       break;
     case Bytecodes::_f2l:
-      push(SharkValue::create_jint(
-        builder()->CreateFPToSI(
-          pop()->jfloat_value(), SharkType::jlong_type())));
+      push(SharkValue::create_jlong(
+        call_vm_leaf(SharkRuntime::f2l(), pop()->jfloat_value())));
       break;
     case Bytecodes::_f2d:
       push(SharkValue::create_jdouble(
@@ -743,13 +756,11 @@
 
     case Bytecodes::_d2i:
       push(SharkValue::create_jint(
-        builder()->CreateFPToSI(
-          pop()->jdouble_value(), SharkType::jint_type())));
+        call_vm_leaf(SharkRuntime::d2i(), pop()->jdouble_value())));
       break;
     case Bytecodes::_d2l:
       push(SharkValue::create_jlong(
-        builder()->CreateFPToSI(
-          pop()->jdouble_value(), SharkType::jlong_type())));
+        call_vm_leaf(SharkRuntime::d2l(), pop()->jdouble_value())));
       break;
     case Bytecodes::_d2f:
       push(SharkValue::create_jfloat(
--- a/ports/hotspot/src/share/vm/shark/sharkBlock.hpp	Mon Nov 17 12:41:07 2008 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkBlock.hpp	Mon Nov 17 15:26:51 2008 +0000
@@ -371,6 +371,12 @@
     return call_vm_nocheck(callee, args, args + 4);
   }
 
+  llvm::CallInst* call_vm_leaf(llvm::Constant* callee,
+                               llvm::Value*    arg1)
+  {
+    return builder()->CreateCall(callee, arg1);
+  }
+
   // Whole-method synchronization
  public:
   void acquire_method_lock();  
--- a/ports/hotspot/src/share/vm/shark/sharkRuntime.cpp	Mon Nov 17 12:41:07 2008 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkRuntime.cpp	Mon Nov 17 15:26:51 2008 +0000
@@ -43,6 +43,11 @@
 Constant* SharkRuntime::_throw_NullPointerException;
 Constant* SharkRuntime::_trace_bytecode;
 
+Constant* SharkRuntime::_f2i;
+Constant* SharkRuntime::_f2l;
+Constant* SharkRuntime::_d2i;
+Constant* SharkRuntime::_d2l;
+
 Constant* SharkRuntime::_dump;
 Constant* SharkRuntime::_is_subtype_of;
 Constant* SharkRuntime::_should_not_reach_here;
@@ -158,6 +163,29 @@
     FunctionType::get(Type::VoidTy, params, false),
     "SharkRuntime__trace_bytecode");
 
+  // Leaf calls
+  params.clear();
+  params.push_back(SharkType::jfloat_type());
+  _f2i = builder->make_function(
+    (intptr_t) SharedRuntime::f2i,
+    FunctionType::get(SharkType::jint_type(), params, false),
+    "SharedRuntime__f2i");  
+  _f2l = builder->make_function(
+    (intptr_t) SharedRuntime::f2l,
+    FunctionType::get(SharkType::jlong_type(), params, false),
+    "SharedRuntime__f2l");  
+
+  params.clear();
+  params.push_back(SharkType::jdouble_type());
+  _d2i = builder->make_function(
+    (intptr_t) SharedRuntime::d2i,
+    FunctionType::get(SharkType::jint_type(), params, false),
+    "SharedRuntime__d2i");  
+  _d2l = builder->make_function(
+    (intptr_t) SharedRuntime::d2l,
+    FunctionType::get(SharkType::jlong_type(), params, false),
+    "SharedRuntime__d2l");  
+  
   // Non-VM calls
   params.clear();
   params.push_back(SharkType::intptr_type());
--- a/ports/hotspot/src/share/vm/shark/sharkRuntime.hpp	Mon Nov 17 12:41:07 2008 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkRuntime.hpp	Mon Nov 17 15:26:51 2008 +0000
@@ -162,6 +162,31 @@
     return *(thread->zero_stack()->sp() + offset);
   }  
 
+  // Leaf calls
+ private:
+  static llvm::Constant* _f2i;
+  static llvm::Constant* _f2l;
+  static llvm::Constant* _d2i;
+  static llvm::Constant* _d2l;
+
+ public:
+  static llvm::Constant* f2i()
+  {
+    return _f2i;
+  }  
+  static llvm::Constant* f2l()
+  {
+    return _f2l;
+  }  
+  static llvm::Constant* d2i()
+  {
+    return _d2i;
+  }  
+  static llvm::Constant* d2l()
+  {
+    return _d2l;
+  }  
+  
   // Non-VM calls
  private:
   static llvm::Constant* _dump;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Debug.java	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,104 @@
+/* EventLoop.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package org.classpath.icedtea.pulseaudio;
+
+public class Debug {
+
+	public enum DebugLevel {
+		Verbose, Debug, Info, Warning, Error, None
+	}
+
+	private static DebugLevel currentDebugLevel = DebugLevel.None;
+
+	public static void initialize() {
+		// System.out.println("PulseAudio: initializing Debug");
+
+		String systemSetting;
+		try {
+			systemSetting = System.getProperty("pulseaudio.debugLevel");
+		} catch (SecurityException e) {
+			// sigh, we cant read that property
+			systemSetting = null;
+		}
+
+		DebugLevel wantedLevel;
+		try {
+			wantedLevel = DebugLevel.valueOf(systemSetting);
+
+		} catch (IllegalArgumentException e) {
+			wantedLevel = DebugLevel.Info;
+		} catch (NullPointerException e) {
+			wantedLevel = DebugLevel.None;
+		}
+
+		currentDebugLevel = wantedLevel;
+		println(DebugLevel.Info, "Using debug level: " + currentDebugLevel);
+	}
+
+	public static void println(String string) {
+		println(DebugLevel.Info, string);
+	}
+
+	public static void print(DebugLevel level, String string) {
+		int result = level.compareTo(currentDebugLevel);
+		if (result >= 0) {
+			if (level.compareTo(DebugLevel.Error) >= 0) {
+				System.err.print(string);
+			} else {
+				System.out.print(string);
+			}
+		} else {
+			// do nothing
+		}
+	}
+
+	public static void println(DebugLevel level, String string) {
+
+		int result = level.compareTo(currentDebugLevel);
+		if (result >= 0) {
+			if (level.compareTo(DebugLevel.Error) >= 0) {
+				System.err.println("DEBUG: pulse-java: " + string);
+			} else {
+				System.out.println("DEBUG: pulse-java: " + string);
+			}
+		} else {
+			// do nothing
+		}
+	}
+
+}
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java	Mon Nov 17 15:26:51 2008 +0000
@@ -42,6 +42,7 @@
 import java.util.concurrent.Semaphore;
 
 import org.classpath.icedtea.pulseaudio.ContextEvent.Type;
+import org.classpath.icedtea.pulseaudio.Debug.DebugLevel;
 
 /*
  * any methods that can obstruct the behaviour of pa_mainloop should run
@@ -55,7 +56,6 @@
 	/*
 	 * the threadLock object is the object used for synchronizing the
 	 * non-thread-safe operations of pulseaudio's c api
-	 * 
 	 */
 	public Object threadLock = new Object();
 
@@ -79,7 +79,6 @@
 	 * 
 	 * Do not synchronize the individual functions, synchronize
 	 * block/method/lines around the call
-	 * 
 	 */
 
 	private native void native_setup(String appName, String server);
@@ -92,12 +91,8 @@
 
 	/*
 	 * These fields hold pointers
-	 * 
-	 * 
 	 */
-	@SuppressWarnings("unused")
 	private byte[] contextPointer;
-	@SuppressWarnings("unused")
 	private byte[] mainloopPointer;
 
 	/*
@@ -105,7 +100,7 @@
 	 */
 
 	static {
-		System.loadLibrary("pulse-java");
+		SecurityWrapper.loadNativeLibrary();
 	}
 
 	private EventLoop() {
@@ -132,6 +127,8 @@
 	public void run() {
 		native_setup(this.name, this.serverString);
 
+		Debug.println(DebugLevel.Info, "Eventloop.run(): eventloop starting");
+
 		/*
 		 * Perhaps this loop should be written in C doing a Java to C call on
 		 * every iteration of the loop might be slow
@@ -144,14 +141,15 @@
 
 				if (Thread.interrupted()) {
 					native_shutdown();
-					// System.out.println(this.getClass().getName()
-					// + ": shutting down");
 
 					// clean up the listeners
 					synchronized (contextListeners) {
 						contextListeners.clear();
 					}
 
+					Debug.println(DebugLevel.Info,
+							"EventLoop.run(): event loop terminated");
+
 					return;
 
 				}
@@ -197,7 +195,8 @@
 				break;
 			case 5:
 				fireEvent(new ContextEvent(Type.FAILED));
-				System.out.println("context failed");
+				Debug.println(DebugLevel.Warning,
+						"EventLoop.update(): Context failed");
 				break;
 			case 6:
 				fireEvent(new ContextEvent(Type.TERMINATED));
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Operation.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Operation.java	Mon Nov 17 15:26:51 2008 +0000
@@ -58,7 +58,7 @@
 	}
 
 	static {
-		System.loadLibrary("pulse-java");
+		SecurityWrapper.loadNativeLibrary();
 	}
 
 	private native void native_ref();
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java	Mon Nov 17 15:26:51 2008 +0000
@@ -41,12 +41,12 @@
 
 import javax.sound.sampled.AudioFormat;
 import javax.sound.sampled.AudioInputStream;
-import javax.sound.sampled.AudioPermission;
 import javax.sound.sampled.AudioSystem;
 import javax.sound.sampled.Clip;
 import javax.sound.sampled.DataLine;
 import javax.sound.sampled.LineUnavailableException;
 
+import org.classpath.icedtea.pulseaudio.Debug.DebugLevel;
 import org.classpath.icedtea.pulseaudio.Stream.WriteListener;
 
 public class PulseAudioClip extends PulseAudioDataLine implements Clip,
@@ -146,6 +146,9 @@
 
 		stream.addWriteListener(writeListener);
 
+		Debug.println(DebugLevel.Verbose,
+				"PulseAudioClip$ClipThread.writeFrames(): Writing");
+
 		int remainingFrames = lastFrame - startingFrame - 1;
 		while (remainingFrames > 0) {
 			synchronized (eventLoop.threadLock) {
@@ -231,10 +234,6 @@
 	@Override
 	public void close() {
 
-		/* check for permission to play audio */
-		AudioPermission perm = new AudioPermission("play", null);
-		perm.checkGuard(null);
-
 		if (!isOpen) {
 			throw new IllegalStateException("line already closed");
 		}
@@ -255,6 +254,9 @@
 
 		super.close();
 
+		Debug.println(DebugLevel.Verbose, "PulseAudioClip.close(): "
+				+ "Clip closed");
+
 	}
 
 	/*
@@ -397,10 +399,6 @@
 	public void open(AudioFormat format, byte[] data, int offset, int bufferSize)
 			throws LineUnavailableException {
 
-		/* check for permission to play audio */
-		AudioPermission perm = new AudioPermission("play", null);
-		perm.checkGuard(null);
-
 		super.open(format);
 		this.data = new byte[bufferSize];
 		System.arraycopy(data, offset, this.data, 0, bufferSize);
@@ -425,6 +423,7 @@
 		mixer.addSourceLine(this);
 
 		isOpen = true;
+		Debug.println(DebugLevel.Verbose, "PulseAudioClip.open(): Clip opened");
 
 	}
 
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java	Mon Nov 17 15:26:51 2008 +0000
@@ -67,6 +67,8 @@
 import javax.sound.sampled.AudioFormat.Encoding;
 import javax.sound.sampled.Control.Type;
 
+import org.classpath.icedtea.pulseaudio.Debug.DebugLevel;
+
 public class PulseAudioMixer implements javax.sound.sampled.Mixer {
 	// singleton
 
@@ -92,6 +94,10 @@
 	private final List<LineListener> lineListeners = new ArrayList<LineListener>();
 
 	private PulseAudioMixer() {
+
+		Debug.println(DebugLevel.Verbose, "PulseAudioMixer.PulseAudioMixer(): "
+				+ "Contructing PulseAudioMixer...");
+
 		AudioFormat[] formats = getSupportedFormats();
 
 		staticSourceLineInfos.add(new DataLine.Info(SourceDataLine.class,
@@ -107,6 +113,9 @@
 
 		refreshSourceAndTargetLines();
 
+		Debug.println(DebugLevel.Verbose, "PulseAudioMixer.PulseAudioMixer(): "
+				+ "Finished constructing PulseAudioMixer");
+
 	}
 
 	synchronized public static PulseAudioMixer getInstance() {
@@ -126,7 +135,9 @@
 		 * frameSize = sample size (in bytes, not bits) x # of channels
 		 * 
 		 * From PulseAudio's sources
-		 * http://git.0pointer.de/?p=pulseaudio.git;a=blob;f=src/pulse/sample.c;h=93da2465f4301e27af4976e82737c3a048124a68;hb=82ea8dde8abc51165a781c69bc3b38034d62d969#l63
+		 * http://git.0pointer.de/?p=pulseaudio.git;a=blob
+		 * ;f=src/pulse/sample.c;h=93da2465f4301e27af4976e82737c3a048124a68;hb=
+		 * 82ea8dde8abc51165a781c69bc3b38034d62d969#l63
 		 */
 
 		/*
@@ -135,7 +146,6 @@
 		 * 
 		 * PA_CHANNEL_MAP_DEFAULT (=PA_CHANNEL_MAP_AIFF) supports 1,2,3,4,5 or 6
 		 * channels only
-		 * 
 		 */
 		int[] channelSizes = new int[] { 1, 2, 3, 4, 5, 6 };
 
@@ -298,15 +308,11 @@
 		}
 
 		if ((info.getLineClass() == SourceDataLine.class)) {
-			/* check for permission to play audio */
-			AudioPermission perm = new AudioPermission("play", null);
-			perm.checkGuard(null);
-
 			return new PulseAudioSourceDataLine(formats, defaultFormat);
 		}
 
 		if ((info.getLineClass() == TargetDataLine.class)) {
-			/* check for permission to play audio */
+			/* check for permission to record audio */
 			AudioPermission perm = new AudioPermission("record", null);
 			perm.checkGuard(null);
 
@@ -314,10 +320,6 @@
 		}
 
 		if ((info.getLineClass() == Clip.class)) {
-			/* check for permission to play audio */
-			AudioPermission perm = new AudioPermission("play", null);
-			perm.checkGuard(null);
-
 			return new PulseAudioClip(formats, defaultFormat);
 		}
 
@@ -330,6 +332,9 @@
 			}
 		}
 
+		Debug.println(DebugLevel.Info, "PulseAudioMixer.getLine(): "
+				+ "No matching line supported by PulseAudio");
+
 		throw new IllegalArgumentException("No matching lines found");
 
 	}
@@ -371,11 +376,6 @@
 
 	@Override
 	public Line[] getSourceLines() {
-
-		/* check for permmission to play audio */
-		AudioPermission perm = new AudioPermission("play", null);
-		perm.checkGuard(null);
-
 		return (Line[]) sourceLines.toArray(new Line[0]);
 
 	}
@@ -401,7 +401,7 @@
 	@Override
 	public Line[] getTargetLines() {
 
-		/* check for permission to play audio */
+		/* check for permission to record audio */
 		AudioPermission perm = new AudioPermission("record", null);
 		perm.checkGuard(null);
 
@@ -492,16 +492,6 @@
 		 * is allowed
 		 */
 
-		try {
-			/* check for permission to play audio */
-			AudioPermission perm = new AudioPermission("play", null);
-			perm.checkGuard(null);
-		} catch (SecurityException e) {
-			/* check for permission to record audio */
-			AudioPermission perm = new AudioPermission("record", null);
-			perm.checkGuard(null);
-		}
-
 		if (!this.isOpen) {
 			throw new IllegalStateException("Mixer is not open; cant close");
 		}
@@ -509,11 +499,14 @@
 		List<Line> linesToClose = new LinkedList<Line>();
 		linesToClose.addAll(sourceLines);
 		if (sourceLines.size() > 0) {
+
+			Debug.println(DebugLevel.Warning, "PulseAudioMixer.close(): "
+					+ linesToClose.size()
+					+ " source lines were not closed. closing them now.");
+
 			linesToClose.addAll(sourceLines);
 			for (Line line : linesToClose) {
 				if (line.isOpen()) {
-					System.out
-							.println("PulseAudioMixer: DEBUG: some source lines have not been closed");
 					line.close();
 				}
 			}
@@ -521,11 +514,13 @@
 		linesToClose.clear();
 
 		if (targetLines.size() > 0) {
+			Debug.println(DebugLevel.Warning, "PulseAudioMixer.close(): "
+					+ linesToClose.size()
+					+ " target lines have not been closed");
+
 			linesToClose.addAll(targetLines);
 			for (Line line : linesToClose) {
 				if (line.isOpen()) {
-					System.out
-							.println("PulseAudioMixer: DEBUG: some target lines have not been closed");
 					line.close();
 				}
 			}
@@ -544,12 +539,13 @@
 					+ ": interrupted while waiting for eventloop to finish");
 		}
 
-		// System.out.println(this.getClass().getName() + ": closed");
-
 		isOpen = false;
 
 		refreshSourceAndTargetLines();
 
+		Debug.println(DebugLevel.Verbose, "PulseAudioMixer.close(): "
+				+ "Mixer closed");
+
 	}
 
 	@Override
@@ -617,16 +613,6 @@
 		 * is allowed
 		 */
 
-		try {
-			/* check for permission to play audio */
-			AudioPermission perm = new AudioPermission("play", null);
-			perm.checkGuard(null);
-		} catch (SecurityException e) {
-			/* check for permission to record audio */
-			AudioPermission perm = new AudioPermission("record", null);
-			perm.checkGuard(null);
-		}
-
 		if (isOpen) {
 			throw new IllegalStateException("Mixer is already open");
 		}
@@ -724,6 +710,9 @@
 			targetLineInfos.add(new Port.Info(Port.class, portName, false));
 		}
 
+		Debug.println(DebugLevel.Debug, "PulseAudioMixer.open(): "
+				+ "Mixer opened");
+
 	}
 
 	@Override
@@ -738,7 +727,6 @@
 	 * Cons: - eventListeners are run from other threads, if those then call
 	 * fireEvent while a method is waiting on a listener, this synchronized
 	 * block wont be entered: deadlock!
-	 * 
 	 */
 	private void fireEvent(final LineEvent e) {
 		synchronized (lineListeners) {
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixerProvider.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixerProvider.java	Mon Nov 17 15:26:51 2008 +0000
@@ -43,6 +43,10 @@
 public class PulseAudioMixerProvider extends
 		javax.sound.sampled.spi.MixerProvider {
 
+	public PulseAudioMixerProvider() {
+		Debug.initialize();
+	}
+
 	@Override
 	public Mixer getMixer(Info info) {
 		// System.out.println("DEBUG: getMixer called");
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java	Mon Nov 17 15:26:51 2008 +0000
@@ -63,7 +63,7 @@
 	private PulseAudioVolumeControl volumeControl;
 
 	static {
-		System.loadLibrary("pulse-java");
+		SecurityWrapper.loadNativeLibrary();
 	}
 
 	public PulseAudioPort(String name) {
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java	Mon Nov 17 15:26:51 2008 +0000
@@ -41,11 +41,12 @@
 
 import javax.sound.sampled.AudioFormat;
 import javax.sound.sampled.DataLine;
-import javax.sound.sampled.AudioPermission;
 import javax.sound.sampled.LineListener;
 import javax.sound.sampled.LineUnavailableException;
 import javax.sound.sampled.SourceDataLine;
 
+import org.classpath.icedtea.pulseaudio.Debug.DebugLevel;
+
 public class PulseAudioSourceDataLine extends PulseAudioDataLine implements
 		SourceDataLine, PulseAudioPlaybackLine {
 
@@ -68,10 +69,6 @@
 	synchronized public void open(AudioFormat format, int bufferSize)
 			throws LineUnavailableException {
 
-		/* check for permission to play audio */
-		AudioPermission perm = new AudioPermission("play", null);
-		perm.checkGuard(null);
-
 		super.open(format, bufferSize);
 
 		volumeControl = new PulseAudioVolumeControl(this, eventLoop);
@@ -82,6 +79,9 @@
 		PulseAudioMixer parentMixer = PulseAudioMixer.getInstance();
 		parentMixer.addSourceLine(this);
 
+		Debug.println(DebugLevel.Verbose, "PulseAudioSourceDataLine.open(): "
+				+ "line opened");
+
 	}
 
 	@Override
@@ -154,11 +154,14 @@
 		}
 
 		if (offset < 0) {
-			throw new ArrayIndexOutOfBoundsException("offset is negative: " + offset);
+			throw new ArrayIndexOutOfBoundsException("offset is negative: "
+					+ offset);
 		}
-		
+
 		if (length + offset > data.length) {
-			throw new ArrayIndexOutOfBoundsException("writing data beyond the length of the array: " + (length + offset));
+			throw new ArrayIndexOutOfBoundsException(
+					"writing data beyond the length of the array: "
+							+ (length + offset));
 		}
 
 		int position = offset;
@@ -318,10 +321,6 @@
 	@Override
 	synchronized public void close() {
 
-		/* check for permmission to play audio */
-		AudioPermission perm = new AudioPermission("play", null);
-		perm.checkGuard(null);
-
 		if (!isOpen) {
 			throw new IllegalStateException("not open so cant close");
 		}
@@ -332,8 +331,12 @@
 		parent.removeSourceLine(this);
 
 		super.close();
+
+		Debug.println(DebugLevel.Verbose, "PulseAudioSourceDataLine.close():"
+				+ " line closed");
+
 	}
-	
+
 	public javax.sound.sampled.Line.Info getLineInfo() {
 		return new DataLine.Info(SourceDataLine.class, supportedFormats,
 				StreamBufferAttributes.MIN_VALUE,
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java	Mon Nov 17 15:26:51 2008 +0000
@@ -45,7 +45,7 @@
 	/* aka mic */
 
 	static {
-		System.loadLibrary("pulse-java");
+		SecurityWrapper.loadNativeLibrary();
 	}
 
 	public PulseAudioSourcePort(String name) {
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java	Mon Nov 17 15:26:51 2008 +0000
@@ -44,6 +44,8 @@
 import javax.sound.sampled.LineUnavailableException;
 import javax.sound.sampled.TargetDataLine;
 
+import org.classpath.icedtea.pulseaudio.Debug.DebugLevel;
+
 public class PulseAudioTargetDataLine extends PulseAudioDataLine implements
 		TargetDataLine {
 
@@ -84,6 +86,9 @@
 		parentMixer.removeTargetLine(this);
 
 		super.close();
+
+		Debug.println(DebugLevel.Verbose, "PulseAudioTargetDataLine.close(): "
+				+ "Line closed");
 	}
 
 	@Override
@@ -107,6 +112,9 @@
 		/* add this open line to the mixer */
 		PulseAudioMixer parentMixer = PulseAudioMixer.getInstance();
 		parentMixer.addTargetLine(this);
+
+		Debug.println(DebugLevel.Verbose, "PulseAudioTargetDataLine.open(): "
+				+ "Line opened");
 	}
 
 	@Override
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java	Mon Nov 17 15:26:51 2008 +0000
@@ -37,7 +37,6 @@
 
 package org.classpath.icedtea.pulseaudio;
 
-import javax.sound.sampled.AudioPermission;
 import javax.sound.sampled.Port;
 
 public class PulseAudioTargetPort extends PulseAudioPort {
@@ -45,7 +44,7 @@
 	/* aka speaker */
 
 	static {
-		System.loadLibrary("pulse-java");
+		SecurityWrapper.loadNativeLibrary();
 	}
 
 	public PulseAudioTargetPort(String name) {
@@ -55,10 +54,6 @@
 
 	public void open() {
 
-		/* check for permission to play audio */
-		AudioPermission perm = new AudioPermission("play", null);
-		perm.checkGuard(null);
-
 		super.open();
 
 		PulseAudioMixer parent = PulseAudioMixer.getInstance();
@@ -67,10 +62,6 @@
 
 	public void close() {
 
-		/* check for permission to play audio */
-		AudioPermission perm = new AudioPermission("play", null);
-		perm.checkGuard(null);
-
 		if (!isOpen) {
 			throw new IllegalStateException("not open, so cant close Port");
 		}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/SecurityWrapper.java	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,27 @@
+package org.classpath.icedtea.pulseaudio;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+class SecurityWrapper {
+
+	public static void loadNativeLibrary() {
+
+		if (System.getSecurityManager() != null) {
+			PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() {
+				@Override
+				public Boolean run() {
+					System.loadLibrary("pulse-java");
+					return true;
+				}
+
+			};
+
+			AccessController.doPrivileged(action);
+
+		} else {
+			System.loadLibrary("pulse-java");
+		}
+
+	}
+}
--- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/Stream.java	Mon Nov 17 15:26:51 2008 +0000
@@ -104,11 +104,10 @@
 
 	public static final String DEFAULT_DEVICE = null;
 
-	@SuppressWarnings("unused")
 	private byte[] streamPointer;
 
 	static {
-		System.loadLibrary("pulse-java");
+		SecurityWrapper.loadNativeLibrary();
 	}
 
 	private Format format;
--- a/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c	Mon Nov 17 12:41:07 2008 +0000
+++ b/pulseaudio/src/native/org_classpath_icedtea_pulseaudio_EventLoop.c	Mon Nov 17 15:26:51 2008 +0000
@@ -356,7 +356,8 @@
 	*new_volume = volume;
 
 	int stream_id = pa_stream_get_index(stream);
-	pa_context_get_sink_input_info(context, stream_id,sink_input_change_volume, new_volume);
+	pa_operation* o = pa_context_get_sink_input_info(context, stream_id,sink_input_change_volume, new_volume);
+	pa_operation_unref(o);
 	return;
 }
 
--- a/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java	Mon Nov 17 15:26:51 2008 +0000
@@ -227,6 +227,66 @@
 
 	}
 
+	@Test(expected = IllegalArgumentException.class)
+	public void testWriteIntegralNumberFrames() throws LineUnavailableException {
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
+				SourceDataLine.class));
+
+		/* try writing an non-integral number of frames size */
+		sourceDataLine.open();
+		int frameSize = sourceDataLine.getFormat().getFrameSize();
+		byte[] buffer = new byte[(frameSize * 2) - 1];
+		sourceDataLine.write(buffer, 0, buffer.length);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testWriteNegativeLength() throws LineUnavailableException {
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
+				SourceDataLine.class));
+
+		sourceDataLine.open();
+		int frameSize = sourceDataLine.getFormat().getFrameSize();
+		byte[] buffer = new byte[(frameSize * 2)];
+		/* try writing a negative length */
+		sourceDataLine.write(buffer, 0, -2);
+	}
+
+	@Test(expected = ArrayIndexOutOfBoundsException.class)
+	public void testWriteNegativeOffset() throws LineUnavailableException {
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
+				SourceDataLine.class));
+
+		sourceDataLine.open();
+		int frameSize = sourceDataLine.getFormat().getFrameSize();
+		byte[] buffer = new byte[(frameSize * 2)];
+		/* try writing with a negative offset */
+		sourceDataLine.write(buffer, -1, buffer.length);
+	}
+
+	@Test(expected = ArrayIndexOutOfBoundsException.class)
+	public void testWriteMoreThanArrayLength() throws LineUnavailableException {
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
+				SourceDataLine.class));
+
+		sourceDataLine.open();
+		int frameSize = sourceDataLine.getFormat().getFrameSize();
+		byte[] buffer = new byte[(frameSize * 2)];
+		/* try writing more than the array length */
+		sourceDataLine.write(buffer, 0, frameSize * 3);
+	}
+
+	@Test(expected = ArrayIndexOutOfBoundsException.class)
+	public void testWriteMoreThanArrayLength2() throws LineUnavailableException {
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
+				SourceDataLine.class));
+
+		sourceDataLine.open();
+		int frameSize = sourceDataLine.getFormat().getFrameSize();
+		byte[] buffer = new byte[(frameSize * 2)];
+		/* try writing more than the array length */
+		sourceDataLine.write(buffer, 1, buffer.length);
+	}
+
 	@Test
 	public void testWriteWithoutStart() throws UnsupportedAudioFileException,
 			IOException, LineUnavailableException, InterruptedException {
@@ -253,11 +313,18 @@
 					int total = 0;
 
 					while (bytesRead >= 0 && total < 50) {
+
 						bytesRead = audioInputStream.read(abData, 0,
 								abData.length);
 						if (bytesRead > 0) {
 							sourceDataLine.write(abData, 0, bytesRead);
 						}
+						
+						// when the line is closed (in tearDown),
+						// break out of the loop
+						if (!sourceDataLine.isOpen()) {
+							break;
+						}
 						total++;
 					}
 				} catch (LineUnavailableException e) {
@@ -273,7 +340,7 @@
 
 		Thread.sleep(100);
 
-		writer.join(1000);
+		writer.join(2000);
 
 		/* assert that the writer is still waiting in write */
 		Assert.assertTrue(writer.isAlive());
--- a/test/jtreg/README	Mon Nov 17 12:41:07 2008 +0000
+++ b/test/jtreg/README	Mon Nov 17 15:26:51 2008 +0000
@@ -20,7 +20,7 @@
 This version is based on:
 
 - jtharness-oss-4_1_3a-dev
-- jtreg-4_0-src-b01-29_apr_2008
+- jtreg-4_0-src-b02-15_oct_2008
 
 IcedJTReg is distrubuted under the GPLv2.0, like jtreg and jtharness.
 See the documents in the legal directory included in this release.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jtreg/com/sun/javatest/diff/Diff.java	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.javatest.diff;
+
+import com.sun.javatest.Status;
+import com.sun.javatest.TestResult;
+import com.sun.javatest.TestSuite;
+import com.sun.javatest.WorkDirectory;
+import com.sun.javatest.util.I18NResourceBundle;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+public abstract class Diff {
+
+    public abstract boolean report(File outFile) throws Fault, InterruptedException;
+
+    protected boolean diff(List<File> files, File outFile)
+            throws Fault, InterruptedException {
+        this.outFile = outFile;
+        List<DiffReader> list = new ArrayList<DiffReader>();
+        for (File f: files)
+            list.add(open(f));
+
+        PrintWriter prevOut = out;
+        if (out == null && outFile != null) {
+            try {
+                out = new PrintWriter(new BufferedWriter(new FileWriter(outFile))); // FIXME don't want to use PrintWriter
+            } catch (IOException e) {
+                throw new Fault(i18n, "diff.cantOpenFile", outFile, e);
+            }
+        }
+
+        try {
+            initComparator();
+
+            initReporter();
+            reporter.setTitle(title);
+            reporter.setComparator(comparator);
+            reporter.setReaders(list);
+
+            List<int[]> testCounts = new ArrayList<int[]>();
+            MultiMap<String,TestResult> table = new MultiMap<String,TestResult>();
+            for (DiffReader r: list) {
+                int index = table.addColumn(r.getFile().getPath());
+                int[] counts = new int[Status.NUM_STATES];
+                for (TestResult tr: r) {
+                    table.addRow(index, tr.getTestName(), tr);
+                    counts[tr.getStatus().getType()]++;
+                }
+                testCounts.add(counts);
+            }
+            reporter.setTestCounts(testCounts);
+
+            try {
+                reporter.write(table);
+            } catch (IOException e) {
+                throw new Fault(i18n, "diff.ioError", e);
+            }
+
+            return (reporter.diffs == 0);
+        } finally {
+            if (out != prevOut) {
+//                try {
+                    out.close();
+//                } catch (IOException e) {
+//                    throw new Fault(i18n, "main.ioError", e);
+//                }
+                out = prevOut;
+            }
+        }
+    }
+
+    protected void initFormat() {
+        if (format == null && outFile != null) {
+            String name = outFile.getName();
+            int dot = name.lastIndexOf(".");
+            if (dot != -1)
+                format = name.substring(dot + 1).toLowerCase();
+        }
+    }
+
+    protected void initReporter() throws Fault {
+        if (reporter == null) {
+            try {
+                initFormat();
+                if (format != null && format.equals("html"))
+                    reporter = new HTMLReporter(out);
+                else
+                    reporter = new SimpleReporter(out);
+            } catch (IOException e) {
+                throw new Fault(i18n, "diff.cantOpenReport", e);
+            }
+        }
+    }
+
+    protected void initComparator() {
+        if (comparator == null)
+            comparator = new StatusComparator(includeReason);
+    }
+
+    protected DiffReader open(File f) throws Fault {
+        if (!f.exists())
+            throw new Fault(i18n, "main.cantFindFile", f);
+
+        try {
+            if (WorkDirectoryReader.accepts(f))
+                return new WorkDirectoryReader(f);
+
+            if (ReportReader.accepts(f))
+                return new ReportReader(f);
+
+            throw new Fault(i18n, "main.unrecognizedFile", f);
+
+        } catch (TestSuite.Fault e) {
+            throw new Fault(i18n, "main.cantOpenFile", f, e);
+        } catch (WorkDirectory.Fault e) {
+            throw new Fault(i18n, "main.cantOpenFile", f, e);
+        } catch (IOException e) {
+            throw new Fault(i18n, "main.cantOpenFile", f, e);
+        }
+
+    }
+
+    protected File outFile;
+    protected PrintWriter out;
+    protected Comparator<TestResult> comparator;
+    protected Reporter reporter;
+    protected boolean includeReason;
+    protected String format;
+    protected String title;
+    private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(Diff.class);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jtreg/com/sun/javatest/diff/Fault.java	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.javatest.diff;
+
+import com.sun.javatest.util.I18NResourceBundle;
+
+/**
+ * Exception to report a problem while executing in Main.
+ */
+public class Fault extends Exception {
+
+    static final long serialVersionUID = 1607979458544175906L;
+
+    Fault(I18NResourceBundle i18n, String s, Object... args) {
+        super(i18n.getString(s, args));
+    }
+}
--- a/test/jtreg/com/sun/javatest/diff/HTMLReporter.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/test/jtreg/com/sun/javatest/diff/HTMLReporter.java	Mon Nov 17 15:26:51 2008 +0000
@@ -33,7 +33,6 @@
 
 import com.sun.javatest.TestResult;
 import com.sun.javatest.Status;
-import com.sun.javatest.util.HTMLWriter;
 import com.sun.javatest.util.I18NResourceBundle;
 
 import static com.sun.javatest.util.HTMLWriter.*;
@@ -47,8 +46,8 @@
  * Report differences to an HTML file.
  */
 public class HTMLReporter extends Reporter {
-    
-    /** Creates a new instance of SimpleDiffReporter */
+
+    /** Creates a new instance of HTMLReporter */
     public HTMLReporter(Writer out) throws IOException {
         this.out = new HTMLWriter(out, DOCTYPE);
         this.out.setI18NResourceBundle(i18n);
@@ -56,10 +55,40 @@
 
     public void write(MultiMap<String, TestResult> table) throws IOException {
         this.table = table;
-        
         size = table.getColumns();
-        
+
+        startReport(title);
+
+        out.startTag(H1);
+        if (title == null)
+            out.writeI18N("html.head.notitle");
+        else
+            out.writeI18N("html.head.title", title);
+        out.endTag(H1);
+
+        writeIndexTable();
+        writeMainTable();
+        writeSummary();
+
+        endReport();
+    }
+
+    protected void startReport(String title) throws IOException {
         out.startTag(HTML);
+        writeHead(title);
+        out.startTag(BODY);
+    }
+
+    protected void endReport() throws IOException {
+        out.startTag(HR);
+        out.writeI18N("html.generatedAt", new Date());
+        out.endTag(BODY);
+
+        out.endTag(HTML);
+        out.flush();
+    }
+
+    protected void writeHead(String title) throws IOException {
         out.startTag(HEAD);
         out.startTag(TITLE);
         if (title == null)
@@ -74,40 +103,24 @@
         out.write("tr.head { background-color:#dddddd }");
         out.write("tr.odd  { background-color:#eeeeee }");
         out.write("tr.even { background-color:white } ");
-        out.write("td { padding: 0 1em }");
+        out.write("td { padding: 0 .5em }");
         out.write("td.pass { background-color:#ddffdd } ");
         out.write("td.fail { background-color:#ffdddd } ");
         out.write("td.error { background-color:#ddddff } ");
         out.write("td.notRun { background-color:#dddddd } ");
+        out.write("th { padding: 0 .5em }");
         out.write("hr      { margin-top:30px; }");
         out.write("\n");
         out.endTag(STYLE);
         out.endTag(HEAD);
-        
-        out.startTag(BODY);
-        out.startTag(H1);
-        if (title == null)
-            out.writeI18N("html.head.notitle");
-        else
-            out.writeI18N("html.head.title", title);
-        out.endTag(H1);
-        writeHead();
-        writeBody();
-        writeSummary();
-        
-        out.startTag(HR);
-        out.writeI18N("html.generatedAt", new Date());
-        out.endTag(BODY);
-        
-        out.endTag(HTML);
-        out.flush();
+
     }
-    
-    private void writeHead() throws IOException {
+
+    private void writeIndexTable() throws IOException {
         out.startTag(H2);
         out.writeI18N("html.head.sets");
         out.endTag(H2);
-        
+
         out.startTag(TABLE);
         out.writeAttr(FRAME, BOX);
         out.writeAttr(RULES, GROUPS);
@@ -120,6 +133,7 @@
         out.startTag(TH);
         out.writeI18N("html.th.location");
         out.endTag(TH);
+        writeIndexTableInfoHeadings();
 //        out.startTag(TH);
 //        out.writeI18N("html.th.type");
 //        out.endTag(TH);
@@ -146,16 +160,17 @@
         out.endTag(TH);
         out.endTag(TR);
         out.endTag(THEAD);
-        
+
         out.startTag(TBODY);
         for (int i = 0; i < size; i++) {
             out.startTag(TR);
             out.writeAttr(CLASS, (i % 2 == 0 ? EVEN : ODD));
             out.startTag(TD);
-            out.write(String.valueOf(i));
+            out.write(String.valueOf(i + 1));
             out.endTag(TD);
             out.startTag(TD);
             out.write(table.getColumnName(i));
+            writeIndexTableInfoValues(table.getColumnName(i));
             out.endTag(TD);
 //            out.startTag(TD);
 //            out.write("??");
@@ -166,7 +181,7 @@
                 out.startTag(TD);
                 if (counts[c] > 0)
                     out.write(String.valueOf(counts[c]));
-                else 
+                else
                     out.writeEntity("&nbsp;");
                 total += counts[c];
                 out.endTag(TD);
@@ -179,8 +194,14 @@
         out.endTag(TBODY);
         out.endTag(TABLE);
     }
-    
-    private void writeBody() throws IOException {
+
+    protected void writeIndexTableInfoHeadings() throws IOException {
+    }
+
+    protected void writeIndexTableInfoValues(String name) throws IOException {
+    }
+
+    private void writeMainTable() throws IOException {
         diffs = 0;
         for (Map.Entry<String, MultiMap.Entry<TestResult>> e: table.entrySet()) {
             String testName = e.getKey();
@@ -202,7 +223,10 @@
                 out.endTag(TH);
                 for (int i = 0; i < result.getSize(); i++) {
                     out.startTag(TH);
-                    out.writeI18N("html.th.setN", i);
+                    if (compact)
+                        out.write(String.valueOf(i + 1));
+                    else
+                        out.writeI18N("html.th.setN", i + 1);
                     out.endTag(TH);
                 }
                 out.endTag(TR);
@@ -222,36 +246,24 @@
                     if (wd != null)
                         trFile = new File(wd, tr.getWorkRelativePath());
                 }
+                out.startTag(TD);
                 Status s = (tr == null ? null : tr.getStatus());
-                out.startTag(TD);
-                String classAttr;
-                String text;
-                switch (s == null ? Status.NOT_RUN : s.getType()) {
-                    case Status.PASSED:
-                        classAttr = PASS;
-                        text = i18n.getString("html.pass");
-                        break;
-                    case Status.FAILED:
-                        classAttr = FAIL;
-                        text = i18n.getString("html.fail");
-                        break;
-                    case Status.ERROR:
-                        classAttr = ERROR;
-                        text = i18n.getString("html.error");
-                        break;
-                    default:
-                        classAttr = NOT_RUN;
-                        text = i18n.getString("html.notRun");
-                        break;
-                }
-                out.writeAttr(CLASS, classAttr);
+                out.writeAttr(CLASS, getClassAttr(s));
+                String text = getText(s);
                 if (trFile != null && trFile.exists()) {
                     out.startTag(A);
                     out.writeAttr(HREF, trFile.toURI().toString());
-                    out.write(text);
+                    if (text.startsWith("&"))
+                        out.writeEntity(text);
+                    else
+                        out.write(text);
                     out.endTag(A);
-                } else
-                    out.write(text);
+                } else {
+                    if (text.startsWith("&"))
+                        out.writeEntity(text);
+                    else
+                        out.write(text);
+                }
                 out.endTag(TD);
             }
             out.endTag(TR);
@@ -262,7 +274,7 @@
             out.endTag(TABLE);
         }
     }
-    
+
     private void writeSummary() throws IOException {
         out.startTag(P);
         if (diffs == 0)
@@ -271,27 +283,60 @@
             out.writeI18N("html.diffs.count", diffs);
         out.endTag(P);
     }
-    
+
+    protected String getClassAttr(Status s) {
+        switch (s == null ? Status.NOT_RUN : s.getType()) {
+            case Status.PASSED:
+                return PASS;
+            case Status.FAILED:
+                return FAIL;
+            case Status.ERROR:
+                return ERROR;
+            default:
+                return NOT_RUN;
+        }
+    }
+
+    protected String getText(Status s) {
+        if (statusStrings == null) {
+            statusStrings = new String[Status.NUM_STATES];
+            if (compact) {
+                statusStrings[Status.PASSED] = i18n.getString("html.pass.compact");
+                statusStrings[Status.FAILED] = i18n.getString("html.fail.compact");
+                statusStrings[Status.ERROR] = i18n.getString("html.error.compact");
+                statusStrings[Status.NOT_RUN] = i18n.getString("html.notRun.compact");
+            } else {
+                statusStrings[Status.PASSED] = i18n.getString("html.pass");
+                statusStrings[Status.FAILED] = i18n.getString("html.fail");
+                statusStrings[Status.ERROR] = i18n.getString("html.error");
+                statusStrings[Status.NOT_RUN] = i18n.getString("html.notRun");
+            }
+        }
+        return statusStrings[s == null ? Status.NOT_RUN : s.getType()];
+    }
+
+    private String[] statusStrings;
+
+    protected final HTMLWriter out;
     private MultiMap<String, TestResult> table;
     private int size;
-    private HTMLWriter out;
-    
-    private static final String DOCTYPE = 
+
+    private static final String DOCTYPE =
             "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd\">";
-    
+
     // HTML tags
     private static final String THEAD = "thead";
     private static final String TBODY = "tbody";
-    
+
     // HTML attribute names
     private static final String CLASS = "class";
     private static final String FRAME = "frame";
     private static final String RULES = "rules";
-    
+
     // HTML attribute values
     private static final String BOX = "box";
     private static final String GROUPS = "groups";
-    
+
     // HTML class values
     private static final String HEAD = "head";
     private static final String ODD  = "odd";
@@ -300,6 +345,7 @@
     private static final String FAIL = "fail";
     private static final String ERROR = "error";
     private static final String NOT_RUN = "notRun";
-    
+
+    private boolean compact = Boolean.TRUE.equals(Boolean.getBoolean("jtdiff.html.compact"));
     private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(HTMLReporter.class);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jtreg/com/sun/javatest/diff/HTMLWriter.java	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,558 @@
+/*
+ * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.javatest.diff;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.Writer;
+import java.net.URL;
+import com.sun.javatest.util.I18NResourceBundle;
+
+/**
+ * A class to facilitate writing HTML via a stream.
+ */
+public class HTMLWriter
+{
+    /**
+     * Create an HTMLWriter object, using a default doctype for HTML 3.2.
+     * @param out a Writer to which to write the generated HTML
+     * @throws IOException if there is a problem writing to the underlying stream
+     */
+    public HTMLWriter(Writer out) throws IOException {
+        this(out, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">");
+    }
+
+    /**
+     * Create an HTMLWriter object, using a specifed doctype header.
+     * @param out a Writer to which to write the generated HTML
+     * @param docType a string containing a doctype header for the HTML to be generetaed
+     * @throws IOException if there is a problem writing to the underlying stream
+     */
+    public HTMLWriter(Writer out, String docType) throws IOException {
+        if (out instanceof BufferedWriter)
+            this.out = (BufferedWriter) out;
+        else
+            this.out = new BufferedWriter(out);
+        this.out.write(docType);
+        this.out.newLine();
+    }
+
+    /**
+     * Create an HTMLWriter object, using a specified bundle for l0calizing messages.
+     * @param out a Writer to which to write the generated HTML
+     * @param i18n a resource bundle to use to localize messages
+     * @throws IOException if there is a problem writing to the underlying stream
+     */
+    public HTMLWriter(Writer out, I18NResourceBundle i18n) throws IOException {
+        this(out);
+        this.i18n = i18n;
+    }
+
+
+    /**
+     * Create an HTMLWriter object, using a specifed doctype header and
+     * using a specified bundle for l0calizing messages.
+     * @param out a Writer to which to write the generated HTML
+     * @param docType a string containing a doctype header for the HTML to be generetaed
+     * @param i18n a resource bundle to use to localize messages
+     * @throws IOException if there is a problem writing to the underlying stream
+     */
+    public HTMLWriter(Writer out, String docType, I18NResourceBundle i18n) throws IOException {
+        this(out, docType);
+        this.i18n = i18n;
+    }
+
+    /**
+     * Set the reource bundle to be used for localizing messages.
+     * @param i18n the resource bundle to be used for localizing messages
+     */
+    public void setI18NResourceBundle(I18NResourceBundle i18n) {
+        this.i18n = i18n;
+    }
+
+    /**
+     * Flush the stream, and the underlying output stream.
+     * @throws IOException if there is a problem writing to the underlying stream
+     */
+    public void flush() throws IOException {
+        out.flush();
+    }
+
+    /**
+     * Close the stream, and the underlying output stream.
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void close() throws IOException {
+        out.close();
+    }
+
+    /**
+     * Write a newline to the underlying output stream.
+     * @throws IOException if there is a problem writing to the underlying stream
+     */
+    public void newLine() throws IOException {
+        out.newLine();
+    }
+
+    /**
+     * Start an HTML tag.  If a prior tag has been started, it will
+     * be closed first. Once a tag has been opened, attributes for the
+     * tag may be written out, followed by body content before finally
+     * ending the tag.
+     * @param tag the tag to be started
+     * @throws IOException if there is a problem writing to the underlying stream
+     * @see #writeAttr
+     * @see #write
+     * @see #endTag
+     */
+    public void startTag(String tag) throws IOException {
+        if (state == IN_TAG) {
+            out.write(">");
+            state = IN_BODY;
+        }
+        newLine();
+        out.write("<");
+        out.write(tag);
+        state = IN_TAG;
+    }
+
+    /**
+     * Finish an HTML tag. It is expected that a call to endTag will match
+     * a corresponding earlier call to startTag, but there is no formal check
+     * for this.
+     * @param tag the tag to be closed.
+     * @throws IOException if there is a problem writing to the underlying stream
+     */
+    public void endTag(String tag) throws IOException {
+        if (state == IN_TAG) {
+            out.write(">");
+            state = IN_BODY;
+            out.newLine();
+        }
+        out.write("</");
+        out.write(tag);
+        out.write(">");
+        //out.newLine();   // PATCHED, jjg
+        state = IN_BODY;
+    }
+
+    /**
+     * Finish an empty element tag, such as a META, BASE or LINK tag.
+     * This is expected to correspond with a startTag.
+     * @param tag the tag which is being closed.  this is only useful for
+     *        validation, it is not written out
+     * @throws IllegalStateException if this call does not follow startTag
+     *         (stream is not currently inside a tag)
+     * @throws IOException if there is a problem writing to the underlying stream
+     */
+    public void endEmptyTag(String tag) throws IOException {
+        if (state != IN_TAG)
+            throw new IllegalStateException();
+
+        out.write(">");
+        state = IN_BODY;
+        out.newLine();
+    }
+
+    /**
+     * Write an attribute for a tag. A tag must previously have been started.
+     * All tag attributes must be written before any body text is written.
+     * The value will be quoted if necessary when writing it to the underlying
+     * stream. No check is made that the attribute is valid for the current tag.
+     * @param name the name of the attribute to be written
+     * @param value the value of the attribute to be written
+     * @throws IllegalStateException if the stream is not in a state to
+     * write attributes -- e.g. if this call does not follow startTag or other
+     * calls of writteAttr
+     * @throws IOException if there is a problem writing to the underlying stream
+     */
+    public void writeAttr(String name, String value) throws IOException {
+        if (state != IN_TAG)
+            throw new IllegalStateException();
+
+        out.write(" ");
+        out.write(name);
+        out.write("=");
+        boolean alpha = true;
+        for (int i = 0; i < value.length() && alpha; i++)
+            alpha = Character.isLetter(value.charAt(i));
+        if (!alpha)
+            out.write("\"");
+        out.write(value);
+        if (!alpha)
+            out.write("\"");
+    }
+
+    /**
+     * Write an attribute for a tag. A tag must previously have been started.
+     * All tag attributes must be written before any body text is written.
+     * The value will be quoted if necessary when writing it to the underlying
+     * stream. No check is made that the attribute is valid for the current tag.
+     * @param name the name of the attribute to be written
+     * @param value the value of the attribute to be written
+     * @throws IllegalStateException if the stream is not in a state to
+     * write attributes -- e.g. if this call does not follow startTag or other
+     * calls of writteAttr
+     * @throws IOException if there is a problem writing to the underlying stream
+     */
+    public void writeAttr(String name, int value) throws IOException {
+        writeAttr(name, Integer.toString(value));
+    }
+
+    /**
+     * Write a line of text, followed by a newline.
+     * The text will be escaped as necessary.
+     * @param text the text to be written.
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void writeLine(String text) throws IOException {
+        write(text);
+        out.newLine();
+    }
+
+    /**
+     * Write body text, escaping it as necessary.
+     * If this call follows a call of startTag, the open tag will be
+     * closed -- meaning that no more attributes can be written until another
+     * tag is started.  If the text value is null, the current tag will still
+     * be closed, but no other text will be written.
+     * @param text the text to be written, may be null or zero length.
+     * @throws IOException if there is a problem writing to the underlying stream
+     */
+    public void write(String text) throws IOException {
+        if (state == IN_TAG) {
+            out.write(">");
+            state = IN_BODY;
+        }
+
+        if (text == null)
+            return;
+
+        // check to see if there are any special characters
+        boolean specialChars = false;
+        for (int i = 0; i < text.length() && !specialChars; i++) {
+            switch (text.charAt(i)) {
+            case '<': case '>': case '&':
+                specialChars = true;
+            }
+        }
+
+        // if there are special characters write the string character at a time;
+        // otherwise, write it out as is
+        if (specialChars) {
+            for (int i = 0; i < text.length(); i++) {
+                char c = text.charAt(i);
+                switch (c) {
+                case '<': out.write("&lt;"); break;
+                case '>': out.write("&gt;"); break;
+                case '&': out.write("&amp;"); break;
+                default: out.write(c);
+                }
+            }
+        }
+        else
+            out.write(text);
+    }
+
+    /**
+     * Write a basic HTML entity, such as &nbsp; or &#123; .
+     * @param entity the entity to write
+     * @throws IOException if there is a problem writing to the underlying stream
+     */
+    public void writeEntity(String entity) throws IOException {
+        if (state == IN_TAG) {
+            out.write(">");
+            state = IN_BODY;
+        }
+        out.write(entity);
+    }
+
+    /**
+     * Write an image tag, using a specified path for the image source attribute.
+     * @param imagePath the path for the image source
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void writeImage(String imagePath) throws IOException {
+        startTag(IMAGE);
+        writeAttr(SRC, imagePath);
+    }
+
+    /**
+     * Write an image tag, using a specified path for the image source attribute.
+     * @param imageURL the url for the image source
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void writeImage(URL imageURL) throws IOException {
+        writeImage(imageURL.toString());
+    }
+
+    /**
+     * Write a hypertext link.
+     * @param anchor the target for the link
+     * @param body the body text for the link
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void writeLink(String anchor, String body) throws IOException {
+        startTag(A);
+        writeAttr(HREF, anchor);
+        write(body);
+        endTag(A);
+    }
+
+    /**
+     * Write a hypertext link.
+     * @param file the target for the link
+     * @param body the body text for the link
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void writeLink(File file, String body) throws IOException {
+        startTag(A);
+        StringBuffer sb = new StringBuffer();
+        String path = file.getPath().replace(File.separatorChar, '/');
+        if (file.isAbsolute() && !path.startsWith("/"))
+            sb.append('/');
+        sb.append(path);
+        writeAttr(HREF, sb.toString());
+        write(body);
+        endTag(A);
+    }
+
+    /**
+     * Write a hypertext link.
+     * @param file the target and body for the link
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void writeLink(File file) throws IOException {
+        writeLink(file, file.getPath());
+    }
+
+    /**
+     * Write a hypertext link.
+     * @param url the target for the link
+     * @param body the body text for the link
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void writeLink(URL url, String body) throws IOException {
+        startTag(A);
+        writeAttr(HREF, url.toString());
+        write(body);
+        endTag(A);
+    }
+
+    /**
+     * Write the destination marker for a hypertext link.
+     * @param anchor the destination marker for hypertext links
+     * @param body the body text for the marker
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void writeLinkDestination(String anchor, String body) throws IOException {
+        startTag(A);
+        writeAttr(NAME, anchor);
+        write(body);
+        endTag(A);
+    }
+
+    /**
+     * Write a parameter tag.
+     * @param name the name of the parameter
+     * @param value the value of the parameter
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void writeParam(String name, String value) throws IOException {
+        startTag(PARAM);
+        writeAttr(NAME, name);
+        writeAttr(VALUE, value);
+    }
+
+    /**
+     * Write a style attribute.
+     * @param value the value for the style atrtribute
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void writeStyleAttr(String value) throws IOException {
+        writeAttr(STYLE, value);
+    }
+
+    /**
+     * Write a localized message, using a specified resource bundle.
+     * @param i18n the resource bundle used to localize the message
+     * @param key the key for the message to be localized
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void write(I18NResourceBundle i18n, String key) throws IOException {
+        write(i18n.getString(key));
+    }
+
+    /**
+     * Write a localized message, using a specified resource bundle.
+     * @param i18n the resource bundle used to localize the message
+     * @param key the key for the message to be localized
+     * @param arg an argument to be formatted into the localized message
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void write(I18NResourceBundle i18n, String key, Object arg) throws IOException {
+        write(i18n.getString(key, arg));
+    }
+
+    /**
+     * Write a localized message, using a specified resource bundle.
+     * @param i18n the resource bundle used to localize the message
+     * @param key the key for the message to be localized
+     * @param args arguments to be formatted into the localized message
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void write(I18NResourceBundle i18n, String key, Object[] args) throws IOException {
+        write(i18n.getString(key, args));
+    }
+
+    /**
+     * Write a localized message, using the default resource bundle.
+     * @param key the key for the message to be localized
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void writeI18N(String key) throws IOException {
+        write(i18n.getString(key));
+    }
+
+    /**
+     * Write a localized message, using the default resource bundle.
+     * @param key the key for the message to be localized
+     * @param arg an argument to be formatted into the localized message
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void writeI18N(String key, Object arg) throws IOException {
+        write(i18n.getString(key, arg));
+    }
+
+    /**
+     * Write a localized message, using the default resource bundle.
+     * @param key the key for the message to be localized
+     * @param args arguments to be formatted into the localized message
+     * @throws IOException if there is a problem closing the underlying stream
+     */
+    public void writeI18N(String key, Object[] args) throws IOException {
+        write(i18n.getString(key, args));
+    }
+
+    /** The HTML "a" tag. */
+    public static final String A = "a";
+    /** The HTML "align" attribute. */
+    public static final String ALIGN = "align";
+    /** The HTML "b" tag. */
+    public static final String B = "b";
+    /** The HTML "body" tag. */
+    public static final String BODY = "body";
+    /** The HTML "border" attribute. */
+    public static final String BORDER = "border";
+    /** The HTML "br" tag. */
+    public static final String BR = "br";
+    /** The HTML "classid" attribute. */
+    public static final String CLASSID  = "classid";
+    /** The HTML "code" tag. */
+    public static final String CODE  = "code";
+    /** The HTML "color" attribte. */
+    public static final String COLOR  = "color";
+    /** The HTML "col" attribute value. */
+    public static final String COL = "col";
+    /** The HTML "font" tag. */
+    public static final String FONT = "font";
+    /** The HTML "h1" tag. */
+    public static final String H1 = "h1";
+    /** The HTML "h2" tag. */
+    public static final String H2 = "h2";
+    /** The HTML "h3" tag. */
+    public static final String H3 = "h3";
+    /** The HTML "h4" tag. */
+    public static final String H4 = "h4";
+    /** The HTML "head" tag. */
+    public static final String HEAD = "head";
+    /** The HTML "href" attribute. */
+    public static final String HREF = "href";
+    /** The HTML "html" tag. */
+    public static final String HTML = "html";
+    /** The HTML "hr" tag. */
+    public static final String HR = "hr";
+    /** The HTML "i" tag. */
+    public static final String I = "i";
+    /** The HTML "image" tag. */
+    public static final String IMAGE = "image";
+    /** The HTML "left" attribute value. */
+    public static final String LEFT = "left";
+    /** The HTML "li" tag. */
+    public static final String LI = "li";
+    /** The HTML "link" tag. */
+    public static final String LINK = "link";
+    /** The HTML "name" attribute. */
+    public static final String NAME = "name";
+    /** The HTML "object" tag. */
+    public static final String OBJECT = "object";
+    /** The HTML "p" tag. */
+    public static final String PARAM = "param";
+    /** The HTML "param" tag. */
+    public static final String P = "p";
+    /** The HTML "rel" attribute value. */
+    public static final String REL = "rel";
+    /** The HTML "right" attribute value. */
+    public static final String RIGHT = "right";
+    /** The HTML "row" attribute value. */
+    public static final String ROW = "row";
+    /** The HTML "small" tag. */
+    public static final String SMALL = "small";
+    /** The HTML "src" attribute. */
+    public static final String SRC = "src";
+    /** The HTML "scope" attribute. */
+    public static final String SCOPE = "scope";
+    /** The HTML "style" attribute. */
+    public static final String STYLE = "style";
+    /** The HTML "table" tag. */
+    public static final String TABLE = "table";
+    /** The HTML "td" tag. */
+    public static final String TD = "td";
+    /** The HTML "title"attribute. */
+    public static final String TITLE = "title";
+    /** The HTML "th" tag. */
+    public static final String TH = "th";
+    /** The HTML "top" attribute value. */
+    public static final String TOP = "top";
+    /** The HTML "tr" tag. */
+    public static final String TR = "tr";
+    /** The HTML "type" attribute. */
+    public static final String TYPE = "type";
+    /** The HTML "ul" tag. */
+    public static final String UL = "ul";
+    /** The HTML "valign" attribute. */
+    public static final String VALIGN = "valign";
+    /** The HTML "value" attribute. */
+    public static final String VALUE = "value";
+
+
+    private BufferedWriter out;
+    private int state;
+    private I18NResourceBundle i18n;
+    private static final int IN_TAG = 1;
+    private static final int IN_BODY = 2;
+}
--- a/test/jtreg/com/sun/javatest/diff/Main.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/test/jtreg/com/sun/javatest/diff/Main.java	Mon Nov 17 15:26:51 2008 +0000
@@ -33,20 +33,12 @@
 package com.sun.javatest.diff;
 
 import com.sun.javatest.regtest.BadArgs;
-import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Comparator;
 import java.util.List;
 
-import com.sun.javatest.Status;
-import com.sun.javatest.TestResult;
-import com.sun.javatest.TestSuite;
-import com.sun.javatest.WorkDirectory;
 import com.sun.javatest.regtest.AntOptionDecoder;
 import com.sun.javatest.regtest.Option;
 import com.sun.javatest.regtest.OptionDecoder;
@@ -58,29 +50,24 @@
  * Main entry point for jtdiff.
  */
 public class Main {
-    
-    /**
-     * Exception to report a problem while executing in Main.
-     */
-    public static class Fault extends Exception {
-        static final long serialVersionUID = 1607979458544175906L;
-        Fault(I18NResourceBundle i18n, String s, Object... args) {
-            super(i18n.getString(s, args));
-        }
-    }
     //---------- command line option decoding ----------------------------------
-  
+
     private static final String COMPARE = "compare";
     private static final String OUTPUT = "output";
     private static final String DOC = "doc";
     private static final String FILES = "files";
-    
+
     Option[] options = {
-        new Option(NONE, COMPARE, "r", "reason") {
+        new Option(NONE, COMPARE, "r", "r", "reason") {
             public void process(String opt, String arg) {
                 includeReason = true;
             }
         },
+        new Option(NONE, COMPARE, "s", "s", "super") {
+            public void process(String opt, String arg) {
+                superMode = true;
+            }
+        },
         new Option(OLD, OUTPUT, "o", "o", "outFile") {
             public void process(String opt, String arg) {
                 outFile = new File(arg);
@@ -136,7 +123,7 @@
             } finally {
                 out.flush();
             }
-            
+
             if (!ok) {
                 // take care not to exit if GUI might be around,
                 // and take care to ensure JavaTestSecurityManager will
@@ -159,16 +146,16 @@
             exit(3);
         }
     } // main()
-    
+
     public Main() {
         this(new PrintWriter(System.out, true), new PrintWriter(System.err, true));
     }
-    
+
     public Main(PrintWriter out, PrintWriter err) {
         this.out = out;
         this.err = err;
     }
-    
+
     /**
      * Decode command line args and perform the requested operations.
      * @param args An array of args, such as might be supplied on the command line.
@@ -178,141 +165,55 @@
      */
     public final boolean run(String[] args) throws BadArgs, Fault, InterruptedException {
         new OptionDecoder(options).decodeArgs(args);
-            
+
+        if (superMode) {
+            if (fileArgs.size() != 1 || !fileArgs.get(0).isDirectory())
+                throw new Fault(i18n, "main.bad.super.dir");
+            if (format != null)
+                throw new Fault(i18n, "main.bad.super.format");
+        }
+
         return run();
     }
-    
+
     private boolean run() throws Fault, InterruptedException {
-        if (fileArgs.size() == 0 && help == null) {
+        if (fileArgs.size() == 0 && !superMode && help == null) {
             help = new Help(options);
             help.setCommandLineHelpQuery(null);
         }
-        
+
         if (help != null) {
             help.show(out);
             return true;
         }
-        
-        List<DiffReader> list = new ArrayList<DiffReader>();
-        for (File f: fileArgs)
-            list.add(open(f));
-        
-        PrintWriter prevOut = out;
-        if (outFile != null) {
-            try {
-                out = new PrintWriter(new BufferedWriter(new FileWriter(outFile))); // FIXME don't want to use PrintWriter
-            } catch (IOException e) {
-                throw new Fault(i18n, "main.cantOpenFile", outFile, e);
-            }
-        }
-        
-        try {
-            initComparator();  
-            
-            initReporter();  
-            reporter.setTitle(title); 
-            reporter.setComparator(comparator);
-            reporter.setReaders(list);
 
-            List<int[]> testCounts = new ArrayList<int[]>();
-            MultiMap<String,TestResult> table = new MultiMap<String,TestResult>();
-            for (DiffReader r: list) {
-                int index = table.add(r.getFile().getPath());
-                int[] counts = new int[Status.NUM_STATES];
-                for (TestResult tr: r) {
-                    table.add(index, tr.getTestName(), tr);
-                    counts[tr.getStatus().getType()]++;
-                }
-                testCounts.add(counts);
-            }
-
-            reporter.setTestCounts(testCounts);
-            
-            try {
-                reporter.write(table);
-            } catch (IOException e) {
-                throw new Fault(i18n, "main.ioError", e);
-            }
+        Diff d;
+        if (superMode)
+            d = new SuperDiff(fileArgs.get(0));
+        else
+            d = new StandardDiff(fileArgs);
 
-            return (reporter.diffs == 0);
-        } finally {
-            if (out != prevOut) {
-//                try {
-                    out.close();
-//                } catch (IOException e) {
-//                    throw new Fault(i18n, "main.ioError", e);
-//                }
-                out = prevOut;
-            }
-        }
-    }
-    
-    private void initFormat() {
-        if (format == null && outFile != null) {
-            String name = outFile.getName();
-            int dot = name.lastIndexOf(".");
-            if (dot != -1) 
-                format = name.substring(dot + 1).toLowerCase();
-        }
+        d.includeReason = includeReason;
+        d.format = format;
+        d.title = title;
+
+        return d.report(outFile);
     }
-    
-    private void initReporter() throws Fault {
-        if (reporter == null) {
-            try {
-                initFormat();
-                if (format != null && format.equals("html"))
-                    reporter = new HTMLReporter(out);
-                if (reporter == null)
-                    reporter = new SimpleReporter(out); 
-            } catch (IOException e) {
-                throw new Fault(i18n, "main.cantOpenReport", e);
-            }
-        }
-    }
-    
-    private void initComparator() {
-        if (comparator == null)
-            comparator = new StatusComparator(includeReason); 
-    }
-    
-    private DiffReader open(File f) throws Fault {
-        if (!f.exists())
-            throw new Fault(i18n, "main.cantFindFile", f);
-        
-        try {
-            if (WorkDirectoryReader.accepts(f)) 
-                return new WorkDirectoryReader(f);
-            
-            if (ReportReader.accepts(f)) 
-                return new ReportReader(f);
-            
-            throw new Fault(i18n, "main.unrecognizedFile", f);
-            
-        } catch (TestSuite.Fault e) {
-            throw new Fault(i18n, "main.cantOpenFile", f, e);
-        } catch (WorkDirectory.Fault e) {
-            throw new Fault(i18n, "main.cantOpenFile", f, e);
-        } catch (IOException e) {
-            throw new Fault(i18n, "main.cantOpenFile", f, e);
-        }
-        
-    }
-    
+
     private static void exit(int exitCode) {
         System.exit(exitCode);
     }
-    
+
     private PrintWriter out;
     private PrintWriter err;
-    private Comparator<TestResult> comparator;
-    private Reporter reporter;
-    
+
     private boolean includeReason;
     private String format;
     private String title;
     private File outFile;
     private List<File> fileArgs = new ArrayList<File>();
+    private boolean superMode;
     private Help help;
-    
+
     private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(Main.class);
 }
--- a/test/jtreg/com/sun/javatest/diff/MultiMap.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/test/jtreg/com/sun/javatest/diff/MultiMap.java	Mon Nov 17 15:26:51 2008 +0000
@@ -38,26 +38,26 @@
  */
 public class MultiMap<K,V> implements Map<K, MultiMap.Entry<V>> {
     public static class Entry<V> {
-        
+
         private Entry(MultiMap<?,?> t) {
             table = t;
         }
-        
+
         V get(int index) {
             return (index < list.size() ? list.get(index) : null);
         }
-        
+
         int getSize() {
             return table.getColumns();
         }
-        
+
         void put(int index, V value) {
             if (index >= table.getColumns())
                 throw new IndexOutOfBoundsException();
-            
+
             if (list == null)
                 list = new ArrayList<V>(index);
-            
+
             if (index < list.size())
                 list.set(index, value);
             else {
@@ -66,7 +66,7 @@
                 list.add(value);
             }
         }
-        
+
         boolean allEqual(Comparator<V> c) {
             if (list.size() == 0)
                 return true;
@@ -79,96 +79,95 @@
             }
             return true;
         }
-        
+
         private List<V> list;
         private MultiMap<?,?> table;
     }
-    
-    /** Creates a new instance of DiffTable */
+
+    /** Creates a new instance of MultiMap */
     public MultiMap() {
         names = new ArrayList<String>();
         map = new TreeMap<K, Entry<V>>();
     }
-    
+
     int getColumns() {
         return names.size();
     }
-    
+
     String getColumnName(int index) {
         return names.get(index);
     }
-    
-    int add(String name) {
+
+    int addColumn(String name) {
         names.add(name);
         return names.size() - 1;
     }
-    
-    void add(int index, K k, V v) {
+
+    void addColumn(String name, Map<K, V> map) {
+        addColumn(name, map.entrySet());
+    }
+
+    void addColumn(String name, Iterable<Map.Entry<K,V>> iter) {
+        int index = addColumn(name);
+        for (Map.Entry<K,V> e: iter)
+            addRow(index, e.getKey(), e.getValue());
+    }
+
+    void addRow(int index, K k, V v) {
         Entry<V> de = get(k);
         if (de == null)
             put(k, de = new Entry<V>(this));
         de.put(index, v);
-        
     }
-    
-    void add(String name, Map<K, V> map) {
-        add(name, map.entrySet());
-    }
-    
-    void add(String name, Iterable<Map.Entry<K,V>> iter) {
-        int index = add(name);
-        for (Map.Entry<K,V> e: iter)
-            add(index, e.getKey(), e.getValue());
-    }
-    
+
     public int size() {
         return map.size();
     }
-    
+
     public Entry<V> get(Object path) {
         return map.get(path);
     }
-    
+
     public boolean isEmpty() {
         return map.isEmpty();
     }
-    
+
     public boolean containsKey(Object key) {
         return map.containsKey(key);
     }
-    
+
     public boolean containsValue(Object value) {
         return map.containsValue(value);
     }
-    
+
     public Entry<V> put(K key, Entry<V> value) {
         return map.put(key, value);
     }
-    
+
     public Entry<V> remove(Object key) {
         return map.remove(key);
     }
-    
+
     public void putAll(Map<? extends K, ? extends Entry<V>> t) {
         map.putAll(t);
     }
-    
+
     public void clear() {
         map.clear();
     }
-    
+
     public Set<Map.Entry<K, Entry<V>>> entrySet() {
         return map.entrySet();
     }
-    
+
     public Set<K> keySet() {
         return map.keySet();
     }
-    
+
     public Collection<Entry<V>> values() {
         return map.values();
     }
-    
+
     private List<String> names;
     private TreeMap<K, Entry<V>> map;
 }
--- a/test/jtreg/com/sun/javatest/diff/ReportReader.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/test/jtreg/com/sun/javatest/diff/ReportReader.java	Mon Nov 17 15:26:51 2008 +0000
@@ -39,28 +39,28 @@
 import java.util.List;
 
 /**
- * Read a set of test results from summary.txt, possibly located in a 
+ * Read a set of test results from summary.txt, possibly located in a
  * report directory.
  */
 public class ReportReader implements DiffReader {
-    private static final String SUMMARY_TXT = "summary.txt"; 
-    
+    private static final String SUMMARY_TXT = "summary.txt";
+
     public static boolean accepts(File f) {
         if (!f.exists())
             return false;
-        
+
         if (f.isFile() && f.getName().equals(SUMMARY_TXT))
             return true;
-        
+
         if (f.isDirectory() && new File(f, SUMMARY_TXT).exists())
             return true;
-        
+
         if (f.isDirectory() && new File(new File(f, "text"), SUMMARY_TXT).exists())
             return true;
-        
+
         return false;
     }
-    
+
     /** Creates a new instance of SummaryReader */
     public ReportReader(File file) {
         this.file = file;
@@ -69,11 +69,7 @@
     public File getFile() {
         return file;
     }
-    
-    public File getWorkDirectory() {
-        return null;
-    }
-    
+
     public String getFileType() {
         if (file != null && file.isDirectory())
             return i18n.getString("report.reportDir");
@@ -81,10 +77,14 @@
             return i18n.getString("report.reportFile");
     }
 
+    public File getWorkDirectory() {
+        return null;
+    }
+
     public Iterator<TestResult> iterator() {
         return readSummary().iterator();
     }
-    
+
     private List<TestResult> readSummary() {
         List<TestResult> list = new ArrayList<TestResult>();
         File root = getRoot();
@@ -97,7 +97,7 @@
             f = new File(new File(file, "text"), SUMMARY_TXT);
         else
             throw new IllegalStateException();
-        
+
         try {
             BufferedReader in = new BufferedReader(new FileReader(f));
             String line;
@@ -113,14 +113,14 @@
         }
         return list;
     }
-    
+
     private File getRoot() {
         return UNKNOWN;
     }
-    
+
     private static File UNKNOWN = new File("unknown");
-    
+
     private File file;
-    
+
     private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(WorkDirectoryReader.class);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jtreg/com/sun/javatest/diff/StandardDiff.java	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.javatest.diff;
+
+import java.io.File;
+import java.util.List;
+
+public class StandardDiff extends Diff {
+    StandardDiff(List<File> files) {
+        this.files = files;
+    }
+
+    @Override
+    public boolean report(File outFile) throws Fault, InterruptedException {
+        return diff(files, outFile);
+    }
+
+    List<File> files;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jtreg/com/sun/javatest/diff/SuperDiff.java	Mon Nov 17 15:26:51 2008 +0000
@@ -0,0 +1,342 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.javatest.diff;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Writer;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import com.sun.javatest.util.I18NResourceBundle;
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import static com.sun.javatest.util.HTMLWriter.*;
+
+class SuperDiff extends Diff {
+    SuperDiff(File dir) {
+        table = new SuperTable(dir, resultPath);
+    }
+
+    @Override
+    public boolean report(File outDir) throws Fault, InterruptedException {
+        baseTitle = title;
+        boolean ok = true;
+        for (YearDay yearDay: table.getRecentKeys(historySize))
+            ok &= diffPlatforms(yearDay, outDir);
+        for (String platform : table.platforms) {
+            ok &= diffHistory(platform, outDir);
+        }
+        writeIndex(outDir, baseTitle);
+        return ok;
+    }
+
+    protected boolean diff(List<File> files, File outFile, String title) throws Fault, InterruptedException {
+        this.title = title;
+        reporter = null;
+        return diff(files, outFile);
+    }
+
+    @Override
+    protected void initReporter() throws Fault {
+        try {
+             reporter = new SuperReporter(out);
+        } catch (IOException e) {
+            throw new Fault(i18n, "main.cantOpenReport", e);
+        }
+    }
+
+    private boolean diffPlatforms(YearDay yearDay, File outDir) throws Fault, InterruptedException {
+        Map<String, File> pMap = table.get(yearDay);
+        List<File> pDirs = new ArrayList<File>();
+        for (String platform : table.platforms) {
+            File dir = pMap.get(platform);
+            if (dir != null) {
+                pDirs.add(dir);
+            }
+        }
+        File file = new File(outDir, yearDay.year + "_" + yearDay.dayOfYear + ".html");
+        platformIndex.put(yearDay.toDateString(monthDayFormat), file);
+        String prefix = baseTitle == null ? "" : baseTitle + ": ";
+        return diff(pDirs, file, prefix + yearDay.toDateString(mediumDateFormat)); // I18N a better title?
+    }
+
+    private boolean diffHistory(String platform, File outDir) throws Fault, InterruptedException {
+        List<File> pDirs = new ArrayList<File>();
+        for (YearDay yearDay: table.getRecentKeys(historySize, platform)) {
+            pDirs.add(table.get(yearDay).get(platform));
+        }
+        File file = new File(outDir, platform + ".html");
+        historyIndex.put(platform, file);
+        String prefix = baseTitle == null ? "" : baseTitle + ": ";
+        return diff(pDirs, file, prefix + platform);// I18N a better title?
+    }
+
+    private void writeIndex(File outDir, String title) throws Fault {
+        PrintWriter out;
+        try {
+            out = new PrintWriter(new BufferedWriter(new FileWriter(new File(outDir, "index.html"))));
+        } catch (IOException e) {
+            throw new Fault(i18n, "main.cantOpenReport", e);
+        }
+
+        try {
+            SuperReporter r = new SuperReporter(out);
+            r.writeMainIndex(title);
+        } catch (IOException e) {
+            throw new Fault(i18n, "main.ioError", e);
+        } finally {
+            out.close();
+        }
+    }
+
+    protected String resultPath = System.getProperty("jtdiff.super.testResults", "JTreport/text/summary.txt");
+    protected int historySize = Integer.getInteger("jtdiff.super.history", 21);
+
+    private SuperTable table;
+    private String baseTitle;
+    private Map<String,File> historyIndex = new LinkedHashMap<String,File>();
+    private Map<String,File> platformIndex = new LinkedHashMap<String,File>();
+
+    private static DateFormat monthDayFormat = new SimpleDateFormat("MMM d");
+    private static DateFormat mediumDateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM);
+    private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(Main.class);
+
+    static class Info {
+        Info(String platform, Date date) {
+            this.platform = platform;
+            this.date = date;
+        }
+
+        final String platform;
+        final Date date;
+    }
+
+    class SuperReporter extends HTMLReporter {
+        SuperReporter(Writer out) throws IOException {
+            super(out);
+        }
+
+        protected void writeIndexTableInfoHeadings() throws IOException {
+            out.startTag(TH);
+            out.writeI18N("super.th.platform");
+            out.endTag(TH);
+            out.startTag(TH);
+            out.writeI18N("super.th.date");
+            out.endTag(TH);
+        }
+
+        protected void writeIndexTableInfoValues(String path) throws IOException {
+            Info info = table.getInfo(path);
+            out.startTag(TD);
+            if (info != null)
+                out.write(info.platform);
+            out.endTag(TD);
+            out.startTag(TD);
+            if (info != null)
+                out.write(monthDayFormat.format(info.date));
+            out.endTag(TH);
+        }
+
+        void writeMainIndex(String title) throws IOException {
+            startReport(title);
+
+            out.startTag(H1);
+            out.write(baseTitle);
+            out.endTag(H1);
+
+            writeMainIndexList(i18n.getString("super.platforms"), platformIndex);
+            writeMainIndexList(i18n.getString("super.history"), historyIndex);
+
+            endReport();
+        }
+
+        void writeMainIndexList(String head, Map<String,File> map) throws IOException {
+            out.startTag(H2);
+            out.write(head);
+            out.endTag(H2);
+            out.startTag(P);
+            String comma = "";
+            for (Map.Entry<String,File> e: map.entrySet()) {
+                out.write(comma);
+                out.startTag(A);
+                out.writeAttr(HREF, e.getValue().getName());
+                String nbsp = "";
+                for (String s: e.getKey().split(" ")) {
+                    out.writeEntity(nbsp);
+                    out.write(s);
+                    nbsp = "&nbsp;";
+                }
+                out.endTag(A);
+                comma = ", ";
+            }
+        }
+    }
+
+    static class SuperTable extends TreeMap<YearDay, Map<String, File>> {
+
+        static final long serialVersionUID = 5933594140534747584L;
+
+        SuperTable(File inDir, String resultPath) {
+            super();
+            for (File pDir : inDir.listFiles()) {
+                if (!pDir.isDirectory()) {
+                    continue;
+                }
+                for (File yDir : pDir.listFiles()) {
+                    if (!yDir.isDirectory()) {
+                        continue;
+                    }
+                    for (File dDir : yDir.listFiles()) {
+                        if (!dDir.isDirectory()) {
+                            continue;
+                        }
+                        File resultDir = new File(dDir, resultPath);
+                        if (resultDir.exists()) {
+                            add(pDir.getName(), yDir.getName(), dDir.getName(), resultDir);
+                        }
+                    }
+                }
+            }
+        }
+
+        private void add(String platform, String year, String day, File dir) {
+            platforms.add(platform);
+            YearDay yd = new YearDay(year, day);
+            Map<String, File> pMap = get(yd);
+            if (pMap == null) {
+                pMap = new HashMap<String, File>();
+                put(yd, pMap);
+            }
+            pMap.put(platform, dir);
+
+            Date date;
+            try {
+                Calendar c = Calendar.getInstance();
+                c.clear();
+                c.set(Calendar.YEAR, Integer.parseInt(year));
+                c.set(Calendar.DAY_OF_YEAR, Integer.parseInt(day));
+                date = c.getTime();
+            } catch (NumberFormatException e) {
+                date = null;
+            }
+            infoTable.put(dir.getPath(), new Info(platform, date));
+        }
+
+        List<YearDay> getRecentKeys(int n) {
+            return getRecentKeys(n, null);
+        }
+
+        List<YearDay> getRecentKeys(int n, String platform) {
+            LinkedList<YearDay> results = new LinkedList<YearDay>();
+            List<YearDay> keys = new ArrayList<YearDay>(keySet());
+            for (ListIterator<YearDay> iter = keys.listIterator(keys.size());
+                    iter.hasPrevious() && results.size() < n; ) {
+                YearDay key = iter.previous();
+                if (platform == null || get(key).get(platform) != null)
+                    results.addFirst(key);
+            }
+            return results;
+        }
+
+        Info getInfo(String path) {
+            return infoTable.get(path);
+        }
+
+        final Set<String> platforms = new TreeSet<String>();
+        final Map<String,Info> infoTable = new HashMap<String, Info>();
+    }
+
+    static class YearDay implements Comparable<YearDay> {
+        YearDay(String year, String dayOfYear) {
+            year.getClass();
+            dayOfYear.getClass();
+            this.year = year;
+            this.dayOfYear = dayOfYear;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof YearDay))
+                return false;
+            YearDay ydo = (YearDay) o;
+            return year.equals(ydo.year) && dayOfYear.equals(ydo.dayOfYear);
+        }
+
+        @Override
+        public int hashCode() {
+            return year.hashCode() * 37 + dayOfYear.hashCode();
+        }
+
+        //@Override
+        public int compareTo(YearDay o) {
+            int c = compare(year, o.year);
+            return (c == 0 ? compare(dayOfYear, o.dayOfYear) : c);
+        }
+
+        public String toString() {
+            return year + ":" + dayOfYear;
+        }
+
+        public Date asDate() {
+            try {
+                Calendar c = Calendar.getInstance();
+                c.clear();
+                c.set(Calendar.YEAR, Integer.parseInt(year));
+                c.set(Calendar.DAY_OF_YEAR, Integer.parseInt(dayOfYear));
+                return c.getTime();
+            } catch (NumberFormatException e) {
+                return null;
+            }
+        }
+
+        public String toDateString(DateFormat f) {
+            Date d = asDate();
+            return (d == null ? toString() : f.format(d));
+        }
+
+        private int compare(String left, String right) {
+            return left.compareTo(right);
+        }
+
+        final String year;
+        final String dayOfYear;
+    }
+
+}
--- a/test/jtreg/com/sun/javatest/diff/WorkDirectoryReader.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/test/jtreg/com/sun/javatest/diff/WorkDirectoryReader.java	Mon Nov 17 15:26:51 2008 +0000
@@ -48,12 +48,12 @@
     public static boolean accepts(File f) {
         return WorkDirectory.isWorkDirectory(f);
     }
-    
+
     /** Creates a new instance of WorkDirectoryReader */
-    public WorkDirectoryReader(File file) 
+    public WorkDirectoryReader(File file)
             throws FileNotFoundException, WorkDirectory.Fault, TestSuite.Fault {
         this.file = file;
-        
+
         // Because regtest testsuites don't contain testsuite.jtt
         // files, we can't use the standard WorkDirectory.open call.
         File tsp = getTestSuitePath(file);
@@ -63,31 +63,31 @@
         } else
             wd = WorkDirectory.open(file);
     }
-    
+
+    public File getFile() {
+        return file;
+    }
+
     public String getFileType() {
         return i18n.getString("wd.name");
     }
-    
-    public File getFile() {
-        return file;
-    }
-    
+
     public File getWorkDirectory() {
         return wd.getRoot();
     }
-    
+
     @SuppressWarnings("unchecked")
     public Iterator<TestResult> iterator() {
         TestResultTable trt = wd.getTestResultTable();
         trt.waitUntilReady();
         return trt.getIterator();
     }
-    
+
     private static File getTestSuitePath(File workDir) {
         File f = new File(new File(workDir, "jtData"), "testsuite");
-        if (!f.exists()) 
+        if (!f.exists())
             return null;
-          
+
         InputStream in = null;
         try {
             in = new BufferedInputStream(new FileInputStream(f));
@@ -105,9 +105,9 @@
             return null;
         }
     }
-    
+
     private File file;;
     private WorkDirectory wd;
-    
+
     private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(WorkDirectoryReader.class);
 }
--- a/test/jtreg/com/sun/javatest/diff/i18n.properties	Mon Nov 17 12:41:07 2008 +0000
+++ b/test/jtreg/com/sun/javatest/diff/i18n.properties	Mon Nov 17 15:26:51 2008 +0000
@@ -23,6 +23,10 @@
 # have any questions.
 #
 
+diff.cantOpenFile=Cannot open file {0}: {1}
+diff.cantOpenReport=Cannot open report: {0}
+diff.ioError=Error: {0}
+
 help.cantFindReleaseNotes=
 help.onlineHelp.pleaseWait=Loading online help ...
 help.releaseNotes=
@@ -42,8 +46,21 @@
 
 help.compare.name=Compare Options      
 help.compare.desc=
-help.compare.reason.desc=Include the reason string in the comparison, as well as \
+help.compare.r.desc=Include the reason string in the comparison, as well as \
     the type (i.e. Passed, Failed, etc.)
+help.compare.s.desc=Perform a "super-diff" looking for result sets within \
+    a directory hierarchy. The hierarchy must be arranged as \
+    follows: PATH/PLATFORM/YEAR/DAY_OF_YEAR/TEST_RESULTS, where PATH is \
+    given by the single directory argument, PLATFORM is the name of the \
+    platform on which the tests were run, YEAR and DAY_OF_YEAR are numbers \
+    identifying when the tests were run, and TESTSUITE_RESULTS is a fixed string \
+    identifying when to find the result set in the hierarchy. The default \
+    is "JTreport/text/summary.txt", but it can be set to a different value by \
+    setting the system property "jtdiff.super.testResults". It may identify any \
+    source of results acceptable to a standard invocation of jtdiff. \
+    Set system property jtdiff.html.compact=true for a more output format, with \
+    symbols replacing the words "pass" (check mark), "fail" (cross), "error" \
+    (cross in a circle), and "not run" (horizontal bar).
 
 help.doc.name=Help Options
 help.doc.desc=Options for additional help and information
@@ -76,6 +93,10 @@
 html.fail=fail
 html.notRun=not run
 html.pass=pass
+html.error.compact=&otimes;
+html.fail.compact=&times;
+html.notRun.compact=&mdash;
+html.pass.compact=&radic;
 
 html.head.differences=Differences
 html.head.notitle=jtdiff results
@@ -94,6 +115,8 @@
 html.th.type=Type
 
 main.badArgs=Error: {0}
+main.bad.super.dir=Bad directory argument for "super" mode
+main.bad.super.format=Cannot specify format in "super" mode
 main.cantFindFile=Cannot find file: {0}
 main.cantOpenFile=Cannot open file {0}: {1}
 main.cantOpenReport=Cannot open report: {0}
@@ -123,3 +146,8 @@
     {6,choice,0#|0<not run: {6,number}}
 
 wd.name=Work Directory
+
+super.history=Comparison of recent results by platform
+super.platforms=Comparison across platforms by date 
+super.th.date=Date
+super.th.platform=Platform
--- a/test/jtreg/com/sun/javatest/regtest/Main.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/test/jtreg/com/sun/javatest/regtest/Main.java	Mon Nov 17 15:26:51 2008 +0000
@@ -83,7 +83,7 @@
  * JavaTest entry point to be used to access regression extensions.
  */
 public class Main {
-    
+
     /**
      * Exception to report a problem while executing in Main.
      */
@@ -93,14 +93,14 @@
             super(i18n.getString(s, args));
         }
     }
-    
+
     public static final String MAIN = "main";           // main set of options
     public static final String SELECT = "select";       // test selection options
     public static final String JDK = "jdk";             // specify JDK to use
     public static final String MODE = "mode";           // sameVM or otherVM
     public static final String VERBOSE = "verbose";     // verbose controls
     public static final String DOC = "doc";             // help or doc info
-    
+
     Option[] options = {
         new Option(OPT, VERBOSE, "verbose", "v", "verbose") {
             @Override
@@ -122,49 +122,49 @@
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(NONE, VERBOSE, "verbose", "v1") {
             public void process(String opt, String arg) {
                 verbose = Verbose.SUMMARY;
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(NONE, VERBOSE, "verbose", "va") {
             public void process(String opt, String arg) {
                 verbose = Verbose.ALL;
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(NONE, VERBOSE, "verbose", "vp") {
             public void process(String opt, String arg) {
                 verbose = Verbose.PASS;
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(NONE, VERBOSE, "verbose", "vf") {
             public void process(String opt, String arg) {
                 verbose = Verbose.FAIL;
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(NONE, VERBOSE, "verbose", "ve") {
             public void process(String opt, String arg) {
                 verbose = Verbose.ERROR;
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(NONE, VERBOSE, "verbose", "vt") {
             public void process(String opt, String arg) {
                 verbose = Verbose.TIME;
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(NONE, DOC, "", "t", "tagspec") {
             public void process(String opt, String arg) {
                 if (help == null)
@@ -172,7 +172,7 @@
                 help.setTagSpec(true);
             }
         },
-        
+
         new Option(NONE, DOC, "", "n", "relnote") {
             public void process(String opt, String arg) {
                 if (help == null)
@@ -180,15 +180,15 @@
                 help.setReleaseNotes(true);
             }
         },
-        
+
         new Option(OLD, MAIN, "", "w", "workDir") {
             public void process(String opt, String arg) {
-                
+
                 workDirArg = new File(arg);
                 childArgs.add("-w:" + workDirArg.getAbsolutePath());
             }
         },
-        
+
         new Option(OPT, MAIN, "", "retain") {
             @Override
             public String[] getChoices() {
@@ -204,34 +204,40 @@
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(OLD, MAIN, "", "r", "reportDir") {
             public void process(String opt, String arg) {
                 reportDirArg = new File(arg);
                 childArgs.add("-r:" + reportDirArg.getAbsolutePath());
             }
         },
-        
-        new Option(NONE, MAIN, null, "ro", "reportOnly") {
+
+        new Option(NONE, MAIN, "ro-nr", "ro", "reportOnly") {
             public void process(String opt, String arg) {
                 reportOnlyFlag = true;
             }
         },
-        
+
+        new Option(NONE, MAIN, "ro-nr", "nr", "noreport") {
+            public void process(String opt, String arg) {
+                noReportFlag = true;
+            }
+        },
+
         new Option(STD, MAIN, "", "timeout", "timeoutFactor") {
             public void process(String opt, String arg) {
                 timeoutFactorArg = arg;
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(STD, MAIN, "", "dir") {
             public void process(String opt, String arg) {
                 baseDirArg = new File(arg);
                 childArgs.add("-dir:" + baseDirArg.getAbsolutePath());
             }
         },
-        
+
         new Option(STD, SELECT, "", "status") {
             @Override
             public String[] getChoices() {
@@ -242,29 +248,29 @@
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(STD, SELECT, "", "exclude", "Xexclude") {
             public void process(String opt, String arg) {
                 File f = new File(arg);
                 excludeListArgs.add(f);
-                childArgs.add(f.getAbsolutePath());
+                childArgs.add("-exclude:" + f.getAbsolutePath());
             }
         },
-        
+
         new Option(NONE, MAIN, null, "startHttpd") {
             public void process(String opt, String arg) {
                 httpdFlag = true;
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(OLD, MAIN, "", "o", "observer") {
             public void process(String opt, String arg) {
                 observerClassName = arg;
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(OLD, MAIN, "", "od", "observerDir", "op", "observerPath") {
             public void process(String opt, String arg) {
                 arg = arg.trim();
@@ -279,20 +285,20 @@
                 childArgs.add("-op:" + filesToAbsolutePath(pathToFiles(arg)));
             }
         },
-        
+
         new Option(NONE, MAIN, null, "g", "gui") {
             public void process(String opt, String arg) {
                 guiFlag = true;
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(NONE, MAIN, null, "c", "check") {
             public void process(String opt, String arg) {
                 checkFlag = true;
             }
         },
-        
+
         // deprecated
         new Option(NONE, MAIN, "ignore", "noignore") {
             public void process(String opt, String arg) {
@@ -300,7 +306,7 @@
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(STD, MAIN, "ignore", "ignore") {
             @Override
             public String[] getChoices() {
@@ -323,69 +329,69 @@
                 throw new BadArgs(i18n, "main.unknownIgnore", arg);
             }
         },
-        
+
         new Option(NONE, SELECT, "a-m", "a", "automatic", "automagic") {
             public void process(String opt, String arg) {
                 keywordsExprArg = combineKeywords(keywordsExprArg, AUTOMATIC);
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(NONE, SELECT, "a-m", "m", "manual") {
             public void process(String opt, String arg) {
                 keywordsExprArg = combineKeywords(keywordsExprArg, MANUAL);
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(NONE, SELECT, "shell-noshell", "shell") {
             public void process(String opt, String arg) {
                 keywordsExprArg = combineKeywords(keywordsExprArg, "shell");
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(NONE, SELECT, "shell-noshell", "noshell") {
             public void process(String opt, String arg) {
                 keywordsExprArg = combineKeywords(keywordsExprArg, "!shell");
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(STD, SELECT, null, "bug") {
             public void process(String opt, String arg) {
                 keywordsExprArg = combineKeywords(keywordsExprArg, "bug" + arg);
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(STD, SELECT, null, "k", "keywords") {
             public void process(String opt, String arg) {
                 keywordsExprArg = combineKeywords(keywordsExprArg, "(" + arg + ")");
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(NONE, MODE, "svm-ovm", "ovm", "othervm") {
             public void process(String opt, String arg) {
                 sameJVMFlag = false;
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(NONE, MODE, "svm-ovm", "s", "svm", "samevm") {
             public void process(String opt, String arg) {
                 sameJVMFlag = true;
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(OLD, JDK, "", "jdk", "testjdk") {
             public void process(String opt, String arg) {
                 jdk = new JDK(arg);
             }
         },
-        
+
         new Option(STD, JDK, "", "cpa", "classpathappend") {
             public void process(String opt, String arg) {
                 arg = arg.trim();
@@ -398,73 +404,73 @@
                 }
             }
         },
-        
+
         new Option(NONE, JDK, "jit-nojit", "jit") {
             public void process(String opt, String arg) {
                 jitFlag = true;
             }
         },
-        
+
         new Option(NONE, JDK, "jit-nojit", "nojit") {
             public void process(String opt, String arg) {
                 jitFlag = false;
             }
         },
-        
+
         new Option(WILDCARD, JDK, null, "Xrunjcov") {
             public void process(String opt, String arg) {
                 testVMOpts.add(opt);
             }
         },
-        
+
         new Option(NONE, JDK, null, "classic", "green", "native", "hotspot", "client", "server", "d32", "d64") {
             public void process(String opt, String arg) {
                 testVMOpts.add(opt);
             }
         },
-        
+
         new Option(OPT, JDK, null, "enableassertions", "ea", "disableassertions", "da") {
             public void process(String opt, String arg) {
                 testVMOpts.add(opt);
             }
         },
-        
+
         new Option(NONE, JDK, null, "enablesystemassertions", "esa", "disablesystemassertions", "dsa") {
             public void process(String opt, String arg) {
                 testVMOpts.add(opt);
             }
         },
-        
+
         new Option(WILDCARD, JDK, null, "XX", "Xms", "Xmx") {
             public void process(String opt, String arg) {
                 testVMOpts.add(opt);
             }
         },
-        
+
         new Option(WILDCARD, JDK, null, "Xint", "Xmixed", "Xcomp") {
             public void process(String opt, String arg) {
                 testVMOpts.add(opt);
             }
         },
-        
+
         new Option(STD, JDK, null, "Xbootclasspath") {
             public void process(String opt, String arg) {
                 testVMOpts.add("-Xbootclasspath:" + filesToAbsolutePath(pathToFiles(arg)));
             }
         },
-        
+
         new Option(STD, JDK, null, "Xbootclasspath/a") {
             public void process(String opt, String arg) {
                 testVMOpts.add("-Xbootclasspath/a:" + filesToAbsolutePath(pathToFiles(arg)));
             }
         },
-        
+
         new Option(STD, JDK, null, "Xbootclasspath/p") {
             public void process(String opt, String arg) {
                 testVMOpts.add("-Xbootclasspath/p:" + filesToAbsolutePath(pathToFiles(arg)));
             }
         },
-        
+
         new Option(WILDCARD, JDK, null, "X") {
             public void process(String opt, String arg) {
                 // This is a change in spec. Previously. -X was used to tunnel
@@ -473,20 +479,20 @@
                 testVMOpts.add(opt);
             }
         },
-        
+
         new Option(WILDCARD, JDK, null, "D") {
             public void process(String opt, String arg) {
                 testVMOpts.add(opt);
             }
         },
-        
+
         new Option(STD, JDK, null, "vmoption") {
             public void process(String opt, String arg) {
                 if (arg.length() > 0)
                     testVMOpts.add(arg);
             }
         },
-        
+
         new Option(STD, JDK, null, "vmoptions") {
             public void process(String opt, String arg) {
                 arg = arg.trim();
@@ -495,7 +501,7 @@
                 testVMOpts.addAll(Arrays.asList(arg.split("\\s+")));
             }
         },
-        
+
         new Option(OLD, JDK, null, "e") {
             public void process(String opt, String arg) {
                 arg = arg.trim();
@@ -504,25 +510,25 @@
                 envVarArgs.addAll(Arrays.asList(arg.split(",")));
             }
         },
-        
+
         new Option(STD, JDK, null, "agentlib") {
             public void process(String opt, String arg) {
                 testVMOpts.add(opt);
             }
         },
-        
+
         new Option(STD, JDK, null, "agentpath") {
             public void process(String opt, String arg) {
                 testVMOpts.add(opt);
             }
         },
-        
+
         new Option(STD, JDK, null, "javaagent") {
             public void process(String opt, String arg) {
                 testVMOpts.add(opt);
             }
         },
-        
+
         new Option(STD, JDK, null, "javacoption") {
             public void process(String opt, String arg) {
                 arg = arg.trim();
@@ -532,7 +538,7 @@
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(STD, JDK, null, "javacoptions") {
             public void process(String opt, String arg) {
                 arg = arg.trim();
@@ -542,7 +548,7 @@
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(STD, JDK, null, "javaoption") {
             public void process(String opt, String arg) {
                 arg = arg.trim();
@@ -552,7 +558,7 @@
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(STD, JDK, null, "javaoptions") {
             public void process(String opt, String arg) {
                 arg = arg.trim();
@@ -562,7 +568,7 @@
                 childArgs.add(opt);
             }
         },
-        
+
         new Option(REST, DOC, "help", "h", "help", "usage") {
             public void process(String opt, String arg) {
                 if (help == null)
@@ -570,7 +576,7 @@
                 help.setCommandLineHelpQuery(arg);
             }
         },
-        
+
         new Option(REST, DOC, "help", "onlineHelp") {
             public void process(String opt, String arg) {
                 if (help == null)
@@ -578,7 +584,7 @@
                 help.setOnlineHelpQuery(arg);
             }
         },
-        
+
         new Option(NONE, DOC, "help", "version") {
             public void process(String opt, String arg) {
                 if (help == null)
@@ -586,7 +592,7 @@
                 help.setVersionFlag(true);
             }
         },
-        
+
         new Option(FILE, MAIN, null) {
             public void process(String opt, String arg) {
                 File f= new File(arg);
@@ -610,7 +616,7 @@
     public static final int EXIT_FAULT = 4;
     /** Unexpected exception occurred. */
     public static final int EXIT_EXCEPTION = 5;
-    
+
     /**
      * Standard entry point. Only returns if GUI mode is initiated; otherwise, it calls System.exit
      * with an appropriate exit code.
@@ -628,7 +634,7 @@
                 out.flush();
                 err.flush();
             }
-            
+
             if (!(m.guiFlag && rc == EXIT_OK)) {
                 // take care not to exit if GUI might be around,
                 // and take care to ensure JavaTestSecurityManager will
@@ -654,21 +660,21 @@
             exit(EXIT_EXCEPTION);
         }
     } // main()
-    
+
     public Main() {
         this(new PrintWriter(System.out, true), new PrintWriter(System.err, true));
     }
-    
+
     public Main(PrintWriter out, PrintWriter err) {
         this.out = out;
         this.err = err;
-        
+
         // FIXME: work around bug 6466752
         File javatest_jar = findJar("javatest.jar", "lib/javatest.jar", com.sun.javatest.Harness.class);
         if (javatest_jar != null)
             System.setProperty("javatestClassDir", javatest_jar.getPath());
     }
-    
+
     /**
      * Decode command line args and perform the requested operations.
      * @param args An array of args, such as might be supplied on the command line.
@@ -681,7 +687,7 @@
         new OptionDecoder(options).decodeArgs(expandAtFiles(args));
         return run();
     }
-    
+
     private int run() throws BadArgs, Fault, Harness.Fault, InterruptedException {
         if (help != null) {
             guiFlag = help.show(out);
@@ -690,7 +696,7 @@
 
         if (sameJVMFlag && !testJavaOpts.isEmpty())
             throw new Fault(i18n, "main.cant.mix.samevm.java.options");
-        
+
         if (jdk == null) {
             String s = null;
             if (!sameJVMFlag)
@@ -706,23 +712,23 @@
                 f = f.getParentFile();
             jdk = new JDK(f);
         }
-        
+
         if (jitFlag == false) {
             if (sameJVMFlag)
                 testVMOpts.add("-Djava.compiler=");
             else
                 envVarArgs.add("JAVA_COMPILER=");
         }
-        
+
         if (classPathAppendArg.size() > 0) {
             // TODO: store this separately in RegressionParameters, instead of in envVars
             if (!sameJVMFlag)
                 envVarArgs.add("CPAPPEND=" + filesToAbsolutePath(classPathAppendArg));
         }
-        
+
         if (!jdk.exists())
             throw new Fault(i18n, "main.jdk.not.found", jdk);
-        
+
         File baseDir;
         if (baseDirArg == null) {
             baseDir = new File(System.getProperty("user.dir"));
@@ -731,9 +737,9 @@
                 throw new Fault(i18n, "main.cantFindFile", baseDirArg);
             baseDir = baseDirArg.getAbsoluteFile();
         }
-        
+
         List<File> absTestFileArgs = new ArrayList<File>();
-        
+
         for (File t: testFileArgs) {
             if (!t.isAbsolute())
                 t = new File(baseDir, t.getPath());
@@ -741,13 +747,13 @@
                 throw new Fault(i18n, "main.cantFindFile", t);
             absTestFileArgs.add(t);
         }
-        
+
         testFileArgs = absTestFileArgs;
-        
+
         String antFileList = System.getProperty(JAVATEST_ANT_FILE_LIST);
         if (antFileList != null)
             antFileArgs.addAll(readFileList(new File(antFileList)));
-        
+
         if (testSuiteArg == null) {
             File t;
             if (testFileArgs.size() > 0)
@@ -756,49 +762,57 @@
                 t = antFileArgs.iterator().next();
             else
                 throw new BadArgs(i18n, "main.noTestSuiteOrTests");
-            
+
             testSuiteArg = getTestSuite(t);
             if (testSuiteArg == null)
                 throw new Fault(i18n, "main.cantDetermineTestSuite", t);
         }
-        
+
         if (workDirArg == null) {
             workDirArg = new File("JTwork");
             childArgs.add(0, "-w:" + workDirArg.getAbsolutePath());
         }
-        
-        if (reportDirArg == null) {
+
+        if (reportDirArg == null && !noReportFlag) {
             reportDirArg = new File("JTreport");
             childArgs.add(0, "-r:" + reportDirArg.getAbsolutePath());
         }
-        
-        makeDir(reportDirArg);
+
+        if (!noReportFlag)
+            makeDir(reportDirArg);
+
         makeDir(workDirArg);
         makeDir(new File(workDirArg, "scratch"));
-        
+
         if (!isThisVMOK())
             return execChild();
-        
+
         RegressionParameters params = createParameters();
-        
+
         checkLockFiles(params.getWorkDirectory().getRoot(), "start");
-        
+
         Harness.setClassDir(ProductInfo.getJavaTestClassDir());
-        
+
         // Allow keywords to begin with a numeric
         Keywords.setAllowNumericKeywords(true);
-        
+
         // Before we install our own security manager (which will restrict access
         // to the system properties), take a copy of the system properties.
         TestEnvironment.addDefaultPropTable("(system properties)", System.getProperties());
-        
+
         // TODO: take SecurityManager into account for isThisVMOK
-        if (sameJVMFlag)
+        if (sameJVMFlag) {
             RegressionSecurityManager.install();
-        
+            SecurityManager sc = System.getSecurityManager();
+            if (sc instanceof RegressionSecurityManager) {
+                // experimental
+                ((RegressionSecurityManager) sc).setAllowSetIO(true);
+            }
+        }
+
         if (httpdFlag)
             startHttpServer();
-        
+
         if (guiFlag) {
             showTool(params);
             return EXIT_OK;
@@ -810,7 +824,7 @@
             }
         }
     }
-    
+
     /**
      * Process Win32-style command files for the specified command line
      * arguments and return the resulting arguments. A command file argument
@@ -839,7 +853,7 @@
         }
         return newArgs.toArray(new String[newArgs.size()]);
     }
-    
+
     private static void loadCmdFile(String name, List<String> args)
     throws Fault {
         Reader r;
@@ -871,7 +885,7 @@
             }
         }
     }
-    
+
     private static List<File> readFileList(File file)
     throws Fault {
         BufferedReader r;
@@ -898,7 +912,7 @@
             }
         }
     }
-    
+
     private static void writeFileList(File file, List<File> list) throws Fault {
         try {
             BufferedWriter out = new BufferedWriter(new FileWriter(file));
@@ -912,21 +926,21 @@
             throw new Fault(i18n, "main.cantWrite", file, e);
         }
     }
-    
+
     public int[] getTestStats() {
         return testStats;
     }
-    
+
     private boolean isThisVMOK() {
         if (reportOnlyFlag || checkFlag || !sameJVMFlag)
             return true;
-        
+
         // sameVM tests can use this VM if
         // - the current directory is the required scratch directory
         // - the current VM is the required test VM
         // - there are no outstanding VM options
         // - there is no classpath append
-        
+
         File scratchDir = canon(new File(workDirArg, "scratch"));
         File currDir = canon(new File(""));
         if (!currDir.equals(scratchDir)) {
@@ -934,7 +948,7 @@
                 System.err.println("dir mismatch: " + currDir + " " + scratchDir);
             return false;
         }
-        
+
         File currJDKHome = canon(new File(System.getProperty("java.home")));
         if (currJDKHome.getName().toLowerCase().equals("jre"))
             currJDKHome = currJDKHome.getParentFile();
@@ -943,53 +957,53 @@
                 System.err.println("jdk mismatch: " + currJDKHome + " " + jdk + " (" + jdk.getCanonicalFile() + ")");
             return false;
         }
-        
+
         if (System.getProperty("javatest.child") == null && !testVMOpts.isEmpty()) {
             if (debugChild)
                 System.err.println("need VM opts: " + testVMOpts);
             return false;
         }
-        
+
         if (classPathAppendArg.size() > 0) {
             if (debugChild)
                 System.err.println("need classPathAppend: " + classPathAppendArg);
             return false;
         }
-        
+
         return true;
     }
-    
+
     // TODO use @file for args?
     private int execChild() throws Fault {
         if (System.getProperty("javatest.child") != null)
             throw new AssertionError();
-        
+
         File javatest_jar = findJar("javatest.jar", "lib/javatest.jar", com.sun.javatest.Harness.class);
         if (javatest_jar == null)
             throw new Fault(i18n, "main.cantFind.javatest.jar");
-        
+
         File jtreg_jar = findJar("jtreg.jar", "lib/jtreg.jar", getClass());
         if (jtreg_jar == null)
             throw new Fault(i18n, "main.cantFind.jtreg.jar");
-        
+
         File childJDKHome = jdk.getAbsoluteFile();
         File childJava = new File(new File(childJDKHome, "bin"), "java");
         File childTools  = new File(new File(childJDKHome, "lib"), "tools.jar");
-        
+
         File scratchDir = canon(new File(workDirArg, "scratch"));
-        
+
         List<String> c = new ArrayList<String>();
         c.add(childJava.getPath());
-        
+
         c.add("-classpath");
         List<File> classpath = new ArrayList<File>();
         classpath.add(jtreg_jar);
         classpath.add(childTools);
         classpath.addAll(classPathAppendArg);
         c.add(filesToAbsolutePath(classpath));
-        
+
         c.addAll(testVMOpts);
-        
+
         // Tunnel Ant file args separately from command line tests, so that
         // they can be treated specially in the child VM:  invalid files
         // specified by the user on the command line give an error;
@@ -1003,39 +1017,39 @@
                 throw new Fault(i18n, "main.cantWriteTempFile", e);
             }
         }
-        
+
         for (Map.Entry<?,?> e: System.getProperties().entrySet()) {
             String name = (String) e.getKey();
             if (name.startsWith("javatest."))
                 c.add("-D" + name + "=" + e.getValue());
         }
-        
+
         c.add("-Djavatest.child=true");
-        
+
         c.add(Main.class.getName());
-        
+
         for (String o: testVMOpts)
             c.add("-vmoption:" + o);
-        
+
         if (baseDirArg == null)
             c.add("-dir:" + System.getProperty("user.dir"));
-        
+
         c.addAll(childArgs);
-        
+
         String[] cmd = c.toArray(new String[c.size()]);
         File execDir = scratchDir;
-        
+
         if (debugChild) {
             System.err.println("Starting JavaTest child");
             System.err.println("Dir " + execDir + "; Command " + c);
         }
-        
+
         Runtime r = Runtime.getRuntime();
         Process p = null;
-        
+
         try {
             try {
-                
+
                 // strictly speaking, we do not need to set the CLASSPATH for the child VM,
                 // but we do it to maximize the consistency between sameVM and otherVM env.
                 // See similar code in MainAction for otherVM tests.
@@ -1043,46 +1057,46 @@
                 // because it will not have (and cannot have) the test-specific values.
                 String cp = "CLASSPATH=" + javatest_jar + PATHSEP + jtreg_jar
                         + PATHSEP + jdk.getToolsJar();
-                
+
                 String[] env = getEnvVars();
                 String[] env_cp = new String[env.length + 1];
                 System.arraycopy(env, 0, env_cp, 0, env.length);
                 env_cp[env_cp.length - 1] = cp;
-                
+
                 p = r.exec(cmd, env_cp, execDir);
             } catch (IOException e) {
                 err.println("cannot start child VM");
                 return EXIT_FAULT;
             }
-            
+
             InputStream childOut = p.getInputStream(); // output stream from process
             StreamCopier childOutCopier = new StreamCopier(childOut, out);
             childOutCopier.start();
             InputStream childErr = p.getErrorStream();
             StreamCopier childErrCopier = new StreamCopier(childErr, err);
             childErrCopier.start();
-            
+
             OutputStream childIn = p.getOutputStream();  // input stream to process
             if (childIn != null)
                 childIn.close();
-            
+
             // wait for the stream copiers to complete
             childOutCopier.waitUntilDone();
             childErrCopier.waitUntilDone();
-            
+
             // wait for the process to complete;
             int exitCode = p.waitFor();
             p = null;
-            
+
             if (debugChild) {
                 System.err.println("JavaTest child process: rc=" + exitCode);
             }
-            
+
             childOut.close();
             childErr.close();
-            
+
             return exitCode;
-            
+
         } catch (IOException e) {
             // TODO handle exception
             return EXIT_EXCEPTION;
@@ -1094,7 +1108,7 @@
                 p.destroy();
         }
     }
-    
+
     /**
      * A thread to copy an input stream to an output stream
      */
@@ -1109,7 +1123,7 @@
             in = new BufferedReader(new InputStreamReader(from));
             out = to;
         }
-        
+
         /**
          * Set the thread going.
          */
@@ -1130,32 +1144,32 @@
                 notifyAll();
             }
         }
-        
+
         public synchronized boolean isDone() {
             return done;
         }
-        
+
         /**
          * Blocks until the copy is complete, or until the thread is interrupted
          */
         public synchronized void waitUntilDone() throws InterruptedException {
             boolean interrupted = false;
-            
+
             // poll interrupted flag, while waiting for copy to complete
             while (!(interrupted = Thread.interrupted()) && !done)
                 wait(1000);
-            
+
             if (interrupted)
                 throw new InterruptedException();
         }
-        
+
         private BufferedReader in;
         private PrintWriter out;
         private boolean done;
         private static int serial;
-        
+
     }
-    
+
     private File getTestSuite(File test) {
         File f = canon(test);
         if (f.isFile())
@@ -1168,7 +1182,7 @@
         // TODO try and default from work directory
         return null;
     }
-    
+
     private String getEnvVar(String name) {
         for (String arg: envVarArgs) {
             if (arg.startsWith(name + "="))
@@ -1176,7 +1190,7 @@
         }
         return null;
     }
-    
+
     private void makeDir(File dir) throws Fault {
         // FIXME: I18N
         if (dir.isDirectory())
@@ -1187,7 +1201,7 @@
             throw new Fault(i18n, "main.cantCreateDir", dir);
         }
     }
-    
+
     private static List<File> pathToFiles(String path) {
         List<File> files = new ArrayList<File>();
         for (String f: path.split(File.pathSeparator)) {
@@ -1196,7 +1210,7 @@
         }
         return files;
     }
-    
+
     private static String filesToAbsolutePath(List<File> files) {
         StringBuffer sb = new StringBuffer();
         for (File f: files) {
@@ -1206,7 +1220,7 @@
         }
         return sb.toString();
     }
-    
+
     private static String join(Iterator<?> iter, String sep) {
         StringBuilder sb = new StringBuilder();
         while (iter.hasNext()) {
@@ -1216,7 +1230,7 @@
         }
         return sb.toString();
     }
-    
+
     /**
      * Create a RegressionParameters object based on the values set up by decodeArgs.
      * @return a RegressionParameters object
@@ -1224,26 +1238,26 @@
     private RegressionParameters createParameters() throws BadArgs, Fault {
         File ts = testSuiteArg;
         File wd = workDirArg;
-        
+
         try {
             // create a canonTestFile suite and work dir.
             RegressionTestSuite testSuite = new RegressionTestSuite(ts);
             RegressionParameters rp = (RegressionParameters) (testSuite.createInterview());
-            
+
             WorkDirectory workDir;
             if (WorkDirectory.isWorkDirectory(wd))
                 workDir = WorkDirectory.open(wd, testSuite);
             else
                 workDir = WorkDirectory.convert(wd, testSuite);
             rp.setWorkDirectory(workDir);
-            
+
             rp.setRetainArgs(retainArgs);
-            
+
             // set up the tests mode, and if specified tests are used, pass in the canonTestFile list.
             // ensure the tests parameters are root-relative
             File root = testSuite.getRoot();
             List<String> tests = new ArrayList<String>();
-            
+
             if (testFileArgs != null) {
                 // In the command line, the canonTestFile args are filenames, probably absolute,
                 // and possibly with non-canonical file separators (e.g. / on Windows).
@@ -1261,7 +1275,7 @@
                     }
                 }
             }
-            
+
             // no need to scan ant tests if all test suite selected (i.e. tests == null)
             if (tests != null && antFileArgs != null && antFileArgs.size() > 0) {
                 TestResultTable trt = workDir.getTestResultTable();
@@ -1279,10 +1293,10 @@
                     }
                 }
             }
-            
+
             if (tests != null && tests.size() > 0)
                 rp.setTests(tests);
-            
+
             if (keywordsExprArg != null)
                 rp.setKeywordsExpr(keywordsExprArg);
             rp.setExcludeLists(excludeListArgs.toArray(new File[excludeListArgs.size()]));
@@ -1296,7 +1310,7 @@
                 b[Status.NOT_RUN] = (priorStatusValuesArg.indexOf("notr") != -1);
                 rp.setPriorStatusValues(b);
             }
-            
+
             if (concurrencyArg != null) {
                 try {
                     rp.setConcurrency(Integer.parseInt(concurrencyArg));
@@ -1304,7 +1318,7 @@
                     throw new BadArgs(i18n, "main.badConcurrency");
                 }
             }
-            
+
             if (timeoutFactorArg != null) {
                 try {
                     rp.setTimeoutFactor(Integer.parseInt(timeoutFactorArg));
@@ -1312,10 +1326,10 @@
                     throw new BadArgs(i18n, "main.badTimeoutFactor");
                 }
             }
-            
+
             if (!rp.isValid())
                 throw new Fault(i18n, "main.badParams", rp.getErrorMessage());
-            
+
             for (String o: testVMOpts) {
                 if (o.startsWith("-Xrunjcov")) {
                     if (!testVMOpts.contains("-XX:+EnableJVMPIInstructionStartEvent"))
@@ -1323,23 +1337,23 @@
                     break;
                 }
             }
-            
+
             if (testVMOpts.size() > 0)
                 rp.setTestVMOptions(testVMOpts);
-            
+
             if (testCompilerOpts.size() > 0)
                 rp.setTestCompilerOptions(testCompilerOpts);
-            
+
             if (testJavaOpts.size() > 0)
                 rp.setTestJavaOptions(testJavaOpts);
-            
+
             rp.setCheck(checkFlag);
             rp.setSameJVM(sameJVMFlag);
             rp.setEnvVars(getEnvVars());
             rp.setJDK(jdk);
             if (ignoreKind != null)
                 rp.setIgnoreKind(ignoreKind);
-            
+
             return rp;
         } catch (TestSuite.Fault f) {
             f.printStackTrace();
@@ -1359,7 +1373,7 @@
             return file.getAbsoluteFile();
         }
     }
-    
+
     private String getRelativePath(File base, File f) {
         StringBuilder sb = new StringBuilder();
         for ( ; f != null; f = f.getParentFile()) {
@@ -1371,18 +1385,18 @@
         }
         return null;
     }
-    
+
     /**
      * Initialize the harness.  If we are in verbose mode, add our own observer.
      */
     private Harness createHarness() throws Fault {
-        
+
         // Set backup parameters; in time this might become more versatile.
         BackupPolicy backupPolicy = createBackupPolicy();
-        
+
         Harness h = new Harness();
         h.setBackupPolicy(backupPolicy);
-        
+
         if (observerClassName != null) {
             try {
                 Class observerClass;
@@ -1413,16 +1427,16 @@
                 throw new Fault(i18n, "main.obsvrFault", e);
             }
         }
-        
+
         // add our own observer for verbose
         if (verbose != null) {
             Harness.Observer observer = new RegressionObserver(verbose, out, err);
             h.addObserver(observer);
         }
-        
+
         return h;
     } // createHarness()
-    
+
     /**
      * Run the harness in batch mode, using the specified parameters.
      */
@@ -1430,7 +1444,7 @@
     throws Fault, Harness.Fault, InterruptedException {
         try {
             boolean ok;
-            
+
             if (reportOnlyFlag) {
                 testStats = new int[Status.NUM_STATES];
                 for (Iterator iter = getResultsIterator(params); iter.hasNext(); ) {
@@ -1443,15 +1457,27 @@
                 harness.addObserver(new BatchObserver());
                 ok = harness.batch(params);
             }
-            
+
             showResultStats(testStats);
-            
-            boolean reportRequired = !Boolean.getBoolean("javatest.noReportRequired");
+
+            boolean reportRequired =
+                    !noReportFlag && !Boolean.getBoolean("javatest.noReportRequired");
+            List<String> reportKinds =
+                    Arrays.asList(System.getProperty("javatest.report.kinds", "html text").split("[ ,]+"));
             if (reportRequired) {
                 try {
                     Report r = new Report();
                     Report.Settings s = new Report.Settings(params);
-                    s.setHtmlMainReport(true, true);
+                    if (reportKinds.contains("html")) {
+                        s.setEnableHtmlReport(true);
+                        s.setHtmlMainReport(true, true);
+                    }
+                    if (reportKinds.contains("text")) {
+                        s.setEnablePlainReport(true);
+                    }
+                    if (reportKinds.contains("xml")) {
+                        s.setEnableXmlReport(true);
+                    }
                     s.setFilter(new CompositeFilter(params.getFilters()));
                     r.writeReport(s, reportDirArg);
                     File report = new File(reportDirArg, "report.html"); // std through version 3.*
@@ -1463,15 +1489,15 @@
                     out.println("Error while writing report: " + e);
                 }
             }
-            
+
             if (!reportOnlyFlag)
                 out.println("Results written to " + params.getWorkDirectory().getPath());
-            
+
             // report a brief msg to System.err as well, in case System.out has
             // been redirected.
             if (!ok)
                 err.println(i18n.getString("main.testsFailed"));
-            
+
             return (testStats[Status.ERROR] > 0 ? EXIT_TEST_ERROR :
                 testStats[Status.FAILED] > 0 ? EXIT_TEST_FAILED :
                     EXIT_OK);
@@ -1480,11 +1506,11 @@
             err.flush();
         }
     }
-    
+
     private Iterator getResultsIterator(InterviewParameters params) {
         TestResultTable trt = params.getWorkDirectory().getTestResultTable();
         trt.waitUntilReady();
-        
+
         String[] tests = params.getTests();
         TestFilter[] filters = params.getFilters();
         if (tests == null)
@@ -1492,10 +1518,10 @@
         else
             return trt.getIterator(tests, filters);
     }
-    
+
     private void showTool(final InterviewParameters params) throws BadArgs {
         Startup startup = new Startup();
-        
+
         try {
             EventQueue.invokeLater(new Runnable() {
                 public void run() {
@@ -1512,13 +1538,13 @@
             startup.disposeLater();
         }
     } // showTool()
-    
+
     private void showResultStats(int[] stats) {
         int p = stats[Status.PASSED];
         int f = stats[Status.FAILED];
         int e = stats[Status.ERROR];
         int nr = stats[Status.NOT_RUN];
-        
+
         String msg;
         if (p + f + e + nr == 0)
             msg = i18n.getString("main.noTests");
@@ -1536,7 +1562,7 @@
         }
         out.println(msg);
     }
-    
+
     private BackupPolicy createBackupPolicy() {
         return new BackupPolicy() {
             public int getNumBackupsToKeep(File file) {
@@ -1555,7 +1581,7 @@
             private String[] ignoreExtns = StringArray.split(System.getProperty("javatest.backup.ignore", ".jtr"));
         };
     }
-    
+
     private void startHttpServer() {
         // start the http server
         // do this as early as possible, since objects may check
@@ -1563,9 +1589,9 @@
         // register their handlers
         HttpdServer server = new HttpdServer();
         Thread thr = new Thread(server);
-        
+
         PageGenerator.setSWName(ProductInfo.getName());
-        
+
         // format the date for i18n
         DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
         Date dt = ProductInfo.getBuildDate();
@@ -1574,15 +1600,15 @@
             date = df.format(dt);
         else
             date = i18n.getString("main.nobDate");
-        
+
         PageGenerator.setSWBuildDate(date);
         PageGenerator.setSWVersion(ProductInfo.getVersion());
-        
+
         thr.start();
     }
-    
+
     private String[] getEnvVars() {
-        
+
         Map<String,String> envVars = new TreeMap<String,String>();
         String osName = System.getProperty("os.name").toLowerCase();
         if (osName.startsWith("windows")) {
@@ -1594,22 +1620,22 @@
             addEnvVars(envVars, "PATH=/bin:/usr/bin");
         }
         addEnvVars(envVars, envVarArgs);
-        
+
         return envVars.values().toArray(new String[envVars.size()]);
     }
-    
+
     private void addEnvVars(Map<String,String> table, String list) {
         addEnvVars(table, list.split(","));
     }
-    
+
     private void addEnvVars(Map<String,String> table, String[] list) {
         addEnvVars(table, Arrays.asList(list));
     }
-    
+
     private void addEnvVars(Map<String,String> table, List<String> list) {
         if (list == null)
             return;
-        
+
         for (String s: list) {
             s = s.trim();
             if (s.length() == 0)
@@ -1625,24 +1651,24 @@
             }
         }
     }
-    
+
     private static String combineKeywords(String kw1, String kw2) {
         return (kw1 == null ? kw2 : kw1 + " & " + kw2);
     }
-    
+
     private File findJar(String jarProp, String pathFromHome, Class<?> c) {
         if (jarProp != null) {
             String v = System.getProperty(jarProp);
             if (v != null)
                 return new File(v);
         }
-        
+
         if (pathFromHome != null) {
             String v = System.getProperty("jtreg.home");
             if (v != null)
                 return new File(v, pathFromHome);
         }
-        
+
         if (c != null)  {
             try {
                 String className = c.getName().replace(".", "/") + ".class";
@@ -1659,10 +1685,10 @@
                 ignore.printStackTrace();
             }
         }
-        
+
         return null;
     }
-    
+
     /**
      * Call System.exit, taking care to get permission from the
      * JavaTestSecurityManager, if it is installed.
@@ -1675,7 +1701,7 @@
             ((JavaTestSecurityManager) sc).setAllowExit(true);
         System.exit(exitCode);
     }
-    
+
     // This is almost completely dead code; testStats appears unused
     // so the only use here is error handling, which perhaps can be
     // folded into RegressionObserver
@@ -1683,24 +1709,24 @@
         public void startingTestRun(Parameters params) {
             testStats = new int[Status.NUM_STATES];
         }
-        
+
         public void startingTest(TestResult tr) { }
-        
+
         public void finishedTest(TestResult tr) {
             testStats[tr.getStatus().getType()]++;
         }
-        
+
         public void stoppingTestRun() { }
-        
+
         public void finishedTesting() { }
-        
+
         public void finishedTestRun(boolean allOK) { }
-        
+
         public void error(String msg) {
             err.println(i18n.getString("main.error", msg));
         }
     }
-    
+
     private void checkLockFiles(File workDir, String msg) {
 //      String jc = System.getProperty("javatest.child");
 //      File jtData = new File(workDir, "jtData");
@@ -1712,12 +1738,12 @@
 //          }
 //      }
     }
-    
+
     //----------member variables-----------------------------------------------
-    
+
     private PrintWriter out;
     private PrintWriter err;
-    
+
     // this first group of args are the "standard" JavaTest args
     private File testSuiteArg;
     private File workDirArg;
@@ -1732,13 +1758,14 @@
     // TODO: consider making this a "pathset" to detect redundant specification
     // of directories and paths within them.
     private List<File> antFileArgs = new ArrayList<File>();
-    
+
     // these args are jtreg extras
     private File baseDirArg;
     private boolean sameJVMFlag;
     private JDK jdk;
     private boolean guiFlag;
     private boolean reportOnlyFlag;
+    private boolean noReportFlag;
     private static Verbose  verbose;
     private boolean httpdFlag;
     private String observerClassName;
@@ -1752,28 +1779,28 @@
     private List<File> classPathAppendArg = new ArrayList<File>();
     private boolean jitFlag = true;
     private Help help;
-    
-    
+
+
     // the list of args to be passed down to a  child VM
     private List<String> childArgs = new ArrayList<String>();
-    
+
     private int[] testStats;
-    
+
     private static final String AUTOMATIC = "!manual";
     private static final String MANUAL    = "manual";
-    
+
     private static final String[] DEFAULT_UNIX_ENV_VARS = {
         "DISPLAY", "HOME", "LANG", "LC_ALL", "LC_TYPE", "LPDEST", "PRINTER", "TZ", "XMODIFIERS"
     };
-    
+
     private static final String[] DEFAULT_WINDOWS_ENV_VARS = {
         "SystemDrive", "SystemRoot", "windir", "TMP", "TEMP"
     };
-    
+
     private static final String JAVATEST_ANT_FILE_LIST = "javatest.ant.file.list";
-    
+
     private static boolean debugChild = Boolean.getBoolean("javatest.regtest.debugChild");
     private static final String PATHSEP  = System.getProperty("path.separator");
-    
+
     private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(Main.class);
 }
--- a/test/jtreg/com/sun/javatest/regtest/MainAction.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/test/jtreg/com/sun/javatest/regtest/MainAction.java	Mon Nov 17 15:26:51 2008 +0000
@@ -151,7 +151,7 @@
                 throw new ParseException(PARSE_SECURE_OTHERVM);
         }
     } // init()
-    
+
     @Override
     public File[] getSourceFiles() {
         List<File> l = new ArrayList<File>();
@@ -244,11 +244,11 @@
         // available to main and applet actions via the system properties
         // "test.src" and "test.classes", respectively"
         List<String> command = new ArrayList<String>(6);
-        
+
         // some tests are inappropriately relying on the CLASSPATH environment
         // variable being set, so force the use here.
         final boolean useCLASSPATH = true;
-        
+
         if (useCLASSPATH || script.isJDK11()) {
             command.add("CLASSPATH=" + script.getJavaTestClassPath() +
                         PATHSEP + script.testClassPath());
@@ -263,10 +263,10 @@
 
         command.add("-Dtest.src=" + script.absTestSrcDir());
         command.add("-Dtest.classes=" + script.absTestClsDir());
-        command.add("-Dtest.vm.opts=" + script.getTestVMOptions());
-        command.add("-Dtest.tool.vm.opts=" + script.getTestToolVMOptions());
-        command.add("-Dtest.javac.opts=" + script.getTestCompilerOptions());
-        command.add("-Dtest.java.opts=" + script.getTestJavaOptions());
+        command.add("-Dtest.vm.opts=" + join(script.getTestVMOptions()));
+        command.add("-Dtest.tool.vm.opts=" + join(script.getTestToolVMOptions()));
+        command.add("-Dtest.javac.opts=" + join(script.getTestCompilerOptions()));
+        command.add("-Dtest.java.opts=" + join(script.getTestJavaOptions()));
 
         String newPolicyFN;
         if (policyFN != null) {
@@ -364,7 +364,7 @@
     } // runOtherJVM()
 
     private static Hashtable savedSystemProperties;
-    
+
     private Status runSameJVM() throws TestRunException {
         // TAG-SPEC:  "The source and class directories of a test are made
         // available to main and applet actions via the system properties
@@ -376,6 +376,11 @@
                 Properties p = System.getProperties();
                 if (savedSystemProperties == null)
                     savedSystemProperties = copyProperties(p);
+                p.put("java.class.path",
+                        script.absTestClsDir() + PATHSEP +
+                        script.absTestSrcDir() + PATHSEP +
+                        script.absClsLibListStr() + PATHSEP +
+                        p.getProperty("java.class.path"));
                 p.put("test.src", script.absTestSrcDir().getPath());
                 p.put("test.classes", script.absTestClsDir().getPath());
                 p.put("test.vm.opts", StringUtils.join(script.getTestVMOptions(), " "));
@@ -390,18 +395,18 @@
                 //return Status.error(MAIN_SECMGR_BAD);
             }
         }
-        
+
         ByteArrayOutputStream newOut = new ByteArrayOutputStream();
         ByteArrayOutputStream newErr = new ByteArrayOutputStream();
         PrintStream psOut = new PrintStream(newOut);
         PrintStream psErr = new PrintStream(newErr);
-        
+
         Status status;
         PrintStream saveOut = System.out;
         PrintStream saveErr = System.err;
         try {
             status = Status.passed(EXEC_PASS);
-            
+
             String[] classpath = StringArray.splitSeparator(PATHSEP, script.testClassPath());
             List<URL> urls = new ArrayList<URL>();
             for (int i = 0; i < classpath.length; i++) {
@@ -417,18 +422,18 @@
             Class<?> c = loader.loadClass(buildFN);
             Class<?>[] argTypes = { String[].class };
             Method method = c.getMethod("main", argTypes);
-            
+
             // XXX 4/1 possible to use splitSeparator instead?
             String[] tmpArgs = StringArray.splitWS(mainArgs);
             Object[] runArgs = {tmpArgs};
-            
+
             Status stat = redirectOutput(psOut, psErr);
             if (!stat.isPassed()) {
                 return stat;
             }
-            
+
             // RUN JAVA IN ANOTHER THREADGROUP
-            
+
             SameVMThreadGroup tg = new SameVMThreadGroup();
             SameVMThread svmt = new SameVMThread(method, runArgs, psErr);
             Thread t = new Thread(tg, svmt, "SameVMThread");
@@ -443,7 +448,7 @@
                 }
             }
             tg.cleanup();
-            
+
             if (((svmt.t != null) || (tg.uncaughtThrowable != null)) && (error == null)) {
                 if (svmt.t == null)
                     error = tg.uncaughtThrowable;
@@ -451,12 +456,12 @@
                     error = svmt.t;
                 status = Status.failed(MAIN_THREW_EXCEPT + error.toString());
             }
-            
+
             // EVALUATE RESULTS
             if (status.getReason().endsWith("java.lang.SecurityException: System.exit() forbidden by JavaTest")) {
                 status = Status.failed(UNEXPECT_SYS_EXIT);
             } else {
-                
+
                 boolean ok = status.isPassed();
                 int st   = status.getType();
                 String sr;
@@ -503,19 +508,20 @@
                     System.setProperties(newProperties(savedSystemProperties));
 //                    System.err.println("reset properties");
                 } else {
+                    System.setProperty("java.class.path", (String) savedSystemProperties.get("java.class.path"));
 //                    System.err.println("no need to reset properties");
                 }
                 rsm.setAllowPropertiesAccess(false);
             }
-            
+
             Status stat = redirectOutput(saveOut, saveErr);
             if (!stat.isPassed()) {
                 return stat;
             }
-            
+
             psOut.close();
             psErr.close();
-            
+
             String outString = newOut.toString();
             String errString = newErr.toString();
             PrintWriter sysOut = section.createOutput("System.out");
@@ -528,7 +534,7 @@
                 if (sysErr != null) sysErr.close();
             }
         }
-        
+
         return status;
     } // runSameJVM()
 
@@ -539,7 +545,7 @@
             value = "novalue";
         return value;
     } // parseMainManual()
-    
+
     private static Hashtable<Object,Object> copyProperties(Properties p) {
         Hashtable<Object,Object> h = new Hashtable<Object,Object>();
         for (Enumeration<?> e = p.propertyNames(); e.hasMoreElements(); ) {
@@ -548,7 +554,7 @@
         }
         return h;
     }
-    
+
     private static Properties newProperties(Hashtable<?,?> h) {
         Properties p = new Properties();
         for (Enumeration<?> e = h.keys(); e.hasMoreElements(); ) {
@@ -556,7 +562,17 @@
             p.put(key, h.get(key));
         }
         return p;
-        
+
+    }
+
+    private String join(List<String> list) {
+        StringBuffer sb = new StringBuffer();
+        for (String s: list) {
+            if (sb.length() > 0)
+                sb.append(" ");
+            sb.append(s);
+        }
+        return sb.toString();
     }
 
     //----------internal classes------------------------------------------------
@@ -630,27 +646,27 @@
 
         private void cleanup() {
             cleanMode = true;
-            
+
             final int CLEANUP_ROUNDS = 4;
             final long MAX_CLEANUP_TIME_MILLIS = 2 * 60 * 1000;
             final long CLEANUP_MILLIS_PER_ROUND = MAX_CLEANUP_TIME_MILLIS / CLEANUP_ROUNDS;
             final long NANOS_PER_MILLI = 1000L * 1000L;
-            
+
             long startCleanupTime = System.nanoTime();
-            
+
             for (int i = 1; i <= CLEANUP_ROUNDS; i++) {
                 long deadline = startCleanupTime + i * CLEANUP_MILLIS_PER_ROUND * NANOS_PER_MILLI;
                 List<Thread> liveThreads = liveThreads();
-                if (liveThreads.isEmpty()) { 
+                if (liveThreads.isEmpty()) {
                     // nothing left to cleanup
                     cleanupOK = true;
                     return;
                 }
-                
+
                 // kick the remaining live threads
                 for (Thread thread : liveThreads)
                     thread.interrupt();
-                
+
                 // try joining as many threads as possible before
                 // the round times out
                 for (Thread thread : liveThreads) {
@@ -663,10 +679,10 @@
                     }
                 }
             }
-            
+
             cleanupOK = liveThreads().isEmpty();
         } // cleanup()
-        
+
         /**
          * Gets all the "interesting" threads in the thread group.
          * @see ThreadGroup#enumerate(Thread[])
--- a/test/jtreg/com/sun/javatest/regtest/RegressionSecurityManager.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/test/jtreg/com/sun/javatest/regtest/RegressionSecurityManager.java	Mon Nov 17 15:26:51 2008 +0000
@@ -25,7 +25,6 @@
 
 package com.sun.javatest.regtest;
 
-import java.lang.RuntimePermission;
 import java.security.Permission;
 import java.util.PropertyPermission;
 
@@ -55,7 +54,7 @@
                 System.err.println("execution of sameJVM tests");
                 System.err.println();
             }
-            else 
+            else
                 System.setSecurityManager(new RegressionSecurityManager());
         }
         catch (SecurityException e) {
@@ -104,13 +103,13 @@
         // allow most stuff, but limit as appropriate
         if (perm instanceof RuntimePermission) {
             if (perm.getName().equals("setIO")) {
-                if (!allowSetIO) 
+                if (!allowSetIO)
                     // is this right or should we really restrict this more?
                     super.checkPermission(new java.lang.RuntimePermission("setIO"));
             }
             else if (perm.getName().equals("exitVM"))
                 checkExit(0);
-            else if (perm.getName().equals("createSecurityManager")) 
+            else if (perm.getName().equals("createSecurityManager"))
                 super.checkPermission(new java.lang.RuntimePermission("createSecurityManager"));
         }
         else if (perm instanceof PropertyPermission) {
@@ -118,21 +117,21 @@
                 checkPropertiesAccess();
         }
     }
-    
+
     private boolean propertiesAccessed;
-    
+
     public synchronized void checkPropertiesAccess() {
         super.checkPropertiesAccess();
         propertiesAccessed = true;
     }
-    
+
     boolean isPropertiesAccessed() {
         return propertiesAccessed;
     }
-    
+
     void resetPropertiesAccessed() {
         propertiesAccessed = false;
-    } 
+    }
 
     public boolean setAllowSetIO(boolean bool) {
         boolean prev = allowSetIO;
--- a/test/jtreg/com/sun/javatest/regtest/RegressionTestFinder.java	Mon Nov 17 12:41:07 2008 +0000
+++ b/test/jtreg/com/sun/javatest/regtest/RegressionTestFinder.java	Mon Nov 17 15:26:51 2008 +0000
@@ -40,6 +40,7 @@
 import com.sun.javatest.finder.TagTestFinder;
 import com.sun.javatest.finder.HTMLCommentStream;
 import com.sun.javatest.finder.ShScriptCommentStream;
+import java.util.regex.Pattern;
 
 /**
   * This is a specific implementation of the TagTestFinder which is to be used
@@ -169,36 +170,33 @@
         }
 
         // force more key words based on actions
-        String name;
         String value = newTagValues.get("run");
 
         String origKeywords = newTagValues.get("keywords");
         String addKeywords  = "";
 
-        if (value.indexOf(name = "othervm") != -1)
-            addKeywords += "othervm ";
+        if (match(value, OTHERVM_OPTION))
+            addKeywords += " othervm";
 
-        if (value.indexOf(name = "manual") != -1)
-            addKeywords += "manual ";
+        if (match(value, MANUAL_OPTION))
+            addKeywords += " manual";
 
-        if (value.indexOf(name = "shell") != -1)
-            addKeywords += "shell ";
+        if (match(value, SHELL_ACTION))
+            addKeywords += " shell";
 
-        if (value.indexOf(name = "ignore") != -1)
-            addKeywords += "ignore ";
+        if (match(value, IGNORE_ACTION))
+            addKeywords += " ignore";
 
         if (!addKeywords.equals("")) {
             if (origKeywords == null)
                 newTagValues.put("keywords", addKeywords.trim());
             else
-                newTagValues.put("keywords", origKeywords + " " + addKeywords.trim());
+                newTagValues.put("keywords", origKeywords + addKeywords);
         }
 
         /*
-        for (Enumeration e = newTagValues.keys(); e.hasMoreElements(); ) {
-            name  = (String) e.nextElement();
-            value = (String) newTagValues.get(name);
-            System.out.println("NAME: " + name + " VALUE: " + value);
+        for (Map.Entry<String,String> e: newTagValues.entrySet()) {
+            System.out.println("NAME: " + e.getKey() + " VALUE: " + e.getValue());
 //          if (name.equals("keywords"))
 //              System.out.println(currFile + " " + "`" + value + "'");
         }
@@ -206,6 +204,10 @@
 
         return newTagValues;
     }
+    
+    private static boolean match(CharSequence cs, Pattern p) {
+        return p.matcher(cs).matches();
+    }
 
     /**
      * Make sure that the provide name-value pair is of the proper format as
@@ -221,7 +223,6 @@
     {
         Map<String,String> tagValues = (Map<String,String>) tv;
         
-        File currFile = getCurrentFile();
         // check for valid tag name, don't produce error message for the
         // the SCCS sequence '%' 'W' '%'
         if (name.startsWith("(#)"))
@@ -552,6 +553,12 @@
     
     private static final boolean allowLocalKeys = 
             Boolean.parseBoolean(System.getProperty("javatest.regtest.allowLocalKeys", "true"));
+    
+    private static final Pattern 
+        OTHERVM_OPTION = Pattern.compile(".*/othervm[/ \t].*",    Pattern.DOTALL),
+        MANUAL_OPTION  = Pattern.compile(".*/manual[/= \t].*",    Pattern.DOTALL),
+        SHELL_ACTION   = Pattern.compile(".*[ \t]shell[/ \t].*",  Pattern.DOTALL),
+        IGNORE_ACTION  = Pattern.compile(".*[ \t]ignore[/ \t].*", Pattern.DOTALL);
 
     //----------member variables------------------------------------------------
 
--- a/test/jtreg/com/sun/javatest/regtest/i18n.properties	Mon Nov 17 12:41:07 2008 +0000
+++ b/test/jtreg/com/sun/javatest/regtest/i18n.properties	Mon Nov 17 15:26:51 2008 +0000
@@ -176,6 +176,7 @@
     re-run any tests.  A work directory containing the results of the executed \
     tests must be provided.  The default location is "./JTwork". To specify an \
     alternate directory, use -workDir.
+help.main.nr.desc=Do not generate a final report.
 help.main.startHttpd.desc=Start the http server to view test results
 help.main.timeout.desc=A scaling factor to extend the default timeout of all \
     tests.  Typically used when running on slow file systems.