/*
 * File:        sidl_Java.c
 * Copyright:   (c) 2001 Lawrence Livermore National Security, LLC
 * Revision:    @(#) $Revision: 6482 $
 * Date:        $Date: 2008-08-21 15:50:53 -0700 (Thu, 21 Aug 2008) $
 * Description: run-time support for Java integration with the JVM
 * Copyright (c) 2000-2001, Lawrence Livermore National Security, LLC
 * Produced at the Lawrence Livermore National Laboratory.
 * Written by the Components Team <components@llnl.gov>
 * UCRL-CODE-2002-054
 * All rights reserved.
 * 
 * This file is part of Babel. For more information, see
 * http://www.llnl.gov/CASC/components/. Please read the COPYRIGHT file
 * for Our Notice and the LICENSE file for the GNU Lesser General Public
 * License.
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (as published by
 * the Free Software Foundation) version 2.1 dated February 1999.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
 * conditions of the GNU Lesser General Public License for more details.
 * 
 * You should have recieved a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * WARNING!!!!! SOME (BUT NOT ALL) OF THIS FILE IS AUTOGENERATED!  From the top
 * through the go_llnl_sidl_BaseArray fucntion is all hand written.  However, 
 * below that is all autogenerated by the gen-java-arrays.sh script.  Look
 * for the big comment to find the break point.
 *
 */

#include "sidl_Java.h"
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "babel_config.h"
#include "sidlType.h"
#include "sidl_BaseClass.h"
#include "sidl_BaseInterface.h"
#include "sidl_DLL.h"
#include "sidl_Loader.h"
#include "sidl_String.h"
#include "sidl_Exception.h"
#include "sidlArray.h"
#if defined(SIDL_DEBUG_REFCOUNT) && defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include <stdlib.h>


#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef NULL
#define NULL 0
#endif

/*
 * Convert between jlongs and void* pointers.
 */
#if (SIZEOF_VOID_P == 8)
#define JLONG_TO_POINTER(x) ((void*)(x))
#define POINTER_TO_JLONG(x) ((jlong)(x))
#else
#define JLONG_TO_POINTER(x) ((void*)(int32_t)(x))
#define POINTER_TO_JLONG(x) ((jlong)(int32_t)(x))
#endif

/*
 * This static variable is a reference to the Java JVM.  It is either
 * taken from a currently running JVM or from creating a new JVM.
 */
static JavaVM* s_jvm = NULL;

#ifdef SIDL_DEBUG_REFCOUNT
static void sidl_cleanup_JVM(void *ignored)
{
  JNIEnv *env = sidl_Java_getEnv();
  if (env) {
    jclass sys = (*env)->FindClass(env, "java/lang/System");
    if (sys) {
      jmethodID mid = (*env)->GetStaticMethodID(env, sys, "gc", "()V");
      if (mid) {
        int i;
        printf("\n\n\nCleaningup JVM!!\n\n\n");
        for(i = 0; i < 3; ++i) {
          (*env)->CallStaticVoidMethod(env, sys, mid, NULL);
#ifdef HAVE_UNISTD_H
          usleep(100000);
#endif
        }
      }
      else {
        printf("\n\n\nFailed to lookup gc method.\n\n\n");
      }
      (*env)->DeleteLocalRef(env, sys);
    }
    else {
      printf("\n\n\nFailed to find class java/lang/System.\n\n\n");
    }
  }
  else {
    printf("\n\n\nJava env is NULL.\n\n\n");
  }
  if (s_jvm){
    printf("Destroying JVM!!!\n");
    (*s_jvm)->DestroyJavaVM(s_jvm);
#ifdef HAVE_UNISTD_H
    usleep(100000);
#endif
    s_jvm = NULL;
  }
}
#endif

/*
 * Static method to create a JVM if one has not already been created.  This
 * method takes the CLASSPATH from the environment.
 */
static void sidl_Java_getJVM(void)
{
  typedef jint (*jvmf_t)(JavaVM**,JNIEnv**,JavaVMInitArgs*);
  sidl_BaseInterface _ex; /*TODO: a way to not throw these away? */
  if (s_jvm == NULL) {
    JavaVMInitArgs vm_args;
    JavaVMOption*  options = NULL;
    char *         babel_jvm_flags = NULL;
    char *         index_ptr = NULL; 
    int            num_flags, count = 0;
    
    JNIEnv* env     = NULL;
    jvmf_t  jvmf    = NULL;
    char*   clspath = NULL;
    sidl_DLL dll;
    sidl__array_add(NULL); /* force array leak checking to initialize first */
    babel_jvm_flags = getenv("BABEL_JVM_FLAGS");
#if defined(_AIX)
    setenv("AIXTHREAD_SCOPE", "S", 1);
    setenv("AIXTHREAD_MUTEX_DEBUG", "OFF", 1);
    setenv("AIXTHREAD_RWLOCK_DEBUG", "OFF", 1);
    setenv("AIXTHREAD_COND_DEBUG", "OFF", 1);
#endif
    /*This section of code takes any flags passed in through the enviornment
      variable BABEL_JVM_FLAGS and passed them to the JVM*/
    
    if((babel_jvm_flags != NULL) && (strlen(babel_jvm_flags) > 1)) {
      index_ptr = babel_jvm_flags;
      num_flags = 3;  /*Default 2 flags below, plus at least 1*/
      while(*index_ptr != '\0') {  /*count up flags*/
        if(*index_ptr == ';')
          ++num_flags;
        ++index_ptr;
      }
      options = (JavaVMOption*)calloc(num_flags, sizeof(JavaVMOption));
      for(count = 2; count < num_flags; ++count) {
        if(count == 2)
          options[count].optionString = (char*)strtok(babel_jvm_flags, ";");
        else 
          options[count].optionString = (char*)strtok(NULL, ";");
      }
    } else {
      num_flags = 2;
      options = (JavaVMOption*)calloc(num_flags, sizeof(JavaVMOption));
    }  
    
    clspath = sidl_String_concat2("-Djava.class.path=", getenv("CLASSPATH"));
    
    options[0].optionString = "-Djava.compiler=NONE";
    options[1].optionString = clspath;
    
    vm_args.version            = 0x00010002;
    vm_args.options            = options;
    vm_args.nOptions           = num_flags;
    vm_args.ignoreUnrecognized = 1;
    
    dll = sidl_DLL__create(&_ex); SIDL_CHECK(_ex);
    if (dll) {
      sidl_bool loaded = sidl_DLL_loadLibrary(dll, "main:", TRUE, TRUE, &_ex); SIDL_CHECK(_ex);
      if (loaded) { 
        jvmf = (jvmf_t) sidl_DLL_lookupSymbol(dll, "JNI_CreateJavaVM", &_ex); SIDL_CHECK(_ex);
      }
      sidl_DLL_deleteRef(dll, &_ex);SIDL_CHECK(_ex);
    }
    if (!jvmf) { /* not in main: */
#ifdef JVM_SHARED_LIBRARY
      char *url = sidl_String_concat2("file:", JVM_SHARED_LIBRARY);
      if (url) {
        dll = sidl_Loader_loadLibrary(url, TRUE, TRUE,&_ex);SIDL_CHECK(_ex);
        if (dll) {
          jvmf = (jvmf_t) sidl_DLL_lookupSymbol(dll, "JNI_CreateJavaVM",&_ex); SIDL_CHECK(_ex);
          sidl_DLL_deleteRef(dll,&_ex); SIDL_CHECK(_ex);
        }
        sidl_String_free(url);
      }
#else
      fprintf(stderr, "Babel: Unable to initialized Java Virtual Machine\n\
 Babel: JVM shared library not found during Babel configuration.\n");
#endif
    }
    if (jvmf != NULL) {
      if (((*jvmf)(&s_jvm, &env, &vm_args)) < 0) {
        s_jvm = NULL;
      }
#ifdef SIDL_DEBUG_REFCOUNT
      else {
        sidl_atexit(sidl_cleanup_JVM, NULL);
      }
#endif
    }
    sidl_String_free(clspath);
    free(options);  /*calloced above*/
  }
 EXIT:
  return;
}

/*
 * Attach the current thread to the running JVM and return the Java
 * environment description.  If there is not a currently running JVM,
 * then one is created.
 */
JNIEnv* sidl_Java_getEnv(void)
{
  JNIEnv* env = NULL;
  if (s_jvm == NULL) {
    (void) sidl_Java_getJVM();
  }
  if (s_jvm != NULL) {
    if (((*s_jvm)->GetEnv(s_jvm, (void **)&env, JNI_VERSION_1_4) == JNI_OK) &&
        (env != NULL)) return env;
    (*s_jvm)->AttachCurrentThread(s_jvm, (void**)&env, NULL);
  }
  return env;
}

/*
 * JNI method called by Java to register sidl JNI native implementations.
 */
void Java_gov_llnl_sidl_BaseClass__1registerNatives(
						    JNIEnv* env,
						    jclass  cls,
						    jstring name)
{
  const char* s = NULL;
  sidl_BaseInterface _ex; /*TODO: a way to not throw these away? */

  /*
   * Get a handle to the Java virtual machine if we have
   * not already done so.
   */
  if (s_jvm == NULL) {
    (*env)->GetJavaVM(env, &s_jvm);
  }

  /*
   * Extract the sidl name and convert it to linker registration
   * symbol.  Add a "__register" suffix and convert "." scope
   * separators to underscores.
   */
  
  s = (*env)->GetStringUTFChars(env, name, NULL);
  if (s) {
    sidl_DLL dll = NULL;
    void* address = NULL;
    char* symbol  = sidl_String_concat2(s, "__register");

    sidl_String_replace(symbol, '.', '_');

    /* search the global namespace first */
    dll = sidl_DLL__create(&_ex); SIDL_CHECK(_ex);
    if (dll) {
      sidl_bool loaded = sidl_DLL_loadLibrary(dll, "main:", TRUE, FALSE, &_ex); SIDL_CHECK(_ex);
      if (loaded) { 
        address = sidl_DLL_lookupSymbol(dll, symbol, &_ex); SIDL_CHECK(_ex);
      }
      sidl_DLL_deleteRef(dll,&_ex);SIDL_CHECK(_ex);
    }

    if (!address) {
      /*
       * If we find the registration function in the DLL path, then register
       * the Java types.  Otherwise, return with a unsatisfied link error.
       */
      dll = sidl_Loader_findLibrary(s, "java",
                                    sidl_Scope_SCLSCOPE,
                                    sidl_Resolve_SCLRESOLVE, &_ex);SIDL_CHECK(_ex);
      if (dll) {
        address = sidl_DLL_lookupSymbol(dll, symbol,&_ex);SIDL_CHECK(_ex);
        sidl_DLL_deleteRef(dll,&_ex);SIDL_CHECK(_ex);
      }
    }
    if (address) {
      ((void(*)(JNIEnv*)) address)(env);
    } 
    else {
      jclass e = (*env)->FindClass(env, "java/lang/UnsatisfiedLinkError");
      if (e != NULL) {
        char* msg = sidl_String_concat3(
                                        "Could not find native class \"", s, "\"; check SIDL_DLL_PATH");
        (*env)->ThrowNew(env, e, msg);
        sidl_String_free(msg);
        (*env)->DeleteLocalRef(env, e);
      }
    }
    sidl_String_free(symbol);
    (*env)->ReleaseStringUTFChars(env, name, s);
  }
 EXIT:
  return;
}

/*
 * JNI method called by Java base class to cast this sidl IOR object.
 */
jlong Java_gov_llnl_sidl_BaseClass__1cast_1ior(
					       JNIEnv* env,
					       jobject obj,
					       jstring name)
{
  jlong ior = 0;
  sidl_BaseInterface ex = NULL;

  if (name != (jstring) NULL) {
    jclass    cls = (*env)->GetObjectClass(env, obj);
    jmethodID mid = (*env)->GetMethodID(env, cls, "_get_ior", "()J");
    void*     ptr = JLONG_TO_POINTER((*env)->CallLongMethod(env, obj, mid));

    (*env)->DeleteLocalRef(env, cls);

    if (ptr != NULL) {
      
      const char* utf = (*env)->GetStringUTFChars(env, name, NULL);
      ior = POINTER_TO_JLONG(sidl_BaseInterface__cast2(ptr, utf, &ex)); SIDL_CHECK(ex);
      (*env)->ReleaseStringUTFChars(env, name, utf);
    }
  }

  return ior;
 EXIT:
  sidl_Java_CheckException(env,
			   ex,
			   "sidl.RuntimeException",
			   NULL);
  
  return 0;
  
}

/*
 * JNI method called by Java base class to get the url of this object.
 */
jstring Java_gov_llnl_sidl_BaseClass__1getURL(
					      JNIEnv* env,
					      jobject obj)
{
  char* _ior_res = (char*) NULL;
  jstring _res = (jstring) NULL;
  sidl_BaseInterface ex = NULL;

  jclass    cls = (*env)->GetObjectClass(env, obj);
  jmethodID mid = (*env)->GetMethodID(env, cls, "_get_ior", "()J");
  void*     ptr = JLONG_TO_POINTER((*env)->CallLongMethod(env, obj, mid));
  
  (*env)->DeleteLocalRef(env, cls);
  
  if (ptr != NULL) {
    _ior_res = sidl_BaseInterface__getURL(ptr, &ex); SIDL_CHECK(ex);
    _res = sidl_Java_I2J_string(env, _ior_res);
    sidl_String_free(_ior_res);
  }

  return _res;
 EXIT:
  sidl_Java_CheckException(env,
			   ex,
			   "sidl.RuntimeException",
			   NULL);
  
  return _res;
  
}

/*
 * JNI method called by Java base class to see if this object is implemented remotely
 */
jboolean Java_gov_llnl_sidl_BaseClass__1isRemote(
						 JNIEnv* env,
						 jobject obj)
{
 
  jboolean _res = (jboolean) NULL;
  sidl_BaseInterface ex = NULL;

  jclass    cls = (*env)->GetObjectClass(env, obj);
  jmethodID mid = (*env)->GetMethodID(env, cls, "_get_ior", "()J");
  void*     ptr = JLONG_TO_POINTER((*env)->CallLongMethod(env, obj, mid));
  
  (*env)->DeleteLocalRef(env, cls);
  
  if (ptr != NULL) {
    _res = (jboolean) sidl_BaseInterface__isRemote(ptr, &ex); SIDL_CHECK(ex);
  }

  return _res;
 EXIT:
  sidl_Java_CheckException(env,
			   ex,
			   "sidl.RuntimeException",
			   NULL);
  
  return _res;
  
}

/*
 * JNI method called by Java base class to see if this object is implemented locally
 */
jboolean Java_gov_llnl_sidl_BaseClass__1isLocal(
						JNIEnv* env,
						jobject obj)
{
 
  jboolean _res = (jboolean) NULL;
  sidl_BaseInterface ex = NULL;

  jclass    cls = (*env)->GetObjectClass(env, obj);
  jmethodID mid = (*env)->GetMethodID(env, cls, "_get_ior", "()J");
  void*     ptr = JLONG_TO_POINTER((*env)->CallLongMethod(env, obj, mid));
  
  (*env)->DeleteLocalRef(env, cls);
  
  if (ptr != NULL) {
    _res = (jboolean) sidl_BaseInterface__isRemote(ptr, &ex); SIDL_CHECK(ex);
  }

  return !_res;
 EXIT:
  sidl_Java_CheckException(env,
			   ex,
			   "sidl.RuntimeException",
			   NULL);
  
  return _res;
  
}

/*
 * JNI method called by Java base class to see if this object is implemented locally
 */
/*void Java_gov_llnl_sidl_BaseClass__1exec(
  JNIEnv* env,
  jobject obj,
  jstring methodName,
  jobject inArgs,
  jobject outArgs)
  {
 
  sidl_BaseInterface ex = NULL;

  jclass    cls = (*env)->GetObjectClass(env, obj);
  jmethodID mid = (*env)->GetMethodID(env, cls, "_get_ior", "()J");
  void*     ptr = JLONG_TO_POINTER((*env)->CallLongMethod(env, obj, mid));
  struct sidl_rmi_Call__object* _tmp_inArgs = NULL;
  struct sidl_rmi_Return__object* _tmp_outArgs = NULL;
  char* _tmp_methodName = NULL;

  (*env)->DeleteLocalRef(env, cls);

  if (ptr != NULL) {
  _tmp_inArgs = (struct sidl_rmi_Call__object*) sidl_Java_J2I_cls(env,
  inArgs, FALSE);JAVA_CHECK(env);
  _tmp_outArgs = (struct sidl_rmi_Return__object*) sidl_Java_J2I_cls(env,
  outArgs, FALSE);JAVA_CHECK(env);
  _tmp_methodName = sidl_Java_J2I_string(env, methodName);

  sidl_BaseInterface__exec(ptr, _tmp_methodName, _tmp_inArgs, _tmp_outArgs, &ex); 
  SIDL_CHECK(ex);
  }

  return;
  
  EXIT:
  sidl_Java_CheckException(env,
  ex,
  "sidl.RuntimeException",
  NULL);
  JAVA_EXIT:

  return;
  
  }
*/
/*
 * JNI method called by Java base class to dereference sidl IOR objects.
 */
void Java_gov_llnl_sidl_BaseClass__1finalize(
					     JNIEnv* env,
					     jobject obj)
{
  void* ptr = NULL;
  sidl_BaseInterface _ex; /*TODO: a way to not throw these away? */

  /*
   * Initialize the IOR data member reference to avoid repeated lookups.
   */
  static jfieldID s_ior_field = NULL;

  if (s_ior_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_ior_field = (*env)->GetFieldID(env, cls, "d_ior", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  /*
   * Extract the IOR reference from the object and decrement the reference
   * count.
   */
  ptr = JLONG_TO_POINTER((*env)->GetLongField(env, obj, s_ior_field));

  if (ptr != NULL) {
    struct sidl_BaseInterface__object* bi = (struct sidl_BaseInterface__object*) ptr;
    (bi->d_epv->f_deleteRef)(bi->d_object, &_ex);
   
  }
  (*env)->SetLongField(env, obj, s_ior_field, (jlong) NULL);
}


/*
 * Return TRUE if the specified object is a sidl class; otherwise, return
 * FALSE.
 */
sidl_bool sidl_Java_isClass(
			    JNIEnv* env,
			    struct sidl_BaseInterface__object* ptr, 
			    const char* type)
{
  struct sidl_BaseInterface__object* ex = NULL;
  jclass cls = (jclass) NULL;
  char* name = NULL; 
  jmethodID ctor = NULL;
  /*If the type is wrong, this is not the class you're looking for*/
  if(ptr == NULL) {
    int is_type = sidl_BaseInterface_isType(ptr, type, &ex);SIDL_CHECK(ex);
    if(!is_type){
      return FALSE;
    }
  }
  /*If the type works, check if it's actually a class by trying to
   * find its constructor */
    
  name = sidl_String_strdup(type);
  sidl_String_replace(name, '.', '/');

  cls = (*env)->FindClass(env, name);
  if ((*env)->ExceptionCheck(env)) {
    (*env)->ExceptionClear(env);
    return FALSE;
  }

  ctor = (*env)->GetMethodID(env, cls, "<init>", "(J)V");
  if ((*env)->ExceptionCheck(env) || ctor == NULL) {
    (*env)->ExceptionClear(env);
    return FALSE;
  }
  
  /*If it has a constructor, it must be a class.*/
  return TRUE;
 EXIT:
  sidl_Java_CheckException(env,
			   ex,
			   "sidl.RuntimeException",
			   NULL);
  
  return FALSE;
}

/*
 * Throw a Java exception if the exception argument is not null.  If the
 * appropriate Java class does not exist, then a class not found exception
 * is thrown.  The variable-argument parameter gives the possible Java type
 * strings.  It must be terminated by a NULL.
 */
void sidl_Java_CheckException(
			      JNIEnv* env,
			      struct sidl_BaseInterface__object* ex,
			      ...)
{
  va_list args;
  const char* type = NULL;
  sidl_BaseInterface throwaway_ex = NULL;
  if (ex != NULL) {

    /*
     * Search the varargs list of possible exception types.  Throw a particular
     * exception type if a match is found.
     */

    va_start(args, ex);
    while ((type = va_arg(args, const char*)) != NULL) {
      void* ptr = sidl_BaseInterface__cast2(ex, type, &throwaway_ex);
      if (ptr != NULL) {
	jthrowable obj;
        sidl_BaseInterface_deleteRef(ex, &throwaway_ex);
	obj = (jthrowable) sidl_Java_I2J_cls(env, ptr, type, FALSE);JAVA_CHECK(env);
	if(!obj) {
	  obj = (jthrowable) sidl_Java_I2J_ifc(env, ptr, type, FALSE);JAVA_CHECK(env);
	}
	if (obj != NULL) {
	  if((*env)->Throw(env, obj) != 0)
	    fprintf(stderr, "Babel: Unable rethrow the exception recieved.\n");
	}
	break;
      }
    }
    va_end(args);

    /*
     * If we were not able to match the exception type, then throw an
     * internal error to the Java JVM.
     */

    if (type == NULL) {
      jclass e = (*env)->FindClass(env, "java/lang/InternalError");
      if (e != NULL) {
        (*env)->ThrowNew(env, e, "Unknown exception thrown by library routine");
        (*env)->DeleteLocalRef(env, e);
      }
    }
  }
  return;
 JAVA_EXIT:
  fprintf(stderr,"Exception caught in sidl_Java_CheckException\n");
  return;
}

/*
 * This test determines if a throwable object from Java is a SIDL object or not..
 */
sidl_bool sidl_Java_isSIDLException(
				    JNIEnv* env,
				    jobject obj)
{
  if(obj != NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    if(cls != NULL) {
      jmethodID mid = (*env)->GetMethodID(env, cls, "_get_ior", "()J");
      if(mid != NULL) {
	return TRUE;
      }
      (*env)->ExceptionClear(env);
    }
  }
  return FALSE;
}

/*
 *  This function takes a SIDL exception from java as jthrowable obj, and checks if it is an 
 *  expected  exception from this function.  If it is it returns the IOR pointer, if not
 *  it returns NULL.
 */

struct sidl_BaseInterface__object* sidl_Java_catch_SIDLException(
								 JNIEnv* env,
								 jthrowable obj,
								 ...)
{
  va_list args;
  const char* type = NULL;
  struct sidl_BaseInterface__object* ex2;
  if (obj != NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    if(cls != NULL) {
      jmethodID mid = (*env)->GetMethodID(env, cls, "_get_ior", "()J");
      void*     ex = JLONG_TO_POINTER((*env)->CallLongMethod(env, obj, mid));
      /*
       * Search the varargs list of possible exception types.  Throw a particular
       * exception type if a match is found.
       */
      va_start(args, obj);
      while ((type = va_arg(args, const char*)) != NULL) {
	void* ptr = sidl_BaseInterface__cast2(ex, type,&ex2);SIDL_CHECK(ex2);
	if (ptr != NULL) {
	  return ex;
	}
      }
      va_end(args);
      (*env)->DeleteLocalRef(env, cls);
    }
  }
  return NULL;
 EXIT:
  sidl_Java_CheckException(env,
			   ex2,
			   "sidl.RuntimeException",
			   NULL);
  
  return NULL;
}


/*
 * Extract the boolean type from the sidl.Boolean.Holder holder class.
 */
sidl_bool sidl_Java_J2I_boolean_holder(
				       JNIEnv* env,
				       jobject obj)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "get", "()Z");
    (*env)->DeleteLocalRef(env, cls);
  }
  return (*env)->CallBooleanMethod(env, obj, mid) ? TRUE : FALSE;
}

/*
 * Set the boolean type in the sidl.Boolean.Holder holder class.
 */
void sidl_Java_I2J_boolean_holder(
				  JNIEnv* env,
				  jobject obj,
				  sidl_bool value)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "set", "(Z)V");
    (*env)->DeleteLocalRef(env, cls);
  }
  (*env)->CallVoidMethod(env, obj, mid, (value ? JNI_TRUE : JNI_FALSE));
}

/*
 * Extract the character type from the sidl.Character.Holder holder class.
 */
char sidl_Java_J2I_character_holder(
				    JNIEnv* env,
				    jobject obj)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "get", "()C");
    (*env)->DeleteLocalRef(env, cls);
  }
  return (char) (*env)->CallCharMethod(env, obj, mid);
}

/*
 * Set the character type in the sidl.Character.Holder holder class.
 */
void sidl_Java_I2J_character_holder(
				    JNIEnv* env,
				    jobject obj,
				    char value)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "set", "(C)V");
    (*env)->DeleteLocalRef(env, cls);
  }
  (*env)->CallVoidMethod(env, obj, mid, (jchar) value);
}

/*
 * Extract the double type from the sidl.Double.Holder holder class.
 */
double sidl_Java_J2I_double_holder(
				   JNIEnv* env,
				   jobject obj)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "get", "()D");
    (*env)->DeleteLocalRef(env, cls);
  }
  return (*env)->CallDoubleMethod(env, obj, mid);
}

/*
 * Set the double type in the sidl.Double.Holder holder class.
 */
void sidl_Java_I2J_double_holder(
				 JNIEnv* env,
				 jobject obj,
				 double value)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "set", "(D)V");
    (*env)->DeleteLocalRef(env, cls);
  }
  (*env)->CallVoidMethod(env, obj, mid, (jdouble) value);
}

/*
 * Extract the float type from the sidl.Float.Holder holder class.
 */
float sidl_Java_J2I_float_holder(
				 JNIEnv* env,
				 jobject obj)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "get", "()F");
    (*env)->DeleteLocalRef(env, cls);
  }
  return (*env)->CallFloatMethod(env, obj, mid);
}

/*
 * Set the float type in the sidl.Float.Holder holder class.
 */
void sidl_Java_I2J_float_holder(
				JNIEnv* env,
				jobject obj,
				float value)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "set", "(F)V");
    (*env)->DeleteLocalRef(env, cls);
  }
  (*env)->CallVoidMethod(env, obj, mid, (jfloat) value);
}

/*
 * Extract the int type from the sidl.Integer.Holder holder class.
 */
int sidl_Java_J2I_int_holder(
			     JNIEnv* env,
			     jobject obj)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "get", "()I");
    (*env)->DeleteLocalRef(env, cls);
  }
  return (*env)->CallIntMethod(env, obj, mid);
}

/*
 * Set the int type in the sidl.Integer.Holder holder class.
 */
void sidl_Java_I2J_int_holder(
			      JNIEnv* env,
			      jobject obj,
			      int value)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "set", "(I)V");
    (*env)->DeleteLocalRef(env, cls);
  }
  (*env)->CallVoidMethod(env, obj, mid, (jint) value);
}

/*
 * Extract the long type from the sidl.Long.Holder holder class.
 */
int64_t sidl_Java_J2I_long_holder(
				  JNIEnv* env,
				  jobject obj)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "get", "()J");
    (*env)->DeleteLocalRef(env, cls);
  }
  return (int64_t) (*env)->CallLongMethod(env, obj, mid);
}

/*
 * Set the long type in the sidl.Long.Holder holder class.
 */
void sidl_Java_I2J_long_holder(
			       JNIEnv* env,
			       jobject obj,
			       int64_t value)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "set", "(J)V");
    (*env)->DeleteLocalRef(env, cls);
  }
  (*env)->CallVoidMethod(env, obj, mid, (jlong) value);
}

/*
 * Extract the opaque type from the sidl.Opaque.Holder holder class.
 */
void* sidl_Java_J2I_opaque_holder(
				  JNIEnv* env,
				  jobject obj)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "get", "()J");
    (*env)->DeleteLocalRef(env, cls);
  }
  return JLONG_TO_POINTER((*env)->CallLongMethod(env, obj, mid));
}

/*
 * Set the opaque type in the sidl.Opaque.Holder holder class.
 */
void sidl_Java_I2J_opaque_holder(
				 JNIEnv* env,
				 jobject obj,
				 void* value)
{
  static jmethodID mid = (jmethodID) NULL;
  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "set", "(J)V");
    (*env)->DeleteLocalRef(env, cls);
  }
  (*env)->CallVoidMethod(env, obj, mid, POINTER_TO_JLONG(value));
}

/*
 * Extract the dcomplex type from the sidl.DoubleComplex.Holder holder class.
 */
struct sidl_dcomplex sidl_Java_J2I_dcomplex_holder(
						   JNIEnv* env,
						   jobject obj)
{
  static jmethodID mid_get  = (jmethodID) NULL;
  struct sidl_dcomplex dcomplex = { 0.0, 0.0 };
  jobject holdee = (jobject) NULL;

  if (mid_get == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid_get  = (*env)->GetMethodID(env, cls, "get", "()Lsidl/DoubleComplex;");
    (*env)->DeleteLocalRef(env, cls);
  }

  holdee   = (*env)->CallObjectMethod(env, obj, mid_get);
  dcomplex = sidl_Java_J2I_dcomplex(env, holdee);
  (*env)->DeleteLocalRef(env, holdee);

  return dcomplex;
}

/*
 * Set the dcomplex type in the sidl.DoubleComplex.Holder holder class.
 */
void sidl_Java_I2J_dcomplex_holder(
				   JNIEnv* env,
				   jobject obj,
				   struct sidl_dcomplex* value)
{
  static jmethodID mid_geth = (jmethodID) NULL;
  static jmethodID mid_setc = (jmethodID) NULL;
  static jmethodID mid_seth = (jmethodID) NULL;

  jobject holdee = (jobject) NULL;

  if (mid_geth == (jmethodID) NULL) {
    jclass cls1 = (*env)->GetObjectClass(env, obj);
    jclass cls2 = (*env)->FindClass(env, "sidl/DoubleComplex");
    mid_geth = (*env)->GetMethodID(env, cls1, "get", "()Lsidl/DoubleComplex;");
    mid_setc = (*env)->GetMethodID(env, cls2, "set", "(DD)V");
    mid_seth = (*env)->GetMethodID(env, cls1, "set", "(Lsidl/DoubleComplex;)V");
    (*env)->DeleteLocalRef(env, cls1);
    (*env)->DeleteLocalRef(env, cls2);
  }

  holdee = (*env)->CallObjectMethod(env, obj, mid_geth);
  if (holdee == NULL) {
    holdee = sidl_Java_I2J_dcomplex(env, value);
    (*env)->CallVoidMethod(env, obj, mid_seth, holdee);
  } else {
    (*env)->CallVoidMethod(env,
                           holdee,
                           mid_setc,
                           value->real,
                           value->imaginary);
  }
  (*env)->DeleteLocalRef(env, holdee);
}

/*
 * Extract the fcomplex type from the sidl.FloatComplex.Holder holder class.
 */
struct sidl_fcomplex sidl_Java_J2I_fcomplex_holder(
						   JNIEnv* env,
						   jobject obj)
{
  static jmethodID mid_get  = (jmethodID) NULL;
  struct sidl_fcomplex fcomplex = { 0.0, 0.0 };
  jobject holdee = (jobject) NULL;

  if (mid_get == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid_get  = (*env)->GetMethodID(env, cls, "get", "()Lsidl/FloatComplex;");
    (*env)->DeleteLocalRef(env, cls);
  }

  holdee   = (*env)->CallObjectMethod(env, obj, mid_get);
  fcomplex = sidl_Java_J2I_fcomplex(env, holdee);
  (*env)->DeleteLocalRef(env, holdee);

  return fcomplex;
}

/*
 * Set the fcomplex type in the sidl.FloatComplex.Holder holder class.
 */
void sidl_Java_I2J_fcomplex_holder(
				   JNIEnv* env,
				   jobject obj,
				   struct sidl_fcomplex* value)
{
  static jmethodID mid_geth = (jmethodID) NULL;
  static jmethodID mid_setc = (jmethodID) NULL;
  static jmethodID mid_seth = (jmethodID) NULL;

  jobject holdee = (jobject) NULL;

  if (mid_geth == (jmethodID) NULL) {
    jclass cls1 = (*env)->GetObjectClass(env, obj);
    jclass cls2 = (*env)->FindClass(env, "sidl/FloatComplex");
    mid_geth = (*env)->GetMethodID(env, cls1, "get", "()Lsidl/FloatComplex;");
    mid_setc = (*env)->GetMethodID(env, cls2, "set", "(FF)V");
    mid_seth = (*env)->GetMethodID(env, cls1, "set", "(Lsidl/FloatComplex;)V");
    (*env)->DeleteLocalRef(env, cls1);
    (*env)->DeleteLocalRef(env, cls2);
  }

  holdee = (*env)->CallObjectMethod(env, obj, mid_geth);
  if (holdee == NULL) {
    holdee = sidl_Java_I2J_fcomplex(env, value);
    (*env)->CallVoidMethod(env, obj, mid_seth, holdee);
  } else {
    (*env)->CallVoidMethod(env,
                           holdee,
                           mid_setc,
                           value->real,
                           value->imaginary);
  }
  (*env)->DeleteLocalRef(env, holdee);
}

/*
 * Extract the double complex type from a sidl.DoubleComplex object.
 */
struct sidl_dcomplex sidl_Java_J2I_dcomplex(
					    JNIEnv* env,
					    jobject obj)
{
  static jmethodID mid_real = (jmethodID) NULL;
  static jmethodID mid_imag = (jmethodID) NULL;

  struct sidl_dcomplex dcomplex = { 0.0, 0.0 };

  if ((mid_real == (jmethodID) NULL) && (obj != (jobject) NULL)) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid_real = (*env)->GetMethodID(env, cls, "real", "()D");
    mid_imag = (*env)->GetMethodID(env, cls, "imag", "()D");
    (*env)->DeleteLocalRef(env, cls);
  }

  if (obj != (jobject) NULL) {
    dcomplex.real      = (*env)->CallDoubleMethod(env, obj, mid_real);
    dcomplex.imaginary = (*env)->CallDoubleMethod(env, obj, mid_imag);
  }

  return dcomplex;
}

/*
 * Create and return a sidl.DoubleComplex object from a sidl double
 * complex value.
 */
jobject sidl_Java_I2J_dcomplex(
			       JNIEnv* env,
			       struct sidl_dcomplex* value)
{
  jclass cls = (*env)->FindClass(env, "sidl/DoubleComplex");
  jmethodID mid_ctor = (*env)->GetMethodID(env, cls, "<init>", "(DD)V");
  jobject obj = (*env)->NewObject(env,
                                  cls,
                                  mid_ctor,
                                  value->real,
                                  value->imaginary);
  (*env)->DeleteLocalRef(env, cls);
  return obj;
}

/*
 * Extract the float complex type from a sidl.FloatComplex object.
 */
struct sidl_fcomplex sidl_Java_J2I_fcomplex(
					    JNIEnv* env,
					    jobject obj)
{
  static jmethodID mid_real = (jmethodID) NULL;
  static jmethodID mid_imag = (jmethodID) NULL;

  struct sidl_fcomplex fcomplex = { 0.0, 0.0 };

  if ((mid_real == (jmethodID) NULL) && (obj != (jobject) NULL)) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid_real = (*env)->GetMethodID(env, cls, "real", "()F");
    mid_imag = (*env)->GetMethodID(env, cls, "imag", "()F");
    (*env)->DeleteLocalRef(env, cls);
  }

  if (obj != (jobject) NULL) {
    fcomplex.real      = (*env)->CallFloatMethod(env, obj, mid_real);
    fcomplex.imaginary = (*env)->CallFloatMethod(env, obj, mid_imag);
  }

  return fcomplex;
}

/*
 * Create and return a sidl.FloatComplex object from a sidl float
 * complex value.
 */
jobject sidl_Java_I2J_fcomplex(
			       JNIEnv* env,
			       struct sidl_fcomplex* value)
{
  jclass cls = (*env)->FindClass(env, "sidl/FloatComplex");
  jmethodID mid_ctor = (*env)->GetMethodID(env, cls, "<init>", "(FF)V");
  jobject obj = (*env)->NewObject(env,
                                  cls,
                                  mid_ctor,
                                  value->real,
                                  value->imaginary);
  (*env)->DeleteLocalRef(env, cls);
  return obj;
}

/*
 * Extract the string type from the sidl.String.Holder holder class.  The
 * string returned by this function must be freed by the system free() routine
 * or sidl_String_free().
 */
char* sidl_Java_J2I_string_holder(
				  JNIEnv* env,
				  jobject obj)
{
  static jmethodID mid = (jmethodID) NULL;
  jobject holdee = (jobject) NULL;
  char* string = NULL;

  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "get", "()Ljava/lang/String;");
    (*env)->DeleteLocalRef(env, cls);
  }

  holdee = (*env)->CallObjectMethod(env, obj, mid);
  string = sidl_Java_J2I_string(env, holdee);
  (*env)->DeleteLocalRef(env, holdee);

  return string;
}

/*
 * Set the string type in the sidl.String.Holder holder class.  An internal
 * copy is made of the string argument; therefore, the caller must free it
 * to avoid a memory leak.
 */
void sidl_Java_I2J_string_holder(
				 JNIEnv* env,
				 jobject obj,
				 const char* value)
{
  static jmethodID mid = (jmethodID) NULL;
  jstring holdee = sidl_Java_I2J_string(env, value);

  if (mid == (jmethodID) NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    mid = (*env)->GetMethodID(env, cls, "set", "(Ljava/lang/String;)V");
    (*env)->DeleteLocalRef(env, cls);
  }

  (*env)->CallVoidMethod(env, obj, mid, holdee);
  (*env)->DeleteLocalRef(env, holdee);
}

/*
 * Extract the string type from the java.lang.String object.  The string
 * returned by this function must be freed by the system free() routine
 * or sidl_String_free().
 */
char* sidl_Java_J2I_string(
			   JNIEnv* env,
			   jstring str)
{
  char* string = NULL;

  if (str != (jstring) NULL) {
    const char* utf = (*env)->GetStringUTFChars(env, str, NULL);
    string = sidl_String_strdup(utf);
    (*env)->ReleaseStringUTFChars(env, str, utf);
  }

  return string;
}

/*
 * Create a java.lang.String object from the specified input string.  An
 * internal copy is made of the string argument; therefore, the caller must
 * free it to avoid a memory leak.
 */
jstring sidl_Java_I2J_string(
			     JNIEnv* env,
			     const char* value)
{
  return value ? (*env)->NewStringUTF(env, value) : NULL;
}

/*
 * Extract the IOR class type from the holder class.  The IOR class type
 * returned by this function will need to be cast to the appropriate IOR
 * type.  The name of the held class must be provided in the java_name.
 */
void* sidl_Java_J2I_cls_holder(
			       JNIEnv* env,
			       jobject obj,
			       const char* java_name,
			       int addRef)
{
  jclass    cls    = (jclass) NULL;
  jmethodID mid    = (jmethodID) NULL;
  jobject   holdee = (jobject) NULL;
  void*     ptr    = NULL;

  
  char* signature = sidl_String_concat3("()L", java_name, ";");
  sidl_String_replace(signature, '.', '/');

  cls    = (*env)->GetObjectClass(env, obj);
  mid    = (*env)->GetMethodID(env, cls, "get", signature);
  holdee = (*env)->CallObjectMethod(env, obj, mid);
  ptr    = sidl_Java_J2I_cls(env, holdee, addRef);
  (*env)->DeleteLocalRef(env, cls);
  (*env)->DeleteLocalRef(env, holdee);
  sidl_String_free(signature);

  return ptr;

}

/*
 * Set the IOR class type in the holder class.  The name of the held class
 * must be provided in the java_name.
 */
void sidl_Java_I2J_cls_holder(
			      JNIEnv* env,
			      jobject obj,
			      void* value,
			      const char* java_name,
			      int addRef)
{
  
  jmethodID mid = (jmethodID) NULL;
  jobject holdee = (jobject) NULL;
  jclass cls = NULL;
  char* signature = NULL;
  cls = (*env)->GetObjectClass(env, obj);
  holdee = sidl_Java_I2J_cls(env, value, java_name, addRef); JAVA_CHECK(env);
  signature = sidl_String_concat3("(L", java_name, ";)V");
  sidl_String_replace(signature, '.', '/');
  
  mid = (*env)->GetMethodID(env, cls, "set", signature);
  (*env)->CallVoidMethod(env, obj, mid, holdee);
  (*env)->DeleteLocalRef(env, cls);
  (*env)->DeleteLocalRef(env, holdee);
  sidl_String_free(signature);
  return;
 JAVA_EXIT:
  if(cls) {(*env)->DeleteLocalRef(env, cls);}
  return;
}

/*
 * Extract the IOR class type from the Java class wrapper.  The IOR class
 * type returned by this function will need to be cast to the appropriate
 * IOR type.
 */
void* sidl_Java_J2I_cls(
			JNIEnv* env,
			jobject obj,
			int addRef)
{
  void* ptr = NULL;

  if (obj != NULL) {
    jclass    cls = (*env)->GetObjectClass(env, obj);    
    jmethodID mid = (*env)->GetMethodID(env, cls, "_get_ior", "()J");
    ptr = JLONG_TO_POINTER((*env)->CallLongMethod(env, obj, mid));
    if (addRef && ptr) {
      sidl_BaseInterface _throwaway_exception;
      sidl_BaseInterface_addRef((struct sidl_BaseInterface__object *)ptr,
                                &_throwaway_exception);
    }
    (*env)->DeleteLocalRef(env, cls);
  }

  return ptr;
}

/*
 * Create a new Java class object to represent the sidl class.  The Java
 * class name must be supplied in the java_name argument.
 */
jobject sidl_Java_I2J_cls(
			  JNIEnv* env,
			  void* value,
			  const char* java_name,
			  int addRef)
{
  sidl_BaseInterface ex = NULL;
 
  jobject obj = (jobject) NULL;
  
  if (value != NULL) {
    jclass cls = (jclass) NULL;
    char* name = sidl_String_strdup(java_name);
    sidl_String_replace(name, '.', '/');
    cls = (*env)->FindClass(env, name);
    if ((*env)->ExceptionCheck(env)) {
      (*env)->ExceptionClear(env);
    }
    if (cls != NULL) {
      jmethodID ctor = (*env)->GetMethodID(env, cls, "<init>", "(J)V");
      if ((*env)->ExceptionCheck(env) || ctor == NULL) {
	(*env)->ExceptionClear(env);
	return NULL;
      } else {
	obj = (*env)->NewObject(env, cls, ctor, POINTER_TO_JLONG(value));
        if (addRef) {
          sidl_BaseInterface_addRef((struct sidl_BaseInterface__object *)
                                    value, &ex);
        }
      }
      (*env)->DeleteLocalRef(env, cls);
    }
    sidl_String_free(name);
  }
  if (ex == NULL) {
    return obj;
  }
  else {
    sidl_Java_CheckException(env,
                             ex,
                             "sidl.RuntimeException",
                             NULL);
  
    return NULL;
  }
}

/*
 * Create an empty Java object of the given name.  Good for cerating holders 
 */

jobject sidl_Java_create_empty_class(
				     JNIEnv* env,
				     const char* java_name)
{
  jobject obj = (jobject) NULL;
  jclass cls = (jclass) NULL;
  char* name = sidl_String_strdup(java_name);
  sidl_String_replace(name, '.', '/');
  cls = (jclass) (*env)->FindClass(env, name);
  if ((*env)->ExceptionOccurred(env)) {
    (*env)->ExceptionDescribe(env);
    return 0;
  }
  if (cls != NULL) {
    jmethodID ctor = (*env)->GetMethodID(env, cls, "<init>", "()V");
    obj = (*env)->NewObject(env, cls, ctor);
    if ((*env)->ExceptionOccurred(env)) {
      (*env)->ExceptionDescribe(env);
      return 0;
    }
    (*env)->DeleteLocalRef(env, cls);
  }
  sidl_String_free(name);
  return obj;
}

/*
 * Extract the IOR interface type from the holder class.  The IOR interface
 * type returned by this function will need to be cast to the appropriate IOR
 * type.  The name of the held class must be provided in the java_name.
 */
void* sidl_Java_J2I_ifc_holder(
			       JNIEnv* env,
			       jobject obj,
			       const char* java_name,
			       int addRef)
{
  jclass    cls    = (jclass) NULL;
  jmethodID mid    = (jmethodID) NULL;
  jobject   holdee = (jobject) NULL;
  void*     ptr    = NULL;

  char* signature = sidl_String_concat3("()L", java_name, ";");
  sidl_String_replace(signature, '.', '/');
  cls    = (*env)->GetObjectClass(env, obj);
  mid    = (*env)->GetMethodID(env, cls, "get", signature);

  holdee = (*env)->CallObjectMethod(env, obj, mid);
  ptr    = sidl_Java_J2I_ifc(env, holdee, java_name, addRef);JAVA_CHECK(env);

  (*env)->DeleteLocalRef(env, cls);
  (*env)->DeleteLocalRef(env, holdee);
  sidl_String_free(signature);

  return ptr;
 JAVA_EXIT:
  if(cls) {(*env)->DeleteLocalRef(env, cls);}
  if(holdee) {(*env)->DeleteLocalRef(env, holdee);}
  return NULL;
}

/*
 * Set the IOR interface type in the holder class.  The name of the held
 * interface must be provided in the java_name.
 */
void sidl_Java_I2J_ifc_holder(
			      JNIEnv* env,
			      jobject obj,
			      void* value,
			      const char* java_name,
			      int addRef)
{
  jmethodID mid = (jmethodID) NULL;
  jobject holdee = NULL;
  jclass cls = NULL;
  char* signature = NULL;

  signature = sidl_String_concat3("(L", java_name, ";)V");
  holdee = sidl_Java_I2J_ifc(env, value, java_name,addRef); JAVA_CHECK(env);
  cls = (*env)->GetObjectClass(env, obj);

  sidl_String_replace(signature, '.', '/');

  mid = (*env)->GetMethodID(env, cls, "set", signature);
  (*env)->CallVoidMethod(env, obj, mid, holdee);

  (*env)->DeleteLocalRef(env, cls);
  (*env)->DeleteLocalRef(env, holdee);
  sidl_String_free(signature);
 JAVA_EXIT:
  return;
}

/*
 * Extract the IOR interface type from the Java interface wrapper.  The
 * IOR interface type returned by this function will need to be cast to the
 * appropriate IOR type.  The sidl name of the desired interface must be
 * provided in the sidl_name.
 */
void* sidl_Java_J2I_ifc(
			JNIEnv* env,
			jobject obj,
			const char* sidl_name,
			int addRef)
{
  void* ptr = NULL;
  struct sidl_BaseInterface__object* ex = NULL;;

  if (obj != NULL) {
    jclass    cls = (*env)->GetObjectClass(env, obj);
    jmethodID mid = NULL;
    void*     ior = NULL;
    mid = (*env)->GetMethodID(env, cls, "_get_ior", "()J");
    if ((*env)->ExceptionCheck(env)) {
      (*env)->ExceptionClear(env);
    }
    ior = JLONG_TO_POINTER((*env)->CallLongMethod(env, obj, mid));
    if ((*env)->ExceptionCheck(env)) {
      (*env)->ExceptionClear(env);
    }
    (*env)->DeleteLocalRef(env, cls);
    if ((*env)->ExceptionCheck(env)) {
      (*env)->ExceptionClear(env);
    }
    
    ptr = sidl_BaseInterface__cast2(ior, sidl_name, &ex);SIDL_CHECK(ex);
    if (!addRef) {
      sidl_BaseInterface_deleteRef(ptr, &ex);SIDL_CHECK(ex);
    }
  }  
  
  return ptr;
 EXIT:
  sidl_Java_CheckException(env,
			   ex,
			   "sidl.RuntimeException",
			   NULL);
  
  return NULL;
}

/*
 * Create a new Java object to represent the sidl interface.  The Java
 * class name must be supplied in the java_name argument.
 *
 * FIXME: Note that this function should be smarter and use metadata from
 * the interface to create the actual concrete class instead of its wrapper.
 */
jobject sidl_Java_I2J_ifc(
			  JNIEnv* env,
			  void* value,
			  const char* java_name,
			  int addRef)
{
  struct sidl_BaseInterface__object* _throwaway_exception = NULL;
  jobject obj = (jobject) NULL;
  if (value != NULL) {
    jclass cls = (jclass) NULL;
    char* wrapper = sidl_String_concat2(java_name, "$Wrapper");
    sidl_String_replace(wrapper, '.', '/');
    cls = (*env)->FindClass(env, wrapper);
    if ((*env)->ExceptionCheck(env)) {
      (*env)->ExceptionClear(env);
    }
    if (cls != NULL) {
      jmethodID ctor = (*env)->GetMethodID(env, cls, "<init>", "(J)V");
      if ((*env)->ExceptionCheck(env) || ctor == NULL) {
	(*env)->ExceptionClear(env);
	return NULL;
      }
      obj = (*env)->NewObject(env, cls, ctor, POINTER_TO_JLONG(value));
      if (addRef && value) {
        sidl_BaseInterface_addRef((struct sidl_BaseInterface__object *)
                                  value, &_throwaway_exception);
      }
      if ((*env)->ExceptionCheck(env)) {
	(*env)->ExceptionDescribe(env);
    	(*env)->ExceptionClear(env);
      }
      (*env)->DeleteLocalRef(env, cls);
    }
    sidl_String_free(wrapper);
  }
  return obj;
}

/*
 * Create a new Java object to represent the sidl interface.  The Java
 * class name must be supplied in the java_name argument.
 *
 * This function is ONLY FOR GETTING AN OBJECT OUT OF ARRAYS.  It's been created 
 * as a hack to get around a refcount problem in Java.  Basically, all objects
 * on creation need to be refcounted before they are passed to java, however,
 * objects that come from arrays have already by the IOR Array.  The is the 
 * same function as sidl_Java_I2J_ifc but without the addRef.
 * 
 */
jobject sidl_Java_Array2J_ifc(
			      JNIEnv* env,
			      void* value,
			      const char* java_name)
{
  jobject obj = (jobject) NULL;
  if (value != NULL) {
    jclass cls = (jclass) NULL;
    char* wrapper = sidl_String_concat2(java_name, "$Wrapper");
    sidl_String_replace(wrapper, '.', '/');
    cls = (*env)->FindClass(env, wrapper);
    if ((*env)->ExceptionCheck(env)) {
      (*env)->ExceptionClear(env);
    }
    if (cls != NULL) {
      jmethodID ctor = (*env)->GetMethodID(env, cls, "<init>", "(J)V");
      if ((*env)->ExceptionCheck(env) || ctor == NULL) {
	(*env)->ExceptionClear(env);
	return NULL;
      }
      obj = (*env)->NewObject(env, cls, ctor, POINTER_TO_JLONG(value));
      if ((*env)->ExceptionCheck(env)) {
	(*env)->ExceptionClear(env);
      }
      (*env)->DeleteLocalRef(env, cls);
    }
    sidl_String_free(wrapper);
  }
  return obj;
}

/*
 * Function to convert an enumerated array type to it's 
 * equivelent Java string.
 */
char* get_array_name(enum sidl_array_type array_type) {
  char * ret = NULL;
  switch(array_type) {
  case sidl_bool_array:
    ret ="sidl/Boolean$Array";
    break;
  case sidl_char_array:
    ret = "sidl/Character$Array";
    break;
  case sidl_dcomplex_array:
    ret = "sidl/DoubleComplex$Array";
    break;
  case sidl_double_array:
    ret = "sidl/Double$Array";
    break;
  case sidl_fcomplex_array:
    ret = "sidl/FloatComplex$Array";
    break;
  case sidl_float_array:
    ret = "sidl/Float$Array";
    break;
  case sidl_int_array:
    ret = "sidl/Integer$Array";
    break;
  case sidl_long_array:
    ret = "sidl/Long$Array";
    break;
  case sidl_opaque_array:
    ret = "sidl/Opaque$Array";
    break;
  case sidl_string_array:
    ret = "sidl/String$Array";
    break;
  case sidl_interface_array:
    return "sidl/BaseInterface$Array";
  default:
    break;
  }

  return ret;

}

/*
 * Set the IOR class type in the holder class.  The name of the held array
 * must be provided in the java_name.
 */
void sidl_Java_I2J_array_holder(
				JNIEnv* env,
				jobject obj,
				void* value,
				const char* java_name)
{
  jmethodID mid = (jmethodID) NULL;
  jobject holdee = NULL;
  jclass cls = NULL;
  char* signature = NULL;
  char* array_name = sidl_String_strdup(java_name);
  if((strcmp(java_name, "gov/llnl/sidl/BaseArray") == 0) ||
     (strcmp(java_name, "gov.llnl.sidl.BaseArray") == 0)) {
    enum sidl_array_type array_type = (enum sidl_array_type) sidl__array_type(((struct sidl__array*)value));
    array_name = sidl_String_strdup(get_array_name(array_type));
  } 
  holdee = sidl_Java_I2J_new_array(env, value, array_name);
  cls = (*env)->GetObjectClass(env, obj);
  signature = sidl_String_concat3("(L", java_name, ";)V");
  sidl_String_replace(signature, '.', '/');
  mid = (*env)->GetMethodID(env, cls, "set", signature);
  (*env)->CallVoidMethod(env, obj, mid, holdee);
  (*env)->DeleteLocalRef(env, holdee);
  (*env)->DeleteLocalRef(env, cls);
  sidl_String_free(signature);
  sidl_String_free(array_name);

}

void
sidl_Java_destroy_array(JNIEnv* env,
                        jobject array)
{
  jmethodID mid = (jmethodID) NULL;
  jclass cls = (jclass) NULL;
  if (array) {
    cls = (*env)->GetObjectClass(env, array); JAVA_CHECK(env);
    if (cls) {
      mid = (*env)->GetMethodID(env, cls, "destroy", "()V");
      if (mid) {
        (*env)->CallVoidMethod(env, array, mid);
      }
    }
  }
 JAVA_EXIT:
  if (cls) (*env)->DeleteLocalRef(env, cls);
  if (array) (*env)->DeleteLocalRef(env, array);
}

/*
 * Extract the IOR array type from the holder class.  The IOR array type
 * returned by this function will need to be cast to the appropriate IOR
 * type.  The name of the held class must be provided in the java_name.
 */
void* sidl_Java_J2I_array_holder(
				 JNIEnv* env,
				 jobject obj,
				 const char* java_name)
{
  jclass    cls    = (jclass) NULL;
  jmethodID mid    = (jmethodID) NULL;
  jobject   holdee = (jobject) NULL;
  void*     ptr    = NULL;

  char* signature = sidl_String_concat3("()L", java_name, ";");
  if(obj != NULL) {

    sidl_String_replace(signature, '.', '/');
    
    cls    = (*env)->GetObjectClass(env, obj);
    if(cls != NULL) {
      mid    = (*env)->GetMethodID(env, cls, "get", signature);
      holdee = (*env)->CallObjectMethod(env, obj, mid);
      if(holdee != NULL) {
	ptr    = sidl_Java_J2I_take_array(env, holdee);	
	(*env)->DeleteLocalRef(env, holdee);
	sidl_String_free(signature);
      }
      (*env)->DeleteLocalRef(env, cls);
    }
  }
  return ptr;
}

/*
 * Extract the sidl array pointer from the Java array object.  This method
 * simply "borrows" the pointer; the sidl array remains the owner of the array
 * data.  This is used for "in" arguments.
 */
void* sidl_Java_J2I_borrow_array(
				 JNIEnv* env,
				 jobject obj)
{
  void* array = NULL;
  if (obj != NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    jfieldID array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
    
    array = JLONG_TO_POINTER((*env)->GetLongField(env, obj, array_field));
    
  }
  return array;
}

/*
 * Extract the sidl array pointer from the Java array object and addRef it.
 * This is used for "inout" arguments.
 */
void* sidl_Java_J2I_take_array(
			       JNIEnv* env,
			       jobject obj)
{
  struct sidl__array* array = NULL;

  if (obj != NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    jfieldID array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    
    array = (struct sidl__array*) JLONG_TO_POINTER((*env)->GetLongField(env, obj, array_field));
    sidl__array_addRef(array); 

    (*env)->DeleteLocalRef(env, cls);

  }

  return array;
}

/*
 * Change the current Java array object to point to the specified sidl
 * IOR object. 
 */
void sidl_Java_I2J_set_array(
			     JNIEnv* env,
			     jobject obj,
			     void* value)
{
  jclass    cls = (*env)->GetObjectClass(env, obj);
  jmethodID mid = (*env)->GetMethodID(env, cls, "reset", "(JZ)V");
  (*env)->CallVoidMethod(env, obj, mid, POINTER_TO_JLONG(value), JNI_TRUE);
  (*env)->DeleteLocalRef(env, cls);
}

/*
 * Create a new array object from the sidl IOR object.  The array_name
 * argument must provide the name of the Java array type.  This version
 * takes the array reference.  
 */
jobject sidl_Java_I2J_new_array(
				JNIEnv* env,
				void* value,
				const char* array_name)
{
  char*   jni_name = NULL;
  jclass  cls      = (jclass) NULL;
  jobject obj      = (jobject) NULL;
  if(value != NULL) {
    if((strcmp(array_name, "gov/llnl/sidl/BaseArray") == 0) ||
       (strcmp(array_name, "gov.llnl.sidl.BaseArray") == 0)) {
      enum sidl_array_type array_type = (enum sidl_array_type) sidl__array_type(value);
      jni_name = sidl_String_strdup(get_array_name(array_type));
    } else {
      jni_name = sidl_String_strdup(array_name);
      sidl_String_replace(jni_name, '.', '/');
    }
    cls = (*env)->FindClass(env, jni_name);
    sidl_String_free(jni_name);
    if (cls) {
      jmethodID ctor = (*env)->GetMethodID(env, cls, "<init>", "(JZ)V");
      obj = (*env)->NewObject(env, cls, ctor, POINTER_TO_JLONG(value), JNI_TRUE);
      if ((*env)->ExceptionOccurred(env)) {
	(*env)->ExceptionDescribe(env);
	return 0;
      }
      (*env)->DeleteLocalRef(env, cls);
    } 
  }
  return obj;
}

/*
 * Create a new array object from the sidl IOR object.  The array_name
 * argument must provide the name of the Java array type.  This version
 * borrows the reference.
 */
jobject sidl_Java_I2J_new_array_server(
				       JNIEnv* env,
				       void* value,
				       const char* array_name)
{
  char*   jni_name = NULL; 
  jclass  cls      = NULL;
  jobject obj      = NULL;

  if(value != NULL) {
    if((strcmp(array_name, "gov/llnl/sidl/BaseArray") == 0) ||
       (strcmp(array_name, "gov.llnl.sidl.BaseArray") == 0)) {
      enum sidl_array_type array_type = (enum sidl_array_type) sidl__array_type(value);
      jni_name = sidl_String_strdup(get_array_name(array_type));
      
    } else { 
      jni_name = sidl_String_strdup(array_name);
      sidl_String_replace(jni_name, '.', '/');
    }
    cls = (*env)->FindClass(env, jni_name);
    sidl_String_free(jni_name);
    if (cls) {
      jmethodID ctor = (*env)->GetMethodID(env, cls, "<init>", "(JZ)V");
      obj = (*env)->NewObject(env, cls, ctor, POINTER_TO_JLONG(value), JNI_FALSE);
      if ((*env)->ExceptionOccurred(env)) {
	(*env)->ExceptionDescribe(env);
	return 0;
      }
      (*env)->DeleteLocalRef(env, cls);
    }
  }
  return obj;
}



/* 
 * Local utility function to extract the array pointer from the Java object.
 * Extract the d_array long data member and convert it to a pointer.
 */
static struct sidl__array* sidl__getptr(
					JNIEnv* env,
					jobject obj)
{
  void* ptr = NULL;
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  ptr = JLONG_TO_POINTER((*env)->GetLongField(env, obj, s_array_field));
  return (struct sidl__array*) ptr;
}

/*
 * Local utility function to set the array pointer on the Java object.
 * Convert the pointer to a long value and set the d_array data member.
 */
static void sidl__setptr(
			 JNIEnv* env,
			 jobject obj,
			 struct sidl__array* array)
{
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  (*env)->SetLongField(env, obj, s_array_field, POINTER_TO_JLONG(array));
}

/*
 * Native routine to get the dimension of the current array.  This
 * routine assumes that the array has already been initialized.  If
 * the array has not been initialized, then horrible things may happen.
 */
static jint sidl__dim(
		      JNIEnv* env,
		      jobject obj)
{
  struct sidl__array* array = sidl__getptr(env, obj);
  return (jint) sidl__array_dimen(array);
}

/*
 * Native routine to get the dimension of the current array.  This
 * routine assumes that the array has already been initialized.  If
 * the array has not been initialized, then horrible things may happen.
 */
static jint sidl__type(
		       JNIEnv* env,
		       jobject obj)
{
  struct sidl__array* array = sidl__getptr(env, obj);
  return (jint) sidl__array_type(array);
}

/*
 * Native routine to fetch the specified lower bound of the array.  The
 * specified array dimension must be between zero and the array dimension
 * minus one.  Invalid values will have unpredictable (but almost certainly
 * bad) results.
 */
static jint sidl__lower(
			JNIEnv* env,
			jobject obj,
			jint dim)
{
  struct sidl__array* array = sidl__getptr(env, obj);
  return (jint) sidl__array_lower(array, dim);
}

/*
 * Native routine to fetch the specified upper bound of the array.  The
 * specified array dimension must be between zero and the array dimension
 * minus one.  Invalid values will have unpredictable (but almost certainly
 * bad) results.
 */
static jint sidl__upper(
			JNIEnv* env,
			jobject obj,
			jint dim)
{
  struct sidl__array* array = sidl__getptr(env, obj);
  return (jint) sidl__array_upper(array, dim);
}

/*
 * Native routine to returns true if the array is Column order.  
 */
static jboolean sidl__isColumnOrder(
				    JNIEnv* env,
				    jobject obj)
{
  struct sidl__array* array = sidl__getptr(env, obj);
#if (JNI_TRUE == TRUE) && (JNI_FALSE == FALSE)
  return (jboolean) sidl__array_isColumnOrder(array);
#else
  return sidl__array_isColumnOrder(array) ? JNI_TRUE : JNI_FALSE;
#endif
}
/*
 * Native routine returns the if array is RowOrder.  
 */
static jint sidl__isRowOrder(
			     JNIEnv* env,
			     jobject obj)
{
  struct sidl__array* array = sidl__getptr(env, obj);
#if (JNI_TRUE == TRUE) && (JNI_FALSE == FALSE)
  return (jboolean) sidl__array_isRowOrder(array);
#else
  return sidl__array_isRowOrder(array) ? JNI_TRUE : JNI_FALSE;
#endif
}


/*
 * Native function copies borrowed arrays, or increments the reference count
 * of non-borrowed arrays.  Good if you want to keep a copy of a passed
 * in array.  Returns an array, new if borrowed.
 */
static jobject sidl__smartCopy(
			       JNIEnv* env,
			       jobject obj)
{
  struct sidl__array* array = sidl__getptr(env, obj);
  struct sidl__array* ret_ptr = NULL;
  jobject ret_array = NULL;
  
  if (array != NULL) {
    ret_ptr = sidl__array_smartCopy(array);
  }

  /* Assuming our pointer comes back good, create a new java array with the correct pointer,
     and owner and pass that back */
  if(ret_ptr != NULL) {  
    ret_array = sidl_Java_I2J_new_array(env,ret_ptr, "gov/llnl/sidl/BaseArray");/* FIX THIS!! */
  }
  return ret_array;
}



/*
 * Native routine to increment the current array reference count.
 */
static void sidl__addRef(
			 JNIEnv* env,
			 jobject obj)
{
  struct sidl__array* array = sidl__getptr(env, obj);
  if (array != NULL) {
    sidl__array_addRef(array);
  }
}

/*
 * Native routine to decrement the current array reference count.
 */
static void sidl__deallocate(
			     JNIEnv* env,
			     jobject obj)
{
  struct sidl__array* array = sidl__getptr(env, obj);
  if (array != NULL) {
    sidl__array_deleteRef(array);
  }
  sidl__setptr(env, obj, NULL);
}

/*
 * Native routine to destroy (deallocate) the current array data.
 */
static void sidl__destroy(
			  JNIEnv* env,
			  jobject obj)
{
  struct sidl__array* array = sidl__getptr(env, obj);
  if (array != NULL) {
    sidl__array_deleteRef(array);
  }
  sidl__setptr(env, obj, NULL);
}



/*
 * Register JNI array methods with the Java JVM.
 */
void gov_llnl_sidl_BaseArray__register(JNIEnv* env)
{
  JNINativeMethod methods[11];
  jclass cls;

  methods[0].name      = "_dim";
  methods[0].signature = "()I";
  methods[0].fnPtr     = sidl__dim;
  methods[1].name      = "_lower";
  methods[1].signature = "(I)I";
  methods[1].fnPtr     = sidl__lower;
  methods[2].name      = "_upper";
  methods[2].signature = "(I)I";
  methods[2].fnPtr     = sidl__upper;
  methods[3].name      = "_destroy";
  methods[3].signature = "()V";
  methods[3].fnPtr     = sidl__destroy;
  methods[4].name      = "_isColumnOrder";
  methods[4].signature = "()Z";
  methods[4].fnPtr     = sidl__isColumnOrder;       
  methods[5].name      = "_isRowOrder";
  methods[5].signature = "()Z";
  methods[5].fnPtr     = sidl__isRowOrder;
  methods[6].name      = "_deallocate";
  methods[6].signature = "()V";
  methods[6].fnPtr     = sidl__deallocate;
  methods[7].name      = "_smartCopy";
  methods[7].signature = "()Lgov/llnl/sidl/BaseArray;";
  methods[7].fnPtr     = sidl__smartCopy;    
  methods[8].name      = "_addRef";
  methods[8].signature = "()V";
  methods[8].fnPtr     = sidl__addRef;
  methods[9].name      = "_type";
  methods[9].signature = "()I";
  methods[9].fnPtr     = sidl__type;

  cls = (*env)->FindClass(env, "gov/llnl/sidl/BaseArray");
  if (cls) {
    (*env)->RegisterNatives(env, cls, methods, 10);
    (*env)->DeleteLocalRef(env, cls);
  }
}


/************************************************************************
 *
 * FROM THIS POINT FORWARD, THIS FILE IS AUTOGENERATED BY THE 
 * gen-java-arrays.sh SCRIPT.  PLEASE DO NOT CHANGE BY HAND,
 * JUST USE THE SCRIPT TO PRODUCE IT'S OUTPUT AND CUT AND PASTE FROM THAT
 *
 ***********************************************************************/ 


/* 
 * Local utility function to extract the array pointer from the Java object.
 * Extract the d_array long data member and convert it to a pointer.
 */
static struct sidl_bool__array *
sidl_Boolean__getptr(JNIEnv * env, jobject obj)
{
  void *ptr = NULL;
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  ptr = JLONG_TO_POINTER((*env)->GetLongField(env, obj, s_array_field));
  return (struct sidl_bool__array *) ptr;
}

/*
 * Local utility function to set the array pointer on the Java object.
 * Convert the pointer to a long value and set the d_array data member.
 */
static void
sidl_Boolean__setptr(JNIEnv * env,
                     jobject obj, struct sidl_bool__array *array)
{
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  (*env)->SetLongField(env, obj, s_array_field, POINTER_TO_JLONG(array));
}

/*
 * Native routine to fetch the specified value from the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static jboolean
sidl_Boolean__get(JNIEnv * env,
                  jobject obj,
                  jint i, jint j, jint k, jint l, jint m, jint n, jint o)
{
  struct sidl_bool__array *array = sidl_Boolean__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
#if (JNI_TRUE == TRUE) && (JNI_FALSE == FALSE)
  return (jboolean) sidl_bool__array_get(array, a);
#else
  return sidl_bool__array_get(array, a) ? JNI_TRUE : JNI_FALSE;
#endif
}

/**
 * Native routine to set the specified value in the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static void
sidl_Boolean__set(JNIEnv * env,
                  jobject obj,
                  jint i,
                  jint j,
                  jint k, jint l, jint m, jint n, jint o, jboolean value)
{
  struct sidl_bool__array *array = sidl_Boolean__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
#if (JNI_TRUE == TRUE) && (JNI_FALSE == FALSE)
  sidl_bool__array_set(array, a, (sidl_bool) value);
#else
  sidl_bool__array_set(array, a, ((value) ? TRUE : FALSE));
#endif
}

/*
 * Native routine to reallocate data in the array.  The specified array
 * dimension and indices must match and be within valid ranges (e.g., the
 * upper bounds must be greater than or equal to lowe rbounds.  Invalid
 * indices will have unpredictable (but almost certainly bad) results.
 * This routine will deallocate the existing array data if it is not null.
 * if argument "isRow" is true, the array will be in RowOrder, other wise
 * it will be in ColumnOrder   
 */
static void
sidl_Boolean__reallocate(JNIEnv * env,
                         jobject obj,
                         jint dim, jarray lower, jarray upper, jboolean isRow)
{
  jint *l = NULL;
  jint *u = NULL;
  struct sidl_bool__array *array = NULL;

  sidl__destroy(env, obj);

  l = (*env)->GetIntArrayElements(env, lower, NULL);
  u = (*env)->GetIntArrayElements(env, upper, NULL);
  if (isRow)
    array = sidl_bool__array_createRow((int32_t) dim, (int32_t *) l,
                                       (int32_t *) u);
  else
    array = sidl_bool__array_createCol((int32_t) dim, (int32_t *) l,
                                       (int32_t *) u);
  (*env)->ReleaseIntArrayElements(env, lower, l, JNI_ABORT);
  (*env)->ReleaseIntArrayElements(env, upper, u, JNI_ABORT);

  sidl_Boolean__setptr(env, obj, array);
}


/*
 * Native function copies borrowed arrays, or increments the reference count
 * of non-borrowed arrays.  Good if you want to keep a copy of a passed
 * in array.  Returns an array, new if borrowed.
 */
static void
sidl_Boolean__copy(JNIEnv * env, jobject obj, jobject dest)
{
  struct sidl_bool__array *csrc = sidl_Boolean__getptr(env, obj);
  struct sidl_bool__array *cdest = sidl_Boolean__getptr(env, dest);

  if (csrc && cdest) {
    sidl_bool__array_copy(csrc, cdest);
  }

}

/*
 * Native function slices arrays in various ways
 */
static jobject
sidl_Boolean__slice(JNIEnv * env,
                    jobject obj,
                    jint dimen,
                    jintArray numElem,
                    jintArray srcStart,
                    jintArray srcStride, jintArray newStart)
{
  struct sidl_bool__array *array = sidl_Boolean__getptr(env, obj);
  struct sidl_bool__array *ret_ptr = NULL;
  jobject ret_array = NULL;

  /* I'm cheating a bit here.  Slice expects any unused arguments to be
     null.  But I don't want to use malloc, so I'm allocating the space
     on the stack, but only pointing to it if that argument is actually
     used. */
  jint anumElem[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStart[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStride[SIDL_MAX_ARRAY_DIMENSION];
  jint anewStart[SIDL_MAX_ARRAY_DIMENSION];
  jint *cnumElem = NULL;
  jint *csrcStart = NULL;
  jint *csrcStride = NULL;
  jint *cnewStart = NULL;
  int i = 0;

  if (numElem == NULL) {
    return NULL;                /*If numElem is NULL, we need to return Null, that's bad. */
  }
  else {
    if ((*env)->GetArrayLength(env, numElem) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnumElem = anumElem;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnumElem[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, numElem, 0,
                              (*env)->GetArrayLength(env, numElem), cnumElem);

  }

  if (srcStart != NULL) {
    if ((*env)->GetArrayLength(env, srcStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStart = asrcStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStart, 0,
                              (*env)->GetArrayLength(env, srcStart),
                              csrcStart);
  }

  if (srcStride != NULL) {
    if ((*env)->GetArrayLength(env, srcStride) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStride = asrcStride;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStride[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStride, 0,
                              (*env)->GetArrayLength(env, srcStride),
                              csrcStride);
  }

  if (newStart != NULL) {
    if ((*env)->GetArrayLength(env, newStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnewStart = anewStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnewStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, newStart, 0,
                              (*env)->GetArrayLength(env, newStart),
                              cnewStart);
  }

  if (array != NULL) {
    /* jint should be equivalent to int32_t; Java int is 32 bits */
    ret_ptr =
      sidl_bool__array_slice(array, dimen, cnumElem, csrcStart, csrcStride,
                             cnewStart);
  }

  if (ret_ptr != NULL) {
    ret_array = sidl_Java_I2J_new_array(env, ret_ptr, "sidl.Boolean$Array");
  }

  return ret_array;
}


/*
 * Register JNI array methods with the Java JVM.
 */
void
sidl_Boolean__register(JNIEnv * env)
{
  JNINativeMethod methods[5];
  jclass cls;

  methods[0].name = "_get";
  methods[0].signature = "(IIIIIII)Z";
  methods[0].fnPtr = sidl_Boolean__get;
  methods[1].name = "_set";
  methods[1].signature = "(IIIIIIIZ)V";
  methods[1].fnPtr = sidl_Boolean__set;
  methods[2].name = "_copy";
  methods[2].signature = "(Lsidl/Boolean$Array;)V";
  methods[2].fnPtr = sidl_Boolean__copy;
  methods[3].name = "_slice";
  methods[3].signature = "(I[I[I[I[I)Lsidl/Boolean$Array;";
  methods[3].fnPtr = sidl_Boolean__slice;
  methods[4].name = "_reallocate";
  methods[4].signature = "(I[I[IZ)V";
  methods[4].fnPtr = sidl_Boolean__reallocate;


  cls = (*env)->FindClass(env, "sidl/Boolean$Array");
  if (cls) {
    (*env)->RegisterNatives(env, cls, methods, 5);
    (*env)->DeleteLocalRef(env, cls);
  }
}

/* 
 * Local utility function to extract the array pointer from the Java object.
 * Extract the d_array long data member and convert it to a pointer.
 */
static struct sidl_char__array *
sidl_Character__getptr(JNIEnv * env, jobject obj)
{
  void *ptr = NULL;
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  ptr = JLONG_TO_POINTER((*env)->GetLongField(env, obj, s_array_field));
  return (struct sidl_char__array *) ptr;
}

/*
 * Local utility function to set the array pointer on the Java object.
 * Convert the pointer to a long value and set the d_array data member.
 */
static void
sidl_Character__setptr(JNIEnv * env,
                       jobject obj, struct sidl_char__array *array)
{
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  (*env)->SetLongField(env, obj, s_array_field, POINTER_TO_JLONG(array));
}

/*
 * Native routine to fetch the specified value from the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static jchar
sidl_Character__get(JNIEnv * env,
                    jobject obj,
                    jint i, jint j, jint k, jint l, jint m, jint n, jint o)
{
  struct sidl_char__array *array = sidl_Character__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  return (jchar) sidl_char__array_get(array, a);
}

/**
 * Native routine to set the specified value in the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static void
sidl_Character__set(JNIEnv * env,
                    jobject obj,
                    jint i,
                    jint j,
                    jint k, jint l, jint m, jint n, jint o, jchar value)
{
  struct sidl_char__array *array = sidl_Character__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  sidl_char__array_set(array, a, (char) value);
}

/*
 * Native routine to reallocate data in the array.  The specified array
 * dimension and indices must match and be within valid ranges (e.g., the
 * upper bounds must be greater than or equal to lowe rbounds.  Invalid
 * indices will have unpredictable (but almost certainly bad) results.
 * This routine will deallocate the existing array data if it is not null.
 * if argument "isRow" is true, the array will be in RowOrder, other wise
 * it will be in ColumnOrder   
 */
static void
sidl_Character__reallocate(JNIEnv * env,
                           jobject obj,
                           jint dim,
                           jarray lower, jarray upper, jboolean isRow)
{
  jint *l = NULL;
  jint *u = NULL;
  struct sidl_char__array *array = NULL;

  sidl__destroy(env, obj);

  l = (*env)->GetIntArrayElements(env, lower, NULL);
  u = (*env)->GetIntArrayElements(env, upper, NULL);
  if (isRow)
    array = sidl_char__array_createRow((int32_t) dim, (int32_t *) l,
                                       (int32_t *) u);
  else
    array = sidl_char__array_createCol((int32_t) dim, (int32_t *) l,
                                       (int32_t *) u);
  (*env)->ReleaseIntArrayElements(env, lower, l, JNI_ABORT);
  (*env)->ReleaseIntArrayElements(env, upper, u, JNI_ABORT);

  sidl_Character__setptr(env, obj, array);
}


/*
 * Native function copies borrowed arrays, or increments the reference count
 * of non-borrowed arrays.  Good if you want to keep a copy of a passed
 * in array.  Returns an array, new if borrowed.
 */
static void
sidl_Character__copy(JNIEnv * env, jobject obj, jobject dest)
{
  struct sidl_char__array *csrc = sidl_Character__getptr(env, obj);
  struct sidl_char__array *cdest = sidl_Character__getptr(env, dest);

  if (csrc && cdest) {
    sidl_char__array_copy(csrc, cdest);
  }

}

/*
 * Native function slices arrays in various ways
 */
static jobject
sidl_Character__slice(JNIEnv * env,
                      jobject obj,
                      jint dimen,
                      jintArray numElem,
                      jintArray srcStart,
                      jintArray srcStride, jintArray newStart)
{
  struct sidl_char__array *array = sidl_Character__getptr(env, obj);
  struct sidl_char__array *ret_ptr = NULL;
  jobject ret_array = NULL;

  /* I'm cheating a bit here.  Slice expects any unused arguments to be
     null.  But I don't want to use malloc, so I'm allocating the space
     on the stack, but only pointing to it if that argument is actually
     used. */
  jint anumElem[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStart[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStride[SIDL_MAX_ARRAY_DIMENSION];
  jint anewStart[SIDL_MAX_ARRAY_DIMENSION];
  jint *cnumElem = NULL;
  jint *csrcStart = NULL;
  jint *csrcStride = NULL;
  jint *cnewStart = NULL;
  int i = 0;

  if (numElem == NULL) {
    return NULL;                /*If numElem is NULL, we need to return Null, that's bad. */
  }
  else {
    if ((*env)->GetArrayLength(env, numElem) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnumElem = anumElem;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnumElem[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, numElem, 0,
                              (*env)->GetArrayLength(env, numElem), cnumElem);

  }

  if (srcStart != NULL) {
    if ((*env)->GetArrayLength(env, srcStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStart = asrcStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStart, 0,
                              (*env)->GetArrayLength(env, srcStart),
                              csrcStart);
  }

  if (srcStride != NULL) {
    if ((*env)->GetArrayLength(env, srcStride) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStride = asrcStride;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStride[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStride, 0,
                              (*env)->GetArrayLength(env, srcStride),
                              csrcStride);
  }

  if (newStart != NULL) {
    if ((*env)->GetArrayLength(env, newStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnewStart = anewStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnewStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, newStart, 0,
                              (*env)->GetArrayLength(env, newStart),
                              cnewStart);
  }

  if (array != NULL) {
    /* jint should be equivalent to int32_t; Java int is 32 bits */
    ret_ptr =
      sidl_char__array_slice(array, dimen, cnumElem, csrcStart, csrcStride,
                             cnewStart);
  }

  if (ret_ptr != NULL) {
    ret_array = sidl_Java_I2J_new_array(env, ret_ptr, "sidl.Character$Array");
  }

  return ret_array;
}


/*
 * Register JNI array methods with the Java JVM.
 */
void
sidl_Character__register(JNIEnv * env)
{
  JNINativeMethod methods[5];
  jclass cls;

  methods[0].name = "_get";
  methods[0].signature = "(IIIIIII)C";
  methods[0].fnPtr = sidl_Character__get;
  methods[1].name = "_set";
  methods[1].signature = "(IIIIIIIC)V";
  methods[1].fnPtr = sidl_Character__set;
  methods[2].name = "_copy";
  methods[2].signature = "(Lsidl/Character$Array;)V";
  methods[2].fnPtr = sidl_Character__copy;
  methods[3].name = "_slice";
  methods[3].signature = "(I[I[I[I[I)Lsidl/Character$Array;";
  methods[3].fnPtr = sidl_Character__slice;
  methods[4].name = "_reallocate";
  methods[4].signature = "(I[I[IZ)V";
  methods[4].fnPtr = sidl_Character__reallocate;


  cls = (*env)->FindClass(env, "sidl/Character$Array");
  if (cls) {
    (*env)->RegisterNatives(env, cls, methods, 5);
    (*env)->DeleteLocalRef(env, cls);
  }
}

/* 
 * Local utility function to extract the array pointer from the Java object.
 * Extract the d_array long data member and convert it to a pointer.
 */
static struct sidl_dcomplex__array *
sidl_DoubleComplex__getptr(JNIEnv * env, jobject obj)
{
  void *ptr = NULL;
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  ptr = JLONG_TO_POINTER((*env)->GetLongField(env, obj, s_array_field));
  return (struct sidl_dcomplex__array *) ptr;
}

/*
 * Local utility function to set the array pointer on the Java object.
 * Convert the pointer to a long value and set the d_array data member.
 */
static void
sidl_DoubleComplex__setptr(JNIEnv * env,
                           jobject obj, struct sidl_dcomplex__array *array)
{
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  (*env)->SetLongField(env, obj, s_array_field, POINTER_TO_JLONG(array));
}

/*
 * Native routine to fetch the specified value from the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static jobject
sidl_DoubleComplex__get(JNIEnv * env,
                        jobject obj,
                        jint i,
                        jint j, jint k, jint l, jint m, jint n, jint o)
{
  struct sidl_dcomplex__array *array = sidl_DoubleComplex__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];
  struct sidl_dcomplex value;

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  value = sidl_dcomplex__array_get(array, a);
  return sidl_Java_I2J_dcomplex(env, &value);
}

/**
 * Native routine to set the specified value in the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static void
sidl_DoubleComplex__set(JNIEnv * env,
                        jobject obj,
                        jint i,
                        jint j,
                        jint k, jint l, jint m, jint n, jint o, jobject value)
{
  struct sidl_dcomplex__array *array = sidl_DoubleComplex__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];
  struct sidl_dcomplex elem;

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  elem = sidl_Java_J2I_dcomplex(env, value);
  sidl_dcomplex__array_set(array, a, elem);
}

/*
 * Native routine to reallocate data in the array.  The specified array
 * dimension and indices must match and be within valid ranges (e.g., the
 * upper bounds must be greater than or equal to lowe rbounds.  Invalid
 * indices will have unpredictable (but almost certainly bad) results.
 * This routine will deallocate the existing array data if it is not null.
 * if argument "isRow" is true, the array will be in RowOrder, other wise
 * it will be in ColumnOrder   
 */
static void
sidl_DoubleComplex__reallocate(JNIEnv * env,
                               jobject obj,
                               jint dim,
                               jarray lower, jarray upper, jboolean isRow)
{
  jint *l = NULL;
  jint *u = NULL;
  struct sidl_dcomplex__array *array = NULL;

  sidl__destroy(env, obj);

  l = (*env)->GetIntArrayElements(env, lower, NULL);
  u = (*env)->GetIntArrayElements(env, upper, NULL);
  if (isRow)
    array = sidl_dcomplex__array_createRow((int32_t) dim, (int32_t *) l,
                                           (int32_t *) u);
  else
    array = sidl_dcomplex__array_createCol((int32_t) dim, (int32_t *) l,
                                           (int32_t *) u);
  (*env)->ReleaseIntArrayElements(env, lower, l, JNI_ABORT);
  (*env)->ReleaseIntArrayElements(env, upper, u, JNI_ABORT);

  sidl_DoubleComplex__setptr(env, obj, array);
}


/*
 * Native function copies borrowed arrays, or increments the reference count
 * of non-borrowed arrays.  Good if you want to keep a copy of a passed
 * in array.  Returns an array, new if borrowed.
 */
static void
sidl_DoubleComplex__copy(JNIEnv * env, jobject obj, jobject dest)
{
  struct sidl_dcomplex__array *csrc = sidl_DoubleComplex__getptr(env, obj);
  struct sidl_dcomplex__array *cdest = sidl_DoubleComplex__getptr(env, dest);

  if (csrc && cdest) {
    sidl_dcomplex__array_copy(csrc, cdest);
  }

}

/*
 * Native function slices arrays in various ways
 */
static jobject
sidl_DoubleComplex__slice(JNIEnv * env,
                          jobject obj,
                          jint dimen,
                          jintArray numElem,
                          jintArray srcStart,
                          jintArray srcStride, jintArray newStart)
{
  struct sidl_dcomplex__array *array = sidl_DoubleComplex__getptr(env, obj);
  struct sidl_dcomplex__array *ret_ptr = NULL;
  jobject ret_array = NULL;

  /* I'm cheating a bit here.  Slice expects any unused arguments to be
     null.  But I don't want to use malloc, so I'm allocating the space
     on the stack, but only pointing to it if that argument is actually
     used. */
  jint anumElem[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStart[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStride[SIDL_MAX_ARRAY_DIMENSION];
  jint anewStart[SIDL_MAX_ARRAY_DIMENSION];
  jint *cnumElem = NULL;
  jint *csrcStart = NULL;
  jint *csrcStride = NULL;
  jint *cnewStart = NULL;
  int i = 0;

  if (numElem == NULL) {
    return NULL;                /*If numElem is NULL, we need to return Null, that's bad. */
  }
  else {
    if ((*env)->GetArrayLength(env, numElem) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnumElem = anumElem;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnumElem[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, numElem, 0,
                              (*env)->GetArrayLength(env, numElem), cnumElem);

  }

  if (srcStart != NULL) {
    if ((*env)->GetArrayLength(env, srcStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStart = asrcStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStart, 0,
                              (*env)->GetArrayLength(env, srcStart),
                              csrcStart);
  }

  if (srcStride != NULL) {
    if ((*env)->GetArrayLength(env, srcStride) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStride = asrcStride;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStride[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStride, 0,
                              (*env)->GetArrayLength(env, srcStride),
                              csrcStride);
  }

  if (newStart != NULL) {
    if ((*env)->GetArrayLength(env, newStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnewStart = anewStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnewStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, newStart, 0,
                              (*env)->GetArrayLength(env, newStart),
                              cnewStart);
  }

  if (array != NULL) {
    /* jint should be equivalent to int32_t; Java int is 32 bits */
    ret_ptr =
      sidl_dcomplex__array_slice(array, dimen, cnumElem, csrcStart,
                                 csrcStride, cnewStart);
  }

  if (ret_ptr != NULL) {
    ret_array =
      sidl_Java_I2J_new_array(env, ret_ptr, "sidl.DoubleComplex$Array");
  }

  return ret_array;
}


/*
 * Register JNI array methods with the Java JVM.
 */
void
sidl_DoubleComplex__register(JNIEnv * env)
{
  JNINativeMethod methods[5];
  jclass cls;

  methods[0].name = "_get";
  methods[0].signature = "(IIIIIII)Lsidl/DoubleComplex;";
  methods[0].fnPtr = sidl_DoubleComplex__get;
  methods[1].name = "_set";
  methods[1].signature = "(IIIIIIILsidl/DoubleComplex;)V";
  methods[1].fnPtr = sidl_DoubleComplex__set;
  methods[2].name = "_copy";
  methods[2].signature = "(Lsidl/DoubleComplex$Array;)V";
  methods[2].fnPtr = sidl_DoubleComplex__copy;
  methods[3].name = "_slice";
  methods[3].signature = "(I[I[I[I[I)Lsidl/DoubleComplex$Array;";
  methods[3].fnPtr = sidl_DoubleComplex__slice;
  methods[4].name = "_reallocate";
  methods[4].signature = "(I[I[IZ)V";
  methods[4].fnPtr = sidl_DoubleComplex__reallocate;


  cls = (*env)->FindClass(env, "sidl/DoubleComplex$Array");
  if (cls) {
    (*env)->RegisterNatives(env, cls, methods, 5);
    (*env)->DeleteLocalRef(env, cls);
  }
}

/* 
 * Local utility function to extract the array pointer from the Java object.
 * Extract the d_array long data member and convert it to a pointer.
 */
static struct sidl_double__array *
sidl_Double__getptr(JNIEnv * env, jobject obj)
{
  void *ptr = NULL;
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  ptr = JLONG_TO_POINTER((*env)->GetLongField(env, obj, s_array_field));
  return (struct sidl_double__array *) ptr;
}

/*
 * Local utility function to set the array pointer on the Java object.
 * Convert the pointer to a long value and set the d_array data member.
 */
static void
sidl_Double__setptr(JNIEnv * env,
                    jobject obj, struct sidl_double__array *array)
{
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  (*env)->SetLongField(env, obj, s_array_field, POINTER_TO_JLONG(array));
}

/*
 * Native routine to fetch the specified value from the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static jdouble
sidl_Double__get(JNIEnv * env,
                 jobject obj,
                 jint i, jint j, jint k, jint l, jint m, jint n, jint o)
{
  struct sidl_double__array *array = sidl_Double__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  return (jdouble) sidl_double__array_get(array, a);
}

/**
 * Native routine to set the specified value in the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static void
sidl_Double__set(JNIEnv * env,
                 jobject obj,
                 jint i,
                 jint j,
                 jint k, jint l, jint m, jint n, jint o, jdouble value)
{
  struct sidl_double__array *array = sidl_Double__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  sidl_double__array_set(array, a, (double) value);
}

/*
 * Native routine to reallocate data in the array.  The specified array
 * dimension and indices must match and be within valid ranges (e.g., the
 * upper bounds must be greater than or equal to lowe rbounds.  Invalid
 * indices will have unpredictable (but almost certainly bad) results.
 * This routine will deallocate the existing array data if it is not null.
 * if argument "isRow" is true, the array will be in RowOrder, other wise
 * it will be in ColumnOrder   
 */
static void
sidl_Double__reallocate(JNIEnv * env,
                        jobject obj,
                        jint dim, jarray lower, jarray upper, jboolean isRow)
{
  jint *l = NULL;
  jint *u = NULL;
  struct sidl_double__array *array = NULL;

  sidl__destroy(env, obj);

  l = (*env)->GetIntArrayElements(env, lower, NULL);
  u = (*env)->GetIntArrayElements(env, upper, NULL);
  if (isRow)
    array = sidl_double__array_createRow((int32_t) dim, (int32_t *) l,
                                         (int32_t *) u);
  else
    array = sidl_double__array_createCol((int32_t) dim, (int32_t *) l,
                                         (int32_t *) u);
  (*env)->ReleaseIntArrayElements(env, lower, l, JNI_ABORT);
  (*env)->ReleaseIntArrayElements(env, upper, u, JNI_ABORT);

  sidl_Double__setptr(env, obj, array);
}


/*
 * Native function copies borrowed arrays, or increments the reference count
 * of non-borrowed arrays.  Good if you want to keep a copy of a passed
 * in array.  Returns an array, new if borrowed.
 */
static void
sidl_Double__copy(JNIEnv * env, jobject obj, jobject dest)
{
  struct sidl_double__array *csrc = sidl_Double__getptr(env, obj);
  struct sidl_double__array *cdest = sidl_Double__getptr(env, dest);

  if (csrc && cdest) {
    sidl_double__array_copy(csrc, cdest);
  }

}

/*
 * Native function slices arrays in various ways
 */
static jobject
sidl_Double__slice(JNIEnv * env,
                   jobject obj,
                   jint dimen,
                   jintArray numElem,
                   jintArray srcStart,
                   jintArray srcStride, jintArray newStart)
{
  struct sidl_double__array *array = sidl_Double__getptr(env, obj);
  struct sidl_double__array *ret_ptr = NULL;
  jobject ret_array = NULL;

  /* I'm cheating a bit here.  Slice expects any unused arguments to be
     null.  But I don't want to use malloc, so I'm allocating the space
     on the stack, but only pointing to it if that argument is actually
     used. */
  jint anumElem[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStart[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStride[SIDL_MAX_ARRAY_DIMENSION];
  jint anewStart[SIDL_MAX_ARRAY_DIMENSION];
  jint *cnumElem = NULL;
  jint *csrcStart = NULL;
  jint *csrcStride = NULL;
  jint *cnewStart = NULL;
  int i = 0;

  if (numElem == NULL) {
    return NULL;                /*If numElem is NULL, we need to return Null, that's bad. */
  }
  else {
    if ((*env)->GetArrayLength(env, numElem) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnumElem = anumElem;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnumElem[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, numElem, 0,
                              (*env)->GetArrayLength(env, numElem), cnumElem);

  }

  if (srcStart != NULL) {
    if ((*env)->GetArrayLength(env, srcStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStart = asrcStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStart, 0,
                              (*env)->GetArrayLength(env, srcStart),
                              csrcStart);
  }

  if (srcStride != NULL) {
    if ((*env)->GetArrayLength(env, srcStride) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStride = asrcStride;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStride[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStride, 0,
                              (*env)->GetArrayLength(env, srcStride),
                              csrcStride);
  }

  if (newStart != NULL) {
    if ((*env)->GetArrayLength(env, newStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnewStart = anewStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnewStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, newStart, 0,
                              (*env)->GetArrayLength(env, newStart),
                              cnewStart);
  }

  if (array != NULL) {
    /* jint should be equivalent to int32_t; Java int is 32 bits */
    ret_ptr =
      sidl_double__array_slice(array, dimen, cnumElem, csrcStart, csrcStride,
                               cnewStart);
  }

  if (ret_ptr != NULL) {
    ret_array = sidl_Java_I2J_new_array(env, ret_ptr, "sidl.Double$Array");
  }

  return ret_array;
}


/*
 * Register JNI array methods with the Java JVM.
 */
void
sidl_Double__register(JNIEnv * env)
{
  JNINativeMethod methods[5];
  jclass cls;

  methods[0].name = "_get";
  methods[0].signature = "(IIIIIII)D";
  methods[0].fnPtr = sidl_Double__get;
  methods[1].name = "_set";
  methods[1].signature = "(IIIIIIID)V";
  methods[1].fnPtr = sidl_Double__set;
  methods[2].name = "_copy";
  methods[2].signature = "(Lsidl/Double$Array;)V";
  methods[2].fnPtr = sidl_Double__copy;
  methods[3].name = "_slice";
  methods[3].signature = "(I[I[I[I[I)Lsidl/Double$Array;";
  methods[3].fnPtr = sidl_Double__slice;
  methods[4].name = "_reallocate";
  methods[4].signature = "(I[I[IZ)V";
  methods[4].fnPtr = sidl_Double__reallocate;


  cls = (*env)->FindClass(env, "sidl/Double$Array");
  if (cls) {
    (*env)->RegisterNatives(env, cls, methods, 5);
    (*env)->DeleteLocalRef(env, cls);
  }
}

/* 
 * Local utility function to extract the array pointer from the Java object.
 * Extract the d_array long data member and convert it to a pointer.
 */
static struct sidl_fcomplex__array *
sidl_FloatComplex__getptr(JNIEnv * env, jobject obj)
{
  void *ptr = NULL;
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  ptr = JLONG_TO_POINTER((*env)->GetLongField(env, obj, s_array_field));
  return (struct sidl_fcomplex__array *) ptr;
}

/*
 * Local utility function to set the array pointer on the Java object.
 * Convert the pointer to a long value and set the d_array data member.
 */
static void
sidl_FloatComplex__setptr(JNIEnv * env,
                          jobject obj, struct sidl_fcomplex__array *array)
{
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  (*env)->SetLongField(env, obj, s_array_field, POINTER_TO_JLONG(array));
}

/*
 * Native routine to fetch the specified value from the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static jobject
sidl_FloatComplex__get(JNIEnv * env,
                       jobject obj,
                       jint i, jint j, jint k, jint l, jint m, jint n, jint o)
{
  struct sidl_fcomplex__array *array = sidl_FloatComplex__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];
  struct sidl_fcomplex value;

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  value = sidl_fcomplex__array_get(array, a);
  return sidl_Java_I2J_fcomplex(env, &value);
}

/**
 * Native routine to set the specified value in the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static void
sidl_FloatComplex__set(JNIEnv * env,
                       jobject obj,
                       jint i,
                       jint j,
                       jint k, jint l, jint m, jint n, jint o, jobject value)
{
  struct sidl_fcomplex__array *array = sidl_FloatComplex__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];
  struct sidl_fcomplex elem;

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  elem = sidl_Java_J2I_fcomplex(env, value);
  sidl_fcomplex__array_set(array, a, elem);
}

/*
 * Native routine to reallocate data in the array.  The specified array
 * dimension and indices must match and be within valid ranges (e.g., the
 * upper bounds must be greater than or equal to lowe rbounds.  Invalid
 * indices will have unpredictable (but almost certainly bad) results.
 * This routine will deallocate the existing array data if it is not null.
 * if argument "isRow" is true, the array will be in RowOrder, other wise
 * it will be in ColumnOrder   
 */
static void
sidl_FloatComplex__reallocate(JNIEnv * env,
                              jobject obj,
                              jint dim,
                              jarray lower, jarray upper, jboolean isRow)
{
  jint *l = NULL;
  jint *u = NULL;
  struct sidl_fcomplex__array *array = NULL;

  sidl__destroy(env, obj);

  l = (*env)->GetIntArrayElements(env, lower, NULL);
  u = (*env)->GetIntArrayElements(env, upper, NULL);
  if (isRow)
    array = sidl_fcomplex__array_createRow((int32_t) dim, (int32_t *) l,
                                           (int32_t *) u);
  else
    array = sidl_fcomplex__array_createCol((int32_t) dim, (int32_t *) l,
                                           (int32_t *) u);
  (*env)->ReleaseIntArrayElements(env, lower, l, JNI_ABORT);
  (*env)->ReleaseIntArrayElements(env, upper, u, JNI_ABORT);

  sidl_FloatComplex__setptr(env, obj, array);
}


/*
 * Native function copies borrowed arrays, or increments the reference count
 * of non-borrowed arrays.  Good if you want to keep a copy of a passed
 * in array.  Returns an array, new if borrowed.
 */
static void
sidl_FloatComplex__copy(JNIEnv * env, jobject obj, jobject dest)
{
  struct sidl_fcomplex__array *csrc = sidl_FloatComplex__getptr(env, obj);
  struct sidl_fcomplex__array *cdest = sidl_FloatComplex__getptr(env, dest);

  if (csrc && cdest) {
    sidl_fcomplex__array_copy(csrc, cdest);
  }

}

/*
 * Native function slices arrays in various ways
 */
static jobject
sidl_FloatComplex__slice(JNIEnv * env,
                         jobject obj,
                         jint dimen,
                         jintArray numElem,
                         jintArray srcStart,
                         jintArray srcStride, jintArray newStart)
{
  struct sidl_fcomplex__array *array = sidl_FloatComplex__getptr(env, obj);
  struct sidl_fcomplex__array *ret_ptr = NULL;
  jobject ret_array = NULL;

  /* I'm cheating a bit here.  Slice expects any unused arguments to be
     null.  But I don't want to use malloc, so I'm allocating the space
     on the stack, but only pointing to it if that argument is actually
     used. */
  jint anumElem[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStart[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStride[SIDL_MAX_ARRAY_DIMENSION];
  jint anewStart[SIDL_MAX_ARRAY_DIMENSION];
  jint *cnumElem = NULL;
  jint *csrcStart = NULL;
  jint *csrcStride = NULL;
  jint *cnewStart = NULL;
  int i = 0;

  if (numElem == NULL) {
    return NULL;                /*If numElem is NULL, we need to return Null, that's bad. */
  }
  else {
    if ((*env)->GetArrayLength(env, numElem) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnumElem = anumElem;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnumElem[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, numElem, 0,
                              (*env)->GetArrayLength(env, numElem), cnumElem);

  }

  if (srcStart != NULL) {
    if ((*env)->GetArrayLength(env, srcStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStart = asrcStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStart, 0,
                              (*env)->GetArrayLength(env, srcStart),
                              csrcStart);
  }

  if (srcStride != NULL) {
    if ((*env)->GetArrayLength(env, srcStride) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStride = asrcStride;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStride[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStride, 0,
                              (*env)->GetArrayLength(env, srcStride),
                              csrcStride);
  }

  if (newStart != NULL) {
    if ((*env)->GetArrayLength(env, newStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnewStart = anewStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnewStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, newStart, 0,
                              (*env)->GetArrayLength(env, newStart),
                              cnewStart);
  }

  if (array != NULL) {
    /* jint should be equivalent to int32_t; Java int is 32 bits */
    ret_ptr =
      sidl_fcomplex__array_slice(array, dimen, cnumElem, csrcStart,
                                 csrcStride, cnewStart);
  }

  if (ret_ptr != NULL) {
    ret_array =
      sidl_Java_I2J_new_array(env, ret_ptr, "sidl.FloatComplex$Array");
  }

  return ret_array;
}


/*
 * Register JNI array methods with the Java JVM.
 */
void
sidl_FloatComplex__register(JNIEnv * env)
{
  JNINativeMethod methods[5];
  jclass cls;

  methods[0].name = "_get";
  methods[0].signature = "(IIIIIII)Lsidl/FloatComplex;";
  methods[0].fnPtr = sidl_FloatComplex__get;
  methods[1].name = "_set";
  methods[1].signature = "(IIIIIIILsidl/FloatComplex;)V";
  methods[1].fnPtr = sidl_FloatComplex__set;
  methods[2].name = "_copy";
  methods[2].signature = "(Lsidl/FloatComplex$Array;)V";
  methods[2].fnPtr = sidl_FloatComplex__copy;
  methods[3].name = "_slice";
  methods[3].signature = "(I[I[I[I[I)Lsidl/FloatComplex$Array;";
  methods[3].fnPtr = sidl_FloatComplex__slice;
  methods[4].name = "_reallocate";
  methods[4].signature = "(I[I[IZ)V";
  methods[4].fnPtr = sidl_FloatComplex__reallocate;


  cls = (*env)->FindClass(env, "sidl/FloatComplex$Array");
  if (cls) {
    (*env)->RegisterNatives(env, cls, methods, 5);
    (*env)->DeleteLocalRef(env, cls);
  }
}

/* 
 * Local utility function to extract the array pointer from the Java object.
 * Extract the d_array long data member and convert it to a pointer.
 */
static struct sidl_float__array *
sidl_Float__getptr(JNIEnv * env, jobject obj)
{
  void *ptr = NULL;
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  ptr = JLONG_TO_POINTER((*env)->GetLongField(env, obj, s_array_field));
  return (struct sidl_float__array *) ptr;
}

/*
 * Local utility function to set the array pointer on the Java object.
 * Convert the pointer to a long value and set the d_array data member.
 */
static void
sidl_Float__setptr(JNIEnv * env, jobject obj, struct sidl_float__array *array)
{
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  (*env)->SetLongField(env, obj, s_array_field, POINTER_TO_JLONG(array));
}

/*
 * Native routine to fetch the specified value from the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static jfloat
sidl_Float__get(JNIEnv * env,
                jobject obj,
                jint i, jint j, jint k, jint l, jint m, jint n, jint o)
{
  struct sidl_float__array *array = sidl_Float__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  return (jfloat) sidl_float__array_get(array, a);
}

/**
 * Native routine to set the specified value in the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static void
sidl_Float__set(JNIEnv * env,
                jobject obj,
                jint i,
                jint j, jint k, jint l, jint m, jint n, jint o, jfloat value)
{
  struct sidl_float__array *array = sidl_Float__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  sidl_float__array_set(array, a, (float) value);
}

/*
 * Native routine to reallocate data in the array.  The specified array
 * dimension and indices must match and be within valid ranges (e.g., the
 * upper bounds must be greater than or equal to lowe rbounds.  Invalid
 * indices will have unpredictable (but almost certainly bad) results.
 * This routine will deallocate the existing array data if it is not null.
 * if argument "isRow" is true, the array will be in RowOrder, other wise
 * it will be in ColumnOrder   
 */
static void
sidl_Float__reallocate(JNIEnv * env,
                       jobject obj,
                       jint dim, jarray lower, jarray upper, jboolean isRow)
{
  jint *l = NULL;
  jint *u = NULL;
  struct sidl_float__array *array = NULL;

  sidl__destroy(env, obj);

  l = (*env)->GetIntArrayElements(env, lower, NULL);
  u = (*env)->GetIntArrayElements(env, upper, NULL);
  if (isRow)
    array = sidl_float__array_createRow((int32_t) dim, (int32_t *) l,
                                        (int32_t *) u);
  else
    array = sidl_float__array_createCol((int32_t) dim, (int32_t *) l,
                                        (int32_t *) u);
  (*env)->ReleaseIntArrayElements(env, lower, l, JNI_ABORT);
  (*env)->ReleaseIntArrayElements(env, upper, u, JNI_ABORT);

  sidl_Float__setptr(env, obj, array);
}


/*
 * Native function copies borrowed arrays, or increments the reference count
 * of non-borrowed arrays.  Good if you want to keep a copy of a passed
 * in array.  Returns an array, new if borrowed.
 */
static void
sidl_Float__copy(JNIEnv * env, jobject obj, jobject dest)
{
  struct sidl_float__array *csrc = sidl_Float__getptr(env, obj);
  struct sidl_float__array *cdest = sidl_Float__getptr(env, dest);

  if (csrc && cdest) {
    sidl_float__array_copy(csrc, cdest);
  }

}

/*
 * Native function slices arrays in various ways
 */
static jobject
sidl_Float__slice(JNIEnv * env,
                  jobject obj,
                  jint dimen,
                  jintArray numElem,
                  jintArray srcStart, jintArray srcStride, jintArray newStart)
{
  struct sidl_float__array *array = sidl_Float__getptr(env, obj);
  struct sidl_float__array *ret_ptr = NULL;
  jobject ret_array = NULL;

  /* I'm cheating a bit here.  Slice expects any unused arguments to be
     null.  But I don't want to use malloc, so I'm allocating the space
     on the stack, but only pointing to it if that argument is actually
     used. */
  jint anumElem[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStart[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStride[SIDL_MAX_ARRAY_DIMENSION];
  jint anewStart[SIDL_MAX_ARRAY_DIMENSION];
  jint *cnumElem = NULL;
  jint *csrcStart = NULL;
  jint *csrcStride = NULL;
  jint *cnewStart = NULL;
  int i = 0;

  if (numElem == NULL) {
    return NULL;                /*If numElem is NULL, we need to return Null, that's bad. */
  }
  else {
    if ((*env)->GetArrayLength(env, numElem) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnumElem = anumElem;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnumElem[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, numElem, 0,
                              (*env)->GetArrayLength(env, numElem), cnumElem);

  }

  if (srcStart != NULL) {
    if ((*env)->GetArrayLength(env, srcStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStart = asrcStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStart, 0,
                              (*env)->GetArrayLength(env, srcStart),
                              csrcStart);
  }

  if (srcStride != NULL) {
    if ((*env)->GetArrayLength(env, srcStride) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStride = asrcStride;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStride[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStride, 0,
                              (*env)->GetArrayLength(env, srcStride),
                              csrcStride);
  }

  if (newStart != NULL) {
    if ((*env)->GetArrayLength(env, newStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnewStart = anewStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnewStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, newStart, 0,
                              (*env)->GetArrayLength(env, newStart),
                              cnewStart);
  }

  if (array != NULL) {
    /* jint should be equivalent to int32_t; Java int is 32 bits */
    ret_ptr =
      sidl_float__array_slice(array, dimen, cnumElem, csrcStart, csrcStride,
                              cnewStart);
  }

  if (ret_ptr != NULL) {
    ret_array = sidl_Java_I2J_new_array(env, ret_ptr, "sidl.Float$Array");
  }

  return ret_array;
}


/*
 * Register JNI array methods with the Java JVM.
 */
void
sidl_Float__register(JNIEnv * env)
{
  JNINativeMethod methods[5];
  jclass cls;

  methods[0].name = "_get";
  methods[0].signature = "(IIIIIII)F";
  methods[0].fnPtr = sidl_Float__get;
  methods[1].name = "_set";
  methods[1].signature = "(IIIIIIIF)V";
  methods[1].fnPtr = sidl_Float__set;
  methods[2].name = "_copy";
  methods[2].signature = "(Lsidl/Float$Array;)V";
  methods[2].fnPtr = sidl_Float__copy;
  methods[3].name = "_slice";
  methods[3].signature = "(I[I[I[I[I)Lsidl/Float$Array;";
  methods[3].fnPtr = sidl_Float__slice;
  methods[4].name = "_reallocate";
  methods[4].signature = "(I[I[IZ)V";
  methods[4].fnPtr = sidl_Float__reallocate;


  cls = (*env)->FindClass(env, "sidl/Float$Array");
  if (cls) {
    (*env)->RegisterNatives(env, cls, methods, 5);
    (*env)->DeleteLocalRef(env, cls);
  }
}

/* 
 * Local utility function to extract the array pointer from the Java object.
 * Extract the d_array long data member and convert it to a pointer.
 */
static struct sidl_int__array *
sidl_Integer__getptr(JNIEnv * env, jobject obj)
{
  void *ptr = NULL;
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  ptr = JLONG_TO_POINTER((*env)->GetLongField(env, obj, s_array_field));
  return (struct sidl_int__array *) ptr;
}

/*
 * Local utility function to set the array pointer on the Java object.
 * Convert the pointer to a long value and set the d_array data member.
 */
static void
sidl_Integer__setptr(JNIEnv * env, jobject obj, struct sidl_int__array *array)
{
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  (*env)->SetLongField(env, obj, s_array_field, POINTER_TO_JLONG(array));
}

/*
 * Native routine to fetch the specified value from the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static jint
sidl_Integer__get(JNIEnv * env,
                  jobject obj,
                  jint i, jint j, jint k, jint l, jint m, jint n, jint o)
{
  struct sidl_int__array *array = sidl_Integer__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  return (jint) sidl_int__array_get(array, a);
}

/**
 * Native routine to set the specified value in the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static void
sidl_Integer__set(JNIEnv * env,
                  jobject obj,
                  jint i,
                  jint j, jint k, jint l, jint m, jint n, jint o, jint value)
{
  struct sidl_int__array *array = sidl_Integer__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  sidl_int__array_set(array, a, (int32_t) value);
}

/*
 * Native routine to reallocate data in the array.  The specified array
 * dimension and indices must match and be within valid ranges (e.g., the
 * upper bounds must be greater than or equal to lowe rbounds.  Invalid
 * indices will have unpredictable (but almost certainly bad) results.
 * This routine will deallocate the existing array data if it is not null.
 * if argument "isRow" is true, the array will be in RowOrder, other wise
 * it will be in ColumnOrder   
 */
static void
sidl_Integer__reallocate(JNIEnv * env,
                         jobject obj,
                         jint dim, jarray lower, jarray upper, jboolean isRow)
{
  jint *l = NULL;
  jint *u = NULL;
  struct sidl_int__array *array = NULL;

  sidl__destroy(env, obj);

  l = (*env)->GetIntArrayElements(env, lower, NULL);
  u = (*env)->GetIntArrayElements(env, upper, NULL);
  if (isRow)
    array = sidl_int__array_createRow((int32_t) dim, (int32_t *) l,
                                      (int32_t *) u);
  else
    array = sidl_int__array_createCol((int32_t) dim, (int32_t *) l,
                                      (int32_t *) u);
  (*env)->ReleaseIntArrayElements(env, lower, l, JNI_ABORT);
  (*env)->ReleaseIntArrayElements(env, upper, u, JNI_ABORT);

  sidl_Integer__setptr(env, obj, array);
}


/*
 * Native function copies borrowed arrays, or increments the reference count
 * of non-borrowed arrays.  Good if you want to keep a copy of a passed
 * in array.  Returns an array, new if borrowed.
 */
static void
sidl_Integer__copy(JNIEnv * env, jobject obj, jobject dest)
{
  struct sidl_int__array *csrc = sidl_Integer__getptr(env, obj);
  struct sidl_int__array *cdest = sidl_Integer__getptr(env, dest);

  if (csrc && cdest) {
    sidl_int__array_copy(csrc, cdest);
  }

}

/*
 * Native function slices arrays in various ways
 */
static jobject
sidl_Integer__slice(JNIEnv * env,
                    jobject obj,
                    jint dimen,
                    jintArray numElem,
                    jintArray srcStart,
                    jintArray srcStride, jintArray newStart)
{
  struct sidl_int__array *array = sidl_Integer__getptr(env, obj);
  struct sidl_int__array *ret_ptr = NULL;
  jobject ret_array = NULL;

  /* I'm cheating a bit here.  Slice expects any unused arguments to be
     null.  But I don't want to use malloc, so I'm allocating the space
     on the stack, but only pointing to it if that argument is actually
     used. */
  jint anumElem[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStart[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStride[SIDL_MAX_ARRAY_DIMENSION];
  jint anewStart[SIDL_MAX_ARRAY_DIMENSION];
  jint *cnumElem = NULL;
  jint *csrcStart = NULL;
  jint *csrcStride = NULL;
  jint *cnewStart = NULL;
  int i = 0;

  if (numElem == NULL) {
    return NULL;                /*If numElem is NULL, we need to return Null, that's bad. */
  }
  else {
    if ((*env)->GetArrayLength(env, numElem) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnumElem = anumElem;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnumElem[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, numElem, 0,
                              (*env)->GetArrayLength(env, numElem), cnumElem);

  }

  if (srcStart != NULL) {
    if ((*env)->GetArrayLength(env, srcStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStart = asrcStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStart, 0,
                              (*env)->GetArrayLength(env, srcStart),
                              csrcStart);
  }

  if (srcStride != NULL) {
    if ((*env)->GetArrayLength(env, srcStride) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStride = asrcStride;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStride[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStride, 0,
                              (*env)->GetArrayLength(env, srcStride),
                              csrcStride);
  }

  if (newStart != NULL) {
    if ((*env)->GetArrayLength(env, newStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnewStart = anewStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnewStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, newStart, 0,
                              (*env)->GetArrayLength(env, newStart),
                              cnewStart);
  }

  if (array != NULL) {
    /* jint should be equivalent to int32_t; Java int is 32 bits */
    ret_ptr =
      sidl_int__array_slice(array, dimen, cnumElem, csrcStart, csrcStride,
                            cnewStart);
  }

  if (ret_ptr != NULL) {
    ret_array = sidl_Java_I2J_new_array(env, ret_ptr, "sidl.Integer$Array");
  }

  return ret_array;
}


/*
 * Register JNI array methods with the Java JVM.
 */
void
sidl_Integer__register(JNIEnv * env)
{
  JNINativeMethod methods[5];
  jclass cls;

  methods[0].name = "_get";
  methods[0].signature = "(IIIIIII)I";
  methods[0].fnPtr = sidl_Integer__get;
  methods[1].name = "_set";
  methods[1].signature = "(IIIIIIII)V";
  methods[1].fnPtr = sidl_Integer__set;
  methods[2].name = "_copy";
  methods[2].signature = "(Lsidl/Integer$Array;)V";
  methods[2].fnPtr = sidl_Integer__copy;
  methods[3].name = "_slice";
  methods[3].signature = "(I[I[I[I[I)Lsidl/Integer$Array;";
  methods[3].fnPtr = sidl_Integer__slice;
  methods[4].name = "_reallocate";
  methods[4].signature = "(I[I[IZ)V";
  methods[4].fnPtr = sidl_Integer__reallocate;


  cls = (*env)->FindClass(env, "sidl/Integer$Array");
  if (cls) {
    (*env)->RegisterNatives(env, cls, methods, 5);
    (*env)->DeleteLocalRef(env, cls);
  }
}

/* 
 * Local utility function to extract the array pointer from the Java object.
 * Extract the d_array long data member and convert it to a pointer.
 */
static struct sidl_long__array *
sidl_Long__getptr(JNIEnv * env, jobject obj)
{
  void *ptr = NULL;
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  ptr = JLONG_TO_POINTER((*env)->GetLongField(env, obj, s_array_field));
  return (struct sidl_long__array *) ptr;
}

/*
 * Local utility function to set the array pointer on the Java object.
 * Convert the pointer to a long value and set the d_array data member.
 */
static void
sidl_Long__setptr(JNIEnv * env, jobject obj, struct sidl_long__array *array)
{
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  (*env)->SetLongField(env, obj, s_array_field, POINTER_TO_JLONG(array));
}

/*
 * Native routine to fetch the specified value from the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static jlong
sidl_Long__get(JNIEnv * env,
               jobject obj,
               jint i, jint j, jint k, jint l, jint m, jint n, jint o)
{
  struct sidl_long__array *array = sidl_Long__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  return (jlong) sidl_long__array_get(array, a);
}

/**
 * Native routine to set the specified value in the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static void
sidl_Long__set(JNIEnv * env,
               jobject obj,
               jint i,
               jint j, jint k, jint l, jint m, jint n, jint o, jlong value)
{
  struct sidl_long__array *array = sidl_Long__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  sidl_long__array_set(array, a, (int64_t) value);
}

/*
 * Native routine to reallocate data in the array.  The specified array
 * dimension and indices must match and be within valid ranges (e.g., the
 * upper bounds must be greater than or equal to lowe rbounds.  Invalid
 * indices will have unpredictable (but almost certainly bad) results.
 * This routine will deallocate the existing array data if it is not null.
 * if argument "isRow" is true, the array will be in RowOrder, other wise
 * it will be in ColumnOrder   
 */
static void
sidl_Long__reallocate(JNIEnv * env,
                      jobject obj,
                      jint dim, jarray lower, jarray upper, jboolean isRow)
{
  jint *l = NULL;
  jint *u = NULL;
  struct sidl_long__array *array = NULL;

  sidl__destroy(env, obj);

  l = (*env)->GetIntArrayElements(env, lower, NULL);
  u = (*env)->GetIntArrayElements(env, upper, NULL);
  if (isRow)
    array = sidl_long__array_createRow((int32_t) dim, (int32_t *) l,
                                       (int32_t *) u);
  else
    array = sidl_long__array_createCol((int32_t) dim, (int32_t *) l,
                                       (int32_t *) u);
  (*env)->ReleaseIntArrayElements(env, lower, l, JNI_ABORT);
  (*env)->ReleaseIntArrayElements(env, upper, u, JNI_ABORT);

  sidl_Long__setptr(env, obj, array);
}


/*
 * Native function copies borrowed arrays, or increments the reference count
 * of non-borrowed arrays.  Good if you want to keep a copy of a passed
 * in array.  Returns an array, new if borrowed.
 */
static void
sidl_Long__copy(JNIEnv * env, jobject obj, jobject dest)
{
  struct sidl_long__array *csrc = sidl_Long__getptr(env, obj);
  struct sidl_long__array *cdest = sidl_Long__getptr(env, dest);

  if (csrc && cdest) {
    sidl_long__array_copy(csrc, cdest);
  }

}

/*
 * Native function slices arrays in various ways
 */
static jobject
sidl_Long__slice(JNIEnv * env,
                 jobject obj,
                 jint dimen,
                 jintArray numElem,
                 jintArray srcStart, jintArray srcStride, jintArray newStart)
{
  struct sidl_long__array *array = sidl_Long__getptr(env, obj);
  struct sidl_long__array *ret_ptr = NULL;
  jobject ret_array = NULL;

  /* I'm cheating a bit here.  Slice expects any unused arguments to be
     null.  But I don't want to use malloc, so I'm allocating the space
     on the stack, but only pointing to it if that argument is actually
     used. */
  jint anumElem[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStart[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStride[SIDL_MAX_ARRAY_DIMENSION];
  jint anewStart[SIDL_MAX_ARRAY_DIMENSION];
  jint *cnumElem = NULL;
  jint *csrcStart = NULL;
  jint *csrcStride = NULL;
  jint *cnewStart = NULL;
  int i = 0;

  if (numElem == NULL) {
    return NULL;                /*If numElem is NULL, we need to return Null, that's bad. */
  }
  else {
    if ((*env)->GetArrayLength(env, numElem) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnumElem = anumElem;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnumElem[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, numElem, 0,
                              (*env)->GetArrayLength(env, numElem), cnumElem);

  }

  if (srcStart != NULL) {
    if ((*env)->GetArrayLength(env, srcStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStart = asrcStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStart, 0,
                              (*env)->GetArrayLength(env, srcStart),
                              csrcStart);
  }

  if (srcStride != NULL) {
    if ((*env)->GetArrayLength(env, srcStride) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStride = asrcStride;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStride[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStride, 0,
                              (*env)->GetArrayLength(env, srcStride),
                              csrcStride);
  }

  if (newStart != NULL) {
    if ((*env)->GetArrayLength(env, newStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnewStart = anewStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnewStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, newStart, 0,
                              (*env)->GetArrayLength(env, newStart),
                              cnewStart);
  }

  if (array != NULL) {
    /* jint should be equivalent to int32_t; Java int is 32 bits */
    ret_ptr =
      sidl_long__array_slice(array, dimen, cnumElem, csrcStart, csrcStride,
                             cnewStart);
  }

  if (ret_ptr != NULL) {
    ret_array = sidl_Java_I2J_new_array(env, ret_ptr, "sidl.Long$Array");
  }

  return ret_array;
}


/*
 * Register JNI array methods with the Java JVM.
 */
void
sidl_Long__register(JNIEnv * env)
{
  JNINativeMethod methods[5];
  jclass cls;

  methods[0].name = "_get";
  methods[0].signature = "(IIIIIII)J";
  methods[0].fnPtr = sidl_Long__get;
  methods[1].name = "_set";
  methods[1].signature = "(IIIIIIIJ)V";
  methods[1].fnPtr = sidl_Long__set;
  methods[2].name = "_copy";
  methods[2].signature = "(Lsidl/Long$Array;)V";
  methods[2].fnPtr = sidl_Long__copy;
  methods[3].name = "_slice";
  methods[3].signature = "(I[I[I[I[I)Lsidl/Long$Array;";
  methods[3].fnPtr = sidl_Long__slice;
  methods[4].name = "_reallocate";
  methods[4].signature = "(I[I[IZ)V";
  methods[4].fnPtr = sidl_Long__reallocate;


  cls = (*env)->FindClass(env, "sidl/Long$Array");
  if (cls) {
    (*env)->RegisterNatives(env, cls, methods, 5);
    (*env)->DeleteLocalRef(env, cls);
  }
}

/* 
 * Local utility function to extract the array pointer from the Java object.
 * Extract the d_array long data member and convert it to a pointer.
 */
static struct sidl_opaque__array *
sidl_Opaque__getptr(JNIEnv * env, jobject obj)
{
  void *ptr = NULL;
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  ptr = JLONG_TO_POINTER((*env)->GetLongField(env, obj, s_array_field));
  return (struct sidl_opaque__array *) ptr;
}

/*
 * Local utility function to set the array pointer on the Java object.
 * Convert the pointer to a long value and set the d_array data member.
 */
static void
sidl_Opaque__setptr(JNIEnv * env,
                    jobject obj, struct sidl_opaque__array *array)
{
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  (*env)->SetLongField(env, obj, s_array_field, POINTER_TO_JLONG(array));
}

/*
 * Native routine to fetch the specified value from the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static jlong
sidl_Opaque__get(JNIEnv * env,
                 jobject obj,
                 jint i, jint j, jint k, jint l, jint m, jint n, jint o)
{
  struct sidl_opaque__array *array = sidl_Opaque__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  return POINTER_TO_JLONG(sidl_opaque__array_get(array, a));
}

/**
 * Native routine to set the specified value in the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static void
sidl_Opaque__set(JNIEnv * env,
                 jobject obj,
                 jint i,
                 jint j, jint k, jint l, jint m, jint n, jint o, jlong value)
{
  struct sidl_opaque__array *array = sidl_Opaque__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  sidl_opaque__array_set(array, a, JLONG_TO_POINTER(value));
}

/*
 * Native routine to reallocate data in the array.  The specified array
 * dimension and indices must match and be within valid ranges (e.g., the
 * upper bounds must be greater than or equal to lowe rbounds.  Invalid
 * indices will have unpredictable (but almost certainly bad) results.
 * This routine will deallocate the existing array data if it is not null.
 * if argument "isRow" is true, the array will be in RowOrder, other wise
 * it will be in ColumnOrder   
 */
static void
sidl_Opaque__reallocate(JNIEnv * env,
                        jobject obj,
                        jint dim, jarray lower, jarray upper, jboolean isRow)
{
  jint *l = NULL;
  jint *u = NULL;
  struct sidl_opaque__array *array = NULL;

  sidl__destroy(env, obj);

  l = (*env)->GetIntArrayElements(env, lower, NULL);
  u = (*env)->GetIntArrayElements(env, upper, NULL);
  if (isRow)
    array = sidl_opaque__array_createRow((int32_t) dim, (int32_t *) l,
                                         (int32_t *) u);
  else
    array = sidl_opaque__array_createCol((int32_t) dim, (int32_t *) l,
                                         (int32_t *) u);
  (*env)->ReleaseIntArrayElements(env, lower, l, JNI_ABORT);
  (*env)->ReleaseIntArrayElements(env, upper, u, JNI_ABORT);

  sidl_Opaque__setptr(env, obj, array);
}


/*
 * Native function copies borrowed arrays, or increments the reference count
 * of non-borrowed arrays.  Good if you want to keep a copy of a passed
 * in array.  Returns an array, new if borrowed.
 */
static void
sidl_Opaque__copy(JNIEnv * env, jobject obj, jobject dest)
{
  struct sidl_opaque__array *csrc = sidl_Opaque__getptr(env, obj);
  struct sidl_opaque__array *cdest = sidl_Opaque__getptr(env, dest);

  if (csrc && cdest) {
    sidl_opaque__array_copy(csrc, cdest);
  }

}

/*
 * Native function slices arrays in various ways
 */
static jobject
sidl_Opaque__slice(JNIEnv * env,
                   jobject obj,
                   jint dimen,
                   jintArray numElem,
                   jintArray srcStart,
                   jintArray srcStride, jintArray newStart)
{
  struct sidl_opaque__array *array = sidl_Opaque__getptr(env, obj);
  struct sidl_opaque__array *ret_ptr = NULL;
  jobject ret_array = NULL;

  /* I'm cheating a bit here.  Slice expects any unused arguments to be
     null.  But I don't want to use malloc, so I'm allocating the space
     on the stack, but only pointing to it if that argument is actually
     used. */
  jint anumElem[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStart[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStride[SIDL_MAX_ARRAY_DIMENSION];
  jint anewStart[SIDL_MAX_ARRAY_DIMENSION];
  jint *cnumElem = NULL;
  jint *csrcStart = NULL;
  jint *csrcStride = NULL;
  jint *cnewStart = NULL;
  int i = 0;

  if (numElem == NULL) {
    return NULL;                /*If numElem is NULL, we need to return Null, that's bad. */
  }
  else {
    if ((*env)->GetArrayLength(env, numElem) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnumElem = anumElem;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnumElem[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, numElem, 0,
                              (*env)->GetArrayLength(env, numElem), cnumElem);

  }

  if (srcStart != NULL) {
    if ((*env)->GetArrayLength(env, srcStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStart = asrcStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStart, 0,
                              (*env)->GetArrayLength(env, srcStart),
                              csrcStart);
  }

  if (srcStride != NULL) {
    if ((*env)->GetArrayLength(env, srcStride) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStride = asrcStride;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStride[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStride, 0,
                              (*env)->GetArrayLength(env, srcStride),
                              csrcStride);
  }

  if (newStart != NULL) {
    if ((*env)->GetArrayLength(env, newStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnewStart = anewStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnewStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, newStart, 0,
                              (*env)->GetArrayLength(env, newStart),
                              cnewStart);
  }

  if (array != NULL) {
    /* jint should be equivalent to int32_t; Java int is 32 bits */
    ret_ptr =
      sidl_opaque__array_slice(array, dimen, cnumElem, csrcStart, csrcStride,
                               cnewStart);
  }

  if (ret_ptr != NULL) {
    ret_array = sidl_Java_I2J_new_array(env, ret_ptr, "sidl.Opaque$Array");
  }

  return ret_array;
}


/*
 * Register JNI array methods with the Java JVM.
 */
void
sidl_Opaque__register(JNIEnv * env)
{
  JNINativeMethod methods[5];
  jclass cls;

  methods[0].name = "_get";
  methods[0].signature = "(IIIIIII)J";
  methods[0].fnPtr = sidl_Opaque__get;
  methods[1].name = "_set";
  methods[1].signature = "(IIIIIIIJ)V";
  methods[1].fnPtr = sidl_Opaque__set;
  methods[2].name = "_copy";
  methods[2].signature = "(Lsidl/Opaque$Array;)V";
  methods[2].fnPtr = sidl_Opaque__copy;
  methods[3].name = "_slice";
  methods[3].signature = "(I[I[I[I[I)Lsidl/Opaque$Array;";
  methods[3].fnPtr = sidl_Opaque__slice;
  methods[4].name = "_reallocate";
  methods[4].signature = "(I[I[IZ)V";
  methods[4].fnPtr = sidl_Opaque__reallocate;


  cls = (*env)->FindClass(env, "sidl/Opaque$Array");
  if (cls) {
    (*env)->RegisterNatives(env, cls, methods, 5);
    (*env)->DeleteLocalRef(env, cls);
  }
}

/* 
 * Local utility function to extract the array pointer from the Java object.
 * Extract the d_array long data member and convert it to a pointer.
 */
static struct sidl_string__array *
sidl_String__getptr(JNIEnv * env, jobject obj)
{
  void *ptr = NULL;
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  ptr = JLONG_TO_POINTER((*env)->GetLongField(env, obj, s_array_field));
  return (struct sidl_string__array *) ptr;
}

/*
 * Local utility function to set the array pointer on the Java object.
 * Convert the pointer to a long value and set the d_array data member.
 */
static void
sidl_String__setptr(JNIEnv * env,
                    jobject obj, struct sidl_string__array *array)
{
  static jfieldID s_array_field = NULL;

  if (s_array_field == NULL) {
    jclass cls = (*env)->GetObjectClass(env, obj);
    s_array_field = (*env)->GetFieldID(env, cls, "d_array", "J");
    (*env)->DeleteLocalRef(env, cls);
  }

  (*env)->SetLongField(env, obj, s_array_field, POINTER_TO_JLONG(array));
}

/*
 * Native routine to fetch the specified value from the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static jstring
sidl_String__get(JNIEnv * env,
                 jobject obj,
                 jint i, jint j, jint k, jint l, jint m, jint n, jint o)
{
  struct sidl_string__array *array = sidl_String__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];
  char *value;
  jstring jstr;

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  value = sidl_string__array_get(array, a);
  jstr = sidl_Java_I2J_string(env, value);
  sidl_String_free(value);
  return jstr;
}

/**
 * Native routine to set the specified value in the array.  The
 * specified array index/indices must be lie between the array lower
 * upper bounds (inclusive).  Invalid indices will have unpredictable
 * (but almost certainly bad) results.
 */
static void
sidl_String__set(JNIEnv * env,
                 jobject obj,
                 jint i,
                 jint j,
                 jint k, jint l, jint m, jint n, jint o, jstring value)
{
  struct sidl_string__array *array = sidl_String__getptr(env, obj);
  int32_t a[SIDL_MAX_ARRAY_DIMENSION];
  char *elem;

  a[0] = i;
  a[1] = j;
  a[2] = k;
  a[3] = l;
  a[4] = m;
  a[5] = n;
  a[6] = o;
  elem = sidl_Java_J2I_string(env, value);
  sidl_string__array_set(array, a, elem);
  sidl_String_free(elem);
}

/*
 * Native routine to reallocate data in the array.  The specified array
 * dimension and indices must match and be within valid ranges (e.g., the
 * upper bounds must be greater than or equal to lowe rbounds.  Invalid
 * indices will have unpredictable (but almost certainly bad) results.
 * This routine will deallocate the existing array data if it is not null.
 * if argument "isRow" is true, the array will be in RowOrder, other wise
 * it will be in ColumnOrder   
 */
static void
sidl_String__reallocate(JNIEnv * env,
                        jobject obj,
                        jint dim, jarray lower, jarray upper, jboolean isRow)
{
  jint *l = NULL;
  jint *u = NULL;
  struct sidl_string__array *array = NULL;

  sidl__destroy(env, obj);

  l = (*env)->GetIntArrayElements(env, lower, NULL);
  u = (*env)->GetIntArrayElements(env, upper, NULL);
  if (isRow)
    array = sidl_string__array_createRow((int32_t) dim, (int32_t *) l,
                                         (int32_t *) u);
  else
    array = sidl_string__array_createCol((int32_t) dim, (int32_t *) l,
                                         (int32_t *) u);
  (*env)->ReleaseIntArrayElements(env, lower, l, JNI_ABORT);
  (*env)->ReleaseIntArrayElements(env, upper, u, JNI_ABORT);

  sidl_String__setptr(env, obj, array);
}


/*
 * Native function copies borrowed arrays, or increments the reference count
 * of non-borrowed arrays.  Good if you want to keep a copy of a passed
 * in array.  Returns an array, new if borrowed.
 */
static void
sidl_String__copy(JNIEnv * env, jobject obj, jobject dest)
{
  struct sidl_string__array *csrc = sidl_String__getptr(env, obj);
  struct sidl_string__array *cdest = sidl_String__getptr(env, dest);

  if (csrc && cdest) {
    sidl_string__array_copy(csrc, cdest);
  }

}

/*
 * Native function slices arrays in various ways
 */
static jobject
sidl_String__slice(JNIEnv * env,
                   jobject obj,
                   jint dimen,
                   jintArray numElem,
                   jintArray srcStart,
                   jintArray srcStride, jintArray newStart)
{
  struct sidl_string__array *array = sidl_String__getptr(env, obj);
  struct sidl_string__array *ret_ptr = NULL;
  jobject ret_array = NULL;

  /* I'm cheating a bit here.  Slice expects any unused arguments to be
     null.  But I don't want to use malloc, so I'm allocating the space
     on the stack, but only pointing to it if that argument is actually
     used. */
  jint anumElem[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStart[SIDL_MAX_ARRAY_DIMENSION];
  jint asrcStride[SIDL_MAX_ARRAY_DIMENSION];
  jint anewStart[SIDL_MAX_ARRAY_DIMENSION];
  jint *cnumElem = NULL;
  jint *csrcStart = NULL;
  jint *csrcStride = NULL;
  jint *cnewStart = NULL;
  int i = 0;

  if (numElem == NULL) {
    return NULL;                /*If numElem is NULL, we need to return Null, that's bad. */
  }
  else {
    if ((*env)->GetArrayLength(env, numElem) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnumElem = anumElem;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnumElem[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, numElem, 0,
                              (*env)->GetArrayLength(env, numElem), cnumElem);

  }

  if (srcStart != NULL) {
    if ((*env)->GetArrayLength(env, srcStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStart = asrcStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStart, 0,
                              (*env)->GetArrayLength(env, srcStart),
                              csrcStart);
  }

  if (srcStride != NULL) {
    if ((*env)->GetArrayLength(env, srcStride) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    csrcStride = asrcStride;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      csrcStride[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, srcStride, 0,
                              (*env)->GetArrayLength(env, srcStride),
                              csrcStride);
  }

  if (newStart != NULL) {
    if ((*env)->GetArrayLength(env, newStart) > SIDL_MAX_ARRAY_DIMENSION)
      return NULL;
    cnewStart = anewStart;
    for (i = 0; i < SIDL_MAX_ARRAY_DIMENSION; ++i) {    /*Make sure the array is clean */
      cnewStart[i] = 0;
    }
    (*env)->GetIntArrayRegion(env, newStart, 0,
                              (*env)->GetArrayLength(env, newStart),
                              cnewStart);
  }

  if (array != NULL) {
    /* jint should be equivalent to int32_t; Java int is 32 bits */
    ret_ptr =
      sidl_string__array_slice(array, dimen, cnumElem, csrcStart, csrcStride,
                               cnewStart);
  }

  if (ret_ptr != NULL) {
    ret_array = sidl_Java_I2J_new_array(env, ret_ptr, "sidl.String$Array");
  }

  return ret_array;
}


/*
 * Register JNI array methods with the Java JVM.
 */
void
sidl_String__register(JNIEnv * env)
{
  JNINativeMethod methods[5];
  jclass cls;

  methods[0].name = "_get";
  methods[0].signature = "(IIIIIII)Ljava/lang/String;";
  methods[0].fnPtr = sidl_String__get;
  methods[1].name = "_set";
  methods[1].signature = "(IIIIIIILjava/lang/String;)V";
  methods[1].fnPtr = sidl_String__set;
  methods[2].name = "_copy";
  methods[2].signature = "(Lsidl/String$Array;)V";
  methods[2].fnPtr = sidl_String__copy;
  methods[3].name = "_slice";
  methods[3].signature = "(I[I[I[I[I)Lsidl/String$Array;";
  methods[3].fnPtr = sidl_String__slice;
  methods[4].name = "_reallocate";
  methods[4].signature = "(I[I[IZ)V";
  methods[4].fnPtr = sidl_String__reallocate;


  cls = (*env)->FindClass(env, "sidl/String$Array");
  if (cls) {
    (*env)->RegisterNatives(env, cls, methods, 5);
    (*env)->DeleteLocalRef(env, cls);
  }
}
