/*******************************************************************************
* Copyright (c) 2007, 2014 Nokia 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:
* Nokia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.debug.core.breakpointactions;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.model.IBreakpoint;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;
public class BreakpointActionManager {
public static final String BREAKPOINT_ACTION_ATTRIBUTE = "BREAKPOINT_ACTIONS"; //$NON-NLS-1$
private static final String BREAKPOINT_ACTION_DATA = "BreakpointActionManager.actionData"; //$NON-NLS-1$
private IExtension[] breakpointActionExtensions = null;
private ArrayList<IBreakpointAction> breakpointActions = null;
public BreakpointActionManager() {
}
public void addAction(IBreakpointAction action) {
getBreakpointActions().add(action);
}
private IBreakpointAction createActionFromClassName(String name, String className) {
IBreakpointAction action = null;
IExtension[] actionExtensions = CDebugCorePlugin.getDefault().getBreakpointActionManager().getBreakpointActionExtensions();
try {
for (int i = 0; i < actionExtensions.length && action == null; i++) {
IConfigurationElement[] elements = actionExtensions[i].getConfigurationElements();
for (int j = 0; j < elements.length && action == null; j++) {
IConfigurationElement element = elements[j];
if (element.getName().equals(CDebugCorePlugin.ACTION_TYPE_ELEMENT)) {
if (element.getAttribute("class").equals(className)) { //$NON-NLS-1$
action = (IBreakpointAction) element.createExecutableExtension("class"); //$NON-NLS-1$
action.setName(name);
CDebugCorePlugin.getDefault().getBreakpointActionManager().addAction(action);
}
}
}
}
} catch (CoreException e) {
e.printStackTrace();
}
return action;
}
public void deleteAction(IBreakpointAction action) {
getBreakpointActions().remove(action);
}
public boolean breakpointHasActions(IBreakpoint breakpoint) {
if (breakpoint != null) {
IMarker marker = breakpoint.getMarker();
String actionNames = marker.getAttribute(BREAKPOINT_ACTION_ATTRIBUTE, ""); //$NON-NLS-1$
return actionNames.length() > 0;
}
return false;
}
public void executeActions(final IBreakpoint breakpoint, final IAdaptable context) {
if (breakpoint != null) {
IMarker marker = breakpoint.getMarker();
String actionNames = marker.getAttribute(BREAKPOINT_ACTION_ATTRIBUTE, ""); //$NON-NLS-1$
if (actionNames.length() > 0 ) {
final String[] actions = actionNames.split(","); //$NON-NLS-1$
if (actions.length > 0){
Job job = new Job("Execute breakpoint actions") { //$NON-NLS-1$
@Override
public IStatus run(final IProgressMonitor monitor) {
return doExecuteActions(breakpoint, context, actions, monitor);
}
};
job.schedule();
try {
// wait for actions to execute
job.join();
}catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
private IStatus doExecuteActions(final IBreakpoint breakpoint, final IAdaptable context, String[] actions, IProgressMonitor monitor) {
try {
for (int i = 0; i < actions.length && !monitor.isCanceled(); i++) {
String actionName = actions[i];
IBreakpointAction action = findBreakpointAction(actionName);
if (action != null) {
monitor.setTaskName(action.getSummary());
IStatus status = action.execute(breakpoint, context, monitor);
if (status.getCode() != IStatus.OK) {
// do not log status if user canceled.
if (status.getCode() != IStatus.CANCEL)
CDebugCorePlugin.log(status);
return status;
}
}
monitor.worked(1);
}
} catch (Exception e) {
return new Status( IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), CDebugCorePlugin.INTERNAL_ERROR, "Internal Error", e ); //$NON-NLS-1$
}
return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
}
public IBreakpointAction findBreakpointAction(String name) {
for (IBreakpointAction action : getBreakpointActions()) {
if (action.getName().equals(name))
return action;
}
return null;
}
public IExtension[] getBreakpointActionExtensions() {
if (breakpointActionExtensions == null) {
IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(CDebugCorePlugin.PLUGIN_ID, CDebugCorePlugin.BREAKPOINT_ACTION_EXTENSION_POINT_ID);
if (point == null)
breakpointActionExtensions = new IExtension[0];
else {
breakpointActionExtensions = point.getExtensions();
}
}
return breakpointActionExtensions;
}
public ArrayList<IBreakpointAction> getBreakpointActions() {
if (breakpointActions == null) {
breakpointActions = new ArrayList<IBreakpointAction>();
CDebugCorePlugin.getDefault().getBreakpointActionManager().loadActionData();
}
return breakpointActions;
}
private void loadActionData() {
String actionData = CDebugCorePlugin.getDefault().getPluginPreferences().getString(BREAKPOINT_ACTION_DATA);
if (actionData == null || actionData.length() == 0)
return;
Element root = null;
DocumentBuilder parser;
try {
parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
parser.setErrorHandler(new DefaultHandler());
root = parser.parse(new InputSource(new StringReader(actionData))).getDocumentElement();
NodeList nodeList = root.getChildNodes();
int entryCount = nodeList.getLength();
for (int i = 0; i < entryCount; i++) {
Node node = nodeList.item(i);
short type = node.getNodeType();
if (type == Node.ELEMENT_NODE) {
Element subElement = (Element) node;
String nodeName = subElement.getNodeName();
if (nodeName.equalsIgnoreCase("actionEntry")) { //$NON-NLS-1$
String name = subElement.getAttribute("name"); //$NON-NLS-1$
if (name == null)
throw new Exception();
String value = subElement.getAttribute("value"); //$NON-NLS-1$
if (value == null)
throw new Exception();
String className = subElement.getAttribute("class"); //$NON-NLS-1$
if (className == null)
throw new Exception();
IBreakpointAction action = createActionFromClassName(name, className);
action.initializeFromMemento(value);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public String makeUniqueActionName(String defaultName) {
String result = defaultName;
IBreakpointAction action = findBreakpointAction(defaultName);
int actionCount = 1;
while (action != null) {
result = defaultName + "(" + actionCount + ")"; //$NON-NLS-1$ //$NON-NLS-2$
action = findBreakpointAction(result);
actionCount++;
}
return result;
}
public void revertActionData() {
breakpointActions = null;
}
public void saveActionData() {
String actionData = ""; //$NON-NLS-1$
DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = null;
try {
docBuilder = dfactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("breakpointActionData"); //$NON-NLS-1$
doc.appendChild(rootElement);
for (IBreakpointAction action : getBreakpointActions()) {
Element element = doc.createElement("actionEntry"); //$NON-NLS-1$
element.setAttribute("name", action.getName()); //$NON-NLS-1$
element.setAttribute("class", action.getClass().getName()); //$NON-NLS-1$
element.setAttribute("value", action.getMemento()); //$NON-NLS-1$
rootElement.appendChild(element);
}
ByteArrayOutputStream s = new ByteArrayOutputStream();
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
DOMSource source = new DOMSource(doc);
StreamResult outputTarget = new StreamResult(s);
transformer.transform(source, outputTarget);
actionData = s.toString("UTF8"); //$NON-NLS-1$
} catch (Exception e) {
e.printStackTrace();
}
CDebugCorePlugin.getDefault().getPluginPreferences().setValue(BREAKPOINT_ACTION_DATA, actionData);
CDebugCorePlugin.getDefault().savePluginPreferences();
}
}