From 75c3e0319c8773c6f88beee0595b63104c7a63fd Mon Sep 17 00:00:00 2001
From: Steven Knight <knight@baldmt.com>
Date: Sun, 21 Nov 2004 21:14:41 +0000
Subject: More command-line output customizability:  , , , .

---
 doc/man/scons.1                |  38 +++++
 src/CHANGES.txt                |  10 +-
 src/engine/SCons/Tool/jar.py   |   7 +-
 src/engine/SCons/Tool/javac.py |   5 +-
 src/engine/SCons/Tool/javah.py |   5 +-
 src/engine/SCons/Tool/rmic.py  |   5 +-
 test/JAR.py                    | 266 ---------------------------------
 test/JARFLAGS.py               |  94 ------------
 test/JAVAC.py                  | 314 ---------------------------------------
 test/JAVACFLAGS.py             |  73 ---------
 test/JAVAH.py                  | 315 ---------------------------------------
 test/Java/JAR.py               | 266 +++++++++++++++++++++++++++++++++
 test/Java/JARCOM.py            |  65 +++++++++
 test/Java/JARCOMSTR.py         |  69 +++++++++
 test/Java/JARFLAGS.py          |  94 ++++++++++++
 test/Java/JAVAC.py             | 314 +++++++++++++++++++++++++++++++++++++++
 test/Java/JAVACCOM.py          |  68 +++++++++
 test/Java/JAVACCOMSTR.py       |  72 +++++++++
 test/Java/JAVACFLAGS.py        |  73 +++++++++
 test/Java/JAVAH.py             | 315 +++++++++++++++++++++++++++++++++++++++
 test/Java/JAVAHCOM.py          |  69 +++++++++
 test/Java/JAVAHCOMSTR.py       |  85 +++++++++++
 test/Java/RMIC.py              | 325 +++++++++++++++++++++++++++++++++++++++++
 test/Java/RMICCOM.py           |  79 ++++++++++
 test/Java/RMICCOMSTR.py        |  85 +++++++++++
 test/RMIC.py                   | 325 -----------------------------------------
 26 files changed, 2040 insertions(+), 1396 deletions(-)
 delete mode 100644 test/JAR.py
 delete mode 100644 test/JARFLAGS.py
 delete mode 100644 test/JAVAC.py
 delete mode 100644 test/JAVACFLAGS.py
 delete mode 100644 test/JAVAH.py
 create mode 100644 test/Java/JAR.py
 create mode 100644 test/Java/JARCOM.py
 create mode 100644 test/Java/JARCOMSTR.py
 create mode 100644 test/Java/JARFLAGS.py
 create mode 100644 test/Java/JAVAC.py
 create mode 100644 test/Java/JAVACCOM.py
 create mode 100644 test/Java/JAVACCOMSTR.py
 create mode 100644 test/Java/JAVACFLAGS.py
 create mode 100644 test/Java/JAVAH.py
 create mode 100644 test/Java/JAVAHCOM.py
 create mode 100644 test/Java/JAVAHCOMSTR.py
 create mode 100644 test/Java/RMIC.py
 create mode 100644 test/Java/RMICCOM.py
 create mode 100644 test/Java/RMICCOMSTR.py
 delete mode 100644 test/RMIC.py

diff --git a/doc/man/scons.1 b/doc/man/scons.1
index e73bada..2f504a6 100644
--- a/doc/man/scons.1
+++ b/doc/man/scons.1
@@ -5494,6 +5494,15 @@ option).
 .IP JARCOM
 The command line used to call the Java archive tool.
 
+.IP JARCOMSTR
+The string displayed when the Java archive tool
+is called
+If this is not set, then $JARCOM (the command line) is displayed.
+
+.ES
+env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET")
+.EE
+
 .IP JARFLAGS
 General options passed to the Java archive tool.
 By default this is set to
@@ -5517,6 +5526,16 @@ corresponding Java class files.
 Any options specified in the $JAVACFLAGS construction variable
 are included on this command line.
 
+.IP JAVACCOMSTR
+The string displayed when compiling
+a directory tree of Java source files to
+corresponding Java class files.
+If this is not set, then $JAVACCOM (the command line) is displayed.
+
+.ES
+env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES")
+.EE
+
 .IP JAVACFLAGS
 General options that are passed to the Java compiler.
 
@@ -5541,6 +5560,15 @@ from Java classes.
 Any options specified in the $JAVAHFLAGS construction variable
 are included on this command line.
 
+.IP JAVAHCOMSTR
+The string displayed when C header and stub files
+are generated from Java classes.
+If this is not set, then $JAVAHCOM (the command line) is displayed.
+
+.ES
+env = Environment(JAVAHCOMSTR = "Generating header/stub file(s) $TARGETS from $SOURCES")
+.EE
+
 .IP JAVAHFLAGS
 General options passed to the C header and stub file generator
 for Java classes.
@@ -6258,6 +6286,16 @@ from Java classes that contain RMI implementations.
 Any options specified in the $RMICFLAGS construction variable
 are included on this command line.
 
+.IP RMICCOMSTR
+The string displayed when compiling
+stub and skeleton class files
+from Java classes that contain RMI implementations.
+If this is not set, then $RMICCOM (the command line) is displayed.
+
+.ES
+env = Environment(RMICCOMSTR = "Generating stub/skeleton class files $TARGETS from $SOURCES")
+.EE
+
 .IP RMICFLAGS
 General options passed to the Java RMI stub compiler.
 
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 326f9cf..62d691a 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -133,10 +133,12 @@ RELEASE 0.97 - XXX
   - Support easier customization of what's displayed by various default
     actions by adding new construction variables:  $ARCOMSTR, $ASCOMSTR,
     $ASPPCOMSTR, $BITKEEPERCOMSTR, $CCCOMSTR, $CVSCOMSTR, $CXXCOMSTR,
-    $F77COMSTR, $F90COMSTR, $F95COMSTR, $FORTRANCOMSTR, $LEXCOMSTR,
-    $LINKCOMSTR, $RCSCOMSTR, $SCCSCOMSTR, $SHCCCOMSTR, $SHCXXCOMSTR,
-    $SHF77COMSTR, $SHF90COMSTR, $SHF95COMSTR, $SHFORTRANCOMSTR,
-    $SHLINKCOMSTR and $YACCCOMSTR.
+    $F77COMSTR, $F90COMSTR, $F95COMSTR, $FORTRANCOMSTR, $JARCOMSTR,
+    $JAVACCOMSTR, $JAVAHCOMSTR, $LEXCOMSTR, $LINKCOMSTR, $RCSCOMSTR,
+    $RMICCOMSTR, $SCCSCOMSTR, $SHCCCOMSTR, $SHCXXCOMSTR, $SHF77COMSTR,
+    $SHF90COMSTR, $SHF95COMSTR, $SHFORTRANCOMSTR, $SHLINKCOMSTR and
+    $YACCCOMSTR.
+
 
   From Wayne Lee:
 
diff --git a/src/engine/SCons/Tool/jar.py b/src/engine/SCons/Tool/jar.py
index 3c5e5f5..a721d96 100644
--- a/src/engine/SCons/Tool/jar.py
+++ b/src/engine/SCons/Tool/jar.py
@@ -33,6 +33,7 @@ selection method.
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
+import SCons.Action
 import SCons.Builder
 import SCons.Util
 
@@ -77,8 +78,10 @@ def jarChdir(target, source, env, for_signature):
     if env.has_key('JARCHDIR'):
         return [ '-C', '$JARCHDIR' ]
     return []
-        
-JarBuilder = SCons.Builder.Builder(action = '$JARCOM',
+
+JarAction = SCons.Action.Action('$JARCOM', '$JARCOMSTR')
+
+JarBuilder = SCons.Builder.Builder(action = JarAction,
                                    source_factory = SCons.Node.FS.default_fs.Entry,
                                    suffix = '$JARSUFFIX')
 
diff --git a/src/engine/SCons/Tool/javac.py b/src/engine/SCons/Tool/javac.py
index e16f6d0..e6a0fc3 100644
--- a/src/engine/SCons/Tool/javac.py
+++ b/src/engine/SCons/Tool/javac.py
@@ -37,6 +37,7 @@ import os
 import os.path
 import string
 
+import SCons.Action
 import SCons.Builder
 from SCons.Node.FS import _my_normcase
 from SCons.Tool.JavaCommon import parse_java_file
@@ -91,7 +92,9 @@ def emit_java_classes(target, source, env):
 
     return tlist, slist
 
-JavaBuilder = SCons.Builder.Builder(action = '$JAVACCOM',
+JavaAction = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR')
+
+JavaBuilder = SCons.Builder.Builder(action = JavaAction,
                     emitter = emit_java_classes,
                     target_factory = SCons.Node.FS.default_fs.Dir,
                     source_factory = SCons.Node.FS.default_fs.Dir)
diff --git a/src/engine/SCons/Tool/javah.py b/src/engine/SCons/Tool/javah.py
index 8f69a46..4d5749a 100644
--- a/src/engine/SCons/Tool/javah.py
+++ b/src/engine/SCons/Tool/javah.py
@@ -36,6 +36,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 import os.path
 import string
 
+import SCons.Action
 import SCons.Builder
 import SCons.Node.FS
 import SCons.Tool.javac
@@ -105,7 +106,9 @@ def JavaHOutFlagGenerator(target, source, env, for_signature):
     except AttributeError:
         return '-o ' + str(t)
 
-JavaHBuilder = SCons.Builder.Builder(action = '$JAVAHCOM',
+JavaHAction = SCons.Action.Action('$JAVAHCOM', '$JAVAHCOMSTR')
+
+JavaHBuilder = SCons.Builder.Builder(action = JavaHAction,
                      emitter = emit_java_headers,
                      src_suffix = '$JAVACLASSSUFFIX',
                      target_factory = SCons.Node.FS.default_fs.Entry,
diff --git a/src/engine/SCons/Tool/rmic.py b/src/engine/SCons/Tool/rmic.py
index 465bd68..c5c4854 100644
--- a/src/engine/SCons/Tool/rmic.py
+++ b/src/engine/SCons/Tool/rmic.py
@@ -36,6 +36,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 import os.path
 import string
 
+import SCons.Action
 import SCons.Builder
 import SCons.Node.FS
 import SCons.Util
@@ -89,7 +90,9 @@ def emit_rmic_classes(target, source, env):
 
     return tlist, source
 
-RMICBuilder = SCons.Builder.Builder(action = '$RMICCOM',
+RMICAction = SCons.Action.Action('$RMICCOM', '$RMICCOMSTR')
+
+RMICBuilder = SCons.Builder.Builder(action = RMICAction,
                      emitter = emit_rmic_classes,
                      src_suffix = '$JAVACLASSSUFFIX',
                      target_factory = SCons.Node.FS.default_fs.Dir,
diff --git a/test/JAR.py b/test/JAR.py
deleted file mode 100644
index ea51213..0000000
--- a/test/JAR.py
+++ /dev/null
@@ -1,266 +0,0 @@
-#!/usr/bin/env python
-#
-# __COPYRIGHT__
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import os
-import string
-import sys
-import TestSCons
-
-python = TestSCons.python
-
-test = TestSCons.TestSCons()
-
-test.write('myjar.py', r"""
-import sys
-args = sys.argv[1:]
-while args:
-    a = args[0]
-    if a == 'cf':
-        out = args[1]
-        args = args[1:]
-    else:
-        break
-    args = args[1:]
-outfile = open(out, 'wb')
-for file in args:
-    infile = open(file, 'rb')
-    for l in infile.readlines():
-        if l[:7] != '/*jar*/':
-            outfile.write(l)
-sys.exit(0)
-""")
-
-test.write('SConstruct', """
-env = Environment(tools = ['jar'],
-                  JAR = r'%s myjar.py')
-env.Jar(target = 'test1.jar', source = 'test1.class')
-""" % (python))
-
-test.write('test1.class', """\
-test1.class
-/*jar*/
-line 3
-""")
-
-test.run(arguments = '.', stderr = None)
-
-test.must_match('test1.jar', "test1.class\nline 3\n")
-
-if os.path.normcase('.class') == os.path.normcase('.CLASS'):
-
-    test.write('SConstruct', """
-env = Environment(tools = ['jar'],
-                  JAR = r'%s myjar.py')
-env.Jar(target = 'test2.jar', source = 'test2.CLASS')
-""" % (python))
-
-    test.write('test2.CLASS', """\
-test2.CLASS
-/*jar*/
-line 3
-""")
-
-    test.run(arguments = '.', stderr = None)
-
-    test.must_match('test2.jar', "test2.CLASS\nline 3\n")
-
-test.write('myjar2.py', r"""
-import sys
-import string
-f=open(sys.argv[2], 'wb')
-f.write(string.join(sys.argv[1:]))
-f.write("\n")
-f.close()
-sys.exit(0)
-""")
-
-test.write('SConstruct', """
-env = Environment(tools = ['jar'],
-                  JAR = r'%s myjar2.py',
-                  JARFLAGS='cvf')
-env.Jar(target = 'classes.jar', source = [ 'testdir/bar.class',
-                                           'foo.mf' ],
-        TESTDIR='testdir',
-        JARCHDIR='$TESTDIR')
-""" % (python))
-
-test.subdir('testdir')
-test.write([ 'testdir', 'bar.class' ], 'foo')
-test.write('foo.mf',
-           """Manifest-Version : 1.0
-           blah
-           blah
-           blah
-           """)
-test.run(arguments='classes.jar')
-test.must_match('classes.jar',
-                'cvfm classes.jar foo.mf -C testdir bar.class\n')
-
-if test.detect_tool('javac'):
-    where_javac = test.detect('JAVAC', 'javac')
-else:
-    import SCons.Environment
-    env = SCons.Environment.Environment()
-    where_javac = env.WhereIs('javac', os.environ['PATH'])
-    if not where_javac:
-        where_javac = env.WhereIs('javac', '/usr/local/j2sdk1.3.1/bin')
-        if not where_javac:
-            print "Could not find Java javac, skipping test(s)."
-            test.pass_test(1)
-
-if test.detect_tool('jar'):
-    where_jar = test.detect('JAR', 'jar')
-else:
-    import SCons.Environment
-    env = SCons.Environment.Environment()
-    where_jar = env.WhereIs('jar', os.environ['PATH'])
-    if not where_jar:
-        where_jar = env.WhereIs('jar', '/usr/local/j2sdk1.3.1/bin')
-        if not where_jar:
-            print "Could not find Java jar, skipping test(s)."
-            test.pass_test(1)
-
-
-test.write("wrapper.py", """\
-import os
-import string
-import sys
-open('%s', 'ab').write("wrapper.py %%s\\n" %% string.join(sys.argv[1:]))
-os.system(string.join(sys.argv[1:], " "))
-""" % string.replace(test.workpath('wrapper.out'), '\\', '\\\\'))
-
-test.write('SConstruct', """
-foo = Environment(tools = ['javac', 'jar'],
-                  JAVAC = '%(where_javac)s',
-                  JAR = '%(where_jar)s')
-jar = foo.Dictionary('JAR')
-bar = foo.Copy(JAR = r'%(python)s wrapper.py ' + jar)
-foo.Java(target = 'classes', source = 'com/sub/foo')
-bar.Java(target = 'classes', source = 'com/sub/bar')
-foo.Jar(target = 'foo', source = 'classes/com/sub/foo')
-bar.Jar(target = 'bar', source = 'classes/com/sub/bar')
-""" % locals())
-
-test.subdir('com',
-            ['com', 'sub'],
-            ['com', 'sub', 'foo'],
-            ['com', 'sub', 'bar'])
-
-test.write(['com', 'sub', 'foo', 'Example1.java'], """\
-package com.sub.foo;
-
-public class Example1
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'foo', 'Example2.java'], """\
-package com.sub.foo;
-
-public class Example2
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'foo', 'Example3.java'], """\
-package com.sub.foo;
-
-public class Example3
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'bar', 'Example4.java'], """\
-package com.sub.bar;
-
-public class Example4
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'bar', 'Example5.java'], """\
-package com.sub.bar;
-
-public class Example5
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'bar', 'Example6.java'], """\
-package com.sub.bar;
-
-public class Example6
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.run(arguments = '.')
-
-test.must_match('wrapper.out',
-                "wrapper.py %(where_jar)s cf bar.jar classes/com/sub/bar\n" % locals())
-
-test.must_exist('foo.jar')
-test.must_exist('bar.jar')
-
-test.up_to_date(arguments = '.')
-
-test.pass_test()
diff --git a/test/JARFLAGS.py b/test/JARFLAGS.py
deleted file mode 100644
index 7e3669d..0000000
--- a/test/JARFLAGS.py
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/env python
-#
-# __COPYRIGHT__
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import os.path
-
-import TestSCons
-
-test = TestSCons.TestSCons()
-
-test.subdir('src')
-
-if test.detect_tool('javac'):
-    where_javac = test.detect('JAVAC', 'javac')
-else:
-    import SCons.Environment
-    env = SCons.Environment.Environment()
-    where_javac = env.WhereIs('javac', os.environ['PATH'])
-    if not where_javac:
-        where_javac = env.WhereIs('javac', '/usr/local/j2sdk1.3.1/bin')
-        if not where_javac:
-            print "Could not find Java javac, skipping test(s)."
-            test.pass_test(1)
-
-if test.detect_tool('jar'):
-    where_jar = test.detect('JAR', 'jar')
-else:
-    import SCons.Environment
-    env = SCons.Environment.Environment()
-    where_jar = env.WhereIs('jar', os.environ['PATH'])
-    if not where_jar:
-        where_jar = env.WhereIs('jar', '/usr/local/j2sdk1.3.1/bin')
-        if not where_jar:
-            print "Could not find Java jar, skipping test(s)."
-            test.pass_test(1)
-
-test.write('SConstruct', """
-env = Environment(tools = ['javac', 'jar'],
-                  JAVAC = '%(where_javac)s',
-                  JAR = '%(where_jar)s',
-                  JARFLAGS = 'cvf')
-env['JARFLAGS'] = 'cvf'
-class_files = env.Java(target = 'classes', source = 'src')
-env.Jar(target = 'test.jar', source = class_files)
-""" % locals())
-
-test.write(['src', 'Example1.java'], """\
-package src;
-
-public class Example1
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.run(arguments = '.',
-         match=TestSCons.match_re_dotall,
-         stdout = test.wrap_stdout("""\
-%(where_javac)s -d classes -sourcepath src src/Example1\.java
-%(where_jar)s cvf test.jar classes/src/Example1\.class
-.*
-adding: classes/src/Example1\.class.*
-""" % locals()))
-
-test.must_exist('test.jar')
-
-test.pass_test()
diff --git a/test/JAVAC.py b/test/JAVAC.py
deleted file mode 100644
index 779045f..0000000
--- a/test/JAVAC.py
+++ /dev/null
@@ -1,314 +0,0 @@
-#!/usr/bin/env python
-#
-# __COPYRIGHT__
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import os
-import string
-import sys
-import TestSCons
-
-python = TestSCons.python
-
-test = TestSCons.TestSCons()
-
-
-
-test.write('myjavac.py', r"""
-import sys
-args = sys.argv[1:]
-while args:
-    a = args[0]
-    if a == '-d':
-        args = args[1:]
-    elif a == '-sourcepath':
-        args = args[1:]
-    else:
-        break
-    args = args[1:]
-for file in args:
-    infile = open(file, 'rb')
-    outfile = open(file[:-5] + '.class', 'wb')
-    for l in infile.readlines():
-        if l[:9] != '/*javac*/':
-            outfile.write(l)
-sys.exit(0)
-""")
-
-test.write('SConstruct', """
-env = Environment(tools = ['javac'],
-                  JAVAC = r'%s myjavac.py')
-env.Java(target = '.', source = '.')
-""" % (python))
-
-test.write('test1.java', """\
-test1.java
-/*javac*/
-line 3
-""")
-
-test.run(arguments = '.', stderr = None)
-
-test.must_match('test1.class', "test1.java\nline 3\n")
-
-if os.path.normcase('.java') == os.path.normcase('.JAVA'):
-
-    test.write('SConstruct', """\
-env = Environment(tools = ['javac'],
-                  JAVAC = r'%s myjavac.py')
-env.Java(target = '.', source = '.')
-""" % python)
-
-    test.write('test2.JAVA', """\
-test2.JAVA
-/*javac*/
-line 3
-""")
-
-    test.run(arguments = '.', stderr = None)
-
-    test.must_match('test2.class', "test2.JAVA\nline 3\n")
-
-
-if test.detect_tool('javac'):
-    where_javac = test.detect('JAVAC', 'javac')
-else:
-    import SCons.Environment
-    env = SCons.Environment.Environment()
-    where_javac = env.WhereIs('javac', os.environ['PATH'])
-    if not where_javac:
-        where_javac = env.WhereIs('javac', '/usr/local/j2sdk1.3.1/bin')
-        if not where_javac:
-            print "Could not find Java, skipping test(s)."
-            test.pass_test(1)
-        
-
-
-test.write("wrapper.py", """\
-import os
-import string
-import sys
-open('%s', 'ab').write("wrapper.py %%s\\n" %% string.join(sys.argv[1:]))
-os.system(string.join(sys.argv[1:], " "))
-""" % string.replace(test.workpath('wrapper.out'), '\\', '\\\\'))
-
-test.write('SConstruct', """
-foo = Environment(tools = ['javac'],
-                  JAVAC = '%s')
-javac = foo.Dictionary('JAVAC')
-bar = foo.Copy(JAVAC = r'%s wrapper.py ' + javac)
-foo.Java(target = 'class1', source = 'com/sub/foo')
-bar.Java(target = 'class2', source = 'com/sub/bar')
-foo.Java(target = 'class3', source = ['src1', 'src2'])
-""" % (where_javac, python))
-
-test.subdir('com',
-            ['com', 'sub'],
-            ['com', 'sub', 'foo'],
-            ['com', 'sub', 'bar'],
-            'src1',
-            'src2')
-
-test.write(['com', 'sub', 'foo', 'Example1.java'], """\
-package com.sub.foo;
-
-public class Example1
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'foo', 'Example2.java'], """\
-package com.other;
-
-public class Example2
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'foo', 'Example3.java'], """\
-package com.sub.foo;
-
-public class Example3
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'bar', 'Example4.java'], """\
-package com.sub.bar;
-
-public class Example4
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'bar', 'Example5.java'], """\
-package com.other;
-
-public class Example5
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'bar', 'Example6.java'], """\
-package com.sub.bar;
-
-public class Example6
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['src1', 'Example7.java'], """\
-public class Example7
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-# Acid-test file for parsing inner Java classes, courtesy Chad Austin.
-test.write(['src2', 'Test.java'], """\
-class Empty {
-}
-
-interface Listener {
-  public void execute();
-}
-
-public
-class
-Test {
-  class Inner {
-    void go() {
-      use(new Listener() {
-        public void execute() {
-          System.out.println("In Inner");
-        }
-      });
-    }
-    String s1 = "class A";
-    String s2 = "new Listener() { }";
-    /* class B */
-    /* new Listener() { } */
-  }
-
-  public static void main(String[] args) {
-    new Test().run();
-  }
-
-  void run() {
-    use(new Listener() {
-      public void execute() {
-        use(new Listener( ) {
-          public void execute() {
-            System.out.println("Inside execute()");
-          }
-        });
-      }
-    });
-
-    new Inner().go();
-  }
-
-  void use(Listener l) {
-    l.execute();
-  }
-}
-
-class Private {
-  void run() {
-    new Listener() {
-      public void execute() {
-      }
-    };
-  }
-}
-""")
-
-test.run(arguments = '.')
-
-test.must_match('wrapper.out', "wrapper.py %s -d class2 -sourcepath com/sub/bar com/sub/bar/Example4.java com/sub/bar/Example5.java com/sub/bar/Example6.java\n" % where_javac)
-
-test.must_exist(test.workpath('class1', 'com', 'sub', 'foo', 'Example1.class'))
-test.must_exist(test.workpath('class1', 'com', 'other', 'Example2.class'))
-test.must_exist(test.workpath('class1', 'com', 'sub', 'foo', 'Example3.class'))
-
-test.must_exist(test.workpath('class2', 'com', 'sub', 'bar', 'Example4.class'))
-test.must_exist(test.workpath('class2', 'com', 'other', 'Example5.class'))
-test.must_exist(test.workpath('class2', 'com', 'sub', 'bar', 'Example6.class'))
-
-test.must_exist(test.workpath('class3', 'Example7.class'))
-
-test.must_exist(test.workpath('class3', 'Empty.class'))
-test.must_exist(test.workpath('class3', 'Listener.class'))
-test.must_exist(test.workpath('class3', 'Private.class'))
-test.must_exist(test.workpath('class3', 'Private$1.class'))
-test.must_exist(test.workpath('class3', 'Test.class'))
-test.must_exist(test.workpath('class3', 'Test$1.class'))
-test.must_exist(test.workpath('class3', 'Test$2.class'))
-test.must_exist(test.workpath('class3', 'Test$3.class'))
-test.must_exist(test.workpath('class3', 'Test$Inner.class'))
-
-test.up_to_date(arguments = '.')
-
-test.pass_test()
diff --git a/test/JAVACFLAGS.py b/test/JAVACFLAGS.py
deleted file mode 100644
index ef084cd..0000000
--- a/test/JAVACFLAGS.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env python
-#
-# __COPYRIGHT__
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import os.path
-
-import TestSCons
-
-test = TestSCons.TestSCons()
-
-if test.detect_tool('javac'):
-    where_javac = test.detect('JAVAC', 'javac')
-else:
-    import SCons.Environment
-    env = SCons.Environment.Environment()
-    where_javac = env.WhereIs('javac', os.environ['PATH'])
-    if not where_javac:
-        where_javac = env.WhereIs('javac', '/usr/local/j2sdk1.3.1/bin')
-        if not where_javac:
-            print "Could not find Java javac, skipping test(s)."
-            test.pass_test(1)
-
-test.subdir('src')
-
-test.write('SConstruct', """
-env = Environment(tools = ['javac'],
-                  JAVAC = '%(where_javac)s',
-                  JAVACFLAGS = '-O')
-env.Java(target = 'classes', source = 'src')
-""" % locals())
-
-test.write(['src', 'Example1.java'], """\
-package src;
-
-public class Example1
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.run(arguments = '.',
-         stdout = test.wrap_stdout("%(where_javac)s -O -d classes -sourcepath src src/Example1.java\n" % locals()))
-
-test.must_exist(['classes', 'src', 'Example1.class'])
-
-test.pass_test()
diff --git a/test/JAVAH.py b/test/JAVAH.py
deleted file mode 100644
index b70fde0..0000000
--- a/test/JAVAH.py
+++ /dev/null
@@ -1,315 +0,0 @@
-#!/usr/bin/env python
-#
-# __COPYRIGHT__
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import os
-import string
-import sys
-import TestSCons
-
-python = TestSCons.python
-
-test = TestSCons.TestSCons()
-
-test.write('myjavah.py', r"""
-import sys
-args = sys.argv[1:]
-while args:
-    a = args[0]
-    if a == '-d':
-        outdir = args[1]
-        args = args[1:]
-    elif a == '-o':
-        outfile = open(args[1], 'wb')
-        args = args[1:]
-    elif a == '-classpath':
-        args = args[1:]
-    elif a == '-sourcepath':
-        args = args[1:]
-    else:
-        break
-    args = args[1:]
-for file in args:
-    infile = open(file, 'rb')
-    for l in infile.readlines():
-        if l[:9] != '/*javah*/':
-            outfile.write(l)
-sys.exit(0)
-""")
-
-test.write('SConstruct', """
-env = Environment(tools = ['javah'],
-                  JAVAH = r'%s myjavah.py')
-env.JavaH(target = File('test1.h'), source = 'test1.java')
-""" % (python))
-
-test.write('test1.java', """\
-test1.java
-/*javah*/
-line 3
-""")
-
-test.run(arguments = '.', stderr = None)
-
-test.must_match('test1.h', "test1.java\nline 3\n")
-
-if os.path.normcase('.java') == os.path.normcase('.JAVA'):
-
-    test.write('SConstruct', """\
-env = Environment(tools = ['javah'],
-                  JAVAH = r'%s myjavah.py')
-env.JavaH(target = File('test2.h'), source = 'test2.JAVA')
-""" % python)
-
-    test.write('test2.JAVA', """\
-test2.JAVA
-/*javah*/
-line 3
-""")
-
-    test.run(arguments = '.', stderr = None)
-
-    test.must_match('test2.h', "test2.JAVA\nline 3\n")
-
-
-if test.detect_tool('javac'):
-    where_javac = test.detect('JAVAC', 'javac')
-else:
-    import SCons.Environment
-    env = SCons.Environment.Environment()
-    where_javac = env.WhereIs('javac', os.environ['PATH'])
-    if not where_javac:
-        where_javac = env.WhereIs('javac', '/usr/local/j2sdk1.3.1/bin')
-        if not where_javac:
-            print "Could not find Java javac, skipping test(s)."
-            test.pass_test(1)
-
-if test.detect_tool('javah'):
-    where_javah = test.detect('JAVAH', 'javah')
-else:
-    import SCons.Environment
-    env = SCons.Environment.Environment()
-    where_javah = env.WhereIs('javah', os.environ['PATH'])
-    if not where_javah:
-        where_javah = env.WhereIs('javah', '/usr/local/j2sdk1.3.1/bin')
-        if not where_javah:
-            print "Could not find Java javah, skipping test(s)."
-            test.pass_test(1)
-
-
-
-test.write("wrapper.py", """\
-import os
-import string
-import sys
-open('%s', 'ab').write("wrapper.py %%s\\n" %% string.join(sys.argv[1:]))
-os.system(string.join(sys.argv[1:], " "))
-""" % string.replace(test.workpath('wrapper.out'), '\\', '\\\\'))
-
-test.write('SConstruct', """
-foo = Environment(tools = ['javac', 'javah'],
-                  JAVAC = '%(where_javac)s',
-                  JAVAH = '%(where_javah)s')
-javah = foo.Dictionary('JAVAH')
-bar = foo.Copy(JAVAH = r'%(python)s wrapper.py ' + javah)
-foo.Java(target = 'class1', source = 'com/sub/foo')
-bar_classes = bar.Java(target = 'class2', source = 'com/sub/bar')
-foo_classes = foo.Java(target = 'class3', source = 'src')
-foo.JavaH(target = 'outdir1',
-          source = ['class1/com/sub/foo/Example1.class',
-                    'class1/com/other/Example2',
-                    'class1/com/sub/foo/Example3'],
-          JAVACLASSDIR = 'class1')
-bar.JavaH(target = 'outdir2', source = bar_classes)
-foo.JavaH(target = File('output.h'), source = foo_classes)
-foo.Install('class4/com/sub/foo', 'class1/com/sub/foo/Example1.class')
-foo.JavaH(target = 'outdir4',
-          source = ['class4/com/sub/foo/Example1.class'],
-          JAVACLASSDIR = 'class4')
-""" % locals())
-
-test.subdir('com',
-            ['com', 'sub'],
-            ['com', 'sub', 'foo'],
-            ['com', 'sub', 'bar'],
-            'src')
-
-test.write(['com', 'sub', 'foo', 'Example1.java'], """\
-package com.sub.foo;
-
-public class Example1
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'foo', 'Example2.java'], """\
-package com.other;
-
-public class Example2
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'foo', 'Example3.java'], """\
-package com.sub.foo;
-
-public class Example3
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'bar', 'Example4.java'], """\
-package com.sub.bar;
-
-public class Example4
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'bar', 'Example5.java'], """\
-package com.other;
-
-public class Example5
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['com', 'sub', 'bar', 'Example6.java'], """\
-package com.sub.bar;
-
-public class Example6
-{
-
-     public static void main(String[] args)
-     {
-
-     }
-
-}
-""")
-
-test.write(['src', 'Test.java'], """\
-class Empty {
-}
-
-interface Listener {
-  public void execute();
-}
-
-public
-class
-Test {
-  class Inner {
-    void go() {
-      use(new Listener() {
-        public void execute() {
-          System.out.println("In Inner");
-        }
-      });
-    }
-    String s1 = "class A";
-    String s2 = "new Listener() { }";
-    /* class B */
-    /* new Listener() { } */
-  }
-
-  public static void main(String[] args) {
-    new Test().run();
-  }
-
-  void run() {
-    use(new Listener() {
-      public void execute() {
-        use(new Listener( ) {
-          public void execute() {
-            System.out.println("Inside execute()");
-          }
-        });
-      }
-    });
-
-    new Inner().go();
-  }
-
-  void use(Listener l) {
-    l.execute();
-  }
-}
-
-class Private {
-  void run() {
-    new Listener() {
-      public void execute() {
-      }
-    };
-  }
-}
-""")
-
-test.run(arguments = '.')
-
-test.fail_test(test.read('wrapper.out') != "wrapper.py %(where_javah)s -d outdir2 -classpath class2 com.sub.bar.Example4 com.other.Example5 com.sub.bar.Example6\n" % locals())
-
-test.must_exist(['outdir1', 'com_sub_foo_Example1.h'])
-test.must_exist(['outdir1', 'com_other_Example2.h'])
-test.must_exist(['outdir1', 'com_sub_foo_Example3.h'])
-
-test.must_exist(['outdir2', 'com_sub_bar_Example4.h'])
-test.must_exist(['outdir2', 'com_other_Example5.h'])
-test.must_exist(['outdir2', 'com_sub_bar_Example6.h'])
-
-test.up_to_date(arguments = '.')
-
-test.pass_test()
diff --git a/test/Java/JAR.py b/test/Java/JAR.py
new file mode 100644
index 0000000..ea51213
--- /dev/null
+++ b/test/Java/JAR.py
@@ -0,0 +1,266 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import string
+import sys
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+test.write('myjar.py', r"""
+import sys
+args = sys.argv[1:]
+while args:
+    a = args[0]
+    if a == 'cf':
+        out = args[1]
+        args = args[1:]
+    else:
+        break
+    args = args[1:]
+outfile = open(out, 'wb')
+for file in args:
+    infile = open(file, 'rb')
+    for l in infile.readlines():
+        if l[:7] != '/*jar*/':
+            outfile.write(l)
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+env = Environment(tools = ['jar'],
+                  JAR = r'%s myjar.py')
+env.Jar(target = 'test1.jar', source = 'test1.class')
+""" % (python))
+
+test.write('test1.class', """\
+test1.class
+/*jar*/
+line 3
+""")
+
+test.run(arguments = '.', stderr = None)
+
+test.must_match('test1.jar', "test1.class\nline 3\n")
+
+if os.path.normcase('.class') == os.path.normcase('.CLASS'):
+
+    test.write('SConstruct', """
+env = Environment(tools = ['jar'],
+                  JAR = r'%s myjar.py')
+env.Jar(target = 'test2.jar', source = 'test2.CLASS')
+""" % (python))
+
+    test.write('test2.CLASS', """\
+test2.CLASS
+/*jar*/
+line 3
+""")
+
+    test.run(arguments = '.', stderr = None)
+
+    test.must_match('test2.jar', "test2.CLASS\nline 3\n")
+
+test.write('myjar2.py', r"""
+import sys
+import string
+f=open(sys.argv[2], 'wb')
+f.write(string.join(sys.argv[1:]))
+f.write("\n")
+f.close()
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+env = Environment(tools = ['jar'],
+                  JAR = r'%s myjar2.py',
+                  JARFLAGS='cvf')
+env.Jar(target = 'classes.jar', source = [ 'testdir/bar.class',
+                                           'foo.mf' ],
+        TESTDIR='testdir',
+        JARCHDIR='$TESTDIR')
+""" % (python))
+
+test.subdir('testdir')
+test.write([ 'testdir', 'bar.class' ], 'foo')
+test.write('foo.mf',
+           """Manifest-Version : 1.0
+           blah
+           blah
+           blah
+           """)
+test.run(arguments='classes.jar')
+test.must_match('classes.jar',
+                'cvfm classes.jar foo.mf -C testdir bar.class\n')
+
+if test.detect_tool('javac'):
+    where_javac = test.detect('JAVAC', 'javac')
+else:
+    import SCons.Environment
+    env = SCons.Environment.Environment()
+    where_javac = env.WhereIs('javac', os.environ['PATH'])
+    if not where_javac:
+        where_javac = env.WhereIs('javac', '/usr/local/j2sdk1.3.1/bin')
+        if not where_javac:
+            print "Could not find Java javac, skipping test(s)."
+            test.pass_test(1)
+
+if test.detect_tool('jar'):
+    where_jar = test.detect('JAR', 'jar')
+else:
+    import SCons.Environment
+    env = SCons.Environment.Environment()
+    where_jar = env.WhereIs('jar', os.environ['PATH'])
+    if not where_jar:
+        where_jar = env.WhereIs('jar', '/usr/local/j2sdk1.3.1/bin')
+        if not where_jar:
+            print "Could not find Java jar, skipping test(s)."
+            test.pass_test(1)
+
+
+test.write("wrapper.py", """\
+import os
+import string
+import sys
+open('%s', 'ab').write("wrapper.py %%s\\n" %% string.join(sys.argv[1:]))
+os.system(string.join(sys.argv[1:], " "))
+""" % string.replace(test.workpath('wrapper.out'), '\\', '\\\\'))
+
+test.write('SConstruct', """
+foo = Environment(tools = ['javac', 'jar'],
+                  JAVAC = '%(where_javac)s',
+                  JAR = '%(where_jar)s')
+jar = foo.Dictionary('JAR')
+bar = foo.Copy(JAR = r'%(python)s wrapper.py ' + jar)
+foo.Java(target = 'classes', source = 'com/sub/foo')
+bar.Java(target = 'classes', source = 'com/sub/bar')
+foo.Jar(target = 'foo', source = 'classes/com/sub/foo')
+bar.Jar(target = 'bar', source = 'classes/com/sub/bar')
+""" % locals())
+
+test.subdir('com',
+            ['com', 'sub'],
+            ['com', 'sub', 'foo'],
+            ['com', 'sub', 'bar'])
+
+test.write(['com', 'sub', 'foo', 'Example1.java'], """\
+package com.sub.foo;
+
+public class Example1
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'foo', 'Example2.java'], """\
+package com.sub.foo;
+
+public class Example2
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'foo', 'Example3.java'], """\
+package com.sub.foo;
+
+public class Example3
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'bar', 'Example4.java'], """\
+package com.sub.bar;
+
+public class Example4
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'bar', 'Example5.java'], """\
+package com.sub.bar;
+
+public class Example5
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'bar', 'Example6.java'], """\
+package com.sub.bar;
+
+public class Example6
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.run(arguments = '.')
+
+test.must_match('wrapper.out',
+                "wrapper.py %(where_jar)s cf bar.jar classes/com/sub/bar\n" % locals())
+
+test.must_exist('foo.jar')
+test.must_exist('bar.jar')
+
+test.up_to_date(arguments = '.')
+
+test.pass_test()
diff --git a/test/Java/JARCOM.py b/test/Java/JARCOM.py
new file mode 100644
index 0000000..0d7ebba
--- /dev/null
+++ b/test/Java/JARCOM.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test the ability to configure the $JARCOM construction variable.
+"""
+
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+
+
+test.write('myjar.py', r"""
+import sys
+outfile = open(sys.argv[1], 'wb')
+for f in sys.argv[2:]:
+    infile = open(f, 'rb')
+    for l in filter(lambda l: l != '/*jar*/\n', infile.readlines()):
+        outfile.write(l)
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+env = Environment(TOOLS = ['default', 'jar'],
+                  JARCOM = r'%(python)s myjar.py $TARGET $SOURCES')
+env.Jar(target = 'test1', source = ['file1.in', 'file2.in', 'file3.in'])
+""" % locals())
+
+test.write('file1.in', "file1.in\n/*jar*/\n")
+test.write('file2.in', "file2.in\n/*jar*/\n")
+test.write('file3.in', "file3.in\n/*jar*/\n")
+
+test.run()
+
+test.must_match('test1.jar', "file1.in\nfile2.in\nfile3.in\n")
+
+
+
+test.pass_test()
diff --git a/test/Java/JARCOMSTR.py b/test/Java/JARCOMSTR.py
new file mode 100644
index 0000000..aa8a6ad
--- /dev/null
+++ b/test/Java/JARCOMSTR.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that the $JARCOMSTR construction variable allows you to configure
+the jar output.
+"""
+
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+
+
+test.write('myjar.py', r"""
+import sys
+outfile = open(sys.argv[1], 'wb')
+for f in sys.argv[2:]:
+    infile = open(f, 'rb')
+    for l in filter(lambda l: l != '/*jar*/\n', infile.readlines()):
+        outfile.write(l)
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+env = Environment(TOOLS = ['default', 'jar'],
+                  JARCOM = r'%(python)s myjar.py $TARGET $SOURCES',
+                  JARCOMSTR = "Jar'ing up $TARGET from $SOURCES")
+env.Jar(target = 'test1', source = ['file1.in', 'file2.in', 'file3.in'])
+""" % locals())
+
+test.write('file1.in', "file1.in\n/*jar*/\n")
+test.write('file2.in', "file2.in\n/*jar*/\n")
+test.write('file3.in', "file3.in\n/*jar*/\n")
+
+test.run(stdout = test.wrap_stdout("""\
+Jar'ing up test1.jar from file1.in file2.in file3.in
+"""))
+
+test.must_match('test1.jar', "file1.in\nfile2.in\nfile3.in\n")
+
+
+
+test.pass_test()
diff --git a/test/Java/JARFLAGS.py b/test/Java/JARFLAGS.py
new file mode 100644
index 0000000..7e3669d
--- /dev/null
+++ b/test/Java/JARFLAGS.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os.path
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('src')
+
+if test.detect_tool('javac'):
+    where_javac = test.detect('JAVAC', 'javac')
+else:
+    import SCons.Environment
+    env = SCons.Environment.Environment()
+    where_javac = env.WhereIs('javac', os.environ['PATH'])
+    if not where_javac:
+        where_javac = env.WhereIs('javac', '/usr/local/j2sdk1.3.1/bin')
+        if not where_javac:
+            print "Could not find Java javac, skipping test(s)."
+            test.pass_test(1)
+
+if test.detect_tool('jar'):
+    where_jar = test.detect('JAR', 'jar')
+else:
+    import SCons.Environment
+    env = SCons.Environment.Environment()
+    where_jar = env.WhereIs('jar', os.environ['PATH'])
+    if not where_jar:
+        where_jar = env.WhereIs('jar', '/usr/local/j2sdk1.3.1/bin')
+        if not where_jar:
+            print "Could not find Java jar, skipping test(s)."
+            test.pass_test(1)
+
+test.write('SConstruct', """
+env = Environment(tools = ['javac', 'jar'],
+                  JAVAC = '%(where_javac)s',
+                  JAR = '%(where_jar)s',
+                  JARFLAGS = 'cvf')
+env['JARFLAGS'] = 'cvf'
+class_files = env.Java(target = 'classes', source = 'src')
+env.Jar(target = 'test.jar', source = class_files)
+""" % locals())
+
+test.write(['src', 'Example1.java'], """\
+package src;
+
+public class Example1
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.run(arguments = '.',
+         match=TestSCons.match_re_dotall,
+         stdout = test.wrap_stdout("""\
+%(where_javac)s -d classes -sourcepath src src/Example1\.java
+%(where_jar)s cvf test.jar classes/src/Example1\.class
+.*
+adding: classes/src/Example1\.class.*
+""" % locals()))
+
+test.must_exist('test.jar')
+
+test.pass_test()
diff --git a/test/Java/JAVAC.py b/test/Java/JAVAC.py
new file mode 100644
index 0000000..779045f
--- /dev/null
+++ b/test/Java/JAVAC.py
@@ -0,0 +1,314 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import string
+import sys
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+
+
+test.write('myjavac.py', r"""
+import sys
+args = sys.argv[1:]
+while args:
+    a = args[0]
+    if a == '-d':
+        args = args[1:]
+    elif a == '-sourcepath':
+        args = args[1:]
+    else:
+        break
+    args = args[1:]
+for file in args:
+    infile = open(file, 'rb')
+    outfile = open(file[:-5] + '.class', 'wb')
+    for l in infile.readlines():
+        if l[:9] != '/*javac*/':
+            outfile.write(l)
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+env = Environment(tools = ['javac'],
+                  JAVAC = r'%s myjavac.py')
+env.Java(target = '.', source = '.')
+""" % (python))
+
+test.write('test1.java', """\
+test1.java
+/*javac*/
+line 3
+""")
+
+test.run(arguments = '.', stderr = None)
+
+test.must_match('test1.class', "test1.java\nline 3\n")
+
+if os.path.normcase('.java') == os.path.normcase('.JAVA'):
+
+    test.write('SConstruct', """\
+env = Environment(tools = ['javac'],
+                  JAVAC = r'%s myjavac.py')
+env.Java(target = '.', source = '.')
+""" % python)
+
+    test.write('test2.JAVA', """\
+test2.JAVA
+/*javac*/
+line 3
+""")
+
+    test.run(arguments = '.', stderr = None)
+
+    test.must_match('test2.class', "test2.JAVA\nline 3\n")
+
+
+if test.detect_tool('javac'):
+    where_javac = test.detect('JAVAC', 'javac')
+else:
+    import SCons.Environment
+    env = SCons.Environment.Environment()
+    where_javac = env.WhereIs('javac', os.environ['PATH'])
+    if not where_javac:
+        where_javac = env.WhereIs('javac', '/usr/local/j2sdk1.3.1/bin')
+        if not where_javac:
+            print "Could not find Java, skipping test(s)."
+            test.pass_test(1)
+        
+
+
+test.write("wrapper.py", """\
+import os
+import string
+import sys
+open('%s', 'ab').write("wrapper.py %%s\\n" %% string.join(sys.argv[1:]))
+os.system(string.join(sys.argv[1:], " "))
+""" % string.replace(test.workpath('wrapper.out'), '\\', '\\\\'))
+
+test.write('SConstruct', """
+foo = Environment(tools = ['javac'],
+                  JAVAC = '%s')
+javac = foo.Dictionary('JAVAC')
+bar = foo.Copy(JAVAC = r'%s wrapper.py ' + javac)
+foo.Java(target = 'class1', source = 'com/sub/foo')
+bar.Java(target = 'class2', source = 'com/sub/bar')
+foo.Java(target = 'class3', source = ['src1', 'src2'])
+""" % (where_javac, python))
+
+test.subdir('com',
+            ['com', 'sub'],
+            ['com', 'sub', 'foo'],
+            ['com', 'sub', 'bar'],
+            'src1',
+            'src2')
+
+test.write(['com', 'sub', 'foo', 'Example1.java'], """\
+package com.sub.foo;
+
+public class Example1
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'foo', 'Example2.java'], """\
+package com.other;
+
+public class Example2
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'foo', 'Example3.java'], """\
+package com.sub.foo;
+
+public class Example3
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'bar', 'Example4.java'], """\
+package com.sub.bar;
+
+public class Example4
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'bar', 'Example5.java'], """\
+package com.other;
+
+public class Example5
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'bar', 'Example6.java'], """\
+package com.sub.bar;
+
+public class Example6
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['src1', 'Example7.java'], """\
+public class Example7
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+# Acid-test file for parsing inner Java classes, courtesy Chad Austin.
+test.write(['src2', 'Test.java'], """\
+class Empty {
+}
+
+interface Listener {
+  public void execute();
+}
+
+public
+class
+Test {
+  class Inner {
+    void go() {
+      use(new Listener() {
+        public void execute() {
+          System.out.println("In Inner");
+        }
+      });
+    }
+    String s1 = "class A";
+    String s2 = "new Listener() { }";
+    /* class B */
+    /* new Listener() { } */
+  }
+
+  public static void main(String[] args) {
+    new Test().run();
+  }
+
+  void run() {
+    use(new Listener() {
+      public void execute() {
+        use(new Listener( ) {
+          public void execute() {
+            System.out.println("Inside execute()");
+          }
+        });
+      }
+    });
+
+    new Inner().go();
+  }
+
+  void use(Listener l) {
+    l.execute();
+  }
+}
+
+class Private {
+  void run() {
+    new Listener() {
+      public void execute() {
+      }
+    };
+  }
+}
+""")
+
+test.run(arguments = '.')
+
+test.must_match('wrapper.out', "wrapper.py %s -d class2 -sourcepath com/sub/bar com/sub/bar/Example4.java com/sub/bar/Example5.java com/sub/bar/Example6.java\n" % where_javac)
+
+test.must_exist(test.workpath('class1', 'com', 'sub', 'foo', 'Example1.class'))
+test.must_exist(test.workpath('class1', 'com', 'other', 'Example2.class'))
+test.must_exist(test.workpath('class1', 'com', 'sub', 'foo', 'Example3.class'))
+
+test.must_exist(test.workpath('class2', 'com', 'sub', 'bar', 'Example4.class'))
+test.must_exist(test.workpath('class2', 'com', 'other', 'Example5.class'))
+test.must_exist(test.workpath('class2', 'com', 'sub', 'bar', 'Example6.class'))
+
+test.must_exist(test.workpath('class3', 'Example7.class'))
+
+test.must_exist(test.workpath('class3', 'Empty.class'))
+test.must_exist(test.workpath('class3', 'Listener.class'))
+test.must_exist(test.workpath('class3', 'Private.class'))
+test.must_exist(test.workpath('class3', 'Private$1.class'))
+test.must_exist(test.workpath('class3', 'Test.class'))
+test.must_exist(test.workpath('class3', 'Test$1.class'))
+test.must_exist(test.workpath('class3', 'Test$2.class'))
+test.must_exist(test.workpath('class3', 'Test$3.class'))
+test.must_exist(test.workpath('class3', 'Test$Inner.class'))
+
+test.up_to_date(arguments = '.')
+
+test.pass_test()
diff --git a/test/Java/JAVACCOM.py b/test/Java/JAVACCOM.py
new file mode 100644
index 0000000..171649c
--- /dev/null
+++ b/test/Java/JAVACCOM.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test the ability to configure the $JAVACCOM construction variable.
+"""
+
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+test.subdir('src')
+
+
+
+test.write('myjavac.py', r"""
+import sys
+outfile = open(sys.argv[1], 'wb')
+for f in sys.argv[2:]:
+    infile = open(f, 'rb')
+    for l in filter(lambda l: l != '/*javac*/\n', infile.readlines()):
+        outfile.write(l)
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+env = Environment(TOOLS = ['default', 'javac'],
+                  JAVACCOM = r'%(python)s myjavac.py $TARGET $SOURCES')
+env.Java(target = 'classes', source = 'src')
+""" % locals())
+
+test.write(['src', 'file1.java'], "file1.java\n/*javac*/\n")
+test.write(['src', 'file2.java'], "file2.java\n/*javac*/\n")
+test.write(['src', 'file3.java'], "file3.java\n/*javac*/\n")
+
+test.run()
+
+test.must_match(['classes', 'src', 'file1.class'],
+                "file1.java\nfile2.java\nfile3.java\n")
+
+
+
+test.pass_test()
diff --git a/test/Java/JAVACCOMSTR.py b/test/Java/JAVACCOMSTR.py
new file mode 100644
index 0000000..306ae57
--- /dev/null
+++ b/test/Java/JAVACCOMSTR.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that the $JAVACCOMSTR construction variable allows you to configure
+the javac output.
+"""
+
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+test.subdir('src')
+
+
+
+test.write('myjavac.py', r"""
+import sys
+outfile = open(sys.argv[1], 'wb')
+for f in sys.argv[2:]:
+    infile = open(f, 'rb')
+    for l in filter(lambda l: l != '/*javac*/\n', infile.readlines()):
+        outfile.write(l)
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+env = Environment(TOOLS = ['default', 'javac'],
+                  JAVACCOM = r'%(python)s myjavac.py $TARGET $SOURCES',
+                  JAVACCOMSTR = "Compiling class(es) $TARGET from $SOURCES")
+env.Java(target = 'classes', source = 'src')
+""" % locals())
+
+test.write(['src', 'file1.java'], "file1.java\n/*javac*/\n")
+test.write(['src', 'file2.java'], "file2.java\n/*javac*/\n")
+test.write(['src', 'file3.java'], "file3.java\n/*javac*/\n")
+
+test.run(stdout = test.wrap_stdout("""\
+Compiling class(es) classes/src/file1.class from src/file1.java src/file2.java src/file3.java
+"""))
+
+test.must_match(['classes', 'src', 'file1.class'],
+                "file1.java\nfile2.java\nfile3.java\n")
+
+
+
+test.pass_test()
diff --git a/test/Java/JAVACFLAGS.py b/test/Java/JAVACFLAGS.py
new file mode 100644
index 0000000..ef084cd
--- /dev/null
+++ b/test/Java/JAVACFLAGS.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os.path
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+if test.detect_tool('javac'):
+    where_javac = test.detect('JAVAC', 'javac')
+else:
+    import SCons.Environment
+    env = SCons.Environment.Environment()
+    where_javac = env.WhereIs('javac', os.environ['PATH'])
+    if not where_javac:
+        where_javac = env.WhereIs('javac', '/usr/local/j2sdk1.3.1/bin')
+        if not where_javac:
+            print "Could not find Java javac, skipping test(s)."
+            test.pass_test(1)
+
+test.subdir('src')
+
+test.write('SConstruct', """
+env = Environment(tools = ['javac'],
+                  JAVAC = '%(where_javac)s',
+                  JAVACFLAGS = '-O')
+env.Java(target = 'classes', source = 'src')
+""" % locals())
+
+test.write(['src', 'Example1.java'], """\
+package src;
+
+public class Example1
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.run(arguments = '.',
+         stdout = test.wrap_stdout("%(where_javac)s -O -d classes -sourcepath src src/Example1.java\n" % locals()))
+
+test.must_exist(['classes', 'src', 'Example1.class'])
+
+test.pass_test()
diff --git a/test/Java/JAVAH.py b/test/Java/JAVAH.py
new file mode 100644
index 0000000..b70fde0
--- /dev/null
+++ b/test/Java/JAVAH.py
@@ -0,0 +1,315 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import string
+import sys
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+test.write('myjavah.py', r"""
+import sys
+args = sys.argv[1:]
+while args:
+    a = args[0]
+    if a == '-d':
+        outdir = args[1]
+        args = args[1:]
+    elif a == '-o':
+        outfile = open(args[1], 'wb')
+        args = args[1:]
+    elif a == '-classpath':
+        args = args[1:]
+    elif a == '-sourcepath':
+        args = args[1:]
+    else:
+        break
+    args = args[1:]
+for file in args:
+    infile = open(file, 'rb')
+    for l in infile.readlines():
+        if l[:9] != '/*javah*/':
+            outfile.write(l)
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+env = Environment(tools = ['javah'],
+                  JAVAH = r'%s myjavah.py')
+env.JavaH(target = File('test1.h'), source = 'test1.java')
+""" % (python))
+
+test.write('test1.java', """\
+test1.java
+/*javah*/
+line 3
+""")
+
+test.run(arguments = '.', stderr = None)
+
+test.must_match('test1.h', "test1.java\nline 3\n")
+
+if os.path.normcase('.java') == os.path.normcase('.JAVA'):
+
+    test.write('SConstruct', """\
+env = Environment(tools = ['javah'],
+                  JAVAH = r'%s myjavah.py')
+env.JavaH(target = File('test2.h'), source = 'test2.JAVA')
+""" % python)
+
+    test.write('test2.JAVA', """\
+test2.JAVA
+/*javah*/
+line 3
+""")
+
+    test.run(arguments = '.', stderr = None)
+
+    test.must_match('test2.h', "test2.JAVA\nline 3\n")
+
+
+if test.detect_tool('javac'):
+    where_javac = test.detect('JAVAC', 'javac')
+else:
+    import SCons.Environment
+    env = SCons.Environment.Environment()
+    where_javac = env.WhereIs('javac', os.environ['PATH'])
+    if not where_javac:
+        where_javac = env.WhereIs('javac', '/usr/local/j2sdk1.3.1/bin')
+        if not where_javac:
+            print "Could not find Java javac, skipping test(s)."
+            test.pass_test(1)
+
+if test.detect_tool('javah'):
+    where_javah = test.detect('JAVAH', 'javah')
+else:
+    import SCons.Environment
+    env = SCons.Environment.Environment()
+    where_javah = env.WhereIs('javah', os.environ['PATH'])
+    if not where_javah:
+        where_javah = env.WhereIs('javah', '/usr/local/j2sdk1.3.1/bin')
+        if not where_javah:
+            print "Could not find Java javah, skipping test(s)."
+            test.pass_test(1)
+
+
+
+test.write("wrapper.py", """\
+import os
+import string
+import sys
+open('%s', 'ab').write("wrapper.py %%s\\n" %% string.join(sys.argv[1:]))
+os.system(string.join(sys.argv[1:], " "))
+""" % string.replace(test.workpath('wrapper.out'), '\\', '\\\\'))
+
+test.write('SConstruct', """
+foo = Environment(tools = ['javac', 'javah'],
+                  JAVAC = '%(where_javac)s',
+                  JAVAH = '%(where_javah)s')
+javah = foo.Dictionary('JAVAH')
+bar = foo.Copy(JAVAH = r'%(python)s wrapper.py ' + javah)
+foo.Java(target = 'class1', source = 'com/sub/foo')
+bar_classes = bar.Java(target = 'class2', source = 'com/sub/bar')
+foo_classes = foo.Java(target = 'class3', source = 'src')
+foo.JavaH(target = 'outdir1',
+          source = ['class1/com/sub/foo/Example1.class',
+                    'class1/com/other/Example2',
+                    'class1/com/sub/foo/Example3'],
+          JAVACLASSDIR = 'class1')
+bar.JavaH(target = 'outdir2', source = bar_classes)
+foo.JavaH(target = File('output.h'), source = foo_classes)
+foo.Install('class4/com/sub/foo', 'class1/com/sub/foo/Example1.class')
+foo.JavaH(target = 'outdir4',
+          source = ['class4/com/sub/foo/Example1.class'],
+          JAVACLASSDIR = 'class4')
+""" % locals())
+
+test.subdir('com',
+            ['com', 'sub'],
+            ['com', 'sub', 'foo'],
+            ['com', 'sub', 'bar'],
+            'src')
+
+test.write(['com', 'sub', 'foo', 'Example1.java'], """\
+package com.sub.foo;
+
+public class Example1
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'foo', 'Example2.java'], """\
+package com.other;
+
+public class Example2
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'foo', 'Example3.java'], """\
+package com.sub.foo;
+
+public class Example3
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'bar', 'Example4.java'], """\
+package com.sub.bar;
+
+public class Example4
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'bar', 'Example5.java'], """\
+package com.other;
+
+public class Example5
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['com', 'sub', 'bar', 'Example6.java'], """\
+package com.sub.bar;
+
+public class Example6
+{
+
+     public static void main(String[] args)
+     {
+
+     }
+
+}
+""")
+
+test.write(['src', 'Test.java'], """\
+class Empty {
+}
+
+interface Listener {
+  public void execute();
+}
+
+public
+class
+Test {
+  class Inner {
+    void go() {
+      use(new Listener() {
+        public void execute() {
+          System.out.println("In Inner");
+        }
+      });
+    }
+    String s1 = "class A";
+    String s2 = "new Listener() { }";
+    /* class B */
+    /* new Listener() { } */
+  }
+
+  public static void main(String[] args) {
+    new Test().run();
+  }
+
+  void run() {
+    use(new Listener() {
+      public void execute() {
+        use(new Listener( ) {
+          public void execute() {
+            System.out.println("Inside execute()");
+          }
+        });
+      }
+    });
+
+    new Inner().go();
+  }
+
+  void use(Listener l) {
+    l.execute();
+  }
+}
+
+class Private {
+  void run() {
+    new Listener() {
+      public void execute() {
+      }
+    };
+  }
+}
+""")
+
+test.run(arguments = '.')
+
+test.fail_test(test.read('wrapper.out') != "wrapper.py %(where_javah)s -d outdir2 -classpath class2 com.sub.bar.Example4 com.other.Example5 com.sub.bar.Example6\n" % locals())
+
+test.must_exist(['outdir1', 'com_sub_foo_Example1.h'])
+test.must_exist(['outdir1', 'com_other_Example2.h'])
+test.must_exist(['outdir1', 'com_sub_foo_Example3.h'])
+
+test.must_exist(['outdir2', 'com_sub_bar_Example4.h'])
+test.must_exist(['outdir2', 'com_other_Example5.h'])
+test.must_exist(['outdir2', 'com_sub_bar_Example6.h'])
+
+test.up_to_date(arguments = '.')
+
+test.pass_test()
diff --git a/test/Java/JAVAHCOM.py b/test/Java/JAVAHCOM.py
new file mode 100644
index 0000000..1cc4208
--- /dev/null
+++ b/test/Java/JAVAHCOM.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test the ability to configure the $JAVAHCOM construction variable.
+"""
+
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+
+
+test.write('myjavah.py', r"""
+import sys
+outfile = open(sys.argv[1], 'wb')
+for f in sys.argv[2:]:
+    infile = open(f, 'rb')
+    for l in filter(lambda l: l != '/*javah*/\n', infile.readlines()):
+        outfile.write(l)
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+env = Environment(TOOLS = ['default', 'javah'],
+                  JAVAHCOM = r'%(python)s myjavah.py $TARGET $SOURCES')
+env.JavaH(target = 'out', source = 'file1.class')
+env.JavaH(target = 'out', source = 'file2.class')
+env.JavaH(target = 'out', source = 'file3.class')
+""" % locals())
+
+test.write('file1.class', "file1.class\n/*javah*/\n")
+test.write('file2.class', "file2.class\n/*javah*/\n")
+test.write('file3.class', "file3.class\n/*javah*/\n")
+
+test.run()
+
+test.must_match(['out', 'file1.h'], "file1.class\n")
+test.must_match(['out', 'file2.h'], "file2.class\n")
+test.must_match(['out', 'file3.h'], "file3.class\n")
+
+
+
+test.pass_test()
diff --git a/test/Java/JAVAHCOMSTR.py b/test/Java/JAVAHCOMSTR.py
new file mode 100644
index 0000000..2a14e1c
--- /dev/null
+++ b/test/Java/JAVAHCOMSTR.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that the $JAVAHCOMSTR construction variable allows you to configure
+the javah output.
+"""
+
+import os.path
+
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+test.subdir('src')
+
+
+
+out_file1_h = os.path.join('out', 'file1.h')
+out_file2_h = os.path.join('out', 'file2.h')
+out_file3_h = os.path.join('out', 'file3.h')
+
+
+
+test.write('myjavah.py', r"""
+import sys
+outfile = open(sys.argv[1], 'wb')
+for f in sys.argv[2:]:
+    infile = open(f, 'rb')
+    for l in filter(lambda l: l != '/*javah*/\n', infile.readlines()):
+        outfile.write(l)
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+env = Environment(TOOLS = ['default', 'javah'],
+                  JAVAHCOM = r'%(python)s myjavah.py $TARGET $SOURCES',
+                  JAVAHCOMSTR = 'Building javah $TARGET from $SOURCES')
+env.JavaH(target = 'out', source = 'file1.class')
+env.JavaH(target = 'out', source = 'file2.class')
+env.JavaH(target = 'out', source = 'file3.class')
+""" % locals())
+
+test.write('file1.class', "file1.class\n/*javah*/\n")
+test.write('file2.class', "file2.class\n/*javah*/\n")
+test.write('file3.class', "file3.class\n/*javah*/\n")
+
+test.run(stdout = test.wrap_stdout("""\
+Building javah %(out_file1_h)s from file1.class
+Building javah %(out_file2_h)s from file2.class
+Building javah %(out_file3_h)s from file3.class
+""" % locals()))
+
+test.must_match(['out', 'file1.h'], "file1.class\n")
+test.must_match(['out', 'file2.h'], "file2.class\n")
+test.must_match(['out', 'file3.h'], "file3.class\n")
+
+
+
+test.pass_test()
diff --git a/test/Java/RMIC.py b/test/Java/RMIC.py
new file mode 100644
index 0000000..8f3623c
--- /dev/null
+++ b/test/Java/RMIC.py
@@ -0,0 +1,325 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import string
+import sys
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+test.write('myrmic.py', r"""
+import os.path
+import sys
+args = sys.argv[1:]
+while args:
+    a = args[0]
+    if a == '-d':
+        outdir = args[1]
+        args = args[1:]
+    elif a == '-classpath':
+        args = args[1:]
+    elif a == '-sourcepath':
+        args = args[1:]
+    else:
+        break
+    args = args[1:]
+for file in args:
+    infile = open(file, 'rb')
+    outfile = open(os.path.join(outdir, file[:-5] + '.class'), 'wb')
+    for l in infile.readlines():
+        if l[:8] != '/*rmic*/':
+            outfile.write(l)
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+env = Environment(tools = ['rmic'],
+                  RMIC = r'%s myrmic.py')
+env.RMIC(target = 'outdir', source = 'test1.java')
+""" % (python))
+
+test.write('test1.java', """\
+test1.java
+/*rmic*/
+line 3
+""")
+
+test.run(arguments = '.', stderr = None)
+
+test.fail_test(test.read(['outdir', 'test1.class']) != "test1.java\nline 3\n")
+
+if os.path.normcase('.java') == os.path.normcase('.JAVA'):
+
+    test.write('SConstruct', """\
+env = Environment(tools = ['rmic'],
+                  RMIC = r'%s myrmic.py')
+env.RMIC(target = 'outdir', source = 'test2.JAVA')
+""" % python)
+
+    test.write('test2.JAVA', """\
+test2.JAVA
+/*rmic*/
+line 3
+""")
+
+    test.run(arguments = '.', stderr = None)
+
+    test.fail_test(test.read(['outdir', 'test2.class']) != "test2.JAVA\nline 3\n")
+
+
+if not os.path.exists('/usr/local/j2sdk1.3.1/bin/rmic'):
+    print "Could not find Java, skipping test(s)."
+    test.pass_test(1)
+
+
+
+test.write("wrapper.py", """\
+import os
+import string
+import sys
+open('%s', 'ab').write("wrapper.py %%s\\n" %% string.join(sys.argv[1:]))
+os.system(string.join(sys.argv[1:], " "))
+""" % string.replace(test.workpath('wrapper.out'), '\\', '\\\\'))
+
+test.write('SConstruct', """
+import string
+foo = Environment(tools = ['javac', 'rmic'],
+                  JAVAC = '/usr/local/j2sdk1.3.1/bin/javac',
+                  RMIC = '/usr/local/j2sdk1.3.1/bin/rmic')
+foo.Java(target = 'class1', source = 'com/sub/foo')
+foo.RMIC(target = 'outdir1',
+          source = ['class1/com/sub/foo/Example1.class',
+                    'class1/com/sub/foo/Example2'],
+          JAVACLASSDIR = 'class1')
+
+rmic = foo.Dictionary('RMIC')
+bar = foo.Copy(RMIC = r'%s wrapper.py ' + rmic)
+bar_classes = bar.Java(target = 'class2', source = 'com/sub/bar')
+# XXX This is kind of a Python brute-force way to do what Ant
+# does with its "excludes" attribute.  We should probably find
+# a similar friendlier way to do this.
+bar_classes = filter(lambda c: string.find(str(c), 'Hello') == -1, bar_classes)
+bar.RMIC(target = Dir('outdir2'), source = bar_classes)
+""" % python)
+
+test.subdir('com',
+            ['com', 'other'],
+            ['com', 'sub'],
+            ['com', 'sub', 'foo'],
+            ['com', 'sub', 'bar'],
+            'src3a',
+            'src3b')
+
+test.write(['com', 'sub', 'foo', 'Hello.java'], """\
+package com.sub.foo;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface Hello extends Remote {
+    String sayHello() throws RemoteException;
+}
+""")
+
+test.write(['com', 'sub', 'foo', 'Example1.java'], """\
+package com.sub.foo;
+
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.rmi.RMISecurityManager;
+import java.rmi.server.UnicastRemoteObject;
+
+public class Example1 extends UnicastRemoteObject implements Hello {
+
+    public Example1() throws RemoteException {
+        super();
+    }
+
+    public String sayHello() {
+        return "Hello World!";
+    }
+
+    public static void main(String args[]) {
+        if (System.getSecurityManager() == null) {
+            System.setSecurityManager(new RMISecurityManager());
+        }
+
+        try {
+            Example1 obj = new Example1();
+
+            Naming.rebind("//myhost/HelloServer", obj);
+
+            System.out.println("HelloServer bound in registry");
+        } catch (Exception e) {
+            System.out.println("Example1 err: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+}
+""")
+
+test.write(['com', 'sub', 'foo', 'Example2.java'], """\
+package com.sub.foo;
+
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.rmi.RMISecurityManager;
+import java.rmi.server.UnicastRemoteObject;
+
+public class Example2 extends UnicastRemoteObject implements Hello {
+
+    public Example2() throws RemoteException {
+        super();
+    }
+
+    public String sayHello() {
+        return "Hello World!";
+    }
+
+    public static void main(String args[]) {
+        if (System.getSecurityManager() == null) {
+            System.setSecurityManager(new RMISecurityManager());
+        }
+
+        try {
+            Example2 obj = new Example2();
+
+            Naming.rebind("//myhost/HelloServer", obj);
+
+            System.out.println("HelloServer bound in registry");
+        } catch (Exception e) {
+            System.out.println("Example2 err: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+}
+""")
+
+test.write(['com', 'sub', 'bar', 'Hello.java'], """\
+package com.sub.bar;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface Hello extends Remote {
+    String sayHello() throws RemoteException;
+}
+""")
+
+test.write(['com', 'sub', 'bar', 'Example3.java'], """\
+package com.sub.bar;
+
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.rmi.RMISecurityManager;
+import java.rmi.server.UnicastRemoteObject;
+
+public class Example3 extends UnicastRemoteObject implements Hello {
+
+    public Example3() throws RemoteException {
+        super();
+    }
+
+    public String sayHello() {
+        return "Hello World!";
+    }
+
+    public static void main(String args[]) {
+        if (System.getSecurityManager() == null) {
+            System.setSecurityManager(new RMISecurityManager());
+        }
+
+        try {
+            Example3 obj = new Example3();
+
+            Naming.rebind("//myhost/HelloServer", obj);
+
+            System.out.println("HelloServer bound in registry");
+        } catch (Exception e) {
+            System.out.println("Example3 err: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+}
+""")
+
+test.write(['com', 'sub', 'bar', 'Example4.java'], """\
+package com.sub.bar;
+
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.rmi.RMISecurityManager;
+import java.rmi.server.UnicastRemoteObject;
+
+public class Example4 extends UnicastRemoteObject implements Hello {
+
+    public Example4() throws RemoteException {
+        super();
+    }
+
+    public String sayHello() {
+        return "Hello World!";
+    }
+
+    public static void main(String args[]) {
+        if (System.getSecurityManager() == null) {
+            System.setSecurityManager(new RMISecurityManager());
+        }
+
+        try {
+            Example4 obj = new Example4();
+
+            Naming.rebind("//myhost/HelloServer", obj);
+
+            System.out.println("HelloServer bound in registry");
+        } catch (Exception e) {
+            System.out.println("Example4 err: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+}
+""")
+
+test.run(arguments = '.')
+
+test.fail_test(test.read('wrapper.out') != "wrapper.py /usr/local/j2sdk1.3.1/bin/rmic -d outdir2 -classpath class2 com.sub.bar.Example3 com.sub.bar.Example4\n")
+
+test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Skel.class')))
+test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Stub.class')))
+test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Skel.class')))
+test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Stub.class')))
+
+test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Skel.class')))
+test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Stub.class')))
+test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Skel.class')))
+test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Stub.class')))
+
+test.up_to_date(arguments = '.')
+
+test.pass_test()
diff --git a/test/Java/RMICCOM.py b/test/Java/RMICCOM.py
new file mode 100644
index 0000000..109c22e
--- /dev/null
+++ b/test/Java/RMICCOM.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test the ability to configure the $RMICCOM construction variable.
+"""
+
+import os.path
+
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+test.subdir('src')
+
+
+
+out_file1 = os.path.join('out', 'file1', 'class_Skel.class')
+out_file2 = os.path.join('out', 'file2', 'class_Skel.class')
+out_file3 = os.path.join('out', 'file3', 'class_Skel.class')
+
+
+
+test.write('myrmic.py', r"""
+import sys
+outfile = open(sys.argv[1], 'wb')
+for f in sys.argv[2:]:
+    infile = open(f, 'rb')
+    for l in filter(lambda l: l != '/*rmic*/\n', infile.readlines()):
+        outfile.write(l)
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+env = Environment(TOOLS = ['default', 'rmic'],
+                  RMICCOM = r'%(python)s myrmic.py $TARGET $SOURCES')
+env.RMIC(target = 'out', source = 'file1.class')
+env.RMIC(target = 'out', source = 'file2.class')
+env.RMIC(target = 'out', source = 'file3.class')
+""" % locals())
+
+test.write('file1.class', "file1.class\n/*rmic*/\n")
+test.write('file2.class', "file2.class\n/*rmic*/\n")
+test.write('file3.class', "file3.class\n/*rmic*/\n")
+
+test.run()
+
+test.must_match(out_file1, "file1.class\n")
+test.must_match(out_file2, "file2.class\n")
+test.must_match(out_file3, "file3.class\n")
+
+
+
+test.pass_test()
diff --git a/test/Java/RMICCOMSTR.py b/test/Java/RMICCOMSTR.py
new file mode 100644
index 0000000..1bcf300
--- /dev/null
+++ b/test/Java/RMICCOMSTR.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that the $RMICCOMSTR construction variable allows you to configure
+the rmic output.
+"""
+
+import os.path
+
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+test.subdir('src')
+
+
+
+out_file1 = os.path.join('out', 'file1', 'class_Skel.class')
+out_file2 = os.path.join('out', 'file2', 'class_Skel.class')
+out_file3 = os.path.join('out', 'file3', 'class_Skel.class')
+
+
+
+test.write('myrmic.py', r"""
+import sys
+outfile = open(sys.argv[1], 'wb')
+for f in sys.argv[2:]:
+    infile = open(f, 'rb')
+    for l in filter(lambda l: l != '/*rmic*/\n', infile.readlines()):
+        outfile.write(l)
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+env = Environment(TOOLS = ['default', 'rmic'],
+                  RMICCOM = r'%(python)s myrmic.py $TARGET $SOURCES',
+                  RMICCOMSTR = 'Building rmic $TARGET from $SOURCES')
+env.RMIC(target = 'out', source = 'file1.class')
+env.RMIC(target = 'out', source = 'file2.class')
+env.RMIC(target = 'out', source = 'file3.class')
+""" % locals())
+
+test.write('file1.class', "file1.class\n/*rmic*/\n")
+test.write('file2.class', "file2.class\n/*rmic*/\n")
+test.write('file3.class', "file3.class\n/*rmic*/\n")
+
+test.run(stdout = test.wrap_stdout("""\
+Building rmic %(out_file1)s from file1.class
+Building rmic %(out_file2)s from file2.class
+Building rmic %(out_file3)s from file3.class
+""" % locals()))
+
+test.must_match(out_file1, "file1.class\n")
+test.must_match(out_file2, "file2.class\n")
+test.must_match(out_file3, "file3.class\n")
+
+
+
+test.pass_test()
diff --git a/test/RMIC.py b/test/RMIC.py
deleted file mode 100644
index 8f3623c..0000000
--- a/test/RMIC.py
+++ /dev/null
@@ -1,325 +0,0 @@
-#!/usr/bin/env python
-#
-# __COPYRIGHT__
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import os
-import string
-import sys
-import TestSCons
-
-python = TestSCons.python
-
-test = TestSCons.TestSCons()
-
-test.write('myrmic.py', r"""
-import os.path
-import sys
-args = sys.argv[1:]
-while args:
-    a = args[0]
-    if a == '-d':
-        outdir = args[1]
-        args = args[1:]
-    elif a == '-classpath':
-        args = args[1:]
-    elif a == '-sourcepath':
-        args = args[1:]
-    else:
-        break
-    args = args[1:]
-for file in args:
-    infile = open(file, 'rb')
-    outfile = open(os.path.join(outdir, file[:-5] + '.class'), 'wb')
-    for l in infile.readlines():
-        if l[:8] != '/*rmic*/':
-            outfile.write(l)
-sys.exit(0)
-""")
-
-test.write('SConstruct', """
-env = Environment(tools = ['rmic'],
-                  RMIC = r'%s myrmic.py')
-env.RMIC(target = 'outdir', source = 'test1.java')
-""" % (python))
-
-test.write('test1.java', """\
-test1.java
-/*rmic*/
-line 3
-""")
-
-test.run(arguments = '.', stderr = None)
-
-test.fail_test(test.read(['outdir', 'test1.class']) != "test1.java\nline 3\n")
-
-if os.path.normcase('.java') == os.path.normcase('.JAVA'):
-
-    test.write('SConstruct', """\
-env = Environment(tools = ['rmic'],
-                  RMIC = r'%s myrmic.py')
-env.RMIC(target = 'outdir', source = 'test2.JAVA')
-""" % python)
-
-    test.write('test2.JAVA', """\
-test2.JAVA
-/*rmic*/
-line 3
-""")
-
-    test.run(arguments = '.', stderr = None)
-
-    test.fail_test(test.read(['outdir', 'test2.class']) != "test2.JAVA\nline 3\n")
-
-
-if not os.path.exists('/usr/local/j2sdk1.3.1/bin/rmic'):
-    print "Could not find Java, skipping test(s)."
-    test.pass_test(1)
-
-
-
-test.write("wrapper.py", """\
-import os
-import string
-import sys
-open('%s', 'ab').write("wrapper.py %%s\\n" %% string.join(sys.argv[1:]))
-os.system(string.join(sys.argv[1:], " "))
-""" % string.replace(test.workpath('wrapper.out'), '\\', '\\\\'))
-
-test.write('SConstruct', """
-import string
-foo = Environment(tools = ['javac', 'rmic'],
-                  JAVAC = '/usr/local/j2sdk1.3.1/bin/javac',
-                  RMIC = '/usr/local/j2sdk1.3.1/bin/rmic')
-foo.Java(target = 'class1', source = 'com/sub/foo')
-foo.RMIC(target = 'outdir1',
-          source = ['class1/com/sub/foo/Example1.class',
-                    'class1/com/sub/foo/Example2'],
-          JAVACLASSDIR = 'class1')
-
-rmic = foo.Dictionary('RMIC')
-bar = foo.Copy(RMIC = r'%s wrapper.py ' + rmic)
-bar_classes = bar.Java(target = 'class2', source = 'com/sub/bar')
-# XXX This is kind of a Python brute-force way to do what Ant
-# does with its "excludes" attribute.  We should probably find
-# a similar friendlier way to do this.
-bar_classes = filter(lambda c: string.find(str(c), 'Hello') == -1, bar_classes)
-bar.RMIC(target = Dir('outdir2'), source = bar_classes)
-""" % python)
-
-test.subdir('com',
-            ['com', 'other'],
-            ['com', 'sub'],
-            ['com', 'sub', 'foo'],
-            ['com', 'sub', 'bar'],
-            'src3a',
-            'src3b')
-
-test.write(['com', 'sub', 'foo', 'Hello.java'], """\
-package com.sub.foo;
-
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-
-public interface Hello extends Remote {
-    String sayHello() throws RemoteException;
-}
-""")
-
-test.write(['com', 'sub', 'foo', 'Example1.java'], """\
-package com.sub.foo;
-
-import java.rmi.Naming;
-import java.rmi.RemoteException;
-import java.rmi.RMISecurityManager;
-import java.rmi.server.UnicastRemoteObject;
-
-public class Example1 extends UnicastRemoteObject implements Hello {
-
-    public Example1() throws RemoteException {
-        super();
-    }
-
-    public String sayHello() {
-        return "Hello World!";
-    }
-
-    public static void main(String args[]) {
-        if (System.getSecurityManager() == null) {
-            System.setSecurityManager(new RMISecurityManager());
-        }
-
-        try {
-            Example1 obj = new Example1();
-
-            Naming.rebind("//myhost/HelloServer", obj);
-
-            System.out.println("HelloServer bound in registry");
-        } catch (Exception e) {
-            System.out.println("Example1 err: " + e.getMessage());
-            e.printStackTrace();
-        }
-    }
-}
-""")
-
-test.write(['com', 'sub', 'foo', 'Example2.java'], """\
-package com.sub.foo;
-
-import java.rmi.Naming;
-import java.rmi.RemoteException;
-import java.rmi.RMISecurityManager;
-import java.rmi.server.UnicastRemoteObject;
-
-public class Example2 extends UnicastRemoteObject implements Hello {
-
-    public Example2() throws RemoteException {
-        super();
-    }
-
-    public String sayHello() {
-        return "Hello World!";
-    }
-
-    public static void main(String args[]) {
-        if (System.getSecurityManager() == null) {
-            System.setSecurityManager(new RMISecurityManager());
-        }
-
-        try {
-            Example2 obj = new Example2();
-
-            Naming.rebind("//myhost/HelloServer", obj);
-
-            System.out.println("HelloServer bound in registry");
-        } catch (Exception e) {
-            System.out.println("Example2 err: " + e.getMessage());
-            e.printStackTrace();
-        }
-    }
-}
-""")
-
-test.write(['com', 'sub', 'bar', 'Hello.java'], """\
-package com.sub.bar;
-
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-
-public interface Hello extends Remote {
-    String sayHello() throws RemoteException;
-}
-""")
-
-test.write(['com', 'sub', 'bar', 'Example3.java'], """\
-package com.sub.bar;
-
-import java.rmi.Naming;
-import java.rmi.RemoteException;
-import java.rmi.RMISecurityManager;
-import java.rmi.server.UnicastRemoteObject;
-
-public class Example3 extends UnicastRemoteObject implements Hello {
-
-    public Example3() throws RemoteException {
-        super();
-    }
-
-    public String sayHello() {
-        return "Hello World!";
-    }
-
-    public static void main(String args[]) {
-        if (System.getSecurityManager() == null) {
-            System.setSecurityManager(new RMISecurityManager());
-        }
-
-        try {
-            Example3 obj = new Example3();
-
-            Naming.rebind("//myhost/HelloServer", obj);
-
-            System.out.println("HelloServer bound in registry");
-        } catch (Exception e) {
-            System.out.println("Example3 err: " + e.getMessage());
-            e.printStackTrace();
-        }
-    }
-}
-""")
-
-test.write(['com', 'sub', 'bar', 'Example4.java'], """\
-package com.sub.bar;
-
-import java.rmi.Naming;
-import java.rmi.RemoteException;
-import java.rmi.RMISecurityManager;
-import java.rmi.server.UnicastRemoteObject;
-
-public class Example4 extends UnicastRemoteObject implements Hello {
-
-    public Example4() throws RemoteException {
-        super();
-    }
-
-    public String sayHello() {
-        return "Hello World!";
-    }
-
-    public static void main(String args[]) {
-        if (System.getSecurityManager() == null) {
-            System.setSecurityManager(new RMISecurityManager());
-        }
-
-        try {
-            Example4 obj = new Example4();
-
-            Naming.rebind("//myhost/HelloServer", obj);
-
-            System.out.println("HelloServer bound in registry");
-        } catch (Exception e) {
-            System.out.println("Example4 err: " + e.getMessage());
-            e.printStackTrace();
-        }
-    }
-}
-""")
-
-test.run(arguments = '.')
-
-test.fail_test(test.read('wrapper.out') != "wrapper.py /usr/local/j2sdk1.3.1/bin/rmic -d outdir2 -classpath class2 com.sub.bar.Example3 com.sub.bar.Example4\n")
-
-test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Stub.class')))
-
-test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Stub.class')))
-
-test.up_to_date(arguments = '.')
-
-test.pass_test()
-- 
cgit v0.12