package com.mcafee.gui;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.naming.InitialContext;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingWorker;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mcafee.JmsDiggerException;
import com.mcafee.JmsDurableSubscriberManipulator;
import com.mcafee.JmsHelper;
/**
*
* @author Gursev Singh Kalra @ McAfee, Inc.
*
*/
public class JmsDurableSubscriberTab extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
private String title;
private int space = 5;
private JmsConfigTab jmsConfigTab;
private JTextField topicNameInput;
private JTextField messageSelectorInput;
private JSpinner durableSubsCountSpinner;
private SpinnerNumberModel spinnerModel;
private JButton createMultipleDurableSubsButton;
private JProgressBar progressBar;
private JTextField clientIdInput;
private JTextField subsNameInput;
private JButton createSingleSubsButton;
private JButton eraseDurableSubsButton;
private JTextArea outputArea;
private JmsConfig jmsConfig;
private InitialContext initialContext;
private JmsDurableSubscriberManipulator manipulator ;
private static final Logger LOG = LoggerFactory.getLogger(JmsDurableSubscriberTab.class);
public String getTitle() {
return title;
}
public JmsDurableSubscriberTab(JmsConfigTab jmsConfigTab) throws JmsDiggerException {
this.jmsConfigTab = jmsConfigTab;
//jmsConfig = this.jmsConfigTab.getJmsConfig();
/**
* The following line is commented out to enable late Initial Context generation.
* There are additional two lines of code added see comments beginning __LAZY__ below.
* This mostly appears to be a workaround, but i will have to create a more robust library.
*/
//initialContext = jmsConfig.buildInitialContext();
JPanel masterPanel = new JPanel(new GridBagLayout());
title = "Durable Subscribers";
TriggerDurableSubscriberCreation trigger = new TriggerDurableSubscriberCreation();
JPanel nameFilterPanel = new JPanel(new GridBagLayout());
GridBagConstraints masterGbc = new GridBagConstraints();
GridBagConstraints gbc = new GridBagConstraints();
Border border = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
Insets inset = new Insets(space, space, space, space);
Insets masterInset = new Insets(space * 2, space * 2, space * 2, space * 2);
masterGbc.insets = masterInset;
gbc.insets = inset;
gbc.fill = GridBagConstraints.HORIZONTAL;
JLabel topicNameLabel = new JLabel("Topic Name");
gbc.gridx = 0;
gbc.gridy = 0;
topicNameLabel.setHorizontalAlignment(JLabel.RIGHT);
nameFilterPanel.add(topicNameLabel, gbc);
topicNameInput = new JTextField(30);
gbc.gridx = 1;
gbc.gridy = 0;
nameFilterPanel.add(topicNameInput, gbc);
JLabel filterLabel = new JLabel("Message Selector");
gbc.gridx = 0;
gbc.gridy = 1;
filterLabel.setHorizontalAlignment(JLabel.RIGHT);
nameFilterPanel.add(filterLabel, gbc);
messageSelectorInput = new JTextField(30);
gbc.gridx = 1;
gbc.gridy = 1;
nameFilterPanel.add(messageSelectorInput, gbc);
masterGbc.gridx = 0;
masterGbc.gridy = 0;
masterGbc.anchor = GridBagConstraints.LINE_START;
masterPanel.add(nameFilterPanel, masterGbc);
JPanel randomCountPanel = new JPanel(new GridBagLayout());
Border singleUserBorder = BorderFactory.createTitledBorder(border, "Create Multiple Durable Subscribers");
spinnerModel = new SpinnerNumberModel(10, 1, 9999, 1);
durableSubsCountSpinner = new JSpinner(spinnerModel);
gbc = new GridBagConstraints();
gbc.insets = inset;
gbc.gridx = 0;
gbc.gridy = 0;
randomCountPanel.add(durableSubsCountSpinner, gbc);
createMultipleDurableSubsButton = new JButton("Create");
createMultipleDurableSubsButton.addActionListener(trigger);
gbc.gridx = 1;
gbc.gridy = 0;
randomCountPanel.add(createMultipleDurableSubsButton, gbc);
// JLabel progressLabel = new JLabel("Progress > ");
// gbc.fill = GridBagConstraints.HORIZONTAL;
// gbc.gridx = 0;
// gbc.gridy = 1;
// randomCountPanel.add(progressLabel, gbc);
// progressBar = new JProgressBar();
// progressBar.setBounds(0, 0, 30, 100);
//
// gbc.gridx = 1;
// gbc.gridy = 1;
// gbc.gridwidth = 2;
// randomCountPanel.add(progressBar, gbc);
randomCountPanel.setBorder(singleUserBorder);
masterGbc = new GridBagConstraints();
masterGbc.gridx = 0;
masterGbc.gridy = 2;
masterGbc.insets = inset;
masterGbc.anchor = GridBagConstraints.LINE_START;
masterGbc.fill = GridBagConstraints.HORIZONTAL;
masterPanel.add(randomCountPanel, masterGbc);
JPanel singleSubsPanel = new JPanel(new GridBagLayout());
Border singleSubsBorder = BorderFactory.createTitledBorder(border, "Create/Erase A Durable Subscriber");
gbc = new GridBagConstraints();
JLabel clientIdLabel = new JLabel("Client ID");
clientIdLabel.setHorizontalAlignment(JLabel.RIGHT);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = inset;
gbc.gridx = 0;
gbc.gridy = 0;
singleSubsPanel.add(clientIdLabel, gbc);
clientIdInput = new JTextField(30);
gbc.gridx = 1;
gbc.gridy = 0;
singleSubsPanel.add(clientIdInput, gbc);
JLabel subsNameLabel = new JLabel("Durable Subscriber Name");
subsNameLabel.setHorizontalAlignment(JLabel.RIGHT);
gbc.insets = inset;
gbc.gridx = 0;
gbc.gridy = 1;
singleSubsPanel.add(subsNameLabel, gbc);
subsNameInput = new JTextField(30);
gbc.gridx = 1;
gbc.gridy = 1;
singleSubsPanel.add(subsNameInput, gbc);
JPanel createButtonPanel = new JPanel(new GridBagLayout());
createSingleSubsButton = new JButton("Create");
createSingleSubsButton.addActionListener(trigger);
gbc.gridx = 0;
gbc.gridy = 0;
createButtonPanel.add(createSingleSubsButton, gbc);
eraseDurableSubsButton = new JButton("Erase");
eraseDurableSubsButton.addActionListener(trigger);
gbc.gridx = 1;
gbc.gridy = 0;
createButtonPanel.add(eraseDurableSubsButton, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
gbc.gridwidth = 2;
singleSubsPanel.add(createButtonPanel, gbc);
singleSubsPanel.setBorder(singleSubsBorder);
JPanel outputBoxPanel = new JPanel(new GridBagLayout());
outputArea = new JTextArea(15, 50);
outputArea.setEditable(false);
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 0;
outputBoxPanel.add(new JScrollPane(outputArea), gbc);
Border outputBorder = BorderFactory.createTitledBorder(border, "Results");
outputBoxPanel.setBorder(outputBorder);
masterGbc.gridx = 0;
masterGbc.gridy = 3;
masterPanel.add(outputBoxPanel, masterGbc);
/*
* Pane to display progress
*/
JPanel progressPanel = new JPanel(new GridBagLayout());
JLabel progressLabel = new JLabel("Progress > ");
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.NONE;
progressPanel.add(progressLabel, gbc);
progressBar = new JProgressBar();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 2;
gbc.gridy = 0;
gbc.weightx = 1.0;
progressPanel.add(progressBar, gbc);
masterGbc.gridx = 0;
masterGbc.gridy = 4;
masterGbc.fill = GridBagConstraints.HORIZONTAL;
masterGbc.insets = inset;
masterPanel.add(progressPanel, masterGbc);
masterGbc.gridx = 0;
masterGbc.gridy = 1;
masterGbc.anchor = GridBagConstraints.LINE_START;
masterGbc.insets = inset;
masterPanel.add(singleSubsPanel, masterGbc);
this.add(masterPanel, masterGbc);
}
class TriggerDurableSubscriberErase implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
}
}
class TriggerDurableSubscriberCreation implements ActionListener {
public void disableAllButtons() {
createMultipleDurableSubsButton.setEnabled(false);
createSingleSubsButton.setEnabled(false);
eraseDurableSubsButton.setEnabled(false);
}
public void actionPerformed(ActionEvent event) {
DurableSubscriberWorker durableSubscriberWorker;
if(JmsHelper.isStringNullOrEmpty(topicNameInput.getText())) {
JOptionPane.showMessageDialog(null, "Topic name cannot be empty or null", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
if(event.getSource() == eraseDurableSubsButton) {
if(JmsHelper.isStringNullOrEmpty(subsNameInput.getText()) || JmsHelper.isStringNullOrEmpty(clientIdInput.getText())) {
JOptionPane.showMessageDialog(null, "Erase function requires a Client ID and Durable Subscriber Name", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
}
String topicName = topicNameInput.getText();
String messageSelector = messageSelectorInput.getText();
int count = 1;
String clientId = clientIdInput.getText();
String subsName = subsNameInput.getText();
ArrayList<String> durableSubscriberNames = new ArrayList<String>();
if(JmsHelper.isStringNullOrEmpty(clientId)) {
clientId = JmsHelper.getRandomString();
}
if(event.getSource() == createSingleSubsButton) {
if(JmsHelper.isStringNullOrEmpty(subsName)) {
durableSubscriberNames.add(JmsHelper.getRandomString());
}
else {
durableSubscriberNames.add(subsName);
}
} else {
if(event.getSource() == createMultipleDurableSubsButton) {
count = (Integer) spinnerModel.getValue();
for(int i = 0; i < count; i++) {
durableSubscriberNames.add(JmsHelper.getRandomString());
}
} else if(event.getSource() == eraseDurableSubsButton) {
durableSubscriberNames.add(subsName);
}
}
disableAllButtons();
//durableSubscriberWorker = new DurableSubscriberWorker(topicName, messageSelector, clientIdList, durableSubscriberNames, (Integer) spinnerModel.getValue());
try {
durableSubscriberWorker = new DurableSubscriberWorker(topicName, messageSelector, clientId, durableSubscriberNames, count);
if(event.getSource() == eraseDurableSubsButton) {
durableSubscriberWorker.setErase(true);
}
durableSubscriberWorker.execute();
} catch (JmsDiggerException e) {
LOG.info("An error has occured while creating/executing a durableSubscriberWorker", e);
JmsGuiCommon.showErrorAndLogMessage(e.getMessage());
}
}
}
class DurableSubscriberWorker extends SwingWorker<ProgressInfo, ProgressInfo> {
String messageSelector;
String topicName;
ArrayList<String> clientIdList;
ArrayList<String> durableSubscriberNames;
String clientId;
int count;
boolean erase;
public void setErase(boolean erase) {
this.erase = erase;
}
//public DurableSubscriberWorker(String topicName, String messageSelector, ArrayList<String> clientIdList, ArrayList<String> durableSubscriberNames, int count) {
public DurableSubscriberWorker(String topicName, String messageSelector, String clientId, ArrayList<String> durableSubscriberNames, int count) throws JmsDiggerException {
this.topicName = topicName;
this.messageSelector = messageSelector;
//this.clientIdList = clientIdList;
this.clientId = clientId;
this.durableSubscriberNames = durableSubscriberNames;
this.count = count;
this.erase = false;
/**
* __LAZY__ the addTopic call adds the topic to the initial context's environment
* variables before building the initial context. Once initial context is built, it cannot be changed. <br/>
* Initializing the jmsConfig here to ensure that a new configuration is generated for each button click
* to accommodate for topic changes for a single run.
*/
jmsConfig = jmsConfigTab.getJmsConfig();
jmsConfig.addTopic(topicName);
initialContext = jmsConfig.buildInitialContext();
}
public boolean isErase() {
return erase;
}
@Override
protected ProgressInfo doInBackground() throws Exception {
try {
manipulator = new JmsDurableSubscriberManipulator(initialContext, topicName, jmsConfig.getConnFactName(), jmsConfig.getLoginInfo());
manipulator.init(clientId);
} catch (JmsDiggerException ex) {
LOG.info("DurableSubscriberManipulator initialization failed", ex);
ProgressInfo i = new ProgressInfo(JmsHelper.exceptionStacktraceToString(ex), false, 0);
return i;
}
//publish(new ProgressInfo("\n==================================================\n[+] Creating durable subscribers with clientID \"" + clientId+"\"" , true, 0));
try {
for(int i = 0; i < durableSubscriberNames.size() ; i++) {
try {
if(!isErase()) {
manipulator.createDurableSubscriber(durableSubscriberNames.get(i), messageSelector);
publish(new ProgressInfo("\n[+] Created durable subscriber \"" + durableSubscriberNames.get(i) +"\"" ,true, i*100/count));
} else {
manipulator.eraseDurableSubscriber(durableSubscriberNames.get(0));
publish(new ProgressInfo("\n[+] Erased durable subscriber \"" + durableSubscriberNames.get(i) +"\"" ,true, 100));
}
} catch(JmsDiggerException ex) {
if(!isErase())
publish(new ProgressInfo("\n[-] Could not create durable subscriber \"" + durableSubscriberNames.get(i) +"\"" ,true, i*100/count));
else
publish(new ProgressInfo("\n[-] Could not erase durable subscriber \"" + durableSubscriberNames.get(i) +"\"" ,true, 100));
}
}
} finally {
/**
* Very important to close the connections as ActiveMQ allows only one active connection from one clientID.
* If the connection is not closed, ActiveMQ throws an exception of the following type
* Caused by: javax.jms.InvalidClientIDException: Broker: localhost - Client: <clientID> already connected from tcp://ipadderss:port
*/
manipulator.close();
}
return new ProgressInfo("Completed", true, 100);
}
@Override
public void process(List<ProgressInfo> progressInfo) {
for(ProgressInfo pInfo : progressInfo) {
outputArea.append(pInfo.getDescription());
}
ProgressInfo pInfo = progressInfo.get(progressInfo.size()-1);
progressBar.setValue(pInfo.getPercentage());
}
@Override
public void done() {
try {
ProgressInfo pInfo = get();
if(pInfo.isSuccessful() == false && pInfo.getPercentage() == 0) {
outputArea.setText(pInfo.getDescription());
JOptionPane.showMessageDialog(null, "An error has occured while creating durable subscribers", "Error", JOptionPane.ERROR_MESSAGE);
} else {
progressBar.setValue(pInfo.getPercentage());
}
} catch (InterruptedException ex) {
LOG.info("", ex);
JmsGuiCommon.showErrorAndLogMessage(ex.getMessage());
} catch (ExecutionException ex) {
LOG.info("", ex);
JmsGuiCommon.showErrorAndLogMessage(ex.getMessage());
}
JOptionPane.showMessageDialog(null, "Done!", "", JOptionPane.INFORMATION_MESSAGE);
enableAllButtons();
}
public void enableAllButtons() {
createMultipleDurableSubsButton.setEnabled(true);
createSingleSubsButton.setEnabled(true);
eraseDurableSubsButton.setEnabled(true);
}
}
}