/*
* Copyright 2003,2004,2005,2006 Colin Crist
*
* Licensed 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 hermes.browser;
import hermes.ConnectionListener;
import hermes.Domain;
import hermes.Hermes;
import hermes.HermesConfigurationListener;
import hermes.HermesContext;
import hermes.HermesException;
import hermes.HermesInitialContextFactory;
import hermes.HermesLoader;
import hermes.HermesRepositoryManager;
import hermes.JAXBHermesLoader;
import hermes.JNDIContextFactory;
import hermes.SingletonManager;
import hermes.SystemProperties;
import hermes.browser.actions.ActionFactory;
import hermes.browser.actions.BrowserAction;
import hermes.browser.actions.MessageStoreBrowserAction;
import hermes.browser.actions.QueueBrowseAction;
import hermes.browser.components.ActionsPanel;
import hermes.browser.components.BrowserTree;
import hermes.browser.components.DockableToolPanel;
import hermes.browser.components.Log4JOutputViewer;
import hermes.browser.components.NavigableComponent;
import hermes.browser.components.WatchDockableFrame;
import hermes.browser.dialog.ClasspathIdCellEdtitor;
import hermes.browser.dialog.DirectoryCellEditor;
import hermes.browser.dialog.DomainCellEditor;
import hermes.browser.dialog.HermesCellEditor;
import hermes.browser.dialog.SelectorImpl;
import hermes.browser.dialog.SelectorImplCellEditor;
import hermes.browser.jython.JythonDockableFrame;
import hermes.browser.model.BrowserTreeModel;
import hermes.browser.tasks.HermesBrowserTaskListener;
import hermes.browser.tasks.TaskSupport;
import hermes.browser.tasks.ThreadPool;
import hermes.config.DestinationConfig;
import hermes.config.HermesConfig;
import hermes.config.NamingConfig;
import hermes.config.WatchConfig;
import hermes.fix.FIXPrettyPrinter;
import hermes.fix.FIXUtils;
import hermes.impl.ConfigDAO;
import hermes.impl.ConfigDAOImpl;
import hermes.impl.FileRepositoryManager;
import hermes.impl.SimpleClassLoaderManager;
import hermes.renderers.RendererManager;
import hermes.store.MessageStore;
import hermes.util.JVMUtils;
import hermes.util.TextUtils;
import java.awt.BorderLayout;
import java.awt.HeadlessException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ListSelectionListener;
import javax.swing.plaf.metal.MetalLookAndFeel;
import jsyntaxpane.DefaultSyntaxKit;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.log4j.Logger;
import org.python.core.PyException;
import com.jidesoft.action.CommandBar;
import com.jidesoft.action.DefaultDockableBarDockableHolder;
import com.jidesoft.comparator.ObjectComparatorManager;
import com.jidesoft.converter.ObjectConverterManager;
import com.jidesoft.dialog.JideOptionPane;
import com.jidesoft.docking.DefaultDockingManager;
import com.jidesoft.docking.event.DockableFrameAdapter;
import com.jidesoft.docking.event.DockableFrameEvent;
import com.jidesoft.document.DocumentComponent;
import com.jidesoft.document.DocumentComponentEvent;
import com.jidesoft.document.DocumentComponentListener;
import com.jidesoft.document.DocumentPane;
import com.jidesoft.grid.CellEditorManager;
import com.jidesoft.grid.CellRendererManager;
import com.jidesoft.plaf.LookAndFeelFactory;
import com.jidesoft.status.MemoryStatusBarItem;
import com.jidesoft.status.ProgressStatusBarItem;
import com.jidesoft.status.StatusBar;
import com.jidesoft.status.TimeStatusBarItem;
import com.jidesoft.swing.JideBoxLayout;
import com.jidesoft.swing.JideScrollPane;
import com.jidesoft.swing.SplashScreen;
import com.jidesoft.utils.Lm;
/**
* HermesBrowser. A Swing GUI for working with JMS
*
* @author colincrist@hermesjms.com
* @version $Id: HermesBrowser.java,v 1.94 2007/02/18 19:01:44 colincrist Exp $
*/
public class HermesBrowser extends DefaultDockableBarDockableHolder implements HermesUI {
public static final int DEFAULT_MAX_CACHED_MESSAGES = 1000;
public static final long DEFAULT_QUEUE_BROWSE_CONSUMER_TIMEOUT = 10000;
private static final String DEFAULT_PROFILE_NAME = "hermes.layout";
private static final String HERMES_TITLE = "Hermes " + Hermes.VERSION;
private static final Logger log = Logger.getLogger(HermesBrowser.class);
private static final RendererManager rendererManager = new RendererManager();
private static final ConfigDAO configDAO = new ConfigDAOImpl();
private static final long serialVersionUID = 995079090594726460L;
private static HermesBrowser ui;
private static final String USER_PROFILE_NAME = "hermes.layout." + System.getProperty("user.name");
private boolean restricted = System.getProperty(SystemProperties.RESTRICTED) != null;
public static HermesBrowser getBrowser() {
return ui;
}
public static ConfigDAO getConfigDAO() {
return configDAO;
}
public static RendererManager getRendererManager() {
return rendererManager;
}
public void setConfig(HermesConfig config) {
}
public static void main(String[] args) {
log.debug("Hermes Browser " + Hermes.VERSION + " starting...");
log.debug("working directory: " + new File(".").getAbsolutePath());
Hermes.events.addConnectionListener(new ConnectionListener() {
public void onConnectionOpen(Hermes hermes) {
log.debug("Connection " + hermes.getId() + " opened");
}
public void onConnectionClosed(Hermes hermes) {
log.debug("Connection " + hermes.getId() + " closed");
}
});
//
// Need to bootstrap objects into the singleton manager... hack for now.
JVMUtils.forceInit(SingletonManager.class);
JVMUtils.forceInit(ThreadPool.class);
JVMUtils.forceInit(SimpleClassLoaderManager.class);
//
// Commented out as this is for debug use only.
// RepaintManager.setCurrentManager(new ThreadCheckingRepaintManager());
//
// Note this is the license for the JIDE Framework, it is licenced
// to Colin Crist and the Hermes project and should not be used for any
// other purpose
//
Lm.verifyLicense("Colin Crist", "Hermes", "9vkNAfxF1lvVyW7uZXYjpxFskycSGLw1");
//
// See http://www.jidesoft.com for licensing terms.
//
// Register a converter from a String to a File with PropertyUtils.
ConvertUtils.register(new Converter() {
public Object convert(Class arg0, Object filename) {
return new File((String) filename);
}
}, File.class);
SplashScreen.create(IconCache.getIcon("hermes.splash"));
SplashScreen.show();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
ui = new HermesBrowser(HERMES_TITLE);
ui.initJIDE();
try {
ui.loadConfig();
} catch (NamingException ex) {
log.fatal("cannot initialise hermes: " + ex.getMessage(), ex);
System.exit(1);
} catch (HeadlessException ex) {
log.fatal("cannot initialise hermes browser, no head: " + ex.getMessage(), ex);
System.exit(1);
}
ui.initUI();
ui.init();
ui.getLayoutPersistence().setProfileKey(ui.getUserProfileName());
ui.getLayoutPersistence().loadLayoutData();
// This must be done after the layout has been set otherwise
// the
// frames are hidden.
final ArrayList<WatchConfig> tmpList = new ArrayList<WatchConfig>(ui.getConfig().getWatch());
ui.getLoader().getConfig().getWatch().clear();
for (WatchConfig wConfig : tmpList) {
ui.createWatch(wConfig);
}
ui.firstLoad = false;
} catch (Exception ex) {
log.fatal("cannot initialise hermes browser: " + ex.getMessage(), ex);
}
}
});
}
private static void setStatusMessage(final String statusMessage) {
if (ui != null && ui.progressStatus != null && statusMessage != null) {
if (SwingUtilities.isEventDispatchThread()) {
ui.progressStatus.setStatus(statusMessage);
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ui.progressStatus.setStatus(statusMessage);
}
});
}
}
}
private ActionFactory actionFactory = new ActionFactory(this);
private ActionsPanel actionsPane;
private DocumentPane browserPane;
//
// Structure for this window
private JythonDockableFrame jythonFrame;
private BrowserTreeDockableFrame browserTreePane;
private Context context;
private String currentConfig;
private UIMessageSink defaultMessageSink;
private boolean firstLoad = true;
private File lastOpenConfigDirectory;
private File lastUploadDirectory;
//
// Hermes related stuff
private HermesLoader loader;
private JMenuBar menuBar;
private ProgressStatusBarItem progressStatus;
//
// Standard contents
private Map<String, WatchDockableFrame> queueWatchFrames = new HashMap<String, WatchDockableFrame>();
private HermesRepositoryManager repManager;
private StatusBar statusBar;
private DockableToolPanel toolsPane;
//
// Listeners...
private Set<DocumentComponentListener> documentComponentListeners = new HashSet<DocumentComponentListener>();
private Set<ListSelectionListener> messageSelectionListeners = new HashSet<ListSelectionListener>();
/**
* Start the GUI up....
*/
public HermesBrowser(String arg0) throws HeadlessException {
super(arg0);
// Funnell interesting messages onto the UI...
defaultMessageSink = new UIMessageSink() {
/*
* (non-Javadoc)
*
* @see hermes.browser.UIMessageSink#add(java.lang.String)
*/
public void add(String message) {
setStatusMessage(message);
}
/*
* (non-Javadoc)
*
* @see hermes.browser.UIMessageSink#add(java.lang.StringBuffer)
*/
public void add(StringBuffer message) {
setStatusMessage(message.toString());
}
};
// Listen to asynchronous tasks...
TaskSupport.addGlobalListener(new HermesBrowserTaskListener(this));
}
/**
* A repository manager monitors a directory for XML files containing JMS
* messages.
*
* @return
*/
public HermesRepositoryManager getRepositoryManager() {
return repManager;
}
/**
* Register that the user has created a new DestinationConfig, i.e. queue or
* topic in the main tree.
*
* @param hermes
* @param dConfig
* @throws JMSException
*/
public void addDestinationConfig(Hermes hermes, DestinationConfig dConfig) throws JMSException {
loader.addDestinationConfig(hermes, dConfig);
}
/**
* Add a listener for messages selected in a browse document. The listener
* will be added to the currently active table and removed when its
* deactivated or closed.
*
* @param listener
*/
public void addMessageSelectionListener(ListSelectionListener listener) {
messageSelectionListeners.add(listener);
}
/**
* Add a listener to any document component that gets created in the future.
*
* @param listener
*/
public void addDocumentComponentListener(DocumentComponentListener listener) {
documentComponentListeners.add(listener);
}
public int getSendPersistence() {
return DeliveryMode.PERSISTENT;
}
/**
* Sets the configuration URL.
*
* @param currentConfig
*/
public void setCurrentConfig(String currentConfig) {
this.currentConfig = currentConfig;
}
/**
* Add an BrowserAction to the document pane, registering the required
* listeners and giving it focus.
*
* @param action
*/
public void addDocumentComponent(final DocumentComponent document) {
log.debug("addDocument() name=" + document.getName());
if (getDocumentPane().isDocumentOpened(document.getName())) {
DocumentComponent existing = getDocumentPane().getDocument(document.getName());
if (document != existing) {
getDocumentPane().closeDocument(document.getName());
}
}
//
// Add/remove listeners for document lifecycle.
for (final DocumentComponentListener listener : documentComponentListeners) {
document.addDocumentComponentListener(listener);
}
document.addDocumentComponentListener(AutoRefreshCheckBox.getInstance());
document.addDocumentComponentListener(new DocumentComponetListenerSupport() {
@Override
public void documentComponentClosed(DocumentComponentEvent arg0) {
for (final DocumentComponentListener listener : documentComponentListeners) {
document.removeDocumentComponentListener(listener);
}
document.removeDocumentComponentListener(AutoRefreshCheckBox.getInstance());
}
});
//
// Add/remove listeners for navigation control
if (document instanceof NavigableComponent) {
final NavigableComponent component = (NavigableComponent) document;
for (final ListSelectionListener listener : messageSelectionListeners) {
component.getListSelectionModel().addListSelectionListener(listener);
}
document.addDocumentComponentListener(new DocumentComponetListenerSupport() {
@Override
public void documentComponentClosed(DocumentComponentEvent arg0) {
for (final ListSelectionListener listener : messageSelectionListeners) {
component.getListSelectionModel().removeListSelectionListener(listener);
}
}
});
}
getDocumentPane().openDocument(document);
getDocumentPane().setActiveDocument(document.getName());
}
/**
* Create a new dockable panel for watching all the queues configured on the
* given Hermes.
*
* @param watchId
* @param hermes
*/
public synchronized void addOrCreateWatch(String watchId, Hermes hermes) {
WatchDockableFrame frame = null;
if (queueWatchFrames.containsKey(watchId)) {
frame = queueWatchFrames.get(watchId);
} else {
WatchConfig wConfig = HermesBrowser.getConfigDAO().createWatchConfig();
wConfig.setId(watchId);
frame = createWatch(wConfig);
}
frame.addWatch(hermes);
}
/**
* Create/add the given destination to the new/existing watch panel.
*
* @param watchId
* @param hermes
* @param destination
*/
public synchronized void addOrCreateWatch(String watchId, Hermes hermes, DestinationConfig destination) {
WatchDockableFrame frame = null;
if (queueWatchFrames.containsKey(watchId)) {
frame = queueWatchFrames.get(watchId);
} else {
WatchConfig wConfig = HermesBrowser.getConfigDAO().createWatchConfig();
wConfig.setId(watchId);
frame = createWatch(wConfig);
}
DestinationConfig dConfig = HermesBrowser.getConfigDAO().duplicateForWatch(destination, hermes);
frame.addWatch(hermes.getId(), dConfig);
}
/**
* Backup the configuration into <config>.backup.
*
* @throws HermesException
*/
public void backupConfig() throws HermesException {
loader.backup();
}
/**
* Close all the watch panel.
*/
private void closeWatches() {
for (final Map.Entry<String, WatchDockableFrame> entry : queueWatchFrames.entrySet()) {
final WatchDockableFrame frame = entry.getValue();
frame.close();
getDockingManager().removeFrame(entry.getKey());
}
}
/**
* Create a new Watch dockable frame from the given watch configuration and
* add it to the docking manager and the XML configuration.
*
* @param watchConfig
*/
private WatchDockableFrame createWatch(final WatchConfig wConfig) {
final WatchDockableFrame frame = new WatchDockableFrame(wConfig);
queueWatchFrames.put(wConfig.getId(), frame);
frame.addDockableFrameListener(new DockableFrameAdapter() {
public void dockableFrameHidden(DockableFrameEvent arg0) {
log.debug("watch frame " + wConfig.getId() + " removed, clearing up");
try {
getConfig().getWatch().remove(wConfig);
queueWatchFrames.remove(wConfig.getId());
} catch (HermesException ex) {
Hermes.ui.getDefaultMessageSink().add("Unable to remove watch " + wConfig.getId() + " from configuration: " + ex.getMessage());
}
getDockingManager().removeFrame(wConfig.getId());
frame.close();
}
});
getDockingManager().addFrame(frame);
frame.setVisible(true);
try {
getConfig().getWatch().add(wConfig);
} catch (HermesException ex) {
Hermes.ui.getDefaultMessageSink().add("Unable to add watch " + wConfig.getId() + " to configuration: " + ex.getMessage());
}
frame.updateNow();
return frame;
}
/**
* Get the (inappopriately named) action factory to create long running
* browse tasks.
*
* @return
*/
public ActionFactory getActionFactory() {
return actionFactory;
}
/**
* Get the panal containing the long running actions (tasks).
*
* @return
*/
public ActionsPanel getActionsPanel() {
return actionsPane;
}
/**
* Get the configuration tree of sessions, contexts etc.
*
* @return
*/
public BrowserTree getBrowserTree() {
return browserTreePane.getBrowserTree();
}
public Context createContext(String id) throws JMSException, NamingException, InvocationTargetException, IOException, IllegalAccessException,
NoSuchMethodException {
final NamingConfig config = getBrowserTree().getBrowserModel().getNamingConfigTreeNode(id).getConfig();
final JNDIContextFactory factory = new JNDIContextFactory(config);
return factory.createContext();
}
/**
* Get the current configuration model.
*
* @return
* @throws HermesException
*/
public HermesConfig getConfig() throws HermesException {
return loader.getConfig();
}
/**
* Get the current context of configured Hermes instances.
*
* @return
*/
public Context getContext() {
return context;
}
/**
* Get the URL of the current configuration.
*
* @return
*/
public String getCurrentConfigURL() {
if (currentConfig == null) {
String rval = System.getProperty("hermes");
if (rval == null) {
File dotHermes = new File(JVMUtils.getUserHome() + File.separator + ".hermes");
if (!dotHermes.exists()) {
if (dotHermes.mkdir()) {
log.debug("created new directory: " + dotHermes.getAbsolutePath());
} else {
log.error("could not create directory: " + dotHermes.getAbsolutePath());
log.error("properties set are listed to stdout.");
System.getProperties().list(System.out);
System.exit(1);
}
}
File hermesXML = new File(dotHermes, "hermes-config.xml");
try {
if (!hermesXML.exists()) {
hermesXML.createNewFile();
InputStream istream = getClass().getClassLoader().getResourceAsStream("hermes/bootstrap/default-hermes-config.xml"); // ClassLoader.getSystemResourceAsStream("hermes/bootstrap/default-hermes-config.xml");
OutputStream ostream = new FileOutputStream(hermesXML);
int i;
while ((i = istream.read()) != -1) {
ostream.write(i);
}
ostream.close();
log.debug("bootstrapped empty config to " + hermesXML.getPath());
}
return hermesXML.toURI().getPath();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return null;
} else {
return rval;
}
} else {
return currentConfig;
}
}
/**
* Get the sink for informative messages during tasks.
*/
public UIMessageSink getDefaultMessageSink() {
return defaultMessageSink;
}
/**
* Get the document pane where queue/topic/context browses.
*
* @return
*/
public DocumentPane getDocumentPane() {
return browserPane;
}
/**
* Get the current loader used to create Hermes instances from the XML.
*
* @return
*/
public HermesLoader getLoader() {
return loader;
}
/**
* Gets the maximum number of messages to be displayed in a message browse
* table, -1 means show them all which could get a bit memory hungry.
*
* @return
* @throws HermesException
*/
public int getMaxMessagesInBrowserPane() throws HermesException {
return (loader.getConfig().getMaxMessagesInBrowserPane() == 0) ? DEFAULT_MAX_CACHED_MESSAGES : loader.getConfig().getMaxMessagesInBrowserPane();
}
public long getQueueBrowseConsumerTimeout() throws HermesException {
return (loader.getConfig().getQueueBrowseConsumerTimeout() == 0) ? DEFAULT_QUEUE_BROWSE_CONSUMER_TIMEOUT : loader.getConfig()
.getQueueBrowseConsumerTimeout();
}
/**
* Gets the repository manager for XML message files.
*
* @return
*/
public HermesRepositoryManager getMessageRepository() {
return repManager;
}
/**
* Get the threadpool to dispatch long running tasks to.
*/
public ThreadPool getThreadPool() {
return ThreadPool.get();
}
/**
* Get the profile name to save/load layout configuration with.
*
* @return
*/
public String getUserProfileName() {
return USER_PROFILE_NAME;
}
/**
* Get the watch frame for the give name.
*
* @return Returns the queueWatchPane.
*/
public WatchDockableFrame getWatchFrame(String id) {
return (WatchDockableFrame) queueWatchFrames.get(id);
}
/**
* Initialisation of non-GUI components - can be run on any thread.
*
* @throws NamingException
* @throws JMSException
*/
private void init() throws NamingException, JMSException, IOException {
// Set up the repository manager
HermesConfig config = (HermesConfig) context.lookup(HermesContext.CONFIG);
if (config.getMessageFilesDir() == null) {
config.setMessageFilesDir("./messages");
}
File repDir = new File(TextUtils.replaceClasspathVariables(config.getMessageFilesDir()));
try {
loader.save();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
if (!repDir.exists()) {
repDir.mkdir();
}
repManager = new FileRepositoryManager(repDir, 5000);
repManager.addRepositoryListener((BrowserTreeModel) getBrowserTree().getModel());
log.debug("setting maxThreadPoolSize");
if (config.getMaxThreadPoolSize() == 0) {
config.setMaxThreadPoolSize(1);
}
ThreadPool.get().setThreads(config.getMaxThreadPoolSize());
}
private void initJIDE() throws UnsupportedLookAndFeelException, ClassNotFoundException, InstantiationException, IllegalAccessException {
try {
LookAndFeelFactory.installJideExtension();
} catch (IllegalArgumentException e) {
log.error("l&f incompatible with JIDE, trying metal: " + e.getMessage(), e);
UIManager.setLookAndFeel(new MetalLookAndFeel());
LookAndFeelFactory.installJideExtension();
}
ObjectConverterManager.initDefaultConverter();
CellEditorManager.initDefaultEditor();
CellRendererManager.initDefaultRenderer();
ObjectComparatorManager.initDefaultComparator();
LookAndFeelFactory.UIDefaultsCustomizer uiDefaultsCustomizer = new LookAndFeelFactory.UIDefaultsCustomizer() {
public void customize(UIDefaults defaults) {
Map painter = (Map) defaults.get("Theme.painter");
// ThemePainter painter = (ThemePainter)
// defaults.get("Theme.painter");
defaults.put("OptionPaneUI", "com.jidesoft.plaf.basic.BasicJideOptionPaneUI");
defaults.put("OptionPane.showBanner", Boolean.FALSE); // show
// banner
// or
// not.
// default
// is
// true
defaults.put("OptionPane.bannerBackgroundDk", painter.get("OptionPane.bannerBackgroundDk"));
defaults.put("OptionPane.bannerBackgroundLt", painter.get("OptionPane.bannerBackgroundLt"));
defaults.put("OptionPane.bannerBackgroundDirection", Boolean.TRUE); // default
// is
// true
// optionally, you can set a Paint object for BannerPanel. If
// so, the three UIDefaults related to banner background above
// will be ignored.
defaults.put("OptionPane.bannerBackgroundPaint", null);
defaults.put("OptionPane.buttonAreaBorder", BorderFactory.createEmptyBorder(6, 6, 6, 6));
defaults.put("OptionPane.buttonOrientation", new Integer(SwingConstants.RIGHT));
}
};
uiDefaultsCustomizer.customize(UIManager.getDefaults());
}
/**
* Initialisation of GUI components, must be run on the Swing dispatch
* thread.
*
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws UnsupportedLookAndFeelException
* @throws HermesException
*/
private void initUI() throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException, HermesException {
if (System.getProperty("swing.defaultlaf") == null) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
/**
* http://hermesjms.com/jira/browse/HJMS-16 I've not implemented
* this fully as the L&F class name is not all we need to
* persist, JIDE seems to add in lots of extension stuff and I
* don't see how to persist/restor them yet. if
* (TextUtils.isEmpty(getConfig().getLookAndFeel())) {
* UIManager.
* setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); }
* else { UIManager.setLookAndFeel(getConfig().getLookAndFeel())
* ; }
*/
} catch (Throwable e) {
log.error("cannot load l&f, trying metal: " + e.getMessage(), e);
UIManager.setLookAndFeel(new MetalLookAndFeel());
}
} else {
UIManager.setLookAndFeel(System.getProperty("swing.defaultlaf"));
}
if (getConfig().isEnableJython() && jythonFrame == null) {
jythonFrame = new JythonDockableFrame();
getDockingManager().addFrame(jythonFrame);
}
if (!getConfig().isEnableJython() && jythonFrame != null) {
getDockingManager().removeFrame(jythonFrame.getKey());
jythonFrame = null;
}
CellEditorManager.registerEditor(Domain.class, new DomainCellEditor());
CellEditorManager.registerEditor(SelectorImpl.class, new SelectorImplCellEditor());
CellEditorManager.registerEditor(File.class, new DirectoryCellEditor(), DirectoryCellEditor.CONTEXT);
CellEditorManager.registerEditor(String.class, new ClasspathIdCellEdtitor(), ClasspathIdCellEdtitor.CONTEXT);
CellEditorManager.registerEditor(Hermes.class, new HermesCellEditor());
ObjectComparatorManager.registerComparator(Date.class, new DateComparator());
ObjectComparatorManager.registerComparator(Integer.class, new IntegerComparator());
ObjectComparatorManager.registerComparator(Long.class, new LongComparator());
DefaultSyntaxKit.initKit();
browserPane = new MainDocumentPane();
// Shows us the memory usage and lets the user GC
MemoryStatusBarItem memoryStatusBar = new MemoryStatusBarItem();
memoryStatusBar.setPreferredWidth(100);
// General informative messages go here..
progressStatus = new ProgressStatusBarItem();
statusBar = new StatusBar();
statusBar.add(progressStatus, JideBoxLayout.VARY);
statusBar.add(new TimeStatusBarItem(), JideBoxLayout.FLEXIBLE);
statusBar.add(memoryStatusBar, JideBoxLayout.FLEXIBLE);
// The tools panel includes the running tasks, Jython console and log
// console.
actionsPane = new ActionsPanel();
toolsPane = new DockableToolPanel();
toolsPane.addToolPanel("Tasks", new JideScrollPane(actionsPane));
toolsPane.addToolPanel("Log", new Log4JOutputViewer(""));
browserTreePane = new BrowserTreeDockableFrame();
browserTreePane.setLoader(loader);
// Get the menu bar initialised...
setJMenuBar(new MenuBar(this));
setIconImage(IconCache.getIcon("hermes.icon").getImage());
//
// Layout management initialisation
getDockingManager().setUsePref(false);
getDockingManager().setProfileKey(USER_PROFILE_NAME);
getDockingManager().setInitSplitPriority(DefaultDockingManager.SPLIT_SOUTH_NORTH_EAST_WEST);
getDockingManager().getWorkspace().add(browserPane, BorderLayout.CENTER);
getDockingManager().addFrame(browserTreePane);
getDockingManager().addFrame(toolsPane);
getDockableBarManager().addDockableBar(new MainToolBar());
getDockableBarManager().addDockableBar(new MessageToolBar());
getDockableBarManager().addDockableBar(new ConfigurationToolBar());
getDockableBarManager().addDockableBar(new JNDIToolBar());
getContentPane().add(statusBar, BorderLayout.AFTER_LAST_LINE);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
toFront();
setStatusMessage("Ready");
SplashScreen.hide();
//
// Raise the swing thread to max priority
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
}
});
}
/**
* Bit of a hack this one it tells us if there is a some kind of browse task
* running and the user has selected one or more messages in the tree.
*
* @return
*/
public boolean isBrowseActionSelected() {
if (browserPane.getActiveDocument() instanceof BrowserAction) {
final BrowserAction action = (BrowserAction) browserPane.getActiveDocument();
if (action.getSelectedMessages().size() > 0) {
return true;
}
}
return false;
}
/**
* Initialise the underlying Hermes that we're gonna do all our work with
*
* @throws HermesException
* @throws NamingException
*/
public void loadConfig() throws NamingException, HermesException {
Properties props = new Properties();
Context oldContext = context;
HermesConfig oldConfig = null;
props.put(Context.INITIAL_CONTEXT_FACTORY, HermesInitialContextFactory.class.getName());
props.put(Context.PROVIDER_URL, getCurrentConfigURL());
props.put("hermes.loader", JAXBHermesLoader.class.getName());
log.debug("props=" + props);
Iterator listeners = null;
if (loader != null) {
listeners = loader.getConfigurationListeners();
oldConfig = loader.getConfig();
}
if (oldConfig != null) {
Set naming = new HashSet();
naming.addAll(oldConfig.getNaming());
for (Iterator iter = naming.iterator(); iter.hasNext();) {
NamingConfig oldNaming = (NamingConfig) iter.next();
loader.notifyNamingRemoved(oldNaming);
}
}
context = new InitialContext(props);
loader = (HermesLoader) context.lookup(HermesContext.LOADER);
if (listeners != null) {
while (listeners.hasNext()) {
loader.addConfigurationListener((HermesConfigurationListener) listeners.next());
}
}
if (oldContext != null) {
for (NamingEnumeration iter = oldContext.listBindings(""); iter.hasMoreElements();) {
Binding binding = (Binding) iter.next();
try {
if (oldContext.lookup(binding.getName()) instanceof Hermes) {
Hermes hermes = (Hermes) oldContext.lookup(binding.getName());
Hermes newHermes = null;
try {
newHermes = (Hermes) context.lookup(hermes.getId());
} catch (NamingException e) {
// NOP
}
if (newHermes == null) {
loader.notifyHermesRemoved(hermes);
}
}
} catch (NamingException ex) {
// NOP
}
}
}
if (!firstLoad) {
closeWatches();
final ArrayList tmpList = new ArrayList();
tmpList.addAll(loader.getConfig().getWatch());
loader.getConfig().getWatch().clear();
for (Iterator iter = tmpList.iterator(); iter.hasNext();) {
WatchConfig wConfig = (WatchConfig) iter.next();
createWatch(wConfig);
}
}
setTitle("HermesJMS - " + TextUtils.crumble(getCurrentConfigURL(), 100));
}
/**
* Replace all the destinations that are on a Hermes configuration, used
* after a discover has occured. Not the best codepath.
*
* @param hermes
* @param dConfigs
* @throws JMSException
*/
public void replaceDestinationConfigs(Hermes hermes, Collection dConfigs) throws JMSException {
loader.replaceDestinationConfigs(hermes, dConfigs);
}
/**
* Restore the configuration from a backup.
*
* @throws HermesException
*/
public void restoreConfig() throws HermesException {
loader.restore();
}
/**
* Save the current configuration.
*
* @throws HermesException
*/
public void saveConfig() throws HermesException {
if (!isRestrictedWithWarning()) {
loader.save();
}
}
public void showInformationDialog(final String message) {
Runnable r = new Runnable() {
public void run() {
JOptionPane.showMessageDialog(HermesBrowser.this, message, "Information", JOptionPane.INFORMATION_MESSAGE);
}
};
if (SwingUtilities.isEventDispatchThread()) {
r.run();
} else {
SwingUtilities.invokeLater(r);
}
}
/**
* Show an error dialog with the given message, will dispatch to the evet
* thread if needed.
*
* @param message
*/
public void showErrorDialog(final String message) {
Runnable r = new Runnable() {
public void run() {
JOptionPane.showMessageDialog(HermesBrowser.this, message, "Error", JOptionPane.ERROR_MESSAGE);
}
};
if (SwingUtilities.isEventDispatchThread()) {
r.run();
} else {
SwingUtilities.invokeLater(r);
}
}
/**
* Show an error message with the message from the exception and also log it
* to Log4j.
*
* @param message
* @param t
*/
public void showErrorDialog2(final String message, final Throwable t) {
log.error(t.getMessage(), t);
Runnable r = new Runnable() {
public void run() {
if (t instanceof PyException) {
PyException pyT = (PyException) t;
JOptionPane.showMessageDialog(HermesBrowser.this, message + ": " + pyT.traceback.dumpStack(), "Error", JOptionPane.ERROR_MESSAGE);
} else {
JOptionPane.showMessageDialog(HermesBrowser.this, message + ": " + t.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
};
if (SwingUtilities.isEventDispatchThread()) {
r.run();
} else {
SwingUtilities.invokeLater(r);
}
}
public void showErrorDialog(final String message, final Throwable t) {
Runnable r = new Runnable() {
public void run() {
String detail = null;
if (t instanceof PyException) {
StringBuffer s = new StringBuffer();
PyException pyT = (PyException) t;
pyT.traceback.dumpStack(s);
detail = s.toString();
} else {
StringWriter s = new StringWriter();
PrintWriter p = new PrintWriter(s);
t.printStackTrace(p);
detail = s.toString();
}
JideOptionPane optionPane = new JideOptionPane(message, JOptionPane.ERROR_MESSAGE, JideOptionPane.CLOSE_OPTION,
UIManager.getIcon("OptionPane.errorIcon"));
optionPane.setTitle(message);
if (detail != null) {
optionPane.setDetails(detail);
}
JDialog dialog = optionPane.createDialog(HermesBrowser.this, "Error");
dialog.setResizable(true);
dialog.pack();
dialog.setVisible(true);
}
};
if (SwingUtilities.isEventDispatchThread()) {
r.run();
} else {
SwingUtilities.invokeLater(r);
}
}
/**
* Show an error message with the message from the exception and also log it
* to Log4j.
*
* @param message
* @param t
*/
public void showErrorDialog(Throwable t) {
showErrorDialog("Error: ", t);
}
/**
* Is this Hermes running in the restricted mode? If so then a dialog is
* show telling the user they are not permissioned to do the action.
*
* @return
*/
public boolean isRestrictedWithWarning() {
if (isRestricted()) {
showErrorDialog("You do not have permissions to perform this action.");
}
return isRestricted();
}
/**
* Are message stores disabled?
*
* @return
*/
public boolean isMessageStoresDisabled() {
return System.getProperty(SystemProperties.DISABLE_MESSAGE_STORES) != null;
}
/**
* Is this Hermes running in the restricted mode?
*
* @return
*/
public boolean isRestricted() {
return restricted;
}
public CommandBar createDockableBar(String name) {
return new CommandBar(name);
}
public Hermes getHermes() {
if (getDocumentPane().getActiveDocument() instanceof BrowserAction) {
BrowserAction action = (BrowserAction) getDocumentPane().getActiveDocument();
return action.getHermes();
} else {
return null;
}
}
public static void browseQueue(String hermesId, String queue) throws NamingException, JMSException {
Hermes hermes = (Hermes) HermesBrowser.getBrowser().getContext().lookup(hermesId);
DestinationConfig config = hermes.getDestinationConfig(queue, Domain.QUEUE);
HermesBrowser.getBrowser().getActionFactory().createQueueBrowseAction(hermes, config);
}
public void setFIXPrettyPrinter(FIXPrettyPrinter printer) {
FIXUtils.setPrettyPrinter(printer);
}
public FIXPrettyPrinter getFIXPrettyPrinter() {
return FIXUtils.getPrettyPrinter() == null ? FIXUtils.getDefaultPrettyPrinter() : FIXUtils.getPrettyPrinter();
}
public Collection<Message> getSelectedMessages() {
if (getDocumentPane().getActiveDocument() instanceof BrowserAction) {
BrowserAction action = (BrowserAction) getDocumentPane().getActiveDocument();
return action.getSelectedMessages();
} else {
return Collections.EMPTY_LIST;
}
}
public MessageStoreBrowserAction getOpenStoreBrowser(MessageStore store) {
for (int d = 0 ; d < HermesBrowser.getBrowser().getDocumentPane().getDocumentCount() ; d++) {
DocumentComponent doc = HermesBrowser.getBrowser().getDocumentPane().getDocumentAt(d) ;
if (doc instanceof MessageStoreBrowserAction) {
MessageStoreBrowserAction sBrowser = (MessageStoreBrowserAction) doc ;
if (sBrowser.getMessageStore().equals(store)) {
return sBrowser ;
}
}
}
return null ;
}
public QueueBrowseAction getOpenQueueBrowser(DestinationConfig config) {
for (int d = 0 ; d < HermesBrowser.getBrowser().getDocumentPane().getDocumentCount() ; d++) {
DocumentComponent doc = HermesBrowser.getBrowser().getDocumentPane().getDocumentAt(d) ;
if (doc instanceof QueueBrowseAction) {
QueueBrowseAction qBrowser = (QueueBrowseAction) doc ;
if (qBrowser.getDestinationConfig().equals(config)) {
return qBrowser ;
}
}
}
return null ;
}
}