• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.testng.reporters;
2 
3 import java.io.BufferedWriter;
4 import java.io.File;
5 import java.io.FileReader;
6 import java.io.FileWriter;
7 import java.io.IOException;
8 import java.io.Reader;
9 import java.io.StringReader;
10 import java.io.Writer;
11 import java.util.Random;
12 
13 /**
14  * A string buffer that flushes its content to a temporary file whenever the internal
15  * string buffer becomes larger than MAX. If the buffer never reaches that size, no file
16  * is ever created and everything happens in memory, so the overhead compared to
17  * StringBuffer/StringBuilder is minimal.
18  *
19  * Note: calling toString() will force the entire string to be loaded in memory, use
20  * toWriter() if you need to avoid this.
21  *
22  * This class is not multi thread safe.
23  *
24  * @author Cedric Beust <cedric@beust.com>
25  *
26  * @since Nov 9, 2012
27  */
28 public class FileStringBuffer implements IBuffer {
29   private static int MAX = 100000;
30   private static final boolean VERBOSE = System.getProperty("fileStringBuffer") != null;
31 
32   private File m_file;
33   private StringBuilder m_sb = new StringBuilder();
34   private final int m_maxCharacters;
35 
FileStringBuffer()36   public FileStringBuffer() {
37     this(MAX);
38   }
39 
FileStringBuffer(int maxCharacters)40   public FileStringBuffer(int maxCharacters) {
41     m_maxCharacters = maxCharacters;
42   }
43 
44   @Override
append(CharSequence s)45   public FileStringBuffer append(CharSequence s) {
46     if (s == null) {
47       throw new IllegalArgumentException("CharSequence (Argument 0 of FileStringBuffer#append) should not be null");
48     }
49 //    m_sb.append(s);
50     if (m_sb.length() > m_maxCharacters) {
51       flushToFile();
52     }
53     if (s.length() < MAX) {
54       // Small string, add it to our internal buffer
55       m_sb.append(s);
56     } else {
57       // Big string, add it to the temporary file directly
58       flushToFile();
59       try {
60         copy(new StringReader(s.toString()), new FileWriter(m_file, true /* append */));
61       } catch (IOException e) {
62         e.printStackTrace();
63       }
64     }
65     return this;
66   }
67 
68   @Override
toWriter(Writer fw)69   public void toWriter(Writer fw) {
70     if (fw == null) {
71       throw new IllegalArgumentException("Writer (Argument 0 of FileStringBuffer#toWriter) should not be null");
72     }
73     try {
74       BufferedWriter bw = new BufferedWriter(fw);
75       if (m_file == null) {
76         bw.write(m_sb.toString());
77         bw.close();
78       } else {
79         flushToFile();
80         copy(new FileReader(m_file), bw);
81       }
82     } catch(IOException ex) {
83       ex.printStackTrace();
84     }
85   }
86 
copy(Reader input, Writer output)87   private static void copy(Reader input, Writer output)
88       throws IOException {
89     char[] buf = new char[MAX];
90     while (true) {
91       int length = input.read(buf);
92       if (length < 0) break;
93       output.write(buf, 0, length);
94     }
95 
96     try {
97       input.close();
98     } catch (IOException ignore) {
99     }
100     try {
101       output.close();
102     } catch (IOException ignore) {
103     }
104   }
105 
flushToFile()106   private void flushToFile() {
107     if (m_sb.length() == 0) return;
108 
109     if (m_file == null) {
110       try {
111         m_file = File.createTempFile("testng", "fileStringBuffer");
112         m_file.deleteOnExit();
113         p("Created temp file " + m_file);
114       } catch (IOException e) {
115         e.printStackTrace();
116       }
117     }
118 
119     p("Size " + m_sb.length() + ", flushing to " + m_file);
120     try (FileWriter fw = new FileWriter(m_file, true /* append */)) {
121       fw.append(m_sb);
122     } catch (IOException e) {
123       e.printStackTrace();
124     }
125     m_sb = new StringBuilder();
126   }
127 
p(String s)128   private static void p(String s) {
129     if (VERBOSE) {
130       System.out.println("[FileStringBuffer] " + s);
131     }
132   }
133 
134   @Override
toString()135   public String toString() {
136     String result = null;
137     if (m_file != null) {
138       flushToFile();
139       try {
140         result = Files.readFile(m_file);
141       } catch (IOException e) {
142         e.printStackTrace();
143       }
144     } else {
145       result = m_sb.toString();
146     }
147     return result;
148   }
149 
save(File expected, String s)150   private static void save(File expected, String s) throws IOException {
151     expected.delete();
152     try (FileWriter expectedWriter = new FileWriter(expected)) {
153       expectedWriter.append(s);
154     }
155   }
156 
main(String[] args)157   public static void main(String[] args) throws IOException {
158     String s = "abcdefghijklmnopqrstuvwxyz";
159     FileStringBuffer fsb = new FileStringBuffer(10);
160     StringBuilder control = new StringBuilder();
161     Random r = new Random();
162     for (int i = 0; i < 1000; i++) {
163       int start = Math.abs(r.nextInt() % 26);
164       int length = Math.abs(r.nextInt() % (26 - start));
165       String fragment = s.substring(start, start + length);
166       p("... Appending " + fragment);
167       fsb.append(fragment);
168       control.append(fragment);
169     }
170 
171     File expected = new File("/tmp/expected");
172     expected.delete();
173     FileWriter expectedWriter = new FileWriter(expected);
174     expectedWriter.append(control);
175     expectedWriter.close();
176 
177     File actual = new File("/tmp/actual");
178     actual.delete();
179     FileWriter actualWriter = new FileWriter(actual);
180     fsb.toWriter(actualWriter);
181     actualWriter.close();
182 //    Assert.assertEquals(fsb.toString(), control.toString());
183   }
184 
185 }
186