1 package org.apache.maven.plugin.surefire.report;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.BufferedOutputStream;
23 import java.io.File;
24 import java.io.FileOutputStream;
25 import java.io.FilterOutputStream;
26 import java.io.IOException;
27 import java.util.concurrent.atomic.AtomicStampedReference;
28 import java.util.concurrent.locks.ReentrantLock;
29
30 import org.apache.maven.surefire.booter.DumpErrorSingleton;
31 import org.apache.maven.surefire.report.ReportEntry;
32
33 import static org.apache.maven.plugin.surefire.report.FileReporter.getReportFile;
34
35
36
37
38
39
40
41 public class ConsoleOutputFileReporter
42 implements TestcycleConsoleOutputReceiver
43 {
44 private static final int STREAM_BUFFER_SIZE = 16 * 1024;
45 private static final int OPEN = 0;
46 private static final int CLOSED_TO_REOPEN = 1;
47 private static final int CLOSED = 2;
48
49 private final File reportsDirectory;
50 private final String reportNameSuffix;
51
52 private final AtomicStampedReference<FilterOutputStream> fileOutputStream =
53 new AtomicStampedReference<FilterOutputStream>( null, OPEN );
54
55 private final ReentrantLock lock = new ReentrantLock();
56
57 private volatile String reportEntryName;
58
59 public ConsoleOutputFileReporter( File reportsDirectory, String reportNameSuffix )
60 {
61 this.reportsDirectory = reportsDirectory;
62 this.reportNameSuffix = reportNameSuffix;
63 }
64
65 @Override
66 public void testSetStarting( ReportEntry reportEntry )
67 {
68 lock.lock();
69 try
70 {
71 closeNullReportFile( reportEntry );
72 }
73 finally
74 {
75 lock.unlock();
76 }
77 }
78
79 @Override
80 public void testSetCompleted( ReportEntry report )
81 {
82 }
83
84 @Override
85 public void close()
86 {
87
88 lock.lock();
89 try
90 {
91 closeReportFile();
92 }
93 finally
94 {
95 lock.unlock();
96 }
97 }
98
99 @Override
100 public void writeTestOutput( byte[] buf, int off, int len, boolean stdout )
101 {
102 lock.lock();
103 try
104 {
105
106
107 int[] status = new int[1];
108 FilterOutputStream os = fileOutputStream.get( status );
109 if ( status[0] != CLOSED )
110 {
111 if ( os == null )
112 {
113 if ( !reportsDirectory.exists() )
114 {
115
116 reportsDirectory.mkdirs();
117 }
118 File file = getReportFile( reportsDirectory, reportEntryName, reportNameSuffix, "-output.txt" );
119 os = new BufferedOutputStream( new FileOutputStream( file ), STREAM_BUFFER_SIZE );
120 fileOutputStream.set( os, OPEN );
121 }
122 os.write( buf, off, len );
123 }
124 }
125 catch ( IOException e )
126 {
127 DumpErrorSingleton.getSingleton()
128 .dumpException( e );
129
130 throw new RuntimeException( e );
131 }
132 finally
133 {
134 lock.unlock();
135 }
136 }
137
138 @SuppressWarnings( "checkstyle:emptyblock" )
139 private void closeNullReportFile( ReportEntry reportEntry )
140 {
141 try
142 {
143
144 close( true );
145 }
146 catch ( IOException ignored )
147 {
148 DumpErrorSingleton.getSingleton()
149 .dumpException( ignored );
150 }
151 finally
152 {
153
154 reportEntryName = reportEntry.getName();
155 }
156 }
157
158 @SuppressWarnings( "checkstyle:emptyblock" )
159 private void closeReportFile()
160 {
161 try
162 {
163 close( false );
164 }
165 catch ( IOException ignored )
166 {
167 DumpErrorSingleton.getSingleton()
168 .dumpException( ignored );
169 }
170 }
171
172 private void close( boolean closeReattempt )
173 throws IOException
174 {
175 int[] status = new int[1];
176 FilterOutputStream os = fileOutputStream.get( status );
177 if ( status[0] != CLOSED )
178 {
179 fileOutputStream.set( null, closeReattempt ? CLOSED_TO_REOPEN : CLOSED );
180 if ( os != null && status[0] == OPEN )
181 {
182 os.close();
183 }
184 }
185 }
186 }