Skip to content

Commit

Permalink
Debug with variables (#994)
Browse files Browse the repository at this point in the history
#989: Camel debug - Add support for exchange variables.
  • Loading branch information
davsclaus committed Mar 3, 2024
1 parent f8561d4 commit cbc3d8a
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 15 deletions.
Expand Up @@ -20,6 +20,7 @@
import com.github.cameltooling.idea.runner.debugger.breakpoint.CamelBreakpoint;
import com.github.cameltooling.idea.runner.debugger.stack.CamelMessageInfo;
import com.github.cameltooling.idea.runner.debugger.util.ClasspathUtils;
import com.github.cameltooling.idea.runner.debugger.util.DebuggerUtils;
import com.github.cameltooling.idea.service.CamelRuntime;
import com.github.cameltooling.idea.util.IdeaUtils;
import com.github.cameltooling.idea.util.StringUtils;
Expand Down Expand Up @@ -92,6 +93,7 @@
import static com.github.cameltooling.idea.runner.debugger.CamelDebuggerContext.CAMEL;
import static com.github.cameltooling.idea.runner.debugger.CamelDebuggerTarget.BODY;
import static com.github.cameltooling.idea.runner.debugger.CamelDebuggerTarget.EXCHANGE_PROPERTY;
import static com.github.cameltooling.idea.runner.debugger.CamelDebuggerTarget.EXCHANGE_VARIABLE;
import static com.github.cameltooling.idea.runner.debugger.CamelDebuggerTarget.MESSAGE_HEADER;

public class CamelDebuggerSession implements AbstractDebuggerSession {
Expand Down Expand Up @@ -288,6 +290,10 @@ public void setValue(CamelDebuggerTarget target,
serverConnection.invoke(this.debuggerMBeanObjectName, "setExchangePropertyOnBreakpoint",
new Object[]{breakpointId, targetName, value},
new String[]{"java.lang.String", "java.lang.String", "java.lang.Object"});
} else if (target == EXCHANGE_VARIABLE) {
serverConnection.invoke(this.debuggerMBeanObjectName, "setExchangeVariableOnBreakpoint",
new Object[]{breakpointId, targetName, value},
new String[]{"java.lang.String", "java.lang.String", "java.lang.Object"});
} else if (target == BODY) {
serverConnection.invoke(this.debuggerMBeanObjectName, "setMessageBodyOnBreakpoint",
new Object[]{breakpointId, value},
Expand Down Expand Up @@ -543,8 +549,7 @@ private boolean doConnect() {

//Init DOM Documents
String routes = camelContext.dumpRoutesAsXml(false);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
DocumentBuilder documentBuilder = DebuggerUtils.createDocumentBuilder();
InputStream targetStream = new ByteArrayInputStream(routes.getBytes());
this.routesDOMDocument = documentBuilder.parse(targetStream);

Expand Down Expand Up @@ -796,7 +801,7 @@ private String dumpTracedMessagesAsXml(String id) {
xml = (String) serverConnection.invoke(this.debuggerMBeanObjectName, "dumpTracedMessagesAsXml", new Object[]{id},
new String[]{"java.lang.String"});
} catch (Exception ex) {
LOG.error("Could not invoke dumpTracedMessagesAsXml(" + id + ")", e);
LOG.warn("Could not invoke dumpTracedMessagesAsXml(" + id + ")", e);
return "";
}
}
Expand All @@ -817,7 +822,7 @@ private List<CamelMessageInfo> getStack(String breakpointId, String messageInfoA
new String[]{"java.lang.String"});

InputStream targetStream = new ByteArrayInputStream(messageHistory.getBytes());
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(targetStream);
Document document = DebuggerUtils.createDocumentBuilder().parse(targetStream);
NodeList historyEntries = document.getElementsByTagName("messageHistoryEntry");

for (int i = 0; i < historyEntries.getLength(); i++) {
Expand Down
Expand Up @@ -28,6 +28,10 @@ public enum CamelDebuggerTarget {
* The target used to modify one specific exchange property.
*/
EXCHANGE_PROPERTY("Exchange Property"),
/**
* The target used to modify one specific exchange variable.
*/
EXCHANGE_VARIABLE("Exchange Variable"),
/**
* The target used to modify the body.
*/
Expand Down
Expand Up @@ -16,6 +16,7 @@
*/
package com.github.cameltooling.idea.runner.debugger.stack;

import com.github.cameltooling.idea.runner.debugger.util.DebuggerUtils;
import com.github.cameltooling.idea.util.StringUtils;
import com.intellij.psi.PsiElement;
import com.intellij.util.ArrayUtil;
Expand All @@ -26,18 +27,22 @@
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class CamelMessageInfo {

private Map<String, Value[]> headers;
private Map<String, Value[]> properties;
private Map<String, Value[]> variables;

private Value body;
private String exchangeId;
Expand All @@ -62,7 +67,7 @@ public CamelMessageInfo(@NotNull String messageInfoAsXML,
String processor,
List<CamelMessageInfo> stack) throws Exception {
this.messageInfoAsXML = messageInfoAsXML;
this.documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
this.documentBuilder = DebuggerUtils.createDocumentBuilder();
this.position = position;
this.tag = tag;
this.routeId = routeId;
Expand All @@ -76,7 +81,7 @@ private void init() throws Exception {
InputStream targetStream = new ByteArrayInputStream(messageInfoAsXML.getBytes());
Document document = documentBuilder.parse(targetStream);

headers = new HashMap<>();
headers = new LinkedHashMap<>();

//parse headers
NodeList headersNodeList = document.getElementsByTagName("header");
Expand Down Expand Up @@ -111,11 +116,11 @@ private void init() throws Exception {

NodeList propertiesNodeList = document.getElementsByTagName("exchangeProperty");
if (propertiesNodeList.getLength() > 0) {
properties = new HashMap<>();
properties = new LinkedHashMap<>();
}
for (int i = 0; i < propertiesNodeList.getLength(); i++) {
Element nextProp = (Element) propertiesNodeList.item(i);
String key = nextProp.getAttribute("name");
String key = nextProp.getAttribute("key");
String type = nextProp.getAttribute("type");
String value = nextProp.getTextContent();

Expand All @@ -128,6 +133,25 @@ private void init() throws Exception {
Value newValue = new Value(type, value);
properties.put(key, new Value[]{newValue});
}
NodeList variablesNodeList = document.getElementsByTagName("exchangeVariable");
if (variablesNodeList.getLength() > 0) {
variables = new HashMap<>();
}
for (int i = 0; i < variablesNodeList.getLength(); i++) {
Element nextProp = (Element) variablesNodeList.item(i);
String key = nextProp.getAttribute("key");
String type = nextProp.getAttribute("type");
String value = nextProp.getTextContent();

if (StringUtils.isEmpty(type)) {
type = "java.lang.String";
}
if (StringUtils.isEmpty(value)) {
value = "";
}
Value newValue = new Value(type, value);
variables.put(key, new Value[]{newValue});
}
}

public Map<String, Value[]> getHeaders() {
Expand All @@ -139,6 +163,11 @@ public Map<String, Value[]> getProperties() {
return properties;
}

@Nullable
public Map<String, Value[]> getVariables() {
return variables;
}

public Value getBody() {
return body;
}
Expand Down
Expand Up @@ -16,7 +16,6 @@
*/
package com.github.cameltooling.idea.runner.debugger.stack;


import com.github.cameltooling.idea.runner.debugger.CamelDebuggerSession;
import com.github.cameltooling.idea.runner.debugger.CamelDebuggerTarget;
import com.github.cameltooling.idea.runner.debugger.evaluator.CamelExpressionEvaluator;
Expand All @@ -37,7 +36,6 @@ public class CamelStackFrame extends XStackFrame {
private final CamelDebuggerSession session;
private final CamelMessageInfo camelMessageInfo;


public CamelStackFrame(@NotNull CamelDebuggerSession session, CamelMessageInfo camelMessageInfo) {
this.session = session;
this.camelMessageInfo = camelMessageInfo;
Expand Down Expand Up @@ -75,19 +73,20 @@ public Object getEqualityObject() {
return CamelStackFrame.class;
}


@Override
public void computeChildren(@NotNull XCompositeNode node) {
final XValueChildrenList children = new XValueChildrenList();
children.add("ExchangeId", new ObjectFieldDefinitionValue(this.session, this.camelMessageInfo.exchangeIdAsValue(), AllIcons.Debugger.Value));
children.add("Body", new ObjectFieldDefinitionValue(CamelDebuggerTarget.BODY, null, this.session, this.camelMessageInfo.getBody(), AllIcons.Debugger.Value));
children.add("Headers", new MapOfObjectFieldDefinitionValue(CamelDebuggerTarget.MESSAGE_HEADER, this.session, this.camelMessageInfo.getHeaders(), AllIcons.Debugger.Value));
final var properties = this.camelMessageInfo.getProperties();
if (properties == null) {
children.add("WARNING: ", JavaStackFrame.createMessageNode("Exchange Properties in Debugger are only available in Camel version 3.15 or later", AllIcons.Nodes.WarningMark));
} else {
if (properties != null) {
children.add("Exchange Properties", new MapOfObjectFieldDefinitionValue(CamelDebuggerTarget.EXCHANGE_PROPERTY, this.session, properties, AllIcons.Debugger.Value));
}
final var variables = this.camelMessageInfo.getVariables();
if (variables != null) {
children.add("Exchange Variables", new MapOfObjectFieldDefinitionValue(CamelDebuggerTarget.EXCHANGE_VARIABLE, this.session, variables, AllIcons.Debugger.Value));
}
node.addChildren(children, true);
}
}
Expand Down
@@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.cameltooling.idea.runner.debugger.util;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

public final class DebuggerUtils {

private DebuggerUtils() {
}

public static DocumentBuilder createDocumentBuilder() throws ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(false);
factory.setIgnoringElementContentWhitespace(true);
factory.setIgnoringComments(true);
try {
// Set secure processing
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
} catch (ParserConfigurationException e) {
}
try {
// Disable the external-general-entities by default
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
} catch (ParserConfigurationException e) {
}
try {
// Disable the external-parameter-entities by default
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
} catch (ParserConfigurationException e) {
}
return factory.newDocumentBuilder();
}

}
2 changes: 1 addition & 1 deletion camel-idea-plugin/src/main/resources/META-INF/plugin.xml
Expand Up @@ -11,7 +11,7 @@
<change-notes><![CDATA[
v.1.2.5
<ul>
<li>Bug fixes</li>
<li>Debugger now supports Exchange variables (Camel 4.4)</li>
</ul>
]]>
</change-notes>
Expand Down

0 comments on commit cbc3d8a

Please sign in to comment.