This is an automated email from the ASF dual-hosted git repository.

brusdev pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/artemis-console.git

commit 1480e8e79aadaaabf3bdfb67a167c990cda46cae
Author: Grzegorz Grzybek <[email protected]>
AuthorDate: Thu Feb 19 13:52:29 2026 +0100

    ARTEMIS-5777 - Use Hawtio version of MBean parsing and quoting
---
 .../src/artemis-service.test.ts                    |  4 +-
 .../artemis-console-plugin/src/artemis-service.ts  | 54 +---------------------
 .../src/artemis-tree-processor.ts                  | 14 +++++-
 .../packages/artemis-console-plugin/src/context.ts | 16 ++++---
 .../artemis-console-plugin/src/util/jmx.ts         | 43 ++++++++++++++---
 .../src/views/ArtemisJMXTabView.tsx                |  8 ++--
 6 files changed, 65 insertions(+), 74 deletions(-)

diff --git 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-service.test.ts
 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-service.test.ts
index d043919..fbf9d88 100644
--- 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-service.test.ts
+++ 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-service.test.ts
@@ -15,9 +15,9 @@
  * limitations under the License.
  */
 import { beforeAll, describe, expect, test } from "@jest/globals"
-import { artemisService, parseMBeanName } from "./artemis-service";
+import { artemisService } from "./artemis-service";
 import { SortDirection } from './table/ArtemisTable'
-import { userService } from '@hawtio/react'
+import { userService, parseMBeanName } from '@hawtio/react'
 
 beforeAll(async () => {
   // needed to determine Jolokia URL
diff --git 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-service.ts
 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-service.ts
index ea8c665..a268300 100644
--- 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-service.ts
+++ 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-service.ts
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 import { ActiveSort, Filter } from './table/ArtemisTable'
-import { eventService, jolokiaService, MBeanNode, workspace } from 
'@hawtio/react'
+import { eventService, jolokiaService, MBeanNode, parseMBeanName, workspace } 
from '@hawtio/react'
 import { createAddressObjectName, createQueueObjectName } from './util/jmx'
 import { log } from './globals'
 import { Message } from './messages/MessageView'
@@ -783,61 +783,11 @@ class ArtemisService {
     }
 }
 
-export function parseMBeanName(name: string): { domain: string, properties: 
Record<string, string> } {
-    const colon = name.indexOf(":")
-    if (colon === -1) {
-        throw new Error("Illegal ObjectName")
-    }
-
-    const domain = name.substring(0, colon)
-    const propsString = name.substring(colon + 1)
-
-    let i = 0
-    const len = propsString.length
-    const props: Record<string, string> = {}
-
-    while (i < len) {
-        let key = ""
-        while (i < len && propsString[i] !== "=") {
-            key += propsString[i++]
-        }
-
-        // skip '='
-        i++
-
-        let value = ""
-        if (propsString[i] === '"') {
-            // quoted value - only double quote
-            i++
-            while (i < len) {
-                const ch = propsString[i++]
-                if (ch === '"') {
-                    break
-                }
-                value += ch
-            }
-        } else {
-            // unquoted value can be empty
-            while (i < len && propsString[i] !== ",") {
-                value += propsString[i++]
-            }
-        }
-
-        props[key.trim()] = value.trim()
-
-        if (propsString[i] === ",") {
-            i++
-        }
-    }
-
-    return { domain, properties: props };
-}
-
 export async function findMBeanInfo(brokerObjectName: string): 
Promise<MBeanNode | null> {
     const tree = await workspace.getTree()
     const parsed = parseMBeanName(brokerObjectName)
 
-    const matching = tree.findMBeans(parsed.domain, parsed.properties)
+    const matching = parsed.domain && tree.findMBeans(parsed.domain, 
parsed.properties)
     if (!matching) {
         return null
     }
diff --git 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-tree-processor.ts
 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-tree-processor.ts
index 84b3865..64862b3 100644
--- 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-tree-processor.ts
+++ 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-tree-processor.ts
@@ -92,10 +92,20 @@ function findBrokers(children: MBeanNode[] | undefined): 
MBeanNode[] {
   for (const c of children) {
     if (c.id.endsWith('-folder')) {
       if (oldBrokers.has(c.name)) {
-        const newBrokerNode = oldBrokers.get(c.name)!.copyTo(`Broker 
${c.name}`)
-        newBrokerNode.children = c.children
+        const oldBrokerNode = oldBrokers.get(c.name)!
+        const newBrokerNode = new MBeanNode(null, `Broker ${c.name}`, true)
         newBrokerNode.icon = c.icon
         newBrokerNode.expandedIcon = c.expandedIcon
+        newBrokerNode.children = []
+        // newBrokerNode.metadata = oldBrokerNode.metadata
+        newBrokerNode.objectName = oldBrokerNode.objectName
+        newBrokerNode.mbean = oldBrokerNode.mbean
+        newBrokerNode.propertyList = oldBrokerNode.propertyList
+
+        const children = [...c.children!]
+        children.forEach(c => {
+          newBrokerNode.adopt(c)
+        })
         brokers.push(newBrokerNode)
       }
     }
diff --git 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/context.ts
 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/context.ts
index ae772a7..1d9c1ae 100644
--- 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/context.ts
+++ 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/context.ts
@@ -15,8 +15,7 @@
  * limitations under the License.
  */
 import { eventService, EVENT_REFRESH,MBeanNode, MBeanTree, 
PluginNodeSelectionContext, workspace } from "@hawtio/react";
-import { TreeViewDataItem } from "@patternfly/react-core";
-import { createContext, useContext, useEffect, useState } from "react";
+import { createContext, useContext, useEffect, useRef, useState } from "react";
 import { useNavigate } from 'react-router-dom'
 import { artemisPluginName } from "./globals";
 import { configManager } from "./config-manager";
@@ -32,6 +31,8 @@ export function useArtemisTree() {
     const { selectedNode, setSelectedNode } = 
useContext(PluginNodeSelectionContext)
     const navigate = useNavigate();
 
+    const refSelectedNode = useRef<MBeanNode | null>()
+    refSelectedNode.current = selectedNode
 
     const populateTree = async () => {
         const wkspTree: MBeanTree = await workspace.getTree();
@@ -43,11 +44,12 @@ export function useArtemisTree() {
                 setBrokerNode(rootNode.children[0]);
             }
             // Expand the nodes to redisplay the path
-            if (selectedNode) {
-                rootNode.forEach(selectedNode?.path(), (node: MBeanNode) => {
-                    const tvd = node as TreeViewDataItem
-                    tvd.defaultExpanded = true
-                })
+            if (refSelectedNode.current) {
+                let curr: MBeanNode | null = refSelectedNode.current
+                while (curr) {
+                    curr.defaultExpanded = true
+                    curr = curr.parent
+                }
             }
             const subTree: MBeanTree = 
MBeanTree.createFromNodes(artemisPluginName, [rootNode])
             setTree(subTree)
diff --git 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/util/jmx.ts
 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/util/jmx.ts
index 2c215ea..a310c07 100644
--- 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/util/jmx.ts
+++ 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/util/jmx.ts
@@ -28,16 +28,45 @@ const ADDRESS_COMPONENT = "component=addresses";
  * 
"127.0.0.1",component=addresses,address="q1",subcomponent=queues,routing-type="anycast",queue="q1"
  */
 export function createQueueObjectName(brokerMBean: string, address: string, 
routingType: string, queue: string): string {
-    var queueMBeanName = queue;
-    if(queueMBeanName.includes('\\')){
-        //it may have a client id with /. in the name which is delimeted in 
the mbean name
-        queueMBeanName = queueMBeanName.replaceAll('\\', '\\\\');
-    }
-    return brokerMBean + ADDRESS_COMPONENT_PART + address + 
ADDRESS_SUBCOMPONENT_PART + routingType.toLowerCase() + ADDRESS_TYPE_PART + 
queueMBeanName + STRING_DELIMETER;
+    let addressMBeanName = mbeanEscape(address);
+    let queueMBeanName = mbeanEscape(queue);
+    return brokerMBean + ADDRESS_COMPONENT_PART + addressMBeanName + 
ADDRESS_SUBCOMPONENT_PART + routingType.toLowerCase() + ADDRESS_TYPE_PART + 
queueMBeanName + STRING_DELIMETER;
 }
 
 export function createAddressObjectName(brokerMBean: string, address: string) {
-    return brokerMBean + ADDRESS_COMPONENT_PART + address + STRING_DELIMETER;
+    return brokerMBean + ADDRESS_COMPONENT_PART + mbeanEscape(address) + 
STRING_DELIMETER;
+}
+
+/**
+ * This function is an equivalent of `javax.management.ObjectName.quote()`
+ * @param value
+ */
+function mbeanEscape(value: string): string {
+    let res = value
+    // it may have a client id with \. in the name which is delimited in the 
mbean name
+    // according to javax.management.ObjectName.quote() javadoc, we have to 
replace:
+    res = res.replaceAll('\\', '\\\\');
+    res = res.replaceAll('*', '\\*');
+    res = res.replaceAll('"', '\\"');
+    res = res.replaceAll('?', '\\?');
+    return res
+}
+
+/**
+ * This function should behave like `javax.management.ObjectName.unquote()` 
for quoted values
+ * and should not change the value when it's not quoted
+ * @param value
+ */
+export function mbeanUnescape(value: string): string {
+    if (!value || !value.startsWith('"') || !value.endsWith('"')) {
+        return value
+    }
+    let res = value.substring(1, value.length - 1);
+    res = res.replaceAll('\\"', '"');
+    res = res.replaceAll('\\*', '*');
+    res = res.replaceAll('\\?', '?');
+    res = res.replaceAll('\\\\', '\\');
+    return res
 }
 
 export function isQueue(node: MBeanNode): boolean {
diff --git 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/views/ArtemisJMXTabView.tsx
 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/views/ArtemisJMXTabView.tsx
index 356f672..ad90951 100644
--- 
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/views/ArtemisJMXTabView.tsx
+++ 
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/views/ArtemisJMXTabView.tsx
@@ -19,7 +19,7 @@ import { Tabs, Tab, TabTitleText, Button, Modal, 
ModalVariant, PageSection } fro
 import { Attributes, Chart, MBeanNode, Operations } from '@hawtio/react';
 import { CreateQueue } from '../queues/CreateQueue';
 import { DeleteAddress } from '../addresses/DeleteAddress';
-import { isAddress as isAnAddress, isQueue } from '../util/jmx'
+import { isAddress as isAnAddress, isQueue, mbeanUnescape } from '../util/jmx'
 import { MessagesTable } from '../messages/MessagesTable';
 import { SendMessage } from '../messages/SendMessage';
 import { Message, MessageView } from '../messages/MessageView';
@@ -58,11 +58,11 @@ export const ArtemisJMXTabs: React.FunctionComponent = () 
=> {
   const isAQueue = isQueue(selectedNode);
 
   let prop = selectedNode.getProperty("routing-type");
-  const routingType: string  = prop === undefined?'':prop;
+  const routingType: string  = mbeanUnescape(prop === undefined?'':prop);
   prop = selectedNode.getProperty("address");
-  const address: string | undefined = prop === undefined?'':prop;
+  const address: string | undefined = mbeanUnescape(prop === 
undefined?'':prop);
   prop = selectedNode.getProperty("queue");
-  const queue: string | undefined = prop === undefined?'':prop;
+  const queue: string | undefined = mbeanUnescape(prop === undefined?'':prop);
 
   const handleTabClick = ( event: React.MouseEvent<any> | React.KeyboardEvent 
| MouseEvent, tabIndex: string | number
   ) => {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to