bug-gnulib
[Top][All Lists]
Advanced

[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)
])





reply via email to

[Prev in Thread] Current Thread [Next in Thread]