diff --git a/harness/apisupport.harness/windows-launcher-src/Makefile.mingw b/harness/apisupport.harness/windows-launcher-src/Makefile.mingw new file mode 100644 index 000000000000..866b30dd1e54 --- /dev/null +++ b/harness/apisupport.harness/windows-launcher-src/Makefile.mingw @@ -0,0 +1,41 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +TMPFLD = ../../../../target/tmp/ +OFLD = ../../../../target/harness/ + +all: prepfolder app64.exe app.exe + +prepfolder: + mkdir -p $(TMPFLD) + mkdir -p $(OFLD) + +clean: + rm -f *.res *.exe + +app64.res: app.rc app.exe.manifest + x86_64-w64-mingw32-windres -o$(TMPFLD)app64.res -Ocoff -DMANIFEST_FILE=app.exe.manifest app.rc + +app64.exe: app.cpp applauncher.cpp app64.res ../bootstrap/utilsfuncs.cpp + x86_64-w64-mingw32-gcc -s -DNBEXEC_DLL='"/lib/nbexec64.dll"' -DARCHITECTURE=64 -Wl,--nxcompat -Wl,--dynamicbase -Wl,--no-seh app.cpp -mwindows applauncher.cpp $(TMPFLD)app64.res ../bootstrap/utilsfuncs.cpp ../ide/nblauncher.cpp -I ../bootstrap/ -o$(OFLD)app64.exe -static -lstdc++ -static-libstdc++ -static-libgcc + +app.res: app.rc app.exe.manifest + i686-w64-mingw32-windres -o$(TMPFLD)app.res -Ocoff -DMANIFEST_FILE=app.exe.manifest app.rc + +app.exe: app.cpp applauncher.cpp app.res ../bootstrap/utilsfuncs.cpp + i686-w64-mingw32-gcc -s -DNBEXEC_DLL='"/lib/nbexec.dll"' -DARCHITECTURE=32 -Wl,--nxcompat -Wl,--dynamicbase -Wl,--no-seh -mwindows app.cpp applauncher.cpp $(TMPFLD)app.res ../bootstrap/utilsfuncs.cpp ../ide/nblauncher.cpp -I ../bootstrap/ -o$(OFLD)app.exe -static -lstdc++ -static-libstdc++ -static-libgcc + diff --git a/harness/apisupport.harness/windows-launcher-src/app.cpp b/harness/apisupport.harness/windows-launcher-src/app.cpp new file mode 100644 index 000000000000..840c8285e06e --- /dev/null +++ b/harness/apisupport.harness/windows-launcher-src/app.cpp @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + + +#include "applauncher.h" + +int main(int argc, char *argv[]) { + AppLauncher launcher; + return launcher.start(argc - 1, argv + 1); +} diff --git a/harness/apisupport.harness/windows-launcher-src/app.exe.manifest b/harness/apisupport.harness/windows-launcher-src/app.exe.manifest new file mode 100644 index 000000000000..c1843b229a94 --- /dev/null +++ b/harness/apisupport.harness/windows-launcher-src/app.exe.manifest @@ -0,0 +1,75 @@ + + + + + +NBP application process + + + + + + + + + + + + + + + + + UTF-8 + + + + + + true/PM + PerMonitorV2, PerMonitor, system + + + + + + + + + + + + + diff --git a/harness/apisupport.harness/windows-launcher-src/app.ico b/harness/apisupport.harness/windows-launcher-src/app.ico new file mode 100644 index 000000000000..294cd704d198 Binary files /dev/null and b/harness/apisupport.harness/windows-launcher-src/app.ico differ diff --git a/harness/apisupport.harness/windows-launcher-src/app.rc b/harness/apisupport.harness/windows-launcher-src/app.rc new file mode 100644 index 000000000000..d52211e464c6 --- /dev/null +++ b/harness/apisupport.harness/windows-launcher-src/app.rc @@ -0,0 +1,26 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. + +#include + +100 ICON "app.ico" + +// Value MANIFEST_FILE id taken from windres parameter -DMANIFEST_FILE +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST MANIFEST_FILE diff --git a/harness/apisupport.harness/windows-launcher-src/applauncher.cpp b/harness/apisupport.harness/windows-launcher-src/applauncher.cpp new file mode 100644 index 000000000000..1fa9d4ee8165 --- /dev/null +++ b/harness/apisupport.harness/windows-launcher-src/applauncher.cpp @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + +#include "applauncher.h" +#include "../bootstrap/utilsfuncs.h" +#include "../bootstrap/argnames.h" + +using namespace std; + +const char *AppLauncher::OPT_DEFAULT_USER_DIR = "default_userdir="; +const char *AppLauncher::OPT_DEFAULT_CACHE_DIR = "default_cachedir="; +const char *AppLauncher::OPT_DEFAULT_OPTIONS = "default_options="; +const char *AppLauncher::OPT_EXTRA_CLUSTERS = "extra_clusters="; +const char *AppLauncher::OPT_JDK_HOME = "jdkhome="; +const char *AppLauncher::APPNAME_TOKEN = "${APPNAME}"; +const char *AppLauncher::CACHE_SUFFIX = "\\Cache\\"; + +AppLauncher::AppLauncher() { +} + +AppLauncher::AppLauncher(const AppLauncher& orig) { +} + +AppLauncher::~AppLauncher() { +} + +bool AppLauncher::initBaseNames() { + if (!NbLauncher::initBaseNames()) { + return false; + } + + string pattern = baseDir + "\\platform*"; + WIN32_FIND_DATA fd = {0}; + HANDLE hFind; + hFind = FindFirstFile(pattern.c_str(), &fd); + if (hFind == INVALID_HANDLE_VALUE) { + logErr(false, true, "Cannot find 'platform*' folder!"); + return false; + } + + do { + if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + && fileExists((baseDir + '\\' + fd.cFileName + NbLauncher::NBEXEC_FILE_PATH).c_str())) { + platformDir = baseDir + '\\' + fd.cFileName; + break; + } + } while (FindNextFile(hFind, &fd)); + + FindClose(hFind); + + if (platformDir.empty()) { + logErr(false, true, "Cannot find valid 'platform*' folder!"); + return false; + } + return true; +} + +bool AppLauncher::findUserDir(const char *str) { + logMsg("AppLauncher::findUserDir()"); + if (!NbLauncher::findUserDir(str)) { // will set userDir and possibly userHome. + return false; + } + int pos = userDir.find(APPNAME_TOKEN); + if (pos != string::npos) { + userDir.replace(pos, strlen(APPNAME_TOKEN), appName); + } + return true; +} + +bool AppLauncher::findCacheDir(const char *str) { + logMsg("AppLauncher::findCacheDir"); + if (!NbLauncher::findCacheDir(str)) { // will set userDir and possibly userHome. + return false; + } + int pos = cacheDir.find(APPNAME_TOKEN); + if (pos != string::npos) { + cacheDir.replace(pos, strlen(APPNAME_TOKEN), appName); + } + return true; +} + +const char * AppLauncher::getAppName() { + return appName.c_str(); +} + +void AppLauncher::addSpecificOptions(CmdArgs &args) { +} + +void AppLauncher::adjustHeapSize() { +} + +const char * AppLauncher::getDefUserDirOptName() { + return OPT_DEFAULT_USER_DIR; +} + +const char * AppLauncher::getDefCacheDirOptName() { + return OPT_DEFAULT_CACHE_DIR; +} + +const char * AppLauncher::getDefOptionsOptName() { + return OPT_DEFAULT_OPTIONS; +} + +const char * AppLauncher::getExtraClustersOptName() { + return OPT_EXTRA_CLUSTERS; +} + +const char * AppLauncher::getJdkHomeOptName() { + return OPT_JDK_HOME; +} + +const char * AppLauncher::getCurrentDir() { + return baseDir.c_str(); +} + +std::string AppLauncher::constructApplicationDir(const std::string& dir, bool cache) { + if (cache) { + return dir + "\\" + getAppName() + CACHE_SUFFIX; + } else { + return dir + "\\" + getAppName() + "\\"; + } +} diff --git a/harness/apisupport.harness/windows-launcher-src/applauncher.h b/harness/apisupport.harness/windows-launcher-src/applauncher.h new file mode 100644 index 000000000000..b6002fd95b7b --- /dev/null +++ b/harness/apisupport.harness/windows-launcher-src/applauncher.h @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + +#ifndef _APPLAUNCHER_H +#define _APPLAUNCHER_H + +#include +#include + +#include "shlobj.h" +#include "../ide/nblauncher.h" + +class AppLauncher : public NbLauncher { + + static const char *OPT_DEFAULT_USER_DIR; + static const char *OPT_DEFAULT_CACHE_DIR; + static const char *OPT_DEFAULT_OPTIONS; + static const char *OPT_EXTRA_CLUSTERS; + static const char *OPT_JDK_HOME; + static const char *APPNAME_TOKEN; + static const char *REG_APPDATA_NAME; + static const char *CACHE_SUFFIX; + +public: + AppLauncher(); + virtual ~AppLauncher(); + +protected: + virtual bool initBaseNames(); + virtual const char * getAppName(); + virtual void addSpecificOptions(CmdArgs &args); + virtual void adjustHeapSize(); + virtual bool findUserDir(const char *str); + virtual bool findCacheDir(const char *str); + virtual const char * getDefUserDirOptName(); + virtual const char * getDefCacheDirOptName(); + virtual const char * getDefOptionsOptName(); + virtual const char * getExtraClustersOptName(); + virtual const char * getJdkHomeOptName(); + virtual const char * getCurrentDir(); + virtual std::string constructApplicationDir(const std::string& dir, bool cache); + +private: + AppLauncher(const AppLauncher& orig); +}; + +#endif /* _NBLAUNCHER_H */ + diff --git a/nb/ide.launcher/windows/Makefile.mingw b/nb/ide.launcher/windows/Makefile.mingw new file mode 100644 index 000000000000..6db2f87fc281 --- /dev/null +++ b/nb/ide.launcher/windows/Makefile.mingw @@ -0,0 +1,40 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +TMPFLD = ../../../../target/tmp/ +OFLD = ../../../../target/ide/ + +all: prepfolder netbeans64.exe netbeans.exe + +prepfolder: + mkdir -p $(TMPFLD) + mkdir -p $(OFLD) + +clean: + rm -f *.res *.exe + +netbeans64.res: netbeans.rc netbeans64.exe.manifest + x86_64-w64-mingw32-windres -o$(TMPFLD)netbeans64.res -Ocoff -DMANIFEST_FILE=netbeans64.exe.manifest netbeans.rc + +netbeans64.exe: netbeans.cpp nblauncher.cpp netbeans64.res ../bootstrap/utilsfuncs.cpp + x86_64-w64-mingw32-gcc -s -DNBEXEC_DLL='"/lib/nbexec64.dll"' -DARCHITECTURE=64 -Wl,--nxcompat -Wl,--dynamicbase -Wl,--no-seh -mwindows netbeans.cpp nblauncher.cpp $(TMPFLD)netbeans64.res ../bootstrap/utilsfuncs.cpp -I ../bootstrap/ -o$(OFLD)netbeans64.exe -static -lstdc++ -static-libstdc++ -static-libgcc + +netbeans.res: netbeans.rc netbeans.exe.manifest + i686-w64-mingw32-windres -o$(TMPFLD)netbeans.res -Ocoff -DMANIFEST_FILE=netbeans.exe.manifest netbeans.rc + +netbeans.exe: netbeans.cpp nblauncher.cpp netbeans.res ../bootstrap/utilsfuncs.cpp + i686-w64-mingw32-gcc -s -DNBEXEC_DLL='"/lib/nbexec.dll"' -DARCHITECTURE=32 -Wl,--nxcompat -Wl,--dynamicbase -Wl,--no-seh -mwindows netbeans.cpp nblauncher.cpp $(TMPFLD)netbeans.res ../bootstrap/utilsfuncs.cpp -I ../bootstrap/ -o$(OFLD)netbeans.exe -static -lstdc++ -static-libstdc++ -static-libgcc diff --git a/nb/ide.launcher/windows/cmdargs.h b/nb/ide.launcher/windows/cmdargs.h new file mode 100644 index 000000000000..acf56a411e79 --- /dev/null +++ b/nb/ide.launcher/windows/cmdargs.h @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + +#ifndef _CMDARGS_H +#define _CMDARGS_H + +class CmdArgs { +public: + + CmdArgs(int _count) { + used = 0; + size = _count; + args = new char*[size]; + memset(args, 0, size * sizeof (char*)); + } + + ~CmdArgs() { + if (args) { + for (int i = 0; i < size; i++) { + delete[] args[i]; + } + delete[] args; + } + } + + void add(const char *arg) { + if (used + 1 > size) { + int newSize = size + size / 2 + 1; + char **newArgs = new char*[newSize]; + memcpy(newArgs, args, size * sizeof (char*)); + memset(newArgs + size, 0, (newSize - size) * sizeof (char*)); + delete[] args; + args = newArgs; + size = newSize; + } + args[used] = new char[strlen(arg) + 1]; + strcpy(args[used++], arg); + } + + void addCmdLine(const char *cmdLine) { + char arg[1024] = ""; + bool inQuotes = false; + bool inText = false; + int i = 0; + int j = 0; + char c; + while (c = cmdLine[i]) { + if (inQuotes) { + if (c == '\"') { + inQuotes = false; + } else { + arg[j++] = c; + } + } else { + switch (c) { + case '\"': + inQuotes = true; + inText = true; + break; + case ' ': + case '\t': + case '\n': + case '\r': + if (inText) { + arg[j] = '\0'; + add(arg); + j = 0; + } + inText = false; + break; + default: + inText = true; + arg[j++] = c; + break; + } + } + i++; + } + if (j > 0) { + arg[j] = '\0'; + add(arg); + } + } + + int getCount() { + return used; + } + + char **getArgs() { + return args; + } + +private: + int used; + int size; + char **args; +}; + +#endif /* _CMDARGS_H */ + diff --git a/nb/ide.launcher/windows/nblauncher.cpp b/nb/ide.launcher/windows/nblauncher.cpp new file mode 100644 index 000000000000..393e2cd81a27 --- /dev/null +++ b/nb/ide.launcher/windows/nblauncher.cpp @@ -0,0 +1,554 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x05010100 +#endif + +#include +#include +#include "nblauncher.h" +#include "../bootstrap/utilsfuncs.h" +#include "../bootstrap/argnames.h" +#include "../bootstrap/nbexecloader.h" + +using namespace std; + +const char *NbLauncher::NBEXEC_FILE_PATH = NBEXEC_DLL; +const char *NbLauncher::OPT_NB_DEFAULT_USER_DIR = "netbeans_default_userdir="; +const char *NbLauncher::OPT_NB_DEFAULT_CACHE_DIR = "netbeans_default_cachedir="; +const char *NbLauncher::OPT_NB_DEFAULT_OPTIONS = "netbeans_default_options="; +const char *NbLauncher::OPT_NB_EXTRA_CLUSTERS = "netbeans_extraclusters="; +const char *NbLauncher::OPT_NB_JDK_HOME = "netbeans_jdkhome="; +const char *NbLauncher::ENV_USER_PROFILE = "USERPROFILE"; +const char *NbLauncher::HOME_TOKEN = "${HOME}"; +const char *NbLauncher::DEFAULT_USERDIR_ROOT_TOKEN = "${DEFAULT_USERDIR_ROOT}"; +const char *NbLauncher::DEFAULT_CACHEDIR_ROOT_TOKEN = "${DEFAULT_CACHEDIR_ROOT}"; +const char *NbLauncher::NETBEANS_DIRECTORY = "\\NetBeans\\"; +const char *NbLauncher::NETBEANS_CACHES_DIRECTORY = "\\NetBeans\\Cache\\"; + +const char *NbLauncher::CON_ATTACH_MSG = +"\n\nThe launcher has determined that the parent process has a console and will reuse it for its own console output.\n" +"Closing the console will result in termination of the running program.\n" +"Use '--console suppress' to suppress console output.\n" +"Use '--console new' to create a separate console window.\n"; + +const char *NbLauncher::staticOptions[] = { + "-J-Dnetbeans.importclass=org.netbeans.upgrade.AutoUpgrade", + "--branding", + "nb" +}; + +NbLauncher::NbLauncher() { +} + +NbLauncher::NbLauncher(const NbLauncher& orig) { +} + +NbLauncher::~NbLauncher() { +} + +int NbLauncher::start(char *cmdLine) { + CmdArgs args(50); + args.addCmdLine(cmdLine); + return start(args.getCount(), args.getArgs()); +} + +int NbLauncher::start(int argc, char *argv[]) { + SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); + + DWORD parentProcID = 0; + if (!checkLoggingArg(argc, argv, true) || !setupProcess(argc, argv, parentProcID, CON_ATTACH_MSG) || !initBaseNames() || !readClusterFile()) { + return -1; + } + + parseConfigFile((baseDir + "\\etc\\" + getAppName() + ".conf").c_str()); + + if (!parseArgs(argc, argv)) { + return -1; + } + string oldUserDir = userDir; + parseConfigFile((userDir + "\\etc\\" + getAppName() + ".conf").c_str()); + userDir = oldUserDir; + + addExtraClusters(); + string nbexecPath; + SetDllDirectory(baseDir.c_str()); + if (dirExists(platformDir.c_str())) { + nbexecPath = platformDir; + } else { + nbexecPath = baseDir + '\\' + platformDir; + } + if (!dirExists(nbexecPath.c_str())) { + logErr(false, true, "Could not find platform cluster:\n%s", nbexecPath.c_str()); + return false; + } + + CmdArgs newArgs(argc + 20); + addSpecificOptions(newArgs); + + if (!clusters.empty()) { + newArgs.add(ARG_NAME_CLUSTERS); + newArgs.add(clusters.c_str()); + } + if (!userDir.empty()) { + newArgs.add(ARG_NAME_USER_DIR); + newArgs.add(userDir.c_str()); + } + if (!defUserDirRoot.empty()) { + newArgs.add(ARG_DEFAULT_USER_DIR_ROOT); + newArgs.add(defUserDirRoot.c_str()); + } + if (!cacheDir.empty() && !customUserDirFound) { + newArgs.add(ARG_NAME_CACHE_DIR); + newArgs.add(cacheDir.c_str()); + } + if (!nbOptions.empty()) { + newArgs.addCmdLine(nbOptions.c_str()); + } + for (int i = 0; i < argc; i++) { + newArgs.add(argv[i]); + } + if (!jdkHome.empty()) { + newArgs.add(ARG_NAME_JDKHOME); + newArgs.add(jdkHome.c_str()); + } + if (parentProcID) { + newArgs.add(ARG_NAME_LA_PPID); + char tmp[16] = ""; + newArgs.add(itoa(parentProcID, tmp, 10)); + } + nbexecPath += NBEXEC_FILE_PATH; + + const char *curDir = getCurrentDir(); + if (curDir) { + char olddir[MAX_PATH]; + DWORD rc = GetCurrentDirectory(MAX_PATH, olddir); + if (rc == 0) { + logErr(true, false, "Failed to get current directory"); + } else { + string od = string(olddir); + od.insert(0, "-J-Dnetbeans.user.dir="); + newArgs.add(od.c_str()); + } + logMsg("Changing current directory to: \"%s\"", curDir); + SetCurrentDirectory(curDir); + } + + NBExecLoader loader; + return loader.start(nbexecPath.c_str(), newArgs.getCount(), newArgs.getArgs()); +} + +UINT GetAnsiCodePageForLocale(LCID lcid) { + // See https://devblogs.microsoft.com/oldnewthing/20161007-00/?p=94475 + UINT acp; + int sizeInChars = sizeof(acp) / sizeof(TCHAR); + if (GetLocaleInfo(lcid, + LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, + reinterpret_cast(&acp), + sizeInChars) != sizeInChars) + { + return 0; + } + return acp; +} + +bool NbLauncher::initBaseNames() { + char path[MAX_PATH] = ""; + getCurrentModulePath(path, MAX_PATH); + logMsg("Executable: %s", path); + char *bslash = strrchr(path, '\\'); + if (!bslash) { + return false; + } + appName = bslash + 1; + appName.erase(appName.rfind('.')); + + if (ARCHITECTURE == 64) { + appName = appName.erase(appName.length() - 2); + } + + logMsg("Application name: %s", appName.c_str()); + + *bslash = '\0'; + bslash = strrchr(path, '\\'); + if (!bslash) { + return false; + } + *bslash = '\0'; + + /* Useful messages for debugging character set issues. On Java versions where + https://bugs.openjdk.org/browse/JDK-8272352 has been fixed, NetBeans should now run fine when + there are Unicode characters in the NetBeans installation path, the JDK path, the user/cache + directory paths, or in the java.io.tmpdir path (the latter sometimes being a problem for JNA, + which is used by FlatLAF). Since the JVM is started in-process via JNI, the Java environment + will inherit the UTF-8 code page setting that we have set in the launcher's application + manifest, without requiring the user to change regional settings in the Control Panel. (JEP 400 + might eventually do something similar for the java.exe/javaw.exe executables. See + https://www.mail-archive.com/core-libs-dev@openjdk.java.net/msg80489.html .) */ + logMsg("ANSI code page per GetACP() : %d", GetACP()); + logMsg("ANSI code page per GetConsoleCP() : %d", GetConsoleCP()); + logMsg("ANSI code page for GetThreadLocale() : %d", GetAnsiCodePageForLocale(GetThreadLocale())); + logMsg("ANSI code page for GetUserDefaultLCID() : %d", GetAnsiCodePageForLocale(GetUserDefaultLCID())); + logMsg("ANSI code page for GetSystemDefaultLCID(): %d", GetAnsiCodePageForLocale(GetSystemDefaultLCID())); + + baseDir = path; + + logMsg("Base dir: %s", baseDir.c_str()); + return true; +} + +void NbLauncher::addCluster(const char *cluster) { + + class SetCurDir { + public: + SetCurDir(const char *dir) { + oldCurDir[0] = '\0'; + DWORD rc = GetCurrentDirectory(MAX_PATH, oldCurDir); + if (rc == 0) { + logErr(true, false, "Failed to get current directory"); + return; + } + if (rc > MAX_PATH) { + logMsg("Failed to get current directory, buffer is too small."); + return; + } + if (!SetCurrentDirectory(dir)) { + logErr(true, true, "Failed to set current directory to \"%s\"", dir); + oldCurDir[0] = '\0'; + } + } + + ~SetCurDir() { + if (oldCurDir[0]) { + if (!SetCurrentDirectory(oldCurDir)) { + logErr(true, true, "Failed to set current directory to \"%s\"", oldCurDir); + } + } + } + private: + char oldCurDir[MAX_PATH]; + }; + + logMsg("addCluster: %s", cluster); + SetCurDir setCurDir(baseDir.c_str()); + char clusterPath[MAX_PATH + 1] = {0}; + strncpy(clusterPath, cluster, MAX_PATH); + if (!normalizePath(clusterPath, MAX_PATH)) { + logMsg("Invalid cluster path: %s", cluster); + return; + } + if (!clusters.empty()) { + clusters += ';'; + } + logMsg("Adding cluster %s", clusterPath); + clusters += clusterPath; +} + +void NbLauncher::addExtraClusters() { + logMsg("addExtraClusters()"); + const char delim = ';'; + string::size_type start = extraClusters.find_first_not_of(delim, 0); + string::size_type end = extraClusters.find_first_of(delim, start); + while (string::npos != end || string::npos != start) { + string cluster = extraClusters.substr(start, end - start); + addCluster(cluster.c_str()); + start = extraClusters.find_first_not_of(delim, end); + end = extraClusters.find_first_of(delim, start); + } +} + +bool NbLauncher::readClusterFile() { + clusters = ""; + string clusterFile = baseDir + "\\etc\\" + getAppName() + ".clusters"; + logMsg("readClusterFile() file: %s", clusterFile.c_str()); + + FILE* file = fopen(clusterFile.c_str(), "r"); + if (!file) { + logErr(true, true, "Cannot open file \"%s\" for reading.", clusterFile.c_str()); + return false; + } + + char line[4096] = ""; + while (fgets(line, sizeof(line), file)) { + char *str = skipWhitespaces(line); + if (*str == '#' || *str == '\0') { + continue; + } + char *pc = str; + while (*pc != '\0' && *pc != '\t' && *pc != '\n' && *pc != '\r') { + pc++; + } + *pc = '\0'; + + if (platformDir.empty()) { + char *slash = strrchr(str, '\\'); + if (!slash) { + slash = strrchr(str, '/'); + } + char *dir = slash ? slash + 1 : str; + if (strncmp(dir, "platform", strlen("platform")) == 0) { + platformDir = str; + } else { + addCluster(str); + } + } else { + addCluster(str); + } + } + bool ok = ferror(file) == 0; + if (!ok) { + logErr(true, true, "Error while reading file \"%s\".", clusterFile.c_str()); + } + fclose(file); + return ok; +} + +bool NbLauncher::parseArgs(int argc, char *argv[]) { +#define CHECK_ARG \ + if (i+1 == argc) {\ + logErr(false, true, "Argument is missing for \"%s\" option.", argv[i]);\ + return false;\ + } + + logMsg("parseArgs():"); + for (int i = 0; i < argc; i++) { + logMsg("\t%s", argv[i]); + } + customUserDirFound = 0; + for (int i = 0; i < argc; i++) { + if (strcmp(ARG_NAME_USER_DIR, argv[i]) == 0) { + CHECK_ARG; + char tmp[MAX_PATH + 1] = {0}; + strncpy(tmp, argv[++i], MAX_PATH); + if (!normalizePath(tmp, MAX_PATH)) { + logErr(false, true, "User directory path \"%s\" is not valid.", argv[i]); + return false; + } + customUserDirFound = 1; + userDir = tmp; + logMsg("User dir: %s", userDir.c_str()); + } + if (strcmp(ARG_NAME_CACHE_DIR, argv[i]) == 0) { + CHECK_ARG; + char tmp[MAX_PATH + 1] = {0}; + strncpy(tmp, argv[++i], MAX_PATH); + if (!normalizePath(tmp, MAX_PATH)) { + logErr(false, true, "Cache directory path \"%s\" is not valid.", argv[i]); + return false; + } + cacheDir = tmp; + logMsg("Cache dir: %s", cacheDir.c_str()); + } + } + logMsg("parseArgs() finished"); + return true; +} + +bool NbLauncher::findUserDir(const char *str) { + logMsg("NbLauncher::findUserDir()"); + if (strncmp(str, HOME_TOKEN, strlen(HOME_TOKEN)) == 0) { + if (userHome.empty()) { + char *userProfile = getenv(ENV_USER_PROFILE); + if (userProfile) { + userHome = userProfile; + } else { + TCHAR userHomeChar[MAX_PATH]; + if (FAILED(SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, 0, userHomeChar))) { + return false; + } + userHome = userHomeChar; + userHome.erase(userHome.rfind('\\')); + } + logMsg("User home: %s", userHome.c_str()); + } + userDir = userHome + (str + strlen(HOME_TOKEN)); + } else if (strncmp(str, DEFAULT_USERDIR_ROOT_TOKEN, strlen(DEFAULT_USERDIR_ROOT_TOKEN)) == 0) { + std::string s = std::string("Replacing ") + DEFAULT_USERDIR_ROOT_TOKEN; + logMsg(s.c_str()); + userDir = getDefaultUserDirRoot() + (str + strlen(DEFAULT_USERDIR_ROOT_TOKEN)); + } else { + getDefaultUserDirRoot(); + userDir = str; + } + return true; +} + +bool NbLauncher::findCacheDir(const char *str) { + logMsg("NbLauncher::findCacheDir()"); + if (strncmp(str, HOME_TOKEN, strlen(HOME_TOKEN)) == 0) { + if (userHome.empty()) { + char *userProfile = getenv(ENV_USER_PROFILE); + if (userProfile) { + userHome = userProfile; + } else { + TCHAR userHomeChar[MAX_PATH]; + if (FAILED(SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, 0, userHomeChar))) { + return false; + } + userHome = userHomeChar; + userHome.erase(userHome.rfind('\\')); + } + logMsg("User home: %s", userHome.c_str()); + } + cacheDir = userHome + (str + strlen(HOME_TOKEN)); + } else if (strncmp(str, DEFAULT_CACHEDIR_ROOT_TOKEN, strlen(DEFAULT_CACHEDIR_ROOT_TOKEN)) == 0) { + std::string s = std::string("Replacing ") + DEFAULT_CACHEDIR_ROOT_TOKEN; + logMsg(s.c_str()); + cacheDir = getDefaultCacheDirRoot() + (str + strlen(DEFAULT_CACHEDIR_ROOT_TOKEN)); + } else { + getDefaultCacheDirRoot(); + cacheDir = str; + } + return true; +} + +string NbLauncher::getDefaultUserDirRoot() { + TCHAR defUserDirRootChar[MAX_PATH]; + if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, defUserDirRootChar))) { + return std::string(); + } + defUserDirRoot = constructApplicationDir((string) defUserDirRootChar, false); + defUserDirRoot.erase(defUserDirRoot.rfind('\\')); + logMsg("Default Userdir Root: %s", defUserDirRoot.c_str()); + return defUserDirRoot; +} + +string NbLauncher::getDefaultCacheDirRoot() { + TCHAR defCacheDirRootChar[MAX_PATH]; + if (FAILED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, defCacheDirRootChar))) { + return std::string(); + } + defCacheDirRoot = constructApplicationDir((string) defCacheDirRootChar, true); + defCacheDirRoot.erase(defCacheDirRoot.rfind('\\')); + logMsg("Default Cachedir Root: %s", defCacheDirRoot.c_str()); + return defCacheDirRoot; +} + +bool NbLauncher::getOption(char *&str, const char *opt) { + if (strncmp(str, opt, strlen(opt)) == 0) { + str += strlen(opt); + char *end = trimWhitespaces(str); + if (*str == '"') { + str++; + } + if (end >= str && *end == '"') { + *end = '\0'; + } + logMsg("Option found: %s%s", opt, str); + return true; + } + return false; +} + +bool NbLauncher::parseConfigFile(const char* path) { + logMsg("parseConfigFile(%s)", path); + FILE *file = fopen(path, "r"); + if (!file) { + logErr(true, false, "Cannot open file \"%s\" for reading.", path); + return false; + } + + char line[4096] = ""; + while (fgets(line, sizeof(line), file)) { + char *str = skipWhitespaces(line); + if (*str == '#') { + continue; + } + if (getOption(str, getDefUserDirOptName())) { + findUserDir(str); + logMsg("User dir: %s", userDir.c_str()); + } else if (getOption(str, getDefCacheDirOptName())) { + findCacheDir(str); + logMsg("Cache dir: %s", cacheDir.c_str()); + } else if (getOption(str, getDefOptionsOptName())) { + // replace \" by " + int len = strlen(str); + int k = 0; + for (int i = 0; i < len; i++) { + if (str[i] == '\\' && str[i+1] == '\"') { + continue; + } + str[k++] = str[i]; + } + str[k] = '\0'; + nbOptions = str; + logMsg("After replacement: %s", nbOptions.c_str()); + + } else if (getOption(str, getExtraClustersOptName())) { + extraClusters = str; + } else if (getOption(str, getJdkHomeOptName())) { + jdkHome = str; + } + } + bool ok = ferror(file) == 0; + if (!ok) { + logErr(true, false, "Error while reading file \"%s\".", path); + } + fclose(file); + return true; +} + +typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); + +const char * NbLauncher::getAppName() { + return "netbeans"; +} + +void NbLauncher::addSpecificOptions(CmdArgs &args) { + for (unsigned i = 0; i < sizeof (staticOptions) / sizeof (char*); i++) { + args.add(staticOptions[i]); + } +} + +const char * NbLauncher::getDefUserDirOptName() { + return OPT_NB_DEFAULT_USER_DIR; +} + +const char * NbLauncher::getDefCacheDirOptName() { + return OPT_NB_DEFAULT_CACHE_DIR; +} + + +const char * NbLauncher::getDefOptionsOptName() { + return OPT_NB_DEFAULT_OPTIONS; +} + +const char * NbLauncher::getExtraClustersOptName() { + return OPT_NB_EXTRA_CLUSTERS; +} + +const char * NbLauncher::getJdkHomeOptName() { + return OPT_NB_JDK_HOME; +} + +const char * NbLauncher::getCurrentDir() { + return 0; +} + +std::string NbLauncher::constructApplicationDir(const std::string& dir, bool cache) { + if (cache) { + return dir + NETBEANS_CACHES_DIRECTORY; + } else { + return dir + NETBEANS_DIRECTORY; + } +} diff --git a/nb/ide.launcher/windows/nblauncher.h b/nb/ide.launcher/windows/nblauncher.h new file mode 100644 index 000000000000..469a21f4fa89 --- /dev/null +++ b/nb/ide.launcher/windows/nblauncher.h @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + +#ifndef _NBLAUNCHER_H +#define _NBLAUNCHER_H + +#include +#include +#include +#include "cmdargs.h" + +class NbLauncher { +protected: + static const char *NBEXEC_FILE_PATH; + static const char *OPT_NB_DEFAULT_USER_DIR; + static const char *OPT_NB_DEFAULT_CACHE_DIR; + static const char *OPT_NB_DEFAULT_OPTIONS; + static const char *OPT_NB_EXTRA_CLUSTERS; + static const char *OPT_NB_JDK_HOME; + static const char *REG_SHELL_FOLDERS_KEY; + static const char *HOME_TOKEN; + static const char *DEFAULT_USERDIR_ROOT_TOKEN; + static const char *DEFAULT_CACHEDIR_ROOT_TOKEN; + static const char *CON_ATTACH_MSG; + static const char *NETBEANS_DIRECTORY; + static const char *NETBEANS_CACHES_DIRECTORY; + +private: + static const char *ENV_USER_PROFILE; + static const char *REG_DESKTOP_NAME; + static const char *REG_DEFAULT_USERDIR_ROOT; + static const char *REG_DEFAULT_CACHEDIR_ROOT; + static const char* staticOptions[]; + + typedef int (*StartPlatform)(int argc, char *argv[]); + +public: + NbLauncher(); + virtual ~NbLauncher(); + + int start(int argc, char *argv[]); + int start(char *cmdLine); + +protected: + virtual bool initBaseNames(); + virtual void addSpecificOptions(CmdArgs &args); + virtual bool findUserDir(const char *str); + virtual bool findCacheDir(const char *str); + virtual const char * getAppName(); + virtual const char * getDefUserDirOptName(); + virtual const char * getDefCacheDirOptName(); + virtual const char * getDefOptionsOptName(); + virtual const char * getExtraClustersOptName(); + virtual const char * getJdkHomeOptName(); + virtual const char * getCurrentDir(); + virtual std::string constructApplicationDir(const std::string& dir, bool cache); + +private: + NbLauncher(const NbLauncher& orig); + bool readClusterFile(); + bool parseArgs(int argc, char *argv[]); + bool parseConfigFile(const char* path); + bool getOption(char *&str, const char *opt); + void addCluster(const char *cl); + void addExtraClusters(); + std::string getDefaultUserDirRoot(); + std::string getDefaultCacheDirRoot(); + +protected: + std::string baseDir; + std::string appName; + std::string platformDir; + std::string userHome; + std::string userDir; + std::string cacheDir; + std::string defUserDirRoot; + std::string defCacheDirRoot; + std::string clusters; + std::string extraClusters; + std::string nbOptions; + std::string jdkHome; + +private: + bool customUserDirFound; +}; + +#endif /* _NBLAUNCHER_H */ + diff --git a/nb/ide.launcher/windows/netbeans.cpp b/nb/ide.launcher/windows/netbeans.cpp new file mode 100644 index 000000000000..c14972f5d3e0 --- /dev/null +++ b/nb/ide.launcher/windows/netbeans.cpp @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + + +#include "nblauncher.h" + +int main(int argc, char *argv[]) { + NbLauncher launcher; + return launcher.start(argc - 1, argv + 1); +} diff --git a/nb/ide.launcher/windows/netbeans.exe.manifest b/nb/ide.launcher/windows/netbeans.exe.manifest new file mode 100644 index 000000000000..2dda7fb5081b --- /dev/null +++ b/nb/ide.launcher/windows/netbeans.exe.manifest @@ -0,0 +1,77 @@ + + + + + +NetBeans IDE process + + + + + + + + + + + + + + + + + UTF-8 + + + + + + + true/PM + PerMonitorV2, PerMonitor, system + + + + + + + + + + + + + diff --git a/nb/ide.launcher/windows/netbeans.ico b/nb/ide.launcher/windows/netbeans.ico new file mode 100644 index 000000000000..ec123c065723 Binary files /dev/null and b/nb/ide.launcher/windows/netbeans.ico differ diff --git a/nb/ide.launcher/windows/netbeans.rc b/nb/ide.launcher/windows/netbeans.rc new file mode 100644 index 000000000000..348a32085aba --- /dev/null +++ b/nb/ide.launcher/windows/netbeans.rc @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include + +#include "version.rc" + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. + +100 ICON "netbeans.ico" + +// Value MANIFEST_FILE id taken from windres parameter -DMANIFEST_FILE +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST MANIFEST_FILE + diff --git a/nb/ide.launcher/windows/netbeans64.exe.manifest b/nb/ide.launcher/windows/netbeans64.exe.manifest new file mode 100644 index 000000000000..b1d9a5f31d98 --- /dev/null +++ b/nb/ide.launcher/windows/netbeans64.exe.manifest @@ -0,0 +1,77 @@ + + + + + + +NetBeans IDE process + + + + + + + + + + + + + + + + + UTF-8 + + + + + + true/PM + PerMonitorV2, PerMonitor, system + + + + + + + + + + + + + diff --git a/nb/ide.launcher/windows/version.h b/nb/ide.launcher/windows/version.h new file mode 100644 index 000000000000..b1667b9caf7c --- /dev/null +++ b/nb/ide.launcher/windows/version.h @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#define COMPANY "" +#define COMPONENT "NetBeans IDE" +#define VER "12.5.0.0" +#define FVER 12,5,0,0 +#define BUILD_ID "28062021" +#define INTERNAL_NAME "netbeans" +#define COPYRIGHT "Based on Apache NetBeans from the Apache Software Foundation and is licensed under Apache License Version 2.0" +#define NAME "NetBeans IDE 12.5" + diff --git a/nb/ide.launcher/windows/version.rc b/nb/ide.launcher/windows/version.rc new file mode 100644 index 000000000000..0bb79bf4688a --- /dev/null +++ b/nb/ide.launcher/windows/version.rc @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include "version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION FVER + PRODUCTVERSION FVER + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + // FILEOS 0x4 is Win32, 0x40004 is Win32 NT only + FILEOS 0x4L + // FILETYPE should be 0x1 for .exe and 0x2 for .dll + FILETYPE 0x1 + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", COMPANY "\0" + VALUE "FileDescription", COMPONENT "\0" + VALUE "FileVersion", VER "\0" + VALUE "Full Version", BUILD_ID "\0" + VALUE "InternalName", INTERNAL_NAME "\0" + VALUE "LegalCopyright", COPYRIGHT "\0" + VALUE "ProductName", NAME "\0" + VALUE "ProductVersion", VER "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/platform/o.n.bootstrap/launcher/windows/Makefile.mingw b/platform/o.n.bootstrap/launcher/windows/Makefile.mingw new file mode 100644 index 000000000000..0fd8e394f75c --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/Makefile.mingw @@ -0,0 +1,52 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +TMPFLD = ../../../../target/tmp/ +OFLD = ../../../../target/bootstrap/ + +all: prepfolder nbexec64.dll nbexec64.exe nbexec.dll nbexec.exe + +prepfolder: + mkdir -p $(TMPFLD) + mkdir -p $(OFLD) + +clean: + rm -f *.res *.exe *.dll + +nbexec64.res: nbexec.rc + x86_64-w64-mingw32-windres -o$(TMPFLD)nbexec64.res -Ocoff nbexec.rc + +nbexec64.dll: include/jni.h include/jni_types.h jvmlauncher.cpp nbexec.cpp platformlauncher.cpp utilsfuncs.cpp nbexec64.res + x86_64-w64-mingw32-gcc -s -shared -m64 -o $(OFLD)nbexec64.dll -I include jvmlauncher.cpp nbexec.cpp platformlauncher.cpp utilsfuncs.cpp $(TMPFLD)nbexec64.res -Wl,--no-insert-timestamp -static -lstdc++ -static-libstdc++ -static-libgcc + +nbexec_exe64.res: nbexec_exe.rc nbexec.exe.manifest + x86_64-w64-mingw32-windres -o$(TMPFLD)nbexec_exe64.res -Ocoff -DMANIFEST_FILE=nbexec.exe.manifest nbexec_exe.rc + +nbexec64.exe: nbexecexe.cpp utilsfuncs.cpp nbexec_exe64.res + x86_64-w64-mingw32-gcc -s -DNBEXEC_DLL='"nbexec64.dll"' -DARCHITECTURE=64 -Wl,--nxcompat -Wl,--dynamicbase -Wl,--no-seh -Wl,--no-insert-timestamp -mwindows nbexecexe.cpp utilsfuncs.cpp $(TMPFLD)nbexec_exe64.res -o$(OFLD)nbexec64.exe -static -lstdc++ -static-libstdc++ -static-libgcc + +nbexec.res: nbexec.rc + i686-w64-mingw32-windres -o$(TMPFLD)nbexec.res -Ocoff nbexec.rc + +nbexec.dll: include/jni.h include/jni_types.h jvmlauncher.cpp nbexec.cpp platformlauncher.cpp utilsfuncs.cpp nbexec.res + i686-w64-mingw32-gcc -s -shared -o $(OFLD)nbexec.dll -I include jvmlauncher.cpp nbexec.cpp platformlauncher.cpp utilsfuncs.cpp $(TMPFLD)nbexec.res -static -Wl,--no-insert-timestamp -lstdc++ -static-libstdc++ -static-libgcc + +nbexec_exe.res: nbexec_exe.rc nbexec.exe.manifest + i686-w64-mingw32-windres -o$(TMPFLD)nbexec_exe.res -Ocoff -DMANIFEST_FILE=nbexec.exe.manifest nbexec_exe.rc + +nbexec.exe: nbexecexe.cpp utilsfuncs.cpp nbexec_exe.res + i686-w64-mingw32-gcc -s -DNBEXEC_DLL='"nbexec.dll"' -DARCHITECTURE=32 -Wl,--nxcompat -Wl,--dynamicbase -Wl,--no-seh -Wl,--no-insert-timestamp -mwindows nbexecexe.cpp utilsfuncs.cpp $(TMPFLD)nbexec_exe.res -o$(OFLD)nbexec.exe -static -lstdc++ -static-libstdc++ -static-libgcc diff --git a/platform/o.n.bootstrap/launcher/windows/argnames.h b/platform/o.n.bootstrap/launcher/windows/argnames.h new file mode 100644 index 000000000000..c4bdaba2353f --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/argnames.h @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _ARGNAMES_H +#define _ARGNAMES_H + +#define ARG_NAME_SEPAR_PROC "--fork-java" +#define ARG_NAME_CONSOLE "--console" +#define ARG_NAME_LAUNCHER_LOG "--trace" +#define ARG_NAME_LA_START_APP "--la_start_app" +#define ARG_NAME_LA_START_AU "--la_start_au" +#define ARG_NAME_LA_PPID "--la_ppid" +#define ARG_NAME_USER_DIR "--userdir" +#define ARG_DEFAULT_USER_DIR_ROOT "--default_userdir_root" +#define ARG_NAME_CACHE_DIR "--cachedir" +#define ARG_NAME_CLUSTERS "--clusters" +#define ARG_NAME_BOOTCLASS "--bootclass" +#define ARG_NAME_JDKHOME "--jdkhome" +#define ARG_NAME_CP_PREPEND "--cp:p" +#define ARG_NAME_CP_APPEND "--cp:a" +#define ARG_NAME_NOSPLASH "--nosplash" + + +#endif /* _ARGNAMES_H */ + diff --git a/platform/o.n.bootstrap/launcher/windows/include/README b/platform/o.n.bootstrap/launcher/windows/include/README new file mode 100644 index 000000000000..7641ada3b1fd --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/include/README @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +These header files originate in the Apache Harmony project, tag 5.0m12a. diff --git a/platform/o.n.bootstrap/launcher/windows/include/jni.h b/platform/o.n.bootstrap/launcher/windows/include/jni.h new file mode 100644 index 000000000000..16cf67b457b4 --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/include/jni.h @@ -0,0 +1,1838 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file + * This file describes the JNI interface as per the JNI + * specification 1.5 available from Sun + * + * See specification + * for details. + */ + +#ifndef _JNI_H_ +#define _JNI_H_ + +#include +#include +#include "jni_types.h" + +/* + * Supported JNI versions + */ +/** + * Constant which specifies JNI interface version 1.1 + */ +#define JNI_VERSION_1_1 0x00010001 +/** + * Constant which specifies JNI interface version 1.2 + */ +#define JNI_VERSION_1_2 0x00010002 +/** + * Constant which specifies JNI interface version 1.4 + */ +#define JNI_VERSION_1_4 0x00010004 + +/** + * JNI Native Method Interface table for use in C sources + * + * See specification + * for details + */ +struct JNINativeInterface_ { + void *reserved0; + void *reserved1; + void *reserved2; + void *reserved3; + + jint (JNICALL *GetVersion)(JNIEnv *env); + + jclass (JNICALL *DefineClass) + (JNIEnv *env, const char *name, jobject loader, const jbyte *buf, + jsize len); + jclass (JNICALL *FindClass) + (JNIEnv *env, const char *name); + + jmethodID (JNICALL *FromReflectedMethod) + (JNIEnv *env, jobject method); + jfieldID (JNICALL *FromReflectedField) + (JNIEnv *env, jobject field); + jobject (JNICALL *ToReflectedMethod) + (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic); + + jclass (JNICALL *GetSuperclass) + (JNIEnv *env, jclass sub); + jboolean (JNICALL *IsAssignableFrom) + (JNIEnv *env, jclass sub, jclass sup); + jobject (JNICALL *ToReflectedField) + (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic); + + jint (JNICALL *Throw) + (JNIEnv *env, jthrowable obj); + jint (JNICALL *ThrowNew) + (JNIEnv *env, jclass clazz, const char *msg); + jthrowable (JNICALL *ExceptionOccurred) + (JNIEnv *env); + void (JNICALL *ExceptionDescribe) + (JNIEnv *env); + void (JNICALL *ExceptionClear) + (JNIEnv *env); + void (JNICALL *FatalError) + (JNIEnv *env, const char *msg); + + jint (JNICALL *PushLocalFrame) + (JNIEnv *env, jint cap); + jobject (JNICALL *PopLocalFrame) + (JNIEnv *env, jobject res); + + jobject (JNICALL *NewGlobalRef) + (JNIEnv *env, jobject lobj); + void (JNICALL *DeleteGlobalRef) + (JNIEnv *env, jobject gref); + void (JNICALL *DeleteLocalRef) + (JNIEnv *env, jobject obj); + jboolean (JNICALL *IsSameObject) + (JNIEnv *env, jobject obj1, jobject obj2); + + jobject (JNICALL *NewLocalRef) + (JNIEnv *env, jobject ref); + jint (JNICALL *EnsureLocalCapacity) + (JNIEnv *env, jint); + + jobject (JNICALL *AllocObject) + (JNIEnv *env, jclass clazz); + jobject (JNICALL *NewObject) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *NewObjectV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jobject (JNICALL *NewObjectA) + (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args); + + jclass (JNICALL *GetObjectClass) + (JNIEnv *env, jobject obj); + jboolean (JNICALL *IsInstanceOf) + (JNIEnv *env, jobject obj, jclass clazz); + + jmethodID (JNICALL *GetMethodID) + (JNIEnv *env, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *CallObjectMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jobject (JNICALL *CallObjectMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jobject (JNICALL *CallObjectMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args); + + jboolean (JNICALL *CallBooleanMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jboolean (JNICALL *CallBooleanMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jboolean (JNICALL *CallBooleanMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args); + + jbyte (JNICALL *CallByteMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jbyte (JNICALL *CallByteMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jbyte (JNICALL *CallByteMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args); + + jchar (JNICALL *CallCharMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jchar (JNICALL *CallCharMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jchar (JNICALL *CallCharMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args); + + jshort (JNICALL *CallShortMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jshort (JNICALL *CallShortMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jshort (JNICALL *CallShortMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args); + + jint (JNICALL *CallIntMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jint (JNICALL *CallIntMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jint (JNICALL *CallIntMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args); + + jlong (JNICALL *CallLongMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jlong (JNICALL *CallLongMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jlong (JNICALL *CallLongMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args); + + jfloat (JNICALL *CallFloatMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jfloat (JNICALL *CallFloatMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jfloat (JNICALL *CallFloatMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args); + + jdouble (JNICALL *CallDoubleMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jdouble (JNICALL *CallDoubleMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jdouble (JNICALL *CallDoubleMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args); + + void (JNICALL *CallVoidMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + void (JNICALL *CallVoidMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + void (JNICALL *CallVoidMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args); + + jobject (JNICALL *CallNonvirtualObjectMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *CallNonvirtualObjectMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jobject (JNICALL *CallNonvirtualObjectMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + jvalue * args); + + jboolean (JNICALL *CallNonvirtualBooleanMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jboolean (JNICALL *CallNonvirtualBooleanMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jboolean (JNICALL *CallNonvirtualBooleanMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + jvalue * args); + + jbyte (JNICALL *CallNonvirtualByteMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jbyte (JNICALL *CallNonvirtualByteMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jbyte (JNICALL *CallNonvirtualByteMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + jvalue *args); + + jchar (JNICALL *CallNonvirtualCharMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jchar (JNICALL *CallNonvirtualCharMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jchar (JNICALL *CallNonvirtualCharMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + jvalue *args); + + jshort (JNICALL *CallNonvirtualShortMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jshort (JNICALL *CallNonvirtualShortMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jshort (JNICALL *CallNonvirtualShortMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + jvalue *args); + + jint (JNICALL *CallNonvirtualIntMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jint (JNICALL *CallNonvirtualIntMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jint (JNICALL *CallNonvirtualIntMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + jvalue *args); + + jlong (JNICALL *CallNonvirtualLongMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jlong (JNICALL *CallNonvirtualLongMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jlong (JNICALL *CallNonvirtualLongMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + jvalue *args); + + jfloat (JNICALL *CallNonvirtualFloatMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jfloat (JNICALL *CallNonvirtualFloatMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jfloat (JNICALL *CallNonvirtualFloatMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + jvalue *args); + + jdouble (JNICALL *CallNonvirtualDoubleMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jdouble (JNICALL *CallNonvirtualDoubleMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jdouble (JNICALL *CallNonvirtualDoubleMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + jvalue *args); + + void (JNICALL *CallNonvirtualVoidMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + void (JNICALL *CallNonvirtualVoidMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + void (JNICALL *CallNonvirtualVoidMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + jvalue * args); + + jfieldID (JNICALL *GetFieldID) + (JNIEnv *env, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *GetObjectField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jboolean (JNICALL *GetBooleanField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jbyte (JNICALL *GetByteField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jchar (JNICALL *GetCharField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jshort (JNICALL *GetShortField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jint (JNICALL *GetIntField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jlong (JNICALL *GetLongField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jfloat (JNICALL *GetFloatField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jdouble (JNICALL *GetDoubleField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + + void (JNICALL *SetObjectField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val); + void (JNICALL *SetBooleanField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val); + void (JNICALL *SetByteField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val); + void (JNICALL *SetCharField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val); + void (JNICALL *SetShortField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val); + void (JNICALL *SetIntField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jint val); + void (JNICALL *SetLongField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val); + void (JNICALL *SetFloatField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val); + void (JNICALL *SetDoubleField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val); + + jmethodID (JNICALL *GetStaticMethodID) + (JNIEnv *env, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *CallStaticObjectMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *CallStaticObjectMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jobject (JNICALL *CallStaticObjectMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args); + + jboolean (JNICALL *CallStaticBooleanMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jboolean (JNICALL *CallStaticBooleanMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jboolean (JNICALL *CallStaticBooleanMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args); + + jbyte (JNICALL *CallStaticByteMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jbyte (JNICALL *CallStaticByteMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jbyte (JNICALL *CallStaticByteMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args); + + jchar (JNICALL *CallStaticCharMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jchar (JNICALL *CallStaticCharMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jchar (JNICALL *CallStaticCharMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args); + + jshort (JNICALL *CallStaticShortMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jshort (JNICALL *CallStaticShortMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jshort (JNICALL *CallStaticShortMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args); + + jint (JNICALL *CallStaticIntMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jint (JNICALL *CallStaticIntMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jint (JNICALL *CallStaticIntMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args); + + jlong (JNICALL *CallStaticLongMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jlong (JNICALL *CallStaticLongMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jlong (JNICALL *CallStaticLongMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args); + + jfloat (JNICALL *CallStaticFloatMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jfloat (JNICALL *CallStaticFloatMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jfloat (JNICALL *CallStaticFloatMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args); + + jdouble (JNICALL *CallStaticDoubleMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jdouble (JNICALL *CallStaticDoubleMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jdouble (JNICALL *CallStaticDoubleMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args); + + void (JNICALL *CallStaticVoidMethod) + (JNIEnv *env, jclass cls, jmethodID methodID, ...); + void (JNICALL *CallStaticVoidMethodV) + (JNIEnv *env, jclass cls, jmethodID methodID, va_list args); + void (JNICALL *CallStaticVoidMethodA) + (JNIEnv *env, jclass cls, jmethodID methodID, jvalue * args); + + jfieldID (JNICALL *GetStaticFieldID) + (JNIEnv *env, jclass clazz, const char *name, const char *sig); + jobject (JNICALL *GetStaticObjectField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jboolean (JNICALL *GetStaticBooleanField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jbyte (JNICALL *GetStaticByteField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jchar (JNICALL *GetStaticCharField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jshort (JNICALL *GetStaticShortField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jint (JNICALL *GetStaticIntField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jlong (JNICALL *GetStaticLongField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jfloat (JNICALL *GetStaticFloatField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jdouble (JNICALL *GetStaticDoubleField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + + void (JNICALL *SetStaticObjectField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value); + void (JNICALL *SetStaticBooleanField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value); + void (JNICALL *SetStaticByteField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value); + void (JNICALL *SetStaticCharField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value); + void (JNICALL *SetStaticShortField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value); + void (JNICALL *SetStaticIntField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value); + void (JNICALL *SetStaticLongField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value); + void (JNICALL *SetStaticFloatField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value); + void (JNICALL *SetStaticDoubleField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value); + + jstring (JNICALL *NewString) + (JNIEnv *env, const jchar *unicode, jsize len); + jsize (JNICALL *GetStringLength) + (JNIEnv *env, jstring str); + const jchar *(JNICALL *GetStringChars) + (JNIEnv *env, jstring str, jboolean *isCopy); + void (JNICALL *ReleaseStringChars) + (JNIEnv *env, jstring str, const jchar *chars); + + jstring (JNICALL *NewStringUTF) + (JNIEnv *env, const char *utf); + jsize (JNICALL *GetStringUTFLength) + (JNIEnv *env, jstring str); + const char* (JNICALL *GetStringUTFChars) + (JNIEnv *env, jstring str, jboolean *isCopy); + void (JNICALL *ReleaseStringUTFChars) + (JNIEnv *env, jstring str, const char* chars); + + + jsize (JNICALL *GetArrayLength) + (JNIEnv *env, jarray array); + + jobjectArray (JNICALL *NewObjectArray) + (JNIEnv *env, jsize len, jclass clazz, jobject init); + jobject (JNICALL *GetObjectArrayElement) + (JNIEnv *env, jobjectArray array, jsize index); + void (JNICALL *SetObjectArrayElement) + (JNIEnv *env, jobjectArray array, jsize index, jobject val); + + jbooleanArray (JNICALL *NewBooleanArray) + (JNIEnv *env, jsize len); + jbyteArray (JNICALL *NewByteArray) + (JNIEnv *env, jsize len); + jcharArray (JNICALL *NewCharArray) + (JNIEnv *env, jsize len); + jshortArray (JNICALL *NewShortArray) + (JNIEnv *env, jsize len); + jintArray (JNICALL *NewIntArray) + (JNIEnv *env, jsize len); + jlongArray (JNICALL *NewLongArray) + (JNIEnv *env, jsize len); + jfloatArray (JNICALL *NewFloatArray) + (JNIEnv *env, jsize len); + jdoubleArray (JNICALL *NewDoubleArray) + (JNIEnv *env, jsize len); + + jboolean * (JNICALL *GetBooleanArrayElements) + (JNIEnv *env, jbooleanArray array, jboolean *isCopy); + jbyte * (JNICALL *GetByteArrayElements) + (JNIEnv *env, jbyteArray array, jboolean *isCopy); + jchar * (JNICALL *GetCharArrayElements) + (JNIEnv *env, jcharArray array, jboolean *isCopy); + jshort * (JNICALL *GetShortArrayElements) + (JNIEnv *env, jshortArray array, jboolean *isCopy); + jint * (JNICALL *GetIntArrayElements) + (JNIEnv *env, jintArray array, jboolean *isCopy); + jlong * (JNICALL *GetLongArrayElements) + (JNIEnv *env, jlongArray array, jboolean *isCopy); + jfloat * (JNICALL *GetFloatArrayElements) + (JNIEnv *env, jfloatArray array, jboolean *isCopy); + jdouble * (JNICALL *GetDoubleArrayElements) + (JNIEnv *env, jdoubleArray array, jboolean *isCopy); + + void (JNICALL *ReleaseBooleanArrayElements) + (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode); + void (JNICALL *ReleaseByteArrayElements) + (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode); + void (JNICALL *ReleaseCharArrayElements) + (JNIEnv *env, jcharArray array, jchar *elems, jint mode); + void (JNICALL *ReleaseShortArrayElements) + (JNIEnv *env, jshortArray array, jshort *elems, jint mode); + void (JNICALL *ReleaseIntArrayElements) + (JNIEnv *env, jintArray array, jint *elems, jint mode); + void (JNICALL *ReleaseLongArrayElements) + (JNIEnv *env, jlongArray array, jlong *elems, jint mode); + void (JNICALL *ReleaseFloatArrayElements) + (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode); + void (JNICALL *ReleaseDoubleArrayElements) + (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode); + + void (JNICALL *GetBooleanArrayRegion) + (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf); + void (JNICALL *GetByteArrayRegion) + (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf); + void (JNICALL *GetCharArrayRegion) + (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf); + void (JNICALL *GetShortArrayRegion) + (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf); + void (JNICALL *GetIntArrayRegion) + (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf); + void (JNICALL *GetLongArrayRegion) + (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf); + void (JNICALL *GetFloatArrayRegion) + (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf); + void (JNICALL *GetDoubleArrayRegion) + (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf); + + void (JNICALL *SetBooleanArrayRegion) + (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf); + void (JNICALL *SetByteArrayRegion) + (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf); + void (JNICALL *SetCharArrayRegion) + (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf); + void (JNICALL *SetShortArrayRegion) + (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf); + void (JNICALL *SetIntArrayRegion) + (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf); + void (JNICALL *SetLongArrayRegion) + (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf); + void (JNICALL *SetFloatArrayRegion) + (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf); + void (JNICALL *SetDoubleArrayRegion) + (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf); + + jint (JNICALL *RegisterNatives) + (JNIEnv *env, jclass clazz, const JNINativeMethod *methods, + jint nMethods); + jint (JNICALL *UnregisterNatives) + (JNIEnv *env, jclass clazz); + + jint (JNICALL *MonitorEnter) + (JNIEnv *env, jobject obj); + jint (JNICALL *MonitorExit) + (JNIEnv *env, jobject obj); + + jint (JNICALL *GetJavaVM) + (JNIEnv *env, JavaVM **vm); + + void (JNICALL *GetStringRegion) + (JNIEnv *env, jstring, jsize, jsize, jchar*); + void (JNICALL *GetStringUTFRegion) + (JNIEnv *env, jstring, jsize, jsize, char*); + + void* (JNICALL *GetPrimitiveArrayCritical) + (JNIEnv *env, jarray array, jboolean *isCopy); + void (JNICALL *ReleasePrimitiveArrayCritical) + (JNIEnv *env, jarray array, void* carray, jint mode); + + const jchar* (JNICALL *GetStringCritical) + (JNIEnv *env, jstring s, jboolean* isCopy); + void (JNICALL *ReleaseStringCritical) + (JNIEnv *env, jstring s, const jchar* cstr); + + jweak (JNICALL *NewWeakGlobalRef) + (JNIEnv *env, jobject obj); + void (JNICALL *DeleteWeakGlobalRef) + (JNIEnv *env, jweak obj); + + jboolean (JNICALL *ExceptionCheck) + (JNIEnv *env); + + jobject (JNICALL *NewDirectByteBuffer) + (JNIEnv* env, void* address, jlong capacity); + void* (JNICALL *GetDirectBufferAddress) + (JNIEnv* env, jobject buf); + jlong (JNICALL *GetDirectBufferCapacity) + (JNIEnv* env, jobject buf); +}; + + +/** + * JNI Native Method Interface table for use in C++ sources + * + * See specification + * for details + */ +struct JNIEnv_External { + const struct JNINativeInterface_ *functions; + +#ifdef __cplusplus + jint GetVersion() { + return functions->GetVersion(this); + } + jclass DefineClass(const char *name, jobject loader, const jbyte *buf, + jsize len) { + return functions->DefineClass(this, name, loader, buf, len); + } + jclass FindClass(const char *name) { + return functions->FindClass(this, name); + } + jmethodID FromReflectedMethod(jobject method) { + return functions->FromReflectedMethod(this, method); + } + jfieldID FromReflectedField(jobject field) { + return functions->FromReflectedField(this, field); + } + jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) { + return functions->ToReflectedMethod(this, cls, methodID, isStatic); + } + jclass GetSuperclass(jclass sub) { + return functions->GetSuperclass(this, sub); + } + jboolean IsAssignableFrom(jclass sub, jclass sup) { + return functions->IsAssignableFrom(this, sub, sup); + } + jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) { + return functions->ToReflectedField(this, cls, fieldID, isStatic); + } + + jint Throw(jthrowable obj) { + return functions->Throw(this, obj); + } + jint ThrowNew(jclass clazz, const char *msg) { + return functions->ThrowNew(this, clazz, msg); + } + jthrowable ExceptionOccurred() { + return functions->ExceptionOccurred(this); + } + void ExceptionDescribe() { + functions->ExceptionDescribe(this); + } + void ExceptionClear() { + functions->ExceptionClear(this); + } + void FatalError(const char *msg) { + functions->FatalError(this, msg); + } + + jint PushLocalFrame(jint cap) { + return functions->PushLocalFrame(this, cap); + } + jobject PopLocalFrame(jobject res) { + return functions->PopLocalFrame(this, res); + } + + jobject NewGlobalRef(jobject lobj) { + return functions->NewGlobalRef(this,lobj); + } + void DeleteGlobalRef(jobject gref) { + functions->DeleteGlobalRef(this,gref); + } + void DeleteLocalRef(jobject obj) { + functions->DeleteLocalRef(this, obj); + } + + jboolean IsSameObject(jobject obj1, jobject obj2) { + return functions->IsSameObject(this,obj1,obj2); + } + jobject NewLocalRef(jobject ref) { + return functions->NewLocalRef(this, ref); + } + + jint EnsureLocalCapacity(jint cap) { + return functions->EnsureLocalCapacity(this,cap); + } + + jobject AllocObject(jclass clazz) { + return functions->AllocObject(this,clazz); + } + jobject NewObject(jclass clazz, jmethodID methodID, ...) { + va_list args; + jobject result; + va_start(args, methodID); + result = functions->NewObjectV(this,clazz,methodID,args); + va_end(args); + return result; + } + jobject NewObjectV(jclass clazz, jmethodID methodID, + va_list args) { + return functions->NewObjectV(this,clazz,methodID,args); + } + jobject NewObjectA(jclass clazz, jmethodID methodID, + jvalue *args) { + return functions->NewObjectA(this,clazz,methodID,args); + } + + jclass GetObjectClass(jobject obj) { + return functions->GetObjectClass(this,obj); + } + jboolean IsInstanceOf(jobject obj, jclass clazz) { + return functions->IsInstanceOf(this,obj,clazz); + } + + jmethodID GetMethodID(jclass clazz, const char *name, + const char *sig) { + return functions->GetMethodID(this,clazz,name,sig); + } + + jobject CallObjectMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jobject result; + va_start(args,methodID); + result = functions->CallObjectMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jobject CallObjectMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallObjectMethodV(this,obj,methodID,args); + } + jobject CallObjectMethodA(jobject obj, jmethodID methodID, + jvalue * args) { + return functions->CallObjectMethodA(this,obj,methodID,args); + } + + jboolean CallBooleanMethod(jobject obj, + jmethodID methodID, ...) { + va_list args; + jboolean result; + va_start(args,methodID); + result = functions->CallBooleanMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jboolean CallBooleanMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallBooleanMethodV(this,obj,methodID,args); + } + jboolean CallBooleanMethodA(jobject obj, jmethodID methodID, + jvalue * args) { + return functions->CallBooleanMethodA(this,obj,methodID, args); + } + + jbyte CallByteMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jbyte result; + va_start(args,methodID); + result = functions->CallByteMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jbyte CallByteMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallByteMethodV(this,obj,methodID,args); + } + jbyte CallByteMethodA(jobject obj, jmethodID methodID, + jvalue * args) { + return functions->CallByteMethodA(this,obj,methodID,args); + } + + jchar CallCharMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jchar result; + va_start(args,methodID); + result = functions->CallCharMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jchar CallCharMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallCharMethodV(this,obj,methodID,args); + } + jchar CallCharMethodA(jobject obj, jmethodID methodID, + jvalue * args) { + return functions->CallCharMethodA(this,obj,methodID,args); + } + + jshort CallShortMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jshort result; + va_start(args,methodID); + result = functions->CallShortMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jshort CallShortMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallShortMethodV(this,obj,methodID,args); + } + jshort CallShortMethodA(jobject obj, jmethodID methodID, + jvalue * args) { + return functions->CallShortMethodA(this,obj,methodID,args); + } + + jint CallIntMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jint result; + va_start(args,methodID); + result = functions->CallIntMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jint CallIntMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallIntMethodV(this,obj,methodID,args); + } + jint CallIntMethodA(jobject obj, jmethodID methodID, + jvalue * args) { + return functions->CallIntMethodA(this,obj,methodID,args); + } + + jlong CallLongMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jlong result; + va_start(args,methodID); + result = functions->CallLongMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jlong CallLongMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallLongMethodV(this,obj,methodID,args); + } + jlong CallLongMethodA(jobject obj, jmethodID methodID, + jvalue * args) { + return functions->CallLongMethodA(this,obj,methodID,args); + } + + jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jfloat result; + va_start(args,methodID); + result = functions->CallFloatMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jfloat CallFloatMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallFloatMethodV(this,obj,methodID,args); + } + jfloat CallFloatMethodA(jobject obj, jmethodID methodID, + jvalue * args) { + return functions->CallFloatMethodA(this,obj,methodID,args); + } + + jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jdouble result; + va_start(args,methodID); + result = functions->CallDoubleMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jdouble CallDoubleMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallDoubleMethodV(this,obj,methodID,args); + } + jdouble CallDoubleMethodA(jobject obj, jmethodID methodID, + jvalue * args) { + return functions->CallDoubleMethodA(this,obj,methodID,args); + } + + void CallVoidMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + va_start(args,methodID); + functions->CallVoidMethodV(this,obj,methodID,args); + va_end(args); + } + void CallVoidMethodV(jobject obj, jmethodID methodID, + va_list args) { + functions->CallVoidMethodV(this,obj,methodID,args); + } + void CallVoidMethodA(jobject obj, jmethodID methodID, + jvalue * args) { + functions->CallVoidMethodA(this,obj,methodID,args); + } + + jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jobject result; + va_start(args,methodID); + result = functions->CallNonvirtualObjectMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualObjectMethodV(this,obj,clazz, + methodID,args); + } + jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz, + jmethodID methodID, jvalue * args) { + return functions->CallNonvirtualObjectMethodA(this,obj,clazz, + methodID,args); + } + + jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jboolean result; + va_start(args,methodID); + result = functions->CallNonvirtualBooleanMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualBooleanMethodV(this,obj,clazz, + methodID,args); + } + jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz, + jmethodID methodID, jvalue * args) { + return functions->CallNonvirtualBooleanMethodA(this,obj,clazz, + methodID, args); + } + + jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jbyte result; + va_start(args,methodID); + result = functions->CallNonvirtualByteMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualByteMethodV(this,obj,clazz, + methodID,args); + } + jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz, + jmethodID methodID, jvalue * args) { + return functions->CallNonvirtualByteMethodA(this,obj,clazz, + methodID,args); + } + + jchar CallNonvirtualCharMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jchar result; + va_start(args,methodID); + result = functions->CallNonvirtualCharMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualCharMethodV(this,obj,clazz, + methodID,args); + } + jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz, + jmethodID methodID, jvalue * args) { + return functions->CallNonvirtualCharMethodA(this,obj,clazz, + methodID,args); + } + + jshort CallNonvirtualShortMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jshort result; + va_start(args,methodID); + result = functions->CallNonvirtualShortMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualShortMethodV(this,obj,clazz, + methodID,args); + } + jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz, + jmethodID methodID, jvalue * args) { + return functions->CallNonvirtualShortMethodA(this,obj,clazz, + methodID,args); + } + + jint CallNonvirtualIntMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jint result; + va_start(args,methodID); + result = functions->CallNonvirtualIntMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jint CallNonvirtualIntMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualIntMethodV(this,obj,clazz, + methodID,args); + } + jint CallNonvirtualIntMethodA(jobject obj, jclass clazz, + jmethodID methodID, jvalue * args) { + return functions->CallNonvirtualIntMethodA(this,obj,clazz, + methodID,args); + } + + jlong CallNonvirtualLongMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jlong result; + va_start(args,methodID); + result = functions->CallNonvirtualLongMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualLongMethodV(this,obj,clazz, + methodID,args); + } + jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz, + jmethodID methodID, jvalue * args) { + return functions->CallNonvirtualLongMethodA(this,obj,clazz, + methodID,args); + } + + jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jfloat result; + va_start(args,methodID); + result = functions->CallNonvirtualFloatMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz, + jmethodID methodID, + va_list args) { + return functions->CallNonvirtualFloatMethodV(this,obj,clazz, + methodID,args); + } + jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz, + jmethodID methodID, + jvalue * args) { + return functions->CallNonvirtualFloatMethodA(this,obj,clazz, + methodID,args); + } + + jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jdouble result; + va_start(args,methodID); + result = functions->CallNonvirtualDoubleMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz, + jmethodID methodID, + va_list args) { + return functions->CallNonvirtualDoubleMethodV(this,obj,clazz, + methodID,args); + } + jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz, + jmethodID methodID, + jvalue * args) { + return functions->CallNonvirtualDoubleMethodA(this,obj,clazz, + methodID,args); + } + + void CallNonvirtualVoidMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + va_start(args,methodID); + functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args); + va_end(args); + } + void CallNonvirtualVoidMethodV(jobject obj, jclass clazz, + jmethodID methodID, + va_list args) { + functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args); + } + void CallNonvirtualVoidMethodA(jobject obj, jclass clazz, + jmethodID methodID, + jvalue * args) { + functions->CallNonvirtualVoidMethodA(this,obj,clazz,methodID,args); + } + + jfieldID GetFieldID(jclass clazz, const char *name, + const char *sig) { + return functions->GetFieldID(this,clazz,name,sig); + } + + jobject GetObjectField(jobject obj, jfieldID fieldID) { + return functions->GetObjectField(this,obj,fieldID); + } + jboolean GetBooleanField(jobject obj, jfieldID fieldID) { + return functions->GetBooleanField(this,obj,fieldID); + } + jbyte GetByteField(jobject obj, jfieldID fieldID) { + return functions->GetByteField(this,obj,fieldID); + } + jchar GetCharField(jobject obj, jfieldID fieldID) { + return functions->GetCharField(this,obj,fieldID); + } + jshort GetShortField(jobject obj, jfieldID fieldID) { + return functions->GetShortField(this,obj,fieldID); + } + jint GetIntField(jobject obj, jfieldID fieldID) { + return functions->GetIntField(this,obj,fieldID); + } + jlong GetLongField(jobject obj, jfieldID fieldID) { + return functions->GetLongField(this,obj,fieldID); + } + jfloat GetFloatField(jobject obj, jfieldID fieldID) { + return functions->GetFloatField(this,obj,fieldID); + } + jdouble GetDoubleField(jobject obj, jfieldID fieldID) { + return functions->GetDoubleField(this,obj,fieldID); + } + + void SetObjectField(jobject obj, jfieldID fieldID, jobject val) { + functions->SetObjectField(this,obj,fieldID,val); + } + void SetBooleanField(jobject obj, jfieldID fieldID, + jboolean val) { + functions->SetBooleanField(this,obj,fieldID,val); + } + void SetByteField(jobject obj, jfieldID fieldID, + jbyte val) { + functions->SetByteField(this,obj,fieldID,val); + } + void SetCharField(jobject obj, jfieldID fieldID, + jchar val) { + functions->SetCharField(this,obj,fieldID,val); + } + void SetShortField(jobject obj, jfieldID fieldID, + jshort val) { + functions->SetShortField(this,obj,fieldID,val); + } + void SetIntField(jobject obj, jfieldID fieldID, + jint val) { + functions->SetIntField(this,obj,fieldID,val); + } + void SetLongField(jobject obj, jfieldID fieldID, + jlong val) { + functions->SetLongField(this,obj,fieldID,val); + } + void SetFloatField(jobject obj, jfieldID fieldID, + jfloat val) { + functions->SetFloatField(this,obj,fieldID,val); + } + void SetDoubleField(jobject obj, jfieldID fieldID, + jdouble val) { + functions->SetDoubleField(this,obj,fieldID,val); + } + + jmethodID GetStaticMethodID(jclass clazz, const char *name, + const char *sig) { + return functions->GetStaticMethodID(this,clazz,name,sig); + } + + jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID, + ...) { + va_list args; + jobject result; + va_start(args,methodID); + result = functions->CallStaticObjectMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID, + va_list args) { + return functions->CallStaticObjectMethodV(this,clazz,methodID,args); + } + jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID, + jvalue *args) { + return functions->CallStaticObjectMethodA(this,clazz,methodID,args); + } + + jboolean CallStaticBooleanMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jboolean result; + va_start(args,methodID); + result = functions->CallStaticBooleanMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jboolean CallStaticBooleanMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticBooleanMethodV(this,clazz,methodID,args); + } + jboolean CallStaticBooleanMethodA(jclass clazz, + jmethodID methodID, jvalue *args) { + return functions->CallStaticBooleanMethodA(this,clazz,methodID,args); + } + + jbyte CallStaticByteMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jbyte result; + va_start(args,methodID); + result = functions->CallStaticByteMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jbyte CallStaticByteMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticByteMethodV(this,clazz,methodID,args); + } + jbyte CallStaticByteMethodA(jclass clazz, + jmethodID methodID, jvalue *args) { + return functions->CallStaticByteMethodA(this,clazz,methodID,args); + } + + jchar CallStaticCharMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jchar result; + va_start(args,methodID); + result = functions->CallStaticCharMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jchar CallStaticCharMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticCharMethodV(this,clazz,methodID,args); + } + jchar CallStaticCharMethodA(jclass clazz, + jmethodID methodID, jvalue *args) { + return functions->CallStaticCharMethodA(this,clazz,methodID,args); + } + + jshort CallStaticShortMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jshort result; + va_start(args,methodID); + result = functions->CallStaticShortMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jshort CallStaticShortMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticShortMethodV(this,clazz,methodID,args); + } + jshort CallStaticShortMethodA(jclass clazz, + jmethodID methodID, jvalue *args) { + return functions->CallStaticShortMethodA(this,clazz,methodID,args); + } + + jint CallStaticIntMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jint result; + va_start(args,methodID); + result = functions->CallStaticIntMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jint CallStaticIntMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticIntMethodV(this,clazz,methodID,args); + } + jint CallStaticIntMethodA(jclass clazz, + jmethodID methodID, jvalue *args) { + return functions->CallStaticIntMethodA(this,clazz,methodID,args); + } + + jlong CallStaticLongMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jlong result; + va_start(args,methodID); + result = functions->CallStaticLongMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jlong CallStaticLongMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticLongMethodV(this,clazz,methodID,args); + } + jlong CallStaticLongMethodA(jclass clazz, + jmethodID methodID, jvalue *args) { + return functions->CallStaticLongMethodA(this,clazz,methodID,args); + } + + jfloat CallStaticFloatMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jfloat result; + va_start(args,methodID); + result = functions->CallStaticFloatMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jfloat CallStaticFloatMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticFloatMethodV(this,clazz,methodID,args); + } + jfloat CallStaticFloatMethodA(jclass clazz, + jmethodID methodID, jvalue *args) { + return functions->CallStaticFloatMethodA(this,clazz,methodID,args); + } + + jdouble CallStaticDoubleMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jdouble result; + va_start(args,methodID); + result = functions->CallStaticDoubleMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jdouble CallStaticDoubleMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticDoubleMethodV(this,clazz,methodID,args); + } + jdouble CallStaticDoubleMethodA(jclass clazz, + jmethodID methodID, jvalue *args) { + return functions->CallStaticDoubleMethodA(this,clazz,methodID,args); + } + + void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...) { + va_list args; + va_start(args,methodID); + functions->CallStaticVoidMethodV(this,cls,methodID,args); + va_end(args); + } + void CallStaticVoidMethodV(jclass cls, jmethodID methodID, + va_list args) { + functions->CallStaticVoidMethodV(this,cls,methodID,args); + } + void CallStaticVoidMethodA(jclass cls, jmethodID methodID, + jvalue * args) { + functions->CallStaticVoidMethodA(this,cls,methodID,args); + } + + jfieldID GetStaticFieldID(jclass clazz, const char *name, + const char *sig) { + return functions->GetStaticFieldID(this,clazz,name,sig); + } + jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticObjectField(this,clazz,fieldID); + } + jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticBooleanField(this,clazz,fieldID); + } + jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticByteField(this,clazz,fieldID); + } + jchar GetStaticCharField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticCharField(this,clazz,fieldID); + } + jshort GetStaticShortField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticShortField(this,clazz,fieldID); + } + jint GetStaticIntField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticIntField(this,clazz,fieldID); + } + jlong GetStaticLongField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticLongField(this,clazz,fieldID); + } + jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticFloatField(this,clazz,fieldID); + } + jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticDoubleField(this,clazz,fieldID); + } + + void SetStaticObjectField(jclass clazz, jfieldID fieldID, + jobject value) { + functions->SetStaticObjectField(this,clazz,fieldID,value); + } + void SetStaticBooleanField(jclass clazz, jfieldID fieldID, + jboolean value) { + functions->SetStaticBooleanField(this,clazz,fieldID,value); + } + void SetStaticByteField(jclass clazz, jfieldID fieldID, + jbyte value) { + functions->SetStaticByteField(this,clazz,fieldID,value); + } + void SetStaticCharField(jclass clazz, jfieldID fieldID, + jchar value) { + functions->SetStaticCharField(this,clazz,fieldID,value); + } + void SetStaticShortField(jclass clazz, jfieldID fieldID, + jshort value) { + functions->SetStaticShortField(this,clazz,fieldID,value); + } + void SetStaticIntField(jclass clazz, jfieldID fieldID, + jint value) { + functions->SetStaticIntField(this,clazz,fieldID,value); + } + void SetStaticLongField(jclass clazz, jfieldID fieldID, + jlong value) { + functions->SetStaticLongField(this,clazz,fieldID,value); + } + void SetStaticFloatField(jclass clazz, jfieldID fieldID, + jfloat value) { + functions->SetStaticFloatField(this,clazz,fieldID,value); + } + void SetStaticDoubleField(jclass clazz, jfieldID fieldID, + jdouble value) { + functions->SetStaticDoubleField(this,clazz,fieldID,value); + } + + jstring NewString(const jchar *unicode, jsize len) { + return functions->NewString(this,unicode,len); + } + jsize GetStringLength(jstring str) { + return functions->GetStringLength(this,str); + } + const jchar *GetStringChars(jstring str, jboolean *isCopy) { + return functions->GetStringChars(this,str,isCopy); + } + void ReleaseStringChars(jstring str, const jchar *chars) { + functions->ReleaseStringChars(this,str,chars); + } + + jstring NewStringUTF(const char *utf) { + return functions->NewStringUTF(this,utf); + } + jsize GetStringUTFLength(jstring str) { + return functions->GetStringUTFLength(this,str); + } + const char* GetStringUTFChars(jstring str, jboolean *isCopy) { + return functions->GetStringUTFChars(this,str,isCopy); + } + void ReleaseStringUTFChars(jstring str, const char* chars) { + functions->ReleaseStringUTFChars(this,str,chars); + } + + jsize GetArrayLength(jarray array) { + return functions->GetArrayLength(this,array); + } + + jobjectArray NewObjectArray(jsize len, jclass clazz, + jobject init) { + return functions->NewObjectArray(this,len,clazz,init); + } + jobject GetObjectArrayElement(jobjectArray array, jsize index) { + return functions->GetObjectArrayElement(this,array,index); + } + void SetObjectArrayElement(jobjectArray array, jsize index, + jobject val) { + functions->SetObjectArrayElement(this,array,index,val); + } + + jbooleanArray NewBooleanArray(jsize len) { + return functions->NewBooleanArray(this,len); + } + jbyteArray NewByteArray(jsize len) { + return functions->NewByteArray(this,len); + } + jcharArray NewCharArray(jsize len) { + return functions->NewCharArray(this,len); + } + jshortArray NewShortArray(jsize len) { + return functions->NewShortArray(this,len); + } + jintArray NewIntArray(jsize len) { + return functions->NewIntArray(this,len); + } + jlongArray NewLongArray(jsize len) { + return functions->NewLongArray(this,len); + } + jfloatArray NewFloatArray(jsize len) { + return functions->NewFloatArray(this,len); + } + jdoubleArray NewDoubleArray(jsize len) { + return functions->NewDoubleArray(this,len); + } + + jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy) { + return functions->GetBooleanArrayElements(this,array,isCopy); + } + jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy) { + return functions->GetByteArrayElements(this,array,isCopy); + } + jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy) { + return functions->GetCharArrayElements(this,array,isCopy); + } + jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) { + return functions->GetShortArrayElements(this,array,isCopy); + } + jint * GetIntArrayElements(jintArray array, jboolean *isCopy) { + return functions->GetIntArrayElements(this,array,isCopy); + } + jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy) { + return functions->GetLongArrayElements(this,array,isCopy); + } + jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy) { + return functions->GetFloatArrayElements(this,array,isCopy); + } + jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy) { + return functions->GetDoubleArrayElements(this,array,isCopy); + } + + void ReleaseBooleanArrayElements(jbooleanArray array, + jboolean *elems, + jint mode) { + functions->ReleaseBooleanArrayElements(this,array,elems,mode); + } + void ReleaseByteArrayElements(jbyteArray array, + jbyte *elems, + jint mode) { + functions->ReleaseByteArrayElements(this,array,elems,mode); + } + void ReleaseCharArrayElements(jcharArray array, + jchar *elems, + jint mode) { + functions->ReleaseCharArrayElements(this,array,elems,mode); + } + void ReleaseShortArrayElements(jshortArray array, + jshort *elems, + jint mode) { + functions->ReleaseShortArrayElements(this,array,elems,mode); + } + void ReleaseIntArrayElements(jintArray array, + jint *elems, + jint mode) { + functions->ReleaseIntArrayElements(this,array,elems,mode); + } + void ReleaseLongArrayElements(jlongArray array, + jlong *elems, + jint mode) { + functions->ReleaseLongArrayElements(this,array,elems,mode); + } + void ReleaseFloatArrayElements(jfloatArray array, + jfloat *elems, + jint mode) { + functions->ReleaseFloatArrayElements(this,array,elems,mode); + } + void ReleaseDoubleArrayElements(jdoubleArray array, + jdouble *elems, + jint mode) { + functions->ReleaseDoubleArrayElements(this,array,elems,mode); + } + + void GetBooleanArrayRegion(jbooleanArray array, + jsize start, jsize len, jboolean *buf) { + functions->GetBooleanArrayRegion(this,array,start,len,buf); + } + void GetByteArrayRegion(jbyteArray array, + jsize start, jsize len, jbyte *buf) { + functions->GetByteArrayRegion(this,array,start,len,buf); + } + void GetCharArrayRegion(jcharArray array, + jsize start, jsize len, jchar *buf) { + functions->GetCharArrayRegion(this,array,start,len,buf); + } + void GetShortArrayRegion(jshortArray array, + jsize start, jsize len, jshort *buf) { + functions->GetShortArrayRegion(this,array,start,len,buf); + } + void GetIntArrayRegion(jintArray array, + jsize start, jsize len, jint *buf) { + functions->GetIntArrayRegion(this,array,start,len,buf); + } + void GetLongArrayRegion(jlongArray array, + jsize start, jsize len, jlong *buf) { + functions->GetLongArrayRegion(this,array,start,len,buf); + } + void GetFloatArrayRegion(jfloatArray array, + jsize start, jsize len, jfloat *buf) { + functions->GetFloatArrayRegion(this,array,start,len,buf); + } + void GetDoubleArrayRegion(jdoubleArray array, + jsize start, jsize len, jdouble *buf) { + functions->GetDoubleArrayRegion(this,array,start,len,buf); + } + + void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, + jboolean *buf) { + functions->SetBooleanArrayRegion(this,array,start,len,buf); + } + void SetByteArrayRegion(jbyteArray array, jsize start, jsize len, + jbyte *buf) { + functions->SetByteArrayRegion(this,array,start,len,buf); + } + void SetCharArrayRegion(jcharArray array, jsize start, jsize len, + jchar *buf) { + functions->SetCharArrayRegion(this,array,start,len,buf); + } + void SetShortArrayRegion(jshortArray array, jsize start, jsize len, + jshort *buf) { + functions->SetShortArrayRegion(this,array,start,len,buf); + } + void SetIntArrayRegion(jintArray array, jsize start, jsize len, + jint *buf) { + functions->SetIntArrayRegion(this,array,start,len,buf); + } + void SetLongArrayRegion(jlongArray array, jsize start, jsize len, + jlong *buf) { + functions->SetLongArrayRegion(this,array,start,len,buf); + } + void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, + jfloat *buf) { + functions->SetFloatArrayRegion(this,array,start,len,buf); + } + void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, + jdouble *buf) { + functions->SetDoubleArrayRegion(this,array,start,len,buf); + } + + jint RegisterNatives(jclass clazz, const JNINativeMethod *methods, + jint nMethods) { + return functions->RegisterNatives(this,clazz,methods,nMethods); + } + jint UnregisterNatives(jclass clazz) { + return functions->UnregisterNatives(this,clazz); + } + + jint MonitorEnter(jobject obj) { + return functions->MonitorEnter(this,obj); + } + jint MonitorExit(jobject obj) { + return functions->MonitorExit(this,obj); + } + + jint GetJavaVM(JavaVM **vm) { + return functions->GetJavaVM(this,vm); + } + + void GetStringRegion(jstring s, jsize off, jsize len, jchar* d) { + functions->GetStringRegion(this, s, off, len, d); + } + void GetStringUTFRegion(jstring s, jsize off, jsize len, char* d) { + functions->GetStringUTFRegion(this, s, off, len, d); + } + + void* GetPrimitiveArrayCritical(jarray array, jboolean* isCopy) { + return functions->GetPrimitiveArrayCritical(this, array, isCopy); + } + + void ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode) { + functions->ReleasePrimitiveArrayCritical(this, array, carray, mode); + } + + const jchar* GetStringCritical(jstring s, jboolean* isCopy) { + return functions->GetStringCritical(this, s, isCopy); + } + void ReleaseStringCritical(jstring s, const jchar* cstr) { + functions->ReleaseStringCritical(this, s, cstr); + } + + jweak NewWeakGlobalRef(jobject obj) { + return functions->NewWeakGlobalRef(this, obj); + } + + void DeleteWeakGlobalRef(jweak obj) { + functions->DeleteWeakGlobalRef(this, obj); + } + + jboolean ExceptionCheck() { + return functions->ExceptionCheck(this); + } + + jobject NewDirectByteBuffer(void *address, jlong capacity) { + return functions->NewDirectByteBuffer(this, address, capacity); + } + void *GetDirectBufferAddress(jobject buf) { + return functions->GetDirectBufferAddress(this, buf); + } + jlong GetDirectBufferCapacity(jobject buf) { + return functions->GetDirectBufferCapacity(this, buf); + } +#endif + +}; + +/** + * Structure which describes one Java VM invocation argument + * + * See specification + * for details. + */ +typedef struct JavaVMOption { + char *optionString; + void *extraInfo; +} JavaVMOption; + +/** + * Structure which describes one Java VM invocation arguments for JNI + * interface version 1.2 and greater + * + * See specification + * for details. + */ +typedef struct JavaVMInitArgs { + jint version; + jint nOptions; + JavaVMOption *options; + jboolean ignoreUnrecognized; +} JavaVMInitArgs; + +/** + * Structure which describes arguments for attaching a native thread to a Java VM + * + * See specification + * for details. + */ +typedef struct JavaVMAttachArgs { + jint version; + char *name; + jobject group; +} JavaVMAttachArgs; + +/** + * JNI Invocation Interface table for use in C sources + * + * See + * specification for details + */ +struct JNIInvokeInterface_ { + void* reserved0; + void* reserved1; + void* reserved2; + + jint (JNICALL *DestroyJavaVM)(JavaVM*); + + jint (JNICALL *AttachCurrentThread)(JavaVM*, void** penv, void* args); + jint (JNICALL *DetachCurrentThread)(JavaVM*); + + jint (JNICALL *GetEnv)(JavaVM*, void** penv, jint ver); + + jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM*, void** penv, void* args); +}; + +/** + * JNI Invocation Interface table for use in C++ sources + * + * See + * specification for details + */ +struct JavaVM_External { + const struct JNIInvokeInterface_* functions; + +#ifdef __cplusplus + jint DestroyJavaVM() { + return functions->DestroyJavaVM(this); + } + + jint AttachCurrentThread(void** penv, void* args) { + return functions->AttachCurrentThread(this, penv, args); + } + + jint DetachCurrentThread() { + return functions->DetachCurrentThread(this); + } + + jint GetEnv(void** penv, jint ver) { + return functions->GetEnv(this, penv, ver); + } + + jint AttachCurrentThreadAsDaemon(void** penv, void* args) { + return functions->AttachCurrentThreadAsDaemon(this, penv, args); + } + +#endif +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def _JNI_EXPORT_ + * Function attribute used when building VM from sources + */ +#ifdef BUILDING_VM +#define _JNI_EXPORT_ +#else +#define _JNI_EXPORT_ JNIIMPORT +#endif + +/** + * Function to get the default VM arguments + * + * See specification + * for details. + */ +_JNI_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void * vm_args); + +/** + * Function to get an array of already created Java VMs in the current + * process + * + * See specification + * for details. + */ +_JNI_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs(JavaVM ** vmBuf, + jsize bufLen, + jsize * nVMs); + +/** + * Creates Java VM in the current process + * + * See specification + * for details. + */ +_JNI_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM ** p_vm, JNIEnv ** p_env, + void * vm_args); + +#ifdef __cplusplus +} +#endif + + +#endif /* _JNI_H_ */ diff --git a/platform/o.n.bootstrap/launcher/windows/include/jni_types.h b/platform/o.n.bootstrap/launcher/windows/include/jni_types.h new file mode 100644 index 000000000000..a809ebba8f33 --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/include/jni_types.h @@ -0,0 +1,451 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _JNI_TYPES_H_ +#define _JNI_TYPES_H_ + +/** + * @file + * Types used in JNI and OPEN interfaces. + * + * For the most part JNI types are defined by Sun specification on + * Java Native Interface (JNI). See specification + * for details. + */ + +/* The following documentation is both for windows and linux, so it + * resides outside of ifdef-endif block */ +/** + * @def JNIEXPORT + * Function attribute to make native JNI function exportable + */ +/** + * @def JNIIMPORT + * Function attribute used when building VM from sources + */ +/** + * @def JNICALL + * Function attribute to specify calling conventions that should be + * used for native JNI functions + */ +/** + * @typedef jlong + * Signed 64-bit long type equivalent to Java "long" type + */ +#if defined (_WIN32) || defined (__WIN32__) || defined (WIN32) + +#define JNIEXPORT __declspec(dllexport) +#define JNIIMPORT __declspec(dllimport) +#define JNICALL __stdcall + +typedef signed __int64 jlong; + +#else + +#define JNIEXPORT +#define JNIIMPORT +#define JNICALL + +typedef signed long long jlong; + +#endif + +/* + * Primitive types + */ +/** + * Unsigned 8-bit primitive boolean type equivalent to Java "boolean" + * type + * + * See specification + * for details. + */ +typedef unsigned char jboolean; +/** + * Signed 8-bit primitive byte type equivalent to Java "byte" type + * + * See specification + * for details. + */ +typedef signed char jbyte; +/** + * Unsigned 16-bit primitive char type equivalent to Java "char" type + * + * See specification + * for details. + */ +typedef unsigned short jchar; +/** + * Signed 16-bit primitive short type equivalent to Java "short" type + * + * See specification + * for details. + */ +typedef signed short jshort; +/** + * Signed 32-bit primitive integer type equivalent to Java "int" type + * + * See specification + * for details. + */ +typedef signed int jint; +/** + * Signed 32-bit primitive floating point type equivalent to Java + * "float" type + * + * See specification + * for details. + */ +typedef float jfloat; +/** + * Signed 64-bit primitive floating point type equivalent to Java + * "double" type + * + * See specification + * for details. + */ +typedef double jdouble; +/** + * Signed 32-bit primitive integer type used to describe sizes + * + * See specification + * for details. + */ +typedef jint jsize; + +/* + * Java types + */ +struct _jobject; +/** + * Reference type which describes a general Java object in native + * function + * + * See specification + * for details. + */ +typedef struct _jobject* jobject; +/** + * Reference type which describes a java.lang.Class instance object in + * native function + * + * See specification + * for details. + */ +typedef jobject jclass; +/** + * Reference type which describes a java.lang.String instance object + * in native function + * + * See specification + * for details. + */ +typedef jobject jstring; +/** + * Reference type which describes a generic array instance object in + * native function + * + * See specification + * for details. + */ +typedef jobject jarray; +/** + * Reference type which describes an array of java.lang.Object + * instances in native function + * + * See specification + * for details. + */ + typedef jarray jobjectArray; +/** + * Reference type which describes an array of booleans in native + * function + * + * See specification + * for details. + */ + typedef jarray jbooleanArray; +/** + * Reference type which describes an array of bytes type in native + * function + * + * See specification + * for details. + */ + typedef jarray jbyteArray; +/** + * Reference type which describes an array of chars type in native + * function + * + * See specification + * for details. + */ + typedef jarray jcharArray; +/** + * Reference type which describes an array of shorts type in native + * function + * + * See specification + * for details. + */ + typedef jarray jshortArray; +/** + * Reference type which describes an array of ints type in native + * function + * + * See specification + * for details. + */ + typedef jarray jintArray; +/** + * Reference type which describes an array of longs type in native + * function + * + * See specification + * for details. + */ + typedef jarray jlongArray; +/** + * Reference type which describes an array of floats type in native + * function + * + * See specification + * for details. + */ + typedef jarray jfloatArray; +/** + * Reference type which describes an array of doubles type in native + * function + * + * See specification + * for details. + */ + typedef jarray jdoubleArray; +/** + * Reference type which describes a java.lang.Throwable instance + * object in native function + * + * See specification + * for details. + */ +typedef jobject jthrowable; +/** + * Reference type which describes a weak reference to a general object + * + * This type is the same as #jobject but the reference held in it + * is weak, so if the referred object is weakly reacheable, it may be + * garbage collected to VM. + */ +typedef jobject jweak; + +/** + * This union used to pass arguments to native functions when Call<type>MethodA + * and CallStatic<type>MethodA + * functions are used + * + * It consists of all possible primitive Java types plus #jobject, so + * it is possible to pass any kind of argument type through it. + */ +typedef union jvalue { + jboolean z; + jbyte b; + jchar c; + jshort s; + jint i; + jlong j; + jfloat f; + jdouble d; + jobject l; +} jvalue; + +/** + * Type which describes an identfier of a field inside of class + * + * This type together with a #jclass reference uniquily identifies a + * field inside of the class described by #jclass. + */ +typedef struct _jfieldID* jfieldID; + +/** + * Type which describes an identfier of a method inside of class + * + * This type together with a #jclass reference uniquily identifies a + * method inside of the class described by #jclass. + */ +typedef struct _jmethodID* jmethodID; + +/* + * Constants + */ + +/* + * Boolean constants + */ +/** + * Constant which defines boolean truth in native Java functions. It + * is equivalent to Java constant "true" + */ +#define JNI_FALSE 0 +/** + * Constant which defines boolean false in native Java functions. It + * is equivalent to Java constant "false" + */ +#define JNI_TRUE 1 + +/* + * Return values + */ +/** + * Constant which describes success when returned by JNI API functions + */ +#define JNI_OK 0 +/** + * Constant which describes an error when returned by JNI API + * functions + */ +#define JNI_ERR (-1) +/** + * Constant which describes a deatached thread condition when returned + * by JNI API functions + */ +#define JNI_EDETACHED (-2) +/** + * Constant which describes wrong JNI interface verions when returned + * by JNI API functions + */ +#define JNI_EVERSION (-3) +/** + * Constant which describes out of memory condition when returned by + * JNI API functions + */ +#define JNI_ENOMEM (-4) +/** + * Constant which means that a limited resource already exists when + * returned by JNI API functions + */ +#define JNI_EEXIST (-5) +/** + * Constant which means that an illegal argument value was passed to a + * JNI function + */ +#define JNI_EINVAL (-6) + +/* + * Release modes for working with arrays. + */ +/** + * Constant which means that an array region should be committed into + * memory. Used in ReleaseArrayElements functions + */ +#define JNI_COMMIT 1 +/** + * Constant which means that an array region should be discarded. Used + * in ReleaseArrayElements functions + */ +#define JNI_ABORT 2 + +/* + * Used as a generic pointer to a function. + */ +/** + * Structure which describes a generic pointer to a native + * function. Used in RegisterNatives + * function. + */ +typedef struct { + char *name; + char *signature; + void *fnPtr; +} JNINativeMethod; + +/* + * JNI Native Method Interface + */ +struct JNINativeInterface_; +struct JNIEnv_External; + +#ifdef __cplusplus +/** + * JNI API interface table type for usage in C++ + * + * See specification + * for details. */ +typedef JNIEnv_External JNIEnv; +#else +/** + * JNI API interface table type for usage in C + * + * See specification + * for details. */ +typedef const struct JNINativeInterface_ *JNIEnv; +#endif + +/* + * JNI Invocation Interface + */ +struct JNIInvokeInterface_; +struct JavaVM_External; + +#ifdef __cplusplus +/** + * Java VM interface table type for usage in C++ + * + * See specification + * for details + */ +typedef JavaVM_External JavaVM; +#else +/** + * Java VM interface table type for usage in C + * + * See specification + * for details + */ +typedef const struct JNIInvokeInterface_ *JavaVM; +#endif + +#endif /* _JNI_TYPES_H_ */ diff --git a/platform/o.n.bootstrap/launcher/windows/jvmlauncher.cpp b/platform/o.n.bootstrap/launcher/windows/jvmlauncher.cpp new file mode 100644 index 000000000000..74bf1cc91932 --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/jvmlauncher.cpp @@ -0,0 +1,454 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + +#include "jvmlauncher.h" +#include + +using namespace std; + +const char *JvmLauncher::JDK_KEY = "Software\\JavaSoft\\Java Development Kit"; +const char *JvmLauncher::JRE_KEY = "Software\\JavaSoft\\Java Runtime Environment"; +const char *JvmLauncher::JDK_POST9_KEY = "Software\\JavaSoft\\JDK"; +const char *JvmLauncher::JRE_POST9_KEY = "Software\\JavaSoft\\JRE"; +const char *JvmLauncher::CUR_VERSION_NAME = "CurrentVersion"; +const char *JvmLauncher::JAVA_HOME_NAME = "JavaHome"; +const char *JvmLauncher::JAVA_BIN_DIR = "\\bin"; +const char *JvmLauncher::JAVA_EXE_FILE = "\\bin\\java.exe"; +const char *JvmLauncher::JAVAW_EXE_FILE = "\\bin\\javaw.exe"; +const char *JvmLauncher::JAVA_CLIENT_DLL_FILE = "\\bin\\client\\jvm.dll"; +const char *JvmLauncher::JAVA_SERVER_DLL_FILE = "\\bin\\server\\jvm.dll"; +const char *JvmLauncher::JAVA_JRE_PREFIX = "\\jre"; +const char *JvmLauncher::JNI_CREATEVM_FUNC = "JNI_CreateJavaVM"; + +extern void exitHook(int status); + +JvmLauncher::JvmLauncher() + : suppressConsole(false) { +} + +JvmLauncher::JvmLauncher(const JvmLauncher& orig) { +} + +JvmLauncher::~JvmLauncher() { +} + +bool JvmLauncher::checkJava(const char *path, const char *prefix) { + assert(path); + assert(prefix); + logMsg("checkJava(%s)", path); + javaPath = path; + if (*javaPath.rbegin() == '\\') { + javaPath.erase(javaPath.length() - 1, 1); + } + javaExePath = javaPath + prefix + JAVA_EXE_FILE; + javawExePath = javaPath + prefix + JAVAW_EXE_FILE; + javaClientDllPath = javaPath + prefix + JAVA_CLIENT_DLL_FILE; + javaServerDllPath = javaPath + prefix + JAVA_SERVER_DLL_FILE; + if (!fileExists(javaClientDllPath.c_str())) { + javaClientDllPath = ""; + } + if (!fileExists(javaServerDllPath.c_str())) { + javaServerDllPath = ""; + } + javaBinPath = javaPath + prefix + JAVA_BIN_DIR; + if (fileExists(javaExePath.c_str()) || !javaClientDllPath.empty() || !javaServerDllPath.empty()) { + if (!fileExists(javawExePath.c_str())) { + logMsg("javaw.exe not exists, forcing java.exe"); + javawExePath = javaExePath; + } + return true; + } + + javaPath.clear(); + javaBinPath.clear(); + javaExePath.clear(); + javawExePath.clear(); + javaClientDllPath.clear(); + javaServerDllPath.clear(); + return false; +} + +bool JvmLauncher::initialize(const char *javaPathOrMinVersion) { + logMsg("JvmLauncher::initialize()\n\tjavaPathOrMinVersion: %s", javaPathOrMinVersion); + assert(javaPathOrMinVersion); + if (isVersionString(javaPathOrMinVersion)) { + return findJava(javaPathOrMinVersion); + } else { + return (checkJava(javaPathOrMinVersion, JAVA_JRE_PREFIX) || checkJava(javaPathOrMinVersion, "")); + } +} + +bool JvmLauncher::getJavaPath(string &path) { + logMsg("JvmLauncher::getJavaPath()"); + path = javaPath; + return !javaPath.empty(); +} + +bool JvmLauncher::start(const char *mainClassName, const list &args, const list &options, bool &separateProcess, DWORD *retCode) { + assert(mainClassName); + logMsg("JvmLauncher::start()\n\tmainClassName: %s\n\tseparateProcess: %s", + mainClassName, separateProcess ? "true" : "false"); + logMsg(" args:"); + for (list::const_iterator it = args.begin(); it != args.end(); ++it) { + logMsg("\t%s", it->c_str()); + } + logMsg(" options:"); + for (list::const_iterator it = options.begin(); it != options.end(); ++it) { + logMsg("\t%s", it->c_str()); + } + + if (!javaExePath.empty() && javaClientDllPath.empty() && javaServerDllPath.empty()) { + logMsg("Found only java.exe at %s. No DLLs. Falling back to java.exe\n", javaExePath.c_str()); + separateProcess = true; + } else { + if (javaExePath.empty() || (javaClientDllPath.empty() && javaServerDllPath.empty())) { + if (!initialize("")) { + return false; + } + } + } + + if (!separateProcess) { + // both client/server found, check option which should be used + if (!javaClientDllPath.empty() && !javaServerDllPath.empty()) { + javaDllPath = findClientOption(options) ? javaClientDllPath : javaServerDllPath; + } else { + javaDllPath = javaClientDllPath.empty() ? javaServerDllPath : javaClientDllPath; + } + + // it is necessary to absolutize dll path because current dir has to be + // temporarily changed for dll loading + char absoluteJavaDllPath[MAX_PATH] = ""; + strncpy(absoluteJavaDllPath, javaDllPath.c_str(), MAX_PATH); + normalizePath(absoluteJavaDllPath, MAX_PATH); + javaDllPath = absoluteJavaDllPath; + + logMsg("Java DLL path: %s", javaDllPath.c_str()); + if (!canLoadJavaDll()) { + logMsg("Falling back to running Java in a separate process; DLL cannot be loaded (64-bit DLL?)."); + separateProcess = true; + } + } + + return separateProcess ? startOutProcJvm(mainClassName, args, options, retCode) + : startInProcJvm(mainClassName, args, options); +} + +bool JvmLauncher::findClientOption(const list &options) { + for (list::const_iterator it = options.begin(); it != options.end(); ++it) { + if (*it == "-client") { + return true; + } + } + return false; +} + +bool JvmLauncher::canLoadJavaDll() { + // be prepared for stupid placement of msvcr71.dll in java installation + // (in java 1.6/1.7 jvm.dll is dynamically linked to msvcr71.dll which si placed + // in bin directory) + PrepareDllPath prepare(javaBinPath.c_str()); + HMODULE hDll = LoadLibrary(javaDllPath.c_str()); + if (hDll) { + FreeLibrary(hDll); + return true; + } + logErr(true, false, "Cannot load %s.", javaDllPath.c_str()); + return false; +} + +bool JvmLauncher::isVersionString(const char *str) { + char *end = 0; + strtod(str, &end); + return *end == '\0'; +} + +bool JvmLauncher::startInProcJvm(const char *mainClassName, const std::list &args, const std::list &options) { + class Jvm { + public: + + Jvm(JvmLauncher *jvmLauncher) + : hDll(0) + , hSplash(0) + , jvm(0) + , env(0) + , jvmOptions(0) + , jvmLauncher(jvmLauncher) + { + } + + ~Jvm() { + if (env && env->ExceptionOccurred()) { + env->ExceptionDescribe(); + } + + if (jvm) { + logMsg("Destroying JVM"); + jvm->DestroyJavaVM(); + } + + if (jvmOptions) { + delete[] jvmOptions; + } + + if (hDll) { + FreeLibrary(hDll); + } + if (hSplash) { + FreeLibrary(hSplash); + } + } + + bool init(const list &options) { + logMsg("JvmLauncher::Jvm::init()"); + logMsg("LoadLibrary(\"%s\")", jvmLauncher->javaDllPath.c_str()); + { + PrepareDllPath prepare(jvmLauncher->javaBinPath.c_str()); + hDll = LoadLibrary(jvmLauncher->javaDllPath.c_str()); + if (!hDll) { + logErr(true, true, "Cannot load %s.", jvmLauncher->javaDllPath.c_str()); + return false; + } + + string pref = jvmLauncher->javaBinPath; + pref += "\\splashscreen.dll"; + const string splash = pref; + logMsg("Trying to load %s", splash.c_str()); + hSplash = LoadLibrary(splash.c_str()); + logMsg("Splash loaded as %d", hSplash); + } + + CreateJavaVM createJavaVM = (CreateJavaVM) GetProcAddress(hDll, JNI_CREATEVM_FUNC); + if (!createJavaVM) { + logErr(true, true, "GetProcAddress for %s failed.", JNI_CREATEVM_FUNC); + return false; + } + + logMsg("JVM options:"); + jvmOptions = new JavaVMOption[options.size() + 1]; + int i = 0; + for (list::const_iterator it = options.begin(); it != options.end(); ++it, ++i) { + const string &option = *it; + logMsg("\t%s", option.c_str()); + if (option.find("-splash:") == 0 && hSplash > 0) { + const string splash = option.substr(8); + logMsg("splash at %s", splash.c_str()); + + SplashInit splashInit = (SplashInit)GetProcAddress(hSplash, "SplashInit"); + SplashLoadFile splashLoadFile = (SplashLoadFile)GetProcAddress(hSplash, "SplashLoadFile"); + + logMsg("splash init %d and load %d", splashInit, splashLoadFile); + if (splashInit && splashLoadFile) { + splashInit(); + splashLoadFile(splash.c_str()); + } + } + jvmOptions[i].optionString = (char *) option.c_str(); + jvmOptions[i].extraInfo = 0; + } + JavaVMInitArgs jvmArgs; + jvmOptions[options.size()].optionString = (char *) "exit"; + jvmOptions[options.size()].extraInfo = (void *) &exitHook; + + jvmArgs.options = jvmOptions; + jvmArgs.nOptions = options.size() + 1; + jvmArgs.version = JNI_VERSION_1_4; + jvmArgs.ignoreUnrecognized = JNI_TRUE; + + logMsg("Creating JVM..."); + if (createJavaVM(&jvm, &env, &jvmArgs) < 0) { + logErr(false, true, "JVM creation failed"); + return false; + } + logMsg("JVM created."); + return true; + } + typedef jint (CALLBACK *CreateJavaVM)(JavaVM **jvm, JNIEnv **env, void *args); + typedef void (CALLBACK *SplashInit)(); + typedef int (CALLBACK *SplashLoadFile)(const char* file); + + HMODULE hDll; + HMODULE hSplash; + JavaVM *jvm; + JNIEnv *env; + JavaVMOption *jvmOptions; + JvmLauncher *jvmLauncher; + }; + + Jvm jvm(this); + if (!jvm.init(options)) { + return false; + } + + jclass mainClass = jvm.env->FindClass(mainClassName); + if (!mainClass) { + logErr(false, true, "Cannot find class %s.", mainClassName); + return false; + } + + jmethodID mainMethod = jvm.env->GetStaticMethodID(mainClass, "main", "([Ljava/lang/String;)V"); + if (!mainMethod) { + logErr(false, true, "Cannot get main method."); + return false; + } + + jclass jclassString = jvm.env->FindClass("java/lang/String"); + if (!jclassString) { + logErr(false, true, "Cannot find java/lang/String class"); + return false; + } + + jstring jstringArg = jvm.env->NewStringUTF(""); + if (!jstringArg) { + logErr(false, true, "NewStringUTF() failed"); + return false; + } + + jobjectArray mainArgs = jvm.env->NewObjectArray(args.size(), jclassString, jstringArg); + if (!mainArgs) { + logErr(false, true, "NewObjectArray() failed"); + return false; + } + int i = 0; + for (list::const_iterator it = args.begin(); it != args.end(); ++it, ++i) { + const string &arg = *it; + const int len = 32*1024; + char utf8[len] = ""; + if (convertAnsiToUtf8(arg.c_str(), utf8, len)) + logMsg("Conversion to UTF8 failed"); + jstring jstringArg = jvm.env->NewStringUTF(utf8); + if (!jstringArg) { + logErr(false, true, "NewStringUTF() failed"); + return false; + } + jvm.env->SetObjectArrayElement(mainArgs, i, jstringArg); + } + + jvm.env->CallStaticVoidMethod(mainClass, mainMethod, mainArgs); + return true; +} + + +bool JvmLauncher::startOutProcJvm(const char *mainClassName, const std::list &args, const std::list &options, DWORD *retCode) { + string cmdLine = '\"' + (suppressConsole ? javawExePath : javaExePath) + '\"'; + cmdLine.reserve(32*1024); + for (list::const_iterator it = options.begin(); it != options.end(); ++it) { + cmdLine += " \""; + cmdLine += *it; + cmdLine += "\""; + } + + // mainClass and args + cmdLine += ' '; + cmdLine += mainClassName; + for (list::const_iterator it = args.begin(); it != args.end(); ++it) { + if (javaClientDllPath.empty() && *it == "-client") { + logMsg("Removing -client option, client java dll not found."); + // remove client parameter, no client java found + continue; + } + cmdLine += " \""; + cmdLine += *it; + cmdLine += "\""; + } + + logMsg("Command line:\n%s", cmdLine.c_str()); + if (cmdLine.size() >= 32*1024) { + logErr(false, true, "Command line is too long. Length: %u. Maximum length: %u.", cmdLine.c_str(), 32*1024); + return false; + } + + STARTUPINFO si = {0}; + si.cb = sizeof (STARTUPINFO); + PROCESS_INFORMATION pi = {0}; + + char cmdLineStr[32*1024] = ""; + strcpy(cmdLineStr, cmdLine.c_str()); + if (!CreateProcess(NULL, cmdLineStr, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) { + logErr(true, true, "Failed to create process"); + return false; + } + + disableFolderVirtualization(pi.hProcess); + ResumeThread(pi.hThread); + WaitForSingleObject(pi.hProcess, INFINITE); + if (retCode) { + GetExitCodeProcess(pi.hProcess, retCode); + } + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return true; +} + +bool JvmLauncher::findJava(const char *minJavaVersion) { + // scan for registry for jdk/jre version 9 + if (findJava(JDK_POST9_KEY, "", minJavaVersion)) { + return true; + } + if (findJava(JRE_POST9_KEY, "", minJavaVersion)) { + return true; + } + if (findJava(JDK_KEY, JAVA_JRE_PREFIX, minJavaVersion)) { + return true; + } + if (findJava(JRE_KEY, "", minJavaVersion)) { + return true; + } + javaPath = ""; + javaExePath = ""; + javaClientDllPath = ""; + javaServerDllPath = ""; + javaBinPath = ""; + return false; +} + +bool JvmLauncher::findJava(const char *javaKey, const char *prefix, const char *minJavaVersion) { + logMsg("JvmLauncher::findJava()\n\tjavaKey: %s\n\tprefix: %s\n\tminJavaVersion: %s", javaKey, prefix, minJavaVersion); + string value; + bool result = false; + if (getStringFromRegistry(HKEY_LOCAL_MACHINE, javaKey, CUR_VERSION_NAME, value)) { + if (value >= minJavaVersion) { + string path; + if (getStringFromRegistry(HKEY_LOCAL_MACHINE, (string(javaKey) + "\\" + value).c_str(), JAVA_HOME_NAME, path)) { + if (*path.rbegin() == '\\') { + path.erase(path.length() - 1, 1); + } + result = checkJava(path.c_str(), prefix); + } + } + } + if(!result && isWow64()) { + if (getStringFromRegistry64bit(HKEY_LOCAL_MACHINE, javaKey, CUR_VERSION_NAME, value)) { + if (value >= minJavaVersion) { + string path; + if (getStringFromRegistry64bit(HKEY_LOCAL_MACHINE, (string(javaKey) + "\\" + value).c_str(), JAVA_HOME_NAME, path)) { + if (*path.rbegin() == '\\') { + path.erase(path.length() - 1, 1); + } + result = checkJava(path.c_str(), prefix); + } + } + } + } + // probably also need to check 32bit registry when launcher becomes 64-bit but is not the case now. + return result; +} diff --git a/platform/o.n.bootstrap/launcher/windows/jvmlauncher.h b/platform/o.n.bootstrap/launcher/windows/jvmlauncher.h new file mode 100644 index 000000000000..01f4e3448c97 --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/jvmlauncher.h @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + +#ifndef _JVMLAUNCHER_H +#define _JVMLAUNCHER_H + +#include +#include +#include +#include "jni.h" +#include "utilsfuncs.h" + +class JvmLauncher { + static const int MAX_ARGS_LEN = 32*1024; + + static const char *JDK_KEY; + static const char *JRE_KEY; + // registry key change starting with version 9 + static const char *JDK_POST9_KEY; + static const char *JRE_POST9_KEY; + static const char *CUR_VERSION_NAME; + static const char *JAVA_HOME_NAME; + static const char *JAVA_BIN_DIR; + static const char *JAVA_EXE_FILE; + static const char *JAVAW_EXE_FILE; + static const char *JAVA_CLIENT_DLL_FILE; + static const char *JAVA_SERVER_DLL_FILE; + static const char *JAVA_JRE_PREFIX; + static const char *JNI_CREATEVM_FUNC; + +public: + JvmLauncher(); + virtual ~JvmLauncher(); + + bool initialize(const char *javaPathOrMinVersion); + bool getJavaPath(std::string &path); + bool start(const char *mainClassName, const std::list &args, const std::list &options, bool &separateProcess, DWORD *retCode); + + void setSuppressConsole(bool val) { + suppressConsole = val; + } + +private: + JvmLauncher(const JvmLauncher& orig); + + bool checkJava(const char *javaPath, const char *prefix); + bool findJava(const char *minJavaVersion); + bool findJava(const char *javaKey, const char *prefix, const char *minJavaVersion); + bool startOutProcJvm(const char *mainClassName, const std::list &args, const std::list &options, DWORD *retCode); + bool startInProcJvm(const char *mainClassName, const std::list &args, const std::list &options); + bool isVersionString(const char *str); + bool canLoadJavaDll(); + bool findClientOption(const std::list &options); + +private: + bool suppressConsole; + std::string javaExePath; + std::string javawExePath; + std::string javaDllPath; + std::string javaClientDllPath; + std::string javaServerDllPath; + std::string javaPath; + std::string javaBinPath; + + class PrepareDllPath { + public: + PrepareDllPath(const char *dllDirectory) + : setDllDirectory(0) { + logMsg("PrepareDllPath: %s", dllDirectory); + oldCurDir[0] = '\0'; + + // SetDllDirectory is present since XP SP1, so we have to load it dynamically + HINSTANCE hKernel32 = GetModuleHandle("kernel32"); + if (!hKernel32) { + logErr(true, false, "Cannot load kernel32."); + return; + } + + LPFNSDD setDllDirectory = (LPFNSDD)GetProcAddress(hKernel32, "SetDllDirectoryA"); + if (setDllDirectory) { + setDllDirectory(dllDirectory); + } else { + logErr(true, false, "Cannot find SetDllDirectoryA"); + } + GetCurrentDirectory(MAX_PATH, oldCurDir); + SetCurrentDirectory(dllDirectory); + } + ~PrepareDllPath() { + if (setDllDirectory) { + setDllDirectory(NULL); + } + if (oldCurDir[0]) { + SetCurrentDirectory(oldCurDir); + } + } + private: + typedef BOOL (WINAPI *LPFNSDD)(LPCTSTR lpPathname); + LPFNSDD setDllDirectory; + char oldCurDir[MAX_PATH]; + }; +}; + +#endif /* _JVMLAUNCHER_H */ + diff --git a/platform/o.n.bootstrap/launcher/windows/nbexec.cpp b/platform/o.n.bootstrap/launcher/windows/nbexec.cpp new file mode 100644 index 000000000000..47e490ebe465 --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/nbexec.cpp @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + +#include "platformlauncher.h" +#include "utilsfuncs.h" + +PlatformLauncher launcher; + +extern "C" BOOL APIENTRY DllMain(HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) { + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH: + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + launcher.onExit(); + break; + } + return TRUE; +} + +volatile int exitStatus = 0; + +void exitHook(int status) { + exitStatus = status; + logMsg("Exit hook called with status %d", status); + // do not handle possible restarts, if we are just CLI-connecting to a running process. + if (status != -252) { + launcher.onExit(); + } + logMsg("Exit hook terminated."); +} + +#define NBEXEC_EXPORT extern "C" __declspec(dllexport) + +NBEXEC_EXPORT int startPlatform(int argc, char *argv[], const char *helpMsg) { + DWORD retCode = 0; + launcher.appendToHelp(helpMsg); + launcher.setSuppressConsole(!isConsoleAttached()); + if (!launcher.start(argv, argc, &retCode)) { + return -1; + } + return retCode; +} + + diff --git a/platform/o.n.bootstrap/launcher/windows/nbexec.exe.manifest b/platform/o.n.bootstrap/launcher/windows/nbexec.exe.manifest new file mode 100644 index 000000000000..580bb41e424e --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/nbexec.exe.manifest @@ -0,0 +1,75 @@ + + + + + +nbexec process + + + + + + + + + + + + + + + + + UTF-8 + + + + + + true/PM + PerMonitorV2, PerMonitor, system + + + + + + + + + + + + + diff --git a/platform/o.n.bootstrap/launcher/windows/nbexec.rc b/platform/o.n.bootstrap/launcher/windows/nbexec.rc new file mode 100644 index 000000000000..b0843afe3b43 --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/nbexec.rc @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include + +#define FNAME "nbexec.dll" +#define FILETYPE_ID 0x2L + +#include "version.rc" + diff --git a/platform/o.n.bootstrap/launcher/windows/nbexec_exe.rc b/platform/o.n.bootstrap/launcher/windows/nbexec_exe.rc new file mode 100644 index 000000000000..df75c0b3bd69 --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/nbexec_exe.rc @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include + +#define FNAME "nbexec.exe" +#define FILETYPE_ID 0x1L + +#include "version.rc" + +// Value MANIFEST_FILE id taken from windres parameter -DMANIFEST_FILE +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST MANIFEST_FILE + diff --git a/platform/o.n.bootstrap/launcher/windows/nbexecexe.cpp b/platform/o.n.bootstrap/launcher/windows/nbexecexe.cpp new file mode 100644 index 000000000000..181a365d1fb4 --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/nbexecexe.cpp @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + +#include +#include "nbexecloader.h" + +int main(int argc, char *argv[]) { + checkLoggingArg(argc, argv, true); + NBExecLoader loader; + + // NBEXEC_DLL specified in preprocessor definitions + return loader.start(NBEXEC_DLL, argc - 1, argv + 1); +} diff --git a/platform/o.n.bootstrap/launcher/windows/nbexecloader.h b/platform/o.n.bootstrap/launcher/windows/nbexecloader.h new file mode 100644 index 000000000000..221a55764c74 --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/nbexecloader.h @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _NBEXECLOADER_H +#define _NBEXECLOADER_H + +#include "utilsfuncs.h" + +#define HELP_MSG \ +"\ + --console suppress supppress console output\n\ + --console new open new console for output\n\ +\n" + +class NBExecLoader { + typedef int (*StartPlatform)(int argc, char *argv[], const char *help); + +public: + NBExecLoader() + : hLib(0) { + } + ~NBExecLoader() { + if (hLib) { + FreeLibrary(hLib); + } + } + int start(const char *path, int argc, char *argv[]) { + if (!hLib) { + hLib = LoadLibrary(path); + if (!hLib) { + logErr(true, true, "Cannot load \"%s\".", path); + return -1; + } + } + + StartPlatform startPlatform = (StartPlatform) GetProcAddress(hLib, "startPlatform"); + if (!startPlatform) { + logErr(true, true, "Cannot start platform, failed to find startPlatform() in %s", path); + return -1; + } + logMsg("Starting platform...\n"); + return startPlatform(argc, argv, HELP_MSG); + } + +private: + HMODULE hLib; +}; + +#endif /* _NBEXECLOADER_H */ + diff --git a/platform/o.n.bootstrap/launcher/windows/platformlauncher.cpp b/platform/o.n.bootstrap/launcher/windows/platformlauncher.cpp new file mode 100644 index 000000000000..76fc6fc204f7 --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/platformlauncher.cpp @@ -0,0 +1,735 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + +#include "utilsfuncs.h" +#include "platformlauncher.h" +#include "argnames.h" + +volatile extern int exitStatus; + +using namespace std; + +const char *PlatformLauncher::HELP_MSG = +"\nUsage: launcher {options} arguments\n\ +\n\ +General options:\n\ + --help show this help\n\ + --jdkhome path to JDK\n\ + -J pass to JVM\n\ +\n\ + --cp:p prepend to classpath\n\ + --cp:a append to classpath\n\ +\n\ + --fork-java run java in separate process\n\ + --trace path for launcher log (for trouble shooting)\n\ +\n"; + +const char *PlatformLauncher::REQ_JAVA_VERSION = "1.8"; + +const char *PlatformLauncher::OPT_JDK_HOME = "-Djdk.home="; +const char *PlatformLauncher::OPT_NB_PLATFORM_HOME = "-Dnetbeans.home="; +const char *PlatformLauncher::OPT_NB_CLUSTERS = "-Dnetbeans.dirs="; +const char *PlatformLauncher::OPT_NB_USERDIR = "-Dnetbeans.user="; +const char *PlatformLauncher::OPT_DEFAULT_USERDIR_ROOT = "-Dnetbeans.default_userdir_root="; +const char *PlatformLauncher::OPT_HEAP_DUMP = "-XX:+HeapDumpOnOutOfMemoryError"; +const char *PlatformLauncher::OPT_HEAP_DUMP_PATH = "-XX:HeapDumpPath="; +const char *PlatformLauncher::OPT_JAVA_SECURITY_MANAGER_ALLOW = "-Djava.security.manager=allow"; +const char *PlatformLauncher::OPT_KEEP_WORKING_SET_ON_MINIMIZE = "-Dsun.awt.keepWorkingSetOnMinimize=true"; +const char *PlatformLauncher::OPT_CLASS_PATH = "-Djava.class.path="; +const char *PlatformLauncher::OPT_SPLASH = "-splash:"; +const char *PlatformLauncher::OPT_SPLASH_PATH = "\\var\\cache\\splash.png"; + +const char *PlatformLauncher::HEAP_DUMP_PATH = "\\var\\log\\heapdump.hprof"; +const char *PlatformLauncher::RESTART_FILE_PATH = "\\var\\restart"; + +const char *PlatformLauncher::UPDATER_MAIN_CLASS = "org/netbeans/updater/UpdaterFrame"; +const char *PlatformLauncher::IDE_MAIN_CLASS = "org/netbeans/Main"; + +PlatformLauncher::PlatformLauncher() + : separateProcess(false) + , suppressConsole(false) + , heapDumpPathOptFound(false) + , nosplash(false) + , exiting(false) { +} + +PlatformLauncher::PlatformLauncher(const PlatformLauncher& orig) { +} + +PlatformLauncher::~PlatformLauncher() { +} + +bool PlatformLauncher::start(char* argv[], int argc, DWORD *retCode) { + if (!checkLoggingArg(argc, argv, false) || !initPlatformDir() || !parseArgs(argc, argv)) { + return false; + } + disableFolderVirtualization(GetCurrentProcess()); + + if (jdkhome.empty()) { + if (!jvmLauncher.initialize(REQ_JAVA_VERSION)) { + logErr(false, true, "Cannot find Java %s or higher.", REQ_JAVA_VERSION); + return false; + } + } + jvmLauncher.getJavaPath(jdkhome); + + deleteNewClustersFile(); + prepareOptions(); + + if (nextAction.empty()) { + if (shouldAutoUpdateClusters(true)) { + // run updater + if (!run(true, retCode)) { + return false; + } + } + + while (true) { + // run app + if (!run(false, retCode)) { + return false; + } + + if (shouldAutoUpdateClusters(false)) { + // run updater + if (!run(true, retCode)) { + return false; + } + } else if (!restartRequested()) { + break; + } + } + } else { + if (nextAction == ARG_NAME_LA_START_APP) { + return run(false, retCode); + } else if (nextAction == ARG_NAME_LA_START_AU) { + if (shouldAutoUpdateClusters(false)) { + return run(true, retCode); + } + } else { + logErr(false, true, "We should not get here."); + return false; + } + } + + return true; +} + +bool PlatformLauncher::run(bool updater, DWORD *retCode) { + logMsg(updater ? "Starting updater..." : "Starting application..."); + constructClassPath(updater); + const char *mainClass; + if (updater) { + mainClass = UPDATER_MAIN_CLASS; + nextAction = ARG_NAME_LA_START_APP; + } else { + DeleteFile((userDir + RESTART_FILE_PATH).c_str()); + mainClass = bootclass.empty() ? IDE_MAIN_CLASS : bootclass.c_str(); + nextAction = ARG_NAME_LA_START_AU; + } + + string option = OPT_NB_CLUSTERS; + option += auClusters.empty() ? clusters : auClusters; + javaOptions.push_back(option); + + option = OPT_CLASS_PATH; + option += classPath; + javaOptions.push_back(option); + + jvmLauncher.setSuppressConsole(suppressConsole); + bool rc = jvmLauncher.start(mainClass, progArgs, javaOptions, separateProcess, retCode); + if (!separateProcess) { + exit(0); + } + + javaOptions.pop_back(); + javaOptions.pop_back(); + return rc; +} + + + +bool PlatformLauncher::initPlatformDir() { + char path[MAX_PATH] = ""; + getCurrentModulePath(path, MAX_PATH); + logMsg("Module: %s", path); + char *bslash = strrchr(path, '\\'); + if (!bslash) { + return false; + } + *bslash = '\0'; + bslash = strrchr(path, '\\'); + if (!bslash) { + return false; + } + *bslash = '\0'; + clusters = platformDir = path; + logMsg("Platform dir: %s", platformDir.c_str()); + return true; +} + +bool PlatformLauncher::parseArgs(int argc, char *argv[]) { +#define CHECK_ARG \ + if (i+1 == argc) {\ + logErr(false, true, "Argument is missing for \"%s\" option.", argv[i]);\ + return false;\ + } + + logMsg("Parsing arguments:"); + for (int i = 0; i < argc; i++) { + logMsg("\t%s", argv[i]); + } + + for (int i = 0; i < argc; i++) { + if (strcmp(ARG_NAME_SEPAR_PROC, argv[i]) == 0) { + separateProcess = true; + logMsg("Run Java in separater process"); + } else if (strcmp(ARG_NAME_LAUNCHER_LOG, argv[i]) == 0) { + CHECK_ARG; + i++; + } else if (strcmp(ARG_NAME_LA_START_APP, argv[i]) == 0 + || strcmp(ARG_NAME_LA_START_AU, argv[i]) == 0) { + nextAction = argv[i]; + logMsg("Next launcher action: %s", nextAction.c_str()); + } else if (strcmp(ARG_NAME_LA_PPID, argv[i]) == 0) { + CHECK_ARG; + suppressConsole = false; + parentProcID = argv[++i]; + logMsg("Parent process ID found: %s", parentProcID.c_str()); + } else if (strcmp(ARG_NAME_USER_DIR, argv[i]) == 0) { + CHECK_ARG; + char tmp[MAX_PATH + 1] = {0}; + strncpy(tmp, argv[++i], MAX_PATH); + if (strcmp(tmp, "memory") != 0 && !normalizePath(tmp, MAX_PATH)) { + logErr(false, true, "User directory path \"%s\" is not valid.", argv[i]); + return false; + } + userDir = tmp; + logMsg("User dir: %s", userDir.c_str()); + } else if (strcmp(ARG_DEFAULT_USER_DIR_ROOT, argv[i]) == 0) { + CHECK_ARG; + char tmp[MAX_PATH + 1] = {0}; + strncpy(tmp, argv[++i], MAX_PATH); + if (strcmp(tmp, "memory") != 0 && !normalizePath(tmp, MAX_PATH)) { + logErr(false, true, "Default User directory path \"%s\" is not valid.", argv[i]); + return false; + } + defaultUserDirRoot = tmp; + logMsg("Default Userdir root: %s", defaultUserDirRoot.c_str()); + } else if (strcmp(ARG_NAME_CLUSTERS, argv[i]) == 0) { + CHECK_ARG; + clusters = argv[++i]; + } else if (strcmp(ARG_NAME_BOOTCLASS, argv[i]) == 0) { + CHECK_ARG; + bootclass = argv[++i]; + } else if (strcmp(ARG_NAME_JDKHOME, argv[i]) == 0) { + CHECK_ARG; + if (jdkhome.empty()) { + jdkhome = argv[++i]; + if (!jvmLauncher.initialize(jdkhome.c_str())) { + logMsg("Cannot locate java installation in specified jdkhome: %s", jdkhome.c_str()); + string errMsg = "Cannot locate java installation in specified jdkhome:\n"; + errMsg += jdkhome; + errMsg += "\nDo you want to try to use default version?"; + jdkhome = ""; + if (::MessageBox(NULL, errMsg.c_str(), "Invalid jdkhome specified", MB_ICONQUESTION | MB_YESNO) == IDNO) { + return false; + } + } + } else { + i++; + } + } else if (strcmp(ARG_NAME_CP_PREPEND, argv[i]) == 0 + || strcmp(ARG_NAME_CP_PREPEND + 1, argv[i]) == 0) { + CHECK_ARG; + cpBefore += argv[++i]; + } else if (strcmp(ARG_NAME_CP_APPEND, argv[i]) == 0 + || strcmp(ARG_NAME_CP_APPEND + 1, argv[i]) == 0 + || strncmp(ARG_NAME_CP_APPEND + 1, argv[i], 3) == 0 + || strncmp(ARG_NAME_CP_APPEND, argv[i], 4) == 0) { + CHECK_ARG; + cpAfter += argv[++i]; + } else if (strncmp("-J", argv[i], 2) == 0) { + javaOptions.push_back(argv[i] + 2); + if (strncmp(argv[i] + 2, OPT_HEAP_DUMP_PATH, strlen(OPT_HEAP_DUMP_PATH)) == 0) { + heapDumpPathOptFound = true; + } + } else { + if (strcmp(argv[i], "-h") == 0 + || strcmp(argv[i], "-help") == 0 + || strcmp(argv[i], "--help") == 0 + || strcmp(argv[i], "/?") == 0) { + printToConsole(HELP_MSG); + if (!appendHelp.empty()) { + printToConsole(appendHelp.c_str()); + } + } else if (strcmp(ARG_NAME_NOSPLASH, argv[i]) == 0) { + nosplash = true; + } + progArgs.push_back(argv[i]); + } + } + return true; +} + +bool PlatformLauncher::processAutoUpdateCL() { + logMsg("processAutoUpdateCL()..."); + if (userDir.empty()) { + logMsg("\tuserdir empty, quiting"); + return false; + } + string listPath = userDir; + listPath += "\\update\\download\\netbeans.dirs"; + + WIN32_FIND_DATA fd = {0}; + HANDLE hFind = 0; + hFind = FindFirstFile(listPath.c_str(), &fd); + if (hFind == INVALID_HANDLE_VALUE) { + logMsg("File \"%s\" does not exist", listPath.c_str()); + return false; + } + FindClose(hFind); + + FILE *file = fopen(listPath.c_str(), "r"); + if (!file) { + logErr(true, false, "Cannot open file %s", listPath.c_str()); + return false; + } + + int len = fd.nFileSizeLow + 1; + char *str = new char[len]; + if (!fgets(str, len, file)) { + fclose(file); + delete[] str; + logErr(true, false, "Cannot read from file %s", listPath.c_str()); + return false; + } + len = strlen(str) - 1; + if (str[len] == '\n') { + str[len] = '\0'; + } + + auClusters = str; + fclose(file); + delete[] str; + return true; +} + +void PlatformLauncher::deleteNewClustersFile() { + logMsg("deleteNewClustersFile()..."); + if (userDir.empty()) { + logMsg("\tuserdir empty, quiting"); + return; + } + string listPath = userDir; + listPath += "\\update\\download\\netbeans.dirs"; + + if (fileExists(listPath.c_str())) { + DeleteFileA(listPath.c_str()); + logMsg("%s file deleted.", listPath.c_str()); + } +} + +// check if new updater exists, if exists install it (replace old one) and remove ...\new_updater directory +bool PlatformLauncher::checkForNewUpdater(const char *basePath) { + logMsg("checkForNewUpdater() at %s", basePath); + BOOL removeDir = false; + string srcPath = basePath; + srcPath += "\\update\\new_updater\\updater.jar"; + WIN32_FIND_DATA fd = {0}; + HANDLE hFind = FindFirstFile(srcPath.c_str(), &fd); + if (hFind != INVALID_HANDLE_VALUE) { + logMsg("New updater found: %s", srcPath.c_str()); + FindClose(hFind); + string destPath = basePath; + destPath += "\\modules\\ext\\updater.jar"; + createPath(destPath.c_str()); + + int i = 0; + while (true) { + if (MoveFileEx(srcPath.c_str(), destPath.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) { + break; + } + if (exiting || ++i > 10) { + logErr(true, false, "Failed to move \"%s\" to \"%s\"", srcPath.c_str(), destPath.c_str()); + return false; + } + logErr(true, false, "Failed to move \"%s\" to \"%s\", trying to wait", srcPath.c_str(), destPath.c_str()); + Sleep(100); + } + logMsg("New updater successfully moved from \"%s\" to \"%s\"", srcPath.c_str(), destPath.c_str()); + removeDir = true; + } else { + logMsg("No new updater at %s", srcPath.c_str()); + } + string locPath = basePath; + locPath += "\\update\\new_updater\\updater_*.jar"; + hFind = FindFirstFile(locPath.c_str(), &fd); + while (hFind != INVALID_HANDLE_VALUE) { + string destPath = basePath; + string name = fd.cFileName; + logMsg("New updater localization found: %s", name.c_str()); + destPath += "\\modules\\ext\\locale\\"; + destPath += name; + + string fromPath = basePath; + fromPath += "\\update\\new_updater\\"; + fromPath += name; + + createPath(destPath.c_str()); + + int i = 0; + while (true) { + if (MoveFileEx(fromPath.c_str(), destPath.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) { + break; + } + if (exiting || ++i > 10) { + logErr(true, false, "Failed to move \"%s\" to \"%s\"", fromPath.c_str(), destPath.c_str()); + return false; + } + logErr(true, false, "Failed to move \"%s\" to \"%s\", trying to wait", fromPath.c_str(), destPath.c_str()); + Sleep(100); + } + logMsg("New updater successfully moved from \"%s\" to \"%s\"", fromPath.c_str(), destPath.c_str()); + removeDir = true; + + if (!FindNextFile(hFind, &fd)) { + break; + } + } + FindClose(hFind); + + if (removeDir) { + srcPath.erase(srcPath.rfind('\\')); + logMsg("Removing directory \"%s\"", srcPath.c_str()); + if (!RemoveDirectory(srcPath.c_str())) { + logErr(true, false, "Failed to remove directory \"%s\"", srcPath.c_str()); + } + } + return true; +} + +bool PlatformLauncher::shouldAutoUpdate(bool firstStart, const char *basePath) { + // The logic is following: + // if there is an NBM for installation then run updater + // unless it is not a first start and we asked to install later (on next start) + + // then also check if last run left list of modules to disable/uninstall and + // did not mark them to be deactivated later (on next start) + string path = basePath; + path += "\\update\\download\\*.nbm"; + logMsg("Checking for updates: %s", path.c_str()); + WIN32_FIND_DATA fd; + HANDLE hFindNbms = FindFirstFile(path.c_str(), &fd); + if (hFindNbms != INVALID_HANDLE_VALUE) { + logMsg("Some updates found at %s", path.c_str()); + FindClose(hFindNbms); + } else { + //also check for OSGi jars if *.nbm not found + path = basePath; + path += "\\update\\download\\*.jar"; + hFindNbms = FindFirstFile(path.c_str(), &fd); + if (hFindNbms != INVALID_HANDLE_VALUE) { + logMsg("Some OSGi updates found at %s", path.c_str()); + FindClose(hFindNbms); + } + } + + path = basePath; + path += "\\update\\download\\install_later.xml"; + HANDLE hFind = FindFirstFile(path.c_str(), &fd); + if (hFind != INVALID_HANDLE_VALUE) { + logMsg("install_later.xml found: %s", path.c_str()); + FindClose(hFind); + } + + if (hFindNbms != INVALID_HANDLE_VALUE && (firstStart || hFind == INVALID_HANDLE_VALUE)) { + return true; + } + + path = basePath; + path += "\\update\\deactivate\\deactivate_later.txt"; + hFind = FindFirstFile(path.c_str(), &fd); + if (hFind != INVALID_HANDLE_VALUE) { + logMsg("deactivate_later.txt found: %s", path.c_str()); + FindClose(hFind); + } + + if (firstStart || hFind == INVALID_HANDLE_VALUE) { + path = basePath; + path += "\\update\\deactivate\\to_disable.txt"; + hFind = FindFirstFile(path.c_str(), &fd); + if (hFind != INVALID_HANDLE_VALUE) { + logMsg("to_disable.txt found: %s", path.c_str()); + FindClose(hFind); + return true; + } + + path = basePath; + path += "\\update\\deactivate\\to_uninstall.txt"; + hFind = FindFirstFile(path.c_str(), &fd); + if (hFind != INVALID_HANDLE_VALUE) { + logMsg("to_uninstall.txt found: %s", path.c_str()); + FindClose(hFind); + return true; + } + } + + return false; +} + +bool PlatformLauncher::shouldAutoUpdateClusters(bool firstStart) { + bool runUpdater = false; + string cl = processAutoUpdateCL() ? auClusters : clusters; + checkForNewUpdater(platformDir.c_str()); + runUpdater = shouldAutoUpdate(firstStart, platformDir.c_str()); + + const char delim = ';'; + string::size_type start = cl.find_first_not_of(delim, 0); + string::size_type end = cl.find_first_of(delim, start); + while (string::npos != end || string::npos != start) { + string cluster = cl.substr(start, end - start); + checkForNewUpdater(cluster.c_str()); + if (!runUpdater) { + runUpdater = shouldAutoUpdate(firstStart, cluster.c_str()); + } + start = cl.find_first_not_of(delim, end); + end = cl.find_first_of(delim, start); + } + + checkForNewUpdater(userDir.c_str()); + if (!runUpdater) { + runUpdater = shouldAutoUpdate(firstStart, userDir.c_str()); + } + return runUpdater; +} + +void PlatformLauncher::prepareOptions() { + string option = OPT_JDK_HOME; + option += jdkhome; + javaOptions.push_back(option); + + if (!nosplash) { + string splashPath = userDir; + splashPath += OPT_SPLASH_PATH; + if (fileExists(splashPath.c_str())) { + javaOptions.push_back(OPT_SPLASH + splashPath); + } + } + + option = OPT_NB_PLATFORM_HOME; + option += platformDir; + javaOptions.push_back(option); + + option = OPT_NB_USERDIR; + option += userDir; + javaOptions.push_back(option); + + option = OPT_DEFAULT_USERDIR_ROOT; + option += defaultUserDirRoot; + javaOptions.push_back(option); + + option = OPT_HEAP_DUMP; + javaOptions.push_back(option); + + if (!heapDumpPathOptFound) { + option = OPT_HEAP_DUMP_PATH; + option += userDir; + option += HEAP_DUMP_PATH; + javaOptions.push_back(option); + // rename old heap dump to .old + string heapdumpfile = userDir + HEAP_DUMP_PATH; + if (fileExists(heapdumpfile.c_str())) { + string heapdumpfileold = heapdumpfile + ".old"; + if (fileExists(heapdumpfileold.c_str())) { + DeleteFileA(heapdumpfileold.c_str()); + } + MoveFile (heapdumpfile.c_str(), heapdumpfileold.c_str()); + } + } + + option = OPT_KEEP_WORKING_SET_ON_MINIMIZE; + javaOptions.push_back(option); + + option = OPT_JAVA_SECURITY_MANAGER_ALLOW; + javaOptions.push_back(option); +} + +string & PlatformLauncher::constructClassPath(bool runUpdater) { + logMsg("constructClassPath()"); + addedToCP.clear(); + classPath = cpBefore; + + addJarsToClassPathFrom(userDir.c_str()); + addJarsToClassPathFrom(platformDir.c_str()); + + if (runUpdater) { + const char *baseUpdaterPath = userDir.c_str(); + string updaterPath = userDir + "\\modules\\ext\\updater.jar"; + + // if user updater does not exist, use updater from platform + if (!fileExists(updaterPath.c_str())) { + baseUpdaterPath = platformDir.c_str(); + updaterPath = platformDir + "\\modules\\ext\\updater.jar"; + } + + addToClassPath(updaterPath.c_str(), false); + addFilesToClassPath(baseUpdaterPath, "\\modules\\ext\\locale", "updater_*.jar"); + } + + addToClassPath((jdkhome + "\\lib\\dt.jar").c_str(), true); + addToClassPath((jdkhome + "\\lib\\tools.jar").c_str(), true); + + if (!cpAfter.empty()) { + addToClassPath(cpAfter.c_str(), false); + } + logMsg("ClassPath: %s", classPath.c_str()); + return classPath; +} + +void PlatformLauncher::addJarsToClassPathFrom(const char *dir) { + addFilesToClassPath(dir, "lib\\patches", "*.jar"); + addFilesToClassPath(dir, "lib\\patches", "*.zip"); + + addFilesToClassPath(dir, "lib", "*.jar"); + addFilesToClassPath(dir, "lib", "*.zip"); + + addFilesToClassPath(dir, "lib\\locale", "*.jar"); + addFilesToClassPath(dir, "lib\\locale", "*.zip"); +} + +void PlatformLauncher::addFilesToClassPath(const char *dir, const char *subdir, const char *pattern) { + logMsg("addFilesToClassPath()\n\tdir: %s\n\tsubdir: %s\n\tpattern: %s", dir, subdir, pattern); + string path = dir; + path += '\\'; + path += subdir; + path += '\\'; + + WIN32_FIND_DATA fd = {0}; + string patternPath = path + pattern; + HANDLE hFind = FindFirstFile(patternPath.c_str(), &fd); + if (hFind == INVALID_HANDLE_VALUE) { + logMsg("Nothing found (%s)", patternPath.c_str()); + return; + } + do { + string name = subdir; + name += fd.cFileName; + string fullName = path + fd.cFileName; + if (addedToCP.insert(name).second) { + addToClassPath(fullName.c_str()); + } else { + logMsg("\"%s\" already added, skipping \"%s\"", name.c_str(), fullName.c_str()); + } + } while (FindNextFile(hFind, &fd)); + FindClose(hFind); +} + +void PlatformLauncher::addToClassPath(const char *path, bool onlyIfExists) { + logMsg("addToClassPath()\n\tpath: %s\n\tonlyIfExists: %s", path, onlyIfExists ? "true" : "false"); + if (onlyIfExists && !fileExists(path)) { + return; + } + + if (!classPath.empty()) { + classPath += ';'; + } + classPath += path; +} + +void PlatformLauncher::appendToHelp(const char *msg) { + if (msg) { + appendHelp = msg; + } +} + +bool PlatformLauncher::restartRequested() { + return fileExists((userDir + RESTART_FILE_PATH).c_str()); +} + +void PlatformLauncher::onExit() { + logMsg("onExit()"); + if (exitStatus == -252) { + logMsg("Exiting from CLI client, will not restart."); + return; + } + + if (exiting) { + logMsg("Already exiting, no need to schedule restart"); + return; + } + + exiting = true; + + if (separateProcess) { + logMsg("JVM in separate process, no need to restart"); + return; + } + + bool restart = (nextAction == ARG_NAME_LA_START_APP || (nextAction == ARG_NAME_LA_START_AU && shouldAutoUpdateClusters(false))); + if (!restart && restartRequested()) { + restart = true; + nextAction = ARG_NAME_LA_START_APP; + } + + if (restart) { + string cmdLine = GetCommandLine(); + logMsg("Old command line: %s", cmdLine.c_str()); + string::size_type bslashPos = cmdLine.find_last_of('\\'); + string::size_type pos = cmdLine.find(ARG_NAME_LA_START_APP); + if ((bslashPos == string::npos || bslashPos < pos) && pos != string::npos) { + cmdLine.erase(pos, strlen(ARG_NAME_LA_START_APP)); + } + pos = cmdLine.find(ARG_NAME_LA_START_AU); + if ((bslashPos == string::npos || bslashPos < pos) && pos != string::npos) { + cmdLine.erase(pos, strlen(ARG_NAME_LA_START_AU)); + } + + if (*cmdLine.rbegin() != ' ') { + cmdLine += ' '; + } + if (!parentProcID.empty() && cmdLine.find(ARG_NAME_LA_PPID) == string::npos) { + cmdLine += ARG_NAME_LA_PPID; + cmdLine += ' '; + cmdLine += parentProcID; + } + + if (*cmdLine.rbegin() != ' ') { + cmdLine += ' '; + } + cmdLine += nextAction; + + logMsg("New command line: %s", cmdLine.c_str()); + char cmdLineStr[32 * 1024] = ""; + strcpy(cmdLineStr, cmdLine.c_str()); + STARTUPINFO si = {0}; + PROCESS_INFORMATION pi = {0}; + si.cb = sizeof(STARTUPINFO); + + if (!CreateProcess(NULL, cmdLineStr, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { + logErr(true, true, "Failed to create process."); + return; + } + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + } +} diff --git a/platform/o.n.bootstrap/launcher/windows/platformlauncher.h b/platform/o.n.bootstrap/launcher/windows/platformlauncher.h new file mode 100644 index 000000000000..ac3e7be4b706 --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/platformlauncher.h @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + +#ifndef _PLATFORMLAUNCHER_H +#define _PLATFORMLAUNCHER_H + +#include "jvmlauncher.h" +#include +#include +#include + +class PlatformLauncher { + static const char *REQ_JAVA_VERSION; + static const char *HELP_MSG; + + static const char *HEAP_DUMP_PATH; + static const char *RESTART_FILE_PATH; + + static const char *OPT_JDK_HOME; + static const char *OPT_NB_PLATFORM_HOME; + static const char *OPT_NB_CLUSTERS; + static const char *OPT_NB_USERDIR; + static const char *OPT_DEFAULT_USERDIR_ROOT; + static const char *OPT_HEAP_DUMP; + static const char *OPT_HEAP_DUMP_PATH; + static const char *OPT_JAVA_SECURITY_MANAGER_ALLOW; + static const char *OPT_KEEP_WORKING_SET_ON_MINIMIZE; + static const char *OPT_CLASS_PATH; + static const char *OPT_SPLASH; + static const char *OPT_SPLASH_PATH; + + static const char *UPDATER_MAIN_CLASS; + static const char *IDE_MAIN_CLASS; + + +public: + PlatformLauncher(); + virtual ~PlatformLauncher(); + + bool start(char* argv[], int argc, DWORD *retCode); + void appendToHelp(const char *msg); + void onExit(); + + void setSuppressConsole(bool val) { + suppressConsole = val; + } + +private: + PlatformLauncher(const PlatformLauncher& orig); + bool parseArgs(int argc, char *argv[]); + bool initPlatformDir(); + bool processAutoUpdateCL(); + void deleteNewClustersFile(); + bool checkForNewUpdater(const char *basePath); + bool shouldAutoUpdate(bool firstStart, const char *basePath); + bool shouldAutoUpdateClusters(bool firstStart); + void prepareOptions(); + std::string & constructClassPath(bool runUpdater); + void addFilesToClassPath(const char *dir, const char *subdir, const char *pattern); + void addToClassPath(const char *path, bool onlyIfExists = false); + void addJarsToClassPathFrom(const char *dir); + bool run(bool updater, DWORD *retCode); + bool restartRequested(); + +private: + bool separateProcess; + bool suppressConsole; + bool heapDumpPathOptFound; + bool nosplash; + bool exiting; + std::string platformDir; + std::string userDir; + std::string defaultUserDirRoot; + std::string clusters; + std::string bootclass; + std::string jdkhome; + std::string cpBefore; + std::string cpAfter; + std::string auClusters; + std::string nextAction; + std::string parentProcID; + + std::list javaOptions; + std::list launcherOptions; + std::list progArgs; + JvmLauncher jvmLauncher; + std::set addedToCP; + std::string classPath; + std::string appendHelp; +}; + +#endif /* _PLATFORMLAUNCHER_H */ + diff --git a/platform/o.n.bootstrap/launcher/windows/utilsfuncs.cpp b/platform/o.n.bootstrap/launcher/windows/utilsfuncs.cpp new file mode 100644 index 000000000000..16c6ce07d81d --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/utilsfuncs.cpp @@ -0,0 +1,464 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + +#ifndef KEY_WOW64_64KEY +#define KEY_WOW64_64KEY 0x0100 +#endif + +#include "utilsfuncs.h" +#include "argnames.h" +#include +#include + +using namespace std; + +bool disableFolderVirtualization(HANDLE hProcess) { + OSVERSIONINFO osvi = {0}; + osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + if (GetVersionEx(&osvi) && osvi.dwMajorVersion == 6) // check it is Win VISTA + { + HANDLE hToken; + if (OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken)) { + DWORD tokenInfoVal = 0; + if (!SetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS) 24, &tokenInfoVal, sizeof (DWORD))) { + // invalid token information class (24) is OK, it means there is no folder virtualization on current system + if (GetLastError() != ERROR_INVALID_PARAMETER) { + logErr(true, true, "Failed to set token information."); + return false; + } + } + CloseHandle(hToken); + } else { + logErr(true, true, "Failed to open process token."); + return false; + } + } + return true; +} + +bool getStringFromRegistry(HKEY rootKey, const char *keyName, const char *valueName, string &value) { + return getStringFromRegistryEx(rootKey, keyName, valueName, value, false); +} + +bool getStringFromRegistry64bit(HKEY rootKey, const char *keyName, const char *valueName, string &value) { + return getStringFromRegistryEx(rootKey, keyName, valueName, value, true); +} + + + +bool getStringFromRegistryEx(HKEY rootKey, const char *keyName, const char *valueName, string &value, bool read64bit) { + logMsg("getStringFromRegistry()\n\tkeyName: %s\n\tvalueName: %s", keyName, valueName); + HKEY hKey = 0; + if (RegOpenKeyEx(rootKey, keyName, 0, KEY_READ | (read64bit ? KEY_WOW64_64KEY : 0), &hKey) == ERROR_SUCCESS) { + DWORD valSize = 4096; + DWORD type = 0; + char val[4096] = ""; + if (RegQueryValueEx(hKey, valueName, 0, &type, (BYTE *) val, &valSize) == ERROR_SUCCESS + && type == REG_SZ) { + logMsg("%s: %s", valueName, val); + RegCloseKey(hKey); + value = val; + return true; + } else { + logErr(true, false, "RegQueryValueEx() failed."); + } + RegCloseKey(hKey); + } else { + logErr(true, false, "RegOpenKeyEx() failed."); + } + return false; +} + +bool getDwordFromRegistry(HKEY rootKey, const char *keyName, const char *valueName, DWORD &value) { + logMsg("getDwordFromRegistry()\n\tkeyName: %s\n\tvalueName: %s", keyName, valueName); + HKEY hKey = 0; + if (RegOpenKeyEx(rootKey, keyName, 0, KEY_READ, &hKey) == ERROR_SUCCESS) { + DWORD valSize = sizeof(DWORD); + DWORD type = 0; + if (RegQueryValueEx(hKey, valueName, 0, &type, (BYTE *) &value, &valSize) == ERROR_SUCCESS + && type == REG_DWORD) { + logMsg("%s: %u", valueName, value); + RegCloseKey(hKey); + return true; + } else { + logErr(true, false, "RegQueryValueEx() failed."); + } + RegCloseKey(hKey); + } else { + logErr(true, false, "RegOpenKeyEx() failed."); + } + return false; +} + +bool dirExists(const char *path) { + WIN32_FIND_DATA fd = {0}; + HANDLE hFind = 0; + hFind = FindFirstFile(path, &fd); + if (hFind == INVALID_HANDLE_VALUE) { + logMsg("Dir \"%s\" does not exist", path); + return false; + } + logMsg("Dir \"%s\" exists", path); + FindClose(hFind); + return (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; +} + +bool fileExists(const char *path) { + WIN32_FIND_DATA fd = {0}; + HANDLE hFind = 0; + hFind = FindFirstFile(path, &fd); + if (hFind == INVALID_HANDLE_VALUE) { + logMsg("File \"%s\" does not exist", path); + return false; + } + + logMsg("File \"%s\" exists", path); + FindClose(hFind); + return true; +} + +bool normalizePath(char *path, int len) { + char tmp[MAX_PATH] = ""; + int i = 0; + while (path[i] && i < MAX_PATH - 1) { + tmp[i] = path[i] == '/' ? '\\' : path[i]; + i++; + } + tmp[i] = '\0'; + return _fullpath(path, tmp, len) != NULL; +} + +bool createPath(const char *path) { + logMsg("Creating directory \"%s\"", path); + char dir[MAX_PATH] = ""; + const char *sep = strchr(path, '\\'); + while (sep) { + strncpy(dir, path, sep - path); + if (!CreateDirectory(dir, 0) && GetLastError() != ERROR_ALREADY_EXISTS) { + logErr(true, false, "Failed to create directory %s", dir); + return false; + } + sep = strchr(sep + 1, '\\'); + } + return true; +} + + +char * getCurrentModulePath(char *path, int pathLen) { + MEMORY_BASIC_INFORMATION mbi; + static int dummy; + VirtualQuery(&dummy, &mbi, sizeof (mbi)); + HMODULE hModule = (HMODULE) mbi.AllocationBase; + GetModuleFileName(hModule, path, pathLen); + return path; +} + +char * skipWhitespaces(char *str) { + while (*str != '\0' && (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r')) { + str++; + } + return str; +} + +char * trimWhitespaces(char *str) { + char *end = str + strlen(str) - 1; + while (end >= str && (*end == ' ' || *end == '\t' || *end == '\n' || *end == '\r')) { + *end = '\0'; + end--; + } + return end; +} + +char* getSysError(char *str, int strSize) { + int err = GetLastError(); + LPTSTR lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) & lpMsgBuf, + 0, + NULL + ); + LPTSTR tmp = strchr(lpMsgBuf, '\r'); + if (tmp != NULL) { + *tmp = '\0'; + } + + _snprintf(str, strSize, " %s (%u)", lpMsgBuf, err); + LocalFree(lpMsgBuf); + return str; +} + +string gLogFileName; + +void logV(bool appendSysError, bool showMsgBox, const char *format, va_list args) { + char msg[4096] = ""; + vsnprintf(msg, 4096, format, args); + + if (appendSysError) { + char sysErr[512] = ""; + getSysError(sysErr, 512); + strncat(msg, sysErr, 4096 - strlen(msg)); + } + + if (!gLogFileName.empty()) { + FILE *file = fopen(gLogFileName.c_str(), "a"); + if (file) { + fprintf(file, "%s\n", msg); + fclose(file); + } + } + + if (showMsgBox) { + ::MessageBox(NULL, msg, "Error", MB_OK | MB_ICONSTOP); + } +} + +void logErr(bool appendSysError, bool showMsgBox, const char *format, ...) { + va_list args; + va_start(args, format); + logV(appendSysError, showMsgBox, format, args); +} + +void logMsg(const char *format, ...) { + va_list args; + va_start(args, format); + logV(false, false, format, args); +} + +bool restarting(int argc, char *argv[]) { + for (int i = 0; i < argc; i++) { + if (strcmp(ARG_NAME_LA_START_APP, argv[i]) == 0 || strcmp(ARG_NAME_LA_START_AU, argv[i]) == 0) { + return true; + } + } + return false; +} + +bool checkLoggingArg(int argc, char *argv[], bool delFile) { + for (int i = 0; i < argc; i++) { + if (strcmp(ARG_NAME_LAUNCHER_LOG, argv[i]) == 0) { + if (i + 1 == argc) { + logErr(false, true, "Argument is missing for \"%s\" option.", argv[i]); + return false; + } + gLogFileName = argv[++i]; + // if we are restarting, keep log file + if (delFile && !restarting(argc, argv)) { + DeleteFile(gLogFileName.c_str()); + } + break; + } + } + return true; +} + +void setConsoleCodepage() { + /* The Windows console (cmd) has its own code page setting that's usually different from the + system and user code page, e.g. on US Windows the console will use code page 437 while the + rest of the system uses 1252. Setting the console code page here to UTF-8 makes Unicode + characters printed from the application appear correctly. Since the launcher itself also runs + with UTF-8 as its code page (specified in the application manifest), this also makes log + messages from the launchers appear correctly, e.g. when printing paths that may have Unicode + characters in them. Note that if we attached to an existing console, the modified code page + setting will persist after the launcher exits. */ + SetConsoleOutputCP(CP_UTF8); + SetConsoleCP(CP_UTF8); +} + +bool setupProcess(int &argc, char *argv[], DWORD &parentProcID, const char *attachMsg) { +#define CHECK_ARG \ + if (i+1 == argc) {\ + logErr(false, true, "Argument is missing for \"%s\" option.", argv[i]);\ + return false;\ + } + + parentProcID = 0; + DWORD cmdLineArgPPID = 0; + for (int i = 0; i < argc; i++) { + if (strcmp(ARG_NAME_CONSOLE, argv[i]) == 0) { + CHECK_ARG; + if (strcmp("new", argv[i + 1]) == 0){ + AllocConsole(); + setConsoleCodepage(); + } else if (strcmp("suppress", argv[i + 1]) == 0) { + // nothing, no console should be attached + } else { + logErr(false, true, "Invalid argument for \"%s\" option.", argv[i]); + return false; + } + // remove options + for (int k = i + 2; k < argc; k++) { + argv[k-2] = argv[k]; + } + argc -= 2; + return true; + } else if (strcmp(ARG_NAME_LA_PPID, argv[i]) == 0) { + CHECK_ARG; + char *end = 0; + cmdLineArgPPID = strtoul(argv[++i], &end, 10); + if (cmdLineArgPPID == 0 && *end != '\0') { + logErr(false, true, "Invalid parameter for option %s", ARG_NAME_LA_PPID); + return false; + } + logMsg("Command line arg PPID: %u", cmdLineArgPPID); + break; + } + } +#undef CHECK_ARG + + // default, attach to parent process console if exists + // AttachConsole exists since WinXP, so be nice and do it dynamically + typedef BOOL (WINAPI *LPFAC)(DWORD dwProcessId); + HINSTANCE hKernel32 = GetModuleHandle("kernel32"); + if (hKernel32) { + LPFAC attachConsole = (LPFAC) GetProcAddress(hKernel32, "AttachConsole"); + if (attachConsole) { + if (cmdLineArgPPID) { + if (!attachConsole(cmdLineArgPPID)) { + logErr(true, false, "AttachConsole of PPID: %u failed.", cmdLineArgPPID); + } + } else { + if (!attachConsole((DWORD) -1)) { + logErr(true, false, "AttachConsole of PP failed."); + } else { + getParentProcessID(parentProcID); + setConsoleCodepage(); + if (attachMsg) { + printToConsole(attachMsg); + } + } + } + } else { + logErr(true, false, "GetProcAddress() for AttachConsole failed."); + } + } + return true; +} + +bool isConsoleAttached() { + typedef HWND (WINAPI *GetConsoleWindowT)(); + HINSTANCE hKernel32 = GetModuleHandle("kernel32"); + if (hKernel32) { + GetConsoleWindowT getConsoleWindow = (GetConsoleWindowT) GetProcAddress(hKernel32, "GetConsoleWindow"); + if (getConsoleWindow) { + if (getConsoleWindow() != NULL) { + logMsg("Console is attached."); + return true; + } + } else { + logErr(true, false, "GetProcAddress() for GetConsoleWindow failed."); + } + } + return false; +} + +bool printToConsole(const char *msg) { + FILE *console = fopen("CON", "a"); + if (!console) { + return false; + } + fprintf(console, "%s", msg); + fclose(console); + return false; +} + +bool getParentProcessID(DWORD &id) { + typedef HANDLE (WINAPI * CreateToolhelp32SnapshotT)(DWORD, DWORD); + typedef BOOL (WINAPI * Process32FirstT)(HANDLE, LPPROCESSENTRY32); + typedef BOOL (WINAPI * Process32NextT)(HANDLE, LPPROCESSENTRY32); + + HINSTANCE hKernel32 = GetModuleHandle("kernel32"); + if (!hKernel32) { + return false; + } + + CreateToolhelp32SnapshotT createToolhelp32Snapshot = (CreateToolhelp32SnapshotT) GetProcAddress(hKernel32, "CreateToolhelp32Snapshot"); + Process32FirstT process32First = (Process32FirstT) GetProcAddress(hKernel32, "Process32First"); + Process32NextT process32Next = (Process32NextT) GetProcAddress(hKernel32, "Process32Next"); + + if (createToolhelp32Snapshot == NULL || process32First == NULL || process32Next == NULL) { + logErr(true, false, "Failed to obtain Toolhelp32 functions."); + return false; + } + + HANDLE hSnapshot = createToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapshot == INVALID_HANDLE_VALUE) { + logErr(true, false, "Failed to obtain process snapshot."); + return false; + } + + PROCESSENTRY32 entry = {0}; + entry.dwSize = sizeof (PROCESSENTRY32); + if (!process32First(hSnapshot, &entry)) { + CloseHandle(hSnapshot); + return false; + } + + DWORD curID = GetCurrentProcessId(); + logMsg("Current process ID: %u", curID); + + do { + if (entry.th32ProcessID == curID) { + id = entry.th32ParentProcessID; + logMsg("Parent process ID: %u", id); + CloseHandle(hSnapshot); + return true; + } + } while (process32Next(hSnapshot, &entry)); + + CloseHandle(hSnapshot); + return false; +} + +bool isWow64() +{ + BOOL IsWow64 = FALSE; + typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + LPFN_ISWOW64PROCESS fnIsWow64Process; + + fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(GetModuleHandle(TEXT("kernel32")),"IsWow64Process"); + + if (NULL != fnIsWow64Process) + { + if (!fnIsWow64Process(GetCurrentProcess(),&IsWow64)) + { + // handle error + } + } + return IsWow64; +} + +int convertAnsiToUtf8(const char *ansi, char *utf8, int utf8Len) { + const int len = 32*1024; + WCHAR tmp[len] = L""; + if (MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, ansi, -1, tmp, len) == 0) + return -1; + if (WideCharToMultiByte(CP_UTF8, 0, tmp, -1, utf8, utf8Len, NULL, NULL) == 0) + return -1; + return 0; +} + diff --git a/platform/o.n.bootstrap/launcher/windows/utilsfuncs.h b/platform/o.n.bootstrap/launcher/windows/utilsfuncs.h new file mode 100644 index 000000000000..6cf172a24db5 --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/utilsfuncs.h @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * Author: Tomas Holy + */ + +#ifndef _UTILSFUNCS_H +#define _UTILSFUNCS_H + +#include +#include + +bool isWow64(); +bool disableFolderVirtualization(HANDLE hProcess); +bool getStringFromRegistry(HKEY rootKey, const char *keyName, const char *valueName, std::string &value); +bool getStringFromRegistryEx(HKEY rootKey, const char *keyName, const char *valueName, std::string &value,bool read64bit); +bool getStringFromRegistry64bit(HKEY rootKey, const char *keyName, const char *valueName, std::string &value); +bool getDwordFromRegistry(HKEY rootKey, const char *keyName, const char *valueName, DWORD &value); +bool dirExists(const char *path); +bool fileExists(const char *path); +bool normalizePath(char *path, int len); +bool createPath(const char *path); +char * getCurrentModulePath(char *path, int pathLen); +char * skipWhitespaces(char *str); +char * trimWhitespaces(char *str); +void logMsg(const char *format, ...); +void logErr(bool appendSysError, bool showMsgBox, const char *format, ...); +bool checkLoggingArg(int argc, char *argv[], bool delFile); +bool setupProcess(int &argc, char *argv[], DWORD &parentProcID, const char *attachMsg = 0); +bool printToConsole(const char *msg); +bool getParentProcessID(DWORD &id); +bool isConsoleAttached(); +int convertAnsiToUtf8(const char *ansi, char *utf8, int utf8Len); + +#endif /* _UTILSFUNCS_H */ + diff --git a/platform/o.n.bootstrap/launcher/windows/version.h b/platform/o.n.bootstrap/launcher/windows/version.h new file mode 100644 index 000000000000..26b4461403ba --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/version.h @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#define COMPANY "" +#define COMPONENT "NetBeans Platform Launcher" +#define VER "12.5.0.0" +#define FVER 12,5,0,0 +#define BUILD_ID "28062021" +#define INTERNAL_NAME "nbexec" +#define COPYRIGHT "Based on Apache NetBeans from the Apache Software Foundation and is licensed under Apache License Version 2.0" +#define NAME "NetBeans Platform Launcher" + diff --git a/platform/o.n.bootstrap/launcher/windows/version.rc b/platform/o.n.bootstrap/launcher/windows/version.rc new file mode 100644 index 000000000000..7a516a4c5876 --- /dev/null +++ b/platform/o.n.bootstrap/launcher/windows/version.rc @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include "version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION FVER + PRODUCTVERSION FVER + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + // FILEOS 0x4 is Win32, 0x40004 is Win32 NT only + FILEOS 0x4L + // FILETYPE should be 0x1 for .exe and 0x2 for .dll + FILETYPE FILETYPE_ID + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", COMPANY "\0" + VALUE "FileDescription", COMPONENT "\0" + VALUE "FileVersion", VER "\0" + VALUE "Full Version", BUILD_ID "\0" + VALUE "InternalName", INTERNAL_NAME "\0" + VALUE "LegalCopyright", COPYRIGHT "\0" + VALUE "OriginalFilename", FNAME "\0" + VALUE "ProductName", NAME "\0" + VALUE "ProductVersion", VER "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END