1
2 package org.sentrysoftware.jawk.ext;
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 import java.io.BufferedReader;
27 import java.io.IOException;
28 import java.io.InputStreamReader;
29 import java.util.concurrent.BlockingQueue;
30 import java.util.concurrent.LinkedBlockingQueue;
31
32 import org.sentrysoftware.jawk.NotImplementedError;
33 import org.sentrysoftware.jawk.jrt.BlockObject;
34 import org.sentrysoftware.jawk.jrt.JRT;
35 import org.sentrysoftware.jawk.jrt.VariableManager;
36 import org.sentrysoftware.jawk.util.AwkLogger;
37 import org.sentrysoftware.jawk.util.AwkSettings;
38 import org.slf4j.Logger;
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 public class StdinExtension extends AbstractExtension implements JawkExtension {
102
103 private static final Logger LOG = AwkLogger.getLogger(StdinExtension.class);
104
105 private static final Object DONE = new Object();
106
107 private final BlockingQueue<Object> getLineInput = new LinkedBlockingQueue<Object>();
108
109 private final BlockObject blocker = new BlockObject() {
110
111 @Override
112 public String getNotifierTag() {
113 return "Stdin";
114 }
115
116 @Override
117 public final void block()
118 throws InterruptedException
119 {
120 synchronized (blocker) {
121 if (stdInHasInput() == 0) {
122 blocker.wait();
123 }
124 }
125 }
126 };
127
128 private boolean isEof = false;
129
130
131 @Override
132 public void init(VariableManager vm, JRT jrt, final AwkSettings settings) {
133 super.init(vm, jrt, settings);
134
135 Thread getLineInputThread = new Thread("getLineInputThread") {
136 @Override
137 public final void run() {
138 try {
139 BufferedReader br = new BufferedReader(
140 new InputStreamReader(settings.getInput()));
141 String line;
142 while ((line = br.readLine()) != null) {
143 getLineInput.put(line);
144 synchronized (blocker) {
145 blocker.notify();
146 }
147 }
148 } catch (InterruptedException ie) {
149 LOG.error("", ie);
150
151 } catch (IOException ioe) {
152 LOG.error("", ioe);
153
154 }
155 try {
156 getLineInput.put(DONE);
157 } catch (InterruptedException ie) {
158 LOG.error("Should never be interrupted.", ie);
159 System.exit(1);
160 }
161 synchronized (blocker) {
162 blocker.notify();
163 }
164 }
165 };
166 getLineInputThread.setDaemon(true);
167 getLineInputThread.start();
168 }
169
170
171 @Override
172 public String getExtensionName() {
173 return "Stdin Support";
174 }
175
176
177 @Override
178 public String[] extensionKeywords() {
179 return new String[] {
180
181 "StdinHasInput",
182 "StdinGetline",
183 "StdinBlock",
184 };
185 }
186
187
188 @Override
189 public Object invoke(String keyword, Object[] args) {
190 if (keyword.equals("StdinHasInput")) {
191 checkNumArgs(args, 0);
192 return stdInHasInput();
193 } else if (keyword.equals("StdinGetline")) {
194 checkNumArgs(args, 0);
195 return stdInGetLine();
196 } else if (keyword.equals("StdinBlock")) {
197 if (args.length == 0) {
198 return stdInBlock();
199 } else if (args.length == 1) {
200 return stdInBlock((BlockObject) args[0]);
201 } else {
202 throw new IllegalArgumentException("StdinBlock accepts 0 or 1 args.");
203 }
204 } else {
205 throw new NotImplementedError(keyword);
206 }
207 }
208
209 private int stdInHasInput() {
210 if (isEof) {
211
212 return 1;
213 } else if (getLineInput.size() == 0) {
214
215 return 0;
216 } else if (getLineInput.size() == 1 && getLineInput.peek() == DONE) {
217
218 return 0;
219 } else {
220
221 return 1;
222 }
223 }
224
225
226
227
228
229 private Object stdInGetLine() {
230 try {
231 if (isEof) {
232 return 0;
233 }
234 Object lineObj = getLineInput.take();
235 if (lineObj == DONE) {
236 isEof = true;
237 return 0;
238 }
239 getJrt().setInputLine((String) lineObj);
240 getJrt().jrtParseFields();
241 return 1;
242 } catch (InterruptedException ie) {
243 LOG.warn("", ie);
244 return -1;
245 }
246 }
247
248 private BlockObject stdInBlock() {
249 blocker.clearNextBlockObject();
250 return blocker;
251 }
252
253 private BlockObject stdInBlock(BlockObject bo) {
254 assert bo != null;
255 blocker.setNextBlockObject(bo);
256 return blocker;
257 }
258 }