001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2026 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.q2.cli;
020
021import org.jpos.q2.CLICommand;
022import org.jpos.q2.CLIContext;
023import org.jpos.util.LogEvent;
024import org.jpos.util.LogListener;
025import org.jpos.util.Logger;
026import org.jpos.util.NameRegistrar;
027
028import java.io.PrintStream;
029import java.util.Date;
030import java.util.Iterator;
031import java.util.Map;
032
033/**
034 * CLI command that subscribes to one or more named loggers and streams their
035 * events to the terminal until the user presses Enter.
036 */
037public class TAIL implements CLICommand, LogListener {
038    /** Default constructor; no instance state to initialise. */
039    public TAIL() {}
040    PrintStream p;
041    CLIContext cli;
042    boolean ansi;
043
044    public void exec(CLIContext cli, String[] args) throws Exception {
045        this.p = new PrintStream(cli.getReader().getTerminal().output());
046        this.cli = cli;
047        this.ansi = false; // cli.getReader().getTerminal().isAnsiSupported();
048        if (args.length == 1) {
049            usage(cli);
050            return;
051        }
052        for (int i = 1; i < args.length; i++) {
053            try {
054                Logger logger = (Logger) NameRegistrar.get("logger." + args[i]);
055                logger.addListener(this);
056            } catch (NameRegistrar.NotFoundException e) {
057                cli.println("Logger " + args[i] + " not found -- ignored.");
058            }
059        }
060        // cli.getReader().readCharacter(new char[]{'q', 'Q'});
061        cli.getReader().readLine();
062        for (int i = 1; i < args.length; i++) {
063            try {
064                Logger logger = (Logger) NameRegistrar.get("logger." + args[i]);
065                logger.removeListener(this);
066            } catch (NameRegistrar.NotFoundException ignored) {
067                // NOPMD OK to happen
068            }
069        }
070    }
071
072    /**
073     * Prints command usage and lists the registered loggers.
074     *
075     * @param cli the CLI context to write to
076     */
077    public void usage(CLIContext cli) {
078        cli.println("Usage: tail [log-name] [log-name] ...");
079        showLoggers(cli);
080    }
081
082    public synchronized LogEvent log(LogEvent ev) {
083        if (p != null) {
084            Date d = new Date(System.currentTimeMillis());
085//            if (ansi)
086//                cli.getOutputStream().write(1); // BOLD
087            cli.println(
088              ev.getSource().getLogger().getName() +
089                ": " + ev.getRealm() + " " + d.toString() + "." + d.getTime() % 1000
090            );
091            ev.dump(p, " ");
092//            if (ansi)
093//                cli.getOutputStream().write(0); // OFF
094
095            p.flush();
096        }
097        return ev;
098    }
099
100    private void showLoggers(CLIContext cli) {
101        NameRegistrar nr = NameRegistrar.getInstance();
102        int maxw = 0;
103        Iterator iter = NameRegistrar.getAsMap().entrySet().iterator();
104        StringBuilder sb = new StringBuilder("available loggers:");
105        while (iter.hasNext()) {
106            Map.Entry entry = (Map.Entry) iter.next();
107            String key = (String) entry.getKey();
108            if (key.startsWith("logger.") && entry.getValue() instanceof Logger) {
109                sb.append(' ');
110                sb.append(key.substring(7));
111            }
112        }
113        cli.println(sb.toString());
114    }
115}
116