@@ -85,6 +85,9 @@ public final class XmlDataExporter extends DBOption {
8585 @ Option (names = "undefined-prefix" , description = "In case a queue does not exist, this will define the prefix to be used on the message export. Default: 'UndefinedQueue_'" )
8686 private String undefinedPrefix = "UndefinedQueue_" ;
8787
88+ @ Option (names = "--queue" , description = "Only export the specified queue(s). Repeatable. When omitted, all queues are exported." )
89+ private List <String > queues ;
90+
8891 // an inner map of message refs hashed by the queue ID to which they belong and then hashed by their record ID
8992 private final Map <Long , Map <Long , ReferenceDescribe >> messageRefs = new HashMap <>();
9093
@@ -114,6 +117,20 @@ public XmlDataExporter setUndefinedPrefix(String undefinedPrefix) {
114117 return this ;
115118 }
116119
120+ public List <String > getQueues () {
121+ return queues ;
122+ }
123+
124+ public XmlDataExporter setQueues (List <String > queues ) {
125+ this .queues = queues ;
126+ return this ;
127+ }
128+
129+ // when no queue filter is set (null/empty) everything is exported, preserving the default behavior
130+ private boolean includeQueue (String queueName ) {
131+ return queues == null || queues .isEmpty () || queues .contains (queueName );
132+ }
133+
117134 @ Override
118135 public Object execute (ActionContext context ) throws Exception {
119136 super .execute (context );
@@ -164,6 +181,7 @@ protected void writeOutput(OutputStream out) throws Exception {
164181 private void writeXMLData () throws Exception {
165182 long start = System .currentTimeMillis ();
166183 getBindings ();
184+ warnUnknownQueues ();
167185 processMessageJournal ();
168186 printDataAsXML ();
169187 logger .debug ("\n \n Processing took: {}ms" , (System .currentTimeMillis () - start ));
@@ -328,6 +346,25 @@ private void getBindings() throws Exception {
328346 bindingsJournal .stop ();
329347 }
330348
349+ /**
350+ * Warn about any queue name passed via {@code --queue} that doesn't exist among the real bindings, so a typo doesn't
351+ * silently result in an empty export. Must run after {@link #getBindings()} but before any synthetic
352+ * {@code undefinedPrefix} bindings are created.
353+ */
354+ private void warnUnknownQueues () {
355+ if (queues == null || queues .isEmpty ()) {
356+ return ;
357+ }
358+ Set <String > existing = queueBindings .values ().stream ()
359+ .map (binding -> binding .getQueueConfiguration ().getName ().toString ())
360+ .collect (Collectors .toSet ());
361+ for (String queue : queues ) {
362+ if (!existing .contains (queue )) {
363+ getActionContext ().err .println ("Queue '" + queue + "' was not found; nothing will be exported for it." );
364+ }
365+ }
366+ }
367+
331368 private void printDataAsXML () {
332369 try {
333370
@@ -349,9 +386,20 @@ public Throwable getLastError() {
349386 }
350387
351388 private void printBindingsAsXML () throws XMLStreamException {
389+ // when a queue filter is active only export the addresses that host at least one of the requested queues
390+ Set <String > includedAddresses = (queues == null || queues .isEmpty ()) ? null :
391+ queueBindings .values ().stream ()
392+ .map (PersistentQueueBindingEncoding ::getQueueConfiguration )
393+ .filter (queueConfig -> includeQueue (queueConfig .getName ().toString ()))
394+ .map (queueConfig -> queueConfig .getAddress ().toString ())
395+ .collect (Collectors .toSet ());
396+
352397 xmlWriter .writeStartElement (XmlDataConstants .BINDINGS_PARENT );
353398 for (Map .Entry <Long , PersistentAddressBindingEncoding > addressBindingEncodingEntry : addressBindings .entrySet ()) {
354399 PersistentAddressBindingEncoding bindingEncoding = addressBindings .get (addressBindingEncodingEntry .getKey ());
400+ if (includedAddresses != null && !includedAddresses .contains (bindingEncoding .getName ().toString ())) {
401+ continue ;
402+ }
355403 xmlWriter .writeEmptyElement (XmlDataConstants .ADDRESS_BINDINGS_CHILD );
356404 String routingTypes = bindingEncoding .getRoutingTypes ().stream ().
357405 map (Enum ::toString ).collect (Collectors .joining ("," ));
@@ -362,6 +410,9 @@ private void printBindingsAsXML() throws XMLStreamException {
362410 }
363411 for (Map .Entry <Long , PersistentQueueBindingEncoding > queueBindingEncodingEntry : queueBindings .entrySet ()) {
364412 QueueConfiguration queueConfig = queueBindings .get (queueBindingEncodingEntry .getKey ()).getQueueConfiguration ();
413+ if (!includeQueue (queueConfig .getName ().toString ())) {
414+ continue ;
415+ }
365416 xmlWriter .writeEmptyElement (XmlDataConstants .QUEUE_BINDINGS_CHILD );
366417 xmlWriter .writeAttribute (XmlDataConstants .QUEUE_BINDING_ADDRESS , queueConfig .getAddress ().toString ());
367418 xmlWriter .writeAttribute (XmlDataConstants .QUEUE_BINDING_FILTER_STRING , queueConfig .getFilterString () == null ? "" : queueConfig .getFilterString ().toString ());
@@ -384,7 +435,12 @@ private void printAllMessagesAsXML() throws Exception {
384435 // Order here is important. We must process the messages from the journal before we process those from the page
385436 // files in order to get the messages in the right order.
386437 for (Map .Entry <Long , Message > messageMapEntry : messages .entrySet ()) {
387- printSingleMessageAsXML (messageMapEntry .getValue ().toCore (), extractQueueNames (messageRefs .get (messageMapEntry .getKey ())));
438+ List <String > queueNames = extractQueueNames (messageRefs .get (messageMapEntry .getKey ()));
439+ // when a queue filter is active a message with no matching queue is dropped entirely
440+ if (queueNames .isEmpty ()) {
441+ continue ;
442+ }
443+ printSingleMessageAsXML (messageMapEntry .getValue ().toCore (), queueNames );
388444 msgs ++;
389445 if (logInterval > 0 ) {
390446 if (msgs % logInterval == 0 ) {
@@ -457,7 +513,9 @@ private void printPagedMessagesAsXML() {
457513 PersistentQueueBindingEncoding queueBinding = queueBindings .get (queueID );
458514 if (queueBinding != null ) {
459515 SimpleString queueName = queueBinding .getQueueConfiguration ().getName ();
460- queueNames .add (queueName .toString ());
516+ if (includeQueue (queueName .toString ())) {
517+ queueNames .add (queueName .toString ());
518+ }
461519 }
462520 }
463521 }
@@ -482,13 +540,17 @@ private void printPagedMessagesAsXML() {
482540 }
483541
484542 private List <String > extractQueueNames (Map <Long , DescribeJournal .ReferenceDescribe > refMap ) {
485- List <String > queues = new ArrayList <>();
543+ List <String > queueList = new ArrayList <>();
486544 for (DescribeJournal .ReferenceDescribe ref : refMap .values ()) {
487545 String queueName ;
488546
489547 long id = ref .refEncoding .queueID ;
490548 PersistentQueueBindingEncoding persistentQueueBindingEncoding = queueBindings .get (id );
491549 if (persistentQueueBindingEncoding == null ) {
550+ // an unknown queue ID has no name that could match a --queue filter, so there's nothing to export for it
551+ if (queues != null && !queues .isEmpty ()) {
552+ continue ;
553+ }
492554 String name = undefinedPrefix + id ;
493555 queueBindings .put (id , new PersistentQueueBindingEncoding (QueueConfiguration .of (name ).setAddress (name )));
494556 queueName = String .valueOf (name );
@@ -497,9 +559,11 @@ private List<String> extractQueueNames(Map<Long, DescribeJournal.ReferenceDescri
497559 queueName = String .valueOf (persistentQueueBindingEncoding .getQueueConfiguration ().getName ());
498560 }
499561
500- queues .add (queueName );
562+ if (includeQueue (queueName )) {
563+ queueList .add (queueName );
564+ }
501565 }
502- return queues ;
566+ return queueList ;
503567 }
504568
505569 /**
0 commit comments