View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *  http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.any23.cli;
19  
20  import java.io.IOException;
21  import java.io.OutputStream;
22  import java.io.PrintStream;
23  import java.io.UnsupportedEncodingException;
24  
25  /**
26   * This class reduces the verbosity of testing command-line console output by intercepting the underlying
27   * {@link PrintStream} when applicable and replacing it with a more concise version.
28   *
29   * @author Hans Brende (hansbrende@apache.org)
30   */
31  abstract class BaseTool implements Tool {
32  
33      abstract PrintStream getOut();
34  
35      abstract void setOut(PrintStream out);
36  
37      void run(boolean concise) throws Exception {
38          PrintStream out = concise(getOut(), concise);
39          setOut(out);
40          try {
41              run();
42          } finally {
43              close(out);
44          }
45      }
46  
47      private static void close(PrintStream stream) {
48          if (stream != null && stream != System.out && stream != System.err) {
49              try {
50                  stream.close();
51              } catch (Throwable th) {
52                  // ignore
53              }
54          }
55      }
56  
57      private static PrintStream concise(PrintStream out, boolean concise) {
58          try {
59              return (concise && (out == System.out || out == System.err)) ? new ConcisePrintStream(out)
60                      : (out instanceof ConcisePrintStream ? ((ConcisePrintStream) out).out : out);
61          } catch (UnsupportedEncodingException e) {
62              throw new RuntimeException("Error supporting UTF-8 encodings in ConcisePrintStream", e);
63          }
64      }
65  
66      private static final class ConcisePrintStream extends PrintStream {
67  
68          private PrintStream out;
69  
70          private ConcisePrintStream(PrintStream out) throws UnsupportedEncodingException {
71              super(new OutputStream() {
72                  StringBuilder sb = new StringBuilder();
73                  int lineCount;
74                  boolean truncated = false;
75  
76                  @Override
77                  public void write(int b) throws IOException {
78                      if (sb == null) {
79                          throw new IOException("stream closed");
80                      }
81                      if (b == '\n') {
82                          lineCount++;
83                      }
84                      if (lineCount == 0 && sb.length() < 200) {
85                          sb.append((char) b);
86                      } else if (!Character.isWhitespace(b)) {
87                          truncated = true;
88                      }
89                  }
90  
91                  @Override
92                  public void close() {
93                      if (sb == null) {
94                          return;
95                      }
96                      if (truncated) {
97                          sb.append("...");
98                      }
99                      if (lineCount > 1) {
100                         sb.append("\n...\n[Suppressed ").append(lineCount).append(" lines of output.]");
101                     }
102 
103                     out.println(sb);
104                     sb = null;
105                     BaseTool.close(out);
106                 }
107             }, true, "UTF-8");
108             this.out = out;
109         }
110 
111     }
112 
113 }