summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-05-10 04:44:31 (GMT)
committerSteven Knight <knight@baldmt.com>2003-05-10 04:44:31 (GMT)
commit2333feeb8864c753a8834a45f0743876e28386e7 (patch)
tree0fc4462c350905522ee065908b43fc4689297050
parent8c7c96993d069298a66834db8bddb038725a6637 (diff)
downloadSCons-2333feeb8864c753a8834a45f0743876e28386e7.zip
SCons-2333feeb8864c753a8834a45f0743876e28386e7.tar.gz
SCons-2333feeb8864c753a8834a45f0743876e28386e7.tar.bz2
Add Java RMIC support.
-rw-r--r--bin/files1
-rw-r--r--doc/man/scons.152
-rw-r--r--src/CHANGES.txt2
-rw-r--r--src/engine/MANIFEST.in1
-rw-r--r--src/engine/SCons/Tool/__init__.py2
-rw-r--r--src/engine/SCons/Tool/rmic.py109
-rw-r--r--test/RMIC.py325
-rw-r--r--test/Repository/RMIC.py343
8 files changed, 831 insertions, 4 deletions
diff --git a/bin/files b/bin/files
index 9b24f9a..dec6750 100644
--- a/bin/files
+++ b/bin/files
@@ -66,6 +66,7 @@
./SCons/Tool/nasm.py
./SCons/Tool/pdflatex.py
./SCons/Tool/pdftex.py
+./SCons/Tool/rmic.py
./SCons/Tool/sgiar.py
./SCons/Tool/sgicc.py
./SCons/Tool/sgilink.py
diff --git a/doc/man/scons.1 b/doc/man/scons.1
index 2cbf048..99ddfa0 100644
--- a/doc/man/scons.1
+++ b/doc/man/scons.1
@@ -860,8 +860,7 @@ platform name when the Environment is constructed. Changing the PATH
variable after the Environment is constructed will not cause the tools to
be redetected.
-SCons supports the following tool specifications
-out of the box on all platforms:
+SCons supports the following tool specifications out of the box:
.ES
386asm
ar
@@ -878,6 +877,7 @@ gcc
gnulink
jar
javac
+javah
latex
lex
linkloc
@@ -890,6 +890,7 @@ msvc
nasm
pdflatex
pdftex
+rmic
sgiar
sgias
sgicc
@@ -1368,6 +1369,40 @@ env.JavaH(target = 'export',
JAVACLASSDIR = 'classes')
.EE
+.IP RMIC
+Builds stub and skeleton class files
+for remote objects
+from Java .class files.
+The target is a directory
+relative to which the stub
+and skeleton class files will be written.
+The source can be the names of .class files,
+or the objects return from the
+.B Java
+builder.
+
+If the construction variable
+.B JAVACLASSDIR
+is set, either in the environment
+or in the call to the
+.B RMIC
+builder itself,
+then the value of the variable
+will be stripped from the
+beginning of any .class file names.
+
+.ES
+classes = env.Java(target = 'classdir', source = 'src')
+env.RMIC(target = 'outdir1', source = classes)
+
+env.RMIC(target = 'outdir2',
+ source = ['package/foo.class', 'package/bar.class'])
+
+env.RMIC(target = 'outdir3',
+ source = ['classes/foo.class', 'classes/bar.class'],
+ JAVACLASSDIR = 'classes')
+.EE
+
.IP TypeLibrary
Builds a Windows type library (.tlb) file from and input IDL file
(.idl). In addition, it will build the associated inteface stub and
@@ -2734,6 +2769,19 @@ Options that are passed to the $RCS_CO command.
A function that converts a file name into a list of Dir instances by
searching the repositories.
+.IP RMIC
+The Java RMI stub compiler.
+
+.IP RMICCOM
+The command line used to compile stub
+and skeleton class files
+from Java classes that contain RMI implementations.
+Any options specified in the $RMICFLAGS construction variable
+are included on this command line.
+
+.IP RMICFLAGS
+General options passed to the Java RMI stub compiler.
+
.IP SCANNERS
A list of the available implicit dependency scanners. [CScan] by default.
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 1cd8565..7717ce6 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -57,7 +57,7 @@ RELEASE 0.14 - XXX
From Steven Knight:
- - Add Java support (javac, javah and jar).
+ - Add Java support (javac, javah, jar and rmic).
- Propagate the external SYSTEMROOT environment variable into ENV on
Win32 systems, so external commands that use sockets will work.
diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in
index 8bd3c2f..24277b4 100644
--- a/src/engine/MANIFEST.in
+++ b/src/engine/MANIFEST.in
@@ -81,6 +81,7 @@ SCons/Tool/pdftex.py
SCons/Tool/Perforce.py
SCons/Tool/PharLapCommon.py
SCons/Tool/RCS.py
+SCons/Tool/rmic.py
SCons/Tool/SCCS.py
SCons/Tool/sgiar.py
SCons/Tool/sgicc.py
diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py
index 25d7462..908101e 100644
--- a/src/engine/SCons/Tool/__init__.py
+++ b/src/engine/SCons/Tool/__init__.py
@@ -226,7 +226,7 @@ def tool_list(platform, env):
'jar', 'javac', 'javah',
'latex', 'lex', 'midl',
'pdflatex', 'pdftex', 'Perforce',
- 'RCS', 'SCCS',
+ 'RCS', 'rmic', 'SCCS',
# 'Subversion',
'tar', 'tex', 'yacc', 'zip'],
env)
diff --git a/src/engine/SCons/Tool/rmic.py b/src/engine/SCons/Tool/rmic.py
new file mode 100644
index 0000000..7043566
--- /dev/null
+++ b/src/engine/SCons/Tool/rmic.py
@@ -0,0 +1,109 @@
+"""SCons.Tool.rmic
+
+Tool-specific initialization for rmic.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# __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 re
+import string
+
+import SCons.Builder
+import SCons.Node.FS
+
+def emit_rmic_classes(target, source, env):
+ """Create and return lists of Java RMI stub and skeleton
+ class files to be created from a set of class files.
+ """
+ class_suffix = env.get('JAVACLASSSUFFIX', '.class')
+ classdir = env.get('JAVACLASSDIR')
+
+ if not classdir:
+ try:
+ s = source[0]
+ except IndexError:
+ classdir = '.'
+ else:
+ try:
+ classdir = s.attributes.java_classdir
+ except:
+ classdir = '.'
+ classdir = SCons.Node.FS.default_fs.Dir(classdir).rdir()
+ if str(classdir) == '.':
+ c_ = None
+ else:
+ c_ = str(classdir) + os.sep
+
+ slist = []
+ for src in source:
+ try:
+ classname = src.attributes.java_classname
+ except AttributeError:
+ classname = str(src)
+ if c_ and classname[:len(c_)] == c_:
+ classname = classname[len(c_):]
+ if class_suffix and classname[:-len(class_suffix)] == class_suffix:
+ classname = classname[-len(class_suffix):]
+ s = src.rfile()
+ s.attributes.java_classdir = classdir
+ s.attributes.java_classname = classname
+ slist.append(s)
+
+ File = SCons.Node.FS.default_fs.File
+ tlist = []
+ for s in source:
+ for suff in ['_Skel', '_Stub']:
+ fname = string.replace(s.attributes.java_classname, '.', os.sep) + \
+ suff + class_suffix
+ t = target[0].File(fname)
+ t.attributes.java_lookupdir = target[0]
+ tlist.append(t)
+
+ return tlist, source
+
+RMICBuilder = SCons.Builder.Builder(action = '$RMICCOM',
+ emitter = emit_rmic_classes,
+ src_suffix = '$JAVACLASSSUFFIX',
+ target_factory = SCons.Node.FS.default_fs.Dir,
+ source_factory = SCons.Node.FS.default_fs.File)
+
+def generate(env):
+ """Add Builders and construction variables for rmic to an Environment."""
+ env['BUILDERS']['RMIC'] = RMICBuilder
+
+ env['RMIC'] = 'rmic'
+ env['RMICFLAGS'] = ''
+ env['RMICCOM'] = '$RMIC $RMICFLAGS -d ${TARGET.attributes.java_lookupdir} -classpath ${SOURCE.attributes.java_classdir} ${SOURCES.attributes.java_classname}'
+ env['JAVACLASSSUFFIX'] = '.class'
+
+def exists(env):
+ return env.Detect('rmic')
diff --git a/test/RMIC.py b/test/RMIC.py
new file mode 100644
index 0000000..abad6cd
--- /dev/null
+++ b/test/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.Java(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('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/Repository/RMIC.py b/test/Repository/RMIC.py
new file mode 100644
index 0000000..9282835
--- /dev/null
+++ b/test/Repository/RMIC.py
@@ -0,0 +1,343 @@
+#!/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 building Java applications when using Repositories.
+"""
+
+import os
+import string
+import sys
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+java = '/usr/local/j2sdk1.3.1/bin/java'
+javac = '/usr/local/j2sdk1.3.1/bin/javac'
+rmic = '/usr/local/j2sdk1.3.1/bin/rmic'
+
+if not os.path.exists(javac):
+ print "Could not find Java (javac), skipping test(s)."
+ test.pass_test(1)
+
+if not os.path.exists(rmic):
+ print "Could not find Java (rmic), skipping test(s)."
+ test.pass_test(1)
+
+###############################################################################
+
+#
+test.subdir('rep1', ['rep1', 'src'],
+ 'work1',
+ 'work2',
+ 'work3')
+
+#
+rep1_classes = test.workpath('rep1', 'classes')
+work1_classes = test.workpath('work1', 'classes')
+work3_classes = test.workpath('work3', 'classes')
+
+#
+opts = '-Y ' + test.workpath('rep1')
+
+#
+test.write(['rep1', 'SConstruct'], """
+import string
+env = Environment(tools = ['javac', 'rmic'],
+ JAVAC = r'%s',
+ RMIC = r'%s')
+classes = env.Java(target = 'classes', source = 'src')
+# Brute-force removal of the "Hello" class.
+classes = filter(lambda c: string.find(str(c), 'Hello') == -1, classes)
+env.RMIC(target = 'outdir', source = classes)
+""" % (javac, rmic))
+
+test.write(['rep1', 'src', '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(['rep1', 'src', 'Foo1.java'], """\
+package com.sub.foo;
+
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.rmi.RMISecurityManager;
+import java.rmi.server.UnicastRemoteObject;
+
+public class Foo1 extends UnicastRemoteObject implements Hello {
+
+ public Foo1() throws RemoteException {
+ super();
+ }
+
+ public String sayHello() {
+ return "rep1/src/Foo1.java";
+ }
+
+ public static void main(String args[]) {
+ if (System.getSecurityManager() == null) {
+ System.setSecurityManager(new RMISecurityManager());
+ }
+
+ try {
+ Foo1 obj = new Foo1();
+
+ Naming.rebind("//myhost/HelloServer", obj);
+
+ System.out.println("HelloServer bound in registry");
+ } catch (Exception e) {
+ System.out.println("Foo1 err: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+}
+""")
+
+test.write(['rep1', 'src', 'Foo2.java'], """\
+package com.sub.foo;
+
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.rmi.RMISecurityManager;
+import java.rmi.server.UnicastRemoteObject;
+
+public class Foo2 extends UnicastRemoteObject implements Hello {
+
+ public Foo2() throws RemoteException {
+ super();
+ }
+
+ public String sayHello() {
+ return "rep1/src/Foo2.java";
+ }
+
+ public static void main(String args[]) {
+ if (System.getSecurityManager() == null) {
+ System.setSecurityManager(new RMISecurityManager());
+ }
+
+ try {
+ Foo2 obj = new Foo2();
+
+ Naming.rebind("//myhost/HelloServer", obj);
+
+ System.out.println("HelloServer bound in registry");
+ } catch (Exception e) {
+ System.out.println("Foo2 err: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+}
+""")
+
+# Make the repository non-writable,
+# so we'll detect if we try to write into it accidentally.
+test.writable('repository', 0)
+
+#
+test.run(chdir = 'work1', options = opts, arguments = ".")
+
+# XXX I'd rather run the resulting class files through the JVM here to
+# see that they were built from the proper rep1 sources, but I don't
+# know how to do that with RMI, so punt for now.
+
+test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
+test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
+test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
+test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+
+test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
+test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
+test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
+test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+
+test.up_to_date(chdir = 'work1', options = opts, arguments = ".")
+
+#
+test.subdir(['work1', 'src'])
+
+test.write(['work1', 'src', '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(['work1', 'src', 'Foo1.java'], """\
+package com.sub.foo;
+
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.rmi.RMISecurityManager;
+import java.rmi.server.UnicastRemoteObject;
+
+public class Foo1 extends UnicastRemoteObject implements Hello {
+
+ public Foo1() throws RemoteException {
+ super();
+ }
+
+ public String sayHello() {
+ return "work1/src/Foo1.java";
+ }
+
+ public static void main(String args[]) {
+ if (System.getSecurityManager() == null) {
+ System.setSecurityManager(new RMISecurityManager());
+ }
+
+ try {
+ Foo1 obj = new Foo1();
+
+ Naming.rebind("//myhost/HelloServer", obj);
+
+ System.out.println("HelloServer bound in registry");
+ } catch (Exception e) {
+ System.out.println("Foo1 err: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+}
+""")
+
+test.write(['work1', 'src', 'Foo2.java'], """\
+package com.sub.foo;
+
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.rmi.RMISecurityManager;
+import java.rmi.server.UnicastRemoteObject;
+
+public class Foo2 extends UnicastRemoteObject implements Hello {
+
+ public Foo2() throws RemoteException {
+ super();
+ }
+
+ public String sayHello() {
+ return "work1/src/Foo2.java";
+ }
+
+ public static void main(String args[]) {
+ if (System.getSecurityManager() == null) {
+ System.setSecurityManager(new RMISecurityManager());
+ }
+
+ try {
+ Foo2 obj = new Foo2();
+
+ Naming.rebind("//myhost/HelloServer", obj);
+
+ System.out.println("HelloServer bound in registry");
+ } catch (Exception e) {
+ System.out.println("Foo2 err: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+}
+""")
+
+test.run(chdir = 'work1', options = opts, arguments = ".")
+
+test.fail_test(string.find(test.stdout(), ' src/Foo1.java src/Foo2.java') == -1)
+test.fail_test(string.find(test.stdout(), ' com.sub.foo.Foo1 com.sub.foo.Foo2') == -1)
+
+# XXX I'd rather run the resulting class files through the JVM here to
+# see that they were built from the proper work1 sources, but I don't
+# know how to do that with RMI, so punt for now.
+
+test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
+test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
+test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
+test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+
+test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
+test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
+test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
+test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+
+test.up_to_date(chdir = 'work1', options = opts, arguments = ".")
+
+#
+test.writable('rep1', 1)
+
+test.run(chdir = 'rep1', options = opts, arguments = ".")
+
+# XXX I'd rather run the resulting class files through the JVM here to
+# see that they were built from the proper work1 sources, but I don't
+# know how to do that with RMI, so punt for now.
+
+test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
+test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
+test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
+test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+
+test.up_to_date(chdir = 'rep1', options = opts, arguments = ".")
+
+#
+test.writable('repository', 0)
+
+#
+test.up_to_date(chdir = 'work2', options = opts, arguments = ".")
+
+#
+test.write(['work3', 'SConstruct'], """
+import string
+env = Environment(tools = ['javac', 'rmic'],
+ JAVAC = r'%s',
+ RMIC = r'%s')
+classes = env.Java(target = 'classes', source = 'src')
+# Brute-force removal of the "Hello" class.
+classes = filter(lambda c: string.find(str(c), 'Hello') == -1, classes)
+rmi_classes = env.RMIC(target = 'outdir', source = classes)
+Local(rmi_classes)
+""" % (javac, rmic))
+
+test.run(chdir = 'work3', options = opts, arguments = ".")
+
+test.fail_test(os.path.exists(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Hello.class')))
+test.fail_test(os.path.exists(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo1.class')))
+test.fail_test(os.path.exists(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo2.class')))
+
+test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
+test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
+test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
+test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+
+test.pass_test()