Files
openide/java/java-runtime/src/com/intellij/rt/execution/application/AppMain.java
T

162 lines
5.2 KiB
Java

/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* 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.
*/
package com.intellij.rt.execution.application;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.Socket;
import java.util.Locale;
/**
* @author ven
* @noinspection UseOfSystemOutOrSystemErr
*/
public class AppMain {
public static final String LAUNCHER_PORT_NUMBER = "idea.launcher.port";
public static final String LAUNCHER_BIN_PATH = "idea.launcher.bin.path";
private static final String JAVAFX_LAUNCHER = "com.sun.javafx.application.LauncherImpl";
private static final String LAUNCH_APPLICATION_METHOD_NAME = "launchApplication";
private static native void triggerControlBreak();
private static boolean loadHelper(String binPath) {
String osName = System.getProperty("os.name").toLowerCase(Locale.US);
if (osName.startsWith("windows")) {
String arch = System.getProperty("os.arch").toLowerCase(Locale.US);
File libFile = new File(binPath, arch.equals("amd64") ? "breakgen64.dll" : "breakgen.dll");
if (libFile.isFile()) {
System.load(libFile.getAbsolutePath());
return true;
}
}
return false;
}
private static void startMonitor(final int portNumber, final boolean helperLibLoaded) {
Thread t = new Thread("Monitor Ctrl-Break") {
public void run() {
try {
Socket client = new Socket("127.0.0.1", portNumber);
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "US-ASCII"));
try {
while (true) {
String msg = reader.readLine();
if ("TERM".equals(msg)) {
return;
}
else if ("BREAK".equals(msg)) {
if (helperLibLoaded) {
triggerControlBreak();
}
}
else if ("STOP".equals(msg)) {
System.exit(1);
}
}
}
finally {
reader.close();
}
}
finally {
client.close();
}
}
catch (Exception ignored) { }
}
};
t.setDaemon(true);
t.start();
}
public static void premain(String args) {
try {
int p = args.indexOf(':');
if (p < 0) throw new IllegalArgumentException("incorrect parameter: " + args);
boolean helperLibLoaded = loadHelper(args.substring(p + 1));
int portNumber = Integer.parseInt(args.substring(0, p));
startMonitor(portNumber, helperLibLoaded);
}
catch (Throwable t) {
System.err.println("Launcher failed - \"Dump Threads\" and \"Exit\" actions are unavailable (" + t.getMessage() + ')');
}
}
public static void main(String[] args) throws Throwable {
try {
boolean helperLibLoaded = loadHelper(System.getProperty(LAUNCHER_BIN_PATH));
int portNumber = Integer.parseInt(System.getProperty(LAUNCHER_PORT_NUMBER));
startMonitor(portNumber, helperLibLoaded);
}
catch (Throwable t) {
System.err.println("Launcher failed - \"Dump Threads\" and \"Exit\" actions are unavailable (" + t.getMessage() + ')');
}
String mainClass = args[0];
String[] params = new String[args.length - 1];
System.arraycopy(args, 1, params, 0, args.length - 1);
Class appClass = Class.forName(mainClass);
Method m;
try {
m = appClass.getMethod("main", new Class[]{params.getClass()});
}
catch (NoSuchMethodException e) {
if (!startJavaFXApplication(params, appClass)) {
throw e;
}
return;
}
if (!Modifier.isStatic(m.getModifiers())) {
System.err.println("main method should be static");
return;
}
if (!void.class.isAssignableFrom(m.getReturnType())) {
System.err.println("main method must return a value of type void");
return;
}
try {
m.setAccessible(true);
m.invoke(null, new Object[]{params});
}
catch (InvocationTargetException ite) {
throw ite.getTargetException();
}
}
private static boolean startJavaFXApplication(String[] params, Class appClass) throws NoSuchMethodException {
try {
//check in launch method for application class in the stack trace leads to this hack here
Class[] types = {appClass.getClass(), params.getClass()};
Method launchApplication = Class.forName(JAVAFX_LAUNCHER).getMethod(LAUNCH_APPLICATION_METHOD_NAME, types);
launchApplication.invoke(null, new Object[] {appClass, params});
return true;
}
catch (Throwable e) {
return false;
}
}
}