#!/usr/bin/perl -w
#
# Used to start the Jython interpreter.
#
# Copyright (C) 2004-2005, Ben Burton <bab@debian.org>
# Released under the GPL.

use strict;
use File::Basename;
use Text::ParseWords;
use Cwd 'abs_path';

# Debian constants.
#
# The jython launcher in installed into ${jython.home}/bin
my $jythonHome = dirname(dirname(abs_path($0)));
my $debianJNIDir = '/usr/lib/jni';
my $defaultRuntime = '/usr/bin/java';

# Establish the user's home directory.
#
my $home = $ENV{HOME} || $ENV{LOGDIR};
$home or bail("I cannot determine your home directory.",
	"Please set \$HOME and try again.");

# Decide upon the Java runtime.
#
my $javaRuntime = undef;
if ($ENV{JAVA}) {
	$javaRuntime = $ENV{JAVA};
} elsif (-x $defaultRuntime) {
	$javaRuntime = $defaultRuntime;
} else {
	&warn("The default Java runtime ($defaultRuntime) cannot be executed.",
		"Since every Java runtime in Debian must supply an alternative",
		"for $defaultRuntime, your system is almost certainly misconfigured.");
	if ($ENV{JAVA_HOME}) {
		&warn("Using \$JAVA_HOME/bin/java instead.");
		$javaRuntime = "$ENV{JAVA_HOME}/bin/java";
	} else {
		bail("I cannot find an appropriate Java runtime to use instead.",
			"Please set \$JAVA to the appropriate binary and try again.");
	}
}

# Decide upon and export the classpath.
# Add in $CLASSPATH as well as other useful libraries if they exist.
#
my $classpath = '/usr/share/java/jython.jar';
appendClasspath($ENV{CLASSPATH});
appendJar('/usr/share/java/antlr3-runtime-3.2.jar');          # direct dependency of jython
appendJar('/usr/share/java/stringtemplate.jar');          # dependency of antlr3-runtime
appendJar('/usr/share/java/antlr3-3.2.jar');                   # dependency of stringtemplate

appendJar('/usr/share/java/asm3.jar');                    # direct dependency of jython

appendJar('/usr/share/java/asm3-commons.jar');            # direct dependency of jython
appendJar('/usr/share/java/asm3-tree.jar');               # dependency of asm3-commons
# asm3-commons also depends on asm3, already included

appendJar('/usr/share/java/jnr-constants.jar');             # direct dependency of jython

appendJar('/usr/share/java/guava.jar');                   # direct dependency of jython
appendJar('/usr/share/java/jsr305.jar');                  # dependency of guava

appendJar('/usr/share/java/jnr-posix.jar');               # direct dependency of jython
appendJar('/usr/share/java/jaffl.jar');                   # dependency of jnr-posix
appendJar('/usr/share/java/jffi.jar');                    # dependency of jaffl
appendJar('/usr/share/java/jnr-ffi.jar');                 # (needed for pycompile build step)
#appendJar('/usr/lib/jffi/jffi-native.jar');               # dependency of jffi-native
# jaffl also depends on asm3, already included
appendJar('/usr/share/java/jnr-x86asm.jar');              # dependency of jaffl
# jnr-posix also depends on constantine, already included

appendJar('/usr/share/java/jnr-netdb.jar');               # direct dependency of jython
# jnr-netdb also depends on jaffl, already included

appendJar('/usr/share/java/livetribe-jsr223.jar');        # direct dependency of jython

appendJar('/usr/share/java/jline.jar');                   # direct dependency of jython

appendJar('/usr/share/java/servlet-api-3.1.jar');         # direct dependency of jython

appendJar('/usr/share/java/libreadline-java.jar');        # direct dependency of jython

appendJar('/usr/share/java/mysql-connector-java.jar');    # direct dependency of jython

appendJar('/usr/share/java/postgresql-jdbc4.jar');        # direct dependency of jython


$ENV{CLASSPATH} = $classpath;

# Decide upon the python path.
my $jythonPath = "/usr/lib/site-python:/usr/share/jython/Lib";

# We will build up a JNI library path from various places.
#
my $jniPath = '';

# Run through $JAVA_OPTIONS and extract the java arguments.
# Any JNI library path arguments will be removed and put into $jniPath
# instead.
#
my @javaArgs = ();

if ($ENV{JAVA_OPTIONS}) {
	foreach my $arg (shellwords($ENV{JAVA_OPTIONS})) {
		if ($arg =~ /^-Djava\.library\.path=(.+)$/) {
			$jniPath = $jniPath ? "$jniPath:$1" : "$1";
		} else {
			push @javaArgs, $arg;
		}
	}
}

# Run through the command-line options and extract the jython arguments.
# Any -Djava... arguments will be reassigned as java arguments instead
# (unless it's for the JNI library path, in which case it will go to
# $jniPath).
#
my @jythonArgs = ();

foreach my $arg (@ARGV) {
	if ($arg =~ /^-Djava\.library\.path=(.+)$/) {
		$jniPath = $jniPath ? "$jniPath:$1" : "$1";
	} elsif ($arg =~ /^-Djava/) {
		push @javaArgs, $arg;
	} else {
		push @jythonArgs, $arg;
	}
}

# Finish by adding the debian JNI directory to $jniPath if it's not
# already present, since some popular non-free JVMs still don't support
# it (grumble).
#
if ($jniPath !~ /(^|:)$debianJNIDir($|:)/) {
	$jniPath = $jniPath ? "$jniPath:$debianJNIDir" : $debianJNIDir;
}

# Invoke jython!
#
my @fullCommandLine = ( $javaRuntime );
push @fullCommandLine, @javaArgs;
push @fullCommandLine, "-Djava.library.path=$jniPath";
push @fullCommandLine, "-Dpython.home=$jythonHome";
push @fullCommandLine, "-Dpython.path=$jythonPath";
push @fullCommandLine, "-Dpython.executable=$0";
push @fullCommandLine, "-Dpython.console=org.python.util.ReadlineConsole";
push @fullCommandLine, "-Dpython.console.readlinelib=Editline";
$ENV{CALLED_FROM_JYTHONC} and
	push @fullCommandLine, "-Dpython.jythonc.compiler=$ENV{JAVAC}";
push @fullCommandLine, 'org.python.util.jython';
push @fullCommandLine, @jythonArgs;
$ENV{JYTHON_WRAPPER_DEBUG} and print "$ENV{CLASSPATH}\n\n@fullCommandLine\n\n";
exec @fullCommandLine or exit(1);

# All done.
#
exit 0;

# Helper routines:

# Print the given warning messages to stderr, one per line.
# The messages should not contain trailing newlines.
#
sub warn {
	foreach (@_) {
		print STDERR "WARNING: $_\n";
	}
}

# Print the given error messages to stderr, one per line, and exit.
# The messages should not contain trailing newlines.
#
sub bail {
	foreach (@_) {
		print STDERR "ERROR: $_\n";
	}
	exit 1;
}

# Append the given string to the classpath if it's non-empty.
#
sub appendClasspath {
	my $string = shift;
	$string and $classpath = "$classpath:$string";
}

# Append the given jar to the classpath if it exists.
#
sub appendJar {
	my $jar = shift;
	-e $jar and $classpath = "$classpath:$jar";
}

# Append the given directory to the python path if it exists.
#
sub appendPythonDir {
	my $dir = shift;
	-d $dir and $jythonPath = "$jythonPath:$dir";
}

