File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\jenkins\util\MarkFindingOutputStream.java.html

1 package jenkins.util;
2
3 import java.io.IOException;
4 import java.io.OutputStream;
5 import java.io.UnsupportedEncodingException;
6
7 /**
8 * Filtering {@link OutputStream} that looks for {@link #MARK} in the output stream and notifies the callback.
9 *
10 * The mark itself will be removed from the stream.
11 *
12 * @author Kohsuke Kawaguchi
13 * @since 1.458
14 */
15 public abstract class MarkFindingOutputStream extends OutputStream {
16 private final OutputStream base;
17
18 public MarkFindingOutputStream(OutputStream base) {
19 this.base = base;
20 }
21
22 /**
23 * Position in {@link #MARK} if we are currently suspecting a match.
24 */
25 private int match = 0;
26
27 public synchronized void write(int b) throws IOException {
28 if (MBYTES[match] == b) {// another byte matched. Good. Keep going...
29 match++;
30 if (match == MBYTES.length) {
31 // don't send MARK to the output, but instead notify the callback
32 onMarkFound();
33 match = 0;
34 }
35 } else {
36 if (match > 0) {
37 // only matched partially. send the partial match that we held off down the pipe
38 base.write(MBYTES, 0, match);
39 match = 0;
40
41 // this might match the first byte in MARK, so retry.
42 write(b);
43 } else {
44 base.write(b);
45 }
46 }
47 }
48
49 public void write(byte b[], int off, int len) throws IOException {
50 final int start = off;
51 final int end = off + len;
52 for (int i=off; i<end; ) {
53 if (MBYTES[match] == b[i]) {// another byte matched. Good. Keep going...
54 match++;
55 i++;
56 if (match == MBYTES.length) {
57 base.write(b,off,i-off-MBYTES.length); // flush the portion up to MARK
58 // don't send MARK to the output, but instead notify the callback
59 onMarkFound();
60 match = 0;
61 off = i;
62 len = end-i;
63 }
64 } else {
65 if (match > 0) {
66 // only matched partially.
67 // if a part of the partial match spans into the previous write, we need to fake that write.
68 int extra = match-(i-start);
69 if (extra>0) {
70 base.write(MBYTES,0,extra);
71 }
72 match = 0;
73
74 // this b[i] might be a fast byte in MARK, so we'll retry
75 } else {
76 // irrelevant byte.
77 i++;
78 }
79 }
80
81 }
82
83 // if we are partially matching, can't send that portion yet.
84 if (len-match>0)
85 base.write(b, off, len-match);
86 }
87
88 public void flush() throws IOException {
89 flushPartialMatch();
90 base.flush();
91 }
92
93 public void close() throws IOException {
94 flushPartialMatch();
95 base.close();
96 }
97
98 private void flushPartialMatch() throws IOException {
99 if (match>0) {
100 base.write(MBYTES,0,match);
101 match = 0;
102 }
103 }
104
105 protected abstract void onMarkFound();
106
107 // having a new line in the end makes it work better with line-buffering transformation
108 public static final String MARK = "[Jenkins:SYNC-MARK]\n";
109 private static final byte[] MBYTES = toUTF8(MARK);
110
111 private static byte[] toUTF8(String s) {
112 try {
113 return s.getBytes("UTF-8");
114 } catch (UnsupportedEncodingException e) {
115 throw new AssertionError(e);
116 }
117 }
118 }
119