main.java.com.scalagent.jmstool.Tool Maven / Gradle / Ivy
The newest version!
/**
* (C) 2020 - 2024 ScalAgent Distributed Technologies
* All rights reserved
*/
package com.scalagent.jmstool;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.StreamMessage;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import org.objectweb.joram.client.jms.admin.AdminException;
import org.objectweb.joram.client.jms.admin.AdminWrapper;
import org.objectweb.joram.client.jms.admin.User;
import fr.dyade.aaa.common.BinaryDump;
import org.objectweb.joram.client.jms.Queue;
import org.objectweb.joram.client.jms.Session;
/**
* This client test a Joram JMS connector.
*
* Options, set by Java environment variable ("-Dproperty=value" in command line)
* - JNDI_FILE: Path of JNDI properties file. If not defined, Joram's default are
* used. "fr.dyade.aaa.jndi2.client.NamingContextFactory" for JNDI Factory,
* "localhost", and 16400 for host and port.
* These values can be overloaded by specific properties below.
* - JNDI_FACTORY: Classname of the JNDI factory (cf java.naming.factory.initial
* property).
* - JNDI_URL: URL of JNDI server (cf java.naming.provider.url property).
* - CF: JNDI name of the ConnectionFactory to use, by default "cf".
* - QUEUE: JNDI name of JMS queue to handle, by default "queue".
* - ADMIN: User name for authentication, by default "root.
* - PASS: Password for authentication, by default "root".
* - FORWARD: JNDI Name of queue to forward messages, no default.
* - MSGID: Unique identifier of message to handle, no default.
* - ALL: If defined true, all messages are automatically handled. With the
* browse command all messages are displayed, with the forward command
* all messages are forwarded to the new destination. If false each message
* is handled in an interactive way.
* - DUMP: If defined true, try to dump (hex+ascii) the content of Stream and
* Object messages.
* - BODY_AS_TEXT: Try to print message body as a String using a proposed
* charset (by default UTF-8). This option is only available with BytesMessage.
* - CHARSET: ALlows to fix the charset used to save TextMessage, and to
* display BytesMessage in text. By default UTF-8.
* - SILENT: If defined true, the output is minimum.
*
* Commands: help, browse, purge, forward, remove, pause_on/pause_off, create,
* delete and statistics.
* - help: prints the usage message.
* - browse: prints successively each message of the queue, allowing to delete
* or forward it. If ALL option is defined, all messages are automatically
* handled.
* - purge: removes all messages in the queue.
* - forward: forwards the message identified by MSGID option.
* - remove: removes the message identified by MSGID option.
* - pause_on/pause_off: pause (resp. restart) the queue.
* - create: creates the queue and registers it in JNDI. The rights set allow
* any user to send or receive messages on this queue.
* - delete: deletes the queue in the JMS server.
* - statistics: prints all statistics about the queue.
* - lookup: gets the registered object in JNDI (name asked on terminal).
* - unbind: removes the binding in JNDI (name asked on terminal).
* - password: updates a user password (parameters asked in command line).
*
* The client returns 0 if the command is ok, -1 otherwise.
*/
public final class Tool {
public final static String HELP_CMD = "help";
public final static String BROWSE_CMD = "browse";
public final static String PURGE_CMD = "purge";
public final static String FORWARD_CMD = "forward";
public final static String REMOVE_CMD = "remove";
public final static String CREATE_CMD = "create";
public final static String DELETE_CMD = "delete";
public final static String PAUSE_ON_CMD = "pause_on";
public final static String PAUSE_OFF_CMD = "pause_off";
public final static String STAT_CMD = "statistics";
public final static String LOOKUP_CMD = "lookup";
public final static String UNBIND_CMD = "unbind";
public final static String PASSWORD_CMD = "password";
public final static String ALL = "ALL";
public static final String QUEUE = "QUEUE";
public static final String QUEUE_DFLT = "queue";
public static final String FORWARD_QUEUE = "FORWARD";
public static final String MSGID = "MSGID";
public static final String INPUT = "INPUT";
public static final String GUI = "GUI";
public static final String SILENT = "SILENT";
public static final boolean silent = Boolean.getBoolean(SILENT);
public static final String DEBUG = "DEBUG";
public static final boolean debug = Boolean.getBoolean(DEBUG);
public static final String DUMP = "DUMP";
public static final boolean dump = Boolean.getBoolean(DUMP);
/**
* Try to print message body as a String using a proposed charset (by default UTF-8).
* This option is only available with BytesMessage.
*/
public static final String BODY_AS_TEXT = "BODY_AS_TEXT";
public static final boolean bodyAsText = Boolean.getBoolean(BODY_AS_TEXT);
/**
* Property allowing to fix charset used to save TextMessage, and to display
* BytesMessage in text. By default UTF-8.
*/
public static final String CHARSET = "CHARSET";
public static final String DEFAULT_CHARSET = "UTF-8";
public static final String charset = System.getProperty(CHARSET, DEFAULT_CHARSET);
public static void usage() {
System.out.println("usage:\njava -D" + JNDI_FILE + "=./jndi.properties -DSILENT=true -D" + ALL +"=true\n" +
" -D" + CF + "=cf -D" + QUEUE + "=queue -D" + FORWARD_QUEUE + "=forward -jar jmstool.jar\n" +
" [parameters]\n");
System.err.println("Options and parameters, set by Java environment variable (\"-Dproperty=value\" in\n" +
" command line):");
System.err.println(" - " + JNDI_FILE + ": Path of JNDI properties file. If not defined, Joram's default\n" +
" are used. \"fr.dyade.aaa.jndi2.client.NamingContextFactory\" for JNDI\n" +
" Factory, \"localhost\", and 16400 for host and port.\n" +
" These values can be overloaded by specific properties below.");
System.err.println(" - " + JNDI_FACTORY + ": Classname of the JNDI factory (cf " + InitialContext.INITIAL_CONTEXT_FACTORY + "\n" +
" property). By default \"" + JNDI_FACTORY_DFLT + "\".");
System.err.println(" - " + JNDI_PROVIDER_URL + ": URL of JNDI server (cf " + InitialContext.PROVIDER_URL + "). By default\n" +
" \"" + JNDI_PROVIDER_URL_DFLT + "\".");
System.err.println(" - " + CF + ": JNDI name of the ConnectionFactory to use, by default \"" + CF_DFLT + "\".");
System.err.println(" - " + QUEUE + ": JNDI name of JMS queue to handle, by default \"" + QUEUE_DFLT + "\".");
System.err.println(" - " + ADMIN + ": User name for authentication, by default \"" + ADMIN_DFLT + ".");
System.err.println(" - " + PASS + ": Password for authentication, by default \"" + PASS_DFLT + "\".");
System.err.println(" - " + FORWARD_QUEUE + ": JNDI Name of queue to forward messages, no default.");
System.err.println(" - " + MSGID + ": Unique identifier of message to handle, no default.");
System.err.println(" - " + INPUT + ": Pathname of file containing additionnal parameters (see\n" +
" Parameters section below). Each line specfies a parameter.\n" +
" The additional command line parameters, and \"" + GUI + "\" option\n" +
" will then be ignored.");
System.err.println(" - " + GUI + ": If set to true use a GUI dialog to get password, by default false.");
System.err.println(" - " + ALL + ": If defined true, all messages are automatically handled. With the\n" +
" browse command all messages are displayed, with the forward command\n" +
" all messages are forwarded to the new destination. If false each message\n" +
" is handled in an interactive way.");
System.err.println(" - " + DUMP + ": If defined true, try to dump (hex+ascii) the content of Stream and\n" +
" Object messages.");
System.err.println(" - " + BODY_AS_TEXT + ": Try to print message body as a String using a proposed\n" +
" charset (by default UTF-8). This option is only available with BytesMessage.");
System.err.println(" - " + CHARSET + ": ALlows to fix the charset used to save TextMessage, and to\n"
+ " display BytesMessage in text. By default UTF-8.");
System.err.println(" - " + SILENT + ": If defined true, the output is minimum.");
System.err.println("\nCommands:\n" +
" - " + HELP_CMD + ": prints the usage message.\n" +
" - " + BROWSE_CMD + ":prints successively each message of the queue, allowing to delete\n" +
" or forward it. If ALL option is defined, all messages are automatically\n" +
" handled (only bodies of TextMessage are displayed).\n" +
" - " + PURGE_CMD + ": removes all messages in the queue.\n" +
" - " + FORWARD_CMD + ": forwards the message identified by MSGID option.\n" +
" - " + REMOVE_CMD + ": removes the message identified by MSGID option.\n" +
" - " + PAUSE_ON_CMD + '/' + PAUSE_OFF_CMD + ": pause (resp. restart) the queue.\n" +
" - " + CREATE_CMD + ": creates the queue and registers it in JNDI. The rights set allow\n" +
" any user to send or receive messages on this queue.\n" +
" - " + DELETE_CMD + ": deletes the queue in the JMS server.\n" +
" - " + STAT_CMD + " statistics: prints all statistics about the queue.\n" +
" - " + LOOKUP_CMD + ": gets the registered object in JNDI (name asked on terminal).\n" +
" - " + UNBIND_CMD + ": removes the binding in JNDI (name asked on terminal).\n" +
" - " + PASSWORD_CMD+ ": updates a user password (parameters asked on terminal).");
System.err.println("\nParameters: Some commands require additional parameters normally entered by\n" +
" the user at the terminal. These parameters can be given in the command line\n" +
" in the order requested by the command:\n" +
" - " + LOOKUP_CMD + '/' + UNBIND_CMD + ": \n" +
" These commands can take multiple parameters, to stipulate the last\n" +
" parameter and avoid a request on the terminal you can use the \"\"\n" +
" empty parameter.\n" +
" - " + PASSWORD_CMD + ": \n" +
" If a parameter contains white space characters it must be surrounded by \".");
}
static Context ictx = null;
static Connection cnx = null;
static AdminWrapper admin = null;
static String[] values = null;
static int idx = 0;
public static void main(String[] args) throws Exception {
if (args.length < 1) {
usage();
return;
}
String input = System.getProperty(INPUT);
if (input != null) {
try {
stdin = new BufferedReader(new FileReader(input));
} catch (Exception exc) {
System.err.println("Error opening input file: " + input);
if (debug) exc.printStackTrace(System.err);
System.exit(-1);
}
if ((stdin != null) && (args.length > 1))
System.err.println("WARN: an input file is specified, additional command line parameters will be ignored.");
}
gui = Boolean.getBoolean(GUI);
if ((stdin != null) && gui) {
System.err.println("WARN: an input file is specified, \"" + GUI + "\"option will be ignored.");
gui = false;
}
values = args;
idx = 1;
// Verify that the command is valid
String command = args[0];
if (!BROWSE_CMD.equals(command) &&
!PURGE_CMD.equals(command) && !CREATE_CMD.equals(command) && !DELETE_CMD.equals(command) &&
!FORWARD_CMD.equals(command) && !REMOVE_CMD.equals(command) &&
!PAUSE_ON_CMD.equals(command) && !PAUSE_OFF_CMD.equals(command) &&
!STAT_CMD.equals(command) &&
!UNBIND_CMD.equals(command) && !LOOKUP_CMD.equals(command) &&
!PASSWORD_CMD.equals(command)) {
usage();
return;
}
// Get the JNDI initial context
try {
ictx = getJNDIInitialContext();
} catch (Exception exc) {
System.err.println("Error opening JNDI initial context: " + exc.getMessage());
if (debug) exc.printStackTrace(System.err);
System.exit(-1);
}
if (LOOKUP_CMD.equals(command)) {
while (true) {
String name = readLine("name: ");
if ((name == null) || name.isEmpty())
break;
lookup(name);
}
} else if (UNBIND_CMD.equals(command)) {
while (true) {
String name = readLine("name: ");
if ((name == null) || name.isEmpty())
break;
unbind(name);
}
}
// Get the JMS administration connection
try {
cnx = getJMSConnection(ictx);
cnx.start();
} catch (NamingException exc) {
System.err.println("Error opening JNDI connection: " + exc.getMessage());
if (debug) exc.printStackTrace(System.err);
if (ictx != null)
ictx.close();
if (cnx != null)
cnx.close();
System.exit(-1);
} catch (JMSException exc) {
System.err.println("Error opening JMS connection: " + exc.getMessage());
if (debug) exc.printStackTrace(System.err);
if (ictx != null)
ictx.close();
if (cnx != null)
cnx.close();
System.exit(-1);
}
// Initialize the administration API wrapper
try {
admin = new AdminWrapper(cnx);
} catch (Exception exc) {
System.err.println("Error opening Administration session: " + exc.getMessage());
if (debug) exc.printStackTrace(System.err);
if (ictx != null)
ictx.close();
if (cnx != null)
cnx.close();
System.exit(-1);
}
if (PASSWORD_CMD.equals(command)) {
try {
String userid = readLine("user: ");
char[] userpass = readPassword("password: ");
if ((userpass == null) || (userpass.length == 0)) {
System.err.println("Cannot change user passord: no password");
System.exit(-1);
}
User[] users = admin.getUsers();
User user = null;
for (User u : users) {
if (u.getName().equals(userid)) {
user = u;
break;
}
}
if (user == null) {
System.err.println("ERROR: User \"" + userid + "\" unknown.");
System.exit(-1);
}
user.setWrapper(admin);
user.update(userid, new String(userpass));
} catch (Exception exc) {
System.err.println("Cannot change user passord: " + exc.getMessage());
if (debug) exc.printStackTrace(System.err);
System.exit(-1);
} finally {
if (ictx != null)
ictx.close();
if (admin != null)
admin.close();
if (cnx != null)
cnx.close();
}
System.exit(0);
}
// Get the queue to handle
String qname = System.getProperty(QUEUE, QUEUE_DFLT);
Queue queue = null;
if (!CREATE_CMD.equals(command)) {
try {
queue = (Queue) getJMSDestination(ictx, qname);
} catch (Exception exc) {
System.err.println("Can not get the handled queue: " + exc.getMessage());
if (debug) exc.printStackTrace(System.err);
if (ictx != null)
ictx.close();
if (admin != null)
admin.close();
if (cnx != null)
cnx.close();
System.exit(-1);
}
}
// Set the administration wrapper
if (queue != null)
queue.setWrapper(admin);
// Initialize the messageProducer to forward messages if any
MessageProducer forwarder = null;
try {
String forward_qname = System.getProperty(FORWARD_QUEUE);
if (forward_qname != null) {
Destination forward = getJMSDestination(ictx, forward_qname);
Session session = (Session) cnx.createSession();
forwarder = session.createProducer(forward);
}
} catch (Exception exc) {
System.err.println("Cannot initialize message forwarder: " + exc.getMessage());
if (debug) exc.printStackTrace(System.err);
}
// Execute the command
try {
if (BROWSE_CMD.equals(command)) {
boolean all = Boolean.getBoolean(ALL);
browse(queue, forwarder, !all);
} else if (PURGE_CMD.equals(command)) {
purge(queue);
} else if (DELETE_CMD.equals(command)) {
delete(queue);
} else if (CREATE_CMD.equals(command)) {
create(qname);
} else if (FORWARD_CMD.equals(command)) {
boolean all = Boolean.getBoolean(ALL);
if (forwarder != null) {
String msgid = System.getProperty(MSGID);
if ((msgid != null) || all) {
forward(queue, forwarder, msgid);
} else {
System.err.println("Identifier of message is not defined.");
System.exit(-1);
}
} else {
System.err.println("Forward queue is not defined.");
System.exit(-1);
}
} else if (REMOVE_CMD.equals(command)) {
String msgid = System.getProperty(MSGID);
remove(queue, msgid);
} else if (PAUSE_ON_CMD.equals(command)) {
pause(queue, true);
} else if (PAUSE_OFF_CMD.equals(command)) {
pause(queue, false);
} else if (STAT_CMD.equals(command)) {
statistics(queue);
}
} catch (Exception exc) {
System.exit(-1);
} finally {
if (ictx != null)
ictx.close();
if (admin != null)
admin.close();
if (cnx != null)
cnx.close();
}
System.exit(0);
}
/* ********************************************************************************
* Handle parameters about JNDI
* ******************************************************************************** */
public static final String JNDI_FILE = "JNDI_FILE";
public static final String JNDI_FACTORY = "JNDI_FACTORY";
public static final String JNDI_FACTORY_DFLT = "fr.dyade.aaa.jndi2.client.NamingContextFactory";
public static final String JNDI_PROVIDER_URL = "JNDI_URL";
public static final String JNDI_PROVIDER_URL_DFLT = "scn://localhost:16400";
public static InitialContext getJNDIInitialContext() throws FileNotFoundException, IOException, NamingException {
Properties jndiProps = new Properties();
String jndiFile = System.getProperty(JNDI_FILE);
if (jndiFile != null) {
try (FileInputStream fis = new FileInputStream(jndiFile)) {
jndiProps.load(fis);
}
} else {
jndiProps.setProperty(InitialContext.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY_DFLT);
jndiProps.setProperty(InitialContext.PROVIDER_URL, JNDI_PROVIDER_URL_DFLT);
}
String jndiFactory = System.getProperty(JNDI_FACTORY);
if (jndiFactory != null)
jndiProps.setProperty(InitialContext.INITIAL_CONTEXT_FACTORY, jndiFactory);
String jndiURL = System.getProperty(JNDI_PROVIDER_URL);
if (jndiURL != null)
jndiProps.setProperty(InitialContext.PROVIDER_URL, jndiURL);
InitialContext ictx = new InitialContext(jndiProps);
return ictx;
}
/* ********************************************************************************
* Handle parameters about JMS connection
* ******************************************************************************** */
public static final String CF = "CF";
public static final String CF_DFLT = "cf";
public static final String ADMIN = "ADMIN";
public static final String ADMIN_DFLT = "root";
public static final String PASS = "PASS";
public static final String PASS_DFLT = "root";
public static Connection getJMSConnection(Context ictx) throws NamingException, JMSException {
ConnectionFactory cf = null;
String cfname = System.getProperty(CF, CF_DFLT);
try {
cf = (ConnectionFactory) ictx.lookup(cfname);
} catch (NameNotFoundException exc) {
System.err.println("JNDI: " + cfname + " not found.");
System.exit(-1);
}
if (debug)
System.err.println("ConnectionFactory=" + cf);
String user = System.getProperty(ADMIN, ADMIN_DFLT);
String pass = System.getProperty(PASS, PASS_DFLT);
Connection cnx = cf.createConnection(user, pass);
return cnx;
}
public static Destination getJMSDestination(Context ictx, String destname) throws NamingException {
try {
return (Destination) ictx.lookup(destname);
} catch (NameNotFoundException exc) {
System.err.println("JNDI: " + destname + " not found.");
throw exc;
}
}
public final static String LINE_SEP1 = "+==================================================\n";
public final static String LINE_SEP2 = "+------------------------------\n";
public static String msgToString(Message msg) throws JMSException {
StringBuilder strbuf = new StringBuilder();
strbuf.append(LINE_SEP1);
strbuf.append("| MessageID: \"").append(msg.getJMSMessageID()).append("\"\n");
strbuf.append("| Class: \"").append(msg.getClass().getSimpleName()).append("\"\n");
strbuf.append(LINE_SEP2);
msgHeader(strbuf, msg);
strbuf.append(LINE_SEP2);
msgProperties(strbuf, msg);
strbuf.append(LINE_SEP2);
msgBody(strbuf, msg);
strbuf.append(LINE_SEP2);
return strbuf.toString();
}
public static void msgHeader(StringBuilder strbuf, Message msg) throws JMSException {
strbuf.append("| To: ").append(msg.getJMSDestination()).append('\n');
strbuf.append("| CorrelationId: ").append(msg.getJMSCorrelationID()).append('\n');
strbuf.append("| DeliveryMode: ").append(msg.getJMSDeliveryMode()).append('\n');
strbuf.append("| Expiration: ").append(msg.getJMSExpiration()).append('\n');
strbuf.append("| Priority: ").append(msg.getJMSPriority()).append('\n');
strbuf.append("| Redelivered: ").append(msg.getJMSRedelivered()).append('\n');
strbuf.append("| ReplyTo: ").append(msg.getJMSReplyTo()).append('\n');
strbuf.append("| Timestamp: ").append(msg.getJMSTimestamp())
.append(" (").append(new Date(msg.getJMSTimestamp())).append(")\n");
strbuf.append("| Type: ").append(msg.getJMSType()).append('\n');
}
public static void msgProperties(StringBuilder strbuf, Message msg) throws JMSException {
// Handles JMS_JORAM_ERROR properties
if (msg.propertyExists("JMS_JORAM_ERRORCOUNT")) {
int nbErrors = msg.getIntProperty("JMS_JORAM_ERRORCOUNT");
strbuf.append("| ").append("JMS_JORAM_ERRORCOUNT=").append(nbErrors).append('\n');
for (int i=1; i<=nbErrors; i++) {
strbuf.append("| ").append("JMS_JORAM_ERRORCODE_").append(i).append("=").append(msg.getStringProperty("JMS_JORAM_ERRORCODE_"+i)).append('\n');
strbuf.append("| ").append("JMS_JORAM_ERRORCAUSE_").append(i).append("=").append(msg.getStringProperty("JMS_JORAM_ERRORCAUSE_"+i)).append('\n');
}
strbuf.append(LINE_SEP2);
}
// Handles other properties
for (Enumeration names = msg.getPropertyNames();names.hasMoreElements();) {
String name = names.nextElement();
if (! name.startsWith("JMS_JORAM_ERROR")) // Already handled
strbuf.append("| ").append(name).append("=").append(msg.getStringProperty(name)).append('\n');
}
}
public static void msgBody(StringBuilder strbuf, Message msg) throws JMSException {
if (msg instanceof TextMessage) {
// Handling of TextMessage
strbuf.append(((TextMessage) msg).getText()).append('\n');
} else if (msg instanceof BytesMessage) {
// Handling of BytesMessage
try {
byte [] body = msg.getBody(byte[].class);
if ((body == null) || (body.length == 0)) {
strbuf.append("Empty body\n");
} else {
if (bodyAsText) {
try {
strbuf.append(new String(body, charset)).append('\n');
} catch (UnsupportedEncodingException exc) {
strbuf.append("/!\\ Could not writes body: " + exc.getMessage());
}
} else {
strbuf.append(BinaryDump.dump(body, 0, 0));
}
}
} catch (JMSException exc) {
strbuf.append("/!\\ Error reading message body: " + exc.getMessage()).append('\n');
}
} else if (msg instanceof MapMessage) {
// Handling of MapMessage
try {
Map map = msg.getBody(java.util.Map.class);
if (map == null) {
strbuf.append("Empty body\n");
} else {
map.forEach((k, v) -> strbuf.append(k).append('=').append(v).append('\n'));
}
} catch (JMSException exc) {
strbuf.append("/!\\ Error reading message body: " + exc.getMessage()).append('\n');
}
} else if (msg instanceof ObjectMessage) {
// Handling of ObjectMessage
if (dump && (msg instanceof org.objectweb.joram.client.jms.Message)) {
try {
strbuf.append(((org.objectweb.joram.client.jms.Message) msg).dumpBody());
} catch (IOException exc) {
strbuf.append("/!\\ Error dumping message: " + exc.getMessage()).append('\n');
}
} else {
strbuf.append("/!\\ Message boddy cannot be displayed: " + msg.getClass().getName()).append('\n');
}
} else if (msg instanceof StreamMessage) {
// Handling of StreamMessage
if (dump && (msg instanceof org.objectweb.joram.client.jms.Message)) {
try {
strbuf.append(((org.objectweb.joram.client.jms.Message) msg).dumpBody());
} catch (IOException exc) {
strbuf.append("/!\\ Error dumping message: " + exc.getMessage()).append('\n');
}
} else {
strbuf.append("/!\\ Message boddy cannot be displayed: " + msg.getClass().getName()).append('\n');
}
} else {
// Simple message without body
strbuf.append("Empty body\n");
}
}
public static void saveBody(String id, byte[] content) {
File file = new File("Message_" + id.substring(3));
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(content);
fos.flush();
System.out.println("Message saved in " + file.getPath());
} catch (IOException exc) {
System.err.println("/!\\ Cannot save message " + id + ": " + exc.getMessage());
}
}
/* ********************************************************************************
* Prints successively each message of the queue, allowing to delete or forward it.
* If ALL option is defined, all messages are automatically handled.
* ******************************************************************************** */
public final static int QUIT = 'q';
public final static int DELETE = 'd';
public final static int FORWARD = 'f';
public final static int SAVE = 's';
public final static int NEXT = 'n';
public static void browse(Queue queue, MessageProducer forwarder, boolean interactive) {
try {
String ids[] = queue.getMessageIds();
for (String id : ids) {
Message msg = queue.getMessage(id);
System.out.println(msgToString(msg));
if (interactive) {
if (forwarder != null)
System.out.println("d(elete), f(orward), s(ave), n(ext), q(uit)");
else
System.out.println("d(elete), n(ext), s(ave), q(uit)");
int c;
while (true) {
try {
c = System.in.read();
} catch (IOException exc) {
c = QUIT;
}
if ((c == QUIT) || (c == DELETE) || (c == SAVE) || (c == NEXT)) break;
if ((forwarder != null) && (c == FORWARD)) break;
}
if (c == QUIT) break;
if (c == NEXT) continue;
if (c == DELETE) {
queue.deleteMessage(id);
} else if (c == SAVE) {
if (msg instanceof TextMessage) {
try {
saveBody(msg.getJMSMessageID(), ((TextMessage) msg).getText().getBytes(charset));
} catch (UnsupportedEncodingException exc) {
System.err.println(" /!\\" + exc.getMessage());
}
} else if ((msg instanceof BytesMessage) || (msg instanceof MapMessage) || (msg instanceof ObjectMessage) || (msg instanceof StreamMessage)) {
try {
saveBody(msg.getJMSMessageID(), ((org.objectweb.joram.client.jms.Message) msg).getRawBody());
} catch (IOException exc) {
System.err.println(" /!\\" + exc.getMessage());
}
} else {
System.out.println(" /!\\ Message body is empty: " + msg.getJMSMessageID());
}
} else if (c == FORWARD) {
if (forwarder != null) {
// Forwards this message.
// TODO: Use QoS properties of initial message.
forwarder.send(msg);
// Then deletes it.
queue.deleteMessage(id);
}
}
}
}
} catch (ConnectException|AdminException exc) {
System.err.println("Issue with administration connection: " + exc.getMessage());
if (! silent || debug) exc.printStackTrace();
} catch (JMSException exc) {
System.err.println("Issue with JMS connection: " + exc.getMessage());
if (! silent || debug) exc.printStackTrace();
}
}
/* ********************************************************************************
* Removes all messages in the queue.
* ******************************************************************************** */
public static void purge(Queue queue) {
try {
queue.clear();
} catch (ConnectException|AdminException exc) {
System.err.println("Issue with administration connection: " + exc.getMessage());
if (! silent || debug) exc.printStackTrace();
}
}
/* ********************************************************************************
* Creates the queue and registers it in JNDI. The rights set allow any user to send
* or receive messages on this queue.
* ******************************************************************************** */
public static void create(String name) {
org.objectweb.joram.client.jms.Queue queue = null;
try {
queue = (Queue) admin.createQueue(name);
queue.setFreeReading();
queue.setFreeWriting();
} catch (ConnectException|AdminException exc) {
System.err.println("Issue with administration connection: " + exc.getMessage());
if (! silent || debug) exc.printStackTrace();
return;
}
try {
ictx.bind(name, queue);
} catch (NamingException exc) {
System.err.println("Cannot bind queue in JNDI: " + exc.getMessage());
if (! silent || debug) exc.printStackTrace();
}
}
/* ********************************************************************************
* Pause (or restart) the queue.
* ******************************************************************************** */
public static void pause(Queue queue, boolean pause) {
try {
queue.setPause(pause);
} catch (ConnectException|AdminException exc) {
System.err.println("Issue with administration connection: " + exc.getMessage());
if (! silent || debug) exc.printStackTrace();
}
}
/* ********************************************************************************
* Get the queue statistics.
* ******************************************************************************** */
public static void statistics(Queue queue) {
try {
@SuppressWarnings("rawtypes") Hashtable statistics = queue.getStatistics();
StringBuilder strbuf = new StringBuilder();
for (Object key : statistics.keySet()) {
strbuf.append("| ").append(key).append("=").append(statistics.get(key)).append('\n');
}
System.out.println(strbuf.toString());
} catch (ConnectException|AdminException exc) {
System.err.println("Issue with administration connection: " + exc.getMessage());
if (! silent || debug) exc.printStackTrace();
}
}
/* ********************************************************************************
* Delete the queue.
* ******************************************************************************** */
public static void delete(Queue queue) {
try {
queue.delete();
} catch (ConnectException|AdminException|JMSException exc) {
System.err.println("Issue with administration connection: " + exc.getMessage());
if (! silent || debug) exc.printStackTrace();
}
}
/* ********************************************************************************
* Remove a message in the queue.
* ******************************************************************************** */
public static void remove(Queue queue, String msgid) {
try {
Message msg = queue.getMessage(msgid);
if (msg == null) {
System.err.println("Message \"" + msgid +"\" unknown.");
System.exit(-1);
}
queue.deleteMessage(msgid);
System.out.println("Message \"" + msgid + "\" removed.");
} catch (ConnectException|AdminException|JMSException exc) {
System.err.println("Issue with administration connection: " + exc.getMessage());
if (! silent || debug) exc.printStackTrace();
}
}
/* ********************************************************************************
* Forwards the message identified by MSGID option.
* ******************************************************************************** */
public static void forward(Queue queue, MessageProducer forwarder, String msgid) {
try {
if (msgid == null) {
// forwards all messages
String ids[] = queue.getMessageIds();
for (String id : ids) {
forward2(queue, forwarder, id);
}
} else {
// forwards identified message
forward2(queue, forwarder, msgid);
}
} catch (ConnectException|AdminException|JMSException exc) {
System.err.println("Issue with administration connection: " + exc.getMessage());
if (! silent || debug) exc.printStackTrace();
}
}
private static void forward2(Queue queue, MessageProducer forwarder, String msgid) throws ConnectException, AdminException, JMSException {
Message msg = queue.getMessage(msgid);
if (msg == null) {
System.err.println("Message \"" + msgid +"\" unknown.");
System.exit(-1);
}
if (!silent || debug)
System.out.println(msgToString(msg));
// TODO: Use QoS properties of initial message.
forwarder.send(msg);
queue.deleteMessage(msgid);
System.out.println("Message \"" + msgid + "\" forwarded.");
}
/* ********************************************************************************
* Lookup in JNDI.
* ******************************************************************************** */
public static void lookup(String name) {
try {
Object obj = ictx.lookup(name);
System.out.println("Name \"" + name + "\" bind to: " + obj);
} catch (NamingException exc) {
System.err.println("Name \"" + name +"\" unknown.");
if (debug) exc.printStackTrace(System.err);
}
}
/* ********************************************************************************
* Unbind the queue.
* ******************************************************************************** */
public static void unbind(String qname) {
try {
ictx.unbind(qname);
} catch (NamingException exc) {
System.err.println("Name \"" + qname +"\" unknown.");
if (debug) exc.printStackTrace(System.err);
}
}
/* ********************************************************************************
* Allows to use System.console if possible but implements a workaround when the
* console is not available (Eclipse or Mingw terminals).
* ******************************************************************************** */
static BufferedReader stdin = null;
static boolean gui = false;
public static char[] readPassword(String format, Object... args) throws IOException {
if (gui) {
final JPasswordField pf = new JPasswordField();
if (JOptionPane.showConfirmDialog( null, pf, format, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE ) == JOptionPane.OK_OPTION) {
return pf.getPassword();
} else {
return null;
}
}
if ((stdin == null) && (System.console() != null))
return System.console().readPassword(format, args);
return readLine(format, args).toCharArray();
}
public static String readLine(String format, Object... args) throws IOException {
if (stdin != null)
return stdin.readLine();
if (idx < values.length)
return values[idx++];
if (System.console() != null)
return System.console().readLine(format, args);
System.out.print(String.format(format, args));
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
return reader.readLine();
}
}