001/*
002 * Copyright (C) 2009-2017 the original author(s).
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fusesource.jansi;
017
018import java.io.IOException;
019import java.io.OutputStream;
020import java.io.PrintStream;
021
022/**
023 * A PrintStream filtering to another PrintStream, without making any assumption about encoding.
024 * 
025 * @author Hervé Boutemy
026 * @since 1.17
027 */
028public class FilterPrintStream extends PrintStream
029{
030    private static final String NEWLINE = System.getProperty("line.separator");
031    protected final PrintStream ps;
032
033    public FilterPrintStream(PrintStream ps)
034    {
035        super( new OutputStream() {
036
037            @Override
038            public void write(int b) throws IOException {
039                throw new RuntimeException("Direct OutputStream use forbidden: must go through delegate PrintStream");
040            }
041            
042        });
043        this.ps = ps;
044    }
045
046    /**
047     * Filter the content
048     * @param data character to filter
049     * @return <code>true</code> if the data is not filtered then has to be printed to delegate PrintStream
050     */
051    protected boolean filter(int data)
052    {
053        return true;
054    }
055
056    @Override
057    public void write(int data)
058    {
059        if (filter(data))
060        {
061            ps.write(data);
062        }
063    }
064
065    @Override
066    public void write(byte[] buf, int off, int len)
067    {
068        for (int i = 0; i < len; i++)
069        {
070            write(buf[off + i]);
071        }
072    }
073
074    @Override
075    public boolean checkError()
076    {
077        return super.checkError() || ps.checkError();
078    }
079
080    @Override
081    public void close()
082    {
083        super.close();
084        ps.close();
085    }
086
087    @Override
088    public void flush()
089    {
090        super.flush();
091        ps.flush();
092    }
093
094    private void write(char buf[]) {
095        for (char c : buf)
096        {
097            if (filter(c))
098            {
099                ps.print(c);
100            }
101        }
102    }
103
104    private void write(String s) {
105        char[] buf = new char[s.length()];
106        s.getChars(0, s.length(), buf, 0);
107        write(buf);
108    }
109
110    private void newLine() {
111        write(NEWLINE);
112    }
113
114    /* Methods that do not terminate lines */
115
116    @Override
117    public void print(boolean b) {
118        write(b ? "true" : "false");
119    }
120
121    @Override
122    public void print(char c) {
123        write(String.valueOf(c));
124    }
125
126    @Override
127    public void print(int i) {
128        write(String.valueOf(i));
129    }
130
131    @Override
132    public void print(long l) {
133        write(String.valueOf(l));
134    }
135
136    @Override
137    public void print(float f) {
138        write(String.valueOf(f));
139    }
140
141    @Override
142    public void print(double d) {
143        write(String.valueOf(d));
144    }
145
146    @Override
147    public void print(char s[]) {
148        write(s);
149    }
150
151    @Override
152    public void print(String s) {
153        if (s == null) {
154            s = "null";
155        }
156        write(s);
157    }
158
159    @Override
160    public void print(Object obj) {
161        write(String.valueOf(obj));
162    }
163
164
165    /* Methods that do terminate lines */
166
167    @Override
168    public void println() {
169        newLine();
170    }
171
172    @Override
173    public void println(boolean x) {
174        synchronized (this) {
175            print(x);
176            newLine();
177        }
178    }
179
180    @Override
181    public void println(char x) {
182        synchronized (this) {
183            print(x);
184            newLine();
185        }
186    }
187
188    @Override
189    public void println(int x) {
190        synchronized (this) {
191            print(x);
192            newLine();
193        }
194    }
195
196    @Override
197    public void println(long x) {
198        synchronized (this) {
199            print(x);
200            newLine();
201        }
202    }
203
204    @Override
205    public void println(float x) {
206        synchronized (this) {
207            print(x);
208            newLine();
209        }
210    }
211
212    @Override
213    public void println(double x) {
214        synchronized (this) {
215            print(x);
216            newLine();
217        }
218    }
219
220    @Override
221    public void println(char x[]) {
222        synchronized (this) {
223            print(x);
224            newLine();
225        }
226    }
227
228    @Override
229    public void println(String x) {
230        synchronized (this) {
231            print(x);
232            newLine();
233        }
234    }
235
236    @Override
237    public void println(Object x) {
238        String s = String.valueOf(x);
239        synchronized (this) {
240            print(s);
241            newLine();
242        }
243    }
244}