/* * There are a few ways to arrive in the initsequencer. * 1. From _PG_init (called exactly once when the library is loaded for ANY * reason). * 1a. Because of the command LOAD 'libraryname'; * This case can be distinguished because _PG_init will have found the * LOAD command and saved the 'libraryname' in pljavaLoadPath. * 1b. Because of a CREATE FUNCTION naming this library. pljavaLoadPath will * be NULL. * 1c. By the first actual use of a PL/Java function, causing this library * to be loaded. pljavaLoadPath will be NULL. The called function's Oid * will be available to the call handler once we return from _PG_init, * but it isn't (easily) available here. * 2. From the call handler, if initialization isn't complete yet. That can only * mean something failed in the earlier call to _PG_init, and whatever it was * is highly likely to fail again. That may lead to the untidyness of * duplicated diagnostic messages, but for now I like the belt-and-suspenders * approach of making sure the init sequence gets as many chances as possible * to succeed. * 3. From a GUC assign hook, if the user has updated a setting that might allow * initialization to succeed. It resumes from where it left off. * * In all cases, the sequence must progress as far as starting the VM and * initializing the PL/Java classes. In all cases except 1a, that's enough, * assuming the language handlers and schema have all been set up already (or, * in case 1b, the user is intent on setting them up explicitly). * * In case 1a, we can go ahead and test for, and create, the schema, functions, * and language entries as needed, using pljavaLoadPath as the library path * if creating the language handler functions. One-stop shopping. (The presence * of pljavaLoadPath in any of the other cases, such as resumption by an assign * hook, indicates it is really a continuation of case 1a.) */ static void initsequencer(enum initstage is, bool tolerant) { JVMOptList optList; Invocation ctx; jint JNIresult; char *greeting; switch (is) { case IS_FORMLESS_VOID: initstage = IS_GUCS_REGISTERED; case IS_GUCS_REGISTERED: libjvmlocation = strdup("libjvm.so"); initstage = IS_PLJAVA_ENABLED; case IS_PLJAVA_ENABLED: libjvm_handle = pg_dlopen(libjvmlocation); if ( NULL == libjvm_handle ) { ereport(ERROR, ( errmsg("Cannot load libjvm.so library, check that it is available in LD_LIBRARY_PATH"), errdetail("%s", (char *)pg_dlerror()))); goto check_tolerant; } initstage = IS_CAND_JVMOPENED; case IS_CAND_JVMOPENED: pljava_createvm = (jint (JNICALL *)(JavaVM **, void **, void *)) pg_dlsym(libjvm_handle, "JNI_CreateJavaVM"); if ( NULL == pljava_createvm ) { /* * If it hasn't got the symbol, it can't be the right * library, so close/unload it so another can be tried. * Format the dlerror string first: dlclose may clobber it. */ char *dle = MemoryContextStrdup(ErrorContext, pg_dlerror()); pg_dlclose(libjvm_handle); initstage = IS_CAND_JVMLOCATION; ereport(ERROR, ( errmsg("Cannot start Java VM"), errdetail("%s", dle), errhint("Check that libjvm.so is available in LD_LIBRARY_PATH"))); goto check_tolerant; } initstage = IS_CREATEVM_SYM_FOUND; case IS_CREATEVM_SYM_FOUND: s_javaLogLevel = INFO; checkIntTimeType(); HashMap_initialize(); /* creates things in TopMemoryContext */ #ifdef PLJAVA_DEBUG /* Hard setting for debug. Don't forget to recompile... */ pljava_debug = 1; #endif initstage = IS_MISC_ONCE_DONE; case IS_MISC_ONCE_DONE: JVMOptList_init(&optList); /* uses CurrentMemoryContext */ seenVisualVMName = false; addUserJVMOptions(&optList); if ( ! seenVisualVMName ) JVMOptList_addVisualVMName(&optList); JVMOptList_add(&optList, "vfprintf", (void*)my_vfprintf, true); #ifndef GCJ JVMOptList_add(&optList, "-Xrs", 0, true); #endif effectiveClassPath = getClassPath("-Djava.class.path="); if(effectiveClassPath != 0) { JVMOptList_add(&optList, effectiveClassPath, 0, true); } initstage = IS_JAVAVM_OPTLIST; case IS_JAVAVM_OPTLIST: JNIresult = initializeJavaVM(&optList); /* frees the optList */ if( JNI_OK != JNIresult ) { initstage = IS_MISC_ONCE_DONE; /* optList has been freed */ StaticAssertStmt(sizeof(jint) <= sizeof(long int), "jint wider than long int?!"); ereport(WARNING, (errmsg("failed to create Java virtual machine"), errdetail("JNI_CreateJavaVM returned an error code: %ld", (long int)JNIresult), jvmStartedAtLeastOnce ? errhint("Because an earlier attempt during this session " "did start a VM before failing, this probably means your " "Java runtime environment does not support more than one " "VM creation per session. You may need to exit this " "session and start a new one.") : 0)); goto check_tolerant; } jvmStartedAtLeastOnce = true; elog(DEBUG2, "successfully created Java virtual machine"); initstage = IS_JAVAVM_STARTED; case IS_JAVAVM_STARTED: #ifdef USE_PLJAVA_SIGHANDLERS pqsignal(SIGINT, pljavaStatementCancelHandler); pqsignal(SIGTERM, pljavaDieHandler); #endif /* Register an on_proc_exit handler that destroys the VM */ on_proc_exit(_destroyJavaVM, 0); initstage = IS_SIGHANDLERS; case IS_SIGHANDLERS: Invocation_pushBootContext(&ctx); PG_TRY(); { initPLJavaClasses(); initJavaSession(); Invocation_popBootContext(); initstage = IS_PLJAVA_FOUND; } PG_CATCH(); { MemoryContextSwitchTo(ctx.upperContext); /* leave ErrorContext */ Invocation_popBootContext(); initstage = IS_MISC_ONCE_DONE; /* We can't stay here... */ if ( tolerant ) reLogWithChangedLevel(WARNING); /* so xact is not aborted */ else { EmitErrorReport(); /* no more unwinding, just log it */ /* Seeing an ERROR emitted to the log, without leaving the * transaction aborted, would violate the principle of least * astonishment. But at check_tolerant below, another ERROR will * be thrown immediately, so the transaction effect will be as * expected and this ERROR will contribute information beyond * what is in the generic one thrown down there. */ FlushErrorState(); } } PG_END_TRY(); if ( IS_PLJAVA_FOUND != initstage ) { /* JVM initialization failed for some reason. Destroy * the VM if it exists. Perhaps the user will try * fixing the pljava.classpath and make a new attempt. */ ereport(WARNING, ( errmsg("failed to load initial PL/Java classes"), errhint("The most common reason is that \"pljava_classpath\" " "needs to be set, naming the proper \"pljava.jar\" file.") )); _destroyJavaVM(0, 0); goto check_tolerant; } case IS_PLJAVA_FOUND: greeting = InstallHelper_hello(); ereport(NULL != pljavaLoadPath ? NOTICE : DEBUG1, ( errmsg("PL/Java loaded"), errdetail("versions:\n%s", greeting))); pfree(greeting); if ( NULL != pljavaLoadPath ) InstallHelper_groundwork(); /* sqlj schema, language handlers, ...*/ initstage = IS_COMPLETE; case IS_COMPLETE: pljavaLoadingAsExtension = false; if ( alteredSettingsWereNeeded ) { /* Use this StringInfoData to conditionally construct part of the * hint string suggesting ALTER DATABASE ... SET ... FROM CURRENT * provided the server is >= 9.2 where that will actually work. * In 9.3, psprintf appeared, which would make this all simpler, * but if 9.3+ were all that had to be supported, this would all * be moot anyway. Doing the initStringInfo inside the ereport * ensures the string is allocated in ErrorContext and won't leak. * Don't remove the extra parens grouping * (initStringInfo, appendStringInfo, errhint) ... with the parens, * that's a comma expression, which is sequenced; without them, they * are just function parameters with evaluation order unknown. */ StringInfoData buf; #if PG_VERSION_NUM >= 90200 #define MOREHINT \ appendStringInfo(&buf, \ "using ALTER DATABASE %s SET ... FROM CURRENT or ", \ pljavaDbName()), #else #define MOREHINT #endif ereport(NOTICE, ( errmsg("PL/Java successfully started after adjusting settings"), (initStringInfo(&buf), MOREHINT errhint("The settings that worked should be saved (%s" "in the \"%s\" file). For a reminder of what has been set, " "try: SELECT name, setting FROM pg_settings WHERE name LIKE" " 'pljava.%%' AND source = 'session'", buf.data, superuser() ? PG_GETCONFIGOPTION("config_file") : "postgresql.conf")))); #undef MOREHINT if ( loadAsExtensionFailed ) { ereport(NOTICE, (errmsg( "PL/Java load successful after failed CREATE EXTENSION"), errdetail( "PL/Java is now installed, but not as an extension."), errhint( "To correct that, either COMMIT or ROLLBACK, make sure " "the working settings are saved, exit this session, and " "in a new session, either: " "1. if committed, run " "\"CREATE EXTENSION pljava FROM unpackaged\", or 2. " "if rolled back, simply \"CREATE EXTENSION pljava\" again." ))); } } return; default: ereport(ERROR, ( errmsg("cannot set up PL/Java"), errdetail( "An unexpected stage was reached in the startup sequence."), errhint( "Please report the circumstances to the PL/Java maintainers.") )); } check_tolerant: if ( pljavaLoadingAsExtension ) { tolerant = false; loadAsExtensionFailed = true; pljavaLoadingAsExtension = false; } if ( !tolerant ) { ereport(ERROR, ( errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg( "cannot use PL/Java before successfully completing its setup"), errhint( "Check the log for messages closely preceding this one, " "detailing what step of setup failed and what will be needed, " "probably setting one of the \"pljava.\" configuration " "variables, to complete the setup. If there is not enough " "help in the log, try again with different settings for " "\"log_min_messages\" or \"log_error_verbosity\"."))); } }
OSStatus MRJSession::open(const char* consolePath) { // Use vanilla JNI invocation API to fire up a fresh JVM. string classPath = getClassPath(); string pluginHome = getPluginHome(); JavaVMOption theOptions[] = { { (char*) classPath.c_str() }, { (char*) pluginHome.c_str() }, #if REDIRECT_VFPRINTF { "vfprintf", NewMachOFunctionPointer(&java_vfprintf) } #endif }; JavaVMInitArgs theInitArgs = { JNI_VERSION_1_2, sizeof(theOptions) / sizeof(JavaVMOption), theOptions, JNI_TRUE }; mStatus = ::JNI_CreateJavaVM(&mJavaVM, (void**) &mMainEnv, &theInitArgs); if (mStatus == noErr) { // create a monitor for the message queue to unblock Java threads. mMessageMonitor = new MRJMonitor(this); } JNIEnv* env = mMainEnv; jclass session = env->FindClass("netscape/oji/MRJSession"); if (session) { mSession = (jclass) env->NewGlobalRef(session); jmethodID openMethod = env->GetStaticMethodID(session, "open", "(Ljava/lang/String;)V"); if (openMethod) { jstring path = env->NewStringUTF(consolePath); if (path) { env->CallStaticVoidMethod(session, openMethod, path); if (env->ExceptionCheck()) env->ExceptionClear(); env->DeleteLocalRef(path); } } else { env->ExceptionClear(); } env->DeleteLocalRef(session); } else { env->ExceptionClear(); } if (mStatus == noErr) theSession = this; #if REDIRECT_VFPRINTF // XXX test the vfprintf function. jclass notThere = env->FindClass("class/not/Found"); if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); } #endif return mStatus; }
void JVM::jvmStartup(QString libname) { QLibrary lib (libname); cjvm_fn fn = (cjvm_fn) lib.resolve("JNI_CreateJavaVM"); qDebug() << "libjvm found in" << libname; setSettingsValue("extensions/jvm_path", libname); if (!fn) { Logger::global()->enterLogMessage("JPlugin", QObject::tr("Failed to load the correct libjvm: %1").arg(lib.errorString())); return; } jint res; JavaVMInitArgs vm_args; #ifdef DEBUG_BUILD JavaVMOption options[9]; #else JavaVMOption options[7]; #endif JNIEnv* env; QByteArray classpath = getClassPath().toUtf8(); int mb = getSettingsValue("java/maxheap").toInt(); if (!mb) mb = 16; classpath.prepend("-Djava.class.path="); qDebug() << "Java Classpath set to" << classpath; options[0].optionString = classpath.data(); options[1].optionString = static_cast<char*>(alloca(24)); snprintf(options[1].optionString, 24, "-Xmx%dm", mb); options[2].optionString = const_cast<char*>("-Djava.security.manager"); options[3].optionString = const_cast<char*>("-Djava.security.policy=" DATA_LOCATION "/data/java/extension.policy"); options[4].optionString = const_cast<char*>("-XX:+UseParNewGC"); options[5].optionString = const_cast<char*>("-XX:MinHeapFreeRatio=5"); options[6].optionString = const_cast<char*>("-XX:MaxHeapFreeRatio=10"); #ifdef DEBUG_BUILD options[7].optionString = const_cast<char*>("-Xdebug"); options[8].optionString = const_cast<char*>("-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8222"); #endif vm_args.version = 0x00010006; vm_args.options = options; vm_args.nOptions = sizeof(options)/sizeof(options[0]); vm_args.ignoreUnrecognized = JNI_TRUE; res = fn(&m_jvm, (void**)&env, &vm_args); if (res < 0) { Logger::global()->enterLogMessage("JPlugin", QObject::tr("Failed to create a Java VM")); return; } JNIEnv** penv = new JNIEnv*; *penv = env; m_env.setLocalData(penv); if (!m_instance) m_instance = this; try { singleCObjectRegisterNatives(); JSettings::registerNatives(); JPlugin::registerNatives(); JTransferPlugin::registerNatives(); JDownloadPlugin::registerNatives(); JBackgroundWorker::registerNatives(); JAccountStatusPlugin::registerNatives(); } catch (...) { qDebug() << "Failed to register JNI functions. This usually happens when there is an API discrepancy between the Java and the native code.\nPlease, remove ~/.local/share/fatrat/data/java/libs/fatrat-jplugins-core.jar, and try again"; abort(); } }
bool ScriptablePluginObject::Invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result) /* name : method name args : arguments argCount : number of arguments result : return value */ { NPIdentifier test_id = NPN_GetStringIdentifier("test"); if (name == test_id) { printf("temp = %s\n",getTemporaryPath()); printf("home = %s\n",getHomePath()); printf("firefox = %s\n",getFirefoxPath()); printf("conf = %s\n",getConfPath()); printf("classpath = %s\n",getClassPath()); printf("spawn = %s\n",getSpawnPath()); VOID_TO_NPVARIANT(*result); return true; } NPError err; if (!this->HasMethod(name)) return false; VOID_TO_NPVARIANT(*result); //login.jsp test NPIdentifier doSignature_id = NPN_GetStringIdentifier("doSignature"); NPIdentifier getPublicKeyContent_id = NPN_GetStringIdentifier("getPublicKeyContent"); NPObject* sWindowNPObj; if ((err = NPN_GetValue(mNpp, NPNVWindowNPObject, &sWindowNPObj)) != NPERR_NO_ERROR) { printf("Error in getting NPNVWindowNPObject: %d\n",err); return false; } const char *tmpdir = getTemporaryPath(); const char *classpath = getClassPath(); const char *spawnpath = getSpawnPath(); if (name == doSignature_id) { if ((argCount == 2) && (NPVARIANT_IS_STRING(args[0])) && (NPVARIANT_IS_STRING(args[1]))) { char *randomStr = NULL; char *tpmPass = NULL; NPString n_randomStr = NPVARIANT_TO_STRING(args[0]); NPString n_tpmPass = NPVARIANT_TO_STRING(args[1]); m_strFromNP(&randomStr,n_randomStr); m_strFromNP(&tpmPass,n_tpmPass); printf("input = %s, %s",randomStr, tpmPass); char* ret = NULL; char *fname = tempnam(tmpdir,"jni"); if (fname == NULL) fname = "tmp"; char* margs[12]; margs[0] = (char*) spawn_file; margs[1] = "--file"; margs[2] = fname; margs[3] = "--method"; margs[4] = "doSignature"; margs[5] = "--classpath"; margs[6] = (char*) classpath; margs[7] = "--args"; margs[8] = "2"; margs[9] = randomStr; margs[10] = tpmPass; margs[11] = NULL; // in windows use registry to find Firefox directory // in other OS, use path _spawnvp int rval = _spawnv(_P_WAIT,spawnpath,margs); if (rval) { fprintf(stderr,"error = %d\n",rval); } else { ret = getFileContent(fname); if (ret) { STRINGZ_TO_NPVARIANT(ret,*result); } else { fprintf(stderr,"cannot read output file"); } unlink(fname); } free(fname); } else { NPString str; str.UTF8Characters = "alert('usage: doSignature(String, String)');"; str.UTF8Length = strlen(str.UTF8Characters); NPN_Evaluate(this->mNpp, sWindowNPObj, &str, NULL); } } else if (name == getPublicKeyContent_id) { if (argCount == 0) { char *ret = NULL; char *fname = tempnam(tmpdir,"jni"); if (fname == NULL) fname = "tmp"; char* margs[8]; margs[0] = (char*) spawn_file; margs[1] = "--file"; margs[2] = fname; margs[3] = "--method"; margs[4] = "getPublicKeyContent"; margs[5] = "--classpath"; margs[6] = (char*) classpath; margs[7] = NULL; int rval = _spawnv(_P_WAIT,spawnpath,margs); if (rval) { fprintf(stderr,"error = %d\n",rval); } else { ret = getFileContent(fname); if (ret) { STRINGZ_TO_NPVARIANT(ret,*result); } else { fprintf(stderr,"cannot read output file"); } unlink(fname); } free(fname); } else { NPString str; str.UTF8Characters = "alert('usage: getPublicKeyContent()');"; str.UTF8Length = strlen(str.UTF8Characters); NPN_Evaluate(this->mNpp, sWindowNPObj, &str, NULL); } } NPN_ReleaseObject(sWindowNPObj); return true; }
bool SunJVMExe::run(const std::string& mainclass, bool useconsole) { if (!m_version.isValid()) { m_version = guessVersion(); } if (!m_version.isValid()) return false; std::vector<std::string> execv; execv.push_back(StringUtils::requoteForCommandLine(lookUpExecutable(useconsole))); if (m_vmParameter != "") { std::vector<std::string> vmParameter = StringUtils::split(m_vmParameter, " ", " ", false); for (std::vector<std::string>::iterator i=vmParameter.begin(); i != vmParameter.end(); i++) { execv.push_back(*i); } } if (m_maxHeap > 0) { if ((m_version.getMajor()==1)&&(m_version.getMinor()==1)) execv.push_back("-mx" + StringUtils::toString(m_maxHeap)); else execv.push_back("-Xmx" + StringUtils::toString(m_maxHeap)); } if (m_initialHeap > 0) { if ((m_version.getMajor()==1)&&(m_version.getMinor()==1)) execv.push_back("-ms" + StringUtils::toString(m_initialHeap)); else execv.push_back("-Xms" + StringUtils::toString(m_initialHeap)); } for (int i=0; i<m_properties.size(); i++) if(m_properties[i].getName()[0]=='-') { execv.push_back( StringUtils::requoteForCommandLine(m_properties[i].getName())); } else { execv.push_back( StringUtils::requoteForCommandLine("-D" + m_properties[i].getName()) + "=" + StringUtils::requoteForCommandLine(m_properties[i].getValue())); } std::string classpath; if ((m_version.getMajor()==1)&&(m_version.getMinor()==1)) classpath = getClassPath(true); else classpath = getClassPath(false); if (classpath.size() > 0) execv.push_back("-classpath " + StringUtils::requoteForCommandLine(classpath)); execv.push_back(mainclass); for (int i=0; i<m_arguments.size(); i++) { execv.push_back( StringUtils::requoteForCommandLine(m_arguments[i]) ); } std::string execmd = StringUtils::join(execv, " "); DEBUG("COMMAND: <" + execmd + ">"); Process proc(execmd, useconsole); if (proc.run()) { DEBUG("Started successfully"); proc.join(); m_exitCode = proc.getExitCode(); return true; } else { DEBUG("Failed running " + execmd); } return false; }