-
Notifications
You must be signed in to change notification settings - Fork 55
/
PipeFileAfterModificationAction.java
125 lines (113 loc) · 3.96 KB
/
PipeFileAfterModificationAction.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package org.jenkinsci.plugins.unity3d.io;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.concurrent.Callable;
/**
* A Callable that allows piping the output of a file into.
* <p>
* Useful when the file is been modified and one needs to loop.
* <p>
* Note that you can interrupt this task to cancel it.
*
* @author Jerome Lacoste
*/
public class PipeFileAfterModificationAction implements Callable<Long> {
private final String path;
private final OutputStream out;
private final boolean closeOut;
private final int waitBetweenCopyLoops;
public PipeFileAfterModificationAction(String path, OutputStream out, boolean closeOut) {
this.path = path;
if (out == null) {
throw new NullPointerException("out is null");
}
this.out = out;
this.closeOut = closeOut;
waitBetweenCopyLoops = 50;
}
public PipeFileAfterModificationAction(String path, OutputStream out) {
this(path, out, false);
}
/**
* Wait until the file has been modified and then copy its contents into the output, looping repeatedly as the file is been modified.
* @return the number of bytes copied
* @throws IOException
*/
public Long call() throws IOException {
File file = new DetectFileModifiedAction(path).call();
long pos = 0;
if (file != null) {
RandomAccessFile raf = null;
try {
while (true) {
if (file.exists()) {
// I once experienced a FileNotFoundException here, let's see if this happens again
raf = new RandomAccessFile(path, "r");
pos = continueCopyingFrom(raf, pos);
raf.close();
}
synchronized (this) {
try {
wait(waitBetweenCopyLoops);
} catch (InterruptedException e) {
break;
}
}
}
} catch (Throwable t) {
forcePrintStacktrace(t);
} finally {
if (raf != null) {
try {
pos = raf.getFilePointer();
} catch (IOException ignore) {
}
try {
raf.close();
} catch (IOException ignore) {
}
}
closeOutIfNecessary();
}
} else {
writeMessagesToOutput("\nWARNING: No change detected to Editor.log path: '" + path + "'.",
"\tThe unity3d plugin was probably unable to find it in its expected locations (see JENKINS-24265).",
"\tConsider using the -logFile argument to force a known editor.log path or report the issue.");
closeOutIfNecessary();
}
return pos;
}
private void closeOutIfNecessary() throws IOException {
if (closeOut)
out.close();
}
private void writeMessagesToOutput(String... msgs) {
PrintStream printStream = new PrintStream(out);
try {
for (String msg : msgs) {
printStream.println(msg);
}
} finally {
printStream.close();
}
}
private void forcePrintStacktrace(Throwable t) {
PrintStream printStream = new PrintStream(out);
try {
t.printStackTrace(printStream);
} finally {
printStream.close();
}
}
private long continueCopyingFrom(RandomAccessFile raf, long from) throws IOException {
raf.seek(from);
byte[] buf = new byte[8192];
int len;
while ((len = raf.read(buf)) > 0)
out.write(buf, 0, len);
return raf.getFilePointer();
}
}