Skip to content

Commit 54146c5

Browse files
committed
Refactor workspace lock
1 parent 9bb6373 commit 54146c5

File tree

3 files changed

+159
-91
lines changed

3 files changed

+159
-91
lines changed

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

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import org.eclipse.ui.PlatformUI;
6363
import org.eclipse.ui.internal.Workbench;
6464
import org.eclipse.ui.internal.WorkbenchPlugin;
65+
import org.eclipse.ui.internal.WorkspaceLock;
6566
import org.eclipse.ui.internal.ide.ChooseWorkspaceData;
6667
import org.eclipse.ui.internal.ide.ChooseWorkspaceDialog;
6768
import org.eclipse.ui.internal.ide.IDEInternalPreferences;
@@ -90,13 +91,6 @@ public class IDEApplication implements IApplication, IExecutableExtension {
9091

9192
private static final String HOST_NAME_VAR = "HOSTNAME"; //$NON-NLS-1$
9293

93-
private static final String PROCESS_ID = "process-id"; //$NON-NLS-1$
94-
95-
private static final String DISPLAY = "display"; //$NON-NLS-1$
96-
97-
private static final String HOST = "host"; //$NON-NLS-1$
98-
99-
private static final String USER = "user"; //$NON-NLS-1$
10094

10195
private static final String USER_NAME = "user.name"; //$NON-NLS-1$
10296

@@ -270,9 +264,10 @@ protected Object checkInstanceLocation(Shell shell, Map applicationArguments) {
270264
}
271265

272266
// check if there is a lock info then append it to error message.
273-
String lockInfo = Workbench.getWorkspaceLockDetails(instanceLoc.getURL());
267+
String lockInfo = WorkspaceLock.getWorkspaceLockDetails(instanceLoc.getURL());
274268
if (lockInfo != null) {
275-
Workbench.showWorkspaceLockedDialog(workspaceDirectory.getAbsolutePath(), lockInfo);
269+
WorkspaceLock.showWorkspaceLockedDialog(shell, workspaceDirectory.getAbsolutePath(),
270+
lockInfo);
276271
}
277272
} else {
278273
MessageDialog.openError(
@@ -367,7 +362,7 @@ protected Object checkInstanceLocation(Shell shell, Map applicationArguments) {
367362
// by this point it has been determined that the workspace is
368363
// already in use -- force the user to choose again
369364

370-
String lockInfo = Workbench.getWorkspaceLockDetails(workspaceUrl);
365+
String lockInfo = WorkspaceLock.getWorkspaceLockDetails(workspaceUrl);
371366

372367
MessageDialog dialog = new MessageDialog(null, IDEWorkbenchMessages.IDEApplication_workspaceInUseTitle,
373368
null, NLS.bind(IDEWorkbenchMessages.IDEApplication_workspaceInUseMessage, workspaceUrl.getFile()),
@@ -410,19 +405,19 @@ protected void writeWsLockInfo(URL workspaceUrl) {
410405

411406
String user = System.getProperty(USER_NAME);
412407
if (user != null) {
413-
props.setProperty(USER, user);
408+
props.setProperty(WorkspaceLock.USER, user);
414409
}
415410
String host = getHostName();
416411
if (host != null) {
417-
props.setProperty(HOST, host);
412+
props.setProperty(WorkspaceLock.HOST, host);
418413
}
419414
String display = getDisplay();
420415
if (display != null) {
421-
props.setProperty(DISPLAY, display);
416+
props.setProperty(WorkspaceLock.DISPLAY, display);
422417
}
423418
String pid = getProcessId();
424419
if (pid != null) {
425-
props.setProperty(PROCESS_ID, pid);
420+
props.setProperty(WorkspaceLock.PROCESS_ID, pid);
426421
}
427422

428423
if (props.isEmpty()) {
@@ -485,7 +480,7 @@ private String getHostName() {
485480
* @return .lock_info file.
486481
*/
487482
private static Path createLockInfoFile(URL workspaceUrl) throws Exception {
488-
Path lockInfoFile = Workbench.getLockInfoFile(workspaceUrl);
483+
Path lockInfoFile = WorkspaceLock.getLockInfoFile(workspaceUrl);
489484
if (!Files.exists(lockInfoFile)) {
490485
Files.createFile(lockInfoFile);
491486
}

bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/Workbench.java

Lines changed: 4 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import java.net.URI;
4040
import java.net.URISyntaxException;
4141
import java.net.URL;
42-
import java.nio.file.Files;
4342
import java.nio.file.Path;
4443
import java.util.ArrayList;
4544
import java.util.Arrays;
@@ -52,7 +51,6 @@
5251
import java.util.List;
5352
import java.util.Map;
5453
import java.util.Objects;
55-
import java.util.Properties;
5654
import java.util.Set;
5755
import java.util.UUID;
5856
import java.util.concurrent.atomic.AtomicReference;
@@ -84,7 +82,6 @@
8482
import org.eclipse.core.runtime.SafeRunner;
8583
import org.eclipse.core.runtime.Status;
8684
import org.eclipse.core.runtime.SubMonitor;
87-
import org.eclipse.core.runtime.URIUtil;
8885
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
8986
import org.eclipse.core.runtime.jobs.Job;
9087
import org.eclipse.core.runtime.preferences.ConfigurationScope;
@@ -119,7 +116,6 @@
119116
import org.eclipse.e4.ui.workbench.modeling.EModelService;
120117
import org.eclipse.e4.ui.workbench.modeling.EPartService;
121118
import org.eclipse.e4.ui.workbench.modeling.ISaveHandler;
122-
import org.eclipse.e4.ui.workbench.swt.internal.copy.WorkbenchSWTMessages;
123119
import org.eclipse.emf.ecore.EObject;
124120
import org.eclipse.emf.ecore.resource.Resource;
125121
import org.eclipse.emf.ecore.util.EcoreUtil;
@@ -2706,7 +2702,7 @@ private static String buildCommandLine(String workspace) {
27062702
*
27072703
* @param workspacePath the new workspace location
27082704
* @return {@link IApplication#EXIT_OK} or {@link IApplication#EXIT_RELAUNCH} or
2709-
* <code>null</code>
2705+
* <code>null</code> if workspace is locked
27102706
*/
27112707
@SuppressWarnings("restriction")
27122708
public static Object setRestartArguments(String workspacePath) {
@@ -2723,9 +2719,9 @@ public static Object setRestartArguments(String workspacePath) {
27232719
}
27242720
Path selectedWorkspace = Path.of(workspacePath);
27252721
try {
2726-
String workspaceLock = getWorkspaceLockDetails(selectedWorkspace.toUri().toURL());
2727-
if (workspaceLock != null && !workspaceLock.isEmpty()) {
2728-
showWorkspaceLockedDialog(workspacePath, workspaceLock);
2722+
String workspaceLock = WorkspaceLock.getWorkspaceLockDetails(selectedWorkspace.toUri().toURL());
2723+
if (workspaceLock != null) {
2724+
WorkspaceLock.showWorkspaceLockedDialog(null, workspacePath, workspaceLock);
27292725
return null;
27302726
}
27312727
} catch (MalformedURLException e) {
@@ -3701,72 +3697,4 @@ public void runWithInitialAutoScaleValue(Runnable runnable) {
37013697
}
37023698

37033699
}
3704-
3705-
/**
3706-
* Extract the lock details of the selected workspace if it is locked by another
3707-
* Eclipse application
3708-
*
3709-
* @param workspaceUrl the <code>URL</code> of selected workspace
3710-
* @return <code>String</code> details of lock owned workspace,
3711-
* <code>null or Empty</code> if not locked
3712-
*/
3713-
@SuppressWarnings("restriction")
3714-
public static String getWorkspaceLockDetails(URL workspaceUrl) {
3715-
Path lockFile = getLockInfoFile(workspaceUrl);
3716-
if (lockFile != null && Files.exists(lockFile)) {
3717-
StringBuilder lockDetails = new StringBuilder();
3718-
Properties properties = new Properties();
3719-
try (InputStream is = Files.newInputStream(lockFile)) {
3720-
properties.load(is);
3721-
String prop = properties.getProperty("user"); //$NON-NLS-1$
3722-
if (prop != null) {
3723-
lockDetails.append(NLS.bind(WorkbenchSWTMessages.IDEApplication_workspaceLockOwner, prop));
3724-
}
3725-
prop = properties.getProperty("host"); //$NON-NLS-1$
3726-
if (prop != null) {
3727-
lockDetails.append(NLS.bind(WorkbenchSWTMessages.IDEApplication_workspaceLockHost, prop));
3728-
}
3729-
prop = properties.getProperty("display"); //$NON-NLS-1$
3730-
if (prop != null) {
3731-
lockDetails.append(NLS.bind(WorkbenchSWTMessages.IDEApplication_workspaceLockDisplay, prop));
3732-
}
3733-
prop = properties.getProperty("process-id"); //$NON-NLS-1$
3734-
if (prop != null) {
3735-
lockDetails.append(NLS.bind(WorkbenchSWTMessages.IDEApplication_workspaceLockPID, prop));
3736-
}
3737-
3738-
} catch (IOException e) {
3739-
WorkbenchPlugin.log(e);
3740-
}
3741-
return lockDetails.toString();
3742-
}
3743-
return null;
3744-
}
3745-
3746-
/**
3747-
* Returns the lock file.
3748-
*
3749-
* @param workspaceUrl the <code>URL</code> of selected workspace
3750-
* @return the path to the <code>.lock_info</code> file within the specified
3751-
* workspace, or <code> null</code> if the workspace URL cannot be
3752-
* converted to a valid URI
3753-
*/
3754-
public static Path getLockInfoFile(URL workspaceUrl) {
3755-
Path lockFile = Path.of(".metadata", ".lock_info"); //$NON-NLS-1$ //$NON-NLS-2$
3756-
try {
3757-
return Path.of(URIUtil.toURI(workspaceUrl)).resolve(lockFile);
3758-
} catch (URISyntaxException e) {
3759-
return null;
3760-
}
3761-
}
3762-
3763-
@SuppressWarnings("restriction")
3764-
public static void showWorkspaceLockedDialog(String workspacePath, String workspaceLock) {
3765-
String lockMessage = NLS.bind(WorkbenchSWTMessages.IDEApplication_workspaceCannotLockMessage2, workspacePath);
3766-
String wsLockedError = lockMessage + System.lineSeparator() + System.lineSeparator()
3767-
+ NLS.bind(WorkbenchSWTMessages.IDEApplication_workspaceLockMessage, workspaceLock);
3768-
3769-
MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
3770-
WorkbenchSWTMessages.IDEApplication_workspaceCannotLockTitle, wsLockedError);
3771-
}
37723700
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 IBM Corporation.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* IBM Corporation - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.ui.internal;
15+
16+
import java.io.IOException;
17+
import java.io.InputStream;
18+
import java.net.URISyntaxException;
19+
import java.net.URL;
20+
import java.nio.file.Files;
21+
import java.nio.file.Path;
22+
import java.util.Properties;
23+
import org.eclipse.core.runtime.URIUtil;
24+
import org.eclipse.e4.ui.workbench.swt.internal.copy.WorkbenchSWTMessages;
25+
import org.eclipse.jface.dialogs.MessageDialog;
26+
import org.eclipse.osgi.util.NLS;
27+
import org.eclipse.swt.widgets.Shell;
28+
29+
/**
30+
* Utility class for reading and presenting workspace lock information.
31+
*
32+
* <p>
33+
* This class is used during two different phases of the Eclipse application
34+
* lifecycle:
35+
* </p>
36+
* <ul>
37+
* <li>before the Workbench is created (no workbench windows exist, such as when
38+
* the Workspace Launcher dialog is displayed)</li>
39+
* <li>after the Workbench has been created and workbench windows are
40+
* available</li>
41+
* </ul>
42+
*
43+
* <p>
44+
* To support both environments, this class does not rely on workbench-specific
45+
* APIs such as {@code PlatformUI.getWorkbench()} or {@code IWorkbenchWindow},
46+
* nor on any API that requires an initialized workbench window. Only SWT-level
47+
* constructs (for example, {@link org.eclipse.swt.widgets.Display} and
48+
* {@link org.eclipse.swt.widgets.Shell}) and core/runtime APIs are used.
49+
* </p>
50+
*
51+
* @since 3.5
52+
*/
53+
public class WorkspaceLock {
54+
55+
public static final String PROCESS_ID = "process-id"; //$NON-NLS-1$
56+
57+
public static final String DISPLAY = "display"; //$NON-NLS-1$
58+
59+
public static final String HOST = "host"; //$NON-NLS-1$
60+
61+
public static final String USER = "user"; //$NON-NLS-1$
62+
63+
/**
64+
* Extract the lock details of the selected workspace if it is locked by another
65+
* Eclipse application
66+
*
67+
* @param workspaceUrl the <code>URL</code> of selected workspace
68+
* @return <code>String</code> details of lock owned workspace,
69+
* <code>null or Empty</code> if not locked
70+
*/
71+
@SuppressWarnings("restriction")
72+
public static String getWorkspaceLockDetails(URL workspaceUrl) {
73+
Path lockFile = getLockInfoFile(workspaceUrl);
74+
if (lockFile != null && Files.exists(lockFile)) {
75+
StringBuilder lockDetails = new StringBuilder();
76+
Properties properties = new Properties();
77+
try (InputStream is = Files.newInputStream(lockFile)) {
78+
properties.load(is);
79+
String prop = properties.getProperty(USER);
80+
if (prop != null) {
81+
lockDetails.append(NLS.bind(WorkbenchSWTMessages.IDEApplication_workspaceLockOwner, prop));
82+
}
83+
prop = properties.getProperty(HOST);
84+
if (prop != null) {
85+
lockDetails.append(NLS.bind(WorkbenchSWTMessages.IDEApplication_workspaceLockHost, prop));
86+
}
87+
prop = properties.getProperty(DISPLAY);
88+
if (prop != null) {
89+
lockDetails.append(NLS.bind(WorkbenchSWTMessages.IDEApplication_workspaceLockDisplay, prop));
90+
}
91+
prop = properties.getProperty(PROCESS_ID);
92+
if (prop != null) {
93+
lockDetails.append(NLS.bind(WorkbenchSWTMessages.IDEApplication_workspaceLockPID, prop));
94+
}
95+
96+
} catch (IOException e) {
97+
WorkbenchPlugin.log(e);
98+
}
99+
return lockDetails.toString();
100+
}
101+
return null;
102+
}
103+
104+
/**
105+
* Returns the lock file.
106+
*
107+
* @param workspaceUrl the <code>URL</code> of selected workspace
108+
* @return the path to the <code>.lock_info</code> file within the specified
109+
* workspace, or <code> null</code> if the workspace URL cannot be
110+
* converted to a valid URI
111+
*/
112+
public static Path getLockInfoFile(URL workspaceUrl) {
113+
Path lockFile = Path.of(".metadata", ".lock_info"); //$NON-NLS-1$ //$NON-NLS-2$
114+
try {
115+
return Path.of(URIUtil.toURI(workspaceUrl)).resolve(lockFile);
116+
} catch (URISyntaxException e) {
117+
return null;
118+
}
119+
}
120+
121+
/**
122+
* Opens an error dialog indicating that the selected workspace is locked by
123+
* another Eclipse instance.
124+
* <p>
125+
* This method works in both early startup (before the Workbench is created) and
126+
* in normal runtime (after Workbench windows exist).
127+
* </p>
128+
*
129+
* @param shell the parent {@link Shell} for the dialog, or
130+
* {@code null} if no workbench window is available
131+
* @param workspacePath the absolute path of the workspace that could not
132+
* be locked
133+
* @param workspaceLockOwner a formatted description of the existing lock owner
134+
*/
135+
@SuppressWarnings("restriction")
136+
public static void showWorkspaceLockedDialog(Shell shell, String workspacePath, String workspaceLockOwner) {
137+
String lockMessage = NLS.bind(WorkbenchSWTMessages.IDEApplication_workspaceCannotLockMessage2, workspacePath);
138+
String wsLockedError = lockMessage + System.lineSeparator() + System.lineSeparator()
139+
+ NLS.bind(WorkbenchSWTMessages.IDEApplication_workspaceLockMessage, workspaceLockOwner);
140+
141+
MessageDialog.openError(shell,
142+
WorkbenchSWTMessages.IDEApplication_workspaceCannotLockTitle, wsLockedError);
143+
}
144+
145+
}

0 commit comments

Comments
 (0)