    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017
    018package org.apache.commons.net;
    019
    020import java.io.PrintStream;
    021import java.io.PrintWriter;
    022
    023/**
    024 * This is a support class for some of the example programs. It is a sample implementation of the ProtocolCommandListener interface which just prints out to a
    025 * specified stream all command/reply traffic.
    026 *
    027 * @since 2.0
    028 */
    029
    030public class PrintCommandListener implements ProtocolCommandListener {
    031    private final PrintWriter writer;
    032    private final boolean nologin;
    033    private final char eolMarker;
    034    private final boolean directionMarker;
    035
    036    /**
    037     * Create the default instance which prints everything.
    038     *
    039     * @param stream where to write the commands and responses e.g. System.out
    040     * @since 3.0
    041     */
    042    public PrintCommandListener(final PrintStream stream) {
    043        this(new PrintWriter(stream));
    044    }
    045
    046    /**
    047     * Create an instance which optionally suppresses login command text and indicates where the EOL starts with the specified character.
    048     *
    049     * @param stream        where to write the commands and responses
    050     * @param suppressLogin if {@code true}, only print command name for login
    051     *
    052     * @since 3.0
    053     */
    054    public PrintCommandListener(final PrintStream stream, final boolean suppressLogin) {
    055        this(new PrintWriter(stream), suppressLogin);
    056    }
    057
    058    /**
    059     * Create an instance which optionally suppresses login command text and indicates where the EOL starts with the specified character.
    060     *
    061     * @param stream        where to write the commands and responses
    062     * @param suppressLogin if {@code true}, only print command name for login
    063     * @param eolMarker     if non-zero, add a marker just before the EOL.
    064     *
    065     * @since 3.0
    066     */
    067    public PrintCommandListener(final PrintStream stream, final boolean suppressLogin, final char eolMarker) {
    068        this(new PrintWriter(stream), suppressLogin, eolMarker);
    069    }
    070
    071    /**
    072     * Create an instance which optionally suppresses login command text and indicates where the EOL starts with the specified character.
    073     *
    074     * @param stream        where to write the commands and responses
    075     * @param suppressLogin if {@code true}, only print command name for login
    076     * @param eolMarker     if non-zero, add a marker just before the EOL.
    077     * @param showDirection if {@code true}, add {@code "> "} or {@code "< "} as appropriate to the output
    078     *
    079     * @since 3.0
    080     */
    081    public PrintCommandListener(final PrintStream stream, final boolean suppressLogin, final char eolMarker, final boolean showDirection) {
    082        this(new PrintWriter(stream), suppressLogin, eolMarker, showDirection);
    083    }
    084
    085    /**
    086     * Create the default instance which prints everything.
    087     *
    088     * @param writer where to write the commands and responses
    089     */
    090    public PrintCommandListener(final PrintWriter writer) {
    091        this(writer, false);
    092    }
    093
    094    /**
    095     * Create an instance which optionally suppresses login command text.
    096     *
    097     * @param writer        where to write the commands and responses
    098     * @param suppressLogin if {@code true}, only print command name for login
    099     *
    100     * @since 3.0
    101     */
    102    public PrintCommandListener(final PrintWriter writer, final boolean suppressLogin) {
    103        this(writer, suppressLogin, (char) 0);
    104    }
    105
    106    /**
    107     * Create an instance which optionally suppresses login command text and indicates where the EOL starts with the specified character.
    108     *
    109     * @param writer        where to write the commands and responses
    110     * @param suppressLogin if {@code true}, only print command name for login
    111     * @param eolMarker     if non-zero, add a marker just before the EOL.
    112     *
    113     * @since 3.0
    114     */
    115    public PrintCommandListener(final PrintWriter writer, final boolean suppressLogin, final char eolMarker) {
    116        this(writer, suppressLogin, eolMarker, false);
    117    }
    118
    119    /**
    120     * Create an instance which optionally suppresses login command text and indicates where the EOL starts with the specified character.
    121     *
    122     * @param writer        where to write the commands and responses
    123     * @param suppressLogin if {@code true}, only print command name for login
    124     * @param eolMarker     if non-zero, add a marker just before the EOL.
    125     * @param showDirection if {@code true}, add {@code ">} " or {@code "< "} as appropriate to the output
    126     *
    127     * @since 3.0
    128     */
    129    public PrintCommandListener(final PrintWriter writer, final boolean suppressLogin, final char eolMarker, final boolean showDirection) {
    130        this.writer = writer;
    131        this.nologin = suppressLogin;
    132        this.eolMarker = eolMarker;
    133        this.directionMarker = showDirection;
    134    }
    135
    136    private String getPrintableString(final String msg) {
    137        if (eolMarker == 0) {
    138            return msg;
    139        }
    140        final int pos = msg.indexOf(SocketClient.NETASCII_EOL);
    141        if (pos > 0) {
    142            final StringBuilder sb = new StringBuilder();
    143            sb.append(msg.substring(0, pos));
    144            sb.append(eolMarker);
    145            sb.append(msg.substring(pos));
    146            return sb.toString();
    147        }
    148        return msg;
    149    }
    150
    151    @Override
    152    public void protocolCommandSent(final ProtocolCommandEvent event) {
    153        if (directionMarker) {
    154            writer.print("> ");
    155        }
    156        if (nologin) {
    157            final String cmd = event.getCommand();
    158            if ("PASS".equalsIgnoreCase(cmd) || "USER".equalsIgnoreCase(cmd)) {
    159                writer.print(cmd);
    160                writer.println(" *******"); // Don't bother with EOL marker for this!
    161            } else {
    162                final String IMAP_LOGIN = "LOGIN";
    163                if (IMAP_LOGIN.equalsIgnoreCase(cmd)) { // IMAP
    164                    String msg = event.getMessage();
    165                    msg = msg.substring(0, msg.indexOf(IMAP_LOGIN) + IMAP_LOGIN.length());
    166                    writer.print(msg);
    167                    writer.println(" *******"); // Don't bother with EOL marker for this!
    168                } else {
    169                    writer.print(getPrintableString(event.getMessage()));
    170                }
    171            }
    172        } else {
    173            writer.print(getPrintableString(event.getMessage()));
    174        }
    175        writer.flush();
    176    }
    177
    178    @Override
    179    public void protocolReplyReceived(final ProtocolCommandEvent event) {
    180        if (directionMarker) {
    181            writer.print("< ");
    182        }
    183        writer.print(event.getMessage());
    184        writer.flush();
    185    }
    186}