1
2
3
4
5
6
7
8
9
10
11 package org.mule.module.pgp;
12
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.io.PipedInputStream;
16 import java.io.PipedOutputStream;
17
18 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
19 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicLong;
20
21 import org.apache.commons.io.IOUtils;
22
23
24
25
26
27
28
29
30
31
32 public class LazyInputStream extends InputStream
33 {
34
35 private PipedInputStream in;
36 private PipedOutputStream out;
37
38 private AtomicBoolean startedCopying;
39 private Thread copyingThread;
40 private AtomicLong bytesRequested;
41
42 private OutputStreamWriter writer;
43
44 public LazyInputStream(OutputStreamWriter writer) throws IOException
45 {
46 this.in = new PipedInputStream();
47 this.out = new PipedOutputStream(this.in);
48 this.startedCopying = new AtomicBoolean(false);
49 this.bytesRequested = new AtomicLong(0);
50 this.writer = writer;
51 }
52
53 private void copyRequest()
54 {
55 if (this.startedCopying.compareAndSet(false, true))
56 {
57 this.copyingThread = new WriteWork();
58 this.copyingThread.start();
59 }
60 }
61
62 @Override
63 public int available() throws IOException
64 {
65 this.copyRequest();
66 return this.in.available();
67 }
68
69 @Override
70 public void close() throws IOException
71 {
72 this.in.close();
73 this.copyingThread.interrupt();
74 }
75
76 @Override
77 public synchronized void mark(int readlimit)
78 {
79 this.in.mark(readlimit);
80 }
81
82 @Override
83 public boolean markSupported()
84 {
85 return this.in.markSupported();
86 }
87
88 @Override
89 public int read() throws IOException
90 {
91 this.bytesRequested.addAndGet(1);
92 this.copyRequest();
93 return this.in.read();
94 }
95
96 @Override
97 public int read(byte[] b, int off, int len) throws IOException
98 {
99 this.bytesRequested.addAndGet(len);
100 this.copyRequest();
101 return this.in.read(b, off, len);
102 }
103
104 @Override
105 public int read(byte[] b) throws IOException
106 {
107 this.bytesRequested.addAndGet(b.length);
108 this.copyRequest();
109 return this.in.read(b);
110 }
111
112 @Override
113 public synchronized void reset() throws IOException
114 {
115 this.in.reset();
116 }
117
118 @Override
119 public long skip(long n) throws IOException
120 {
121 this.copyRequest();
122 return this.in.skip(n);
123 }
124
125 private class WriteWork extends Thread
126 {
127 public void run()
128 {
129 try
130 {
131 writer.initialize(out);
132
133 boolean finishWriting = false;
134 while (!finishWriting)
135 {
136 finishWriting = writer.write(out, bytesRequested);
137 }
138 }
139 catch (Exception e)
140 {
141 e.printStackTrace();
142 }
143 finally
144 {
145 IOUtils.closeQuietly(out);
146 while (!this.isInterrupted())
147 {
148 try
149 {
150 sleep(1000 * 60);
151 }
152 catch (InterruptedException e)
153 {
154 }
155 }
156 }
157 }
158 }
159 }