/* * Copyright 2003,2004 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.renderers.fix; import hermes.fix.FIXMessage; import hermes.fix.FIXUtils; import hermes.fix.quickfix.QuickFIXMessage; import hermes.fix.quickfix.QuickFIXMessageCache; import hermes.renderers.AbstractMessageRenderer; import hermes.util.MessageUtils; import java.io.IOException; import javax.jms.BytesMessage; import javax.jms.JMSException; import javax.jms.MapMessage; import javax.jms.Message; import javax.jms.ObjectMessage; import javax.jms.StreamMessage; import javax.jms.TextMessage; import javax.swing.JComponent; import javax.swing.JScrollPane; import javax.swing.JTextArea; import org.apache.commons.collections.map.LRUMap; import org.apache.log4j.Logger; /** * Renderer for FIX messages carried in BytesMessage or TextMessage. * * @author colincrist@hermesjms.com last changed by: $Author: colincrist $ * @version $Id: FIXMessageRenderer.java,v 1.6 2006/04/28 09:59:37 colincrist * Exp $ */ public class FIXMessageRenderer extends AbstractMessageRenderer { private static final Logger log = Logger.getLogger(FIXMessageRenderer.class); private static final String MESSAGE_CACHE = "messageCache"; private static final String MESSAGE_CACHE_INFO = "The number of panels to cache - can speed up the user interface when switching between messags"; private static final String VALUE_WITH_ENUM = "displayValueWithEnum"; private static final String VALUE_WITH_ENUM_INDO = "If true displays any enumeration values along with the descriptive text"; private static final String SHOW_HEADER_AND_TRAINER = "displayHeaderAndTrailer"; private static final String SHOW_HEADER_AND_TRAINER_INFO = "Display header and trailer fields"; private final QuickFIXMessageCache cache = new QuickFIXMessageCache(32); private LRUMap panelCache; public class MyConfig extends AbstractMessageRenderer.BasicConfig { private int messageCache = 100; private boolean displayValueWithEnum = true; private boolean displayHeaderAndTrailer = true; private String name; @Override public String getName() { return name; } @Override public void setName(String name) { this.name = name; } @Override public String getPropertyDescription(String propertyName) { if (propertyName.equals(MESSAGE_CACHE)) { return MESSAGE_CACHE_INFO; } if (propertyName.equals(VALUE_WITH_ENUM)) { return VALUE_WITH_ENUM_INDO; } if (propertyName.equals(SHOW_HEADER_AND_TRAINER)) { return SHOW_HEADER_AND_TRAINER_INFO; } return propertyName; } public int getMessageCache() { return messageCache; } public void setMessageCache(int messageCache) { this.messageCache = messageCache; } public boolean getDisplayValueWithEnum() { return displayValueWithEnum; } public void setDisplayValueWithEnum(boolean displayValueWithEnum) { this.displayValueWithEnum = displayValueWithEnum; } public boolean getDisplayHeaderAndTrailer() { return displayHeaderAndTrailer; } public void setDisplayHeaderAndTrailer(boolean displayHeaderAndTrailer) { this.displayHeaderAndTrailer = displayHeaderAndTrailer; } } protected JComponent handleObjectMessage(final ObjectMessage objectMessage) throws JMSException { return null; } protected JComponent handleMapMessage(MapMessage mapMessage) throws JMSException { return null; } protected JComponent handleBytesMessage(BytesMessage bytesMessage) throws JMSException, IOException, ClassNotFoundException { try { bytesMessage.reset(); final byte[] bytes = MessageUtils.asBytes(bytesMessage); return createComponent(new QuickFIXMessage(cache, bytes)); } finally { bytesMessage.reset(); } } protected JComponent handleStreamMessage(StreamMessage streamMessage) throws JMSException { return null; } protected JComponent handleTextMessage(final TextMessage textMessage) throws JMSException { String text = textMessage.getText(); return createComponent(new QuickFIXMessage(cache, text.getBytes())); } protected JComponent createComponent(FIXMessage message) { try { final MyConfig currentConfig = (MyConfig) getConfig(); return FIXUtils.createView(message, currentConfig.getDisplayHeaderAndTrailer(), currentConfig.getDisplayValueWithEnum()); } catch (Exception e) { log.error(e.getMessage(), e); } log.debug("message is not a valid FIX message, ignoring"); return null; } /* * (non-Javadoc) * * @see hermes.browser.MessageRenderer#render(javax.jms.Message) */ @Override public JComponent render(JScrollPane parent, Message m) { try { JComponent rval = null; if (getPanelMap().containsKey(m)) { rval = (JComponent) getPanelMap().get(m); } else { if (m instanceof TextMessage) { rval = handleTextMessage((TextMessage) m); } else if (m instanceof javax.jms.ObjectMessage) { rval = handleObjectMessage((ObjectMessage) m); } else if (m instanceof javax.jms.MapMessage) { rval = handleMapMessage((MapMessage) m); } else if (m instanceof BytesMessage) { rval = handleBytesMessage((BytesMessage) m); } else if (m instanceof StreamMessage) { rval = handleStreamMessage((StreamMessage) m); } if (rval != null) { getPanelMap().put(m, rval); } } return rval; } catch (Throwable ex) { final JTextArea textArea = new JTextArea(); textArea.setEditable(false); textArea.setText("Unable to display message: " + ex.getMessage()); log.error(ex.getMessage(), ex); return textArea; } } /* * (non-Javadoc) * * @see hermes.browser.MessageRenderer#createConfig() */ @Override public Config createConfig() { return new MyConfig(); } public synchronized LRUMap getPanelMap() { if (panelCache == null) { final MyConfig currentConfig = (MyConfig) getConfig(); panelCache = new LRUMap(currentConfig.getMessageCache()); } return panelCache; } @Override public boolean canRender(Message message) { try { return FIXUtils.isFIX(message); } catch (JMSException ex) { log.error("during FIXMessage.isValid(): " + ex.getMessage(), ex); return false; } } @Override public String getDisplayName() { return "FIX"; } }