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
10char 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++ */
18typedef DOH UpcallData;
19
20class 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
93public:
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
4148static Language *new_swig_java() {
4149  return new JAVA();
4150}
4151extern "C" Language *swig_java(void) {
4152  return new_swig_java();
4153}
4154
4155/* -----------------------------------------------------------------------------
4156 * Static member variables
4157 * ----------------------------------------------------------------------------- */
4158
4159const char *JAVA::usage = (char *) "\
4160Java 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";
4167