Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 286531 Details for
Bug 574034
relaunch on exit code
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Relaunch on exit code
0001-Add-option-for-relaunch-on-exit-code.patch (text/plain), 18.95 KB, created by
Fei Ding
on 2021-06-04 17:26:25 EDT
(
hide
)
Description:
Relaunch on exit code
Filename:
MIME Type:
Creator:
Fei Ding
Created:
2021-06-04 17:26:25 EDT
Size:
18.95 KB
patch
obsolete
>From 0e1870017d6985118e0f40df596aa9a091fb7a08 Mon Sep 17 00:00:00 2001 >From: Ding Fei <fei.ding@ustchcs.com> >Date: Sat, 5 Jun 2021 01:10:56 +0800 >Subject: [PATCH] Add option for relaunch on exit code. > >Signed-off-by: Ding Fei <danix800@gmail.com> >--- > .../ui/launchConfigurations/JavaMainTab.java | 70 ++++++++- > .../debug/ui/launcher/LauncherMessages.java | 5 + > .../ui/launcher/LauncherMessages.properties | 4 + > .../internal/launching/LaunchListener.java | 148 ++++++++++++++++++ > .../internal/launching/LaunchingPlugin.java | 14 ++ > .../IJavaLaunchConfigurationConstants.java | 23 +++ > .../jdt/launching/JavaLaunchDelegate.java | 2 + > 7 files changed, 265 insertions(+), 1 deletion(-) > create mode 100644 org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchListener.java > >diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaMainTab.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaMainTab.java >index 9cb792f2d..fdbdad03f 100644 >--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaMainTab.java >+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaMainTab.java >@@ -45,11 +45,14 @@ import org.eclipse.jdt.ui.ISharedImages; > import org.eclipse.jdt.ui.JavaUI; > import org.eclipse.jface.window.Window; > import org.eclipse.osgi.util.NLS; >+import org.eclipse.swt.events.ModifyEvent; >+import org.eclipse.swt.events.ModifyListener; > import org.eclipse.swt.graphics.Image; > import org.eclipse.swt.layout.GridData; > import org.eclipse.swt.layout.GridLayout; > import org.eclipse.swt.widgets.Button; > import org.eclipse.swt.widgets.Composite; >+import org.eclipse.swt.widgets.Text; > import org.eclipse.ui.PlatformUI; > > /** >@@ -85,6 +88,8 @@ public class JavaMainTab extends SharedJavaMainTab { > private Button fSearchExternalJarsCheckButton; > private Button fConsiderInheritedMainButton; > private Button fStopInMainCheckButton; >+ private Button fRelaunchOnExitcodeCheckButton; >+ private Text fRelaunchExitCodeText; > > /* (non-Javadoc) > * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite) >@@ -111,8 +116,18 @@ public class JavaMainTab extends SharedJavaMainTab { > fConsiderInheritedMainButton = SWTFactory.createCheckButton(parent, LauncherMessages.JavaMainTab_22, null, false, 2); > fConsiderInheritedMainButton.addSelectionListener(getDefaultListener()); > >- fStopInMainCheckButton = SWTFactory.createCheckButton(parent, LauncherMessages.JavaMainTab_St_op_in_main_1, null, false, 1); >+ fStopInMainCheckButton = SWTFactory.createCheckButton(parent, LauncherMessages.JavaMainTab_St_op_in_main_1, null, false, 2); > fStopInMainCheckButton.addSelectionListener(getDefaultListener()); >+ >+ fRelaunchOnExitcodeCheckButton = SWTFactory.createCheckButton(parent, LauncherMessages.JavaMainTab_Relaunch_on_exit_code, null, false, 1); >+ fRelaunchOnExitcodeCheckButton.addSelectionListener(getDefaultListener()); >+ fRelaunchExitCodeText = SWTFactory.createSingleText(parent, 1); >+ fRelaunchExitCodeText.addModifyListener(new ModifyListener() { >+ @Override >+ public void modifyText(ModifyEvent e) { >+ updateLaunchConfigurationDialog(); >+ } >+ }); > } > > /* (non-Javadoc) >@@ -203,6 +218,7 @@ public class JavaMainTab extends SharedJavaMainTab { > super.initializeFrom(config); > updateMainTypeFromConfig(config); > updateStopInMainFromConfig(config); >+ updateRelaunchOnExitCode(config); > updateInheritedMainsFromConfig(config); > updateExternalJars(config); > } >@@ -242,6 +258,17 @@ public class JavaMainTab extends SharedJavaMainTab { > setErrorMessage(LauncherMessages.JavaMainTab_Main_type_not_specified_16); > return false; > } >+ String exitCode = fRelaunchExitCodeText.getText().trim(); >+ if (exitCode.length() == 0) { >+ setErrorMessage(LauncherMessages.javaMainTab_Invalid_exit_code); >+ return false; >+ } >+ try { >+ Integer.parseInt(exitCode); >+ } catch (NumberFormatException e) { >+ setErrorMessage(LauncherMessages.javaMainTab_Invalid_exit_code); >+ return false; >+ } > return true; > } > >@@ -263,6 +290,22 @@ public class JavaMainTab extends SharedJavaMainTab { > config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_STOP_IN_MAIN, (String)null); > } > >+ if (fRelaunchOnExitcodeCheckButton.getSelection()) { >+ config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_RELAUNCH_ON_EXIT_CODE, true); >+ } >+ else { >+ config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_RELAUNCH_ON_EXIT_CODE, (String) null); >+ } >+ >+ if (fRelaunchExitCodeText.isEnabled()) { >+ int exitCode = IJavaLaunchConfigurationConstants.DEFAULT_RELAUNCH_EXIT_CODE; >+ try { >+ exitCode = Integer.parseInt(fRelaunchExitCodeText.getText()); >+ } catch (NumberFormatException e) { >+ } >+ config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_RELAUNCH_EXIT_CODE, exitCode); >+ } >+ > // attribute added in 2.1, so null must be used instead of false for backwards compatibility > if (fSearchExternalJarsCheckButton.getSelection()) { > config.setAttribute(ATTR_INCLUDE_EXTERNAL_JARS, true); >@@ -305,6 +348,7 @@ public class JavaMainTab extends SharedJavaMainTab { > super.initializeAttributes(); > getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, LauncherMessages.SharedJavaMainTab_AttributeLabel_MainTypeName); > getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_STOP_IN_MAIN, LauncherMessages.JavaMainTab_AttributeLabel_StopInMain); >+ getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_RELAUNCH_ON_EXIT_CODE, LauncherMessages.JavaMainTab_AttributeLabel_RelaunchOnExitCode); > getAttributesLabelsForPrototype().put(JavaMainTab.ATTR_INCLUDE_EXTERNAL_JARS, LauncherMessages.JavaMainTab_AttributeLabel_IncludeExternalJars); > getAttributesLabelsForPrototype().put(JavaMainTab.ATTR_CONSIDER_INHERITED_MAIN, LauncherMessages.JavaMainTab_AttributeLabel_InheritedMain); > } >@@ -348,4 +392,28 @@ public class JavaMainTab extends SharedJavaMainTab { > fStopInMainCheckButton.setSelection(stop); > } > >+ /** >+ * updates the relaunch on exit code attribute from the specified launch config >+ * >+ * @param config >+ * the config to load the stop in main attribute from >+ */ >+ private void updateRelaunchOnExitCode(ILaunchConfiguration config) { >+ boolean relaunchOnExitcode = false; >+ try { >+ relaunchOnExitcode = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_RELAUNCH_ON_EXIT_CODE, false); >+ } catch (CoreException e) { >+ JDIDebugUIPlugin.log(e); >+ } >+ fRelaunchOnExitcodeCheckButton.setSelection(relaunchOnExitcode); >+ >+ int exitcode = IJavaLaunchConfigurationConstants.DEFAULT_RELAUNCH_EXIT_CODE; >+ try { >+ exitcode = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_RELAUNCH_EXIT_CODE, IJavaLaunchConfigurationConstants.DEFAULT_RELAUNCH_EXIT_CODE); >+ } catch (CoreException e) { >+ JDIDebugUIPlugin.log(e); >+ } >+ fRelaunchExitCodeText.setText(exitcode + ""); //$NON-NLS-1$ >+ } >+ > } >diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.java >index ef34e7d00..f4d822d62 100644 >--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.java >+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.java >@@ -88,6 +88,8 @@ public class LauncherMessages extends NLS { > public static String JavaMainTab_Main_cla_ss__4; > public static String JavaMainTab_Main_type_not_specified_16; > public static String JavaMainTab_St_op_in_main_1; >+ public static String JavaMainTab_Relaunch_on_exit_code; >+ public static String javaMainTab_Invalid_exit_code; > public static String JavaMainTab_19; > public static String JavaMainTab_20; > public static String JavaMainTab_21; >@@ -97,6 +99,9 @@ public class LauncherMessages extends NLS { > public static String JavaLauncherTab_AttributeLabel_ProjectName; > public static String SharedJavaMainTab_AttributeLabel_MainTypeName; > public static String JavaMainTab_AttributeLabel_StopInMain; >+ public static String JavaMainTab_AttributeLabel_RelaunchOnExitCode; >+ public static String JavaMainTab_AttributeLabel_RelaunchExitCode; >+ > public static String JavaMainTab_AttributeLabel_IncludeExternalJars; > public static String JavaMainTab_AttributeLabel_InheritedMain; > >diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.properties >index 342255266..a219a9f14 100644 >--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.properties >+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.properties >@@ -79,6 +79,8 @@ JavaMainTab_E_xt__jars_6=Includ&e system libraries when searching for a main cla > JavaMainTab_Main_cla_ss__4=&Main class: > JavaMainTab_Main_type_not_specified_16=Main type not specified > JavaMainTab_St_op_in_main_1=St&op in main >+JavaMainTab_Relaunch_on_exit_code=Relaunch on exit code >+javaMainTab_Invalid_exit_code=Invalid exit code (should be between 0 ~ 255) > JavaMainTab_19=Illegal project name: {0} > JavaMainTab_20=Project {0} does not exist > JavaMainTab_21=Project {0} is closed >@@ -88,6 +90,8 @@ JavaMainTab_missing_project=Project not specified > JavaLauncherTab_AttributeLabel_ProjectName=Project name > SharedJavaMainTab_AttributeLabel_MainTypeName=Main type name > JavaMainTab_AttributeLabel_StopInMain=Stop in main >+JavaMainTab_AttributeLabel_RelaunchOnExitCode=Relaunch on exit code >+JavaMainTab_AttributeLabel_RelaunchExitCode=Relaunch exit code > JavaMainTab_AttributeLabel_IncludeExternalJars= Include external JARs > JavaMainTab_AttributeLabel_InheritedMain=Inherited main > >diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchListener.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchListener.java >new file mode 100644 >index 000000000..abb6af5a3 >--- /dev/null >+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchListener.java >@@ -0,0 +1,148 @@ >+/******************************************************************************* >+ * Copyright (c) 2000, 2018 IBM Corporation and others. >+ * >+ * This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License 2.0 >+ * which accompanies this distribution, and is available at >+ * https://www.eclipse.org/legal/epl-2.0/ >+ * >+ * SPDX-License-Identifier: EPL-2.0 >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.jdt.internal.launching; >+ >+import java.util.ArrayList; >+ >+import org.eclipse.core.runtime.CoreException; >+import org.eclipse.core.runtime.IStatus; >+import org.eclipse.core.runtime.NullProgressMonitor; >+import org.eclipse.core.runtime.Status; >+import org.eclipse.debug.core.DebugEvent; >+import org.eclipse.debug.core.DebugException; >+import org.eclipse.debug.core.DebugPlugin; >+import org.eclipse.debug.core.IDebugEventSetListener; >+import org.eclipse.debug.core.ILaunch; >+import org.eclipse.debug.core.ILaunchConfiguration; >+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; >+import org.eclipse.debug.core.ILaunchListener; >+import org.eclipse.debug.core.ILaunchManager; >+import org.eclipse.debug.core.IStatusHandler; >+import org.eclipse.debug.core.model.IProcess; >+import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; >+ >+public class LaunchListener implements ILaunchListener, IDebugEventSetListener { >+ private ArrayList<ILaunch> managedLaunches; >+ >+ private static final String RESTART = "restart"; //$NON-NLS-1$ >+ >+ public LaunchListener() { >+ managedLaunches = new ArrayList<>(); >+ } >+ >+ public void manage(ILaunch launch) { >+ if (managedLaunches.isEmpty()) { >+ hookListener(true); >+ } >+ if (!managedLaunches.contains(launch)) { >+ managedLaunches.add(launch); >+ } >+ } >+ >+ @Override >+ public void launchRemoved(ILaunch launch) { >+ update(launch, true); >+ } >+ >+ @Override >+ public void launchAdded(ILaunch launch) { >+ } >+ >+ @Override >+ public void launchChanged(ILaunch launch) { >+ } >+ >+ private void update(ILaunch launch, boolean remove) { >+ if (managedLaunches.contains(launch)) { >+ if (remove || launch.isTerminated()) { >+ managedLaunches.remove(launch); >+ if (managedLaunches.isEmpty()) { >+ hookListener(false); >+ } >+ } >+ } >+ } >+ >+ private void hookListener(boolean add) { >+ DebugPlugin debugPlugin = DebugPlugin.getDefault(); >+ ILaunchManager launchManager = debugPlugin.getLaunchManager(); >+ if (add) { >+ launchManager.addLaunchListener(this); >+ debugPlugin.addDebugEventListener(this); >+ } else { >+ launchManager.removeLaunchListener(this); >+ debugPlugin.removeDebugEventListener(this); >+ } >+ } >+ >+ private void doRestart(ILaunch launch) { >+ ILaunchConfiguration config = launch.getLaunchConfiguration(); >+ try { >+ ILaunchConfigurationWorkingCopy copy = config.getWorkingCopy(); >+ copy.setAttribute(RESTART, true); >+ copy.launch(launch.getLaunchMode(), new NullProgressMonitor()); >+ } catch (CoreException e) { >+ Status status = new Status(IStatus.ERROR, LaunchingPlugin.ID_PLUGIN, 42, null, e); >+ IStatusHandler statusHandler = DebugPlugin.getDefault().getStatusHandler(status); >+ if (statusHandler == null) { >+ LaunchingPlugin.log(e); >+ } else { >+ try { >+ statusHandler.handleStatus(status, null); >+ } catch (CoreException e1) { >+ // status handler failed to log the original exception >+ // log it ourselves >+ LaunchingPlugin.log(e); >+ } >+ } >+ } >+ } >+ >+ public void shutdown() { >+ hookListener(false); >+ } >+ >+ @Override >+ public void handleDebugEvents(DebugEvent[] events) { >+ for (DebugEvent event : events) { >+ Object source = event.getSource(); >+ if (source instanceof IProcess && event.getKind() == DebugEvent.TERMINATE) { >+ IProcess process = (IProcess) source; >+ ILaunch launch = process.getLaunch(); >+ if (launch != null) { >+ try { >+ launchTerminated(launch, process.getExitValue()); >+ } catch (DebugException e) { >+ } catch (CoreException e) { >+ LaunchingPlugin.log(e); >+ } >+ } >+ } >+ } >+ } >+ >+ private void launchTerminated(final ILaunch launch, int returnValue) throws CoreException { >+ if (managedLaunches.contains(launch)) { >+ update(launch, true); >+ ILaunchConfiguration config = launch.getLaunchConfiguration(); >+ int relaunchExitCode = config.getAttribute( >+ IJavaLaunchConfigurationConstants.ATTR_RELAUNCH_EXIT_CODE, >+ IJavaLaunchConfigurationConstants.DEFAULT_RELAUNCH_EXIT_CODE); >+ if (returnValue == relaunchExitCode) { >+ doRestart(launch); >+ } >+ } >+ } >+ >+} >diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingPlugin.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingPlugin.java >index 61dffcbca..82dc8cd36 100644 >--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingPlugin.java >+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingPlugin.java >@@ -408,6 +408,9 @@ public class LaunchingPlugin extends Plugin implements DebugOptionsListener, IEc > > } > >+ // Launches listener >+ private LaunchListener fLaunchListener; >+ > /** > * Constructor > */ >@@ -416,6 +419,13 @@ public class LaunchingPlugin extends Plugin implements DebugOptionsListener, IEc > fgLaunchingPlugin = this; > } > >+ public LaunchListener getLaunchListener() { >+ if (fLaunchListener == null) { >+ fLaunchListener = new LaunchListener(); >+ } >+ return fLaunchListener; >+ } >+ > /** > * Returns the library info that corresponds to the specified JRE install > * path, or <code>null</code> if none. >@@ -533,6 +543,10 @@ public class LaunchingPlugin extends Plugin implements DebugOptionsListener, IEc > @Override > public void stop(BundleContext context) throws Exception { > try { >+ if (fLaunchListener != null) { >+ fLaunchListener.shutdown(); >+ } >+ > AdvancedSourceLookupSupport.stop(); > > DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this); >diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IJavaLaunchConfigurationConstants.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IJavaLaunchConfigurationConstants.java >index 4b7035ef3..5b86bbe59 100644 >--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IJavaLaunchConfigurationConstants.java >+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IJavaLaunchConfigurationConstants.java >@@ -98,6 +98,22 @@ public interface IJavaLaunchConfigurationConstants { > */ > public static final String ATTR_STOP_IN_MAIN = LaunchingPlugin.getUniqueIdentifier() + ".STOP_IN_MAIN"; //$NON-NLS-1$ > >+ /** >+ * Launch configuration attribute key. The value is a boolean specifying >+ * whether to relaunch on exit code. The default value is <code>false</code>. >+ * >+ * @since 3.19 >+ */ >+ public static final String ATTR_RELAUNCH_ON_EXIT_CODE = LaunchingPlugin.getUniqueIdentifier() + ".RELAUNCH_ON_EXIT_CODE"; //$NON-NLS-1$ >+ >+ /** >+ * Launch configuration attribute key. The value is an integer exit code >+ * for relaunching. The default value is <code>194</code>. >+ * >+ * @since 3.19 >+ */ >+ public static final String ATTR_RELAUNCH_EXIT_CODE = LaunchingPlugin.getUniqueIdentifier() + ".RELAUNCH_EXIT_CODE"; //$NON-NLS-1$ >+ > /** > * Launch configuration attribute key. The value is a string specifying > * program arguments for a Java launch configuration, as they should appear >@@ -607,4 +623,11 @@ public interface IJavaLaunchConfigurationConstants { > * @see org.eclipse.jdt.internal.launching.SocketListenConnectorProcess > */ > public static final int DETAIL_CONFIG_READY_TO_ACCEPT_REMOTE_VM_CONNECTION = 1001; >+ >+ /** >+ * Exit code for relaunch. >+ * >+ * @since 3.19 >+ */ >+ public static final int DEFAULT_RELAUNCH_EXIT_CODE = 194; > } >diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java >index da19c8929..e602a834e 100644 >--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java >+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java >@@ -25,6 +25,7 @@ import org.eclipse.debug.core.ILaunchConfiguration; > import org.eclipse.jdt.core.IJavaProject; > import org.eclipse.jdt.core.IModuleDescription; > import org.eclipse.jdt.internal.launching.LaunchingMessages; >+import org.eclipse.jdt.internal.launching.LaunchingPlugin; > import org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedJavaLaunchDelegate; > import org.eclipse.osgi.util.NLS; > >@@ -161,6 +162,7 @@ public class JavaLaunchDelegate extends AbstractJavaLaunchConfigurationDelegate > if (runConfig == null) { > return; > } >+ LaunchingPlugin.getDefault().getLaunchListener().manage(launch); > // stop in main > prepareStopInMain(configuration); > >-- >2.20.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 574034
: 286531