| /******************************************************************************* |
| * Copyright (c) 2005, 2007 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.debug.ui.actions; |
| |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.InputStreamReader; |
| import java.io.UnsupportedEncodingException; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.ArrayList; |
| |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspaceRoot; |
| import org.eclipse.core.resources.IWorkspaceRunnable; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.model.IBreakpoint; |
| import org.eclipse.debug.internal.core.BreakpointManager; |
| import org.eclipse.debug.internal.core.IInternalDebugCoreConstants; |
| 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; |
| |
| /** |
| * Imports breakpoints from a file into the workspace. |
| * <p> |
| * This class may be instantiated. |
| * <p> |
| * @since 3.2 |
| * @noextend This class is not intended to be subclassed by clients. |
| */ |
| public class ImportBreakpointsOperation implements IRunnableWithProgress { |
| |
| private boolean fOverwriteAll = false; |
| |
| private String fFileName = null; |
| |
| private boolean fCreateWorkingSets = false; |
| |
| private ArrayList fAdded = new ArrayList(); |
| |
| private BreakpointManager fManager = (BreakpointManager) DebugPlugin.getDefault().getBreakpointManager(); |
| |
| /** |
| * Constructs an operation to import breakpoints. |
| * |
| * @param fileName the file to read breakpoints from - the file should have been |
| * created from an export operation |
| * @param overwrite whether imported breakpoints will overwrite existing equivalent breakpoints |
| * @param createWorkingSets whether breakpoint working sets should be created. Breakpoints |
| * are exported with information about the breakpoint working sets they belong to. Those |
| * working sets can be optionally re-created on import if they do not already exist in the |
| * workspace. |
| */ |
| public ImportBreakpointsOperation(String fileName, boolean overwrite, boolean createWorkingSets) { |
| fFileName = fileName; |
| fOverwriteAll = overwrite; |
| fCreateWorkingSets = createWorkingSets; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| public void run(final IProgressMonitor monitor) throws InvocationTargetException { |
| IWorkspaceRunnable wr = new IWorkspaceRunnable() { |
| public void run(IProgressMonitor wmonitor) throws CoreException { |
| try { |
| XMLMemento memento = XMLMemento.createReadRoot(new InputStreamReader(new FileInputStream(fFileName), "UTF-8")); //$NON-NLS-1$ |
| IMemento[] nodes = memento.getChildren(IImportExportConstants.IE_NODE_BREAKPOINT); |
| IWorkspaceRoot workspace = ResourcesPlugin.getWorkspace().getRoot(); |
| IMemento node = null; |
| monitor.beginTask(ImportExportMessages.ImportOperation_0, nodes.length); |
| for(int i = 0; i < nodes.length; i++) { |
| if(!monitor.isCanceled()) { |
| node = nodes[i].getChild(IImportExportConstants.IE_NODE_RESOURCE); |
| IResource resource = workspace.findMember(node.getString(IImportExportConstants.IE_NODE_PATH)); |
| // filter resource breakpoints that do not exist in this workspace |
| if(resource != null) { |
| // create a marker, we must do each one, as a straight copy set values as Objects, destroying |
| // the actual value types that they are. |
| node = nodes[i].getChild(IImportExportConstants.IE_NODE_MARKER); |
| IMarker marker = findGeneralMarker(resource, node.getInteger(IMarker.LINE_NUMBER), |
| node.getString(IImportExportConstants.IE_NODE_TYPE), |
| node.getInteger(IImportExportConstants.CHARSTART)); |
| if(marker == null) { |
| marker = resource.createMarker(node.getString(IImportExportConstants.IE_NODE_TYPE)); |
| restoreBreakpoint(marker, nodes[i]); |
| } |
| else { |
| if(fOverwriteAll) { |
| marker.setAttributes(null); |
| restoreBreakpoint(marker, nodes[i]); |
| } |
| } |
| } |
| monitor.worked(i+1); |
| } else { |
| return; |
| } |
| } |
| fManager.addBreakpoints((IBreakpoint[])fAdded.toArray(new IBreakpoint[fAdded.size()])); |
| } |
| catch(FileNotFoundException e) { |
| throw new CoreException(new Status(IStatus.ERROR, IDebugUIConstants.PLUGIN_ID, IDebugUIConstants.INTERNAL_ERROR, |
| MessageFormat.format("Breakpoint import file not found: {0}", new String[]{fFileName}), e)); //$NON-NLS-1$ |
| } |
| catch (UnsupportedEncodingException e) { |
| throw new CoreException(new Status(IStatus.ERROR, IDebugUIConstants.PLUGIN_ID, IDebugUIConstants.INTERNAL_ERROR, |
| MessageFormat.format("The import file was written in non-UTF-8 encoding.", new String[]{fFileName}), e)); //$NON-NLS-1$ |
| } |
| } |
| }; |
| try { |
| ResourcesPlugin.getWorkspace().run(wr, monitor); |
| } catch(CoreException e) { |
| throw new InvocationTargetException(e); |
| } |
| } |
| |
| /** |
| * Restores a breakpoint on the given marker with information from the passed memento |
| * @param marker the marker to restore to |
| * @param node the memento to get the restore information from |
| */ |
| private void restoreBreakpoint(IMarker marker, IMemento node) throws CoreException { |
| IMemento[] childnodes = null; |
| IMemento child = null; |
| // get the marker attributes |
| child = node.getChild(IImportExportConstants.IE_NODE_MARKER); |
| marker.setAttribute(IMarker.LINE_NUMBER, child.getInteger(IMarker.LINE_NUMBER)); |
| marker.setAttribute(IImportExportConstants.IE_NODE_TYPE, child.getString(IImportExportConstants.IE_NODE_TYPE)); |
| marker.setAttribute(IImportExportConstants.CHARSTART, child.getString(IImportExportConstants.CHARSTART)); |
| childnodes = child.getChildren(IImportExportConstants.IE_NODE_ATTRIB); |
| String workingsets = IInternalDebugCoreConstants.EMPTY_STRING; |
| for (int j = 0; j < childnodes.length; j++) { |
| // get the attribute and try to convert it to either Integer, Boolean or leave it alone (String) |
| String name = childnodes[j].getString(IImportExportConstants.IE_NODE_NAME), |
| value = childnodes[j].getString(IImportExportConstants.IE_NODE_VALUE); |
| if (value != null && name != null) { |
| if (name.equals(IInternalDebugUIConstants.WORKING_SET_NAME)) { |
| workingsets = value; |
| } |
| try { |
| marker.setAttribute(name, Integer.valueOf(value)); |
| } catch (NumberFormatException e) { |
| if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("true")) { //$NON-NLS-1$ //$NON-NLS-2$ |
| marker.setAttribute(name, Boolean.valueOf(value)); |
| } |
| else { |
| marker.setAttribute(name, value); |
| } |
| } |
| } |
| } |
| // create the breakpoint |
| IBreakpoint breakpoint = fManager.createBreakpoint(marker); |
| breakpoint.setEnabled(Boolean.valueOf(node.getString(IImportExportConstants.IE_BP_ENABLED)).booleanValue()); |
| breakpoint.setPersisted(Boolean.valueOf(node.getString(IImportExportConstants.IE_BP_PERSISTANT)).booleanValue()); |
| breakpoint.setRegistered(Boolean.valueOf(node.getString(IImportExportConstants.IE_BP_REGISTERED)).booleanValue()); |
| // bug fix 110080 |
| fAdded.add(breakpoint); |
| if (fCreateWorkingSets) { |
| String[] names = workingsets.split("\\" + IImportExportConstants.DELIMITER); //$NON-NLS-1$ |
| for (int m = 1; m < names.length; m++) { |
| createWorkingSet(names[m], breakpoint); |
| } |
| } |
| } |
| |
| /** |
| * Creates a working set and sets the values |
| * @param breakpoint the restored breakpoint to add to the new working set |
| */ |
| private void createWorkingSet(String setname, IAdaptable element) { |
| IWorkingSetManager wsmanager = PlatformUI.getWorkbench().getWorkingSetManager(); |
| IWorkingSet set = wsmanager.getWorkingSet(setname); |
| if (set == null) { |
| set = wsmanager.createWorkingSet(setname, new IAdaptable[] {}); |
| set.setId(IDebugUIConstants.BREAKPOINT_WORKINGSET_ID); |
| wsmanager.addWorkingSet(set); |
| } |
| if (!setContainsBreakpoint(set, (IBreakpoint) element)) { |
| IAdaptable[] elements = set.getElements(); |
| IAdaptable[] newElements = new IAdaptable[elements.length + 1]; |
| newElements[newElements.length - 1] = element; |
| System.arraycopy(elements, 0, newElements, 0, elements.length); |
| set.setElements(newElements); |
| } |
| } |
| |
| /** |
| * 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 |
| */ |
| private boolean setContainsBreakpoint(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; |
| } |
| |
| /** |
| * This method is used internally to find a non-specific marker on a given resource. |
| * With this method we can search for similar markers even though they may have differing IDs |
| * |
| * @param resource the resource to search for the marker |
| * @param line the line number or <code>null</code> |
| * @param type the type of the marker |
| * @param charstart the charstart attribute of the marker or <code>null</code> |
| * @return the marker if found, or <code>null</code> |
| */ |
| private IMarker findGeneralMarker(IResource resource, Integer line, String type, Integer charstart) throws CoreException { |
| IMarker[] markers = resource.findMarkers(null, false, IResource.DEPTH_ZERO); |
| if (type != null) { |
| for (int i = 0; i < markers.length; i++) { |
| Object localline = markers[i].getAttribute(IMarker.LINE_NUMBER); |
| String localtype = markers[i].getType(); |
| if (type.equals(localtype) && objectsEqual(charstart, markers[i].getAttribute(IImportExportConstants.CHARSTART))) { |
| if(objectsEqual(line, localline) ) { |
| return markers[i]; |
| } |
| else if(noLineNumber(line)) { |
| return markers[i]; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns if the specified 'line number' is not valid |
| * @param line |
| * @return true if the specified value is not a valid line number |
| */ |
| private boolean noLineNumber(Integer line) { |
| if(line == null) { |
| return true; |
| } |
| return line.intValue() < 0; |
| } |
| |
| /** |
| * Returns if the two objects are equal. |
| * @param o1 |
| * @param o2 |
| * @return |
| */ |
| private boolean objectsEqual(Object o1, Object o2) { |
| if(o1 == null && o2 == null) { |
| return true; |
| } |
| return o1 != null && o1.equals(o2); |
| } |
| } |