    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
    025 * a sample implementation of the ProtocolCommandListener interface
    026 * which just prints out to a specified stream all command/reply traffic.
    027 *
    028 * @since 2.0
    029 */
    030
    031public class PrintCommandListener implements ProtocolCommandListener
    032{
    033    private final PrintWriter writer;
    034    private final boolean nologin;
    035    private final char eolMarker;
    036    private final boolean directionMarker;
    037
    038    /**
    039     * Create the default instance which prints everything.
    040     *
    041     * @param stream where to write the commands and responses
    042     * e.g. System.out
    043     * @since 3.0
    044     */
    045    public PrintCommandListener(final PrintStream stream)
    046    {
    047        this(new PrintWriter(stream));
    048    }
    049
    050    /**
    051     * Create an instance which optionally suppresses login command text
    052     * and indicates where the EOL starts with the specified character.
    053     *
    054     * @param stream where to write the commands and responses
    055     * @param suppressLogin if {@code true}, only print command name for login
    056     *
    057     * @since 3.0
    058     */
    059    public PrintCommandListener(final PrintStream stream, final boolean suppressLogin) {
    060        this(new PrintWriter(stream), suppressLogin);
    061    }
    062
    063    /**
    064     * Create an instance which optionally suppresses login command text
    065     * and indicates where the EOL starts with the specified character.
    066     *
    067     * @param stream where to write the commands and responses
    068     * @param suppressLogin if {@code true}, only print command name for login
    069     * @param eolMarker if non-zero, add a marker just before the EOL.
    070     *
    071     * @since 3.0
    072     */
    073    public PrintCommandListener(final PrintStream stream, final boolean suppressLogin, final char eolMarker) {
    074        this(new PrintWriter(stream), suppressLogin, eolMarker);
    075    }
    076
    077    /**
    078     * Create an instance which optionally suppresses login command text
    079     * and indicates where the EOL starts with the specified character.
    080     *
    081     * @param stream where to write the commands and responses
    082     * @param suppressLogin if {@code true}, only print command name for login
    083     * @param eolMarker if non-zero, add a marker just before the EOL.
    084     * @param showDirection if {@code true}, add {@code "> "} or {@code "< "} as appropriate to the output
    085     *
    086     * @since 3.0
    087     */
    088    public PrintCommandListener(final PrintStream stream, final boolean suppressLogin, final char eolMarker,
    089            final boolean showDirection) {
    090        this(new PrintWriter(stream), suppressLogin, eolMarker, showDirection);
    091    }
    092
    093    /**
    094     * Create the default instance which prints everything.
    095     *
    096     * @param writer where to write the commands and responses
    097     */
    098    public PrintCommandListener(final PrintWriter writer)
    099    {
    100        this(writer, false);
    101    }
    102
    103    /**
    104     * Create an instance which optionally suppresses login command text.
    105     *
    106     * @param writer where to write the commands and responses
    107     * @param suppressLogin if {@code true}, only print command name for login
    108     *
    109     * @since 3.0
    110     */
    111    public PrintCommandListener(final PrintWriter writer, final boolean suppressLogin)
    112    {
    113        this(writer, suppressLogin, (char) 0);
    114    }
    115
    116    /**
    117     * Create an instance which optionally suppresses login command text
    118     * and indicates where the EOL starts with the specified character.
    119     *
    120     * @param writer where to write the commands and responses
    121     * @param suppressLogin if {@code true}, only print command name for login
    122     * @param eolMarker if non-zero, add a marker just before the EOL.
    123     *
    124     * @since 3.0
    125     */
    126    public PrintCommandListener(final PrintWriter writer, final boolean suppressLogin, final char eolMarker)
    127    {
    128        this(writer, suppressLogin, eolMarker, false);
    129    }
    130
    131    /**
    132     * Create an instance which optionally suppresses login command text
    133     * and indicates where the EOL starts with the specified character.
    134     *
    135     * @param writer where to write the commands and responses
    136     * @param suppressLogin if {@code true}, only print command name for login
    137     * @param eolMarker if non-zero, add a marker just before the EOL.
    138     * @param showDirection if {@code true}, add {@code ">} " or {@code "< "} as appropriate to the output
    139     *
    140     * @since 3.0
    141     */
    142    public PrintCommandListener(final PrintWriter writer, final boolean suppressLogin, final char eolMarker,
    143            final boolean showDirection) {
    144        this.writer = writer;
    145        this.nologin = suppressLogin;
    146        this.eolMarker = eolMarker;
    147        this.directionMarker = showDirection;
    148    }
    149
    150    @Override
    151    public void protocolCommandSent(final ProtocolCommandEvent event)
    152    {
    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    private String getPrintableString(final String msg){
    179        if (eolMarker == 0) {
    180            return msg;
    181        }
    182        final int pos = msg.indexOf(SocketClient.NETASCII_EOL);
    183        if (pos > 0) {
    184            final StringBuilder sb = new StringBuilder();
    185            sb.append(msg.substring(0,pos));
    186            sb.append(eolMarker);
    187            sb.append(msg.substring(pos));
    188            return sb.toString();
    189        }
    190        return msg;
    191    }
    192
    193    @Override
    194    public void protocolReplyReceived(final ProtocolCommandEvent event)
    195    {
    196        if (directionMarker) {
    197            writer.print("< ");
    198        }
    199        writer.print(event.getMessage());
    200        writer.flush();
    201    }
    202}
    203