001    /******************************************************************************
002     * Copyright (C) MActor Developers. All rights reserved.                        *
003     * ---------------------------------------------------------------------------*
004     * This file is part of MActor.                                               *
005     *                                                                            *
006     * MActor is free software; you can redistribute it and/or modify             *
007     * it under the terms of the GNU General Public License as published by       *
008     * the Free Software Foundation; either version 2 of the License, or          *
009     * (at your option) any later version.                                        *
010     *                                                                            *
011     * MActor is distributed in the hope that it will be useful,                  *
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
014     * GNU General Public License for more details.                               *
015     *                                                                            *
016     * You should have received a copy of the GNU General Public License          *
017     * along with MActor; if not, write to the Free Software                      *
018     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA *
019     ******************************************************************************/
020    package org.mactor.ui.gui;
021    
022    import java.awt.BorderLayout;
023    import java.awt.Component;
024    import java.awt.Dimension;
025    import java.util.ArrayList;
026    import java.util.Calendar;
027    
028    import javax.swing.Icon;
029    import javax.swing.JPanel;
030    import javax.swing.JScrollPane;
031    import javax.swing.JTable;
032    import javax.swing.ListSelectionModel;
033    import javax.swing.SwingUtilities;
034    import javax.swing.table.AbstractTableModel;
035    import javax.swing.table.DefaultTableCellRenderer;
036    
037    import org.apache.log4j.Appender;
038    import org.apache.log4j.AppenderSkeleton;
039    import org.apache.log4j.Level;
040    import org.apache.log4j.LogManager;
041    import org.apache.log4j.spi.LoggingEvent;
042    import org.mactor.brokers.MessageBrokerManager.MessageInfo;
043    import org.mactor.brokers.MessageBrokerManager.MessageInfoListener;
044    import org.mactor.framework.MactorException;
045    
046    public class EventLogPanel extends JPanel {
047            private JTable table;
048            EventHistoryTableModel model = new EventHistoryTableModel();
049            public EventLogPanel() throws MactorException {
050                    super(new BorderLayout());
051                    LogManager.getLogger("org.mactor").addAppender(a);
052                    LogManager.getLogger("MactorIncomingMessage").addAppender(new MessageLogAppender(INCOMING_ICON));
053                    LogManager.getLogger("MactorIncomingResponse").addAppender(new MessageLogAppender(INCOMING_RESP_ICON));
054                    LogManager.getLogger("MactorOutgingMessage").addAppender(new MessageLogAppender(OUTGOING_ICON));
055                    LogManager.getLogger("MactorOutgingResponse").addAppender(new MessageLogAppender(OUTGOING_RESP_ICON));
056                    table = new JTable(model);
057                    table.getColumnModel().getColumn(0).setCellRenderer(new MessageTableCellRendere());
058                    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
059                    // summaryTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
060                    table.getColumnModel().getColumn(0).setMaxWidth(25);
061                    table.getColumnModel().getColumn(1).setMaxWidth(200);
062                    JScrollPane tableSp = new JScrollPane(table);
063                    tableSp.setPreferredSize(new Dimension(100, 100));
064                    add(tableSp, BorderLayout.CENTER);
065            }
066            MessageInfoListener miListener = new MessageInfoListener() {
067                    public void onMessageInfo(final MessageInfo messageInfo) {
068                            final Event event = new Event();
069                            event.message = messageInfo.getChannel() + (messageInfo.isResponse() ? " (response)" : "") + " : " + messageInfo.getArchivePath();
070                            event.time = GuiUtil.format(messageInfo.getCreatedTime());
071                            if (messageInfo.isIncoming()) {
072                                    if (messageInfo.isResponse())
073                                            event.icon = INCOMING_RESP_ICON;
074                                    else
075                                            event.icon = INCOMING_ICON;
076                            } else if (messageInfo.isResponse())
077                                    event.icon = OUTGOING_RESP_ICON;
078                            else
079                                    event.icon = OUTGOING_ICON;
080                            SwingUtilities.invokeLater(new Runnable() {
081                                    public void run() {
082                                            model.addEvent(event);
083                                    }
084                            });
085                    };
086            };
087            private class MessageLogAppender extends AppenderSkeleton {
088                    Icon icon;
089                    MessageLogAppender(Icon icon) {
090                            this.icon = icon;
091                    }
092                    @Override
093                    protected void append(LoggingEvent logEvent) {
094                            if (!logEvent.getLevel().isGreaterOrEqual(Level.INFO))
095                                    return;
096                            final Event event = new Event();
097                            event.message = logEvent.getMessage() + "";
098                            Calendar t = Calendar.getInstance();
099                            t.setTimeInMillis(logEvent.timeStamp);
100                            event.time = GuiUtil.format(t);
101                            event.icon = icon;
102                            SwingUtilities.invokeLater(new Runnable() {
103                                    public void run() {
104                                            model.addEvent(event);
105                                    }
106                            });
107                    }
108                    @Override
109                    public void close() {
110                    }
111                    @Override
112                    public boolean requiresLayout() {
113                            return false;
114                    }
115            }
116            Appender a = new AppenderSkeleton() {
117                    @Override
118                    protected void append(LoggingEvent logEvent) {
119                            if (!logEvent.getLevel().isGreaterOrEqual(Level.INFO))
120                                    return;
121                            final Event event = new Event();
122                            event.message = logEvent.getLocationInformation().getClassName() + " : " + logEvent.getMessage();
123                            Calendar t = Calendar.getInstance();
124                            t.setTimeInMillis(logEvent.getStartTime());
125                            event.time = GuiUtil.format(t);
126                            if (Level.INFO.equals(logEvent.getLevel()))
127                                    event.icon = INFO_ICON;
128                            else if (Level.WARN.equals(logEvent.getLevel()))
129                                    event.icon = WARN_ICON;
130                            else if (Level.ERROR.equals(logEvent.getLevel()))
131                                    event.icon = ERROR_ICON;
132                            SwingUtilities.invokeLater(new Runnable() {
133                                    public void run() {
134                                            model.addEvent(event);
135                                    }
136                            });
137                    }
138                    @Override
139                    public void close() {
140                    }
141                    @Override
142                    public boolean requiresLayout() {
143                            return false;
144                    }
145            };
146            public void stop() throws MactorException {
147                    // MessageBrokerManager.getInstance().removeMessageInfoListener(channel,
148                    // miListener);
149            }
150            private static final Icon ERROR_ICON = GuiUtil.loadIcon("/error_16.PNG");
151            private static final Icon INFO_ICON = GuiUtil.loadIcon("/info_16.PNG");
152            private static final Icon WARN_ICON = GuiUtil.loadIcon("/warning_16.PNG");
153            private static final Icon INCOMING_ICON = GuiUtil.loadIcon("/incoming_16.PNG");
154            private static final Icon INCOMING_RESP_ICON = GuiUtil.loadIcon("/incoming_resp_16.PNG");
155            private static final Icon OUTGOING_ICON = GuiUtil.loadIcon("/outgoing_16.PNG");
156            private static final Icon OUTGOING_RESP_ICON = GuiUtil.loadIcon("/outgoing_resp_16.PNG");
157            private class Event {
158                    Icon icon;
159                    String time;
160                    String message;
161                    public Event() {
162                    }
163                    public Event(Icon icon, String time, String message) {
164                            super();
165                            this.icon = icon;
166                            this.time = time;
167                            this.message = message;
168                    }
169            }
170            static final int MAX = 2000;
171            static final int HYST = 500;
172            private static class EventHistoryTableModel extends AbstractTableModel {
173                    ArrayList<Event> history = new ArrayList<Event>();
174                    String[] colums = new String[] { "", "Timestamp", "Message" };
175                    @Override
176                    public String getColumnName(int col) {
177                            return colums[col];
178                    }
179                    public void addEvent(Event event) {
180                            this.history.add(event);
181                            adjust();
182                            super.fireTableDataChanged();
183                    }
184                    final private void adjust() {
185                            if (this.history.size() > MAX)
186                                    this.history = new ArrayList<Event>(this.history.subList((history.size() - MAX) + HYST, history.size() - 1));
187                    }
188                    public int getColumnCount() {
189                            return colums.length;
190                    }
191                    public int getRowCount() {
192                            if (history == null)
193                                    return 0;
194                            return history.size();
195                    }
196                    public Object getValueAt(int row, int col) {
197                            if (history == null)
198                                    return null;
199                            Event event = history.get(history.size() - 1 - row);
200                            if (col == 0)
201                                    return event.icon;
202                            if (col == 1)
203                                    return event.time;
204                            if (col == 2)
205                                    return event.message;
206                            throw new RuntimeException("Invalid column '" + col + "'");
207                    }
208            }
209            public class MessageTableCellRendere extends DefaultTableCellRenderer {
210                    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
211                            if (value instanceof Icon)
212                                    setIcon((Icon) value);
213                            else
214                                    setIcon(null);
215                            setText(null);
216                            return this;
217                    }
218            }
219    }