JNIEXPORT jlong JNICALL
Java_io_jxcore_node_jxcore_callCBString(JNIEnv *env, jobject thiz,
                                        jstring ev_name, jstring param,
                                        jint json) {
  if (eventCB.type_ == 0) {
    error_console("event callback is not ready yet.");
    return 0;
  }

  const char *str_ev = env->GetStringUTFChars(ev_name, 0);
  const char *str_param = env->GetStringUTFChars(param, 0);

  long ret_val = 0;
  JXValue args[2];
  if (JX_CreateEmptyObject(&args[1])) {
    JXValue jx_str_param;
    JX_New(&args[0]);
    JX_New(&jx_str_param);

    JX_SetString(&args[0], str_ev, 0);
    JX_SetString(&jx_str_param, str_param, 0);

    if (json != 1)
      JX_SetNamedProperty(&args[1], "str", &jx_str_param);
    else
      JX_SetNamedProperty(&args[1], "json", &jx_str_param);

    JX_Free(&jx_str_param);

    JXValue out;
    JX_CallFunction(&eventCB, args, 2, &out);

    JX_Free(&args[0]);
    JX_Free(&args[1]);

    if (!JX_IsNull(&out) && !JX_IsUndefined(&out))
      ret_val = JX_StoreValue(&out);
    else
      ret_val = -1;
  } else {
    error_console("couldn't create JXValue Object");
  }

  env->ReleaseStringUTFChars(ev_name, str_ev);
  env->ReleaseStringUTFChars(param, str_param);

  return ret_val;
}
static void defineEventCB(JXValue *results, int argc) {
  if (!JX_IsFunction(results + 1)) {
    error_console("defineEventCB expects a function");
    return;
  }

  JX_MakePersistent(results+1);
  eventCB = *(results + 1);
}
static void callback(JXValue *results, int argc) {
  if (argc != 3) {
    error_console(
        "wrong callback received. expected number of parameters was 3. "
        "received %d",
        argc);
    return;
  }

  if (!JX_IsString(results + 2)) {
    error_console(
        "JXcore-Cordova: Unexpected callback received. Third parameter must "
        "be a String");
    return;
  }

  cb_values = results;

  // results+1 -> err_val
  jxcore::Callback((JX_IsNull(results + 1) || JX_IsUndefined(results + 1)) ? 0
                                                                           : 1);

  cb_values = NULL;
}
JNIEXPORT jlong JNICALL
Java_io_jxcore_node_jxcore_callCBArray(JNIEnv *env, jobject thiz,
                                       jstring ev_name, jobjectArray params,
                                       jint size) {
  if (eventCB.type_ == 0) {
    error_console("event callback is not ready yet.");
    return 0;
  }

  const char *str_ev = env->GetStringUTFChars(ev_name, 0);

  long ret_val = 0;
  JXValue args[2];
  if (JX_CreateArrayObject(&args[1])) {
    JX_New(&args[0]);

    JX_SetString(&args[0], str_ev, 0);

    jclass boolClass = env->FindClass("java/lang/Boolean");
    jclass doubleClass = env->FindClass("java/lang/Double");
    jclass intClass = env->FindClass("java/lang/Integer");
    jclass strClass = env->FindClass("java/lang/String");
    jclass barrClass = env->FindClass("[B");

    for (int i = 0; i < (int)size; i++) {
      jobject elm = (jobject)env->GetObjectArrayElement(params, i);

      JXValue val;
      JX_New(&val);
      if (elm == NULL) {
        JX_SetNull(&val);
      } else if (env->IsInstanceOf(elm, boolClass) == JNI_TRUE) {
        jmethodID bvalID = env->GetMethodID(boolClass, "booleanValue", "()Z");
        bool nval = (bool)env->CallBooleanMethod(elm, bvalID);
        JX_SetBoolean(&val, nval);
      } else if (env->IsInstanceOf(elm, intClass) == JNI_TRUE) {
        jmethodID bvalID = env->GetMethodID(intClass, "intValue", "()I");
        int nval = (int)env->CallIntMethod(elm, bvalID);
        JX_SetInt32(&val, nval);
      } else if (env->IsInstanceOf(elm, doubleClass) == JNI_TRUE) {
        jmethodID bvalID = env->GetMethodID(doubleClass, "doubleValue", "()D");
        double nval = (double)env->CallDoubleMethod(elm, bvalID);
        JX_SetDouble(&val, nval);
      } else if (env->IsInstanceOf(elm, strClass) == JNI_TRUE) {
        jstring jstr = (jstring)elm;
        const char *str = env->GetStringUTFChars(jstr, 0);
        JX_SetString(&val, str, strlen(str));
        env->ReleaseStringUTFChars(jstr, str);
      } else if (env->IsInstanceOf(elm, barrClass) == JNI_TRUE) {
        jbyteArray jarr = (jbyteArray)elm;
        int len = env->GetArrayLength(jarr);
        jbyte *barr = env->GetByteArrayElements(jarr, 0);
        JX_SetBuffer(&val, (char *)barr, len);

        env->ReleaseByteArrayElements(jarr, barr, JNI_ABORT);
      }

      JX_SetIndexedProperty(&args[1], i, &val);
      JX_Free(&val);

      env->DeleteLocalRef(elm);
    }

    env->DeleteLocalRef(boolClass);
    env->DeleteLocalRef(doubleClass);
    env->DeleteLocalRef(intClass);
    env->DeleteLocalRef(strClass);
    env->DeleteLocalRef(barrClass);

    JXValue out;
    JX_CallFunction(&eventCB, args, 2, &out);

    JX_Free(&args[0]);
    JX_Free(&args[1]);

    if (!JX_IsNull(&out) && !JX_IsUndefined(&out))
      ret_val = JX_StoreValue(&out);
    else
      ret_val = -1;
  } else {
    error_console("couldn't create JXValue Object");
  }

  env->ReleaseStringUTFChars(ev_name, str_ev);

  return ret_val;
}
예제 #5
0
파일: process.c 프로젝트: JarshChen/jxcore
int uv_spawn_jx(uv_loop_t* loop, uv_process_t* process,
                uv_process_options_t* options) {
#ifdef WINONECORE
  error_console("Error: WindowsOneCore does not support spawning a process.\n");
  return -1; // not supported
#else
  int i;
  uv_err_t err = uv_ok_;
  WCHAR* path = NULL;
  BOOL result;
  WCHAR* application_path = NULL, *application = NULL, *arguments = NULL,
         *env = NULL, *cwd = NULL;
  STARTUPINFOW startup;
  PROCESS_INFORMATION info;
  DWORD process_flags;

  if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {
    uv__set_artificial_error(loop, UV_ENOTSUP);
    return -1;
  }

  if (options->file == NULL || options->args == NULL) {
    uv__set_artificial_error(loop, UV_EINVAL);
    return -1;
  }

  assert(options->file != NULL);
  assert(!(options->flags &
           ~(UV_PROCESS_DETACHED | UV_PROCESS_SETGID | UV_PROCESS_SETUID |
             UV_PROCESS_WINDOWS_HIDE | UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));

  uv_process_init(loop, process);
  process->exit_cb = options->exit_cb;

  err = uv_utf8_to_utf16_alloc(options->file, &application);
  if (err.code != UV_OK) goto done;

  err = make_program_args(
      options->args, options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS,
      &arguments);
  if (err.code != UV_OK) goto done;

  if (options->env) {
    err = make_program_env(options->env, &env);
    if (err.code != UV_OK) goto done;
  }

  if (options->cwd) {
    /* Explicit cwd */
    err = uv_utf8_to_utf16_alloc(options->cwd, &cwd);
    if (err.code != UV_OK) goto done;

  } else {
    /* Inherit cwd */
    DWORD cwd_len, r;

    cwd_len = GetCurrentDirectoryW(0, NULL);
    if (!cwd_len) {
      err = uv__new_sys_error(GetLastError());
      goto done;
    }

    cwd = (WCHAR*)malloc(cwd_len * sizeof(WCHAR));
    if (cwd == NULL) {
      err = uv__new_artificial_error(UV_ENOMEM);
      goto done;
    }

    r = GetCurrentDirectoryW(cwd_len, cwd);
    if (r == 0 || r >= cwd_len) {
      err = uv__new_sys_error(GetLastError());
      goto done;
    }
  }

  /* Get PATH environment variable. */
  {
    DWORD path_len, r;

    path_len = GetEnvironmentVariableW(L"PATH", NULL, 0);
    if (path_len == 0) {
      err = uv__new_sys_error(GetLastError());
      goto done;
    }

    path = (WCHAR*)malloc(path_len * sizeof(WCHAR));
    if (path == NULL) {
      err = uv__new_artificial_error(UV_ENOMEM);
      goto done;
    }

    r = GetEnvironmentVariableW(L"PATH", path, path_len);
    if (r == 0 || r >= path_len) {
      err = uv__new_sys_error(GetLastError());
      goto done;
    }
  }

  application_path = search_path(application, cwd, path);
  if (application_path == NULL) {
    /* Not found. */
    err = uv__new_artificial_error(UV_ENOENT);
    goto done;
  }

  err = uv__stdio_create(loop, options, &process->child_stdio_buffer);
  if (err.code != UV_OK) goto done;

  startup.cb = sizeof(startup);
  startup.lpReserved = NULL;
  startup.lpDesktop = NULL;
  startup.lpTitle = NULL;
  startup.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;

  startup.cbReserved2 = uv__stdio_size(process->child_stdio_buffer);
  startup.lpReserved2 = (BYTE*)process->child_stdio_buffer;

  startup.hStdInput = uv__stdio_handle(process->child_stdio_buffer, 0);
  startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1);
  startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2);

  if (options->flags & UV_PROCESS_WINDOWS_HIDE) {
    /* Use SW_HIDE to avoid any potential process window. */
    startup.wShowWindow = SW_HIDE;
  } else {
    startup.wShowWindow = SW_SHOWDEFAULT;
  }

  process_flags = CREATE_UNICODE_ENVIRONMENT;

  if (options->flags & UV_PROCESS_DETACHED) {
    /* Note that we're not setting the CREATE_BREAKAWAY_FROM_JOB flag. That
     * means that libuv might not let you create a fully deamonized process
     * when run under job control. However the type of job control that libuv
     * itself creates doesn't trickle down to subprocesses so they can still
     * daemonize.
     *
     * A reason to not do this is that CREATE_BREAKAWAY_FROM_JOB makes the
     * CreateProcess call fail if we're under job control that doesn't allow
     * breakaway.
     */
    process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
  }

  if (CreateProcessW(application_path, arguments, NULL, NULL, 1, process_flags,
                     env, cwd, &startup, &info)) {
    /* Spawn succeeded */
    process->process_handle = info.hProcess;
    process->pid = info.dwProcessId;

    /* If the process isn't spawned as detached, assign to the global job */
    /* object so windows will kill it when the parent process dies. */
    if (!(options->flags & UV_PROCESS_DETACHED)) {
      uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle);

      if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) {
        /* AssignProcessToJobObject might fail if this process is under job
         * control and the job doesn't have the
         * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag set, on a Windows version
         * that doesn't support nested jobs.
         *
         * When that happens we just swallow the error and continue without
         * establishing a kill-child-on-parent-exit relationship, otherwise
         * there would be no way for libuv applications run under job control
         * to spawn processes at all.
         */
        DWORD err = GetLastError();
        if (err != ERROR_ACCESS_DENIED)
          uv_fatal_error(err, "AssignProcessToJobObject");
      }
    }

    /* Set IPC pid to all IPC pipes. */
    for (i = 0; i < options->stdio_count; i++) {
      const uv_stdio_container_t* fdopt = &options->stdio[i];
      if (fdopt->flags & UV_CREATE_PIPE &&
          fdopt->data.stream->type == UV_NAMED_PIPE &&
          ((uv_pipe_t*)fdopt->data.stream)->ipc) {
        ((uv_pipe_t*)fdopt->data.stream)->ipc_pid = info.dwProcessId;
      }
    }

    /* Setup notifications for when the child process exits. */
    result = RegisterWaitForSingleObject(
        &process->wait_handle, process->process_handle, exit_wait_callback,
        (void*)process, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE);
    if (!result) {
      uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject");
    }

    CloseHandle(info.hThread);

  } else {
    /* CreateProcessW failed. */
    err = uv__new_sys_error(GetLastError());
  }

done:
  JX_FREE(process, application);
  JX_FREE(process, application_path);
  JX_FREE(process, arguments);
  JX_FREE(process, cwd);
  JX_FREE(process, env);
  JX_FREE(process, path);

  process->spawn_error = err;

  if (process->child_stdio_buffer != NULL) {
    /* Clean up child stdio handles. */
    uv__stdio_destroy(process->child_stdio_buffer);
    process->child_stdio_buffer = NULL;
  }

  /* Make the handle active. It will remain active until the exit callback */
  /* is made or the handle is closed, whichever happens first. */
  uv__handle_start(process);

  /* If an error happened, queue the exit req. */
  if (err.code != UV_OK) {
    process->exit_cb_pending = 1;
    uv_insert_pending_req(loop, (uv_req_t*)&process->exit_req);
  }

  return 0;
#endif
}