Skip to content

Commit 10fa592

Browse files
committed
Improve workspace lock error dialog.
Write workspace lock info like user, host, java process id, display properties onto .lock file if the lock was successful. Read the current lock data in case of lock was unsuccessful and shown it in error dialog. If the .lock file has no info then nothing is shown. For older eclipse versions. see #2343
1 parent 70a2d11 commit 10fa592

File tree

1 file changed

+171
-1
lines changed
  • bundles/org.eclipse.ui.ide.application/src/org/eclipse/ui/internal/ide/application

1 file changed

+171
-1
lines changed

bundles/org.eclipse.ui.ide.application/src/org/eclipse/ui/internal/ide/application/IDEApplication.java

Lines changed: 171 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
import java.io.FileOutputStream;
2626
import java.io.IOException;
2727
import java.io.OutputStream;
28+
import java.net.InetAddress;
2829
import java.net.MalformedURLException;
2930
import java.net.URL;
31+
import java.net.UnknownHostException;
3032
import java.util.LinkedHashMap;
3133
import java.util.Map;
3234
import java.util.Properties;
@@ -49,7 +51,11 @@
4951
import org.eclipse.osgi.service.datalocation.Location;
5052
import org.eclipse.osgi.util.NLS;
5153
import org.eclipse.swt.SWT;
54+
import org.eclipse.swt.layout.FillLayout;
55+
import org.eclipse.swt.widgets.Composite;
56+
import org.eclipse.swt.widgets.Control;
5257
import org.eclipse.swt.widgets.Display;
58+
import org.eclipse.swt.widgets.Label;
5359
import org.eclipse.swt.widgets.Shell;
5460
import org.eclipse.ui.IWorkbench;
5561
import org.eclipse.ui.PlatformUI;
@@ -79,6 +85,20 @@ public class IDEApplication implements IApplication, IExecutableExtension {
7985

8086
private static final String VERSION_FILENAME = "version.ini"; //$NON-NLS-1$
8187

88+
private static final String LOCK_FILENAME = ".lock"; //$NON-NLS-1$
89+
90+
private static final String DISPLAY_VAR = "DISPLAY"; //$NON-NLS-1$
91+
92+
private static final String PROCESS_ID = "process-id"; //$NON-NLS-1$
93+
94+
private static final String DISPLAY = "display"; //$NON-NLS-1$
95+
96+
private static final String HOST = "host"; //$NON-NLS-1$
97+
98+
private static final String USER = "user"; //$NON-NLS-1$
99+
100+
private static final String USER_NAME = "user.name"; //$NON-NLS-1$
101+
82102
// Use the branding plug-in of the platform feature since this is most likely
83103
// to change on an update of the IDE.
84104
private static final String WORKSPACE_CHECK_REFERENCE_BUNDLE_NAME = "org.eclipse.platform"; //$NON-NLS-1$
@@ -225,6 +245,7 @@ protected Object checkInstanceLocation(Shell shell, Map applicationArguments) {
225245
try {
226246
if (instanceLoc.lock()) {
227247
writeWorkspaceVersion();
248+
writeWsLockInfo();
228249
return null;
229250
}
230251

@@ -313,6 +334,7 @@ protected Object checkInstanceLocation(Shell shell, Map applicationArguments) {
313334
if (instanceLoc.set(workspaceUrl, true)) {
314335
launchData.writePersistedData();
315336
writeWorkspaceVersion();
337+
writeWsLockInfo();
316338
return null;
317339
}
318340
} catch (IllegalStateException e) {
@@ -332,17 +354,165 @@ protected Object checkInstanceLocation(Shell shell, Map applicationArguments) {
332354

333355
// by this point it has been determined that the workspace is
334356
// already in use -- force the user to choose again
357+
358+
String lockInfo = getWorkspaceLockInfo();
359+
335360
MessageDialog dialog = new MessageDialog(null, IDEWorkbenchMessages.IDEApplication_workspaceInUseTitle,
336361
null, NLS.bind(IDEWorkbenchMessages.IDEApplication_workspaceInUseMessage, workspaceUrl.getFile()),
337362
MessageDialog.ERROR, 1, IDEWorkbenchMessages.IDEApplication_workspaceInUse_Retry,
338-
IDEWorkbenchMessages.IDEApplication_workspaceInUse_Choose);
363+
IDEWorkbenchMessages.IDEApplication_workspaceInUse_Choose) {
364+
@Override
365+
protected Control createCustomArea(Composite parent) {
366+
if (lockInfo == null || lockInfo.isBlank()) {
367+
return null;
368+
}
369+
370+
String displayText = "Workspace lock is held by the following owner:\n".concat(lockInfo); //$NON-NLS-1$
371+
372+
Composite container = new Composite(parent, SWT.NONE);
373+
container.setLayout(new FillLayout());
374+
375+
Label multiLineText = new Label(container, SWT.NONE);
376+
multiLineText.setText(displayText);
377+
378+
return container;
379+
}
380+
};
339381
// the return value influences the next loop's iteration
340382
returnValue = dialog.open();
341383
// Remember the locked workspace as recent workspace
342384
launchData.writePersistedData();
343385
}
344386
}
345387

388+
/**
389+
* Read workspace lock file and parse all the properties present. Based on the
390+
* eclipse version and operating system some or all the properties may not
391+
* present. In such scenario it will return empty string.
392+
*
393+
* @return Previous lock owner details.
394+
*/
395+
private String getWorkspaceLockInfo() {
396+
Location instanceLoc = Platform.getInstanceLocation();
397+
File lockFile = getLockFile(instanceLoc.getURL());
398+
StringBuilder sb = new StringBuilder();
399+
Properties props = new Properties();
400+
try (FileInputStream is = new FileInputStream(lockFile)) {
401+
props.load(is);
402+
String prop = props.getProperty(USER);
403+
if (prop != null) {
404+
sb.append("user: ").append(prop).append(System.lineSeparator()); //$NON-NLS-1$
405+
}
406+
prop = props.getProperty(HOST);
407+
if (prop != null) {
408+
sb.append("host: ").append(prop).append(System.lineSeparator()); //$NON-NLS-1$
409+
}
410+
prop = props.getProperty(DISPLAY);
411+
if (prop != null) {
412+
sb.append("display: ").append(prop).append(System.lineSeparator()); //$NON-NLS-1$
413+
}
414+
prop = props.getProperty(PROCESS_ID);
415+
if (prop != null) {
416+
sb.append("process-id: ").append(prop).append(System.lineSeparator()); //$NON-NLS-1$
417+
}
418+
return sb.toString();
419+
} catch (Exception e) {
420+
IDEWorkbenchPlugin.log("Could not read lock file: ", e); //$NON-NLS-1$
421+
}
422+
return null;
423+
}
424+
425+
/**
426+
* Write lock owner details onto workspace lock file. Data includes user, host,
427+
* display and current java process id.
428+
*/
429+
private void writeWsLockInfo() {
430+
Location instanceLoc = Platform.getInstanceLocation();
431+
if (instanceLoc == null || instanceLoc.isReadOnly()) {
432+
return;
433+
}
434+
435+
File lockFile = getLockFile(instanceLoc.getURL());
436+
if (lockFile == null) {
437+
return;
438+
}
439+
440+
Properties props = new Properties();
441+
442+
String user = System.getProperty(USER_NAME);
443+
if (user != null) {
444+
props.setProperty(USER, user);
445+
}
446+
String host = getHostName();
447+
if (host != null) {
448+
props.setProperty(HOST, host);
449+
}
450+
String display = getDisplay();
451+
if (display != null) {
452+
props.setProperty(DISPLAY, display);
453+
}
454+
String pid = getProcessId();
455+
if (pid != null) {
456+
props.setProperty(PROCESS_ID, pid);
457+
}
458+
459+
try (OutputStream output = new FileOutputStream(lockFile)) {
460+
props.store(output, null);
461+
} catch (IOException e) {
462+
IDEWorkbenchPlugin.log("Could not modify lock file", e); //$NON-NLS-1$
463+
}
464+
}
465+
466+
private String getDisplay() {
467+
String displayEnv = null;
468+
try {
469+
displayEnv = System.getenv(DISPLAY_VAR);
470+
} catch (Exception e) {
471+
IDEWorkbenchPlugin.log("Failed to read DISPLAY variable.", e); //$NON-NLS-1$
472+
}
473+
return displayEnv;
474+
}
475+
476+
private String getProcessId() {
477+
Long pid = null;
478+
try {
479+
pid = ProcessHandle.current().pid();
480+
} catch (Exception e) {
481+
IDEWorkbenchPlugin.log("Failed to read Java process id.", e); //$NON-NLS-1$
482+
}
483+
return pid != null ? pid.toString() : null;
484+
}
485+
486+
private String getHostName() {
487+
String hostName = null;
488+
try {
489+
hostName = InetAddress.getLocalHost().getHostName();
490+
} catch (UnknownHostException e) {
491+
IDEWorkbenchPlugin.log("Failed to read host name.", e); //$NON-NLS-1$
492+
}
493+
return hostName;
494+
}
495+
496+
private File getLockFile(URL workspaceUrl) {
497+
if (workspaceUrl == null) {
498+
return null;
499+
}
500+
501+
// make sure the directory exists
502+
File metaDir = new File(workspaceUrl.getPath(), METADATA_FOLDER);
503+
if (!metaDir.exists()) {
504+
return null;
505+
}
506+
507+
// make sure the file exists
508+
File lockFile = new File(metaDir, LOCK_FILENAME);
509+
if (!lockFile.exists()) {
510+
return null;
511+
}
512+
513+
return lockFile;
514+
}
515+
346516
@SuppressWarnings("rawtypes")
347517
private static boolean isDevLaunchMode(Map args) {
348518
// see org.eclipse.pde.internal.core.PluginPathFinder.isDevLaunchMode()

0 commit comments

Comments
 (0)