Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 13ec7cb695817345fb753394d67140dd4f3ad723 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*******************************************************************************
 * Copyright (c) 2010, 2017 SAP AG and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Lazar Kirchev, SAP AG - initial API and implementation  
 *******************************************************************************/

package org.eclipse.equinox.console.common;

import java.io.IOException;
import java.io.OutputStream;

/**
 * This class wraps the actual output stream (e.g., a socket output stream) and is responsible for
 * buffering and flushing the characters to the actual output stream.
 */
public class ConsoleOutputStream extends OutputStream {

    /**
     * A size of the used buffer.
     */
    public static final int BUFFER_SIZE = 2048;
    public final static byte CR = (byte) '\r';
    public final static byte LF = (byte) '\n';

    OutputStream out;
    OutputStream oldOut;

    private boolean isEcho = true;
    private boolean queueing = false;
    private byte prevByte;
    private byte[] buffer;
    private int pos;

    /**
     * Initiates with instance of the output stream to which it will send data. Here it writes to
     * a socket output stream.
     *
     * @param out OutputStream for console output
     */
    public ConsoleOutputStream(OutputStream out) {
        this.out = out;
        buffer = new byte[BUFFER_SIZE];
        pos = 0;
    }

    /**
     * An implementation of the corresponding abstract method in OutputStream.
     */
    @Override
	public synchronized void write(int i) throws IOException {

        if (!queueing) {
            if (isEcho) {
                if (i == '\r' || i == '\0') {
                    queueing = true;
                    prevByte = (byte) i;
                } else if (i == '\n') {
                    add(CR);
                    add(LF);
                } else {
                    add(i);
                }
            }
        } else { // awaiting '\n' AFTER '\r', and '\b' AFTER '\0'
            if (prevByte == '\0' && i == '\b') {
                isEcho = !isEcho;
            } else if (isEcho) {
                if (prevByte == '\r' && i == '\n') {
                    add(CR);
                    add(LF);
                } else {
                    add(CR);
                    add(LF);
                    add(i);
                }
            }

            queueing = false;
            flush();
        }

    }

    /**
     * Empties the buffer and sends data to the socket output stream.
     *
     * @throws IOException
     */
    @Override
	public synchronized void flush() throws IOException {
        if (pos > 0) {
            try {
				out.write(buffer, 0, pos);
				out.flush();
			} finally {
				pos = 0;
			}
            
        }
    }

    /**
     * Adds a variable of type integer to the buffer.
     *
     * @param i integer to add
     * @throws java.io.IOException if there are problems adding the integer
     */
    private void add(int i) throws IOException {
        buffer[pos] = (byte) i;
        pos++;

        if (pos == buffer.length) {
            flush();
        }
    }

    /**
     * Closes this OutputStream.
     *
     * @throws IOException
     */
    @Override
	public void close() throws IOException {
        out.close();
    }

    /**
     * Substitutes the output stream. The old one is stored so that it can be restored later.
     *
     * @param newOut new output stream to use.
     */
    public void setOutput(OutputStream newOut) {
        if (newOut != null) {
            oldOut = out;
            out = newOut;
        } else {
            out = oldOut;
        }

    }
}

Back to the top