import source from 1.3.40
[external/swig.git] / Source / Modules / java.cxx
1 /* -----------------------------------------------------------------------------
2  * See the LICENSE file for information on copyright, usage and redistribution
3  * of SWIG, and the README file for authors - http://www.swig.org/release.html.
4  *
5  * java.cxx
6  *
7  * Java language module for SWIG.
8  * ----------------------------------------------------------------------------- */
9
10 char cvsroot_java_cxx[] = "$Id: java.cxx 11584 2009-08-16 00:04:29Z wsfulton $";
11
12 #include "swigmod.h"
13 #include <limits.h>             // for INT_MAX
14 #include "cparse.h"
15 #include <ctype.h>
16
17 /* Hash type used for upcalls from C/C++ */
18 typedef DOH UpcallData;
19
20 class JAVA:public Language {
21   static const char *usage;
22   const String *empty_string;
23   const String *public_string;
24   const String *protected_string;
25
26   Hash *swig_types_hash;
27   File *f_begin;
28   File *f_runtime;
29   File *f_runtime_h;
30   File *f_header;
31   File *f_wrappers;
32   File *f_init;
33   File *f_directors;
34   File *f_directors_h;
35   List *filenames_list;
36
37   bool proxy_flag;              // Flag for generating proxy classes
38   bool nopgcpp_flag;            // Flag for suppressing the premature garbage collection prevention parameter
39   bool native_function_flag;    // Flag for when wrapping a native function
40   bool enum_constant_flag;      // Flag for when wrapping an enum or constant
41   bool static_flag;             // Flag for when wrapping a static functions or member variables
42   bool variable_wrapper_flag;   // Flag for when wrapping a nonstatic member variable
43   bool wrapping_member_flag;    // Flag for when wrapping a member variable/enum/const
44   bool global_variable_flag;    // Flag for when wrapping a global variable
45   bool old_variable_names;      // Flag for old style variable names in the intermediary class
46   bool member_func_flag;        // flag set when wrapping a member function
47
48   String *imclass_name;         // intermediary class name
49   String *module_class_name;    // module class name
50   String *imclass_class_code;   // intermediary class code
51   String *proxy_class_def;
52   String *proxy_class_code;
53   String *module_class_code;
54   String *proxy_class_name;
55   String *variable_name;        //Name of a variable being wrapped
56   String *proxy_class_constants_code;
57   String *module_class_constants_code;
58   String *enum_code;
59   String *package;              // Optional package name
60   String *jnipackage;           // Package name used in the JNI code
61   String *package_path;         // Package name used internally by JNI (slashes)
62   String *imclass_imports;      //intermediary class imports from %pragma
63   String *module_imports;       //module imports from %pragma
64   String *imclass_baseclass;    //inheritance for intermediary class class from %pragma
65   String *module_baseclass;     //inheritance for module class from %pragma
66   String *imclass_interfaces;   //interfaces for intermediary class class from %pragma
67   String *module_interfaces;    //interfaces for module class from %pragma
68   String *imclass_class_modifiers;      //class modifiers for intermediary class overriden by %pragma
69   String *module_class_modifiers;       //class modifiers for module class overriden by %pragma
70   String *upcasts_code;         //C++ casts for inheritance hierarchies C++ code
71   String *imclass_cppcasts_code;        //C++ casts up inheritance hierarchies intermediary class code
72   String *imclass_directors;    // Intermediate class director code
73   String *destructor_call;      //C++ destructor call if any
74   String *destructor_throws_clause;     //C++ destructor throws clause if any
75
76   // Director method stuff:
77   List *dmethods_seq;
78   Hash *dmethods_table;
79   int n_dmethods;
80   int n_directors;
81   int first_class_dmethod;
82   int curr_class_dmethod;
83
84   enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
85
86   static Parm *NewParmFromNode(SwigType *type, const_String_or_char_ptr name, Node *n) {
87     Parm *p = NewParm(type, name);
88     Setfile(p, Getfile(n));
89     Setline(p, Getline(n));
90     return p;
91   }
92
93 public:
94
95   /* -----------------------------------------------------------------------------
96    * JAVA()
97    * ----------------------------------------------------------------------------- */
98
99    JAVA():empty_string(NewString("")),
100       public_string(NewString("public")),
101       protected_string(NewString("protected")),
102       swig_types_hash(NULL),
103       f_begin(NULL),
104       f_runtime(NULL),
105       f_runtime_h(NULL),
106       f_header(NULL),
107       f_wrappers(NULL),
108       f_init(NULL),
109       f_directors(NULL),
110       f_directors_h(NULL),
111       filenames_list(NULL),
112       proxy_flag(true),
113       nopgcpp_flag(false),
114       native_function_flag(false),
115       enum_constant_flag(false),
116       static_flag(false),
117       variable_wrapper_flag(false),
118       wrapping_member_flag(false),
119       global_variable_flag(false),
120       old_variable_names(false),
121       member_func_flag(false),
122       imclass_name(NULL),
123       module_class_name(NULL),
124       imclass_class_code(NULL),
125       proxy_class_def(NULL),
126       proxy_class_code(NULL),
127       module_class_code(NULL),
128       proxy_class_name(NULL),
129       variable_name(NULL),
130       proxy_class_constants_code(NULL),
131       module_class_constants_code(NULL),
132       package(NULL),
133       jnipackage(NULL),
134       package_path(NULL),
135       imclass_imports(NULL),
136       module_imports(NULL),
137       imclass_baseclass(NULL),
138       module_baseclass(NULL),
139       imclass_interfaces(NULL),
140       module_interfaces(NULL),
141       imclass_class_modifiers(NULL),
142       module_class_modifiers(NULL),
143       upcasts_code(NULL),
144       imclass_cppcasts_code(NULL),
145       imclass_directors(NULL),
146       destructor_call(NULL),
147       destructor_throws_clause(NULL),
148       dmethods_seq(NULL),
149       dmethods_table(NULL),
150       n_dmethods(0),
151       n_directors(0) {
152     /* for now, multiple inheritance in directors is disabled, this
153        should be easy to implement though */
154     director_multiple_inheritance = 0;
155     director_language = 1;
156   }
157
158   /* -----------------------------------------------------------------------------
159    * getProxyName()
160    *
161    * Test to see if a type corresponds to something wrapped with a proxy class
162    * Return NULL if not otherwise the proxy class name
163    * ----------------------------------------------------------------------------- */
164   
165    String *getProxyName(SwigType *t) {
166     if (proxy_flag) {
167       Node *n = classLookup(t);
168       if (n) {
169         return Getattr(n, "sym:name");
170       }
171     }
172     return NULL;
173   }
174
175   /* -----------------------------------------------------------------------------
176    * makeValidJniName()
177    * ----------------------------------------------------------------------------- */
178
179   String *makeValidJniName(const String *name) {
180     String *valid_jni_name = NewString(name);
181     Replaceall(valid_jni_name, "_", "_1");
182     return valid_jni_name;
183   }
184
185   /* -----------------------------------------------------------------------------
186    * directorClassName()
187    * ----------------------------------------------------------------------------- */
188
189   String *directorClassName(Node *n) {
190     String *dirclassname;
191     const char *attrib = "director:classname";
192
193     if (!(dirclassname = Getattr(n, attrib))) {
194       String *classname = Getattr(n, "sym:name");
195
196       dirclassname = NewStringf("SwigDirector_%s", classname);
197       Setattr(n, attrib, dirclassname);
198     }
199
200     return dirclassname;
201   }
202
203   /* ------------------------------------------------------------
204    * main()
205    * ------------------------------------------------------------ */
206
207   virtual void main(int argc, char *argv[]) {
208
209     SWIG_library_directory("java");
210
211     // Look for certain command line options
212     for (int i = 1; i < argc; i++) {
213       if (argv[i]) {
214         if (strcmp(argv[i], "-package") == 0) {
215           if (argv[i + 1]) {
216             package = NewString("");
217             Printf(package, argv[i + 1]);
218             Swig_mark_arg(i);
219             Swig_mark_arg(i + 1);
220             i++;
221           } else {
222             Swig_arg_error();
223           }
224         } else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) {
225           Printf(stderr, "Deprecated command line option: %s. Proxy classes are now generated by default.\n", argv[i]);
226           Swig_mark_arg(i);
227           proxy_flag = true;
228         } else if ((strcmp(argv[i], "-noproxy") == 0)) {
229           Swig_mark_arg(i);
230           proxy_flag = false;
231         } else if (strcmp(argv[i], "-nopgcpp") == 0) {
232           Swig_mark_arg(i);
233           nopgcpp_flag = true;
234         } else if (strcmp(argv[i], "-oldvarnames") == 0) {
235           Swig_mark_arg(i);
236           old_variable_names = true;
237         } else if (strcmp(argv[i], "-jnic") == 0) {
238           Swig_mark_arg(i);
239           Printf(stderr, "Deprecated command line option: -jnic. C JNI calling convention now used when -c++ not specified.\n");
240         } else if (strcmp(argv[i], "-nofinalize") == 0) {
241           Swig_mark_arg(i);
242           Printf(stderr, "Deprecated command line option: -nofinalize. Use the new javafinalize typemap instead.\n");
243         } else if (strcmp(argv[i], "-jnicpp") == 0) {
244           Swig_mark_arg(i);
245           Printf(stderr, "Deprecated command line option: -jnicpp. C++ JNI calling convention now used when -c++ specified.\n");
246         } else if (strcmp(argv[i], "-help") == 0) {
247           Printf(stdout, "%s\n", usage);
248         }
249       }
250     }
251
252     // Add a symbol to the parser for conditional compilation
253     Preprocessor_define("SWIGJAVA 1", 0);
254
255     // Add typemap definitions
256     SWIG_typemap_lang("java");
257     SWIG_config_file("java.swg");
258
259     allow_overloading();
260   }
261
262   /* ---------------------------------------------------------------------
263    * top()
264    * --------------------------------------------------------------------- */
265
266   virtual int top(Node *n) {
267
268     // Get any options set in the module directive
269     Node *optionsnode = Getattr(Getattr(n, "module"), "options");
270
271     if (optionsnode) {
272       if (Getattr(optionsnode, "jniclassname"))
273         imclass_name = Copy(Getattr(optionsnode, "jniclassname"));
274       /* check if directors are enabled for this module.  note: this 
275        * is a "master" switch, without which no director code will be
276        * emitted.  %feature("director") statements are also required
277        * to enable directors for individual classes or methods.
278        *
279        * use %module(directors="1") modulename at the start of the 
280        * interface file to enable director generation.
281        */
282       if (Getattr(optionsnode, "directors")) {
283         allow_directors();
284       }
285       if (Getattr(optionsnode, "dirprot")) {
286         allow_dirprot();
287       }
288       allow_allprotected(GetFlag(optionsnode, "allprotected"));
289     }
290
291     /* Initialize all of the output files */
292     String *outfile = Getattr(n, "outfile");
293     String *outfile_h = Getattr(n, "outfile_h");
294
295     if (!outfile) {
296       Printf(stderr, "Unable to determine outfile\n");
297       SWIG_exit(EXIT_FAILURE);
298     }
299
300     f_begin = NewFile(outfile, "w", SWIG_output_files());
301     if (!f_begin) {
302       FileErrorDisplay(outfile);
303       SWIG_exit(EXIT_FAILURE);
304     }
305
306     if (directorsEnabled()) {
307       if (!outfile_h) {
308         Printf(stderr, "Unable to determine outfile_h\n");
309         SWIG_exit(EXIT_FAILURE);
310       }
311       f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
312       if (!f_runtime_h) {
313         FileErrorDisplay(outfile_h);
314         SWIG_exit(EXIT_FAILURE);
315       }
316     }
317
318     f_runtime = NewString("");
319     f_init = NewString("");
320     f_header = NewString("");
321     f_wrappers = NewString("");
322     f_directors_h = NewString("");
323     f_directors = NewString("");
324
325     /* Register file targets with the SWIG file handler */
326     Swig_register_filebyname("begin", f_begin);
327     Swig_register_filebyname("header", f_header);
328     Swig_register_filebyname("wrapper", f_wrappers);
329     Swig_register_filebyname("runtime", f_runtime);
330     Swig_register_filebyname("init", f_init);
331     Swig_register_filebyname("director", f_directors);
332     Swig_register_filebyname("director_h", f_directors_h);
333
334     swig_types_hash = NewHash();
335     filenames_list = NewList();
336
337     // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
338     if (!imclass_name) {
339       imclass_name = NewStringf("%sJNI", Getattr(n, "name"));
340       module_class_name = Copy(Getattr(n, "name"));
341     } else {
342       // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
343       if (Cmp(imclass_name, Getattr(n, "name")) == 0)
344         module_class_name = NewStringf("%sModule", Getattr(n, "name"));
345       else
346         module_class_name = Copy(Getattr(n, "name"));
347     }
348
349     imclass_class_code = NewString("");
350     proxy_class_def = NewString("");
351     proxy_class_code = NewString("");
352     module_class_constants_code = NewString("");
353     imclass_baseclass = NewString("");
354     imclass_interfaces = NewString("");
355     imclass_class_modifiers = NewString("");
356     module_class_code = NewString("");
357     module_baseclass = NewString("");
358     module_interfaces = NewString("");
359     module_imports = NewString("");
360     module_class_modifiers = NewString("");
361     imclass_imports = NewString("");
362     imclass_cppcasts_code = NewString("");
363     imclass_directors = NewString("");
364     upcasts_code = NewString("");
365     dmethods_seq = NewList();
366     dmethods_table = NewHash();
367     n_dmethods = 0;
368     n_directors = 0;
369     if (!package)
370       package = NewString("");
371     jnipackage = NewString("");
372     package_path = NewString("");
373
374     Swig_banner(f_begin);
375
376     Printf(f_runtime, "\n#define SWIGJAVA\n");
377
378     if (directorsEnabled()) {
379       Printf(f_runtime, "#define SWIG_DIRECTORS\n");
380
381       /* Emit initial director header and director code: */
382       Swig_banner(f_directors_h);
383       Printf(f_directors_h, "\n");
384       Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name);
385       Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name);
386
387       Printf(f_directors, "\n\n");
388       Printf(f_directors, "/* ---------------------------------------------------\n");
389       Printf(f_directors, " * C++ director class methods\n");
390       Printf(f_directors, " * --------------------------------------------------- */\n\n");
391       if (outfile_h)
392         Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h));
393     }
394
395     Printf(f_runtime, "\n");
396
397     String *wrapper_name = NewString("");
398
399     if (Len(package)) {
400       String *jniname = makeValidJniName(package);
401       Printv(jnipackage, jniname, NIL);
402       Delete(jniname);
403       Replaceall(jnipackage, ".", "_");
404       Append(jnipackage, "_");
405       Printv(package_path, package, NIL);
406       Replaceall(package_path, ".", "/");
407     }
408     String *jniname = makeValidJniName(imclass_name);
409     Printf(wrapper_name, "Java_%s%s_%%f", Char(jnipackage), jniname);
410     Delete(jniname);
411
412     Swig_name_register((char *) "wrapper", Char(wrapper_name));
413     if (old_variable_names) {
414       Swig_name_register((char *) "set", (char *) "set_%v");
415       Swig_name_register((char *) "get", (char *) "get_%v");
416     }
417
418     Delete(wrapper_name);
419
420     Printf(f_wrappers, "\n#ifdef __cplusplus\n");
421     Printf(f_wrappers, "extern \"C\" {\n");
422     Printf(f_wrappers, "#endif\n\n");
423
424     /* Emit code */
425     Language::top(n);
426
427     if (directorsEnabled()) {
428       // Insert director runtime into the f_runtime file (make it occur before %header section)
429       Swig_insert_file("director.swg", f_runtime);
430     }
431     // Generate the intermediary class
432     {
433       String *filen = NewStringf("%s%s.java", SWIG_output_directory(), imclass_name);
434       File *f_im = NewFile(filen, "w", SWIG_output_files());
435       if (!f_im) {
436         FileErrorDisplay(filen);
437         SWIG_exit(EXIT_FAILURE);
438       }
439       Append(filenames_list, Copy(filen));
440       Delete(filen);
441       filen = NULL;
442
443       // Start writing out the intermediary class file
444       emitBanner(f_im);
445
446       if (Len(package) > 0)
447         Printf(f_im, "package %s;\n", package);
448
449       if (imclass_imports)
450         Printf(f_im, "%s\n", imclass_imports);
451
452       if (Len(imclass_class_modifiers) > 0)
453         Printf(f_im, "%s ", imclass_class_modifiers);
454       Printf(f_im, "%s ", imclass_name);
455
456       if (imclass_baseclass && *Char(imclass_baseclass))
457         Printf(f_im, "extends %s ", imclass_baseclass);
458       if (Len(imclass_interfaces) > 0)
459         Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
460       Printf(f_im, "{\n");
461
462       // Add the intermediary class methods
463       Replaceall(imclass_class_code, "$module", module_class_name);
464       Replaceall(imclass_class_code, "$imclassname", imclass_name);
465       Printv(f_im, imclass_class_code, NIL);
466       Printv(f_im, imclass_cppcasts_code, NIL);
467       if (Len(imclass_directors) > 0)
468         Printv(f_im, "\n", imclass_directors, NIL);
469
470       if (n_dmethods > 0) {
471         Putc('\n', f_im);
472         Printf(f_im, "  private final static native void swig_module_init();\n");
473         Printf(f_im, "  static {\n");
474         Printf(f_im, "    swig_module_init();\n");
475         Printf(f_im, "  }\n");
476       }
477       // Finish off the class
478       Printf(f_im, "}\n");
479       Close(f_im);
480     }
481
482     // Generate the Java module class
483     {
484       String *filen = NewStringf("%s%s.java", SWIG_output_directory(), module_class_name);
485       File *f_module = NewFile(filen, "w", SWIG_output_files());
486       if (!f_module) {
487         FileErrorDisplay(filen);
488         SWIG_exit(EXIT_FAILURE);
489       }
490       Append(filenames_list, Copy(filen));
491       Delete(filen);
492       filen = NULL;
493
494       // Start writing out the module class file
495       emitBanner(f_module);
496
497       if (Len(package) > 0)
498         Printf(f_module, "package %s;\n", package);
499
500       if (module_imports)
501         Printf(f_module, "%s\n", module_imports);
502
503       if (Len(module_class_modifiers) > 0)
504         Printf(f_module, "%s ", module_class_modifiers);
505       Printf(f_module, "%s ", module_class_name);
506
507       if (module_baseclass && *Char(module_baseclass))
508         Printf(f_module, "extends %s ", module_baseclass);
509       if (Len(module_interfaces) > 0) {
510         if (Len(module_class_constants_code) != 0)
511           Printv(f_module, "implements ", Getattr(n, "name"), "Constants, ", module_interfaces, " ", NIL);
512         else
513           Printv(f_module, "implements ", module_interfaces, " ", NIL);
514       } else {
515         if (Len(module_class_constants_code) != 0)
516           Printv(f_module, "implements ", Getattr(n, "name"), "Constants ", NIL);
517       }
518       Printf(f_module, "{\n");
519
520       Replaceall(module_class_code, "$module", module_class_name);
521       Replaceall(module_class_constants_code, "$module", module_class_name);
522
523       Replaceall(module_class_code, "$imclassname", imclass_name);
524       Replaceall(module_class_constants_code, "$imclassname", imclass_name);
525
526       // Add the wrapper methods
527       Printv(f_module, module_class_code, NIL);
528
529       // Finish off the class
530       Printf(f_module, "}\n");
531       Close(f_module);
532     }
533
534     // Generate the Java constants interface
535     if (Len(module_class_constants_code) != 0) {
536       String *filen = NewStringf("%s%sConstants.java", SWIG_output_directory(), module_class_name);
537       File *f_module = NewFile(filen, "w", SWIG_output_files());
538       if (!f_module) {
539         FileErrorDisplay(filen);
540         SWIG_exit(EXIT_FAILURE);
541       }
542       Append(filenames_list, Copy(filen));
543       Delete(filen);
544       filen = NULL;
545
546       // Start writing out the Java constants interface file
547       emitBanner(f_module);
548
549       if (Len(package) > 0)
550         Printf(f_module, "package %s;\n", package);
551
552       if (module_imports)
553         Printf(f_module, "%s\n", module_imports);
554
555       Printf(f_module, "public interface %sConstants {\n", module_class_name);
556
557       // Write out all the global constants
558       Printv(f_module, module_class_constants_code, NIL);
559
560       // Finish off the Java interface
561       Printf(f_module, "}\n");
562       Close(f_module);
563     }
564
565     if (upcasts_code)
566       Printv(f_wrappers, upcasts_code, NIL);
567
568     emitDirectorUpcalls();
569
570     Printf(f_wrappers, "#ifdef __cplusplus\n");
571     Printf(f_wrappers, "}\n");
572     Printf(f_wrappers, "#endif\n");
573
574     // Output a Java type wrapper class for each SWIG type
575     for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
576       emitTypeWrapperClass(swig_type.key, swig_type.item);
577     }
578
579     // Check for overwriting file problems on filesystems that are case insensitive
580     Iterator it1;
581     Iterator it2;
582     for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
583       String *item1_lower = Swig_string_lower(it1.item);
584       for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
585         String *item2_lower = Swig_string_lower(it2.item);
586         if (it1.item && it2.item) {
587           if (Strcmp(item1_lower, item2_lower) == 0) {
588             Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
589                          "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
590                          "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
591           }
592         }
593         Delete(item2_lower);
594       }
595       Delete(item1_lower);
596     }
597
598     Delete(swig_types_hash);
599     swig_types_hash = NULL;
600     Delete(filenames_list);
601     filenames_list = NULL;
602     Delete(imclass_name);
603     imclass_name = NULL;
604     Delete(imclass_class_code);
605     imclass_class_code = NULL;
606     Delete(proxy_class_def);
607     proxy_class_def = NULL;
608     Delete(proxy_class_code);
609     proxy_class_code = NULL;
610     Delete(module_class_constants_code);
611     module_class_constants_code = NULL;
612     Delete(imclass_baseclass);
613     imclass_baseclass = NULL;
614     Delete(imclass_interfaces);
615     imclass_interfaces = NULL;
616     Delete(imclass_class_modifiers);
617     imclass_class_modifiers = NULL;
618     Delete(module_class_name);
619     module_class_name = NULL;
620     Delete(module_class_code);
621     module_class_code = NULL;
622     Delete(module_baseclass);
623     module_baseclass = NULL;
624     Delete(module_interfaces);
625     module_interfaces = NULL;
626     Delete(module_imports);
627     module_imports = NULL;
628     Delete(module_class_modifiers);
629     module_class_modifiers = NULL;
630     Delete(imclass_imports);
631     imclass_imports = NULL;
632     Delete(imclass_cppcasts_code);
633     imclass_cppcasts_code = NULL;
634     Delete(imclass_directors);
635     imclass_directors = NULL;
636     Delete(upcasts_code);
637     upcasts_code = NULL;
638     Delete(package);
639     package = NULL;
640     Delete(jnipackage);
641     jnipackage = NULL;
642     Delete(package_path);
643     package_path = NULL;
644     Delete(dmethods_seq);
645     dmethods_seq = NULL;
646     Delete(dmethods_table);
647     dmethods_table = NULL;
648     n_dmethods = 0;
649
650     /* Close all of the files */
651     Dump(f_header, f_runtime);
652
653     if (directorsEnabled()) {
654       Dump(f_directors, f_runtime);
655       Dump(f_directors_h, f_runtime_h);
656
657       Printf(f_runtime_h, "\n");
658       Printf(f_runtime_h, "#endif\n");
659
660       Close(f_runtime_h);
661       Delete(f_runtime_h);
662       f_runtime_h = NULL;
663       Delete(f_directors);
664       f_directors = NULL;
665       Delete(f_directors_h);
666       f_directors_h = NULL;
667     }
668
669     Dump(f_wrappers, f_runtime);
670     Wrapper_pretty_print(f_init, f_runtime);
671     Delete(f_header);
672     Delete(f_wrappers);
673     Delete(f_init);
674     Dump(f_runtime, f_begin);
675     Delete(f_runtime);
676     Close(f_begin);
677     Delete(f_begin);
678     return SWIG_OK;
679   }
680
681   /* -----------------------------------------------------------------------------
682    * emitBanner()
683    * ----------------------------------------------------------------------------- */
684
685   void emitBanner(File *f) {
686     Printf(f, "/* ----------------------------------------------------------------------------\n");
687     Swig_banner_target_lang(f, " *");
688     Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
689   }
690
691   /*-----------------------------------------------------------------------
692    * Add new director upcall signature
693    *----------------------------------------------------------------------*/
694
695   UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *imclass_desc, String *class_desc, String *decl) {
696     UpcallData *udata;
697     String *imclass_methodidx;
698     String *class_methodidx;
699     Hash *new_udata;
700     String *key = NewStringf("%s|%s", imclass_method, decl);
701
702     ++curr_class_dmethod;
703
704     /* Do we know about this director class already? */
705     if ((udata = Getattr(dmethods_table, key))) {
706       Delete(key);
707       return Getattr(udata, "methodoff");
708     }
709
710     imclass_methodidx = NewStringf("%d", n_dmethods);
711     class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
712     n_dmethods++;
713
714     new_udata = NewHash();
715     Append(dmethods_seq, new_udata);
716     Setattr(dmethods_table, key, new_udata);
717
718     Setattr(new_udata, "method", Copy(class_method));
719     Setattr(new_udata, "fdesc", Copy(class_desc));
720     Setattr(new_udata, "imclass_method", Copy(imclass_method));
721     Setattr(new_udata, "imclass_fdesc", Copy(imclass_desc));
722     Setattr(new_udata, "imclass_methodidx", imclass_methodidx);
723     Setattr(new_udata, "class_methodidx", class_methodidx);
724     Setattr(new_udata, "decl", Copy(decl));
725
726     Delete(key);
727     return new_udata;
728   }
729
730   /*-----------------------------------------------------------------------
731    * Get director upcall signature
732    *----------------------------------------------------------------------*/
733
734   UpcallData *getUpcallMethodData(String *director_class, String *decl) {
735     String *key = NewStringf("%s|%s", director_class, decl);
736     UpcallData *udata = Getattr(dmethods_table, key);
737
738     Delete(key);
739     return udata;
740   }
741
742   /* ----------------------------------------------------------------------
743    * nativeWrapper()
744    * ---------------------------------------------------------------------- */
745
746   virtual int nativeWrapper(Node *n) {
747     String *wrapname = Getattr(n, "wrap:name");
748
749     if (!addSymbol(wrapname, n))
750       return SWIG_ERROR;
751
752     if (Getattr(n, "type")) {
753       Swig_save("nativeWrapper", n, "name", NIL);
754       Setattr(n, "name", wrapname);
755       native_function_flag = true;
756       functionWrapper(n);
757       Swig_restore(n);
758       native_function_flag = false;
759     } else {
760       Printf(stderr, "%s : Line %d. No return type for %%native method %s.\n", input_file, line_number, Getattr(n, "wrap:name"));
761     }
762
763     return SWIG_OK;
764   }
765
766   /* ----------------------------------------------------------------------
767    * functionWrapper()
768    * ---------------------------------------------------------------------- */
769
770   virtual int functionWrapper(Node *n) {
771     String *symname = Getattr(n, "sym:name");
772     SwigType *t = Getattr(n, "type");
773     ParmList *l = Getattr(n, "parms");
774     String *tm;
775     Parm *p;
776     int i;
777     String *c_return_type = NewString("");
778     String *im_return_type = NewString("");
779     String *cleanup = NewString("");
780     String *outarg = NewString("");
781     String *body = NewString("");
782     int num_arguments = 0;
783     int num_required = 0;
784     int gencomma = 0;
785     bool is_void_return;
786     String *overloaded_name = getOverloadedName(n);
787     String *nondir_args = NewString("");
788     bool is_destructor = (Cmp(Getattr(n, "nodeType"), "destructor") == 0);
789
790     if (!Getattr(n, "sym:overloaded")) {
791       if (!addSymbol(Getattr(n, "sym:name"), n))
792         return SWIG_ERROR;
793     }
794
795     /*
796        The rest of this function deals with generating the intermediary class wrapper function (that wraps
797        a c/c++ function) and generating the JNI c code. Each Java wrapper function has a 
798        matching JNI c function call.
799      */
800
801     // A new wrapper function object
802     Wrapper *f = NewWrapper();
803
804     // Make a wrapper name for this function
805     String *jniname = makeValidJniName(overloaded_name);
806     String *wname = Swig_name_wrapper(jniname);
807
808     Delete(jniname);
809
810     /* Attach the non-standard typemaps to the parameter list. */
811     Swig_typemap_attach_parms("jni", l, f);
812     Swig_typemap_attach_parms("jtype", l, f);
813     Swig_typemap_attach_parms("jstype", l, f);
814
815     /* Get return types */
816     if ((tm = Swig_typemap_lookup("jni", n, "", 0))) {
817       Printf(c_return_type, "%s", tm);
818     } else {
819       Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(t, 0));
820     }
821
822     if ((tm = Swig_typemap_lookup("jtype", n, "", 0))) {
823       Printf(im_return_type, "%s", tm);
824     } else {
825       Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(t, 0));
826     }
827
828     is_void_return = (Cmp(c_return_type, "void") == 0);
829     if (!is_void_return)
830       Wrapper_add_localv(f, "jresult", c_return_type, "jresult = 0", NIL);
831
832     Printv(f->def, "SWIGEXPORT ", c_return_type, " JNICALL ", wname, "(JNIEnv *jenv, jclass jcls", NIL);
833
834     // Usually these function parameters are unused - The code below ensures
835     // that compilers do not issue such a warning if configured to do so.
836
837     Printv(f->code, "    (void)jenv;\n", NIL);
838     Printv(f->code, "    (void)jcls;\n", NIL);
839
840     // Emit all of the local variables for holding arguments.
841     emit_parameter_variables(l, f);
842
843     /* Attach the standard typemaps */
844     emit_attach_parmmaps(l, f);
845
846     // Parameter overloading
847     Setattr(n, "wrap:parms", l);
848     Setattr(n, "wrap:name", wname);
849
850     // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
851     if (Getattr(n, "sym:overloaded")) {
852       // Emit warnings for the few cases that can't be overloaded in Java and give up on generating wrapper
853       Swig_overload_check(n);
854       if (Getattr(n, "overload:ignore"))
855         return SWIG_OK;
856     }
857
858     Printf(imclass_class_code, "  public final static native %s %s(", im_return_type, overloaded_name);
859
860     /* Get number of required and total arguments */
861     num_arguments = emit_num_arguments(l);
862     num_required = emit_num_required(l);
863
864     // Now walk the function parameter list and generate code to get arguments
865     for (i = 0, p = l; i < num_arguments; i++) {
866
867       while (checkAttribute(p, "tmap:in:numinputs", "0")) {
868         p = Getattr(p, "tmap:in:next");
869       }
870
871       SwigType *pt = Getattr(p, "type");
872       String *ln = Getattr(p, "lname");
873       String *im_param_type = NewString("");
874       String *c_param_type = NewString("");
875       String *arg = NewString("");
876
877       Printf(arg, "j%s", ln);
878
879       /* Get the JNI C types of the parameter */
880       if ((tm = Getattr(p, "tmap:jni"))) {
881         Printv(c_param_type, tm, NIL);
882       } else {
883         Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(pt, 0));
884       }
885
886       /* Get the intermediary class parameter types of the parameter */
887       if ((tm = Getattr(p, "tmap:jtype"))) {
888         Printv(im_param_type, tm, NIL);
889       } else {
890         Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(pt, 0));
891       }
892
893       /* Add parameter to intermediary class method */
894       if (gencomma)
895         Printf(imclass_class_code, ", ");
896       Printf(imclass_class_code, "%s %s", im_param_type, arg);
897
898       // Add parameter to C function
899       Printv(f->def, ", ", c_param_type, " ", arg, NIL);
900
901       ++gencomma;
902
903       // Premature garbage collection prevention parameter
904       if (!is_destructor) {
905         String *pgc_parameter = prematureGarbageCollectionPreventionParameter(pt, p);
906         if (pgc_parameter) {
907           Printf(imclass_class_code, ", %s %s_", pgc_parameter, arg);
908           Printf(f->def, ", jobject %s_", arg);
909           Printf(f->code, "    (void)%s_;\n", arg);
910         }
911       }
912       // Get typemap for this argument
913       if ((tm = Getattr(p, "tmap:in"))) {
914         addThrows(n, "tmap:in", p);
915         Replaceall(tm, "$source", arg); /* deprecated */
916         Replaceall(tm, "$target", ln);  /* deprecated */
917         Replaceall(tm, "$arg", arg);    /* deprecated? */
918         Replaceall(tm, "$input", arg);
919         Setattr(p, "emit:input", arg);
920
921         Printf(nondir_args, "%s\n", tm);
922
923         p = Getattr(p, "tmap:in:next");
924       } else {
925         Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
926         p = nextSibling(p);
927       }
928
929       Delete(im_param_type);
930       Delete(c_param_type);
931       Delete(arg);
932     }
933
934     Printv(f->code, nondir_args, NIL);
935     Delete(nondir_args);
936
937     /* Insert constraint checking code */
938     for (p = l; p;) {
939       if ((tm = Getattr(p, "tmap:check"))) {
940         addThrows(n, "tmap:check", p);
941         Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
942         Replaceall(tm, "$arg", Getattr(p, "emit:input"));       /* deprecated? */
943         Replaceall(tm, "$input", Getattr(p, "emit:input"));
944         Printv(f->code, tm, "\n", NIL);
945         p = Getattr(p, "tmap:check:next");
946       } else {
947         p = nextSibling(p);
948       }
949     }
950
951     /* Insert cleanup code */
952     for (p = l; p;) {
953       if ((tm = Getattr(p, "tmap:freearg"))) {
954         addThrows(n, "tmap:freearg", p);
955         Replaceall(tm, "$source", Getattr(p, "emit:input"));    /* deprecated */
956         Replaceall(tm, "$arg", Getattr(p, "emit:input"));       /* deprecated? */
957         Replaceall(tm, "$input", Getattr(p, "emit:input"));
958         Printv(cleanup, tm, "\n", NIL);
959         p = Getattr(p, "tmap:freearg:next");
960       } else {
961         p = nextSibling(p);
962       }
963     }
964
965     /* Insert argument output code */
966     for (p = l; p;) {
967       if ((tm = Getattr(p, "tmap:argout"))) {
968         addThrows(n, "tmap:argout", p);
969         Replaceall(tm, "$source", Getattr(p, "emit:input"));    /* deprecated */
970         Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
971         Replaceall(tm, "$arg", Getattr(p, "emit:input"));       /* deprecated? */
972         Replaceall(tm, "$result", "jresult");
973         Replaceall(tm, "$input", Getattr(p, "emit:input"));
974         Printv(outarg, tm, "\n", NIL);
975         p = Getattr(p, "tmap:argout:next");
976       } else {
977         p = nextSibling(p);
978       }
979     }
980
981     // Get any Java exception classes in the throws typemap
982     ParmList *throw_parm_list = NULL;
983     if ((throw_parm_list = Getattr(n, "catchlist"))) {
984       Swig_typemap_attach_parms("throws", throw_parm_list, f);
985       for (p = throw_parm_list; p; p = nextSibling(p)) {
986         if ((tm = Getattr(p, "tmap:throws"))) {
987           addThrows(n, "tmap:throws", p);
988         }
989       }
990     }
991
992     if (!native_function_flag) {
993       if (Cmp(nodeType(n), "constant") == 0) {
994         // Wrapping a constant hack
995         Swig_save("functionWrapper", n, "wrap:action", NIL);
996
997         // below based on Swig_VargetToFunction()
998         SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
999         Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value")));
1000       }
1001
1002       // Now write code to make the function call
1003       Swig_director_emit_dynamic_cast(n, f);
1004       String *actioncode = emit_action(n);
1005
1006       // Handle exception classes specified in the "except" feature's "throws" attribute
1007       addThrows(n, "feature:except", n);
1008
1009       if (Cmp(nodeType(n), "constant") == 0)
1010         Swig_restore(n);
1011
1012       /* Return value if necessary  */
1013       if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
1014         addThrows(n, "tmap:out", n);
1015         Replaceall(tm, "$source", "result");    /* deprecated */
1016         Replaceall(tm, "$target", "jresult");   /* deprecated */
1017         Replaceall(tm, "$result", "jresult");
1018
1019         if (GetFlag(n, "feature:new"))
1020           Replaceall(tm, "$owner", "1");
1021         else
1022           Replaceall(tm, "$owner", "0");
1023
1024         Printf(f->code, "%s", tm);
1025         if (Len(tm))
1026           Printf(f->code, "\n");
1027       } else {
1028         Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(t, 0), Getattr(n, "name"));
1029       }
1030       emit_return_variable(n, t, f);
1031     }
1032
1033     /* Output argument output code */
1034     Printv(f->code, outarg, NIL);
1035
1036     /* Output cleanup code */
1037     Printv(f->code, cleanup, NIL);
1038
1039     /* Look to see if there is any newfree cleanup code */
1040     if (GetFlag(n, "feature:new")) {
1041       if ((tm = Swig_typemap_lookup("newfree", n, "result", 0))) {
1042         addThrows(n, "tmap:newfree", n);
1043         Replaceall(tm, "$source", "result");    /* deprecated */
1044         Printf(f->code, "%s\n", tm);
1045       }
1046     }
1047
1048     /* See if there is any return cleanup code */
1049     if (!native_function_flag) {
1050       if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
1051         addThrows(n, "tmap:ret", n);
1052         Replaceall(tm, "$source", "result");    /* deprecated */
1053         Printf(f->code, "%s\n", tm);
1054       }
1055     }
1056
1057     /* Finish C function and intermediary class function definitions */
1058     Printf(imclass_class_code, ")");
1059     generateThrowsClause(n, imclass_class_code);
1060     Printf(imclass_class_code, ";\n");
1061
1062     Printf(f->def, ") {");
1063
1064     if (!is_void_return)
1065       Printv(f->code, "    return jresult;\n", NIL);
1066     Printf(f->code, "}\n");
1067
1068     /* Substitute the cleanup code */
1069     Replaceall(f->code, "$cleanup", cleanup);
1070
1071     /* Substitute the function name */
1072     Replaceall(f->code, "$symname", symname);
1073
1074     /* Contract macro modification */
1075     Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ");
1076
1077     if (!is_void_return)
1078       Replaceall(f->code, "$null", "0");
1079     else
1080       Replaceall(f->code, "$null", "");
1081
1082     /* Dump the function out */
1083     if (!native_function_flag)
1084       Wrapper_print(f, f_wrappers);
1085
1086     if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
1087       moduleClassFunctionHandler(n);
1088     }
1089
1090     /* 
1091      * Generate the proxy class getters/setters for public member variables.
1092      * Not for enums and constants.
1093      */
1094     if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
1095       // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name
1096       bool getter_flag = Cmp(symname, Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) != 0;
1097
1098       String *getter_setter_name = NewString("");
1099       if (!getter_flag)
1100         Printf(getter_setter_name, "set");
1101       else
1102         Printf(getter_setter_name, "get");
1103       Putc(toupper((int) *Char(variable_name)), getter_setter_name);
1104       Printf(getter_setter_name, "%s", Char(variable_name) + 1);
1105
1106       Setattr(n, "proxyfuncname", getter_setter_name);
1107       Setattr(n, "imfuncname", symname);
1108
1109       proxyClassFunctionHandler(n);
1110       Delete(getter_setter_name);
1111     }
1112
1113     Delete(c_return_type);
1114     Delete(im_return_type);
1115     Delete(cleanup);
1116     Delete(outarg);
1117     Delete(body);
1118     Delete(overloaded_name);
1119     DelWrapper(f);
1120     return SWIG_OK;
1121   }
1122
1123   /* -----------------------------------------------------------------------
1124    * variableWrapper()
1125    * ----------------------------------------------------------------------- */
1126
1127   virtual int variableWrapper(Node *n) {
1128     variable_wrapper_flag = true;
1129     Language::variableWrapper(n);       /* Default to functions */
1130     variable_wrapper_flag = false;
1131     return SWIG_OK;
1132   }
1133
1134   /* -----------------------------------------------------------------------
1135    * globalvariableHandler()
1136    * ------------------------------------------------------------------------ */
1137
1138   virtual int globalvariableHandler(Node *n) {
1139
1140     variable_name = Getattr(n, "sym:name");
1141     global_variable_flag = true;
1142     int ret = Language::globalvariableHandler(n);
1143     global_variable_flag = false;
1144     return ret;
1145   }
1146
1147   /* ----------------------------------------------------------------------
1148    * enumDeclaration()
1149    *
1150    * C/C++ enums can be mapped in one of 4 ways, depending on the java:enum feature specified:
1151    * 1) Simple enums - simple constant within the proxy class or module class
1152    * 2) Typeunsafe enums - simple constant in a Java class (class named after the c++ enum name)
1153    * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
1154    * 4) Proper enums - proper Java enum
1155    * Anonymous enums always default to 1)
1156    * ---------------------------------------------------------------------- */
1157
1158   virtual int enumDeclaration(Node *n) {
1159
1160     if (!ImportMode) {
1161       if (getCurrentClass() && (cplus_mode != PUBLIC))
1162         return SWIG_NOWRAP;
1163
1164       enum_code = NewString("");
1165       String *symname = Getattr(n, "sym:name");
1166       String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code;
1167       EnumFeature enum_feature = decodeEnumFeature(n);
1168       String *typemap_lookup_type = Getattr(n, "name");
1169
1170       if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
1171         // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum
1172
1173         // Pure Java baseclass and interfaces
1174         const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE);
1175         const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
1176
1177         // Emit the enum
1178         Printv(enum_code, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF),        // Class modifiers (enum modifiers really)
1179                " ", symname, *Char(pure_baseclass) ?    // Bases
1180                " extends " : "", pure_baseclass, *Char(pure_interfaces) ?       // Interfaces
1181                " implements " : "", pure_interfaces, " {\n", NIL);
1182         if (proxy_flag && is_wrapping_class())
1183           Replaceall(enum_code, "$static ", "static ");
1184         else
1185           Replaceall(enum_code, "$static ", "");
1186       } else {
1187         // Wrap C++ enum with integers - just indicate start of enum with a comment, no comment for anonymous enums of any sort
1188         if (symname && !Getattr(n, "unnamedinstance"))
1189           Printf(constants_code, "  // %s \n", symname);
1190       }
1191
1192       // Emit each enum item
1193       Language::enumDeclaration(n);
1194
1195       if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
1196         // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum
1197         // Finish the enum declaration
1198         // Typemaps are used to generate the enum definition in a similar manner to proxy classes.
1199         Printv(enum_code, (enum_feature == ProperEnum) ? ";\n" : "", typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF),       // main body of class
1200                typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE),    // extra Java code
1201                "}", NIL);
1202
1203         Replaceall(enum_code, "$javaclassname", symname);
1204
1205         // Substitute $enumvalues - intended usage is for typesafe enums
1206         if (Getattr(n, "enumvalues"))
1207           Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues"));
1208         else
1209           Replaceall(enum_code, "$enumvalues", "");
1210
1211         if (proxy_flag && is_wrapping_class()) {
1212           // Enums defined within the C++ class are defined within the proxy class
1213
1214           // Add extra indentation
1215           Replaceall(enum_code, "\n", "\n  ");
1216           Replaceall(enum_code, "  \n", "\n");
1217
1218           Printv(proxy_class_constants_code, "  ", enum_code, "\n\n", NIL);
1219         } else {
1220           // Global enums are defined in their own file
1221           String *filen = NewStringf("%s%s.java", SWIG_output_directory(), symname);
1222           File *f_enum = NewFile(filen, "w", SWIG_output_files());
1223           if (!f_enum) {
1224             FileErrorDisplay(filen);
1225             SWIG_exit(EXIT_FAILURE);
1226           }
1227           Append(filenames_list, Copy(filen));
1228           Delete(filen);
1229           filen = NULL;
1230
1231           // Start writing out the enum file
1232           emitBanner(f_enum);
1233
1234           if (Len(package) > 0)
1235             Printf(f_enum, "package %s;\n", package);
1236
1237           Printv(f_enum, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE), // Import statements
1238                  "\n", enum_code, "\n", NIL);
1239
1240           Printf(f_enum, "\n");
1241           Close(f_enum);
1242         }
1243       } else {
1244         // Wrap C++ enum with simple constant
1245         Printf(enum_code, "\n");
1246         if (proxy_flag && is_wrapping_class())
1247           Printv(proxy_class_constants_code, enum_code, NIL);
1248         else
1249           Printv(module_class_constants_code, enum_code, NIL);
1250       }
1251
1252       Delete(enum_code);
1253       enum_code = NULL;
1254     }
1255     return SWIG_OK;
1256   }
1257
1258   /* ----------------------------------------------------------------------
1259    * enumvalueDeclaration()
1260    * ---------------------------------------------------------------------- */
1261
1262   virtual int enumvalueDeclaration(Node *n) {
1263     if (getCurrentClass() && (cplus_mode != PUBLIC))
1264       return SWIG_NOWRAP;
1265
1266     Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
1267     String *symname = Getattr(n, "sym:name");
1268     String *value = Getattr(n, "value");
1269     String *name = Getattr(n, "name");
1270     String *tmpValue;
1271
1272     // Strange hack from parent method
1273     if (value)
1274       tmpValue = NewString(value);
1275     else
1276       tmpValue = NewString(name);
1277     // Note that this is used in enumValue() amongst other places
1278     Setattr(n, "value", tmpValue);
1279
1280     {
1281       EnumFeature enum_feature = decodeEnumFeature(parentNode(n));
1282
1283       if ((enum_feature == ProperEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) {
1284         // Wrap (non-anonymous) C/C++ enum with a proper Java enum
1285         // Emit the enum item.
1286         if (!GetFlag(n, "firstenumitem"))
1287           Printf(enum_code, ",\n");
1288         Printf(enum_code, "  %s", symname);
1289         if (Getattr(n, "enumvalue")) {
1290           String *value = enumValue(n);
1291           Printf(enum_code, "(%s)", value);
1292           Delete(value);
1293         }
1294       } else {
1295         // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
1296         const String *parent_name = Getattr(parentNode(n), "name");
1297         String *typemap_lookup_type = parent_name ? Copy(parent_name) : NewString("int");
1298         const String *tm = typemapLookup(n, "jstype", typemap_lookup_type, WARN_JAVA_TYPEMAP_JSTYPE_UNDEF);
1299         String *return_type = Copy(tm);
1300         Delete(typemap_lookup_type);
1301         typemap_lookup_type = NULL;
1302
1303         const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
1304         methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
1305
1306         if ((enum_feature == TypesafeEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) {
1307           // Wrap (non-anonymouse) enum using the typesafe enum pattern
1308           if (Getattr(n, "enumvalue")) {
1309             String *value = enumValue(n);
1310             Printf(enum_code, "  %s final static %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value);
1311             Delete(value);
1312           } else {
1313             Printf(enum_code, "  %s final static %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname);
1314           }
1315         } else {
1316           // Simple integer constants
1317           // Note these are always generated for anonymous enums, no matter what enum_feature is specified
1318           // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
1319           String *value = enumValue(n);
1320           Printf(enum_code, "  %s final static %s %s = %s;\n", methodmods, return_type, symname, value);
1321           Delete(value);
1322         }
1323       }
1324
1325       // Add the enum value to the comma separated list being constructed in the enum declaration.
1326       String *enumvalues = Getattr(parentNode(n), "enumvalues");
1327       if (!enumvalues)
1328         Setattr(parentNode(n), "enumvalues", Copy(symname));
1329       else
1330         Printv(enumvalues, ", ", symname, NIL);
1331     }
1332
1333     Delete(tmpValue);
1334     Swig_restore(n);
1335     return SWIG_OK;
1336   }
1337
1338   /* -----------------------------------------------------------------------
1339    * constantWrapper()
1340    * Used for wrapping constants - #define or %constant.
1341    * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
1342    * Java static final variables are generated for these.
1343    * If the %javaconst(1) feature is used then the C constant value is used to initialise the Java final variable.
1344    * If not, a JNI method is generated to get the C constant value for initialisation of the Java final variable.
1345    * However, if the %javaconstvalue feature is used, it overrides all other ways to generate the initialisation.
1346    * Also note that this method might be called for wrapping enum items (when the enum is using %javaconst(0)).
1347    * ------------------------------------------------------------------------ */
1348
1349   virtual int constantWrapper(Node *n) {
1350     String *symname = Getattr(n, "sym:name");
1351     SwigType *t = Getattr(n, "type");
1352     ParmList *l = Getattr(n, "parms");
1353     String *tm;
1354     String *return_type = NewString("");
1355     String *constants_code = NewString("");
1356
1357     if (!addSymbol(symname, n))
1358       return SWIG_ERROR;
1359
1360     bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
1361
1362     // The %javaconst feature determines how the constant value is obtained
1363     int const_feature_flag = GetFlag(n, "feature:java:const");
1364
1365     /* Adjust the enum type for the Swig_typemap_lookup.
1366      * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */
1367     if (is_enum_item) {
1368       t = Getattr(parentNode(n), "enumtype");
1369       Setattr(n, "type", t);
1370     }
1371
1372     /* Attach the non-standard typemaps to the parameter list. */
1373     Swig_typemap_attach_parms("jstype", l, NULL);
1374
1375     /* Get Java return types */
1376     bool classname_substituted_flag = false;
1377
1378     if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
1379       classname_substituted_flag = substituteClassname(t, tm);
1380       Printf(return_type, "%s", tm);
1381     } else {
1382       Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
1383     }
1384
1385     // Add the stripped quotes back in
1386     String *new_value = NewString("");
1387     Swig_save("constantWrapper", n, "value", NIL);
1388     if (SwigType_type(t) == T_STRING) {
1389       Printf(new_value, "\"%s\"", Copy(Getattr(n, "value")));
1390       Setattr(n, "value", new_value);
1391     } else if (SwigType_type(t) == T_CHAR) {
1392       Printf(new_value, "\'%s\'", Copy(Getattr(n, "value")));
1393       Setattr(n, "value", new_value);
1394     }
1395
1396     const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
1397     const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
1398     methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
1399
1400     Printf(constants_code, "  %s final static %s %s = ", methodmods, return_type, itemname);
1401
1402     // Check for the %javaconstvalue feature
1403     String *value = Getattr(n, "feature:java:constvalue");
1404
1405     if (value) {
1406       Printf(constants_code, "%s;\n", value);
1407     } else if (!const_feature_flag) {
1408       // Default enum and constant handling will work with any type of C constant and initialises the Java variable from C through a JNI call.
1409
1410       if (classname_substituted_flag) {
1411         if (SwigType_isenum(t)) {
1412           // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on)
1413           Printf(constants_code, "%s.swigToEnum(%s.%s());\n", return_type, imclass_name, Swig_name_get(symname));
1414         } else {
1415           // This handles function pointers using the %constant directive
1416           Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, imclass_name, Swig_name_get(symname));
1417         }
1418       } else
1419         Printf(constants_code, "%s.%s();\n", imclass_name, Swig_name_get(symname));
1420
1421       // Each constant and enum value is wrapped with a separate JNI function call
1422       SetFlag(n, "feature:immutable");
1423       enum_constant_flag = true;
1424       variableWrapper(n);
1425       enum_constant_flag = false;
1426     } else {
1427       // Alternative constant handling will use the C syntax to make a true Java constant and hope that it compiles as Java code
1428       Printf(constants_code, "%s;\n", Getattr(n, "value"));
1429     }
1430
1431     // Emit the generated code to appropriate place
1432     // Enums only emit the intermediate and JNI methods, so no proxy or module class wrapper methods needed
1433     if (!is_enum_item) {
1434       if (proxy_flag && wrapping_member_flag)
1435         Printv(proxy_class_constants_code, constants_code, NIL);
1436       else
1437         Printv(module_class_constants_code, constants_code, NIL);
1438     }
1439     // Cleanup
1440     Swig_restore(n);
1441     Delete(new_value);
1442     Delete(return_type);
1443     Delete(constants_code);
1444     return SWIG_OK;
1445   }
1446
1447   /* -----------------------------------------------------------------------------
1448    * insertDirective()
1449    * ----------------------------------------------------------------------------- */
1450
1451   virtual int insertDirective(Node *n) {
1452     String *code = Getattr(n, "code");
1453     Replaceall(code, "$module", module_class_name);
1454     Replaceall(code, "$imclassname", imclass_name);
1455     return Language::insertDirective(n);
1456   }
1457
1458   /* -----------------------------------------------------------------------------
1459    * pragmaDirective()
1460    *
1461    * Valid Pragmas:
1462    * jniclassbase            - base (extends) for the intermediary class
1463    * jniclassclassmodifiers  - class modifiers for the intermediary class
1464    * jniclasscode            - text (java code) is copied verbatim to the intermediary class
1465    * jniclassimports         - import statements for the intermediary class
1466    * jniclassinterfaces      - interface (implements) for the intermediary class
1467    *
1468    * modulebase              - base (extends) for the module class
1469    * moduleclassmodifiers    - class modifiers for the module class
1470    * modulecode              - text (java code) is copied verbatim to the module class
1471    * moduleimports           - import statements for the module class
1472    * moduleinterfaces        - interface (implements) for the module class
1473    *
1474    * ----------------------------------------------------------------------------- */
1475
1476   virtual int pragmaDirective(Node *n) {
1477     if (!ImportMode) {
1478       String *lang = Getattr(n, "lang");
1479       String *code = Getattr(n, "name");
1480       String *value = Getattr(n, "value");
1481
1482       if (Strcmp(lang, "java") == 0) {
1483
1484         String *strvalue = NewString(value);
1485         Replaceall(strvalue, "\\\"", "\"");
1486
1487         if (Strcmp(code, "jniclassbase") == 0) {
1488           Delete(imclass_baseclass);
1489           imclass_baseclass = Copy(strvalue);
1490         } else if (Strcmp(code, "jniclassclassmodifiers") == 0) {
1491           Delete(imclass_class_modifiers);
1492           imclass_class_modifiers = Copy(strvalue);
1493         } else if (Strcmp(code, "jniclasscode") == 0) {
1494           Printf(imclass_class_code, "%s\n", strvalue);
1495         } else if (Strcmp(code, "jniclassimports") == 0) {
1496           Delete(imclass_imports);
1497           imclass_imports = Copy(strvalue);
1498         } else if (Strcmp(code, "jniclassinterfaces") == 0) {
1499           Delete(imclass_interfaces);
1500           imclass_interfaces = Copy(strvalue);
1501         } else if (Strcmp(code, "modulebase") == 0) {
1502           Delete(module_baseclass);
1503           module_baseclass = Copy(strvalue);
1504         } else if (Strcmp(code, "moduleclassmodifiers") == 0) {
1505           Delete(module_class_modifiers);
1506           module_class_modifiers = Copy(strvalue);
1507         } else if (Strcmp(code, "modulecode") == 0) {
1508           Printf(module_class_code, "%s\n", strvalue);
1509         } else if (Strcmp(code, "moduleimports") == 0) {
1510           Delete(module_imports);
1511           module_imports = Copy(strvalue);
1512         } else if (Strcmp(code, "moduleinterfaces") == 0) {
1513           Delete(module_interfaces);
1514           module_interfaces = Copy(strvalue);
1515         } else if (Strcmp(code, "moduleimport") == 0) {
1516           Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use the moduleimports pragma.\n", input_file, line_number);
1517         } else if (Strcmp(code, "moduleinterface") == 0) {
1518           Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use the moduleinterfaces pragma.\n", input_file, line_number);
1519         } else if (Strcmp(code, "modulemethodmodifiers") == 0) {
1520           Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%javamethodmodifiers.\n", input_file, line_number);
1521         } else if (Strcmp(code, "allshadowimport") == 0) {
1522           Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javaimports).\n", input_file, line_number);
1523         } else if (Strcmp(code, "allshadowcode") == 0) {
1524           Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javacode).\n", input_file, line_number);
1525         } else if (Strcmp(code, "allshadowbase") == 0) {
1526           Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javabase).\n", input_file, line_number);
1527         } else if (Strcmp(code, "allshadowinterface") == 0) {
1528           Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javainterfaces).\n", input_file, line_number);
1529         } else if (Strcmp(code, "allshadowclassmodifiers") == 0) {
1530           Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n", input_file, line_number);
1531         } else if (proxy_flag) {
1532           if (Strcmp(code, "shadowcode") == 0) {
1533             Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javacode).\n", input_file, line_number);
1534           } else if (Strcmp(code, "shadowimport") == 0) {
1535             Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javaimports).\n", input_file, line_number);
1536           } else if (Strcmp(code, "shadowbase") == 0) {
1537             Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javabase).\n", input_file, line_number);
1538           } else if (Strcmp(code, "shadowinterface") == 0) {
1539             Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javainterfaces).\n", input_file, line_number);
1540           } else if (Strcmp(code, "shadowclassmodifiers") == 0) {
1541             Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n", input_file, line_number);
1542           } else {
1543             Printf(stderr, "%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
1544           }
1545         } else {
1546           Printf(stderr, "%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
1547         }
1548         Delete(strvalue);
1549       }
1550     }
1551     return Language::pragmaDirective(n);
1552   }
1553
1554   /* -----------------------------------------------------------------------------
1555    * emitProxyClassDefAndCPPCasts()
1556    * ----------------------------------------------------------------------------- */
1557
1558   void emitProxyClassDefAndCPPCasts(Node *n) {
1559     String *c_classname = SwigType_namestr(Getattr(n, "name"));
1560     String *c_baseclass = NULL;
1561     String *baseclass = NULL;
1562     String *c_baseclassname = NULL;
1563     SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
1564     bool feature_director = Swig_directorclass(n) ? true : false;
1565
1566     // Inheritance from pure Java classes
1567     Node *attributes = NewHash();
1568     const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE, attributes);
1569     bool purebase_replace = GetFlag(attributes, "tmap:javabase:replace") ? true : false;
1570     bool purebase_notderived = GetFlag(attributes, "tmap:javabase:notderived") ? true : false;
1571     Delete(attributes);
1572
1573     // C++ inheritance
1574     if (!purebase_replace) {
1575       List *baselist = Getattr(n, "bases");
1576       if (baselist) {
1577         Iterator base = First(baselist);
1578         while (base.item && GetFlag(base.item, "feature:ignore")) {
1579           base = Next(base);
1580         }
1581         if (base.item) {
1582           c_baseclassname = Getattr(base.item, "name");
1583           baseclass = Copy(getProxyName(c_baseclassname));
1584           if (baseclass)
1585             c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
1586           base = Next(base);
1587           /* Warn about multiple inheritance for additional base class(es) */
1588           while (base.item) {
1589             if (GetFlag(base.item, "feature:ignore")) {
1590               base = Next(base);
1591               continue;
1592             }
1593             String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
1594             String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
1595             Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, input_file, line_number,
1596                          "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java.\n", proxyclassname, baseclassname);
1597             base = Next(base);
1598           }
1599         }
1600       }
1601     }
1602
1603     bool derived = baseclass && getProxyName(c_baseclassname);
1604     if (derived && purebase_notderived)
1605       pure_baseclass = empty_string;
1606     const String *wanted_base = baseclass ? baseclass : pure_baseclass;
1607
1608     if (purebase_replace) {
1609       wanted_base = pure_baseclass;
1610       derived = false;
1611       Delete(baseclass);
1612       baseclass = NULL;
1613       if (purebase_notderived)
1614         Swig_error(input_file, line_number, "The javabase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
1615     } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
1616       Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, input_file, line_number,
1617                    "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java. "
1618                    "Perhaps you need one of the 'replace' or 'notderived' attributes in the csbase typemap?\n", typemap_lookup_type, pure_baseclass);
1619     }
1620
1621     // Pure Java interfaces
1622     const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
1623
1624     // Start writing the proxy class
1625     Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE),    // Import statements
1626            "\n", typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
1627            " $javaclassname",   // Class name and bases
1628            (*Char(wanted_base)) ? " extends " : "", wanted_base, *Char(pure_interfaces) ?       // Pure Java interfaces
1629            " implements " : "", pure_interfaces, " {", derived ? typemapLookup(n, "javabody_derived", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) :  // main body of class
1630            typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
1631            NIL);
1632
1633     // C++ destructor is wrapped by the delete method
1634     // Note that the method name is specified in a typemap attribute called methodname
1635     String *destruct = NewString("");
1636     const String *tm = NULL;
1637     attributes = NewHash();
1638     String *destruct_methodname = NULL;
1639     String *destruct_methodmodifiers = NULL;
1640     if (derived) {
1641       tm = typemapLookup(n, "javadestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
1642       destruct_methodname = Getattr(attributes, "tmap:javadestruct_derived:methodname");
1643       destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct_derived:methodmodifiers");
1644     } else {
1645       tm = typemapLookup(n, "javadestruct", typemap_lookup_type, WARN_NONE, attributes);
1646       destruct_methodname = Getattr(attributes, "tmap:javadestruct:methodname");
1647       destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct:methodmodifiers");
1648     }
1649     if (tm && *Char(tm)) {
1650       if (!destruct_methodname) {
1651         Swig_error(input_file, line_number,
1652                    "No methodname attribute defined in javadestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
1653       }
1654       if (!destruct_methodmodifiers) {
1655         Swig_error(input_file, line_number,
1656                    "No methodmodifiers attribute defined in javadestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
1657       }
1658     }
1659     // Emit the finalize and delete methods
1660     if (tm) {
1661       // Finalize method
1662       if (*Char(destructor_call)) {
1663         Printv(proxy_class_def, typemapLookup(n, "javafinalize", typemap_lookup_type, WARN_NONE), NIL);
1664       }
1665       // delete method
1666       Printv(destruct, tm, NIL);
1667       if (*Char(destructor_call))
1668         Replaceall(destruct, "$jnicall", destructor_call);
1669       else
1670         Replaceall(destruct, "$jnicall", "throw new UnsupportedOperationException(\"C++ destructor does not have public access\")");
1671       if (*Char(destruct))
1672         Printv(proxy_class_def, "\n  ", destruct_methodmodifiers, " void ", destruct_methodname, "()", destructor_throws_clause, " ", destruct, "\n", NIL);
1673     }
1674
1675     /* Insert directordisconnect typemap, if this class has directors enabled */
1676     /* Also insert the swigTakeOwnership and swigReleaseOwnership methods */
1677     if (feature_director) {
1678       String *destruct_jnicall, *release_jnicall, *take_jnicall;
1679
1680       destruct_jnicall = NewStringf("%s()", destruct_methodname);
1681       release_jnicall = NewStringf("%s.%s_change_ownership(this, swigCPtr, false)", imclass_name, proxy_class_name);
1682       take_jnicall = NewStringf("%s.%s_change_ownership(this, swigCPtr, true)", imclass_name, proxy_class_name);
1683
1684       emitCodeTypemap(n, false, typemap_lookup_type, "directordisconnect", "methodname", destruct_jnicall);
1685       emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_release", "methodname", release_jnicall);
1686       emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_take", "methodname", take_jnicall);
1687
1688       Delete(destruct_jnicall);
1689       Delete(release_jnicall);
1690       Delete(take_jnicall);
1691     }
1692
1693     Delete(attributes);
1694     Delete(destruct);
1695
1696     // Emit extra user code
1697     Printv(proxy_class_def, typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE),       // extra Java code
1698            "\n", NIL);
1699
1700     // Substitute various strings into the above template
1701     Replaceall(proxy_class_code, "$javaclassname", proxy_class_name);
1702     Replaceall(proxy_class_def, "$javaclassname", proxy_class_name);
1703
1704     Replaceall(proxy_class_def, "$module", module_class_name);
1705     Replaceall(proxy_class_code, "$module", module_class_name);
1706
1707     Replaceall(proxy_class_def, "$imclassname", imclass_name);
1708     Replaceall(proxy_class_code, "$imclassname", imclass_name);
1709
1710     // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
1711     if (derived) {
1712       Printv(imclass_cppcasts_code, "  public final static native long SWIG$javaclassnameUpcast(long jarg1);\n", NIL);
1713
1714       Replaceall(imclass_cppcasts_code, "$javaclassname", proxy_class_name);
1715
1716       Printv(upcasts_code,
1717              "SWIGEXPORT jlong JNICALL Java_$jnipackage$imimclass_SWIG$imclazznameUpcast",
1718              "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
1719              "    jlong baseptr = 0;\n"
1720              "    (void)jenv;\n" "    (void)jcls;\n" "    *($cbaseclass **)&baseptr = *($cclass **)&jarg1;\n" "    return baseptr;\n" "}\n", "\n", NIL);
1721
1722       String *imimclass = makeValidJniName(imclass_name);
1723       String *imclazzname = makeValidJniName(proxy_class_name);
1724       Replaceall(upcasts_code, "$cbaseclass", c_baseclass);
1725       Replaceall(upcasts_code, "$imclazzname", imclazzname);
1726       Replaceall(upcasts_code, "$cclass", c_classname);
1727       Replaceall(upcasts_code, "$jnipackage", jnipackage);
1728       Replaceall(upcasts_code, "$imimclass", imimclass);
1729
1730       Delete(imclazzname);
1731       Delete(imimclass);
1732     }
1733     Delete(baseclass);
1734   }
1735
1736   /* ----------------------------------------------------------------------
1737    * classHandler()
1738    * ---------------------------------------------------------------------- */
1739
1740   virtual int classHandler(Node *n) {
1741
1742     File *f_proxy = NULL;
1743     if (proxy_flag) {
1744       proxy_class_name = NewString(Getattr(n, "sym:name"));
1745
1746       if (!addSymbol(proxy_class_name, n))
1747         return SWIG_ERROR;
1748
1749       if (Cmp(proxy_class_name, imclass_name) == 0) {
1750         Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
1751         SWIG_exit(EXIT_FAILURE);
1752       }
1753
1754       if (Cmp(proxy_class_name, module_class_name) == 0) {
1755         Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
1756         SWIG_exit(EXIT_FAILURE);
1757       }
1758
1759       String *filen = NewStringf("%s%s.java", SWIG_output_directory(), proxy_class_name);
1760       f_proxy = NewFile(filen, "w", SWIG_output_files());
1761       if (!f_proxy) {
1762         FileErrorDisplay(filen);
1763         SWIG_exit(EXIT_FAILURE);
1764       }
1765       Append(filenames_list, Copy(filen));
1766       Delete(filen);
1767       filen = NULL;
1768
1769       // Start writing out the proxy class file
1770       emitBanner(f_proxy);
1771
1772       if (Len(package) > 0)
1773         Printf(f_proxy, "package %s;\n", package);
1774
1775       Clear(proxy_class_def);
1776       Clear(proxy_class_code);
1777
1778       destructor_call = NewString("");
1779       destructor_throws_clause = NewString("");
1780       proxy_class_constants_code = NewString("");
1781     }
1782
1783     Language::classHandler(n);
1784
1785     if (proxy_flag) {
1786
1787       emitProxyClassDefAndCPPCasts(n);
1788
1789       Replaceall(proxy_class_def, "$module", module_class_name);
1790       Replaceall(proxy_class_code, "$module", module_class_name);
1791       Replaceall(proxy_class_constants_code, "$module", module_class_name);
1792       Replaceall(proxy_class_def, "$imclassname", imclass_name);
1793       Replaceall(proxy_class_code, "$imclassname", imclass_name);
1794       Replaceall(proxy_class_constants_code, "$imclassname", imclass_name);
1795       Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
1796
1797       // Write out all the constants
1798       if (Len(proxy_class_constants_code) != 0)
1799         Printv(f_proxy, proxy_class_constants_code, NIL);
1800
1801       Printf(f_proxy, "}\n");
1802       Close(f_proxy);
1803       f_proxy = NULL;
1804
1805       /* Output the downcast method, if necessary. Note: There's no other really
1806          good place to put this code, since Abstract Base Classes (ABCs) can and should have 
1807          downcasts, making the constructorHandler() a bad place (because ABCs don't get to
1808          have constructors emitted.) */
1809       if (GetFlag(n, "feature:javadowncast")) {
1810         String *jni_imclass_name = makeValidJniName(imclass_name);
1811         String *jni_class_name = makeValidJniName(proxy_class_name);
1812         String *norm_name = SwigType_namestr(Getattr(n, "name"));
1813
1814         Printf(imclass_class_code, "  public final static native %s downcast%s(long cPtrBase, boolean cMemoryOwn);\n", proxy_class_name, proxy_class_name);
1815
1816         Wrapper *dcast_wrap = NewWrapper();
1817
1818         Printf(dcast_wrap->def, "SWIGEXPORT jobject JNICALL Java_%s%s_downcast%s(JNIEnv *jenv, jclass jcls, jlong jCPtrBase, jboolean cMemoryOwn) {",
1819                jnipackage, jni_imclass_name, jni_class_name);
1820         Printf(dcast_wrap->code, "  Swig::Director *director = (Swig::Director *) 0;\n");
1821         Printf(dcast_wrap->code, "  jobject jresult = (jobject) 0;\n");
1822         Printf(dcast_wrap->code, "  %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name);
1823         Printf(dcast_wrap->code, "  if (obj) director = dynamic_cast<Swig::Director *>(obj);\n");
1824         Printf(dcast_wrap->code, "  if (director) jresult = director->swig_get_self(jenv);\n");
1825         Printf(dcast_wrap->code, "  return jresult;\n");
1826         Printf(dcast_wrap->code, "}\n");
1827
1828         Wrapper_print(dcast_wrap, f_wrappers);
1829         DelWrapper(dcast_wrap);
1830       }
1831
1832       emitDirectorExtraMethods(n);
1833
1834       Delete(proxy_class_name);
1835       proxy_class_name = NULL;
1836       Delete(destructor_call);
1837       destructor_call = NULL;
1838       Delete(destructor_throws_clause);
1839       destructor_throws_clause = NULL;
1840       Delete(proxy_class_constants_code);
1841       proxy_class_constants_code = NULL;
1842     }
1843
1844     return SWIG_OK;
1845   }
1846
1847   /* ----------------------------------------------------------------------
1848    * memberfunctionHandler()
1849    * ---------------------------------------------------------------------- */
1850
1851   virtual int memberfunctionHandler(Node *n) {
1852     member_func_flag = true;
1853     Language::memberfunctionHandler(n);
1854
1855     if (proxy_flag) {
1856       String *overloaded_name = getOverloadedName(n);
1857       String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
1858       Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
1859       Setattr(n, "imfuncname", intermediary_function_name);
1860       proxyClassFunctionHandler(n);
1861       Delete(overloaded_name);
1862     }
1863     member_func_flag = false;
1864     return SWIG_OK;
1865   }
1866
1867   /* ----------------------------------------------------------------------
1868    * staticmemberfunctionHandler()
1869    * ---------------------------------------------------------------------- */
1870
1871   virtual int staticmemberfunctionHandler(Node *n) {
1872
1873     static_flag = true;
1874     member_func_flag = true;
1875     Language::staticmemberfunctionHandler(n);
1876
1877     if (proxy_flag) {
1878       String *overloaded_name = getOverloadedName(n);
1879       String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
1880       Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
1881       Setattr(n, "imfuncname", intermediary_function_name);
1882       proxyClassFunctionHandler(n);
1883       Delete(overloaded_name);
1884     }
1885     static_flag = false;
1886     member_func_flag = false;
1887
1888     return SWIG_OK;
1889   }
1890
1891   /* -----------------------------------------------------------------------------
1892    * proxyClassFunctionHandler()
1893    *
1894    * Function called for creating a Java wrapper function around a c++ function in the 
1895    * proxy class. Used for both static and non-static C++ class functions.
1896    * C++ class static functions map to Java static functions.
1897    * Two extra attributes in the Node must be available. These are "proxyfuncname" - 
1898    * the name of the Java class proxy function, which in turn will call "imfuncname" - 
1899    * the intermediary (JNI) function name in the intermediary class.
1900    * ----------------------------------------------------------------------------- */
1901
1902   void proxyClassFunctionHandler(Node *n) {
1903     SwigType *t = Getattr(n, "type");
1904     ParmList *l = Getattr(n, "parms");
1905     String *intermediary_function_name = Getattr(n, "imfuncname");
1906     String *proxy_function_name = Getattr(n, "proxyfuncname");
1907     String *tm;
1908     Parm *p;
1909     int i;
1910     String *imcall = NewString("");
1911     String *return_type = NewString("");
1912     String *function_code = NewString("");
1913     bool setter_flag = false;
1914     String *pre_code = NewString("");
1915     String *post_code = NewString("");
1916
1917     if (!proxy_flag)
1918       return;
1919
1920     // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
1921     if (Getattr(n, "overload:ignore"))
1922       return;
1923
1924     // Don't generate proxy method for additional explicitcall method used in directors
1925     if (GetFlag(n, "explicitcall"))
1926       return;
1927
1928     if (l) {
1929       if (SwigType_type(Getattr(l, "type")) == T_VOID) {
1930         l = nextSibling(l);
1931       }
1932     }
1933
1934     /* Attach the non-standard typemaps to the parameter list */
1935     Swig_typemap_attach_parms("in", l, NULL);
1936     Swig_typemap_attach_parms("jtype", l, NULL);
1937     Swig_typemap_attach_parms("jstype", l, NULL);
1938     Swig_typemap_attach_parms("javain", l, NULL);
1939
1940     /* Get return types */
1941     if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
1942       // Note that in the case of polymorphic (covariant) return types, the method's return type is changed to be the base of the C++ return type
1943       SwigType *covariant = Getattr(n, "covariant");
1944       substituteClassname(covariant ? covariant : t, tm);
1945       Printf(return_type, "%s", tm);
1946       if (covariant)
1947         Swig_warning(WARN_JAVA_COVARIANT_RET, input_file, line_number,
1948                      "Covariant return types not supported in Java. Proxy method will return %s.\n", SwigType_str(covariant, 0));
1949     } else {
1950       Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
1951     }
1952
1953     if (wrapping_member_flag && !enum_constant_flag) {
1954       // For wrapping member variables (Javabean setter)
1955       setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) == 0);
1956     }
1957
1958     /* Start generating the proxy function */
1959     const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
1960     methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
1961     Printf(function_code, "  %s ", methodmods);
1962     if (static_flag)
1963       Printf(function_code, "static ");
1964     Printf(function_code, "%s %s(", return_type, proxy_function_name);
1965
1966     Printv(imcall, imclass_name, ".$imfuncname(", NIL);
1967     if (!static_flag) {
1968       Printf(imcall, "swigCPtr");
1969
1970       String *this_type = Copy(getClassType());
1971       String *name = NewString("self");
1972       String *qualifier = Getattr(n, "qualifier");
1973       if (qualifier)
1974         SwigType_push(this_type, qualifier);
1975       SwigType_add_pointer(this_type);
1976       Parm *this_parm = NewParm(this_type, name);
1977       Swig_typemap_attach_parms("jtype", this_parm, NULL);
1978       Swig_typemap_attach_parms("jstype", this_parm, NULL);
1979
1980       if (prematureGarbageCollectionPreventionParameter(this_type, this_parm))
1981         Printf(imcall, ", this");
1982
1983       Delete(this_parm);
1984       Delete(name);
1985       Delete(this_type);
1986     }
1987
1988     emit_mark_varargs(l);
1989
1990     int gencomma = !static_flag;
1991
1992     /* Output each parameter */
1993     for (i = 0, p = l; p; i++) {
1994
1995       /* Ignored varargs */
1996       if (checkAttribute(p, "varargs:ignore", "1")) {
1997         p = nextSibling(p);
1998         continue;
1999       }
2000
2001       /* Ignored parameters */
2002       if (checkAttribute(p, "tmap:in:numinputs", "0")) {
2003         p = Getattr(p, "tmap:in:next");
2004         continue;
2005       }
2006
2007       /* Ignore the 'this' argument for variable wrappers */
2008       if (!(variable_wrapper_flag && i == 0) || static_flag) {
2009         SwigType *pt = Getattr(p, "type");
2010         String *param_type = NewString("");
2011
2012         /* Get the Java parameter type */
2013         if ((tm = Getattr(p, "tmap:jstype"))) {
2014           substituteClassname(pt, tm);
2015           Printf(param_type, "%s", tm);
2016         } else {
2017           Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
2018         }
2019
2020         if (gencomma)
2021           Printf(imcall, ", ");
2022
2023         String *arg = makeParameterName(n, p, i, setter_flag);
2024
2025         // Use typemaps to transform type used in Java proxy wrapper (in proxy class) to type used in JNI function (in intermediary class)
2026         if ((tm = Getattr(p, "tmap:javain"))) {
2027           addThrows(n, "tmap:javain", p);
2028           substituteClassname(pt, tm);
2029           Replaceall(tm, "$javainput", arg);
2030           String *pre = Getattr(p, "tmap:javain:pre");
2031           if (pre) {
2032             substituteClassname(pt, pre);
2033             Replaceall(pre, "$javainput", arg);
2034             if (Len(pre_code) > 0)
2035               Printf(pre_code, "\n");
2036             Printv(pre_code, pre, NIL);
2037           }
2038           String *post = Getattr(p, "tmap:javain:post");
2039           if (post) {
2040             substituteClassname(pt, post);
2041             Replaceall(post, "$javainput", arg);
2042             if (Len(post_code) > 0)
2043               Printf(post_code, "\n");
2044             Printv(post_code, post, NIL);
2045           }
2046           Printv(imcall, tm, NIL);
2047         } else {
2048           Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
2049         }
2050
2051         /* Add parameter to proxy function */
2052         if (gencomma >= 2)
2053           Printf(function_code, ", ");
2054         gencomma = 2;
2055         Printf(function_code, "%s %s", param_type, arg);
2056
2057         if (prematureGarbageCollectionPreventionParameter(pt, p)) {
2058           String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
2059           if (pgcppname) {
2060             String *argname = Copy(pgcppname);
2061             Replaceall(argname, "$javainput", arg);
2062             Printf(imcall, ", %s", argname);
2063             Delete(argname);
2064           } else {
2065             Printf(imcall, ", %s", arg);
2066           }
2067         }
2068
2069         Delete(arg);
2070         Delete(param_type);
2071       }
2072       p = Getattr(p, "tmap:in:next");
2073     }
2074
2075     Printf(imcall, ")");
2076     Printf(function_code, ")");
2077
2078     // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in proxy class)
2079     if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
2080       addThrows(n, "tmap:javaout", n);
2081       bool is_pre_code = Len(pre_code) > 0;
2082       bool is_post_code = Len(post_code) > 0;
2083       if (is_pre_code || is_post_code) {
2084         Replaceall(tm, "\n ", "\n   "); // add extra indentation to code in typemap
2085         if (is_post_code) {
2086           Insert(tm, 0, "\n    try ");
2087           Printv(tm, " finally {\n", post_code, "\n    }", NIL);
2088         } else {
2089           Insert(tm, 0, "\n    ");
2090         }
2091         if (is_pre_code) {
2092           Insert(tm, 0, pre_code);
2093           Insert(tm, 0, "\n");
2094         }
2095         Insert(tm, 0, "{");
2096         Printf(tm, "\n  }");
2097       }
2098       if (GetFlag(n, "feature:new"))
2099         Replaceall(tm, "$owner", "true");
2100       else
2101         Replaceall(tm, "$owner", "false");
2102       substituteClassname(t, tm);
2103
2104       // For director methods: generate code to selectively make a normal polymorphic call or 
2105       // an explicit method call - needed to prevent infinite recursion calls in director methods.
2106       Node *explicit_n = Getattr(n, "explicitcallnode");
2107       if (explicit_n) {
2108         String *ex_overloaded_name = getOverloadedName(explicit_n);
2109         String *ex_intermediary_function_name = Swig_name_member(proxy_class_name, ex_overloaded_name);
2110
2111         String *ex_imcall = Copy(imcall);
2112         Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
2113         Replaceall(imcall, "$imfuncname", intermediary_function_name);
2114
2115         String *excode = NewString("");
2116         if (!Cmp(return_type, "void"))
2117           Printf(excode, "if (getClass() == %s.class) %s; else %s", proxy_class_name, imcall, ex_imcall);
2118         else
2119           Printf(excode, "(getClass() == %s.class) ? %s : %s", proxy_class_name, imcall, ex_imcall);
2120
2121         Clear(imcall);
2122         Printv(imcall, excode, NIL);
2123         Delete(ex_overloaded_name);
2124         Delete(excode);
2125       } else {
2126         Replaceall(imcall, "$imfuncname", intermediary_function_name);
2127       }
2128
2129       Replaceall(tm, "$jnicall", imcall);
2130     } else {
2131       Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0));
2132     }
2133
2134     generateThrowsClause(n, function_code);
2135     Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
2136     Printv(proxy_class_code, function_code, NIL);
2137
2138     Delete(pre_code);
2139     Delete(post_code);
2140     Delete(function_code);
2141     Delete(return_type);
2142     Delete(imcall);
2143   }
2144
2145   /* ----------------------------------------------------------------------
2146    * constructorHandler()
2147    * ---------------------------------------------------------------------- */
2148
2149   virtual int constructorHandler(Node *n) {
2150
2151     ParmList *l = Getattr(n, "parms");
2152     String *tm;
2153     Parm *p;
2154     int i;
2155     String *function_code = NewString("");
2156     String *helper_code = NewString(""); // Holds code for the constructor helper method generated only when the javain typemap has code in the pre or post attributes
2157     String *helper_args = NewString("");
2158     String *pre_code = NewString("");
2159     String *post_code = NewString("");
2160     String *im_return_type = NewString("");
2161     bool feature_director = (parentNode(n) && Swig_directorclass(n));
2162
2163     Language::constructorHandler(n);
2164
2165     // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
2166     if (Getattr(n, "overload:ignore"))
2167       return SWIG_OK;
2168
2169     if (proxy_flag) {
2170       String *overloaded_name = getOverloadedName(n);
2171       String *mangled_overname = Swig_name_construct(overloaded_name);
2172       String *imcall = NewString("");
2173
2174       const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
2175       methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
2176
2177       tm = Getattr(n, "tmap:jtype"); // typemaps were attached earlier to the node
2178       Printf(im_return_type, "%s", tm);
2179
2180       Printf(function_code, "  %s %s(", methodmods, proxy_class_name);
2181       Printf(helper_code, "  static private %s SwigConstruct%s(", im_return_type, proxy_class_name);
2182
2183       Printv(imcall, imclass_name, ".", mangled_overname, "(", NIL);
2184
2185       /* Attach the non-standard typemaps to the parameter list */
2186       Swig_typemap_attach_parms("in", l, NULL);
2187       Swig_typemap_attach_parms("jtype", l, NULL);
2188       Swig_typemap_attach_parms("jstype", l, NULL);
2189       Swig_typemap_attach_parms("javain", l, NULL);
2190
2191       emit_mark_varargs(l);
2192
2193       int gencomma = 0;
2194
2195       /* Output each parameter */
2196       for (i = 0, p = l; p; i++) {
2197
2198         /* Ignored varargs */
2199         if (checkAttribute(p, "varargs:ignore", "1")) {
2200           p = nextSibling(p);
2201           continue;
2202         }
2203
2204         /* Ignored parameters */
2205         if (checkAttribute(p, "tmap:in:numinputs", "0")) {
2206           p = Getattr(p, "tmap:in:next");
2207           continue;
2208         }
2209
2210         SwigType *pt = Getattr(p, "type");
2211         String *param_type = NewString("");
2212
2213         /* Get the Java parameter type */
2214         if ((tm = Getattr(p, "tmap:jstype"))) {
2215           substituteClassname(pt, tm);
2216           Printf(param_type, "%s", tm);
2217         } else {
2218           Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
2219         }
2220
2221         if (gencomma)
2222           Printf(imcall, ", ");
2223
2224         String *arg = makeParameterName(n, p, i, false);
2225
2226         // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class)
2227         if ((tm = Getattr(p, "tmap:javain"))) {
2228           addThrows(n, "tmap:javain", p);
2229           substituteClassname(pt, tm);
2230           Replaceall(tm, "$javainput", arg);
2231           String *pre = Getattr(p, "tmap:javain:pre");
2232           if (pre) {
2233             substituteClassname(pt, pre);
2234             Replaceall(pre, "$javainput", arg);
2235             if (Len(pre_code) > 0)
2236               Printf(pre_code, "\n");
2237             Printv(pre_code, pre, NIL);
2238           }
2239           String *post = Getattr(p, "tmap:javain:post");
2240           if (post) {
2241             substituteClassname(pt, post);
2242             Replaceall(post, "$javainput", arg);
2243             if (Len(post_code) > 0)
2244               Printf(post_code, "\n");
2245             Printv(post_code, post, NIL);
2246           }
2247           Printv(imcall, tm, NIL);
2248         } else {
2249           Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
2250         }
2251
2252         /* Add parameter to proxy function */
2253         if (gencomma) {
2254           Printf(function_code, ", ");
2255           Printf(helper_code, ", ");
2256           Printf(helper_args, ", ");
2257         }
2258         Printf(function_code, "%s %s", param_type, arg);
2259         Printf(helper_code, "%s %s", param_type, arg);
2260         Printf(helper_args, "%s", arg);
2261         ++gencomma;
2262
2263         if (prematureGarbageCollectionPreventionParameter(pt, p)) {
2264           String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
2265           if (pgcppname) {
2266             String *argname = Copy(pgcppname);
2267             Replaceall(argname, "$javainput", arg);
2268             Printf(imcall, ", %s", argname);
2269             Delete(argname);
2270           } else {
2271             Printf(imcall, ", %s", arg);
2272           }
2273         }
2274
2275         Delete(arg);
2276         Delete(param_type);
2277         p = Getattr(p, "tmap:in:next");
2278       }
2279
2280       Printf(imcall, ")");
2281
2282       Printf(function_code, ")");
2283       Printf(helper_code, ")");
2284       generateThrowsClause(n, function_code);
2285
2286       /* Insert the javaconstruct typemap, doing the replacement for $directorconnect, as needed */
2287       Hash *attributes = NewHash();
2288       String *construct_tm = Copy(typemapLookup(n, "javaconstruct", Getattr(n, "name"),
2289                                                 WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF, attributes));
2290       if (construct_tm) {
2291         if (!feature_director) {
2292           Replaceall(construct_tm, "$directorconnect", "");
2293         } else {
2294           String *connect_attr = Getattr(attributes, "tmap:javaconstruct:directorconnect");
2295
2296           if (connect_attr) {
2297             Replaceall(construct_tm, "$directorconnect", connect_attr);
2298           } else {
2299             Swig_warning(WARN_JAVA_NO_DIRECTORCONNECT_ATTR, input_file, line_number, "\"directorconnect\" attribute missing in %s \"javaconstruct\" typemap.\n",
2300                          Getattr(n, "name"));
2301             Replaceall(construct_tm, "$directorconnect", "");
2302           }
2303         }
2304
2305         Printv(function_code, " ", construct_tm, "\n", NIL);
2306       }
2307
2308       bool is_pre_code = Len(pre_code) > 0;
2309       bool is_post_code = Len(post_code) > 0;
2310       if (is_pre_code || is_post_code) {
2311         generateThrowsClause(n, helper_code);
2312         Printf(helper_code, " {\n");
2313         if (is_pre_code) {
2314           Printv(helper_code, pre_code, "\n", NIL);
2315         }
2316         if (is_post_code) {
2317           Printf(helper_code, "    try {\n");
2318           Printv(helper_code, "      return ", imcall, ";\n", NIL);
2319           Printv(helper_code, "    } finally {\n", post_code, "\n    }", NIL);
2320         } else {
2321           Printv(helper_code, "    return ", imcall, ";", NIL);
2322         }
2323         Printf(helper_code, "\n  }\n");
2324         String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args);
2325         Printv(proxy_class_code, helper_code, "\n", NIL);
2326         Replaceall(function_code, "$imcall", helper_name);
2327         Delete(helper_name);
2328       } else {
2329         Replaceall(function_code, "$imcall", imcall);
2330       }
2331
2332       Printv(proxy_class_code, function_code, "\n", NIL);
2333
2334       Delete(helper_args);
2335       Delete(im_return_type);
2336       Delete(pre_code);
2337       Delete(post_code);
2338       Delete(construct_tm);
2339       Delete(attributes);
2340       Delete(overloaded_name);
2341       Delete(imcall);
2342     }
2343
2344     return SWIG_OK;
2345   }
2346
2347   /* ----------------------------------------------------------------------
2348    * destructorHandler()
2349    * ---------------------------------------------------------------------- */
2350
2351   virtual int destructorHandler(Node *n) {
2352     Language::destructorHandler(n);
2353     String *symname = Getattr(n, "sym:name");
2354
2355     if (proxy_flag) {
2356       Printv(destructor_call, imclass_name, ".", Swig_name_destroy(symname), "(swigCPtr)", NIL);
2357       generateThrowsClause(n, destructor_throws_clause);
2358     }
2359     return SWIG_OK;
2360   }
2361
2362   /* ----------------------------------------------------------------------
2363    * membervariableHandler()
2364    * ---------------------------------------------------------------------- */
2365
2366   virtual int membervariableHandler(Node *n) {
2367     variable_name = Getattr(n, "sym:name");
2368     wrapping_member_flag = true;
2369     variable_wrapper_flag = true;
2370     Language::membervariableHandler(n);
2371     wrapping_member_flag = false;
2372     variable_wrapper_flag = false;
2373     return SWIG_OK;
2374   }
2375
2376   /* ----------------------------------------------------------------------
2377    * staticmembervariableHandler()
2378    * ---------------------------------------------------------------------- */
2379
2380   virtual int staticmembervariableHandler(Node *n) {
2381     variable_name = Getattr(n, "sym:name");
2382     wrapping_member_flag = true;
2383     static_flag = true;
2384     Language::staticmembervariableHandler(n);
2385     wrapping_member_flag = false;
2386     static_flag = false;
2387     return SWIG_OK;
2388   }
2389
2390   /* ----------------------------------------------------------------------
2391    * memberconstantHandler()
2392    * ---------------------------------------------------------------------- */
2393
2394   virtual int memberconstantHandler(Node *n) {
2395     variable_name = Getattr(n, "sym:name");
2396     wrapping_member_flag = true;
2397     Language::memberconstantHandler(n);
2398     wrapping_member_flag = false;
2399     return SWIG_OK;
2400   }
2401
2402   /* -----------------------------------------------------------------------------
2403    * getOverloadedName()
2404    * ----------------------------------------------------------------------------- */
2405
2406   String *getOverloadedName(Node *n) {
2407
2408     /* Although JNI functions are designed to handle overloaded Java functions,
2409      * a Java long is used for all classes in the SWIG intermediary class.
2410      * The intermediary class methods are thus mangled when overloaded to give
2411      * a unique name. */
2412     String *overloaded_name = NewStringf("%s", Getattr(n, "sym:name"));
2413
2414     if (Getattr(n, "sym:overloaded")) {
2415       Printv(overloaded_name, Getattr(n, "sym:overname"), NIL);
2416     }
2417
2418     return overloaded_name;
2419   }
2420
2421   /* -----------------------------------------------------------------------------
2422    * moduleClassFunctionHandler()
2423    * ----------------------------------------------------------------------------- */
2424
2425   void moduleClassFunctionHandler(Node *n) {
2426     SwigType *t = Getattr(n, "type");
2427     ParmList *l = Getattr(n, "parms");
2428     String *tm;
2429     Parm *p;
2430     int i;
2431     String *imcall = NewString("");
2432     String *return_type = NewString("");
2433     String *function_code = NewString("");
2434     int num_arguments = 0;
2435     int num_required = 0;
2436     String *overloaded_name = getOverloadedName(n);
2437     String *func_name = NULL;
2438     bool setter_flag = false;
2439     String *pre_code = NewString("");
2440     String *post_code = NewString("");
2441
2442     if (l) {
2443       if (SwigType_type(Getattr(l, "type")) == T_VOID) {
2444         l = nextSibling(l);
2445       }
2446     }
2447
2448     /* Attach the non-standard typemaps to the parameter list */
2449     Swig_typemap_attach_parms("jstype", l, NULL);
2450     Swig_typemap_attach_parms("javain", l, NULL);
2451
2452     /* Get return types */
2453     if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
2454       substituteClassname(t, tm);
2455       Printf(return_type, "%s", tm);
2456     } else {
2457       Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
2458     }
2459
2460     /* Change function name for global variables */
2461     if (proxy_flag && global_variable_flag) {
2462       // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name
2463       func_name = NewString("");
2464       setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(variable_name)) == 0);
2465       if (setter_flag)
2466         Printf(func_name, "set");
2467       else
2468         Printf(func_name, "get");
2469       Putc(toupper((int) *Char(variable_name)), func_name);
2470       Printf(func_name, "%s", Char(variable_name) + 1);
2471     } else {
2472       func_name = Copy(Getattr(n, "sym:name"));
2473     }
2474
2475     /* Start generating the function */
2476     const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
2477     methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
2478     Printf(function_code, "  %s static %s %s(", methodmods, return_type, func_name);
2479     Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL);
2480
2481     /* Get number of required and total arguments */
2482     num_arguments = emit_num_arguments(l);
2483     num_required = emit_num_required(l);
2484
2485     bool global_or_member_variable = global_variable_flag || (wrapping_member_flag && !enum_constant_flag);
2486     int gencomma = 0;
2487
2488     /* Output each parameter */
2489     for (i = 0, p = l; i < num_arguments; i++) {
2490
2491       /* Ignored parameters */
2492       while (checkAttribute(p, "tmap:in:numinputs", "0")) {
2493         p = Getattr(p, "tmap:in:next");
2494       }
2495
2496       SwigType *pt = Getattr(p, "type");
2497       String *param_type = NewString("");
2498
2499       /* Get the Java parameter type */
2500       if ((tm = Getattr(p, "tmap:jstype"))) {
2501         substituteClassname(pt, tm);
2502         Printf(param_type, "%s", tm);
2503       } else {
2504         Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
2505       }
2506
2507       if (gencomma)
2508         Printf(imcall, ", ");
2509
2510       String *arg = makeParameterName(n, p, i, global_or_member_variable);
2511
2512       // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class)
2513       if ((tm = Getattr(p, "tmap:javain"))) {
2514         addThrows(n, "tmap:javain", p);
2515         substituteClassname(pt, tm);
2516         Replaceall(tm, "$javainput", arg);
2517         String *pre = Getattr(p, "tmap:javain:pre");
2518         if (pre) {
2519           substituteClassname(pt, pre);
2520           Replaceall(pre, "$javainput", arg);
2521           if (Len(pre_code) > 0)
2522             Printf(pre_code, "\n");
2523           Printv(pre_code, pre, NIL);
2524         }
2525         String *post = Getattr(p, "tmap:javain:post");
2526         if (post) {
2527           substituteClassname(pt, post);
2528           Replaceall(post, "$javainput", arg);
2529           if (Len(post_code) > 0)
2530             Printf(post_code, "\n");
2531           Printv(post_code, post, NIL);
2532         }
2533         Printv(imcall, tm, NIL);
2534       } else {
2535         Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
2536       }
2537
2538       /* Add parameter to module class function */
2539       if (gencomma >= 2)
2540         Printf(function_code, ", ");
2541       gencomma = 2;
2542       Printf(function_code, "%s %s", param_type, arg);
2543
2544       if (prematureGarbageCollectionPreventionParameter(pt, p)) {
2545         String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
2546         if (pgcppname) {
2547           String *argname = Copy(pgcppname);
2548           Replaceall(argname, "$javainput", arg);
2549           Printf(imcall, ", %s", argname);
2550           Delete(argname);
2551         } else {
2552           Printf(imcall, ", %s", arg);
2553         }
2554       }
2555
2556       p = Getattr(p, "tmap:in:next");
2557       Delete(arg);
2558       Delete(param_type);
2559     }
2560
2561     Printf(imcall, ")");
2562     Printf(function_code, ")");
2563
2564     // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in module class)
2565     if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
2566       addThrows(n, "tmap:javaout", n);
2567       bool is_pre_code = Len(pre_code) > 0;
2568       bool is_post_code = Len(post_code) > 0;
2569       if (is_pre_code || is_post_code) {
2570         Replaceall(tm, "\n ", "\n   "); // add extra indentation to code in typemap
2571         if (is_post_code) {
2572           Insert(tm, 0, "\n    try ");
2573           Printv(tm, " finally {\n", post_code, "\n    }", NIL);
2574         } else {
2575           Insert(tm, 0, "\n    ");
2576         }
2577         if (is_pre_code) {
2578           Insert(tm, 0, pre_code);
2579           Insert(tm, 0, "\n");
2580         }
2581         Insert(tm, 0, "{");
2582         Printf(tm, "\n  }");
2583       }
2584       if (GetFlag(n, "feature:new"))
2585         Replaceall(tm, "$owner", "true");
2586       else
2587         Replaceall(tm, "$owner", "false");
2588       substituteClassname(t, tm);
2589       Replaceall(tm, "$jnicall", imcall);
2590     } else {
2591       Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0));
2592     }
2593
2594     generateThrowsClause(n, function_code);
2595     Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
2596     Printv(module_class_code, function_code, NIL);
2597
2598     Delete(pre_code);
2599     Delete(post_code);
2600     Delete(function_code);
2601     Delete(return_type);
2602     Delete(imcall);
2603     Delete(func_name);
2604   }
2605
2606   /*----------------------------------------------------------------------
2607    * replaceSpecialVariables()
2608    *--------------------------------------------------------------------*/
2609
2610   virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
2611     (void)method;
2612     SwigType *type = Getattr(parm, "type");
2613     substituteClassname(type, tm);
2614   }
2615
2616   /*----------------------------------------------------------------------
2617    * decodeEnumFeature()
2618    * Decode the possible enum features, which are one of:
2619    *   %javaenum(simple)
2620    *   %javaenum(typeunsafe) - default
2621    *   %javaenum(typesafe)
2622    *   %javaenum(proper)
2623    *--------------------------------------------------------------------*/
2624
2625   EnumFeature decodeEnumFeature(Node *n) {
2626     EnumFeature enum_feature = TypeunsafeEnum;
2627     String *feature = Getattr(n, "feature:java:enum");
2628     if (feature) {
2629       if (Cmp(feature, "simple") == 0)
2630         enum_feature = SimpleEnum;
2631       else if (Cmp(feature, "typesafe") == 0)
2632         enum_feature = TypesafeEnum;
2633       else if (Cmp(feature, "proper") == 0)
2634         enum_feature = ProperEnum;
2635     }
2636     return enum_feature;
2637   }
2638
2639   /* -----------------------------------------------------------------------
2640    * enumValue()
2641    * This method will return a string with an enum value to use in Java generated
2642    * code. If the %javaconst feature is not used, the string will contain the intermediary
2643    * class call to obtain the enum value. The intermediary class and JNI methods to obtain
2644    * the enum value will be generated. Otherwise the C/C++ enum value will be used if there
2645    * is one and hopefully it will compile as Java code - e.g. 20 as in: enum E{e=20};
2646    * The %javaconstvalue feature overrides all other ways to generate the constant value.
2647    * The caller must delete memory allocated for the returned string.
2648    * ------------------------------------------------------------------------ */
2649
2650   String *enumValue(Node *n) {
2651     String *symname = Getattr(n, "sym:name");
2652
2653     // Check for the %javaconstvalue feature
2654     String *value = Getattr(n, "feature:java:constvalue");
2655
2656     if (!value) {
2657       // The %javaconst feature determines how the constant value is obtained
2658       int const_feature_flag = GetFlag(n, "feature:java:const");
2659
2660       if (const_feature_flag) {
2661         // Use the C syntax to make a true Java constant and hope that it compiles as Java code
2662         value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex"));
2663       } else {
2664         // Get the enumvalue from a JNI call
2665         if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) {
2666           // Strange hack to change the name
2667           Setattr(n, "name", Getattr(n, "value"));      /* for wrapping of enums in a namespace when emit_action is used */
2668           constantWrapper(n);
2669           value = NewStringf("%s.%s()", imclass_name, Swig_name_get(symname));
2670         } else {
2671           memberconstantHandler(n);
2672           value = NewStringf("%s.%s()", imclass_name, Swig_name_get(Swig_name_member(proxy_class_name, symname)));
2673         }
2674       }
2675     }
2676     return value;
2677   }
2678
2679   /* -----------------------------------------------------------------------------
2680    * getEnumName()
2681    *
2682    * If jnidescriptor is set, inner class names are separated with '$' otherwise a '.'
2683    * ----------------------------------------------------------------------------- */
2684
2685   String *getEnumName(SwigType *t, bool jnidescriptor) {
2686     Node *enum_name = NULL;
2687     Node *n = enumLookup(t);
2688     if (n) {
2689       String *symname = Getattr(n, "sym:name");
2690       if (symname) {
2691         // Add in class scope when referencing enum if not a global enum
2692         String *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
2693         String *proxyname = 0;
2694         if (scopename_prefix) {
2695           proxyname = getProxyName(scopename_prefix);
2696         }
2697         if (proxyname) {
2698           const char *class_separator = jnidescriptor ? "$" : ".";
2699           enum_name = NewStringf("%s%s%s", proxyname, class_separator, symname);
2700         } else {
2701           enum_name = NewStringf("%s", symname);
2702         }
2703         Delete(scopename_prefix);
2704       }
2705     }
2706
2707     return enum_name;
2708   }
2709
2710   /* -----------------------------------------------------------------------------
2711    * substituteClassname()
2712    *
2713    * Substitute the special variable $javaclassname with the proxy class name for classes/structs/unions 
2714    * that SWIG knows about. Also substitutes enums with enum name.
2715    * Otherwise use the $descriptor name for the Java class name. Note that the $&javaclassname substitution
2716    * is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
2717    * Inputs:
2718    *   pt - parameter type
2719    *   tm - typemap contents that might contain the special variable to be replaced
2720    *   jnidescriptor - if set, inner class names are separated with '$' otherwise a '.'
2721    * Outputs:
2722    *   tm - typemap contents complete with the special variable substitution
2723    * Return:
2724    *   substitution_performed - flag indicating if a substitution was performed
2725    * ----------------------------------------------------------------------------- */
2726
2727   bool substituteClassname(SwigType *pt, String *tm, bool jnidescriptor = false) {
2728     bool substitution_performed = false;
2729     SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
2730     SwigType *strippedtype = SwigType_strip_qualifiers(type);
2731
2732     if (Strstr(tm, "$javaclassname")) {
2733       SwigType *classnametype = Copy(strippedtype);
2734       substituteClassnameSpecialVariable(classnametype, tm, "$javaclassname", jnidescriptor);
2735       substitution_performed = true;
2736       Delete(classnametype);
2737     }
2738     if (Strstr(tm, "$*javaclassname")) {
2739       SwigType *classnametype = Copy(strippedtype);
2740       Delete(SwigType_pop(classnametype));
2741       substituteClassnameSpecialVariable(classnametype, tm, "$*javaclassname", jnidescriptor);
2742       substitution_performed = true;
2743       Delete(classnametype);
2744     }
2745     if (Strstr(tm, "$&javaclassname")) {
2746       SwigType *classnametype = Copy(strippedtype);
2747       SwigType_add_pointer(classnametype);
2748       substituteClassnameSpecialVariable(classnametype, tm, "$&javaclassname", jnidescriptor);
2749       substitution_performed = true;
2750       Delete(classnametype);
2751     }
2752
2753     Delete(strippedtype);
2754     Delete(type);
2755
2756     return substitution_performed;
2757   }
2758
2759   /* -----------------------------------------------------------------------------
2760    * substituteClassnameSpecialVariable()
2761    * ----------------------------------------------------------------------------- */
2762
2763   void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable, bool jnidescriptor) {
2764     if (SwigType_isenum(classnametype)) {
2765       String *enumname = getEnumName(classnametype, jnidescriptor);
2766       if (enumname)
2767         Replaceall(tm, classnamespecialvariable, enumname);
2768       else
2769         Replaceall(tm, classnamespecialvariable, NewStringf("int"));
2770     } else {
2771       String *classname = getProxyName(classnametype);
2772       if (classname) {
2773         Replaceall(tm, classnamespecialvariable, classname);    // getProxyName() works for pointers to classes too
2774       } else {                  // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
2775         String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
2776         Replaceall(tm, classnamespecialvariable, descriptor);
2777
2778         // Add to hash table so that the type wrapper classes can be created later
2779         Setattr(swig_types_hash, descriptor, classnametype);
2780         Delete(descriptor);
2781       }
2782     }
2783   }
2784
2785   /* -----------------------------------------------------------------------------
2786    * makeParameterName()
2787    *
2788    * Inputs: 
2789    *   n - Node
2790    *   p - parameter node
2791    *   arg_num - parameter argument number
2792    *   setter  - set this flag when wrapping variables
2793    * Return:
2794    *   arg - a unique parameter name
2795    * ----------------------------------------------------------------------------- */
2796
2797   String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) {
2798
2799     String *arg = 0;
2800     String *pn = Getattr(p, "name");
2801
2802     // Use C parameter name unless it is a duplicate or an empty parameter name
2803     int count = 0;
2804     ParmList *plist = Getattr(n, "parms");
2805     while (plist) {
2806       if ((Cmp(pn, Getattr(plist, "name")) == 0))
2807         count++;
2808       plist = nextSibling(plist);
2809     }
2810     String *wrn = pn ? Swig_name_warning(p, 0, pn, 0) : 0;
2811     arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d", arg_num) : Copy(pn);
2812
2813     if (setter && Cmp(arg, "self") != 0) {
2814       // Note that for setters the parameter name is always set but sometimes includes C++ 
2815       // scope resolution, so we need to strip off the scope resolution to make a valid name.
2816       Delete(arg);
2817       arg = NewString("value"); //Swig_scopename_last(pn);
2818     }
2819
2820     return arg;
2821   }
2822
2823   /* -----------------------------------------------------------------------------
2824    * emitTypeWrapperClass()
2825    * ----------------------------------------------------------------------------- */
2826
2827   void emitTypeWrapperClass(String *classname, SwigType *type) {
2828     Node *n = NewHash();
2829     Setfile(n, input_file);
2830     Setline(n, line_number);
2831
2832     String *swigtype = NewString("");
2833     String *filen = NewStringf("%s%s.java", SWIG_output_directory(), classname);
2834     File *f_swigtype = NewFile(filen, "w", SWIG_output_files());
2835     if (!f_swigtype) {
2836       FileErrorDisplay(filen);
2837       SWIG_exit(EXIT_FAILURE);
2838     }
2839     Append(filenames_list, Copy(filen));
2840     Delete(filen);
2841     filen = NULL;
2842
2843     // Start writing out the type wrapper class file
2844     emitBanner(f_swigtype);
2845
2846     if (Len(package) > 0)
2847       Printf(f_swigtype, "package %s;\n", package);
2848
2849     // Pure Java baseclass and interfaces
2850     const String *pure_baseclass = typemapLookup(n, "javabase", type, WARN_NONE);
2851     const String *pure_interfaces = typemapLookup(n, "javainterfaces", type, WARN_NONE);
2852
2853     // Emit the class
2854     Printv(swigtype, typemapLookup(n, "javaimports", type, WARN_NONE),  // Import statements
2855            "\n", typemapLookup(n, "javaclassmodifiers", type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF),        // Class modifiers
2856            " $javaclassname",   // Class name and bases
2857            *Char(pure_baseclass) ? " extends " : "", pure_baseclass, *Char(pure_interfaces) ?   // Interfaces
2858            " implements " : "", pure_interfaces, " {", typemapLookup(n, "javabody", type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF),    // main body of class
2859            typemapLookup(n, "javacode", type, WARN_NONE),       // extra Java code
2860            "}\n", "\n", NIL);
2861
2862     Replaceall(swigtype, "$javaclassname", classname);
2863     Replaceall(swigtype, "$module", module_class_name);
2864     Replaceall(swigtype, "$imclassname", imclass_name);
2865     Printv(f_swigtype, swigtype, NIL);
2866
2867     Close(f_swigtype);
2868     Delete(swigtype);
2869     Delete(n);
2870   }
2871
2872   /* -----------------------------------------------------------------------------
2873    * typemapLookup()
2874    * n - for input only and must contain info for Getfile(n) and Getline(n) to work
2875    * tmap_method - typemap method name
2876    * type - typemap type to lookup
2877    * warning - warning number to issue if no typemaps found
2878    * typemap_attributes - the typemap attributes are attached to this node and will 
2879    *   also be used for temporary storage if non null
2880    * return is never NULL, unlike Swig_typemap_lookup()
2881    * ----------------------------------------------------------------------------- */
2882
2883   const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
2884     Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
2885     Setattr(node, "type", type);
2886     Setfile(node, Getfile(n));
2887     Setline(node, Getline(n));
2888     const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
2889     if (!tm) {
2890       tm = empty_string;
2891       if (warning != WARN_NONE)
2892         Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
2893     }
2894     if (!typemap_attributes)
2895       Delete(node);
2896     return tm;
2897   }
2898
2899   /* -----------------------------------------------------------------------------
2900    * addThrows()
2901    *
2902    * Adds exception classes to a throws list. The throws list is the list of classes
2903    * that will form the Java throws clause. Mainly for checked exceptions.
2904    * ----------------------------------------------------------------------------- */
2905
2906   void addThrows(Node *n, const String *attribute, Node *parameter) {
2907     // Get the comma separated exception classes for the throws clause - held in typemap/feature's "throws" attribute
2908     String *throws_attribute = NewStringf("%s:throws", attribute);
2909     String *throws = Getattr(parameter, throws_attribute);
2910
2911     if (throws && Len(throws) > 0) {
2912       String *throws_list = Getattr(n, "java:throwslist");
2913       if (!throws_list) {
2914         throws_list = NewList();
2915         Setattr(n, "java:throwslist", throws_list);
2916       }
2917       // Put the exception classes in the throws clause into a temporary List
2918       List *temp_classes_list = Split(throws, ',', INT_MAX);
2919
2920       // Add the exception classes to the node throws list, but don't duplicate if already in list
2921       if (temp_classes_list && Len(temp_classes_list) > 0) {
2922         for (Iterator cls = First(temp_classes_list); cls.item; cls = Next(cls)) {
2923           String *exception_class = NewString(cls.item);
2924           Replaceall(exception_class, " ", ""); // remove spaces
2925           Replaceall(exception_class, "\t", "");        // remove tabs
2926           if (Len(exception_class) > 0) {
2927             // $javaclassname substitution
2928             SwigType *pt = Getattr(parameter, "type");
2929             substituteClassname(pt, exception_class);
2930
2931             // Don't duplicate the Java exception class in the throws clause
2932             bool found_flag = false;
2933             for (Iterator item = First(throws_list); item.item; item = Next(item)) {
2934               if (Strcmp(item.item, exception_class) == 0)
2935                 found_flag = true;
2936             }
2937             if (!found_flag)
2938               Append(throws_list, exception_class);
2939           }
2940           Delete(exception_class);
2941         }
2942       }
2943       Delete(temp_classes_list);
2944     }
2945     Delete(throws_attribute);
2946   }
2947
2948   /* -----------------------------------------------------------------------------
2949    * generateThrowsClause()
2950    *
2951    * Generates throws clause for checked exception
2952    * ----------------------------------------------------------------------------- */
2953
2954   void generateThrowsClause(Node *n, String *code) {
2955     // Add the throws clause into code
2956     List *throws_list = Getattr(n, "java:throwslist");
2957     if (throws_list) {
2958       Iterator cls = First(throws_list);
2959       Printf(code, " throws %s", cls.item);
2960       while ((cls = Next(cls)).item)
2961         Printf(code, ", %s", cls.item);
2962     }
2963   }
2964
2965   /* -----------------------------------------------------------------------------
2966    * prematureGarbageCollectionPreventionParameter()
2967    *
2968    * Get the proxy class name for use in an additional generated parameter. The
2969    * additional parameter is added to a native method call purely to prevent 
2970    * premature garbage collection of proxy classes which pass their C++ class pointer
2971    * in a Java long to the JNI layer.
2972    * ----------------------------------------------------------------------------- */
2973
2974   String *prematureGarbageCollectionPreventionParameter(SwigType *t, Parm *p) {
2975     String *proxyClassName = 0;
2976     String *jtype = NewString(Getattr(p, "tmap:jtype"));
2977
2978     // Strip C comments
2979     String *stripped_jtype = Swig_strip_c_comments(jtype);
2980     if (stripped_jtype) {
2981       Delete(jtype);
2982       jtype = stripped_jtype;
2983     }
2984
2985     // Remove whitespace
2986     Replaceall(jtype, " ", "");
2987     Replaceall(jtype, "\t", "");
2988
2989     if (Cmp(jtype, "long") == 0) {
2990       if (proxy_flag) {
2991         if (!GetFlag(p, "tmap:jtype:nopgcpp") && !nopgcpp_flag) {
2992           Node *n = classLookup(t);
2993           if (n) {
2994             // Found a struct/class parameter passed by value, reference, pointer, or pointer reference
2995             proxyClassName = Getattr(n, "sym:name");
2996           } else {
2997             // Look for proxy class parameters passed to C++ layer using non-default typemaps, ie not one of above types
2998             String *jstype = NewString(Getattr(p, "tmap:jstype"));
2999             if (jstype) {
3000               Hash *classes = getClassHash();
3001               if (classes) {
3002                 // Strip C comments
3003                 String *stripped_jstype = Swig_strip_c_comments(jstype);
3004                 if (stripped_jstype) {
3005                   Delete(jstype);
3006                   jstype = stripped_jstype;
3007                 }
3008                 // Remove whitespace
3009                 Replaceall(jstype, " ", "");
3010                 Replaceall(jstype, "\t", "");
3011
3012                 Iterator ki;
3013                 for (ki = First(classes); ki.key; ki = Next(ki)) {
3014                   Node *cls = ki.item;
3015                   if (cls && !Getattr(cls, "feature:ignore")) {
3016                     String *symname = Getattr(cls, "sym:name");
3017                     if (symname && Strcmp(symname, jstype) == 0) {
3018                       proxyClassName = symname;
3019                     }
3020                   }
3021                 }
3022               }
3023             }
3024             Delete(jstype);
3025           }
3026         }
3027       }
3028     }
3029     Delete(jtype);
3030     return proxyClassName;
3031   }
3032
3033   /*----------------------------------------------------------------------
3034    * Start of director methods
3035    *--------------------------------------------------------------------*/
3036
3037   /*----------------------------------------------------------------------
3038    * getUpcallJNIMethod()
3039    *--------------------------------------------------------------------*/
3040
3041   String *getUpcallJNIMethod(String *descrip) {
3042     static struct {
3043       char code;
3044       const char *method;
3045     } upcall_methods[] = {
3046       {
3047       'B', "CallStaticByteMethod"}, {
3048       'C', "CallStaticCharMethod"}, {
3049       'D', "CallStaticDoubleMethod"}, {
3050       'F', "CallStaticFloatMethod"}, {
3051       'I', "CallStaticIntMethod"}, {
3052       'J', "CallStaticLongMethod"}, {
3053       'L', "CallStaticObjectMethod"}, {
3054       'S', "CallStaticShortMethod"}, {
3055       'V', "CallStaticVoidMethod"}, {
3056       'Z', "CallStaticBooleanMethod"}, {
3057       '[', "CallStaticObjectMethod"}
3058     };
3059
3060     char code;
3061     int i;
3062
3063     code = *Char(descrip);
3064     for (i = 0; i < (int) (sizeof(upcall_methods) / sizeof(upcall_methods[0])); ++i)
3065       if (code == upcall_methods[i].code)
3066         return NewString(upcall_methods[i].method);
3067     return NULL;
3068   }
3069
3070   /*----------------------------------------------------------------------
3071    * emitDirectorUpcalls()
3072    *--------------------------------------------------------------------*/
3073
3074   void emitDirectorUpcalls() {
3075     if (n_dmethods) {
3076       Wrapper *w = NewWrapper();
3077       String *jni_imclass_name = makeValidJniName(imclass_name);
3078       String *swig_module_init = NewString("swig_module_init");
3079       String *swig_module_init_jni = makeValidJniName(swig_module_init);
3080       String *dmethod_data = NewString("");
3081       int n_methods = 0;
3082       Iterator udata_iter;
3083
3084       udata_iter = First(dmethods_seq);
3085       while (udata_iter.item) {
3086         UpcallData *udata = udata_iter.item;
3087         Printf(dmethod_data, "  { \"%s\", \"%s\" }", Getattr(udata, "imclass_method"), Getattr(udata, "imclass_fdesc"));
3088         ++n_methods;
3089
3090         udata_iter = Next(udata_iter);
3091
3092         if (udata_iter.item)
3093           Putc(',', dmethod_data);
3094         Putc('\n', dmethod_data);
3095       }
3096
3097       Printf(f_runtime, "namespace Swig {\n");
3098       Printf(f_runtime, "  static jclass jclass_%s = NULL;\n", imclass_name);
3099       Printf(f_runtime, "  static jmethodID director_methids[%d];\n", n_methods);
3100       Printf(f_runtime, "}\n");
3101
3102       Printf(w->def, "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls) {", jnipackage, jni_imclass_name, swig_module_init_jni);
3103       Printf(w->code, "static struct {\n");
3104       Printf(w->code, "  const char *method;\n");
3105       Printf(w->code, "  const char *signature;\n");
3106       Printf(w->code, "} methods[%d] = {\n", n_methods);
3107       Printv(w->code, dmethod_data, NIL);
3108       Printf(w->code, "};\n");
3109
3110       Wrapper_add_local(w, "i", "int i");
3111
3112       Printf(w->code, "Swig::jclass_%s = (jclass) jenv->NewGlobalRef(jcls);\n", imclass_name);
3113       Printf(w->code, "if (!Swig::jclass_%s) return;\n", imclass_name);
3114       Printf(w->code, "for (i = 0; i < (int) (sizeof(methods)/sizeof(methods[0])); ++i) {\n");
3115       Printf(w->code, "  Swig::director_methids[i] = jenv->GetStaticMethodID(jcls, methods[i].method, methods[i].signature);\n");
3116       Printf(w->code, "  if (!Swig::director_methids[i]) return;\n");
3117       Printf(w->code, "}\n");
3118
3119       Printf(w->code, "}\n");
3120
3121       Wrapper_print(w, f_wrappers);
3122       Delete(dmethod_data);
3123       Delete(swig_module_init_jni);
3124       Delete(swig_module_init);
3125       Delete(jni_imclass_name);
3126       DelWrapper(w);
3127     }
3128   }
3129
3130   /*----------------------------------------------------------------------
3131    * emitDirectorExtraMethods()
3132    *
3133    * This is where the $javaclassname_director_connect is
3134    * generated.
3135    *--------------------------------------------------------------------*/
3136   void emitDirectorExtraMethods(Node *n) {
3137     if (!Swig_directorclass(n))
3138       return;
3139
3140     // Output the director connect method:
3141     String *jni_imclass_name = makeValidJniName(imclass_name);
3142     String *norm_name = SwigType_namestr(Getattr(n, "name"));
3143     String *swig_director_connect = NewStringf("%s_director_connect", proxy_class_name);
3144     String *swig_director_connect_jni = makeValidJniName(swig_director_connect);
3145     String *sym_name = Getattr(n, "sym:name");
3146     Wrapper *code_wrap;
3147
3148     Printf(imclass_class_code, "  public final static native void %s(%s obj, long cptr, boolean mem_own, boolean weak_global);\n",
3149            swig_director_connect, proxy_class_name);
3150
3151     code_wrap = NewWrapper();
3152     Printf(code_wrap->def,
3153            "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jswig_mem_own, "
3154            "jboolean jweak_global) {\n", jnipackage, jni_imclass_name, swig_director_connect_jni);
3155     Printf(code_wrap->code, "  %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
3156     Printf(code_wrap->code, "  (void)jcls;\n");
3157     Printf(code_wrap->code, "  SwigDirector_%s *director = dynamic_cast<SwigDirector_%s *>(obj);\n", sym_name, sym_name);
3158     Printf(code_wrap->code, "  if (director) {\n");
3159     Printf(code_wrap->code, "    director->swig_connect_director(jenv, jself, jenv->GetObjectClass(jself), "
3160            "(jswig_mem_own == JNI_TRUE), (jweak_global == JNI_TRUE));\n");
3161     Printf(code_wrap->code, "  }\n");
3162     Printf(code_wrap->code, "}\n");
3163
3164     Wrapper_print(code_wrap, f_wrappers);
3165     DelWrapper(code_wrap);
3166
3167     Delete(swig_director_connect_jni);
3168     Delete(swig_director_connect);
3169
3170     // Output the swigReleaseOwnership, swigTakeOwnership methods:
3171     String *changeown_method_name = NewStringf("%s_change_ownership", proxy_class_name);
3172     String *changeown_jnimethod_name = makeValidJniName(changeown_method_name);
3173
3174     Printf(imclass_class_code, "  public final static native void %s(%s obj, long cptr, boolean take_or_release);\n", changeown_method_name, proxy_class_name);
3175
3176     code_wrap = NewWrapper();
3177     Printf(code_wrap->def,
3178            "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jtake_or_release) {\n",
3179            jnipackage, jni_imclass_name, changeown_jnimethod_name);
3180     Printf(code_wrap->code, "  %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
3181     Printf(code_wrap->code, "  SwigDirector_%s *director = dynamic_cast<SwigDirector_%s *>(obj);\n", sym_name, sym_name);
3182     Printf(code_wrap->code, "  (void)jcls;\n");
3183     Printf(code_wrap->code, "  if (director) {\n");
3184     Printf(code_wrap->code, "    director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n");
3185     Printf(code_wrap->code, "  }\n");
3186     Printf(code_wrap->code, "}\n");
3187
3188     Wrapper_print(code_wrap, f_wrappers);
3189     DelWrapper(code_wrap);
3190
3191     Delete(changeown_method_name);
3192     Delete(changeown_jnimethod_name);
3193     Delete(norm_name);
3194     Delete(jni_imclass_name);
3195   }
3196
3197   /*----------------------------------------------------------------------
3198    * emitCodeTypemap()
3199    *
3200    * Output a code typemap that uses $methodname and $jnicall, as used
3201    * in the directordisconnect, director_release and director_take
3202    * typemaps.
3203    *--------------------------------------------------------------------*/
3204
3205   void emitCodeTypemap(Node *n, bool derived, SwigType *lookup_type, const String *typemap, const String *methodname, const String *jnicall) {
3206     const String *tm = NULL;
3207     Node *tmattrs = NewHash();
3208     String *lookup_tmname = NewString(typemap);
3209     String *method_attr_name;
3210     String *method_attr;
3211
3212     if (derived) {
3213       Append(lookup_tmname, "_derived");
3214     }
3215
3216     tm = typemapLookup(n, lookup_tmname, lookup_type, WARN_NONE, tmattrs);
3217     method_attr_name = NewStringf("tmap:%s:%s", lookup_tmname, methodname);
3218     method_attr = Getattr(tmattrs, method_attr_name);
3219
3220     if (*Char(tm)) {
3221       if (method_attr) {
3222         String *codebody = Copy(tm);
3223         Replaceall(codebody, "$methodname", method_attr);
3224         Replaceall(codebody, "$jnicall", jnicall);
3225         Append(proxy_class_def, codebody);
3226         Delete(codebody);
3227       } else {
3228         Swig_error(input_file, line_number, "No %s method name attribute for %s\n", lookup_tmname, proxy_class_name);
3229       }
3230     } else {
3231       Swig_error(input_file, line_number, "No %s typemap for %s\n", lookup_tmname, proxy_class_name);
3232     }
3233
3234     Delete(tmattrs);
3235     Delete(lookup_tmname);
3236     // Delete(method_attr);
3237   }
3238
3239   /* ---------------------------------------------------------------
3240    * Canonicalize the JNI field descriptor
3241    *
3242    * Replace the $javapackage and $javaclassname family of special
3243    * variables with the desired package and Java proxy name as 
3244    * required in the JNI field descriptors.
3245    * 
3246    * !!SFM!! If $packagepath occurs in the field descriptor, but
3247    * package_path isn't set (length == 0), then strip it and the
3248    * optional trailing '/' from the resulting name.
3249    * 
3250    * --------------------------------------------------------------- */
3251
3252   String *canonicalizeJNIDescriptor(String *descriptor_in, Parm *p) {
3253     String *pkg_path = Swig_typemap_lookup("javapackage", p, "", 0);
3254     SwigType *type = Getattr(p, "type");
3255
3256     if (pkg_path && Len(pkg_path) != 0) {
3257       Replaceall(pkg_path, ".", "/");
3258     } else
3259       pkg_path = package_path;
3260
3261     String *descriptor_out = Copy(descriptor_in);
3262
3263     if (Len(pkg_path) > 0) {
3264       Replaceall(descriptor_out, "$packagepath", pkg_path);
3265     } else {
3266       Replaceall(descriptor_out, "$packagepath/", empty_string);
3267       Replaceall(descriptor_out, "$packagepath", empty_string);
3268     }
3269
3270     substituteClassname(type, descriptor_out, true);
3271
3272     if (pkg_path != package_path)
3273       Delete(pkg_path);
3274
3275     return descriptor_out;
3276   }
3277
3278   /* ---------------------------------------------------------------
3279    * classDirectorMethod()
3280    *
3281    * Emit a virtual director method to pass a method call on to the 
3282    * underlying Java object.
3283    *
3284    * --------------------------------------------------------------- */
3285
3286   int classDirectorMethod(Node *n, Node *parent, String *super) {
3287     String *empty_str = NewString("");
3288     String *classname = Getattr(parent, "sym:name");
3289     String *c_classname = Getattr(parent, "name");
3290     String *name = Getattr(n, "name");
3291     String *symname = Getattr(n, "sym:name");
3292     SwigType *type = Getattr(n, "type");
3293     SwigType *returntype = Getattr(n, "returntype");
3294     String *overloaded_name = getOverloadedName(n);
3295     String *storage = Getattr(n, "storage");
3296     String *value = Getattr(n, "value");
3297     String *decl = Getattr(n, "decl");
3298     String *declaration = NewString("");
3299     String *tm;
3300     Parm *p;
3301     int i;
3302     Wrapper *w = NewWrapper();
3303     ParmList *l = Getattr(n, "parms");
3304     bool is_void = !(Cmp(returntype, "void"));
3305     String *qualified_return = NewString("");
3306     bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
3307     int status = SWIG_OK;
3308     bool output_director = true;
3309     String *dirclassname = directorClassName(parent);
3310     String *qualified_name = NewStringf("%s::%s", dirclassname, name);
3311     String *jnidesc = NewString("");
3312     String *classdesc = NewString("");
3313     String *jniret_desc = NewString("");
3314     String *classret_desc = NewString("");
3315     SwigType *c_ret_type = NULL;
3316     String *jupcall_args = NewString("swigjobj");
3317     String *imclass_dmethod;
3318     String *callback_def = NewString("");
3319     String *callback_code = NewString("");
3320     String *imcall_args = NewString("");
3321     int gencomma = 0;
3322     int classmeth_off = curr_class_dmethod - first_class_dmethod;
3323     bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
3324
3325     // Kludge Alert: functionWrapper sets sym:overload properly, but it
3326     // isn't at this point, so we have to manufacture it ourselves. At least
3327     // we're consistent with the sym:overload name in functionWrapper. (?? when
3328     // does the overloaded method name get set?)
3329
3330     imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(classname, overloaded_name));
3331
3332     if (returntype) {
3333
3334       qualified_return = SwigType_rcaststr(returntype, "c_result");
3335
3336       if (!is_void && (!ignored_method || pure_virtual)) {
3337         if (!SwigType_isclass(returntype)) {
3338           if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
3339             String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
3340             Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
3341             Delete(construct_result);
3342           } else {
3343             String *base_typename = SwigType_base(returntype);
3344             String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
3345             Symtab *symtab = Getattr(n, "sym:symtab");
3346             Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
3347
3348             if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstract"))) {
3349               /* initialize pointers to something sane. Same for abstract
3350                  classes when a reference is returned. */
3351               Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
3352             } else {
3353               /* If returning a reference, initialize the pointer to a sane
3354                  default - if a Java exception occurs, then the pointer returns
3355                  something other than a NULL-initialized reference. */
3356               String *non_ref_type = Copy(returntype);
3357
3358               /* Remove reference and const qualifiers */
3359               Replaceall(non_ref_type, "r.", "");
3360               Replaceall(non_ref_type, "q(const).", "");
3361               Wrapper_add_localv(w, "result_default", "static", SwigType_str(non_ref_type, "result_default"), "=", SwigType_str(non_ref_type, "()"), NIL);
3362               Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= &result_default", NIL);
3363
3364               Delete(non_ref_type);
3365             }
3366
3367             Delete(base_typename);
3368             Delete(resolved_typename);
3369           }
3370         } else {
3371           SwigType *vt;
3372
3373           vt = cplus_value_type(returntype);
3374           if (!vt) {
3375             Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
3376           } else {
3377             Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
3378             Delete(vt);
3379           }
3380         }
3381       }
3382
3383       /* Create the intermediate class wrapper */
3384       Parm *tp = NewParmFromNode(returntype, empty_str, n);
3385
3386       tm = Swig_typemap_lookup("jtype", tp, "", 0);
3387       if (tm) {
3388         Printf(callback_def, "  public static %s %s(%s self", tm, imclass_dmethod, classname);
3389       } else {
3390         Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(returntype, 0));
3391       }
3392
3393       String *cdesc = NULL;
3394       SwigType *covariant = Getattr(n, "covariant");
3395       SwigType *adjustedreturntype = covariant ? covariant : returntype;
3396       Parm *adjustedreturntypeparm = NewParmFromNode(adjustedreturntype, empty_str, n);
3397
3398       if ((tm = Swig_typemap_lookup("directorin", adjustedreturntypeparm, "", 0))
3399           && (cdesc = Getattr(adjustedreturntypeparm, "tmap:directorin:descriptor"))) {
3400
3401         // Note that in the case of polymorphic (covariant) return types, the
3402         // method's return type is changed to be the base of the C++ return
3403         // type
3404         String *jnidesc_canon = canonicalizeJNIDescriptor(cdesc, adjustedreturntypeparm);
3405         Append(classret_desc, jnidesc_canon);
3406         Delete(jnidesc_canon);
3407       } else {
3408         Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n", 
3409             SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3410         output_director = false;
3411       }
3412
3413       /* Get the JNI field descriptor for this return type, add the JNI field descriptor
3414          to jniret_desc */
3415
3416       Parm *retpm = NewParmFromNode(returntype, empty_str, n);
3417
3418       if ((c_ret_type = Swig_typemap_lookup("jni", retpm, "", 0))) {
3419         Parm *tp = NewParmFromNode(c_ret_type, empty_str, n);
3420
3421         if (!is_void && !ignored_method) {
3422           String *jretval_decl = NewStringf("%s jresult", c_ret_type);
3423           Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
3424           Delete(jretval_decl);
3425         }
3426
3427         String *jdesc = NULL;
3428         if ((tm = Swig_typemap_lookup("directorin", tp, "", 0))
3429             && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) {
3430
3431           // Objects marshalled passing a Java class across JNI boundary use jobject - the nouse flag indicates this
3432           // We need the specific Java class name instead of the generic 'Ljava/lang/Object;'
3433           if (GetFlag(tp, "tmap:directorin:nouse"))
3434             jdesc = cdesc;
3435           String *jnidesc_canon = canonicalizeJNIDescriptor(jdesc, tp);
3436           Append(jniret_desc, jnidesc_canon);
3437           Delete(jnidesc_canon);
3438         } else {
3439           Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
3440                        "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n", 
3441                        SwigType_str(c_ret_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3442           output_director = false;
3443         }
3444
3445         Delete(tp);
3446       } else {
3447         Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n", 
3448             SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3449         output_director = false;
3450       }
3451
3452       Delete(adjustedreturntypeparm);
3453       Delete(retpm);
3454     }
3455
3456     /* Go through argument list, attach lnames for arguments */
3457     for (i = 0, p = l; p; p = nextSibling(p), ++i) {
3458       String *arg = Getattr(p, "name");
3459       String *lname = NewString("");
3460
3461       if (!arg && Cmp(Getattr(p, "type"), "void")) {
3462         lname = NewStringf("arg%d", i);
3463         Setattr(p, "name", lname);
3464       } else
3465         lname = arg;
3466
3467       Setattr(p, "lname", lname);
3468     }
3469
3470     /* Attach the standard typemaps */
3471     Swig_typemap_attach_parms("out", l, 0);
3472     Swig_typemap_attach_parms("jni", l, 0);
3473     Swig_typemap_attach_parms("jtype", l, 0);
3474     Swig_typemap_attach_parms("directorin", l, 0);
3475     Swig_typemap_attach_parms("javadirectorin", l, 0);
3476
3477     if (!ignored_method) {
3478       /* Add Java environment pointer to wrapper */
3479       String *jenvstr = NewString("jenv");
3480       String *jobjstr = NewString("swigjobj");
3481
3482       Wrapper_add_localv(w, "swigjnienv", "JNIEnvWrapper", "swigjnienv(this)", NIL, NIL);
3483       Wrapper_add_localv(w, jenvstr, "JNIEnv *", jenvstr, "= swigjnienv.getJNIEnv()", NIL);
3484       Wrapper_add_localv(w, jobjstr, "jobject", jobjstr, "= (jobject) NULL", NIL);
3485       Delete(jenvstr);
3486       Delete(jobjstr);
3487
3488       /* Preamble code */
3489       Printf(w->code, "if (!swig_override[%d]) {\n", classmeth_off);
3490     }
3491
3492     if (!pure_virtual) {
3493       String *super_call = Swig_method_call(super, l);
3494       if (is_void) {
3495         Printf(w->code, "%s;\n", super_call);
3496         if (!ignored_method)
3497           Printf(w->code, "return;\n");
3498       } else {
3499         Printf(w->code, "return %s;\n", super_call);
3500       }
3501       Delete(super_call);
3502     } else {
3503       Printf(w->code, "SWIG_JavaThrowException(JNIEnvWrapper(this).getJNIEnv(), SWIG_JavaDirectorPureVirtual, ");
3504       Printf(w->code, "\"Attempted to invoke pure virtual method %s::%s.\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
3505
3506       /* Make sure that we return something in the case of a pure
3507        * virtual method call for syntactical reasons. */
3508       if (!is_void)
3509         Printf(w->code, "return %s;", qualified_return);
3510       else if (!ignored_method)
3511         Printf(w->code, "return;\n");
3512     }
3513
3514     if (!ignored_method) {
3515       Printf(w->code, "}\n");
3516       Printf(w->code, "swigjobj = swig_get_self(jenv);\n");
3517       Printf(w->code, "if (swigjobj && jenv->IsSameObject(swigjobj, NULL) == JNI_FALSE) {\n");
3518     }
3519
3520     /* Start the Java field descriptor for the intermediate class's upcall (insert self object) */
3521     Parm *tp = NewParmFromNode(c_classname, empty_str, n);
3522     String *jdesc;
3523
3524     if ((tm = Swig_typemap_lookup("directorin", tp, "", 0))
3525         && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) {
3526       String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp);
3527       Append(jnidesc, jni_canon);
3528       Delete(jni_canon);
3529       Delete(tm);
3530     } else {
3531       Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
3532                    "No or improper directorin typemap for type %s  for use in %s::%s (skipping director method)\n", 
3533                    SwigType_str(type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3534       output_director = false;
3535     }
3536
3537     Delete(tp);
3538
3539     /* Go through argument list, convert from native to Java */
3540     for (p = l; p; /* empty */ ) {
3541       /* Is this superfluous? */
3542       while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
3543         p = Getattr(p, "tmap:directorin:next");
3544       }
3545
3546       SwigType *pt = Getattr(p, "type");
3547       String *ln = Copy(Getattr(p, "name"));
3548       String *c_param_type = NULL;
3549       String *c_decl = NewString("");
3550       String *arg = NewString("");
3551
3552       Printf(arg, "j%s", ln);
3553
3554       /* Add various typemap's 'throws' clauses */
3555       addThrows(n, "tmap:directorin", p);
3556       addThrows(n, "tmap:out", p);
3557
3558       /* And add to the upcall args */
3559       Printf(jupcall_args, ", %s", arg);
3560
3561       /* Get parameter's intermediary C type */
3562       if ((c_param_type = Getattr(p, "tmap:jni"))) {
3563         Parm *tp = NewParmFromNode(c_param_type, empty_str, n);
3564         String *desc_tm = NULL, *jdesc = NULL, *cdesc = NULL;
3565
3566         /* Add to local variables */
3567         Printf(c_decl, "%s %s", c_param_type, arg);
3568         if (!ignored_method)
3569           Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
3570
3571         /* Add input marshalling code and update JNI field descriptor */
3572         if ((desc_tm = Swig_typemap_lookup("directorin", tp, "", 0))
3573             && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))
3574             && (tm = Getattr(p, "tmap:directorin"))
3575             && (cdesc = Getattr(p, "tmap:directorin:descriptor"))) {
3576
3577           // Objects marshalled by passing a Java class across the JNI boundary use jobject as the JNI type - 
3578           // the nouse flag indicates this. We need the specific Java class name instead of the generic 'Ljava/lang/Object;'
3579           if (GetFlag(tp, "tmap:directorin:nouse"))
3580             jdesc = cdesc;
3581           String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp);
3582           Append(jnidesc, jni_canon);
3583           Delete(jni_canon);
3584
3585           Replaceall(tm, "$input", arg);
3586           Replaceall(tm, "$owner", "0");
3587
3588           if (Len(tm))
3589             if (!ignored_method)
3590               Printf(w->code, "%s\n", tm);
3591
3592           Delete(tm);
3593
3594           /* Add parameter to the intermediate class code if generating the
3595            * intermediate's upcall code */
3596           if ((tm = Getattr(p, "tmap:jtype"))) {
3597             String *din = Copy(Getattr(p, "tmap:javadirectorin"));
3598             addThrows(n, "tmap:javadirectorin", p);
3599
3600             if (din) {
3601               Replaceall(din, "$module", module_class_name);
3602               Replaceall(din, "$imclassname", imclass_name);
3603               substituteClassname(pt, din);
3604               Replaceall(din, "$jniinput", ln);
3605
3606               if (++gencomma > 1)
3607                 Printf(imcall_args, ", ");
3608               Printf(callback_def, ", %s %s", tm, ln);
3609
3610               if (Cmp(din, ln)) {
3611                 Printv(imcall_args, din, NIL);
3612               } else
3613                 Printv(imcall_args, ln, NIL);
3614
3615               jni_canon = canonicalizeJNIDescriptor(cdesc, p);
3616               Append(classdesc, jni_canon);
3617               Delete(jni_canon);
3618             } else {
3619               Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number, "No javadirectorin typemap defined for %s for use in %s::%s (skipping director method)\n", 
3620                   SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3621               output_director = false;
3622             }
3623           } else {
3624             Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s for use in %s::%s (skipping director method)\n", 
3625                 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3626             output_director = false;
3627           }
3628
3629           p = Getattr(p, "tmap:directorin:next");
3630
3631           Delete(desc_tm);
3632         } else {
3633           if (!desc_tm) {
3634             Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number,
3635                          "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n", 
3636                          SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3637             p = nextSibling(p);
3638           } else if (!jdesc) {
3639             Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number,
3640                          "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n", 
3641                          SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3642             p = Getattr(p, "tmap:directorin:next");
3643           } else if (!tm) {
3644             Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number,
3645                          "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n", 
3646                          SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3647             p = nextSibling(p);
3648           } else if (!cdesc) {
3649             Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number,
3650                          "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n", 
3651                          SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3652             p = Getattr(p, "tmap:directorin:next");
3653           }
3654
3655           output_director = false;
3656         }
3657
3658         Delete(tp);
3659       } else {
3660         Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n", 
3661             SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3662         output_director = false;
3663         p = nextSibling(p);
3664       }
3665
3666       Delete(arg);
3667       Delete(c_decl);
3668       Delete(c_param_type);
3669     }
3670
3671     /* header declaration, start wrapper definition */
3672     String *target;
3673     SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type;
3674     target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
3675     Printf(w->def, "%s", target);
3676     Delete(qualified_name);
3677     Delete(target);
3678     target = Swig_method_decl(rtype, decl, name, l, 0, 1);
3679     Printf(declaration, "    virtual %s", target);
3680     Delete(target);
3681
3682     // Add any exception specifications to the methods in the director class
3683     // Get any Java exception classes in the throws typemap
3684     ParmList *throw_parm_list = NULL;
3685
3686     if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
3687       int gencomma = 0;
3688
3689       Append(w->def, " throw(");
3690       Append(declaration, " throw(");
3691
3692       if (throw_parm_list)
3693         Swig_typemap_attach_parms("throws", throw_parm_list, 0);
3694       for (p = throw_parm_list; p; p = nextSibling(p)) {
3695         if ((tm = Getattr(p, "tmap:throws"))) {
3696           addThrows(n, "tmap:throws", p);
3697
3698           if (gencomma++) {
3699             Append(w->def, ", ");
3700             Append(declaration, ", ");
3701           }
3702
3703           Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
3704           Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
3705         }
3706       }
3707
3708       Append(w->def, ")");
3709       Append(declaration, ")");
3710     }
3711
3712     Append(w->def, " {");
3713     Append(declaration, ";\n");
3714
3715     /* Emit the intermediate class's upcall to the actual class */
3716
3717     String *upcall = NewStringf("self.%s(%s)", symname, imcall_args);
3718
3719     if (!is_void) {
3720       Parm *tp = NewParmFromNode(returntype, empty_str, n);
3721
3722       if ((tm = Swig_typemap_lookup("javadirectorout", tp, "", 0))) {
3723         addThrows(n, "tmap:javadirectorout", tp);
3724         substituteClassname(returntype, tm);
3725         Replaceall(tm, "$javacall", upcall);
3726
3727         Printf(callback_code, "    return %s;\n", tm);
3728       }
3729
3730       if ((tm = Swig_typemap_lookup("out", tp, "", 0)))
3731         addThrows(n, "tmap:out", tp);
3732
3733       Delete(tm);
3734       Delete(tp);
3735     } else
3736       Printf(callback_code, "    %s;\n", upcall);
3737
3738     Printf(callback_code, "  }\n");
3739     Delete(upcall);
3740
3741     /* Finish off the inherited upcall's definition */
3742     Putc(')', callback_def);
3743     generateThrowsClause(n, callback_def);
3744     Printf(callback_def, " {\n");
3745
3746     if (!ignored_method) {
3747       /* Emit the actual upcall through */
3748       String *imclass_desc = NewStringf("(%s)%s", jnidesc, jniret_desc);
3749       String *class_desc = NewStringf("(%s)%s", classdesc, classret_desc);
3750       UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, imclass_desc, class_desc, decl);
3751       String *methid = Getattr(udata, "imclass_methodidx");
3752       String *methop = getUpcallJNIMethod(jniret_desc);
3753
3754       if (!is_void)
3755         Printf(w->code, "jresult = (%s) ", c_ret_type);
3756
3757       Printf(w->code, "jenv->%s(Swig::jclass_%s, Swig::director_methids[%s], %s);\n", methop, imclass_name, methid, jupcall_args);
3758
3759       Printf(w->code, "if (jenv->ExceptionOccurred()) return $null;\n");
3760
3761       if (!is_void) {
3762         String *jresult_str = NewString("jresult");
3763         String *result_str = NewString("c_result");
3764         Parm *tp = NewParmFromNode(returntype, result_str, n);
3765
3766         /* Copy jresult into c_result... */
3767         if ((tm = Swig_typemap_lookup("directorout", tp, result_str, w))) {
3768           addThrows(n, "tmap:directorout", tp);
3769           Replaceall(tm, "$input", jresult_str);
3770           Replaceall(tm, "$result", result_str);
3771           Printf(w->code, "%s\n", tm);
3772         } else {
3773           Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
3774                        "Unable to use return type %s used in %s::%s (skipping director method)\n", 
3775                        SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3776           output_director = false;
3777         }
3778
3779         Delete(tp);
3780         Delete(jresult_str);
3781         Delete(result_str);
3782       }
3783
3784       Delete(imclass_desc);
3785       Delete(class_desc);
3786
3787       /* Terminate wrapper code */
3788       Printf(w->code, "} else {\n");
3789       Printf(w->code, "SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, \"null upcall object\");\n");
3790       Printf(w->code, "}\n");
3791
3792       Printf(w->code, "if (swigjobj) jenv->DeleteLocalRef(swigjobj);\n");
3793
3794       if (!is_void)
3795         Printf(w->code, "return %s;", qualified_return);
3796     }
3797
3798     Printf(w->code, "}");
3799
3800     // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
3801     String *inline_extra_method = NewString("");
3802     if (dirprot_mode() && !is_public(n) && !pure_virtual) {
3803       Printv(inline_extra_method, declaration, NIL);
3804       String *extra_method_name = NewStringf("%sSwigPublic", name);
3805       Replaceall(inline_extra_method, name, extra_method_name);
3806       Replaceall(inline_extra_method, ";\n", " {\n      ");
3807       if (!is_void)
3808         Printf(inline_extra_method, "return ");
3809       String *methodcall = Swig_method_call(super, l);
3810       Printv(inline_extra_method, methodcall, ";\n    }\n", NIL);
3811       Delete(methodcall);
3812       Delete(extra_method_name);
3813     }
3814
3815     /* emit code */
3816     if (status == SWIG_OK && output_director) {
3817       if (!is_void) {
3818         Replaceall(w->code, "$null", qualified_return);
3819       } else {
3820         Replaceall(w->code, "$null", "");
3821       }
3822       if (!GetFlag(n, "feature:ignore"))
3823         Printv(imclass_directors, callback_def, callback_code, NIL);
3824       if (!Getattr(n, "defaultargs")) {
3825         Wrapper_print(w, f_directors);
3826         Printv(f_directors_h, declaration, NIL);
3827         Printv(f_directors_h, inline_extra_method, NIL);
3828       }
3829     }
3830
3831     Delete(inline_extra_method);
3832     Delete(qualified_return);
3833     Delete(jnidesc);
3834     Delete(c_ret_type);
3835     Delete(jniret_desc);
3836     Delete(declaration);
3837     Delete(callback_def);
3838     Delete(callback_code);
3839     DelWrapper(w);
3840
3841     return status;
3842   }
3843
3844   /* ------------------------------------------------------------
3845    * directorPrefixArgs()
3846    * ------------------------------------------------------------ */
3847
3848   void directorPrefixArgs(Node *n) {
3849     Parm *p;
3850
3851     /* Need to prepend 'jenv' to the director constructor's argument list */
3852
3853     String *jenv_type = NewString("JNIEnv");
3854
3855     SwigType_add_pointer(jenv_type);
3856
3857     p = NewParmFromNode(jenv_type, NewString("jenv"), n);
3858     Setattr(p, "arg:byname", "1");
3859     set_nextSibling(p, NULL);
3860
3861     Setattr(n, "director:prefix_args", p);
3862   }
3863
3864   /* ------------------------------------------------------------
3865    * classDirectorConstructor()
3866    * ------------------------------------------------------------ */
3867
3868   int classDirectorConstructor(Node *n) {
3869     Node *parent = parentNode(n);
3870     String *decl = Getattr(n, "decl");;
3871     String *supername = Swig_class_name(parent);
3872     String *classname = directorClassName(parent);
3873     String *sub = NewString("");
3874     Parm *p;
3875     ParmList *superparms = Getattr(n, "parms");
3876     ParmList *parms;
3877     int argidx = 0;
3878
3879     /* Assign arguments to superclass's parameters, if not already done */
3880     for (p = superparms; p; p = nextSibling(p)) {
3881       String *pname = Getattr(p, "name");
3882
3883       if (!pname) {
3884         pname = NewStringf("arg%d", argidx++);
3885         Setattr(p, "name", pname);
3886       }
3887     }
3888
3889     /* insert jenv prefix argument */
3890     parms = CopyParmList(superparms);
3891
3892     String *jenv_type = NewString("JNIEnv");
3893     SwigType_add_pointer(jenv_type);
3894     p = NewParmFromNode(jenv_type, NewString("jenv"), n);
3895     set_nextSibling(p, parms);
3896     parms = p;
3897
3898     directorPrefixArgs(n);
3899
3900     if (!Getattr(n, "defaultargs")) {
3901       /* constructor */
3902       {
3903         String *basetype = Getattr(parent, "classtype");
3904         String *target = Swig_method_decl(0, decl, classname, parms, 0, 0);
3905         String *call = Swig_csuperclass_call(0, basetype, superparms);
3906         String *classtype = SwigType_namestr(Getattr(n, "name"));
3907
3908         Printf(f_directors, "%s::%s : %s, %s {\n", classname, target, call, Getattr(parent, "director:ctor"));
3909         Printf(f_directors, "}\n\n");
3910
3911         Delete(classtype);
3912         Delete(target);
3913         Delete(call);
3914       }
3915
3916       /* constructor header */
3917       {
3918         String *target = Swig_method_decl(0, decl, classname, parms, 0, 1);
3919         Printf(f_directors_h, "    %s;\n", target);
3920         Delete(target);
3921       }
3922     }
3923
3924     Delete(sub);
3925     Delete(supername);
3926     Delete(jenv_type);
3927     Delete(parms);
3928     return Language::classDirectorConstructor(n);
3929   }
3930
3931   /* ------------------------------------------------------------
3932    * classDirectorDefaultConstructor()
3933    * ------------------------------------------------------------ */
3934
3935   int classDirectorDefaultConstructor(Node *n) {
3936     String *classname = Swig_class_name(n);
3937     String *classtype = SwigType_namestr(Getattr(n, "name"));
3938     Wrapper *w = NewWrapper();
3939
3940     Printf(w->def, "SwigDirector_%s::SwigDirector_%s(JNIEnv *jenv) : %s {", classname, classname, Getattr(n, "director:ctor"));
3941     Printf(w->code, "}\n");
3942     Wrapper_print(w, f_directors);
3943
3944     Printf(f_directors_h, "    SwigDirector_%s(JNIEnv *jenv);\n", classname);
3945     DelWrapper(w);
3946     Delete(classtype);
3947     Delete(classname);
3948     directorPrefixArgs(n);
3949     return Language::classDirectorDefaultConstructor(n);
3950   }
3951
3952
3953   /* ------------------------------------------------------------
3954    * classDirectorInit()
3955    * ------------------------------------------------------------ */
3956
3957   int classDirectorInit(Node *n) {
3958     Delete(none_comparison);
3959     none_comparison = NewString("");    // not used
3960
3961     Delete(director_ctor_code);
3962     director_ctor_code = NewString("$director_new");
3963
3964     Java_director_declaration(n);
3965
3966     Printf(f_directors_h, "%s {\n", Getattr(n, "director:decl"));
3967     Printf(f_directors_h, "\npublic:\n");
3968     Printf(f_directors_h, "    void swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global);\n");
3969
3970     /* Keep track of the director methods for this class */
3971     first_class_dmethod = curr_class_dmethod = n_dmethods;
3972
3973     return Language::classDirectorInit(n);
3974   }
3975
3976   /* ----------------------------------------------------------------------
3977    * classDirectorDestructor()
3978    * ---------------------------------------------------------------------- */
3979
3980   int classDirectorDestructor(Node *n) {
3981     Node *current_class = getCurrentClass();
3982     String *full_classname = Getattr(current_class, "name");
3983     String *classname = Swig_class_name(current_class);
3984     Wrapper *w = NewWrapper();
3985
3986     if (Getattr(n, "throw")) {
3987       Printf(f_directors_h, "    virtual ~SwigDirector_%s() throw ();\n", classname);
3988       Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() throw () {\n", classname, classname);
3989     } else {
3990       Printf(f_directors_h, "    virtual ~SwigDirector_%s();\n", classname);
3991       Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() {\n", classname, classname);
3992     }
3993
3994     /* Ensure that correct directordisconnect typemap's method name is called
3995      * here: */
3996
3997     const String *disconn_tm = NULL;
3998     Node *disconn_attr = NewHash();
3999     String *disconn_methodname = NULL;
4000
4001     disconn_tm = typemapLookup(n, "directordisconnect", full_classname, WARN_NONE, disconn_attr);
4002     disconn_methodname = Getattr(disconn_attr, "tmap:directordisconnect:methodname");
4003
4004     Printv(w->code, "  swig_disconnect_director_self(\"", disconn_methodname, "\");\n", "}\n", NIL);
4005
4006     Wrapper_print(w, f_directors);
4007
4008     DelWrapper(w);
4009     Delete(disconn_attr);
4010     Delete(classname);
4011     return SWIG_OK;
4012   }
4013
4014   /* ------------------------------------------------------------
4015    * classDirectorEnd()
4016    * ------------------------------------------------------------ */
4017
4018   int classDirectorEnd(Node *n) {
4019     String *classname = Getattr(n, "sym:name");
4020     String *director_classname = directorClassName(n);
4021     String *internal_classname;
4022
4023     Wrapper *w = NewWrapper();
4024
4025     if (Len(package_path) > 0)
4026       internal_classname = NewStringf("%s/%s", package_path, classname);
4027     else
4028       internal_classname = NewStringf("%s", classname);
4029
4030     Wrapper_add_localv(w, "baseclass", "static jclass baseclass", "= 0", NIL);
4031     Printf(w->def, "void %s::swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global) {", director_classname);
4032
4033     if (first_class_dmethod != curr_class_dmethod) {
4034       Printf(w->def, "static struct {\n");
4035       Printf(w->def, "const char *mname;\n");
4036       Printf(w->def, "const char *mdesc;\n");
4037       Printf(w->def, "jmethodID base_methid;\n");
4038       Printf(w->def, "} methods[] = {\n");
4039
4040       for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
4041         UpcallData *udata = Getitem(dmethods_seq, i);
4042
4043         Printf(w->def, "{ \"%s\", \"%s\", NULL }", Getattr(udata, "method"), Getattr(udata, "fdesc"));
4044         if (i != curr_class_dmethod - 1)
4045           Putc(',', w->def);
4046         Putc('\n', w->def);
4047       }
4048
4049       Printf(w->def, "};\n");
4050     }
4051
4052     Printf(w->code, "if (swig_set_self(jenv, jself, swig_mem_own, weak_global)) {\n");
4053     Printf(w->code, "if (!baseclass) {\n");
4054     Printf(w->code, "baseclass = jenv->FindClass(\"%s\");\n", internal_classname);
4055     Printf(w->code, "if (!baseclass) return;\n");
4056     Printf(w->code, "baseclass = (jclass) jenv->NewGlobalRef(baseclass);\n");
4057     Printf(w->code, "}\n");
4058
4059     int n_methods = curr_class_dmethod - first_class_dmethod;
4060
4061     if (n_methods) {
4062       /* Emit the swig_overrides() method and the swig_override array */
4063       Printf(f_directors_h, "public:\n");
4064       Printf(f_directors_h, "    bool swig_overrides(int n) {\n");
4065       Printf(f_directors_h, "      return (n < %d ? swig_override[n] : false);\n", n_methods);
4066       Printf(f_directors_h, "    }\n");
4067       Printf(f_directors_h, "protected:\n");
4068       Printf(f_directors_h, "    bool swig_override[%d];\n", n_methods);
4069
4070       /* Emit the code to look up the class's methods, initialize the override array */
4071
4072       Printf(w->code, "bool derived = (jenv->IsSameObject(baseclass, jcls) ? false : true);\n");
4073       Printf(w->code, "for (int i = 0; i < %d; ++i) {\n", n_methods);
4074       Printf(w->code, "  if (!methods[i].base_methid) {\n");
4075       Printf(w->code, "    methods[i].base_methid = jenv->GetMethodID(baseclass, methods[i].mname, methods[i].mdesc);\n");
4076       Printf(w->code, "    if (!methods[i].base_methid) return;\n");
4077       Printf(w->code, "  }\n");
4078       Printf(w->code, "  swig_override[i] = false;\n");
4079       Printf(w->code, "  if (derived) {\n");
4080       Printf(w->code, "    jmethodID methid = jenv->GetMethodID(jcls, methods[i].mname, methods[i].mdesc);\n");
4081       Printf(w->code, "    swig_override[i] = (methid != methods[i].base_methid);\n");
4082       Printf(w->code, "    jenv->ExceptionClear();\n");
4083       Printf(w->code, "  }\n");
4084       Printf(w->code, "}\n");
4085     } else {
4086       Printf(f_directors_h, "public:\n");
4087       Printf(f_directors_h, "    bool swig_overrides(int n) {\n");
4088       Printf(f_directors_h, "      return false;\n");
4089       Printf(f_directors_h, "    }\n");
4090     }
4091
4092     Printf(f_directors_h, "};\n\n");
4093     Printf(w->code, "}\n");
4094     Printf(w->code, "}\n");
4095
4096     Wrapper_print(w, f_directors);
4097
4098     DelWrapper(w);
4099     Delete(internal_classname);
4100
4101     return Language::classDirectorEnd(n);
4102   }
4103
4104   /* --------------------------------------------------------------------
4105    * classDirectorDisown()
4106    * ------------------------------------------------------------------*/
4107
4108   virtual int classDirectorDisown(Node *n) {
4109     (void) n;
4110     return SWIG_OK;
4111   }
4112
4113   /*----------------------------------------------------------------------
4114    * extraDirectorProtectedCPPMethodsRequired()
4115    *--------------------------------------------------------------------*/
4116   bool extraDirectorProtectedCPPMethodsRequired() const {
4117     return false;
4118   }
4119
4120   /*----------------------------------------------------------------------
4121    * Java_director_declaration()
4122    *
4123    * Generate the director class's declaration
4124    * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
4125    *--------------------------------------------------------------------*/
4126
4127   void Java_director_declaration(Node *n) {
4128     String *base = Getattr(n, "classtype");
4129     String *class_ctor = NewString("Swig::Director(jenv)");
4130
4131     String *classname = Swig_class_name(n);
4132     String *directorname = NewStringf("SwigDirector_%s", classname);
4133     String *declaration = Swig_class_declaration(n, directorname);
4134
4135     Printf(declaration, " : public %s, public Swig::Director", base);
4136
4137     // Stash stuff for later.
4138     Setattr(n, "director:decl", declaration);
4139     Setattr(n, "director:ctor", class_ctor);
4140   }
4141
4142 };                              /* class JAVA */
4143
4144 /* -----------------------------------------------------------------------------
4145  * swig_java()    - Instantiate module
4146  * ----------------------------------------------------------------------------- */
4147
4148 static Language *new_swig_java() {
4149   return new JAVA();
4150 }
4151 extern "C" Language *swig_java(void) {
4152   return new_swig_java();
4153 }
4154
4155 /* -----------------------------------------------------------------------------
4156  * Static member variables
4157  * ----------------------------------------------------------------------------- */
4158
4159 const char *JAVA::usage = (char *) "\
4160 Java Options (available with -java)\n\
4161      -nopgcpp        - Suppress premature garbage collection prevention parameter\n\
4162      -noproxy        - Generate the low-level functional interface instead\n\
4163                        of proxy classes\n\
4164      -oldvarnames    - old intermediary method names for variable wrappers\n\
4165      -package <name> - set name of the Java package to <name>\n\
4166 \n";