ide code migration
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..41d77da
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/target/
+/nb-configuration.xml
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..aeb123f
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,208 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
+********************************************************************************
+Apache NetBeans repository includes a number of source files that are not
+covered by the Apache license. These files are refered to by licenseinfo.xml
+files which hold the license information.
+********************************************************************************
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..1d664ab
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.netbeans</groupId>
+        <artifactId>netbeans-parent</artifactId>
+        <version>2</version>
+    </parent>
+    <groupId>org.apache.netbeans.native</groupId>
+    <version>12.5-SNAPSHOT</version>
+
+    <artifactId>launcher</artifactId>
+    <packaging>jar</packaging>
+  
+    <name>Apache NetBeans Launcher</name>
+    <description>
+   
+    </description> 
+    <licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+
+    <developers>
+        <developer>
+            <id>apachenetbeansdev</id>
+            <name>Apache NetBeans Dev Mailing List</name>
+            <email>dev@netbeans.apache.org</email>
+        </developer>
+    </developers>
+    <url>https://netbeans.apache.org/</url>
+
+    <properties>
+        <skipTests>true</skipTests>
+    </properties>
+  
+    <build>
+        <plugins>
+            <plugin>        
+                <artifactId>maven-antrun-plugin</artifactId>
+                <version>3.0.0</version>  
+                <executions>
+                    <execution>
+                        <id>compile</id>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                        <configuration>
+                            <target>
+                                <exec executable="make" dir="src/main/cpp/bootstrap">
+                                    <arg value="-f"/>
+                                    <arg value="Makefile.mingw"/>
+                                </exec>
+                                <exec executable="make" dir="src/main/cpp/ide">
+                                    <arg value="-f"/>
+                                    <arg value="Makefile.mingw"/>
+                                </exec>
+                                <exec executable="make" dir="src/main/cpp/harness">
+                                    <arg value="-f"/>
+                                    <arg value="Makefile.mingw"/>
+                                </exec>
+                            </target>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>default-jar</id>
+                        <phase>none</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <version>3.2.0</version>
+                <executions>
+                    <execution>
+                        <id>add-source</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>src/main/cpp</source> 
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>create-distribution</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>src/assembly/assembly.xml</descriptor>
+                            </descriptors>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/src/main/cpp/bootstrap/.dep.inc b/src/main/cpp/bootstrap/.dep.inc
new file mode 100755
index 0000000..4560e55
--- /dev/null
+++ b/src/main/cpp/bootstrap/.dep.inc
@@ -0,0 +1,5 @@
+# This code depends on make tool being used
+DEPFILES=$(wildcard $(addsuffix .d, ${OBJECTFILES}))
+ifneq (${DEPFILES},)
+include ${DEPFILES}
+endif
diff --git a/src/main/cpp/bootstrap/Makefile b/src/main/cpp/bootstrap/Makefile
new file mode 100644
index 0000000..ee8f7c1
--- /dev/null
+++ b/src/main/cpp/bootstrap/Makefile
@@ -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.
+
+#  Main targets can be executed directly, and they are:
+#  
+#     build                    build a specific configuration
+#     clean                    remove built files from a configuration
+#     clobber                  remove all built files
+#     all                      build all configurations
+#     help                     print help mesage
+#  
+#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+#  .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+# NOCDDL
+
+# Environment 
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+
+
+
+# build
+build: .build-post-$(CONF)
+
+.build-pre:
+# Add your pre 'build' code here...
+
+.build-post-nbexec: .build-impl nbexecexe.cpp nbexecloader.h utilsfuncs.cpp nbexec_exe.rc
+	windres.exe -Ocoff nbexec_exe.rc nbexec_exe.res
+	g++ -s -mno-cygwin -Wl,--nxcompat -Wl,--dynamicbase -Wl,--no-seh -DNBEXEC_DLL=\"nbexec.dll\" nbexecexe.cpp utilsfuncs.cpp nbexec_exe.res -o nbexec.exe
+	cp nbexec.exe ../../../nbbuild/netbeans/platform/lib/
+	cp nbexec.dll ../../../nbbuild/netbeans/platform/lib/
+	
+.build-post-nbexec64: .build-impl nbexecexe.cpp nbexecloader.h utilsfuncs.cpp nbexec_exe.rc
+	x86_64-w64-mingw32-windres.exe -Ocoff nbexec_exe.rc nbexec_exe64.res 
+	x86_64-w64-mingw32-g++.exe -m64 -s -mno-cygwin -Wl,--nxcompat -Wl,--dynamicbase -DNBEXEC_DLL=\"nbexec64.dll\" -static-libgcc -static-libstdc++ nbexecexe.cpp utilsfuncs.cpp nbexec_exe64.res -o nbexec64.exe 
+	cp nbexec64.exe ../../../nbbuild/netbeans/platform/lib/
+	cp nbexec64.dll ../../../nbbuild/netbeans/platform/lib/
+
+
+
+# clean
+clean: .clean-post-$(CONF)
+
+.clean-pre:
+# Add your pre 'clean' code here...
+
+.clean-post-nbexec: .clean-impl
+	rm -f nbexec_exe32.res nbexec32.exe
+	
+.clean-post-nbexec64: .clean-impl
+	rm -f nbexec_exe64.res nbexec64.exe
+
+
+
+# clobber
+clobber: .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post: .clobber-impl
+# Add your post 'clobber' code here...
+
+
+
+# all
+all: .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post: .all-impl
+# Add your post 'all' code here...
+
+
+
+# help
+help: .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post: .help-impl
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
diff --git a/src/main/cpp/bootstrap/Makefile.mingw b/src/main/cpp/bootstrap/Makefile.mingw
new file mode 100644
index 0000000..302d778
--- /dev/null
+++ b/src/main/cpp/bootstrap/Makefile.mingw
@@ -0,0 +1,45 @@
+# 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.
+
+all: nbexec64.dll nbexec64.exe nbexec.dll nbexec.exe
+
+clean:
+	rm -f *.res *.exe *.dll
+
+nbexec64.res: nbexec.rc
+	x86_64-w64-mingw32-windres -onbexec64.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 nbexec64.dll -I include jvmlauncher.cpp nbexec.cpp platformlauncher.cpp utilsfuncs.cpp 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 -onbexec_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 nbexec_exe64.res -onbexec64.exe -static -lstdc++ -static-libstdc++ -static-libgcc
+
+nbexec.res: nbexec.rc
+	i686-w64-mingw32-windres -onbexec.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 nbexec.dll -I include jvmlauncher.cpp nbexec.cpp platformlauncher.cpp utilsfuncs.cpp 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 -onbexec_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 nbexec_exe.res -onbexec.exe -static -lstdc++ -static-libstdc++ -static-libgcc
diff --git a/src/main/cpp/bootstrap/argnames.h b/src/main/cpp/bootstrap/argnames.h
new file mode 100644
index 0000000..c4bdaba
--- /dev/null
+++ b/src/main/cpp/bootstrap/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/src/main/cpp/bootstrap/include/README b/src/main/cpp/bootstrap/include/README
new file mode 100644
index 0000000..7641ada
--- /dev/null
+++ b/src/main/cpp/bootstrap/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/src/main/cpp/bootstrap/include/jni.h b/src/main/cpp/bootstrap/include/jni.h
new file mode 100644
index 0000000..16cf67b
--- /dev/null
+++ b/src/main/cpp/bootstrap/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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/jniTOC.html">specification</a>
+ * for details.
+ */
+
+#ifndef _JNI_H_
+#define _JNI_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+#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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/functions.html#wp23720">specification</a>
+ * 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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/functions.html#wp23720">specification</a>
+ * 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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#wp16334">specification</a>
+ * 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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#wp16334">specification</a>
+ * 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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#attach_current_thread">specification</a>
+ * for details.
+ */
+typedef struct JavaVMAttachArgs {
+    jint version;  
+    char *name;
+    jobject group;
+} JavaVMAttachArgs;
+
+/**
+ * JNI Invocation Interface table for use in C sources
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#invocation_api_functions">
+ * specification</a> 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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#invocation_api_functions">
+ * specification</a> 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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#wp16064">specification</a>
+ * 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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#wp633">specification</a>
+ * for details.
+ */
+_JNI_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs(JavaVM ** vmBuf,
+                                                jsize bufLen,
+                                                jsize * nVMs);
+
+/**
+ * Creates Java VM in the current process
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#wp16334">specification</a>
+ * 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/src/main/cpp/bootstrap/include/jni_types.h b/src/main/cpp/bootstrap/include/jni_types.h
new file mode 100644
index 0000000..a809ebb
--- /dev/null
+++ b/src/main/cpp/bootstrap/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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html">specification</a>
+ * 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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp428">specification</a>
+ * for details.
+ */
+typedef unsigned char jboolean;
+/**
+ * Signed 8-bit primitive byte type equivalent to Java "byte" type
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp428">specification</a>
+ * for details.
+ */
+typedef signed char jbyte;
+/**
+ * Unsigned 16-bit primitive char type equivalent to Java "char" type
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp428">specification</a>
+ * for details.
+ */
+typedef unsigned short jchar;
+/**
+ * Signed 16-bit primitive short type equivalent to Java "short" type
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp428">specification</a>
+ * for details.
+ */
+typedef signed short jshort;
+/**
+ * Signed 32-bit primitive integer type equivalent to Java "int" type
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp428">specification</a>
+ * for details.
+ */
+typedef signed int jint;
+/**
+ * Signed 32-bit primitive floating point type equivalent to Java
+ * "float" type
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp428">specification</a>
+ * for details.
+ */
+typedef float jfloat;
+/**
+ * Signed 64-bit primitive floating point type equivalent to Java
+ * "double" type
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp428">specification</a>
+ * for details.
+ */
+typedef double jdouble;
+/**
+ * Signed 32-bit primitive integer type used to describe sizes
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp428">specification</a>
+ * for details.
+ */
+typedef jint jsize;
+
+/*
+ * Java types
+ */
+struct _jobject;
+/**
+ * Reference type which describes a general Java object in native
+ * function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * for details.
+ */
+typedef struct _jobject*  jobject;
+/**
+ * Reference type which describes a java.lang.Class instance object in
+ * native function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * for details.
+ */
+typedef jobject           jclass;
+/**
+ * Reference type which describes a java.lang.String instance object
+ * in native function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * for details.
+ */
+typedef jobject           jstring;
+/**
+ * Reference type which describes a generic array instance object in
+ * native function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * for details.
+ */
+typedef jobject           jarray;
+/**
+ * Reference type which describes an array of java.lang.Object
+ * instances in native function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * for details.
+ */
+    typedef jarray        jobjectArray;
+/**
+ * Reference type which describes an array of booleans in native
+ * function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * for details.
+ */
+    typedef jarray        jbooleanArray;
+/**
+ * Reference type which describes an array of bytes type in native
+ * function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * for details.
+ */
+    typedef jarray        jbyteArray;
+/**
+ * Reference type which describes an array of chars type in native
+ * function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * for details.
+ */
+    typedef jarray        jcharArray;
+/**
+ * Reference type which describes an array of shorts type in native
+ * function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * for details.
+ */
+    typedef jarray        jshortArray;
+/**
+ * Reference type which describes an array of ints type in native
+ * function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * for details.
+ */
+    typedef jarray        jintArray;
+/**
+ * Reference type which describes an array of longs type in native
+ * function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * for details.
+ */
+    typedef jarray        jlongArray;
+/**
+ * Reference type which describes an array of floats type in native
+ * function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * for details.
+ */
+    typedef jarray        jfloatArray;
+/**
+ * Reference type which describes an array of doubles type in native
+ * function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * for details.
+ */
+    typedef jarray        jdoubleArray;
+/**
+ * Reference type which describes a java.lang.Throwable instance
+ * object in native function
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp15954">specification</a>
+ * 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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/functions.html#wp4256">Call&lt;type&gt;MethodA</a>
+ * and <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/functions.html#wp4796">CallStatic&lt;type&gt;MethodA</a>
+ * 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 Release<primitive type>ArrayElements functions
+ */
+#define JNI_COMMIT 1
+/**
+ * Constant which means that an array region should be discarded. Used
+ * in Release<primitive type>ArrayElements 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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/functions.html#wp17734">RegisterNatives</a>
+ * 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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/design.html#wp16696">specification</a>
+ * for details. */
+typedef JNIEnv_External JNIEnv;
+#else
+/**
+ * JNI API interface table type for usage in C
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/design.html#wp16696">specification</a>
+ * 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 <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#invocation_api_functions">specification</a>
+ * for details
+ */
+typedef JavaVM_External JavaVM;
+#else
+/**
+ * Java VM interface table type for usage in C
+ *
+ * See <a
+ * href="http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html#invocation_api_functions">specification</a>
+ * for details
+ */
+typedef const struct JNIInvokeInterface_ *JavaVM;
+#endif
+
+#endif /* _JNI_TYPES_H_ */
diff --git a/src/main/cpp/bootstrap/jvmlauncher.cpp b/src/main/cpp/bootstrap/jvmlauncher.cpp
new file mode 100644
index 0000000..74bf1cc
--- /dev/null
+++ b/src/main/cpp/bootstrap/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 <assert.h>
+
+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<string> &args, const list<string> &options, bool &separateProcess, DWORD *retCode) {
+    assert(mainClassName);
+    logMsg("JvmLauncher::start()\n\tmainClassName: %s\n\tseparateProcess: %s",
+            mainClassName, separateProcess ? "true" : "false");
+    logMsg("  args:");
+    for (list<string>::const_iterator it = args.begin(); it != args.end(); ++it) {
+        logMsg("\t%s", it->c_str());
+    }
+    logMsg("  options:");
+    for (list<string>::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<string> &options) {
+    for (list<string>::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<std::string> &args, const std::list<std::string> &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<string> &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<string>::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<string>::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<std::string> &args, const std::list<std::string> &options, DWORD *retCode) {
+    string cmdLine = '\"' + (suppressConsole ? javawExePath : javaExePath) + '\"';
+    cmdLine.reserve(32*1024);
+    for (list<string>::const_iterator it = options.begin(); it != options.end(); ++it) {
+        cmdLine += " \"";
+        cmdLine += *it;
+        cmdLine += "\"";
+    }
+    
+    // mainClass and args
+    cmdLine += ' ';
+    cmdLine += mainClassName;
+    for (list<string>::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/src/main/cpp/bootstrap/jvmlauncher.h b/src/main/cpp/bootstrap/jvmlauncher.h
new file mode 100644
index 0000000..01f4e34
--- /dev/null
+++ b/src/main/cpp/bootstrap/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 <windows.h>
+#include <string>
+#include <list>
+#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<std::string> &args, const std::list<std::string> &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<std::string> &args, const std::list<std::string> &options, DWORD *retCode);
+    bool startInProcJvm(const char *mainClassName, const std::list<std::string> &args, const std::list<std::string> &options);
+    bool isVersionString(const char *str);
+    bool canLoadJavaDll();
+    bool findClientOption(const std::list<std::string> &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/src/main/cpp/bootstrap/nbexec.cpp b/src/main/cpp/bootstrap/nbexec.cpp
new file mode 100644
index 0000000..47e490e
--- /dev/null
+++ b/src/main/cpp/bootstrap/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/src/main/cpp/bootstrap/nbexec.exe.manifest b/src/main/cpp/bootstrap/nbexec.exe.manifest
new file mode 100644
index 0000000..cfc9190
--- /dev/null
+++ b/src/main/cpp/bootstrap/nbexec.exe.manifest
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+    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.
+
+-->
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity version="9.0.0.0"
+   processorArchitecture="X86"
+   name="nbexec.exe"
+   type="win32"/>
+
+<description>nbexec process</description>
+<dependency>
+  <dependentAssembly>
+    <assemblyIdentity
+      type="win32"
+      name="Microsoft.Windows.Common-Controls"
+      version="6.0.0.0"
+      processorArchitecture="*"
+      publicKeyToken="6595b64144ccf1df"
+      language="*"
+    />
+  </dependentAssembly>
+</dependency>
+<!-- Identify the application security requirements. -->
+<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+  <security>
+    <requestedPrivileges>
+      <requestedExecutionLevel
+        level="asInvoker"
+        uiAccess="false"/>
+      </requestedPrivileges>
+     </security>
+</trustInfo>
+<!-- NETBEANS-1227: Indicate the same HiDPI capabilities as javaw.exe from JDK 11. -->
+<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
+  <asmv3:windowsSettings xmlns:dpi1="http://schemas.microsoft.com/SMI/2005/WindowsSettings" xmlns:dpi2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
+    <dpi1:dpiAware>true/PM</dpi1:dpiAware>
+    <dpi2:dpiAwareness>PerMonitorV2, PerMonitor, system</dpi2:dpiAwareness>
+  </asmv3:windowsSettings>
+</asmv3:application>
+<!-- List of explicitly supported Windows versions. This is the list from
+     javaw.exe on JDK 8.0.172, which is the same as that of JDK 11ea. -->
+<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+  <application>
+    <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+    <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+    <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+    <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+    <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+  </application>
+</compatibility>
+</assembly>
diff --git a/src/main/cpp/bootstrap/nbexec.rc b/src/main/cpp/bootstrap/nbexec.rc
new file mode 100644
index 0000000..b0843af
--- /dev/null
+++ b/src/main/cpp/bootstrap/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 <winuser.h>
+
+#define FNAME "nbexec.dll"
+#define FILETYPE_ID 0x2L
+
+#include "version.rc"
+
diff --git a/src/main/cpp/bootstrap/nbexec_exe.rc b/src/main/cpp/bootstrap/nbexec_exe.rc
new file mode 100644
index 0000000..df75c0b
--- /dev/null
+++ b/src/main/cpp/bootstrap/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 <winuser.h>
+
+#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/src/main/cpp/bootstrap/nbexecexe.cpp b/src/main/cpp/bootstrap/nbexecexe.cpp
new file mode 100644
index 0000000..181a365
--- /dev/null
+++ b/src/main/cpp/bootstrap/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 <windows.h>
+#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/src/main/cpp/bootstrap/nbexecloader.h b/src/main/cpp/bootstrap/nbexecloader.h
new file mode 100644
index 0000000..221a557
--- /dev/null
+++ b/src/main/cpp/bootstrap/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/src/main/cpp/bootstrap/nbproject/configurations.xml b/src/main/cpp/bootstrap/nbproject/configurations.xml
new file mode 100644
index 0000000..0121be8
--- /dev/null
+++ b/src/main/cpp/bootstrap/nbproject/configurations.xml
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<configurationDescriptor version="100">
+  <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">
+    <logicalFolder name="HeaderFiles"
+                   displayName="Header Files"
+                   projectFiles="true">
+      <itemPath>argnames.h</itemPath>
+      <itemPath>jvmlauncher.h</itemPath>
+      <itemPath>platformlauncher.h</itemPath>
+      <itemPath>utilsfuncs.h</itemPath>
+      <itemPath>version.h</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ResourceFiles"
+                   displayName="Resource Files"
+                   projectFiles="true">
+      <itemPath>nbexec.exe.manifest</itemPath>
+      <itemPath>nbexec.rc</itemPath>
+      <itemPath>nbexec_exe.rc</itemPath>
+      <itemPath>version.rc</itemPath>
+    </logicalFolder>
+    <logicalFolder name="SourceFiles"
+                   displayName="Source Files"
+                   projectFiles="true">
+      <itemPath>jvmlauncher.cpp</itemPath>
+      <itemPath>nbexec.cpp</itemPath>
+      <itemPath>nbexecexe.cpp</itemPath>
+      <itemPath>nbexecloader.h</itemPath>
+      <itemPath>platformlauncher.cpp</itemPath>
+      <itemPath>utilsfuncs.cpp</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ExternalFiles"
+                   displayName="Important Files"
+                   projectFiles="false">
+      <itemPath>Makefile</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ExternalFiles"
+                   displayName="Important Files"
+                   projectFiles="false">
+      <itemPath>Makefile</itemPath>
+    </logicalFolder>
+  </logicalFolder>
+  <projectmakefile>Makefile</projectmakefile>
+  <confs>
+    <conf name="nbexec" type="2">
+      <toolsSet>
+        <compilerSet>Cygwin|Cygwin</compilerSet>
+        <dependencyChecking>true</dependencyChecking>
+        <rebuildPropChanged>false</rebuildPropChanged>
+      </toolsSet>
+      <compileType>
+        <cTool>
+          <developmentMode>5</developmentMode>
+          <warningLevel>2</warningLevel>
+        </cTool>
+        <ccTool>
+          <developmentMode>5</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <architecture>1</architecture>
+          <incDir>
+            <pElem>C:/Program Files/Java/jdk1.8.0_77/include</pElem>
+            <pElem>C:/Program Files/Java/jdk1.8.0_77/include/win32</pElem>
+          </incDir>
+          <commandLine>-mno-cygwin</commandLine>
+          <preprocessorList>
+            <Elem>NBEXEC_DLL="nbexec.dll"</Elem>
+          </preprocessorList>
+        </ccTool>
+        <linkerTool>
+          <output>nbexec.dll</output>
+          <additionalDep>${OBJECTDIR}/nbexec.res</additionalDep>
+          <linkerLibItems>
+            <linkerOptionItem>${OBJECTDIR}/nbexec.res</linkerOptionItem>
+          </linkerLibItems>
+          <commandLine>-Wl,--nxcompat -Wl,--dynamicbase -Wl,--no-seh</commandLine>
+        </linkerTool>
+      </compileType>
+      <item path="argnames.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="jvmlauncher.cpp" ex="false" tool="1" flavor2="0">
+      </item>
+      <item path="jvmlauncher.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="nbexec.cpp" ex="false" tool="1" flavor2="0">
+      </item>
+      <item path="nbexec.exe.manifest" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="nbexec.rc" ex="false" tool="3" flavor2="0">
+        <customTool>
+          <customToolCommandline>windres.exe -Ocoff nbexec.rc ${OBJECTDIR}/nbexec.res</customToolCommandline>
+          <customToolDescription>Compiling Resource files...</customToolDescription>
+          <customToolOutputs>${OBJECTDIR}/nbexec.res</customToolOutputs>
+          <customToolAdditionalDep>version.h</customToolAdditionalDep>
+        </customTool>
+      </item>
+      <item path="nbexec_exe.rc" ex="false" tool="3" flavor2="0">
+        <customTool>
+          <customToolDescription></customToolDescription>
+        </customTool>
+      </item>
+      <item path="nbexecexe.cpp" ex="false" tool="1" flavor2="0">
+      </item>
+      <item path="nbexecloader.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="platformlauncher.cpp" ex="false" tool="1" flavor2="0">
+      </item>
+      <item path="platformlauncher.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="utilsfuncs.cpp" ex="false" tool="1" flavor2="0">
+      </item>
+      <item path="utilsfuncs.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="version.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="version.rc" ex="false" tool="3" flavor2="0">
+      </item>
+    </conf>
+    <conf name="nbexec64" type="2">
+      <toolsSet>
+        <compilerSet>Cygwin64|Cygwin</compilerSet>
+        <dependencyChecking>true</dependencyChecking>
+        <rebuildPropChanged>false</rebuildPropChanged>
+      </toolsSet>
+      <compileType>
+        <cTool>
+          <developmentMode>5</developmentMode>
+        </cTool>
+        <ccTool>
+          <developmentMode>5</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <architecture>2</architecture>
+          <incDir>
+            <pElem>C:/Program Files/Java/jdk1.8.0_77/include</pElem>
+            <pElem>C:/Program Files/Java/jdk1.8.0_77/include/win32</pElem>
+          </incDir>
+          <commandLine>-mno-cygwin -static-libgcc -static-libstdc++</commandLine>
+          <preprocessorList>
+            <Elem>NBEXEC_DLL="nbexec64.dll"</Elem>
+          </preprocessorList>
+        </ccTool>
+        <linkerTool>
+          <output>nbexec64.dll</output>
+          <additionalDep>${OBJECTDIR}/nbexec64.res</additionalDep>
+          <linkerLibItems>
+            <linkerOptionItem>${OBJECTDIR}/nbexec64.res</linkerOptionItem>
+          </linkerLibItems>
+          <commandLine>-Wl,--nxcompat -Wl,--dynamicbase</commandLine>
+        </linkerTool>
+      </compileType>
+      <item path="argnames.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="jvmlauncher.cpp" ex="false" tool="1" flavor2="0">
+      </item>
+      <item path="jvmlauncher.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="nbexec.cpp" ex="false" tool="1" flavor2="0">
+      </item>
+      <item path="nbexec.exe.manifest" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="nbexec.rc" ex="false" tool="3" flavor2="0">
+        <customTool>
+          <customToolCommandline>x86_64-w64-mingw32-windres.exe -Ocoff nbexec.rc ${OBJECTDIR}/nbexec64.res</customToolCommandline>
+          <customToolDescription>Compiling Resource files...</customToolDescription>
+          <customToolOutputs>${OBJECTDIR}/nbexec64.res</customToolOutputs>
+          <customToolAdditionalDep>version.h</customToolAdditionalDep>
+        </customTool>
+      </item>
+      <item path="nbexec_exe.rc" ex="false" tool="3" flavor2="0">
+        <customTool>
+          <customToolDescription></customToolDescription>
+        </customTool>
+      </item>
+      <item path="nbexecexe.cpp" ex="false" tool="1" flavor2="0">
+      </item>
+      <item path="nbexecloader.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="platformlauncher.cpp" ex="false" tool="1" flavor2="0">
+      </item>
+      <item path="platformlauncher.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="utilsfuncs.cpp" ex="false" tool="1" flavor2="0">
+      </item>
+      <item path="utilsfuncs.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="version.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="version.rc" ex="false" tool="3" flavor2="0">
+      </item>
+    </conf>
+  </confs>
+</configurationDescriptor>
diff --git a/nbproject/project.properties b/src/main/cpp/bootstrap/nbproject/project.properties
similarity index 100%
copy from nbproject/project.properties
copy to src/main/cpp/bootstrap/nbproject/project.properties
diff --git a/src/main/cpp/bootstrap/nbproject/project.xml b/src/main/cpp/bootstrap/nbproject/project.xml
new file mode 100644
index 0000000..99f9274
--- /dev/null
+++ b/src/main/cpp/bootstrap/nbproject/project.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.cnd.makeproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/make-project/1">
+            <name>Platform Launcher Win</name>
+            <make-project-type>0</make-project-type>
+            <c-extensions/>
+            <cpp-extensions>cpp</cpp-extensions>
+            <header-extensions>h</header-extensions>
+            <sourceEncoding>UTF-8</sourceEncoding>
+            <make-dep-projects/>
+            <sourceRootList/>
+            <confList>
+                <confElem>
+                    <name>nbexec</name>
+                    <type>2</type>
+                </confElem>
+                <confElem>
+                    <name>nbexec64</name>
+                    <type>2</type>
+                </confElem>
+            </confList>
+            <formatting>
+                <project-formatting-style>false</project-formatting-style>
+            </formatting>
+        </data>
+    </configuration>
+</project>
diff --git a/src/main/cpp/bootstrap/platformlauncher.cpp b/src/main/cpp/bootstrap/platformlauncher.cpp
new file mode 100644
index 0000000..8df954c
--- /dev/null
+++ b/src/main/cpp/bootstrap/platformlauncher.cpp
@@ -0,0 +1,731 @@
+/*
+ * 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>      path to JDK\n\
+  -J<jvm_option>        pass <jvm_option> to JVM\n\
+\n\
+  --cp:p <classpath>    prepend <classpath> to classpath\n\
+  --cp:a <classpath>    append <classpath> to classpath\n\
+\n\
+  --fork-java           run java in separate process\n\
+  --trace <path>        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_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);
+}
+
+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/src/main/cpp/bootstrap/platformlauncher.h b/src/main/cpp/bootstrap/platformlauncher.h
new file mode 100644
index 0000000..07fe4d8
--- /dev/null
+++ b/src/main/cpp/bootstrap/platformlauncher.h
@@ -0,0 +1,111 @@
+/*
+ * 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 <string>
+#include <list>
+#include <set>
+
+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_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<std::string> javaOptions;
+    std::list<std::string> launcherOptions;
+    std::list<std::string> progArgs;
+    JvmLauncher jvmLauncher;
+    std::set<std::string> addedToCP;
+    std::string classPath;
+    std::string appendHelp;
+};
+
+#endif	/* _PLATFORMLAUNCHER_H */
+
diff --git a/src/main/cpp/bootstrap/utilsfuncs.cpp b/src/main/cpp/bootstrap/utilsfuncs.cpp
new file mode 100644
index 0000000..2902b1e
--- /dev/null
+++ b/src/main/cpp/bootstrap/utilsfuncs.cpp
@@ -0,0 +1,449 @@
+/*
+ * 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 <tlhelp32.h>
+#include <windows.h>
+
+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;
+}
+
+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();
+            } 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);
+                    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/src/main/cpp/bootstrap/utilsfuncs.h b/src/main/cpp/bootstrap/utilsfuncs.h
new file mode 100644
index 0000000..6cf172a
--- /dev/null
+++ b/src/main/cpp/bootstrap/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 <windows.h>
+#include <string>
+
+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/src/main/cpp/bootstrap/version.h b/src/main/cpp/bootstrap/version.h
new file mode 100644
index 0000000..63f0860
--- /dev/null
+++ b/src/main/cpp/bootstrap/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 "9.0.0.0"
+#define FVER 9,0,0,0
+#define BUILD_ID "03062018"
+#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/src/main/cpp/bootstrap/version.rc b/src/main/cpp/bootstrap/version.rc
new file mode 100644
index 0000000..7a516a4
--- /dev/null
+++ b/src/main/cpp/bootstrap/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 <winuser.h>
+#include <winver.h>
+#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
diff --git a/src/main/cpp/harness/Makefile b/src/main/cpp/harness/Makefile
new file mode 100644
index 0000000..bef2334
--- /dev/null
+++ b/src/main/cpp/harness/Makefile
@@ -0,0 +1,103 @@
+# 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.
+
+#  Main targets can be executed directly, and they are:
+#  
+#     build                    build a specific configuration
+#     clean                    remove built files from a configuration
+#     clobber                  remove all built files
+#     all                      build all configurations
+#     help                     print help mesage
+#  
+#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+#  .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+# NOCDDL
+
+
+
+# Environment 
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+
+
+
+# build
+build: .build-post
+
+.build-pre: .build-pre-$(CONF)
+# Add your pre 'build' code here...
+
+.build-pre-app.exe: app.rc
+	windres -oapp.res -Ocoff app.rc
+
+.build-pre-app64.exe: app.rc
+	x86_64-w64-mingw32-windres.exe -oapp64.res -Ocoff app.rc
+
+.build-post: .build-impl
+# Add your post 'build' code here...	
+
+
+
+# clean
+clean: .clean-post
+
+.clean-pre:
+# Add your pre 'clean' code here...
+
+.clean-post: .clean-impl
+# Add your post 'clean' code here...
+
+
+
+# clobber
+clobber: .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post: .clobber-impl
+# Add your post 'clobber' code here...
+
+
+
+# all
+all: .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post: .all-impl
+# Add your post 'all' code here...
+
+
+
+# help
+help: .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post: .help-impl
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
diff --git a/src/main/cpp/harness/Makefile.mingw b/src/main/cpp/harness/Makefile.mingw
new file mode 100644
index 0000000..5ef6f79
--- /dev/null
+++ b/src/main/cpp/harness/Makefile.mingw
@@ -0,0 +1,34 @@
+# 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.
+
+all: app64.exe app.exe
+
+clean:
+	rm -f *.res *.exe
+
+app64.res: app.rc app.exe.manifest
+	x86_64-w64-mingw32-windres -oapp64.res -Ocoff -DMANIFEST_FILE=app.exe.manifest app.rc
+
+app64.exe: app.cpp applauncher.cpp app64.res ../../../platform/o.n.bootstrap/launcher/windows/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 app64.res ../../../platform/o.n.bootstrap/launcher/windows/utilsfuncs.cpp ../../../nb/ide.launcher/windows/nblauncher.cpp -I ../../../platform/o.n.bootstrap/launcher/windows/ -oapp64.exe -static -lstdc++ -static-libstdc++ -static-libgcc
+
+app.res: app.rc app.exe.manifest
+	i686-w64-mingw32-windres -oapp.res -Ocoff -DMANIFEST_FILE=app.exe.manifest app.rc
+
+app.exe: app.cpp applauncher.cpp app.res ../../../platform/o.n.bootstrap/launcher/windows/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 app.res ../../../platform/o.n.bootstrap/launcher/windows/utilsfuncs.cpp ../../../nb/ide.launcher/windows/nblauncher.cpp -I ../../../platform/o.n.bootstrap/launcher/windows/ -oapp.exe -static -lstdc++ -static-libstdc++ -static-libgcc
+
diff --git a/src/main/cpp/harness/app.cpp b/src/main/cpp/harness/app.cpp
new file mode 100644
index 0000000..840c828
--- /dev/null
+++ b/src/main/cpp/harness/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/src/main/cpp/harness/app.exe.manifest b/src/main/cpp/harness/app.exe.manifest
new file mode 100644
index 0000000..26921b3
--- /dev/null
+++ b/src/main/cpp/harness/app.exe.manifest
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+    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.
+
+-->
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity version="9.0.0.0"
+   processorArchitecture="x86"
+   name="app.exe"
+   type="win32"/>
+
+<description>NBP application process</description>
+<dependency>
+  <dependentAssembly>
+    <assemblyIdentity
+      type="win32"
+      name="Microsoft.Windows.Common-Controls"
+      version="6.0.0.0"
+      processorArchitecture="*"
+      publicKeyToken="6595b64144ccf1df"
+      language="*"
+    />
+  </dependentAssembly>
+</dependency>
+<!-- Identify the application security requirements. -->
+<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+  <security>
+    <requestedPrivileges>
+      <requestedExecutionLevel
+        level="asInvoker"
+        uiAccess="false"/>
+      </requestedPrivileges>
+     </security>
+</trustInfo>
+<!-- NETBEANS-1227: Indicate the same HiDPI capabilities as javaw.exe from JDK 11. -->
+<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
+  <asmv3:windowsSettings xmlns:dpi1="http://schemas.microsoft.com/SMI/2005/WindowsSettings" xmlns:dpi2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
+    <dpi1:dpiAware>true/PM</dpi1:dpiAware>
+    <dpi2:dpiAwareness>PerMonitorV2, PerMonitor, system</dpi2:dpiAwareness>
+  </asmv3:windowsSettings>
+</asmv3:application>
+<!-- List of explicitly supported Windows versions. This is the list from
+     javaw.exe on JDK 8.0.172, which is the same as that of JDK 11ea. -->
+<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+  <application>
+    <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+    <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+    <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+    <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+    <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+  </application>
+</compatibility>
+</assembly>
diff --git a/src/main/cpp/harness/app.ico b/src/main/cpp/harness/app.ico
new file mode 100644
index 0000000..294cd70
--- /dev/null
+++ b/src/main/cpp/harness/app.ico
Binary files differ
diff --git a/src/main/cpp/harness/app.rc b/src/main/cpp/harness/app.rc
new file mode 100644
index 0000000..d52211e
--- /dev/null
+++ b/src/main/cpp/harness/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 <winuser.h>
+
+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/src/main/cpp/harness/applauncher.cpp b/src/main/cpp/harness/applauncher.cpp
new file mode 100644
index 0000000..f816316
--- /dev/null
+++ b/src/main/cpp/harness/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 "../../../platform/o.n.bootstrap/launcher/windows/utilsfuncs.h"
+#include "../../../platform/o.n.bootstrap/launcher/windows/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/src/main/cpp/harness/applauncher.h b/src/main/cpp/harness/applauncher.h
new file mode 100644
index 0000000..0801c8a
--- /dev/null
+++ b/src/main/cpp/harness/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 <string>
+#include <windows.h>
+
+#include "shlobj.h"
+#include "../../../nb/ide.launcher/windows/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/src/main/cpp/harness/nbproject/configurations.xml b/src/main/cpp/harness/nbproject/configurations.xml
new file mode 100644
index 0000000..55d0647
--- /dev/null
+++ b/src/main/cpp/harness/nbproject/configurations.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<configurationDescriptor version="84">
+  <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">
+    <logicalFolder name="HeaderFiles"
+                   displayName="Header Files"
+                   projectFiles="true">
+      <itemPath>applauncher.h</itemPath>
+      <itemPath>../../../nb/ide.launcher/windows/nblauncher.h</itemPath>
+      <itemPath>../../../platform/o.n.bootstrap/launcher/windows/utilsfuncs.h</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ResourceFiles"
+                   displayName="Resource Files"
+                   projectFiles="true">
+    </logicalFolder>
+    <logicalFolder name="SourceFiles"
+                   displayName="Source Files"
+                   projectFiles="true">
+      <itemPath>app.cpp</itemPath>
+      <itemPath>applauncher.cpp</itemPath>
+      <itemPath>../../../nb/ide.launcher/windows/nblauncher.cpp</itemPath>
+      <itemPath>../../../platform/o.n.bootstrap/launcher/windows/utilsfuncs.cpp</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ExternalFiles"
+                   displayName="Important Files"
+                   projectFiles="false">
+      <itemPath>Makefile</itemPath>
+    </logicalFolder>
+  </logicalFolder>
+  <projectmakefile>Makefile</projectmakefile>
+  <confs>
+    <conf name="app.exe" type="1">
+      <toolsSet>
+        <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
+        <compilerSet>Cygwin|Cygwin</compilerSet>
+      </toolsSet>
+      <compileType>
+        <cTool>
+          <developmentMode>5</developmentMode>
+        </cTool>
+        <ccTool>
+          <developmentMode>5</developmentMode>
+          <architecture>1</architecture>
+          <commandLine>-mno-cygwin</commandLine>
+          <preprocessorList>
+            <Elem>ARCHITECTURE=32</Elem>
+            <Elem>NBEXEC_DLL="/lib/nbexec.dll"</Elem>
+          </preprocessorList>
+        </ccTool>
+        <fortranCompilerTool>
+          <developmentMode>5</developmentMode>
+        </fortranCompilerTool>
+        <linkerTool>
+          <output>../release/launchers/app.exe</output>
+          <linkerLibItems>
+            <linkerOptionItem>app.res</linkerOptionItem>
+          </linkerLibItems>
+          <commandLine>-mwindows</commandLine>
+        </linkerTool>
+      </compileType>
+    </conf>
+    <conf name="app64.exe" type="1">
+      <toolsSet>
+        <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
+        <compilerSet>Cygwin64|Cygwin</compilerSet>
+      </toolsSet>
+      <compileType>
+        <cTool>
+          <developmentMode>5</developmentMode>
+        </cTool>
+        <ccTool>
+          <developmentMode>5</developmentMode>
+          <architecture>2</architecture>
+          <commandLine>-mno-cygwin -static-libgcc -static-libstdc++</commandLine>
+          <preprocessorList>
+            <Elem>ARCHITECTURE=64</Elem>
+            <Elem>NBEXEC_DLL="/lib/nbexec64.dll"</Elem>
+          </preprocessorList>
+        </ccTool>
+        <fortranCompilerTool>
+          <developmentMode>5</developmentMode>
+        </fortranCompilerTool>
+        <linkerTool>
+          <output>../release/launchers/app64.exe</output>
+          <linkerLibItems>
+            <linkerOptionItem>app64.res</linkerOptionItem>
+          </linkerLibItems>
+          <commandLine>-mwindows</commandLine>
+        </linkerTool>
+      </compileType>
+    </conf>
+  </confs>
+</configurationDescriptor>
diff --git a/nbproject/project.properties b/src/main/cpp/harness/nbproject/project.properties
similarity index 100%
copy from nbproject/project.properties
copy to src/main/cpp/harness/nbproject/project.properties
diff --git a/src/main/cpp/harness/nbproject/project.xml b/src/main/cpp/harness/nbproject/project.xml
new file mode 100644
index 0000000..34dd422
--- /dev/null
+++ b/src/main/cpp/harness/nbproject/project.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.cnd.makeproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/make-project/1">
+            <name>Platform App Launcher Win</name>
+            <make-project-type>0</make-project-type>
+            <c-extensions/>
+            <cpp-extensions>cpp</cpp-extensions>
+            <header-extensions>h</header-extensions>
+            <sourceEncoding>UTF-8</sourceEncoding>
+            <make-dep-projects/>
+            <sourceRootList/>
+            <confList>
+                <confElem>
+                    <name>app.exe</name>
+                    <type>1</type>
+                </confElem>
+                <confElem>
+                    <name>app64.exe</name>
+                    <type>1</type>
+                </confElem>
+            </confList>
+        </data>
+    </configuration>
+</project>
diff --git a/.dep.inc b/src/main/cpp/ide/.dep.inc
similarity index 100%
rename from .dep.inc
rename to src/main/cpp/ide/.dep.inc
diff --git a/Makefile b/src/main/cpp/ide/Makefile
similarity index 100%
rename from Makefile
rename to src/main/cpp/ide/Makefile
diff --git a/Makefile.mingw b/src/main/cpp/ide/Makefile.mingw
similarity index 100%
rename from Makefile.mingw
rename to src/main/cpp/ide/Makefile.mingw
diff --git a/cmdargs.h b/src/main/cpp/ide/cmdargs.h
similarity index 100%
rename from cmdargs.h
rename to src/main/cpp/ide/cmdargs.h
diff --git a/nblauncher.cpp b/src/main/cpp/ide/nblauncher.cpp
similarity index 100%
rename from nblauncher.cpp
rename to src/main/cpp/ide/nblauncher.cpp
diff --git a/nblauncher.h b/src/main/cpp/ide/nblauncher.h
similarity index 100%
rename from nblauncher.h
rename to src/main/cpp/ide/nblauncher.h
diff --git a/nbproject/configurations.xml b/src/main/cpp/ide/nbproject/configurations.xml
similarity index 100%
rename from nbproject/configurations.xml
rename to src/main/cpp/ide/nbproject/configurations.xml
diff --git a/nbproject/project.properties b/src/main/cpp/ide/nbproject/project.properties
similarity index 100%
rename from nbproject/project.properties
rename to src/main/cpp/ide/nbproject/project.properties
diff --git a/nbproject/project.xml b/src/main/cpp/ide/nbproject/project.xml
similarity index 100%
rename from nbproject/project.xml
rename to src/main/cpp/ide/nbproject/project.xml
diff --git a/netbeans.cpp b/src/main/cpp/ide/netbeans.cpp
similarity index 100%
rename from netbeans.cpp
rename to src/main/cpp/ide/netbeans.cpp
diff --git a/netbeans.exe.manifest b/src/main/cpp/ide/netbeans.exe.manifest
similarity index 100%
rename from netbeans.exe.manifest
rename to src/main/cpp/ide/netbeans.exe.manifest
diff --git a/netbeans.ico b/src/main/cpp/ide/netbeans.ico
similarity index 100%
rename from netbeans.ico
rename to src/main/cpp/ide/netbeans.ico
Binary files differ
diff --git a/netbeans.rc b/src/main/cpp/ide/netbeans.rc
similarity index 100%
rename from netbeans.rc
rename to src/main/cpp/ide/netbeans.rc
diff --git a/netbeans64.exe.manifest b/src/main/cpp/ide/netbeans64.exe.manifest
similarity index 100%
rename from netbeans64.exe.manifest
rename to src/main/cpp/ide/netbeans64.exe.manifest
diff --git a/version.h b/src/main/cpp/ide/version.h
similarity index 100%
rename from version.h
rename to src/main/cpp/ide/version.h
diff --git a/version.rc b/src/main/cpp/ide/version.rc
similarity index 100%
rename from version.rc
rename to src/main/cpp/ide/version.rc