1 package org.apache.maven.shared.scriptinterpreter;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.io.File;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.OutputStream;
26 import java.io.PrintStream;
27
28 /**
29 * <p>FileLogger class.</p>
30 *
31 */
32 public class FileLogger implements ExecutionLogger, AutoCloseable
33 {
34
35 /**
36 * The path to the log file.
37 */
38 private File file;
39
40 /**
41 * The underlying file stream this logger writes to.
42 */
43 private PrintStream stream;
44
45 /**
46 * Creates a new logger that writes to the specified file.
47 *
48 * @param outputFile The path to the output file, if null all message will be discarded.
49 * @throws java.io.IOException If the output file could not be created.
50 */
51 public FileLogger( File outputFile ) throws IOException
52 {
53 this( outputFile, null );
54 }
55
56 /**
57 * Creates a new logger that writes to the specified file and optionally mirrors messages.
58 *
59 * @param outputFile The path to the output file, if null all message will be discarded.
60 * @param mirrorHandler The class which handle mirrored message, can be <code>null</code>.
61 * @throws java.io.IOException If the output file could not be created.
62 */
63 public FileLogger( File outputFile, FileLoggerMirrorHandler mirrorHandler ) throws IOException
64 {
65 this.file = outputFile;
66
67 OutputStream outputStream;
68
69 if ( outputFile != null )
70 {
71 outputFile.getParentFile().mkdirs();
72 outputStream = new FileOutputStream( outputFile );
73 }
74 else
75 {
76 outputStream = new NullOutputStream();
77 }
78
79 if ( mirrorHandler != null )
80 {
81 stream = new PrintStream( new MirrorStreamWrapper( outputStream, mirrorHandler ) );
82 }
83 else
84 {
85 stream = new PrintStream( outputStream );
86 }
87 }
88
89 /**
90 * Gets the path to the output file.
91 *
92 * @return The path to the output file, never <code>null</code>.
93 */
94 public File getOutputFile()
95 {
96 return file;
97 }
98
99 /**
100 * Gets the underlying stream used to write message to the log file.
101 *
102 * @return The underlying stream used to write message to the log file, never <code>null</code>.
103 */
104 @Override
105 public PrintStream getPrintStream()
106 {
107 return stream;
108 }
109
110 /**
111 * Writes the specified line to the log file
112 * and invoke {@link FileLoggerMirrorHandler#consumeOutput(String)} if is given.
113 *
114 * @param line The message to log.
115 */
116 @Override
117 public void consumeLine( String line )
118 {
119 stream.println( line );
120 stream.flush();
121 }
122
123 /**
124 * Closes the underlying file stream.
125 */
126 public void close()
127 {
128 if ( stream != null )
129 {
130 stream.flush();
131 stream.close();
132 stream = null;
133 }
134 }
135
136 private static class MirrorStreamWrapper extends OutputStream
137 {
138 private final OutputStream out;
139 private final FileLoggerMirrorHandler mirrorHandler;
140
141 private StringBuilder lineBuffer;
142
143 MirrorStreamWrapper( OutputStream outputStream, FileLoggerMirrorHandler mirrorHandler )
144 {
145 this.out = outputStream;
146 this.mirrorHandler = mirrorHandler;
147 this.lineBuffer = new StringBuilder();
148 }
149
150 @Override
151 public void write( int b ) throws IOException
152 {
153 out.write( b );
154 lineBuffer.append( (char) ( b ) );
155 }
156
157 @Override
158 public void write( byte[] b, int off, int len ) throws IOException
159 {
160 out.write( b, off, len );
161 lineBuffer.append( new String( b, off, len ) );
162 }
163
164 @Override
165 public void flush() throws IOException
166 {
167 out.flush();
168
169 int len = lineBuffer.length();
170 if ( len == 0 )
171 {
172 // nothing to log
173 return;
174 }
175
176 // remove line end for log
177 while ( len > 0 && ( lineBuffer.charAt( len - 1 ) == '\n' || lineBuffer.charAt( len - 1 ) == '\r' ) )
178 {
179 len--;
180 }
181 lineBuffer.setLength( len );
182
183 mirrorHandler.consumeOutput( lineBuffer.toString() );
184
185 // clear buffer
186 lineBuffer = new StringBuilder();
187 }
188 }
189
190 private static class NullOutputStream extends OutputStream
191 {
192 @Override
193 public void write( int b )
194 {
195 // do nothing
196 }
197
198 @Override
199 public void write( byte[] b, int off, int len )
200 {
201 // do nothing
202 }
203 }
204 }