[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[bug-gnulib] Re: new modules for Java interoperability
From: |
Bruno Haible |
Subject: |
[bug-gnulib] Re: new modules for Java interoperability |
Date: |
Fri, 21 Jan 2005 14:13:05 +0100 |
User-agent: |
KMail/1.5 |
There were no comments, so I committed the classpath module.
The next one is for executing Java programs. Besides the C code, it also
contains equivalent code as a shell script, that can be used either during
the build of the package, or when it's a shell script rather than a C
program that wants to execute a Java program.
============================= modules/javaexec =============================
Description:
Execute a Java program.
Files:
lib/javaexec.h
lib/javaexec.c
lib/javaexec.sh.in
m4/javaexec.m4
Depends-on:
stdbool
execute
classpath
xsetenv
sh-quote
pathname
xalloc
xallocsa
error
gettext
configure.ac:
gt_JAVAEXEC
Makefile.am:
DEFS += -DEXEEXT=\"$(EXEEXT)\"
lib_SOURCES += javaexec.h javaexec.c
EXTRA_DIST += javaexec.sh.in
Include:
"javaexec.h"
License:
GPL
Maintainer:
Bruno Haible
============================= lib/javaexec.sh.in =============================
#!/bin/sh
# Execute a Java program.
# Copyright (C) 2001 Free Software Foundation, Inc.
# Written by Bruno Haible <address@hidden>, 2001.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
# This uses the same choices as javaexec.c, but instead of relying on the
# environment settings at run time, it uses the environment variables
# present at configuration time.
#
# This is a separate shell script, because it must be able to unset JAVA_HOME
# in some cases, which a simple shell command cannot do.
#
# The extra CLASSPATH must have been set prior to calling this script.
CONF_JAVA='@JAVA@'
CONF_CLASSPATH='@CLASSPATH@'
if test -n "$CONF_JAVA"; then
# Combine given CLASSPATH and configured CLASSPATH.
if test -n "$CLASSPATH"; then
CLASSPATH="$CLASSPATH${CONF_CLASSPATH:address@hidden@$CONF_CLASSPATH}"
else
CLASSPATH="$CONF_CLASSPATH"
fi
export CLASSPATH
test -z "$JAVA_VERBOSE" || echo "$CONF_JAVA $@"
exec $CONF_JAVA "$@"
else
unset JAVA_HOME
export CLASSPATH
if test -n "@HAVE_GIJ@"; then
test -z "$JAVA_VERBOSE" || echo gij "$@"
exec gij "$@"
else
if test -n "@HAVE_JAVA@"; then
test -z "$JAVA_VERBOSE" || echo java "$@"
exec java "$@"
else
if test -n "@HAVE_JRE@"; then
test -z "$JAVA_VERBOSE" || echo jre "$@"
exec jre "$@"
else
if test -n "@HAVE_JVIEW@"; then
test -z "$JAVA_VERBOSE" || echo jview "$@"
exec jview "$@"
else
echo 'Java virtual machine not found, try installing gij or set
$JAVA, then reconfigure' 1>&2
exit 1
fi
fi
fi
fi
fi
============================= lib/javaexec.h =============================
/* Execute a Java program.
Copyright (C) 2001-2002 Free Software Foundation, Inc.
Written by Bruno Haible <address@hidden>, 2001.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _JAVAEXEC_H
#define _JAVAEXEC_H
#include <stdbool.h>
typedef bool execute_fn (const char *progname,
const char *prog_path, char **prog_argv,
void *private_data);
/* Execute a Java class.
class_name is the Java class name to be executed.
classpaths is a list of pathnames to be prepended to the CLASSPATH.
use_minimal_classpath = true means to ignore the user's CLASSPATH and
use a minimal one. This is likely to reduce possible problems if the
user's CLASSPATH contains garbage or a classes.zip file of the wrong
Java version.
exe_dir is a directory that may contain a native executable for the class.
args is a NULL terminated list of arguments to be passed to the program.
If verbose, the command to be executed will be printed.
Then the command is passed to the execute function together with the
private_data argument. This function returns false if OK, true on error.
Return false if OK, true on error.
If quiet, error messages will not be printed. */
extern bool execute_java_class (const char *class_name,
const char * const *classpaths,
unsigned int classpaths_count,
bool use_minimal_classpath,
const char *exe_dir,
const char * const *args,
bool verbose, bool quiet,
execute_fn *executer, void *private_data);
#endif /* _JAVAEXEC_H */
============================= lib/javaexec.c =============================
/* Execute a Java program.
Copyright (C) 2001-2003 Free Software Foundation, Inc.
Written by Bruno Haible <address@hidden>, 2001.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <alloca.h>
/* Specification. */
#include "javaexec.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "execute.h"
#include "classpath.h"
#include "xsetenv.h"
#include "sh-quote.h"
#include "pathname.h"
#include "xalloc.h"
#include "xallocsa.h"
#include "error.h"
#include "gettext.h"
#define _(str) gettext (str)
/* Survey of Java virtual machines.
A = does it work without CLASSPATH being set
B = does it work with CLASSPATH being set to empty
C = option to set CLASSPATH, other than setting it in the environment
T = test for presence
Program from A B C T
$JAVA unknown N Y n/a true
gij GCC 3.0 Y Y n/a gij --version >/dev/null
java JDK 1.1.8 Y Y -classpath P java -version 2>/dev/null
jre JDK 1.1.8 N Y -classpath P jre 2>/dev/null; test $? = 1
java JDK 1.3.0 Y Y -classpath P java -version 2>/dev/null
jview MS IE Y Y -cp P jview -? >nul; %errorlevel% = 1
The CLASSPATH is a colon separated list of pathnames. (On Windows: a
semicolon separated list of pathnames.)
We try the Java virtual machines in the following order:
1. getenv ("JAVA"), because the user must be able to override our
preferences,
2. "gij", because it is a completely free JVM,
3. "java", because it is a standard JVM,
4. "jre", comes last because it requires a CLASSPATH environment variable,
5. "jview", on Windows only, because it is frequently installed.
We unset the JAVA_HOME environment variable, because a wrong setting of
this variable can confuse the JDK's javac.
*/
bool
execute_java_class (const char *class_name,
const char * const *classpaths,
unsigned int classpaths_count,
bool use_minimal_classpath,
const char *exe_dir,
const char * const *args,
bool verbose, bool quiet,
execute_fn *executer, void *private_data)
{
bool err = false;
unsigned int nargs;
char *old_JAVA_HOME;
/* Count args. */
{
const char * const *arg;
for (nargs = 0, arg = args; *arg != NULL; nargs++, arg++)
;
}
/* First, try a class compiled to a native code executable. */
if (exe_dir != NULL)
{
char *exe_pathname = concatenated_pathname (exe_dir, class_name, EXEEXT);
char *old_classpath;
char **argv = (char **) xallocsa ((1 + nargs + 1) * sizeof (char *));
unsigned int i;
/* Set CLASSPATH. */
old_classpath =
set_classpath (classpaths, classpaths_count, use_minimal_classpath,
verbose);
argv[0] = exe_pathname;
for (i = 0; i <= nargs; i++)
argv[1 + i] = (char *) args[i];
if (verbose)
{
char *command = shell_quote_argv (argv);
printf ("%s\n", command);
free (command);
}
err = executer (class_name, exe_pathname, argv, private_data);
/* Reset CLASSPATH. */
reset_classpath (old_classpath);
freesa (argv);
goto done1;
}
{
const char *java = getenv ("JAVA");
if (java != NULL && java[0] != '\0')
{
/* Because $JAVA may consist of a command and options, we use the
shell. Because $JAVA has been set by the user, we leave all
all environment variables in place, including JAVA_HOME, and
we don't erase the user's CLASSPATH. */
char *old_classpath;
unsigned int command_length;
char *command;
char *argv[4];
const char * const *arg;
char *p;
/* Set CLASSPATH. */
old_classpath =
set_classpath (classpaths, classpaths_count, false,
verbose);
command_length = strlen (java);
command_length += 1 + shell_quote_length (class_name);
for (arg = args; *arg != NULL; arg++)
command_length += 1 + shell_quote_length (*arg);
command_length += 1;
command = (char *) xallocsa (command_length);
p = command;
/* Don't shell_quote $JAVA, because it may consist of a command
and options. */
memcpy (p, java, strlen (java));
p += strlen (java);
*p++ = ' ';
p = shell_quote_copy (p, class_name);
for (arg = args; *arg != NULL; arg++)
{
*p++ = ' ';
p = shell_quote_copy (p, *arg);
}
*p++ = '\0';
/* Ensure command_length was correctly calculated. */
if (p - command > command_length)
abort ();
if (verbose)
printf ("%s\n", command);
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = command;
argv[3] = NULL;
err = executer (java, "/bin/sh", argv, private_data);
freesa (command);
/* Reset CLASSPATH. */
reset_classpath (old_classpath);
goto done1;
}
}
/* Unset the JAVA_HOME environment variable. */
old_JAVA_HOME = getenv ("JAVA_HOME");
if (old_JAVA_HOME != NULL)
{
old_JAVA_HOME = xstrdup (old_JAVA_HOME);
unsetenv ("JAVA_HOME");
}
{
static bool gij_tested;
static bool gij_present;
if (!gij_tested)
{
/* Test for presence of gij: "gij --version > /dev/null" */
char *argv[3];
int exitstatus;
argv[0] = "gij";
argv[1] = "--version";
argv[2] = NULL;
exitstatus = execute ("gij", "gij", argv, false, false, true, true,
true, false);
gij_present = (exitstatus == 0);
gij_tested = true;
}
if (gij_present)
{
char *old_classpath;
char **argv = (char **) xallocsa ((2 + nargs + 1) * sizeof (char *));
unsigned int i;
/* Set CLASSPATH. */
old_classpath =
set_classpath (classpaths, classpaths_count, use_minimal_classpath,
verbose);
argv[0] = "gij";
argv[1] = (char *) class_name;
for (i = 0; i <= nargs; i++)
argv[2 + i] = (char *) args[i];
if (verbose)
{
char *command = shell_quote_argv (argv);
printf ("%s\n", command);
free (command);
}
err = executer ("gij", "gij", argv, private_data);
/* Reset CLASSPATH. */
reset_classpath (old_classpath);
freesa (argv);
goto done2;
}
}
{
static bool java_tested;
static bool java_present;
if (!java_tested)
{
/* Test for presence of java: "java -version 2> /dev/null" */
char *argv[3];
int exitstatus;
argv[0] = "java";
argv[1] = "-version";
argv[2] = NULL;
exitstatus = execute ("java", "java", argv, false, false, true, true,
true, false);
java_present = (exitstatus == 0);
java_tested = true;
}
if (java_present)
{
char *old_classpath;
char **argv = (char **) xallocsa ((2 + nargs + 1) * sizeof (char *));
unsigned int i;
/* Set CLASSPATH. We don't use the "-classpath ..." option because
in JDK 1.1.x its argument should also contain the JDK's classes.zip,
but we don't know its location. (In JDK 1.3.0 it would work.) */
old_classpath =
set_classpath (classpaths, classpaths_count, use_minimal_classpath,
verbose);
argv[0] = "java";
argv[1] = (char *) class_name;
for (i = 0; i <= nargs; i++)
argv[2 + i] = (char *) args[i];
if (verbose)
{
char *command = shell_quote_argv (argv);
printf ("%s\n", command);
free (command);
}
err = executer ("java", "java", argv, private_data);
/* Reset CLASSPATH. */
reset_classpath (old_classpath);
freesa (argv);
goto done2;
}
}
{
static bool jre_tested;
static bool jre_present;
if (!jre_tested)
{
/* Test for presence of jre: "jre 2> /dev/null ; test $? = 1" */
char *argv[2];
int exitstatus;
argv[0] = "jre";
argv[1] = NULL;
exitstatus = execute ("jre", "jre", argv, false, false, true, true,
true, false);
jre_present = (exitstatus == 0 || exitstatus == 1);
jre_tested = true;
}
if (jre_present)
{
char *old_classpath;
char **argv = (char **) xallocsa ((2 + nargs + 1) * sizeof (char *));
unsigned int i;
/* Set CLASSPATH. We don't use the "-classpath ..." option because
in JDK 1.1.x its argument should also contain the JDK's classes.zip,
but we don't know its location. */
old_classpath =
set_classpath (classpaths, classpaths_count, use_minimal_classpath,
verbose);
argv[0] = "jre";
argv[1] = (char *) class_name;
for (i = 0; i <= nargs; i++)
argv[2 + i] = (char *) args[i];
if (verbose)
{
char *command = shell_quote_argv (argv);
printf ("%s\n", command);
free (command);
}
err = executer ("jre", "jre", argv, private_data);
/* Reset CLASSPATH. */
reset_classpath (old_classpath);
freesa (argv);
goto done2;
}
}
#if defined _WIN32 || defined __WIN32__
/* Win32 */
{
static bool jview_tested;
static bool jview_present;
if (!jview_tested)
{
/* Test for presence of jview: "jview -? >nul ; test $? = 1" */
char *argv[3];
int exitstatus;
argv[0] = "jview";
argv[1] = "-?";
argv[2] = NULL;
exitstatus = execute ("jview", "jview", argv, false, false, true, true,
true, false);
jview_present = (exitstatus == 0 || exitstatus == 1);
jview_tested = true;
}
if (jview_present)
{
char *old_classpath;
char **argv = (char **) xallocsa ((2 + nargs + 1) * sizeof (char *));
unsigned int i;
/* Set CLASSPATH. */
old_classpath =
set_classpath (classpaths, classpaths_count, use_minimal_classpath,
verbose);
argv[0] = "jview";
argv[1] = (char *) class_name;
for (i = 0; i <= nargs; i++)
argv[2 + i] = (char *) args[i];
if (verbose)
{
char *command = shell_quote_argv (argv);
printf ("%s\n", command);
free (command);
}
err = executer ("jview", "jview", argv, private_data);
/* Reset CLASSPATH. */
reset_classpath (old_classpath);
freesa (argv);
goto done2;
}
}
#endif
if (!quiet)
error (0, 0, _("Java virtual machine not found, try installing gij or set
$JAVA"));
err = true;
done2:
if (old_JAVA_HOME != NULL)
{
xsetenv ("JAVA_HOME", old_JAVA_HOME, 1);
free (old_JAVA_HOME);
}
done1:
return err;
}
============================= m4/javaexec.m4 =============================
# javaexec.m4 serial 2 (gettext-0.13)
dnl Copyright (C) 2001-2003 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
# Prerequisites of javaexec.sh.
# gt_JAVAEXEC or gt_JAVAEXEC(testclass, its-directory)
# Sets HAVE_JAVAEXEC to nonempty if javaexec.sh will work.
AC_DEFUN([gt_JAVAEXEC],
[
AC_MSG_CHECKING([for Java virtual machine])
AC_EGREP_CPP(yes, [
#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
yes
#endif
], CLASSPATH_SEPARATOR=';', CLASSPATH_SEPARATOR=':')
HAVE_JAVAEXEC=1
if test -n "$JAVA"; then
ac_result="$JAVA"
else
pushdef([AC_MSG_CHECKING],[:])dnl
pushdef([AC_CHECKING],[:])dnl
pushdef([AC_MSG_RESULT],[:])dnl
AC_CHECK_PROG(HAVE_GIJ_IN_PATH, gij, yes)
AC_CHECK_PROG(HAVE_JAVA_IN_PATH, java, yes)
AC_CHECK_PROG(HAVE_JRE_IN_PATH, jre, yes)
AC_CHECK_PROG(HAVE_JVIEW_IN_PATH, jview, yes)
popdef([AC_MSG_RESULT])dnl
popdef([AC_CHECKING])dnl
popdef([AC_MSG_CHECKING])dnl
ifelse([$1], , , [
save_CLASSPATH="$CLASSPATH"
CLASSPATH="$2"${CLASSPATH+"$CLASSPATH_SEPARATOR$CLASSPATH"}
])
export CLASSPATH
if test -n "$HAVE_GIJ_IN_PATH" \
&& gij --version >/dev/null 2>/dev/null \
ifelse([$1], , , [&& gij $1 >/dev/null 2>/dev/null]); then
HAVE_GIJ=1
ac_result="gij"
else
if test -n "$HAVE_JAVA_IN_PATH" \
&& java -version >/dev/null 2>/dev/null \
ifelse([$1], , , [&& java $1 >/dev/null 2>/dev/null]); then
HAVE_JAVA=1
ac_result="java"
else
if test -n "$HAVE_JRE_IN_PATH" \
&& (jre >/dev/null 2>/dev/null || test $? = 1) \
ifelse([$1], , , [&& jre $1 >/dev/null 2>/dev/null]); then
HAVE_JRE=1
ac_result="jre"
else
if test -n "$HAVE_JVIEW_IN_PATH" \
&& (jview -? >/dev/null 2>/dev/null || test $? = 1) \
ifelse([$1], , , [&& jview $1 >/dev/null 2>/dev/null]); then
HAVE_JVIEW=1
ac_result="jview"
else
HAVE_JAVAEXEC=
ac_result="no"
fi
fi
fi
fi
ifelse([$1], , , [
CLASSPATH="$save_CLASSPATH"
])
fi
AC_MSG_RESULT([$ac_result])
AC_SUBST(JAVA)
AC_SUBST(CLASSPATH)
AC_SUBST(CLASSPATH_SEPARATOR)
AC_SUBST(HAVE_GIJ)
AC_SUBST(HAVE_JAVA)
AC_SUBST(HAVE_JRE)
AC_SUBST(HAVE_JVIEW)
])