001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2023 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jpos.ui.factory;
020
021import org.jdom2.Element;
022import org.jpos.ui.UI;
023import org.jpos.ui.UIFactory;
024import org.jpos.util.*;
025
026import javax.swing.*;
027import javax.swing.text.BadLocationException;
028import java.awt.*;
029import java.io.ByteArrayOutputStream;
030import java.io.PrintStream;
031
032/**
033 * @author Alejandro Revilla
034 *
035 * a log listener component
036 *
037 * i.e:
038 * <pre>
039 *  &lt;log-listener scrollable="true"
040 *      logger="Q2" font="fixed-normal-12"
041 *      max-events="100" max-lines="50" /&gt;
042 * </pre>
043 *
044 * @see org.jpos.ui.UIFactory
045 */
046public class LogListenerFactory implements UIFactory {
047    public JComponent create (UI ui, Element e) {
048        JTextArea textArea = new JTextArea (25, 80);
049        String font = e.getAttributeValue ("font");
050        if (font != null) 
051            textArea.setFont (Font.decode (font));
052        textArea.setBackground(Color.black);
053        textArea.setForeground(Color.white);
054        String logId = e.getAttributeValue ("logger", "Q2");
055        try {
056            int maxEvents = Integer.parseInt (
057                e.getAttributeValue ("max-events", "100")
058            );
059            int maxLines = Integer.parseInt (
060                e.getAttributeValue ("max-lines", "1000")
061            );
062            LogProducer logger = (LogProducer) NameRegistrar.get ("logger." + logId);
063            logger.addListener (
064                new Listener (logger, ui, textArea, maxEvents, maxLines)
065            );
066        } catch (NameRegistrar.NotFoundException ex) {
067            textArea.setText (ex.toString ());
068        }
069        return textArea;
070    }
071    public static class Listener implements LogListener, Runnable {
072        final LogProducer logger;
073        JTextArea text;
074        UI ui;
075        int cnt;
076        int maxEvents;
077        int maxLines;
078        public Listener 
079            (LogProducer logger, UI ui, JTextArea text, int maxEvents, int maxLines)
080        {
081            super ();
082            this.ui = ui;
083            this.text = text;
084            this.logger = logger;
085            this.cnt = 0;
086            this.maxEvents = maxEvents;
087            this.maxLines  = maxLines;
088            text.setEditable(false);
089        }
090        public void run () {
091            if (ui.isDestroyed ()) {
092                logger.removeListener (this);
093                text.setText ("");
094                return;
095            }
096            int lc = text.getLineCount ();
097            if (lc > maxLines) {
098                try {
099                    int startOffset = text.getLineStartOffset (maxLines);
100                    int endOffset = text.getLineEndOffset(lc-1);
101                    text.getDocument ().remove (startOffset, endOffset-startOffset);
102                } catch (BadLocationException ex) {
103                    text.setText (ex.toString());
104                }
105            }
106        }
107        public LogEvent log (LogEvent evt) {
108            if (ui.isDestroyed ()) {
109                SwingUtilities.invokeLater (this);
110                return evt;
111            }
112            ByteArrayOutputStream str = new ByteArrayOutputStream();
113            PrintStream ps = new PrintStream (str);
114            evt.dump (ps, "");
115            text.insert (str.toString(), 0);
116
117            if (++cnt % maxEvents == 0) {
118                SwingUtilities.invokeLater (this);
119            }
120            return evt;
121        }
122    }
123}
124