mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Updater: automatically restart if possible
This commit is contained in:
Binary file not shown.
@@ -2,65 +2,20 @@
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
@interface TerminationListener : NSObject
|
||||
{
|
||||
const char *executablePath;
|
||||
pid_t parentProcessId;
|
||||
}
|
||||
int main(int argc, const char *argv[]) {
|
||||
if (argc != 2) return EXIT_FAILURE;
|
||||
|
||||
- (void) relaunch;
|
||||
unsigned int interval = 500; // check every 0.5 second
|
||||
unsigned int slept = 0;
|
||||
while (getppid() != 1) {
|
||||
usleep(interval * 1000);
|
||||
|
||||
@end
|
||||
|
||||
@implementation TerminationListener
|
||||
|
||||
- (id) initWithExecutablePath:(const char *)execPath parentProcessId:(pid_t)ppid
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
executablePath = execPath;
|
||||
parentProcessId = ppid;
|
||||
|
||||
// This adds the input source required by the run loop
|
||||
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(applicationDidTerminate:) name:NSWorkspaceDidTerminateApplicationNotification object:nil];
|
||||
if (getppid() == 1) {
|
||||
// ppid is launchd (1) => parent terminated already
|
||||
[self relaunch];
|
||||
}
|
||||
slept += interval;
|
||||
if (slept > 10 * 1000 /* wait for maximum 10 seconds */) return EXIT_FAILURE;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) applicationDidTerminate:(NSNotification *)notification
|
||||
{
|
||||
if (parentProcessId == [[[notification userInfo] valueForKey:@"NSApplicationProcessIdentifier"] intValue]) {
|
||||
// parent just terminated
|
||||
[self relaunch];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) relaunch
|
||||
{
|
||||
// [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(actualLaunch) userInfo:nil repeats:NO];
|
||||
// NSDate *future = [NSDate dateWithTimeIntervalSinceNow: 5.0 ];
|
||||
// [NSThread sleepUntilDate:future];
|
||||
|
||||
[[NSWorkspace sharedWorkspace] launchApplication:[NSString stringWithUTF8String:executablePath]];
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
int main (int argc, const char * argv[])
|
||||
{
|
||||
if (argc != 3) return EXIT_FAILURE;
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
[[[TerminationListener alloc] initWithExecutablePath:argv[1] parentProcessId:atoi(argv[2])] autorelease];
|
||||
[[NSApplication sharedApplication] run];
|
||||
|
||||
[pool release];
|
||||
char const *pathToRelaunch = argv[1];
|
||||
[[NSWorkspace sharedWorkspace] launchApplication:[NSString stringWithUTF8String:pathToRelaunch]];
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
3A6C10B4148122790074811C /* relaunch.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A6C10B3148122790074811C /* relaunch.m */; };
|
||||
3A6C10B7148122940074811C /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A6C10B6148122940074811C /* AppKit.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
CF2F99674C3F98D5739C1B44 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
3A6C10AE148122660074811C /* relaunch */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = relaunch; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3A6C10B3148122790074811C /* relaunch.m */ = {isa = PBXFileReference; fileEncoding = 11; lastKnownFileType = sourcecode.c.objc; path = relaunch.m; sourceTree = "<group>"; };
|
||||
3A6C10B6148122940074811C /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
CF2F99674C3F98D5739C1B43 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3A6C10B7148122940074811C /* AppKit.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
CF2F99674C3F98D5739C1B39 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3A6C10B3148122790074811C /* relaunch.m */,
|
||||
CF2F99674C3F98D5739C1B3A /* Products */,
|
||||
CF2F99674C3F98D5739C1B45 /* Frameworks */,
|
||||
3A6C10B6148122940074811C /* AppKit.framework */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CF2F99674C3F98D5739C1B3A /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3A6C10AE148122660074811C /* relaunch */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CF2F99674C3F98D5739C1B45 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
CF2F99674C3F98D5739C1B3E /* relaunch */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = CF2F99674C3F98D5739C1B3F /* Build configuration list for PBXNativeTarget "relaunch" */;
|
||||
buildPhases = (
|
||||
CF2F99674C3F98D5739C1B42 /* Sources */,
|
||||
CF2F99674C3F98D5739C1B43 /* Frameworks */,
|
||||
CF2F99674C3F98D5739C1B44 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = relaunch;
|
||||
productName = relaunch;
|
||||
productReference = 3A6C10AE148122660074811C /* relaunch */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
CF2F99674C3F98D5739C1B37 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
buildConfigurationList = CF2F99674C3F98D5739C1B38 /* Build configuration list for PBXProject "relaunch" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = CF2F99674C3F98D5739C1B39;
|
||||
productRefGroup = CF2F99674C3F98D5739C1B3A /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
CF2F99674C3F98D5739C1B3E /* relaunch */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
CF2F99674C3F98D5739C1B42 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3A6C10B4148122790074811C /* relaunch.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
CF2F99674C3F98D5739C1B3B /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_VERSION = 4.0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.4;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
SDKROOT = macosx10.4;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
CF2F99674C3F98D5739C1B3C /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_VERSION = 4.0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.4;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
SDKROOT = macosx10.4;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
CF2F99674C3F98D5739C1B40 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = NO;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
CF2F99674C3F98D5739C1B41 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = NO;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
CF2F99674C3F98D5739C1B38 /* Build configuration list for PBXProject "relaunch" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
CF2F99674C3F98D5739C1B3B /* Release */,
|
||||
CF2F99674C3F98D5739C1B3C /* Debug */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
CF2F99674C3F98D5739C1B3F /* Build configuration list for PBXNativeTarget "relaunch" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
CF2F99674C3F98D5739C1B40 /* Release */,
|
||||
CF2F99674C3F98D5739C1B41 /* Debug */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = CF2F99674C3F98D5739C1B37 /* Project object */;
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package com.intellij.idea;
|
||||
import com.intellij.ide.Bootstrap;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.Restarter;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -39,12 +40,38 @@ public class Main {
|
||||
|
||||
public static void main(final String[] args) {
|
||||
if (installPatch()) {
|
||||
|
||||
boolean restarted = false;
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
restarted = Restarter.restart();
|
||||
}
|
||||
catch (Exception ignore) { }
|
||||
JOptionPane.showMessageDialog(null, "The application cannot start right away since some critical files have been changed, " +
|
||||
"please restart it manually.");
|
||||
catch (Restarter.CannotRestartException e) {
|
||||
// noinspection CallToPrintStackTrace
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
final int restartCode = Restarter.getRestartCode();
|
||||
|
||||
if (!restarted && restartCode == 0) {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"The application cannot start right away since some critical files have been changed.\n" +
|
||||
"Please restart it manually.",
|
||||
"Update",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.exit(restartCode);
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -69,11 +96,11 @@ public class Main {
|
||||
return false;
|
||||
}
|
||||
final String firstArg = args[0];
|
||||
return forceEnabledHeadlessMode ||
|
||||
Comparing.strEqual(firstArg, antAppCode) ||
|
||||
Comparing.strEqual(firstArg, duplocateCode) ||
|
||||
Comparing.strEqual(firstArg, traverseUI) ||
|
||||
(firstArg.length() < 20 && firstArg.endsWith("inspect"));
|
||||
return forceEnabledHeadlessMode ||
|
||||
Comparing.strEqual(firstArg, antAppCode) ||
|
||||
Comparing.strEqual(firstArg, duplocateCode) ||
|
||||
Comparing.strEqual(firstArg, traverseUI) ||
|
||||
(firstArg.length() < 20 && firstArg.endsWith("inspect"));
|
||||
}
|
||||
|
||||
public static boolean isUITraverser(final String[] args) {
|
||||
|
||||
+12
-17
@@ -59,6 +59,7 @@ import com.intellij.ui.Splash;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import com.intellij.util.ReflectionCache;
|
||||
import com.intellij.util.Restarter;
|
||||
import com.intellij.util.concurrency.ReentrantWriterPreferenceReadWriteLock;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import com.intellij.util.io.storage.HeavyProcessLatch;
|
||||
@@ -246,13 +247,7 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application
|
||||
});
|
||||
}
|
||||
|
||||
final String s = System.getProperty("jb.restart.code");
|
||||
if (s != null) {
|
||||
try {
|
||||
myRestartCode = Integer.parseInt(s);
|
||||
} catch (NumberFormatException ignore) {
|
||||
}
|
||||
}
|
||||
myRestartCode = Restarter.getRestartCode();
|
||||
|
||||
registerFont("/fonts/Inconsolata.ttf");
|
||||
}
|
||||
@@ -1297,23 +1292,23 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application
|
||||
}
|
||||
|
||||
public boolean isRestartCapable() {
|
||||
return SystemInfo.isWindows || SystemInfo.isMacOSSnowLeopard || myRestartCode > 0;
|
||||
return Restarter.isSupported() || myRestartCode > 0;
|
||||
}
|
||||
|
||||
public void restart() {
|
||||
if (SystemInfo.isWindows) {
|
||||
Win32Restarter.restart();
|
||||
boolean restarted = false;
|
||||
try {
|
||||
restarted = Restarter.restart();
|
||||
}
|
||||
else if (SystemInfo.isMacOSSnowLeopard) {
|
||||
MacRestarter.restart();
|
||||
catch (Restarter.CannotRestartException e) {
|
||||
LOG.warn(e);
|
||||
}
|
||||
else if (myRestartCode > 0) {
|
||||
|
||||
if (!restarted) {
|
||||
myExitCode = myRestartCode;
|
||||
exit(true);
|
||||
}
|
||||
else {
|
||||
exit(true);
|
||||
}
|
||||
|
||||
exit(true);
|
||||
}
|
||||
|
||||
public boolean isSaving() {
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.openapi.application.impl;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationEx;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.ui.mac.foundation.Foundation;
|
||||
import com.intellij.ui.mac.foundation.ID;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* User: spLeaner
|
||||
*/
|
||||
public class MacRestarter {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.application.impl.MacRestarter");
|
||||
|
||||
private MacRestarter() {
|
||||
}
|
||||
|
||||
@SuppressWarnings({"RedundantArrayCreation"})
|
||||
public static void restart() {
|
||||
final ID autoReleasePool = Foundation.invoke("NSAutoreleasePool", "new");
|
||||
final ID app = Foundation.invoke("NSRunningApplication", "currentApplication");
|
||||
final ID executableURL = Foundation.invoke(app, Foundation.createSelector("executableURL"));
|
||||
final ID stringURL = Foundation.invoke(executableURL, Foundation.createSelector("absoluteString"));
|
||||
|
||||
try {
|
||||
final String executablePath = Foundation.toStringViaUTF8(stringURL);
|
||||
final URL url = new URL(executablePath);
|
||||
final String path = url.getPath().replace("%20", " ");
|
||||
if (path.contains(".app")) {
|
||||
final int appIndex = path.indexOf(".app");
|
||||
final String appPath = path.substring(0, appIndex + 4);
|
||||
final String relaunchPath = path.substring(0, path.lastIndexOf('/')) + "/../../bin/relaunch";
|
||||
if (new File(relaunchPath).exists()) {
|
||||
final long processId = Foundation.invoke(app, Foundation.createSelector("processIdentifier")).longValue();
|
||||
|
||||
final ID args = Foundation.invoke(Foundation.getClass("NSArray"), Foundation.createSelector("arrayWithObjects:"),
|
||||
new Object[]{Foundation.nsString(appPath), Foundation.nsString(String.valueOf(processId))});
|
||||
|
||||
Foundation.invoke(Foundation.getClass("NSTask"), Foundation.createSelector("launchedTaskWithLaunchPath:arguments:"),
|
||||
Foundation.nsString(relaunchPath), args);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
finally {
|
||||
Foundation.invoke(autoReleasePool, Foundation.createSelector("release"));
|
||||
((ApplicationEx)ApplicationManager.getApplication()).exit(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.openapi.application.impl;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationEx;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.WString;
|
||||
import com.sun.jna.win32.StdCallLibrary;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class Win32Restarter {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.application.impl.Win32Restarter");
|
||||
|
||||
private Win32Restarter() {
|
||||
}
|
||||
|
||||
public static void restart() {
|
||||
Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
|
||||
WString cline = kernel32.GetCommandLineW();
|
||||
int pid = kernel32.GetCurrentProcessId();
|
||||
|
||||
try {
|
||||
String command = "restarter " + Integer.toString(pid) + " " + cline;
|
||||
LOG.info("Restarter command: " + command);
|
||||
Runtime.getRuntime().exec(command, null, new File(PathManager.getBinPath()));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
Messages.showMessageDialog("Restart failed: " + ex.getMessage(), "Restart", Messages.getErrorIcon());
|
||||
return;
|
||||
}
|
||||
|
||||
// Since the process ID is passed through the command line, we want to make sure that we don't exit before the "restarter"
|
||||
// process has a chance to open the handle to our process, and that it doesn't wait for the termination of an unrelated
|
||||
// process which happened to have the same process ID.
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
}
|
||||
catch (InterruptedException e1) {
|
||||
// ignore
|
||||
}
|
||||
((ApplicationEx)ApplicationManager.getApplication()).exit(true);
|
||||
}
|
||||
|
||||
private interface Kernel32 extends StdCallLibrary {
|
||||
WString GetCommandLineW();
|
||||
int GetCurrentProcessId();
|
||||
}
|
||||
}
|
||||
+26
-31
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
* Copyright 2000-2011 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.
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.intellij.execution.process;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
@@ -25,16 +23,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Utility class to terminate unix processes.
|
||||
*
|
||||
* @author traff
|
||||
*/
|
||||
public class UnixProcessManager {
|
||||
public static final int SIGINT = 2;
|
||||
public static final int SIGKILL = 9;
|
||||
@@ -56,6 +46,25 @@ public class UnixProcessManager {
|
||||
private UnixProcessManager() {
|
||||
}
|
||||
|
||||
public static int getProcessPid() {
|
||||
checkCLib();
|
||||
return C_LIB.getpid();
|
||||
}
|
||||
|
||||
public static int getProcessPid(Process process) {
|
||||
try {
|
||||
Field f = process.getClass().getDeclaredField("pid");
|
||||
f.setAccessible(true);
|
||||
return ((Number)f.get(process)).intValue();
|
||||
}
|
||||
catch (NoSuchFieldException e) {
|
||||
throw new IllegalStateException("system is not unix", e);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException("system is not unix", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendSignal(Process process, int signal) {
|
||||
int process_pid = getProcessPid(process);
|
||||
sendSignal(process_pid, signal);
|
||||
@@ -99,11 +108,11 @@ public class UnixProcessManager {
|
||||
|
||||
@SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
|
||||
BufferedReader stdInput = new BufferedReader(new
|
||||
InputStreamReader(p.getInputStream()));
|
||||
InputStreamReader(p.getInputStream()));
|
||||
BufferedReader stdError = new BufferedReader(new
|
||||
InputStreamReader(p.getErrorStream()));
|
||||
InputStreamReader(p.getErrorStream()));
|
||||
|
||||
List<Integer> childrenPids = Lists.newArrayList();
|
||||
List<Integer> childrenPids = new ArrayList<Integer>();
|
||||
|
||||
boolean result;
|
||||
try {
|
||||
@@ -162,20 +171,6 @@ public class UnixProcessManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static int getProcessPid(Process process) {
|
||||
try {
|
||||
Field f = process.getClass().getDeclaredField("pid");
|
||||
f.setAccessible(true);
|
||||
return ((Number)f.get(process)).intValue();
|
||||
}
|
||||
catch (NoSuchFieldException e) {
|
||||
throw new IllegalStateException("system is not unix", e);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException("system is not unix", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] getPSCmd(boolean commandLineOnly) {
|
||||
if (SystemInfo.isLinux) {
|
||||
return new String[]{"ps", "-e", "e", "--format", commandLineOnly ? "%a" : "%P%p%a"};
|
||||
@@ -210,11 +205,11 @@ public class UnixProcessManager {
|
||||
}
|
||||
|
||||
private static class ProcessInfo {
|
||||
private Map<Integer, List<Integer>> BY_PARENT = Maps.newTreeMap(); // pid -> list of children pids
|
||||
private Map<Integer, List<Integer>> BY_PARENT = new TreeMap<Integer, List<Integer>>(); // pid -> list of children pids
|
||||
|
||||
public void register(Integer pid, Integer parentPid) {
|
||||
List<Integer> children = BY_PARENT.get(parentPid);
|
||||
if (children == null) children = Lists.newLinkedList();
|
||||
if (children == null) children = new LinkedList<Integer>();
|
||||
children.add(pid);
|
||||
BY_PARENT.put(parentPid, children);
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.util;
|
||||
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.WString;
|
||||
import com.sun.jna.win32.StdCallLibrary;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class Restarter {
|
||||
private Restarter() {
|
||||
}
|
||||
|
||||
public static int getRestartCode() {
|
||||
String s = System.getProperty("jb.restart.code");
|
||||
if (s != null) {
|
||||
try {
|
||||
return Integer.parseInt(s);
|
||||
}
|
||||
catch (NumberFormatException ignore) {
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static boolean isSupported() {
|
||||
return SystemInfo.isWindows || SystemInfo.isMac;
|
||||
}
|
||||
|
||||
public static boolean restart() throws CannotRestartException {
|
||||
try {
|
||||
if (SystemInfo.isWindows) {
|
||||
return restartOnWindows();
|
||||
}
|
||||
else if (SystemInfo.isMac) {
|
||||
return restartOnMac();
|
||||
}
|
||||
}
|
||||
catch (CannotRestartException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
throw new CannotRestartException(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean restartOnWindows() throws CannotRestartException {
|
||||
Kernel32 kernel32 = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class);
|
||||
WString cline = kernel32.GetCommandLineW();
|
||||
int pid = kernel32.GetCurrentProcessId();
|
||||
|
||||
try {
|
||||
String command = "restarter " + Integer.toString(pid) + " " + cline;
|
||||
Runtime.getRuntime().exec(command, null, new File(PathManager.getBinPath()));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new CannotRestartException(ex);
|
||||
}
|
||||
|
||||
// Since the process ID is passed through the command line, we want to make sure that we don't exit before the "restarter"
|
||||
// process has a chance to open the handle to our process, and that it doesn't wait for the termination of an unrelated
|
||||
// process which happened to have the same process ID.
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
}
|
||||
catch (InterruptedException e1) {
|
||||
// ignore
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private interface Kernel32 extends StdCallLibrary {
|
||||
WString GetCommandLineW();
|
||||
|
||||
int GetCurrentProcessId();
|
||||
}
|
||||
|
||||
private static boolean restartOnMac() throws CannotRestartException {
|
||||
String binPath = PathManager.getBinPath();
|
||||
|
||||
if (!binPath.contains(".app")) return false;
|
||||
|
||||
int appIndex = binPath.indexOf(".app");
|
||||
String appPath = binPath.substring(0, appIndex + 4);
|
||||
|
||||
try {
|
||||
Runtime.getRuntime().exec(new String[]{new File(PathManager.getBinPath(), "relaunch").getPath(), appPath});
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new CannotRestartException(e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class CannotRestartException extends Exception {
|
||||
public CannotRestartException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user