OSDN Git Service

2010-11-26 François Dumont <francois.cppdevs@free.fr>
[pf3gnuchains/gcc-fork.git] / libjava / classpath / tools / toolwrapper.c
1 /* toolwrapper.c -- a native tool wrapper for VMs that support the JNI
2    invocation interface
3    Copyright (C) 2006  Free Software Foundation, Inc.
4
5 This file is part of GNU Classpath.
6
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING.  If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
21
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library.  Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
26
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module.  An independent module is a module which is not derived from
34 or based on this library.  If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so.  If you do not wish to do so, delete this
37 exception statement from your version. */
38
39 #include <jni.h>
40 #include <ltdl.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #include "config.h"
44
45 #ifndef JNI_VERSION_1_2
46 # error JNI version 1.2 or greater required
47 #endif
48
49 #ifndef MAINCLASS
50 #define MAINCLASS "Main"
51 #endif
52
53 union env_union
54 {
55   void *void_env;
56   JNIEnv *jni_env;
57 };
58
59 /* Typedef for JNI_CreateJavaVM dlopen call. */
60 typedef jint createVM (JavaVM **, void **, void *);
61
62 int
63 main (int argc, const char** argv)
64 {
65   union env_union tmp;
66   JNIEnv* env;
67   JavaVM* jvm;
68   JavaVMInitArgs vm_args;
69   jint result;
70   jclass class_id;
71   jmethodID method_id;
72   jstring str;
73   jclass string_class_id;
74   jobjectArray args_array;
75   char** non_vm_argv;
76   int non_vm_argc;
77   int i;
78   int classpath_found = 0;
79   /* Variables for JNI_CreateJavaVM dlopen call. */
80   lt_dlhandle libjvm_handle = NULL;
81   createVM* libjvm_create = NULL;
82   int libjvm_error = 0;
83
84   env = NULL;
85   jvm = NULL;
86
87   vm_args.nOptions = 0;
88   vm_args.options = NULL;
89
90   non_vm_argc = 0;
91   non_vm_argv = NULL;
92
93   if (argc > 1)
94     {
95       for (i = 1; i < argc; i++)
96         {
97           if (!strncmp (argv[i], "-J", 2))
98             {
99               if (!strncmp (argv[i], "-J-Djava.class.path=", 20))
100                 classpath_found = 1;
101
102               /* A virtual machine option. */
103               vm_args.options = (JavaVMOption*) realloc (vm_args.options, (vm_args.nOptions + 1) * sizeof (JavaVMOption));
104
105               if (vm_args.options == NULL)
106                 {
107                   fprintf (stderr, TOOLNAME ": realloc failed.\n");
108                   goto destroy;
109                 }
110
111               if (strlen (argv[i]) == 2)
112                 {
113                   fprintf (stderr, TOOLNAME ": the -J option must not be followed by a space.\n");
114                   goto destroy;
115                 }
116               else
117                 vm_args.options[vm_args.nOptions++].optionString = strdup (argv[i] + 2);
118             }
119           else
120             {
121               non_vm_argv = (char**) realloc (non_vm_argv, (non_vm_argc + 1) * sizeof (char*));
122               if (non_vm_argv == NULL)
123                 {
124                   fprintf (stderr, TOOLNAME ": realloc failed.\n");
125                   goto destroy;
126                 }
127               non_vm_argv[non_vm_argc++] = strdup (argv[i]);
128             }
129         }
130     }
131
132   if (!classpath_found)
133     {
134       /* Set the invocation classpath. */
135       vm_args.options = (JavaVMOption*) realloc (vm_args.options, (vm_args.nOptions + 1) * sizeof (JavaVMOption));
136
137       if (vm_args.options == NULL)
138         {
139           fprintf (stderr, TOOLNAME ": realloc failed.\n");
140           goto destroy;
141         }
142
143       vm_args.options[vm_args.nOptions++].optionString = "-Xbootclasspath/p:" TOOLS_ZIP;
144     }
145
146   /* Terminate vm_args.options with a NULL element. */
147   vm_args.options = (JavaVMOption*) realloc (vm_args.options, (vm_args.nOptions + 1) * sizeof (JavaVMOption));
148   if (vm_args.options == NULL)
149     {
150       fprintf (stderr, TOOLNAME ": realloc failed.\n");
151       goto destroy;
152     }
153   vm_args.options[vm_args.nOptions].optionString = NULL;
154
155   /* Terminate non_vm_argv with a NULL element. */
156   non_vm_argv = (char**) realloc (non_vm_argv, (non_vm_argc + 1) * sizeof (char*));
157   if (non_vm_argv == NULL)
158     {
159       fprintf (stderr, TOOLNAME ": realloc failed.\n");
160       goto destroy;
161     }
162   non_vm_argv[non_vm_argc] = NULL;
163
164   vm_args.version = JNI_VERSION_1_2;
165   vm_args.ignoreUnrecognized = JNI_TRUE;
166
167   /* dlopen libjvm.so */
168   libjvm_error = lt_dlinit ();
169   if (libjvm_error)
170     {
171       fprintf (stderr, TOOLNAME ": lt_dlinit failed.\n");
172       goto destroy;
173     }
174
175   libjvm_handle = lt_dlopenext (LIBJVM);
176   if (!libjvm_handle)
177     {
178       fprintf (stderr, TOOLNAME ": failed to open " LIBJVM "\n");
179       goto destroy;
180     }
181   libjvm_create = (createVM*) lt_dlsym (libjvm_handle, "JNI_CreateJavaVM");
182   if (!libjvm_create)
183     {
184       fprintf (stderr, TOOLNAME ": failed to load JNI_CreateJavaVM symbol from " LIBJVM "\n");
185       goto destroy;
186     }
187   result = (*libjvm_create) (&jvm, &tmp.void_env, &vm_args);
188
189   if (result < 0)
190     {
191       fprintf (stderr, TOOLNAME ": couldn't create virtual machine\n");
192       goto destroy;
193     }
194
195   env = tmp.jni_env;
196
197   string_class_id = (*env)->FindClass (env, "java/lang/String");
198   if (string_class_id == NULL)
199     {
200       fprintf (stderr, TOOLNAME ": FindClass failed.\n");
201       goto destroy;
202     }
203
204   args_array = (*env)->NewObjectArray (env, non_vm_argc, string_class_id, NULL);
205   if (args_array == NULL)
206     {
207       fprintf (stderr, TOOLNAME ": NewObjectArray failed.\n");
208       goto destroy;
209     }
210
211   for (i = 0; i < non_vm_argc; i++)
212     {
213       str = (*env)->NewStringUTF (env, non_vm_argv[i]);
214       if (str == NULL)
215         {
216           fprintf (stderr, TOOLNAME ": NewStringUTF failed.\n");
217           goto destroy;
218         }
219
220       (*env)->SetObjectArrayElement (env, args_array, i, str);
221     }
222
223   class_id
224     = (*env)->FindClass (env,
225                          "gnu/classpath/tools/" TOOLPACKAGE "/" MAINCLASS);
226   if (class_id == NULL)
227     {
228       fprintf (stderr, TOOLNAME ": FindClass failed.\n");
229       goto destroy;
230     }
231
232   method_id = (*env)->GetStaticMethodID (env, class_id, "main", "([Ljava/lang/String;)V");
233
234   if (method_id == NULL)
235     {
236       fprintf (stderr, TOOLNAME ": GetStaticMethodID failed.\n");
237       goto destroy;
238     }
239
240   (*env)->CallStaticVoidMethod (env, class_id, method_id, args_array);
241
242  destroy:
243
244   if (env != NULL)
245     {
246       if ((*env)->ExceptionOccurred (env))
247         (*env)->ExceptionDescribe (env);
248
249       if (jvm != NULL)
250         (*jvm)->DestroyJavaVM (jvm);
251     }
252
253   /* libltdl cleanup */
254   if (libjvm_handle)
255     {
256       if (lt_dlclose (libjvm_handle) != 0)
257         fprintf (stderr, TOOLNAME ": failed to close " LIBJVM "\n");
258     }
259
260   if (lt_dlexit () != 0)
261     fprintf (stderr, TOOLNAME ": lt_dlexit failed.\n");
262
263   return 1;
264 }