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 * @see #filter(int)
028 */
029public class FilterPrintStream extends PrintStream
030{
031    private static final String NEWLINE = System.getProperty("line.separator");
032    protected final PrintStream ps;
033
034    public FilterPrintStream(PrintStream ps)
035    {
036        super( new OutputStream() {
037
038            @Override
039            public void write(int b) throws IOException {
040                throw new RuntimeException("Direct OutputStream use forbidden: must go through delegate PrintStream");
041            }
042            
043        });
044        this.ps = ps;
045    }
046
047    /**
048     * Filter the content
049     * @param data character to filter
050     * @return <code>true</code> if the data is not filtered then has to be printed to delegate PrintStream
051     */
052    protected boolean filter(int data)
053    {
054        return true;
055    }
056
057    @Override
058    public void write(int data)
059    {
060        if (filter(data))
061        {
062            ps.write(data);
063        }
064    }
065
066    @Override
067    public void write(byte[] buf, int off, int len)
068    {
069        for (int i = 0; i < len; i++)
070        {
071            write(buf[off + i]);
072        }
073    }
074
075    @Override
076    public boolean checkError()
077    {
078        return super.checkError() || ps.checkError();
079    }
080
081    @Override
082    public void close()
083    {
084        super.close();
085        ps.close();
086    }
087
088    @Override
089    public void flush()
090    {
091        super.flush();
092        ps.flush();
093    }
094
095    private void write(char buf[]) {
096        for (char c : buf)
097        {
098            if (filter(c))
099            {
100                ps.print(c);
101            }
102        }
103    }
104
105    private void write(String s) {
106        char[] buf = new char[s.length()];
107        s.getChars(0, s.length(), buf, 0);
108        write(buf);
109    }
110
111    private void newLine() {
112        write(NEWLINE);
113    }
114
115    /* Methods that do not terminate lines */
116
117    @Override
118    public void print(boolean b) {
119        write(b ? "true" : "false");
120    }
121
122    @Override
123    public void print(char c) {
124        write(String.valueOf(c));
125    }
126
127    @Override
128    public void print(int i) {
129        write(String.valueOf(i));
130    }
131
132    @Override
133    public void print(long l) {
134        write(String.valueOf(l));
135    }
136
137    @Override
138    public void print(float f) {
139        write(String.valueOf(f));
140    }
141
142    @Override
143    public void print(double d) {
144        write(String.valueOf(d));
145    }
146
147    @Override
148    public void print(char s[]) {
149        write(s);
150    }
151
152    @Override
153    public void print(String s) {
154        if (s == null) {
155            s = "null";
156        }
157        write(s);
158    }
159
160    @Override
161    public void print(Object obj) {
162        write(String.valueOf(obj));
163    }
164
165
166    /* Methods that do terminate lines */
167
168    @Override
169    public void println() {
170        newLine();
171    }
172
173    @Override
174    public void println(boolean x) {
175        synchronized (this) {
176            print(x);
177            newLine();
178        }
179    }
180
181    @Override
182    public void println(char x) {
183        synchronized (this) {
184            print(x);
185            newLine();
186        }
187    }
188
189    @Override
190    public void println(int x) {
191        synchronized (this) {
192            print(x);
193            newLine();
194        }
195    }
196
197    @Override
198    public void println(long x) {
199        synchronized (this) {
200            print(x);
201            newLine();
202        }
203    }
204
205    @Override
206    public void println(float x) {
207        synchronized (this) {
208            print(x);
209            newLine();
210        }
211    }
212
213    @Override
214    public void println(double x) {
215        synchronized (this) {
216            print(x);
217            newLine();
218        }
219    }
220
221    @Override
222    public void println(char x[]) {
223        synchronized (this) {
224            print(x);
225            newLine();
226        }
227    }
228
229    @Override
230    public void println(String x) {
231        synchronized (this) {
232            print(x);
233            newLine();
234        }
235    }
236
237    @Override
238    public void println(Object x) {
239        String s = String.valueOf(x);
240        synchronized (this) {
241            print(s);
242            newLine();
243        }
244    }
245}