org.eclipse.debug.ui.actions.ImportBreakpointsOperation.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.debug.ui.actions.ImportBreakpointsOperation.java

Source

/*******************************************************************************
 * Copyright (c) 2005, 2011 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.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
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.SubMonitor;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IBreakpointImportParticipant;
import org.eclipse.debug.internal.core.BreakpointManager;
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 or string buffer 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 String fCurrentWorkingSetProperty = null;

    private BreakpointManager fManager = (BreakpointManager) DebugPlugin.getDefault().getBreakpointManager();

    /** 
     * When a buffer is specified, a file is not used.
     */
    private StringBuffer fBuffer = null;

    /**
     * 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;
    }

    /**
     * Constructs an operation to import breakpoints from a string buffer. The buffer
     * must contain a memento created an {@link ExportBreakpointsOperation}.
     * 
     * @param buffer the string buffer 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.
     * @since 3.5
     */
    public ImportBreakpointsOperation(StringBuffer buffer, boolean overwrite, boolean createWorkingSets) {
        fBuffer = buffer;
        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 {
        SubMonitor localmonitor = SubMonitor.convert(monitor, ImportExportMessages.ImportOperation_0, 1);
        Reader reader = null;
        try {
            if (fBuffer == null) {
                reader = new InputStreamReader(new FileInputStream(fFileName), "UTF-8"); //$NON-NLS-1$
            } else {
                reader = new StringReader(fBuffer.toString());
            }
            XMLMemento memento = XMLMemento.createReadRoot(reader);
            IMemento[] nodes = memento.getChildren(IImportExportConstants.IE_NODE_BREAKPOINT);
            IWorkspaceRoot workspace = ResourcesPlugin.getWorkspace().getRoot();
            localmonitor.setWorkRemaining(nodes.length);
            Map attributes = null;
            IBreakpointImportParticipant[] participants = null;
            for (int i = 0; i < nodes.length; i++) {
                if (localmonitor.isCanceled()) {
                    return;
                }
                attributes = collectBreakpointProperties(nodes[i]);
                IResource resource = workspace
                        .findMember((String) attributes.get(IImportExportConstants.IE_NODE_PATH));
                // filter resource breakpoints that do not exist in this workspace
                if (resource != null) {
                    try {
                        participants = fManager.getImportParticipants(
                                (String) attributes.get(IImportExportConstants.IE_NODE_TYPE));
                    } catch (CoreException ce) {
                    }
                    IMarker marker = findExistingMarker(attributes, participants);
                    if (marker == null) {
                        marker = resource
                                .createMarker((String) attributes.get(IImportExportConstants.IE_NODE_TYPE));
                        restoreBreakpoint(marker, attributes, participants);
                    } else {
                        if (fOverwriteAll) {
                            marker.setAttributes(null);
                            restoreBreakpoint(marker, attributes, participants);
                        }
                    }
                }
                fCurrentWorkingSetProperty = null;
                localmonitor.worked(1);
            }
            if (fAdded.size() > 0) {
                fManager.addBreakpoints((IBreakpoint[]) fAdded.toArray(new IBreakpoint[fAdded.size()]));
            }
        } catch (FileNotFoundException e) {
            throw new InvocationTargetException(e,
                    MessageFormat.format("Breakpoint import file not found: {0}", new String[] { fFileName })); //$NON-NLS-1$
        } catch (UnsupportedEncodingException e) {
            throw new InvocationTargetException(e, MessageFormat
                    .format("The import file was written in non-UTF-8 encoding.", new String[] { fFileName })); //$NON-NLS-1$
        } catch (CoreException ce) {
            throw new InvocationTargetException(ce, MessageFormat
                    .format("There was a problem importing breakpoints from: {0}", new String[] { fFileName })); //$NON-NLS-1$
        } finally {
            localmonitor.done();
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    throw new InvocationTargetException(e);
                }
            }
        }
    }

    /**
     * Returns a marker backing an existing breakpoint based on the given set of breakpoint attributes
     * @param attributes the map of attributes to compare for marker equality
     * @param participants the list of participants to ask if a breakpoint matches the given map of attributes
     * @return the marker for an existing breakpoint or <code>null</code> if one could not be located
     * @since 3.5
     */
    protected IMarker findExistingMarker(Map attributes, IBreakpointImportParticipant[] participants) {
        IBreakpoint[] bps = fManager.getBreakpoints();
        for (int i = 0; i < bps.length; i++) {
            for (int j = 0; j < participants.length; j++) {
                try {
                    if (participants[j].matches(attributes, bps[i])) {
                        return bps[i].getMarker();
                    }
                } catch (CoreException ce) {
                }
            }
        }
        return null;
    }

    /**
     * Collects all of the properties for a breakpoint from the memento describing it.
     * The values in the map will be one of:
     * <ul>
     * <li>{@link String}</li>
     * <li>{@link Integer}</li>
     * <li>{@link Boolean}</li>
     * </ul>
     * @param memento the memento to read breakpoint attributes from
     * @return a new map of all of the breakpoint attributes from the given memento.
     * @since 3.5
     */
    protected Map collectBreakpointProperties(IMemento memento) {
        HashMap map = new HashMap();

        //collect attributes from the 'breakpoint' node
        map.put(IImportExportConstants.IE_BP_ENABLED, memento.getBoolean(IImportExportConstants.IE_BP_ENABLED));
        map.put(IImportExportConstants.IE_BP_PERSISTANT,
                memento.getBoolean(IImportExportConstants.IE_BP_PERSISTANT));
        map.put(IImportExportConstants.IE_BP_REGISTERED,
                memento.getBoolean(IImportExportConstants.IE_BP_REGISTERED));

        //collect attributes from the 'marker' node
        IMemento child = memento.getChild(IImportExportConstants.IE_NODE_MARKER);
        map.put(IImportExportConstants.IE_NODE_TYPE, child.getString(IImportExportConstants.IE_NODE_TYPE));
        map.put(IMarker.LINE_NUMBER, child.getInteger(IMarker.LINE_NUMBER));

        //copy all the marker attributes to the map
        IMemento[] children = child.getChildren(IImportExportConstants.IE_NODE_ATTRIB);
        for (int i = 0; i < children.length; i++) {
            readAttribute(children[i], map);
        }

        //collect attributes from the 'resource' node
        child = memento.getChild(IImportExportConstants.IE_NODE_RESOURCE);
        map.put(IImportExportConstants.IE_NODE_PATH, child.getString(IImportExportConstants.IE_NODE_PATH));
        return map;
    }

    /**
     * Collects the 'name' and 'value' key / attribute from the given memento and places it in the specified map
     * @param memento the memento to read a name / value attribute from 
     * @param map the map to add the read attribute to
     */
    private void readAttribute(IMemento memento, Map map) {
        String name = memento.getString(IImportExportConstants.IE_NODE_NAME),
                value = memento.getString(IImportExportConstants.IE_NODE_VALUE);
        if (value != null && name != null) {
            if (name.equals(IInternalDebugUIConstants.WORKING_SET_NAME)) {
                fCurrentWorkingSetProperty = value;
            }
            Object val = value;
            try {
                val = Integer.valueOf(value);
            } catch (NumberFormatException e) {
                if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("true")) { //$NON-NLS-1$ //$NON-NLS-2$
                    val = Boolean.valueOf(value);
                }
            }
            if (val != null) {
                map.put(name, val);
            }
        }
    }

    /**
     * restores all of the attributes back into the given marker, recreates the breakpoint in the
     * breakpoint manager, and optionally recreates any working set(s) the breakpoint belongs to.
     * @param marker the marker to create the new breakpoint on
     * @param attributes the attributes to set in the new breakpoint
     * @param participants the list of participants used to verify the restored breakpoint
     * @since 3.5
     */
    protected void restoreBreakpoint(IMarker marker, final Map attributes,
            IBreakpointImportParticipant[] participants) {
        String key = null;
        for (Iterator iter = attributes.keySet().iterator(); iter.hasNext();) {
            key = (String) iter.next();
            try {
                marker.setAttribute(key, attributes.get(key));
            } catch (CoreException ce) {
            }
        }
        IBreakpoint breakpoint = null;
        try {
            // create the breakpoint
            breakpoint = fManager.createBreakpoint(marker);
            breakpoint.setEnabled(((Boolean) attributes.get(IImportExportConstants.IE_BP_ENABLED)).booleanValue());
            breakpoint.setPersisted(
                    ((Boolean) attributes.get(IImportExportConstants.IE_BP_PERSISTANT)).booleanValue());
            breakpoint.setRegistered(
                    ((Boolean) attributes.get(IImportExportConstants.IE_BP_REGISTERED)).booleanValue());
            fAdded.add(breakpoint);
            if (fCreateWorkingSets && fCurrentWorkingSetProperty != null) {
                String[] names = fCurrentWorkingSetProperty.split("\\" + IImportExportConstants.DELIMITER); //$NON-NLS-1$
                updateWorkingSets(names, breakpoint);
            }
            if (participants != null) {
                for (int i = 0; i < participants.length; i++) {
                    participants[i].verify(breakpoint);
                }
            }
        } catch (CoreException ce) {
            //Something bad happened while trying to restore the breakpoint, remove it from the cached list and delete the marker
            //to ensure the manager does not hold bogus breakpoints
            if (breakpoint != null) {
                try {
                    fAdded.remove(breakpoint);
                    marker.delete();
                } catch (CoreException e) {
                }
            }
        }
    }

    /**
     * Updates the working sets the given breakpoint belongs to
     * @param wsnames the array of working set names
     * @param breakpoint the breakpoint to add to the working sets
     * @since 3.5
     */
    private void updateWorkingSets(String[] wsnames, IBreakpoint breakpoint) {
        IWorkingSetManager mgr = PlatformUI.getWorkbench().getWorkingSetManager();
        IWorkingSet set = null;
        ArrayList sets = new ArrayList();
        collectContainingWorkingsets(breakpoint, sets);
        for (int i = 0; i < wsnames.length; i++) {
            if ("".equals(wsnames[i])) { //$NON-NLS-1$
                continue;
            }
            set = mgr.getWorkingSet(wsnames[i]);
            if (set == null) {
                //create working set
                set = mgr.createWorkingSet(wsnames[i], new IAdaptable[] {});
                set.setId(IDebugUIConstants.BREAKPOINT_WORKINGSET_ID);
                mgr.addWorkingSet(set);
            }
            if (!sets.contains(set)) {
                IAdaptable[] elements = set.getElements();
                IAdaptable[] newElements = new IAdaptable[elements.length + 1];
                newElements[newElements.length - 1] = breakpoint;
                System.arraycopy(elements, 0, newElements, 0, elements.length);
                set.setElements(newElements);
            }
            sets.remove(set);
        }
        ArrayList items = null;
        for (Iterator iter = sets.iterator(); iter.hasNext();) {
            set = (IWorkingSet) iter.next();
            items = new ArrayList(Arrays.asList(set.getElements()));
            if (items.remove(breakpoint)) {
                set.setElements((IAdaptable[]) items.toArray(new IAdaptable[items.size()]));
            }
        }
    }

    /**
     * Collects all of the breakpoint working sets that contain the given {@link IBreakpoint}
     * in the given list
     * 
     * @param breakpoint the breakpoint to collect working set containers from 
     * @param collector the list to collect containing working sets in 
     * @since 3.5
     */
    private void collectContainingWorkingsets(IBreakpoint breakpoint, List collector) {
        IWorkingSetManager mgr = PlatformUI.getWorkbench().getWorkingSetManager();
        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)) {
                collector.add(sets[i]);
            }
        }
    }

    /**
     * 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 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 the breakpoints that were imported by this operation, possibly
     * an empty list. 
     * 
     * @return breakpoints imported by this operation
     * @since 3.5
     */
    public IBreakpoint[] getImportedBreakpoints() {
        return (IBreakpoint[]) fAdded.toArray(new IBreakpoint[fAdded.size()]);
    }
}