jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp

Print this page
rev 5725 : Merge


  33 #include <limits.h>
  34 
  35 #include <com_sun_java_util_jar_pack_NativeUnpack.h>
  36 
  37 #include "jni_util.h"
  38 
  39 #include "defines.h"
  40 #include "bytes.h"
  41 #include "utils.h"
  42 #include "coding.h"
  43 #include "bands.h"
  44 #include "constants.h"
  45 #include "zip.h"
  46 #include "unpack.h"
  47 
  48 
  49 static jfieldID  unpackerPtrFID;
  50 static jmethodID currentInstMID;
  51 static jmethodID readInputMID;
  52 static jclass    NIclazz;

  53 
  54 static char* dbg = null;
  55 
  56 #define THROW_IOE(x) JNU_ThrowIOException(env,x)
  57 
  58 static jlong read_input_via_jni(unpacker* self,
  59                                 void* buf, jlong minlen, jlong maxlen);
  60 
  61 static unpacker* get_unpacker(JNIEnv *env, jobject pObj, bool noCreate=false) {
  62   unpacker* uPtr;
  63   uPtr = (unpacker*)jlong2ptr(env->GetLongField(pObj, unpackerPtrFID));
  64   //fprintf(stderr, "get_unpacker(%p) uPtr=%p\n", pObj, uPtr);
  65   if (uPtr == null) {
  66     if (noCreate)  return null;
  67     uPtr = new unpacker();
  68     if (uPtr == null) {
  69       THROW_IOE(ERROR_ENOMEM);
  70       return null;
  71     }
  72     //fprintf(stderr, "get_unpacker(%p) uPtr=%p initializing\n", pObj, uPtr);
  73     uPtr->init(read_input_via_jni);
  74     uPtr->jniobj = (void*) env->NewGlobalRef(pObj);
  75     env->SetLongField(pObj, unpackerPtrFID, ptr2jlong(uPtr));
  76   }
  77   uPtr->jnienv = env;  // keep refreshing this in case of MT access
  78   return uPtr;
  79 }
  80 
  81 // This is the harder trick:  Pull the current state out of mid-air.
  82 static unpacker* get_unpacker() {
  83   //fprintf(stderr, "get_unpacker()\n");
  84   JavaVM* vm = null;
  85   jsize nVM = 0;
  86   jint retval = JNI_GetCreatedJavaVMs(&vm, 1, &nVM);
  87   // other VM implements may differ, thus for correctness, we need these checks
  88   if (retval != JNI_OK || nVM != 1)
  89     return null;
  90   void* envRaw = null;
  91   vm->GetEnv(&envRaw, JNI_VERSION_1_1);
  92   JNIEnv* env = (JNIEnv*) envRaw;
  93   //fprintf(stderr, "get_unpacker() env=%p\n", env);
  94   if (env == null)
  95     return null;
  96   jobject pObj = env->CallStaticObjectMethod(NIclazz, currentInstMID);
  97   //fprintf(stderr, "get_unpacker() pObj=%p\n", pObj);
  98   if (pObj == null)
  99     return null;
 100   // Got pObj and env; now do it the easy way.
 101   return get_unpacker(env, pObj);





 102 }
 103 
 104 static void free_unpacker(JNIEnv *env, jobject pObj, unpacker* uPtr) {
 105   if (uPtr != null) {
 106     //fprintf(stderr, "free_unpacker(%p) uPtr=%p\n", pObj, uPtr);
 107     env->DeleteGlobalRef((jobject) uPtr->jniobj);
 108     uPtr->jniobj = null;
 109     uPtr->free();
 110     delete uPtr;
 111     env->SetLongField(pObj, unpackerPtrFID, (jlong)null);
 112    }
 113 }
 114 
 115 unpacker* unpacker::current() {
 116   return get_unpacker();
 117 }
 118 
 119 // Callback for fetching data, Java style.  Calls NativeUnpack.readInputFn().
 120 static jlong read_input_via_jni(unpacker* self,
 121                                 void* buf, jlong minlen, jlong maxlen) {
 122   JNIEnv* env = (JNIEnv*) self->jnienv;
 123   jobject pbuf = env->NewDirectByteBuffer(buf, maxlen);
 124   return env->CallLongMethod((jobject) self->jniobj, readInputMID,
 125                              pbuf, minlen);
 126 }
 127 
 128 JNIEXPORT void JNICALL
 129 Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz) {

 130   dbg = getenv("DEBUG_ATTACH");
 131   while( dbg != null) { sleep(10); }

 132   NIclazz = (jclass) env->NewGlobalRef(clazz);
 133   unpackerPtrFID = env->GetFieldID(clazz, "unpackerPtr", "J");
 134   currentInstMID = env->GetStaticMethodID(clazz, "currentInstance",
 135                                           "()Ljava/lang/Object;");
 136   readInputMID = env->GetMethodID(clazz, "readInputFn",
 137                                   "(Ljava/nio/ByteBuffer;J)J");


 138   if (unpackerPtrFID == null ||
 139       currentInstMID == null ||
 140       readInputMID == null ||
 141       NIclazz == null) {

 142     THROW_IOE("cannot init class members");
 143   }
 144 }
 145 
 146 JNIEXPORT jlong JNICALL
 147 Java_com_sun_java_util_jar_pack_NativeUnpack_start(JNIEnv *env, jobject pObj,
 148                                    jobject pBuf, jlong offset) {
 149   unpacker* uPtr = get_unpacker(env, pObj);
 150 





 151   // redirect our io to the default log file or whatever.
 152   uPtr->redirect_stdio();
 153 
 154   void*  buf    = null;
 155   size_t buflen = 0;
 156   if (pBuf != null) {
 157     buf    = env->GetDirectBufferAddress(pBuf);
 158     buflen = (size_t)env->GetDirectBufferCapacity(pBuf);
 159     if (buflen == 0)  buf = null;
 160     if (buf == null) { THROW_IOE(ERROR_INTERNAL); return 0; }
 161     if ((size_t)offset >= buflen)
 162       { buf = null; buflen = 0; }
 163     else
 164       { buf = (char*)buf + (size_t)offset; buflen -= (size_t)offset; }
 165   }
 166 





 167   uPtr->start(buf, buflen);
 168   if (uPtr->aborting()) {
 169     THROW_IOE(uPtr->get_abort_message());
 170     return 0;
 171   }
 172 
 173   return ((jlong)
 174           uPtr->get_segments_remaining() << 32)
 175     + uPtr->get_files_remaining();
 176 }
 177 
 178 JNIEXPORT jboolean JNICALL
 179 Java_com_sun_java_util_jar_pack_NativeUnpack_getNextFile(JNIEnv *env, jobject pObj,
 180                                          jobjectArray pParts) {
 181 
 182   unpacker* uPtr = get_unpacker(env, pObj);
 183   unpacker::file* filep = uPtr->get_next_file();
 184 
 185   if (uPtr->aborting()) {
 186     THROW_IOE(uPtr->get_abort_message());


 213     pDataBuf = env->NewDirectByteBuffer(filep->data[1].ptr,
 214                                         filep->data[1].len);
 215   env->SetObjectArrayElement(pParts, pidx++, pDataBuf);
 216 
 217   return true;
 218 }
 219 
 220 
 221 JNIEXPORT jobject JNICALL
 222 Java_com_sun_java_util_jar_pack_NativeUnpack_getUnusedInput(JNIEnv *env, jobject pObj) {
 223   unpacker* uPtr = get_unpacker(env, pObj);
 224   unpacker::file* filep = &uPtr->cur_file;
 225 
 226   if (uPtr->aborting()) {
 227     THROW_IOE(uPtr->get_abort_message());
 228     return false;
 229   }
 230 
 231   // We have fetched all the files.
 232   // Now swallow up any remaining input.
 233   if (uPtr->input_remaining() == 0)
 234     return null;
 235   else
 236     return env->NewDirectByteBuffer(uPtr->input_scan(),
 237                                     uPtr->input_remaining());



 238 }
 239 
 240 JNIEXPORT jlong JNICALL
 241 Java_com_sun_java_util_jar_pack_NativeUnpack_finish(JNIEnv *env, jobject pObj) {
 242   unpacker* uPtr = get_unpacker(env, pObj, false);
 243   if (uPtr == null)  return 0;
 244   size_t consumed = uPtr->input_consumed();
 245   free_unpacker(env, pObj, uPtr);
 246   return consumed;
 247 }
 248 
 249 JNIEXPORT jboolean JNICALL
 250 Java_com_sun_java_util_jar_pack_NativeUnpack_setOption(JNIEnv *env, jobject pObj,
 251                                        jstring pProp, jstring pValue) {
 252   unpacker*   uPtr  = get_unpacker(env, pObj);
 253   const char* prop  = env->GetStringUTFChars(pProp, JNI_FALSE);
 254   const char* value = env->GetStringUTFChars(pValue, JNI_FALSE);
 255   jboolean   retval = uPtr->set_option(prop, value);
 256   env->ReleaseStringUTFChars(pProp,  prop);
 257   env->ReleaseStringUTFChars(pValue, value);


  33 #include <limits.h>
  34 
  35 #include <com_sun_java_util_jar_pack_NativeUnpack.h>
  36 
  37 #include "jni_util.h"
  38 
  39 #include "defines.h"
  40 #include "bytes.h"
  41 #include "utils.h"
  42 #include "coding.h"
  43 #include "bands.h"
  44 #include "constants.h"
  45 #include "zip.h"
  46 #include "unpack.h"
  47 
  48 
  49 static jfieldID  unpackerPtrFID;
  50 static jmethodID currentInstMID;
  51 static jmethodID readInputMID;
  52 static jclass    NIclazz;
  53 static jmethodID getUnpackerPtrMID;
  54 
  55 static char* dbg = null;
  56 
  57 #define THROW_IOE(x) JNU_ThrowIOException(env,x)
  58 
  59 static jlong read_input_via_jni(unpacker* self,
  60                                 void* buf, jlong minlen, jlong maxlen);
  61 
  62 static unpacker* get_unpacker(JNIEnv *env, jobject pObj, bool noCreate=false) {
  63   unpacker* uPtr;
  64   jlong p = env->CallLongMethod(pObj, getUnpackerPtrMID);
  65   uPtr = (unpacker*)jlong2ptr(p);
  66   if (uPtr == null) {
  67     if (noCreate)  return null;
  68     uPtr = new unpacker();
  69     if (uPtr == null) {
  70       THROW_IOE(ERROR_ENOMEM);
  71       return null;
  72     }
  73     //fprintf(stderr, "get_unpacker(%p) uPtr=%p initializing\n", pObj, uPtr);
  74     uPtr->init(read_input_via_jni);
  75     uPtr->jniobj = (void*) env->NewGlobalRef(pObj);
  76     env->SetLongField(pObj, unpackerPtrFID, ptr2jlong(uPtr));
  77   }
  78   uPtr->jnienv = env;  // keep refreshing this in case of MT access
  79   return uPtr;
  80 }
  81 
  82 // This is the harder trick:  Pull the current state out of mid-air.
  83 static unpacker* get_unpacker() {
  84   //fprintf(stderr, "get_unpacker()\n");
  85   JavaVM* vm = null;
  86   jsize nVM = 0;
  87   jint retval = JNI_GetCreatedJavaVMs(&vm, 1, &nVM);
  88   // other VM implements may differ, thus for correctness, we need these checks
  89   if (retval != JNI_OK || nVM != 1)
  90     return null;
  91   void* envRaw = null;
  92   vm->GetEnv(&envRaw, JNI_VERSION_1_1);
  93   JNIEnv* env = (JNIEnv*) envRaw;
  94   //fprintf(stderr, "get_unpacker() env=%p\n", env);
  95   if (env == null)
  96     return null;
  97   jobject pObj = env->CallStaticObjectMethod(NIclazz, currentInstMID);
  98   //fprintf(stderr, "get_unpacker0() pObj=%p\n", pObj);
  99   if (pObj != null) {

 100     // Got pObj and env; now do it the easy way.
 101     return get_unpacker(env, pObj);
 102   }
 103   // this should really not happen, if it does something is seriously
 104   // wrong throw an exception
 105   THROW_IOE(ERROR_INTERNAL);
 106   return null;
 107 }
 108 
 109 static void free_unpacker(JNIEnv *env, jobject pObj, unpacker* uPtr) {
 110   if (uPtr != null) {
 111     //fprintf(stderr, "free_unpacker(%p) uPtr=%p\n", pObj, uPtr);
 112     env->DeleteGlobalRef((jobject) uPtr->jniobj);
 113     uPtr->jniobj = null;
 114     uPtr->free();
 115     delete uPtr;
 116     env->SetLongField(pObj, unpackerPtrFID, (jlong)null);
 117    }
 118 }
 119 
 120 unpacker* unpacker::current() {
 121   return get_unpacker();
 122 }
 123 
 124 // Callback for fetching data, Java style.  Calls NativeUnpack.readInputFn().
 125 static jlong read_input_via_jni(unpacker* self,
 126                                 void* buf, jlong minlen, jlong maxlen) {
 127   JNIEnv* env = (JNIEnv*) self->jnienv;
 128   jobject pbuf = env->NewDirectByteBuffer(buf, maxlen);
 129   return env->CallLongMethod((jobject) self->jniobj, readInputMID,
 130                              pbuf, minlen);
 131 }
 132 
 133 JNIEXPORT void JNICALL
 134 Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz) {
 135 #ifndef PRODUCT
 136   dbg = getenv("DEBUG_ATTACH");
 137   while( dbg != null) { sleep(10); }
 138 #endif
 139   NIclazz = (jclass) env->NewGlobalRef(clazz);
 140   unpackerPtrFID = env->GetFieldID(clazz, "unpackerPtr", "J");
 141   currentInstMID = env->GetStaticMethodID(clazz, "currentInstance",
 142                                           "()Ljava/lang/Object;");
 143   readInputMID = env->GetMethodID(clazz, "readInputFn",
 144                                   "(Ljava/nio/ByteBuffer;J)J");
 145   getUnpackerPtrMID = env->GetMethodID(clazz, "getUnpackerPtr", "()J");
 146 
 147   if (unpackerPtrFID == null ||
 148       currentInstMID == null ||
 149       readInputMID == null ||
 150       NIclazz == null ||
 151       getUnpackerPtrMID == null) {
 152     THROW_IOE("cannot init class members");
 153   }
 154 }
 155 
 156 JNIEXPORT jlong JNICALL
 157 Java_com_sun_java_util_jar_pack_NativeUnpack_start(JNIEnv *env, jobject pObj,
 158                                    jobject pBuf, jlong offset) {
 159   // try to get the unpacker pointer the hard way first, we do this to ensure
 160   // valid object pointers and env is intact, if not now is good time to bail.
 161   unpacker* uPtr = get_unpacker();
 162   //fprintf(stderr, "start(%p) uPtr=%p initializing\n", pObj, uPtr);
 163   if (uPtr == null) {
 164       return -1;
 165   }
 166   // redirect our io to the default log file or whatever.
 167   uPtr->redirect_stdio();
 168 
 169   void*  buf    = null;
 170   size_t buflen = 0;
 171   if (pBuf != null) {
 172     buf    = env->GetDirectBufferAddress(pBuf);
 173     buflen = (size_t)env->GetDirectBufferCapacity(pBuf);
 174     if (buflen == 0)  buf = null;
 175     if (buf == null) { THROW_IOE(ERROR_INTERNAL); return 0; }
 176     if ((size_t)offset >= buflen)
 177       { buf = null; buflen = 0; }
 178     else
 179       { buf = (char*)buf + (size_t)offset; buflen -= (size_t)offset; }
 180   }
 181   // before we start off we make sure there is no other error by the time we
 182   // get here
 183   if (uPtr->aborting()) {
 184     THROW_IOE(uPtr->get_abort_message());
 185     return 0;
 186   }
 187   uPtr->start(buf, buflen);
 188   if (uPtr->aborting()) {
 189     THROW_IOE(uPtr->get_abort_message());
 190     return 0;
 191   }
 192 
 193   return ((jlong)
 194           uPtr->get_segments_remaining() << 32)
 195     + uPtr->get_files_remaining();
 196 }
 197 
 198 JNIEXPORT jboolean JNICALL
 199 Java_com_sun_java_util_jar_pack_NativeUnpack_getNextFile(JNIEnv *env, jobject pObj,
 200                                          jobjectArray pParts) {
 201 
 202   unpacker* uPtr = get_unpacker(env, pObj);
 203   unpacker::file* filep = uPtr->get_next_file();
 204 
 205   if (uPtr->aborting()) {
 206     THROW_IOE(uPtr->get_abort_message());


 233     pDataBuf = env->NewDirectByteBuffer(filep->data[1].ptr,
 234                                         filep->data[1].len);
 235   env->SetObjectArrayElement(pParts, pidx++, pDataBuf);
 236 
 237   return true;
 238 }
 239 
 240 
 241 JNIEXPORT jobject JNICALL
 242 Java_com_sun_java_util_jar_pack_NativeUnpack_getUnusedInput(JNIEnv *env, jobject pObj) {
 243   unpacker* uPtr = get_unpacker(env, pObj);
 244   unpacker::file* filep = &uPtr->cur_file;
 245 
 246   if (uPtr->aborting()) {
 247     THROW_IOE(uPtr->get_abort_message());
 248     return false;
 249   }
 250 
 251   // We have fetched all the files.
 252   // Now swallow up any remaining input.
 253   if (uPtr->input_remaining() == 0) {
 254     return null;
 255   } else {
 256     bytes remaining_bytes;
 257     remaining_bytes.malloc(uPtr->input_remaining());
 258     remaining_bytes.copyFrom(uPtr->input_scan(), uPtr->input_remaining());
 259     return env->NewDirectByteBuffer(remaining_bytes.ptr, remaining_bytes.len);
 260   }
 261 }
 262 
 263 JNIEXPORT jlong JNICALL
 264 Java_com_sun_java_util_jar_pack_NativeUnpack_finish(JNIEnv *env, jobject pObj) {
 265   unpacker* uPtr = get_unpacker(env, pObj, false);
 266   if (uPtr == null)  return 0;
 267   size_t consumed = uPtr->input_consumed();
 268   free_unpacker(env, pObj, uPtr);
 269   return consumed;
 270 }
 271 
 272 JNIEXPORT jboolean JNICALL
 273 Java_com_sun_java_util_jar_pack_NativeUnpack_setOption(JNIEnv *env, jobject pObj,
 274                                        jstring pProp, jstring pValue) {
 275   unpacker*   uPtr  = get_unpacker(env, pObj);
 276   const char* prop  = env->GetStringUTFChars(pProp, JNI_FALSE);
 277   const char* value = env->GetStringUTFChars(pValue, JNI_FALSE);
 278   jboolean   retval = uPtr->set_option(prop, value);
 279   env->ReleaseStringUTFChars(pProp,  prop);
 280   env->ReleaseStringUTFChars(pValue, value);