Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 90b4c8973e04ff007ef36ad89b84ab788b744a3e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/*******************************************************************************
 * Copyright (c) 2005, 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.debug.ui.actions;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.Map.Entry;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
import org.eclipse.debug.internal.ui.importexport.breakpoints.IImportExportConstants;
import org.eclipse.debug.internal.ui.importexport.breakpoints.ImportExportMessages;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.XMLMemento;

import com.ibm.icu.text.MessageFormat;

/**
 * Exports breakpoints to a file or string buffer.
 * <p>
 * This class may be instantiated.
 * <p>
 * @since 3.2
 * @noextend This class is not intended to be sub-classed by clients.
 */
public class ExportBreakpointsOperation implements IRunnableWithProgress {

	private IBreakpoint[] fBreakpoints = null;
	/**
	 * Only one of file name or writer is used depending how the operation is
	 * created.
	 */
	private String fFileName = null;
	private StringWriter fWriter = null;

	/**
	 * Constructs an operation to export breakpoints to a file.
	 *
	 * @param breakpoints the breakpoints to export
	 * @param fileName absolute path of file to export breakpoints to - the file
	 * 	will be overwritten if it already exists
	 */
	public ExportBreakpointsOperation(IBreakpoint[] breakpoints, String fileName) {
		fBreakpoints = breakpoints;
		fFileName = fileName;
	}

	/**
	 * Constructs an operation to export breakpoints to a string buffer. The buffer
	 * is available after the operation is run via {@link #getBuffer()}.
	 *
	 * @param breakpoints the breakpoints to export
	 * @since 3.5
	 */
	public ExportBreakpointsOperation(IBreakpoint[] breakpoints) {
		fBreakpoints = breakpoints;
		fWriter = new StringWriter();
	}

	@Override
	public void run(IProgressMonitor monitor) throws InvocationTargetException {
		SubMonitor localmonitor = SubMonitor.convert(monitor, ImportExportMessages.ExportOperation_0, fBreakpoints.length);
		XMLMemento memento = XMLMemento.createWriteRoot(IImportExportConstants.IE_NODE_BREAKPOINTS);
		try (Writer writer = fWriter;) {
			for (int i = 0; i < fBreakpoints.length; i++) {
				if (localmonitor.isCanceled()) {
					return;
				}
				IBreakpoint breakpoint = fBreakpoints[i];
				//in the event we are in working set view, we can have multiple selection of the same breakpoint
				//so do a simple check for it
				IMarker marker = breakpoint.getMarker();
				IMemento root = memento.createChild(IImportExportConstants.IE_NODE_BREAKPOINT);
				root.putString(IImportExportConstants.IE_BP_ENABLED, Boolean.toString(breakpoint.isEnabled()));
				root.putString(IImportExportConstants.IE_BP_REGISTERED, Boolean.toString(breakpoint.isRegistered()));
				root.putString(IImportExportConstants.IE_BP_PERSISTANT, Boolean.toString(breakpoint.isPersisted()));
				//write out the resource information
				IResource resource = marker.getResource();
				IMemento child = root.createChild(IImportExportConstants.IE_NODE_RESOURCE);
				child.putString(IImportExportConstants.IE_NODE_PATH, resource.getFullPath().toPortableString());
				child.putInteger(IImportExportConstants.IE_NODE_TYPE, resource.getType());
				//a generalized (name, value) pairing for attributes each stored as an ATTRIB element
				root = root.createChild(IImportExportConstants.IE_NODE_MARKER);
				root.putString(IImportExportConstants.IE_NODE_TYPE, marker.getType());
				Object val = marker.getAttribute(IMarker.LINE_NUMBER);
				root.putString(IMarker.LINE_NUMBER, (val != null) ? val.toString() : null);
				val = marker.getAttribute(IImportExportConstants.CHARSTART);
				root.putString(IImportExportConstants.CHARSTART, (val != null) ? val.toString() : null);
				String value = null;
				boolean wsattrib = false;
				for (Entry<String, Object> entry : marker.getAttributes().entrySet()) {
					String iterval = entry.getKey();
					value = entry.getValue().toString();
					if(!iterval.equals(IMarker.LINE_NUMBER)) {
						child = root.createChild(IImportExportConstants.IE_NODE_ATTRIB);
						if(iterval.equals(IInternalDebugUIConstants.WORKING_SET_NAME)) {
							wsattrib = true;
							value = getWorkingSetsAttribute(breakpoint);
						}
						child.putString(IImportExportConstants.IE_NODE_NAME, iterval);
						child.putString(IImportExportConstants.IE_NODE_VALUE, value);
					}
				}
				if(!wsattrib) {
					//ensure the working set infos are present if not previously updated
					child = root.createChild(IImportExportConstants.IE_NODE_ATTRIB);
					child.putString(IImportExportConstants.IE_NODE_NAME, IInternalDebugUIConstants.WORKING_SET_NAME);
					child.putString(IImportExportConstants.IE_NODE_VALUE, getWorkingSetsAttribute(breakpoint));
					child = root.createChild(IImportExportConstants.IE_NODE_ATTRIB);
					child.putString(IImportExportConstants.IE_NODE_NAME, IInternalDebugUIConstants.WORKING_SET_ID);
					child.putString(IImportExportConstants.IE_NODE_VALUE, IDebugUIConstants.BREAKPOINT_WORKINGSET_ID);
				}
				localmonitor.worked(1);
			}
			if (writer == null) {
				try (Writer outWriter = new OutputStreamWriter(new FileOutputStream(fFileName), StandardCharsets.UTF_8)) {
					memento.save(outWriter);
				}
			} else {
				memento.save(writer);
			}

		} catch (CoreException e) {
			throw new InvocationTargetException(e);
		} catch (IOException e) {
			throw new InvocationTargetException(e, MessageFormat.format("There was a problem writing file: {0}", new Object[] { fFileName })); //$NON-NLS-1$
		}
		finally {
			localmonitor.done();
		}
	}

	/**
	 * Collects all of the breakpoint working sets that contain the given {@link IBreakpoint}
	 * in the given list
	 *
	 * @param breakpoint the breakpoint to get working set information about
	 * @return the {@link IImportExportConstants#DELIMITER} delimited {@link String} for all of the work sets the given breakpoint belongs to
	 * @since 3.5
	 */
	private String getWorkingSetsAttribute(IBreakpoint breakpoint) {
		IWorkingSetManager mgr = PlatformUI.getWorkbench().getWorkingSetManager();
		StringBuffer buffer = new StringBuffer();
		IWorkingSet[] sets = mgr.getWorkingSets();
		for (int i = 0; i < sets.length; i++) {
			if(IDebugUIConstants.BREAKPOINT_WORKINGSET_ID.equals(sets[i].getId()) &&
					containsBreakpoint(sets[i], breakpoint)) {
				buffer.append(IImportExportConstants.DELIMITER).append(sets[i].getName());
			}
		}
		return buffer.toString();
	}

	/**
	 * Method to ensure markers and breakpoints are not both added to the working set
	 * @param set the set to check
	 * @param breakpoint the breakpoint to check for existence
	 * @return true if it is present false otherwise
	 * @since 3.5
	 */
	private boolean containsBreakpoint(IWorkingSet set, IBreakpoint breakpoint) {
		IAdaptable[] elements = set.getElements();
		for (int i = 0; i < elements.length; i++) {
			if (elements[i].equals(breakpoint)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Returns a string buffer containing a memento of the exported breakpoints
	 * or <code>null</code> if the operation was configured to export to a file.
	 * The memento can be used to import breakpoints into the workspace using an
	 * {@link ImportBreakpointsOperation}.
	 *
	 * @return a string buffer containing a memento of the exported breakpoints
	 * or <code>null</code> if the operation was configured to export to a file
	 * @since 3.5
	 */
	public StringBuffer getBuffer() {
		if (fWriter != null) {
			return fWriter.getBuffer();
		}
		return null;
	}


}

Back to the top