comparison src/luan/modules/IoLuan.java @ 775:1a68fc55a80c

simplify dir structure
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 26 Aug 2016 14:36:40 -0600
parents core/src/luan/modules/IoLuan.java@ef0fc9ad30c1
children c49980cdece6
comparison
equal deleted inserted replaced
774:3e30cf310e56 775:1a68fc55a80c
1 package luan.modules;
2
3 import java.io.InputStream;
4 import java.io.OutputStream;
5 import java.io.PrintStream;
6 import java.io.Reader;
7 import java.io.Writer;
8 import java.io.StringReader;
9 import java.io.BufferedReader;
10 import java.io.BufferedWriter;
11 import java.io.BufferedInputStream;
12 import java.io.BufferedOutputStream;
13 import java.io.File;
14 import java.io.FileInputStream;
15 import java.io.FileOutputStream;
16 import java.io.InputStreamReader;
17 import java.io.OutputStreamWriter;
18 import java.io.ByteArrayInputStream;
19 import java.io.DataInputStream;
20 import java.io.DataOutputStream;
21 import java.io.StringWriter;
22 import java.io.IOException;
23 import java.io.FileNotFoundException;
24 import java.net.URL;
25 import java.net.Socket;
26 import java.net.ServerSocket;
27 import java.net.InetAddress;
28 import java.net.Inet4Address;
29 import java.net.NetworkInterface;
30 import java.net.MalformedURLException;
31 import java.net.UnknownHostException;
32 import java.util.Enumeration;
33 import java.util.List;
34 import java.util.Map;
35 import luan.Luan;
36 import luan.LuanState;
37 import luan.LuanTable;
38 import luan.LuanFunction;
39 import luan.LuanJavaFunction;
40 import luan.LuanException;
41 import luan.modules.url.LuanUrl;
42
43
44 public final class IoLuan {
45
46 private static void add(LuanTable t,String method,Class... parameterTypes) throws NoSuchMethodException {
47 t.rawPut( method, new LuanJavaFunction(IoLuan.class.getMethod(method,parameterTypes),null) );
48 }
49
50 public static String read_console_line(String prompt) throws IOException {
51 if( prompt==null )
52 prompt = "> ";
53 return System.console().readLine(prompt);
54 }
55
56
57 public interface LuanWriter {
58 public void write(LuanState luan,Object... args) throws LuanException, IOException;
59 public void close() throws IOException;
60 }
61
62 public static LuanTable textWriter(final PrintStream out) {
63 LuanWriter luanWriter = new LuanWriter() {
64
65 public void write(LuanState luan,Object... args) throws LuanException {
66 for( Object obj : args ) {
67 out.print( luan.toString(obj) );
68 }
69 }
70
71 public void close() {
72 out.close();
73 }
74 };
75 return writer(luanWriter);
76 }
77
78 public static LuanTable textWriter(final Writer out) {
79 LuanWriter luanWriter = new LuanWriter() {
80
81 public void write(LuanState luan,Object... args) throws LuanException, IOException {
82 for( Object obj : args ) {
83 out.write( luan.toString(obj) );
84 }
85 }
86
87 public void close() throws IOException {
88 out.close();
89 }
90 };
91 return writer(luanWriter);
92 }
93
94 private static LuanTable writer(LuanWriter luanWriter) {
95 LuanTable writer = new LuanTable();
96 try {
97 writer.rawPut( "write", new LuanJavaFunction(
98 LuanWriter.class.getMethod( "write", LuanState.class, new Object[0].getClass() ), luanWriter
99 ) );
100 writer.rawPut( "close", new LuanJavaFunction(
101 LuanWriter.class.getMethod( "close" ), luanWriter
102 ) );
103 } catch(NoSuchMethodException e) {
104 throw new RuntimeException(e);
105 }
106 return writer;
107 }
108
109
110 public static LuanTable binaryWriter(final OutputStream out) {
111 LuanTable writer = new LuanTable();
112 try {
113 writer.rawPut( "write", new LuanJavaFunction(
114 OutputStream.class.getMethod( "write", new byte[0].getClass() ), out
115 ) );
116 writer.rawPut( "close", new LuanJavaFunction(
117 OutputStream.class.getMethod( "close" ), out
118 ) );
119 } catch(NoSuchMethodException e) {
120 throw new RuntimeException(e);
121 }
122 return writer;
123 }
124
125 static LuanFunction lines(final BufferedReader in) {
126 return new LuanFunction() {
127 @Override public Object call(LuanState luan,Object[] args) throws LuanException {
128 try {
129 if( args.length > 0 ) {
130 if( args.length > 1 || !"close".equals(args[0]) )
131 throw new LuanException( "the only argument allowed is 'close'" );
132 in.close();
133 return null;
134 }
135 String rtn = in.readLine();
136 if( rtn==null )
137 in.close();
138 return rtn;
139 } catch(IOException e) {
140 throw new LuanException(e);
141 }
142 }
143 };
144 }
145
146 static LuanFunction blocks(final InputStream in,final int blockSize) {
147 return new LuanFunction() {
148 final byte[] a = new byte[blockSize];
149
150 @Override public Object call(LuanState luan,Object[] args) throws LuanException {
151 try {
152 if( args.length > 0 ) {
153 if( args.length > 1 || !"close".equals(args[0]) )
154 throw new LuanException( "the only argument allowed is 'close'" );
155 in.close();
156 return null;
157 }
158 if( in.read(a) == -1 ) {
159 in.close();
160 return null;
161 }
162 return a;
163 } catch(IOException e) {
164 throw new LuanException(e);
165 }
166 }
167 };
168 }
169
170
171 private static File objToFile(Object obj) {
172 if( obj instanceof String ) {
173 return new File((String)obj);
174 }
175 if( obj instanceof LuanTable ) {
176 LuanTable t = (LuanTable)obj;
177 Object java = t.rawGet("java");
178 if( java instanceof LuanFile ) {
179 LuanFile luanFile = (LuanFile)java;
180 return luanFile.file;
181 }
182 }
183 return null;
184 }
185
186
187 public static abstract class LuanIn {
188 public abstract InputStream inputStream() throws IOException, LuanException;
189 public abstract String to_string();
190 public abstract String to_uri_string();
191
192 public Reader reader() throws IOException, LuanException {
193 return new InputStreamReader(inputStream());
194 }
195
196 public String read_text() throws IOException, LuanException {
197 Reader in = reader();
198 String s = Utils.readAll(in);
199 in.close();
200 return s;
201 }
202
203 public byte[] read_binary() throws IOException, LuanException {
204 InputStream in = inputStream();
205 byte[] a = Utils.readAll(in);
206 in.close();
207 return a;
208 }
209
210 public LuanFunction read_lines() throws IOException, LuanException {
211 return lines(new BufferedReader(reader()));
212 }
213
214 public LuanFunction read_blocks(Integer blockSize) throws IOException, LuanException {
215 int n = blockSize!=null ? blockSize : Utils.bufSize;
216 return blocks(inputStream(),n);
217 }
218
219 public boolean exists() throws IOException, LuanException {
220 try {
221 inputStream().close();
222 return true;
223 } catch(FileNotFoundException e) {
224 return false;
225 }
226 }
227
228 public LuanTable table() {
229 LuanTable tbl = new LuanTable();
230 try {
231 tbl.rawPut( "java", this );
232 tbl.rawPut( "to_string", new LuanJavaFunction(
233 LuanIn.class.getMethod( "to_string" ), this
234 ) );
235 tbl.rawPut( "to_uri_string", new LuanJavaFunction(
236 LuanIn.class.getMethod( "to_uri_string" ), this
237 ) );
238 tbl.rawPut( "read_text", new LuanJavaFunction(
239 LuanIn.class.getMethod( "read_text" ), this
240 ) );
241 tbl.rawPut( "read_binary", new LuanJavaFunction(
242 LuanIn.class.getMethod( "read_binary" ), this
243 ) );
244 tbl.rawPut( "read_lines", new LuanJavaFunction(
245 LuanIn.class.getMethod( "read_lines" ), this
246 ) );
247 tbl.rawPut( "read_blocks", new LuanJavaFunction(
248 LuanIn.class.getMethod( "read_blocks", Integer.class ), this
249 ) );
250 tbl.rawPut( "exists", new LuanJavaFunction(
251 LuanIn.class.getMethod( "exists" ), this
252 ) );
253 } catch(NoSuchMethodException e) {
254 throw new RuntimeException(e);
255 }
256 return tbl;
257 }
258 }
259
260 public static final LuanIn defaultStdin = new LuanIn() {
261
262 @Override public InputStream inputStream() {
263 return System.in;
264 }
265
266 @Override public String to_string() {
267 return "<stdin>";
268 }
269
270 @Override public String to_uri_string() {
271 return "stdin:";
272 }
273
274 @Override public String read_text() throws IOException {
275 return Utils.readAll(new InputStreamReader(System.in));
276 }
277
278 @Override public byte[] read_binary() throws IOException {
279 return Utils.readAll(System.in);
280 }
281
282 @Override public boolean exists() {
283 return true;
284 }
285 };
286
287 public static abstract class LuanIO extends LuanIn {
288 abstract OutputStream outputStream() throws IOException;
289
290 public void write(Object obj) throws LuanException, IOException {
291 if( obj instanceof String ) {
292 String s = (String)obj;
293 Writer out = new OutputStreamWriter(outputStream());
294 out.write(s);
295 out.close();
296 return;
297 }
298 if( obj instanceof byte[] ) {
299 byte[] a = (byte[])obj;
300 OutputStream out = outputStream();
301 Utils.copyAll(new ByteArrayInputStream(a),out);
302 out.close();
303 return;
304 }
305 if( obj instanceof LuanTable ) {
306 LuanTable t = (LuanTable)obj;
307 Object java = t.rawGet("java");
308 if( java instanceof LuanIn ) {
309 LuanIn luanIn = (LuanIn)java;
310 InputStream in = luanIn.inputStream();
311 OutputStream out = outputStream();
312 Utils.copyAll(in,out);
313 out.close();
314 in.close();
315 return;
316 }
317 }
318 throw new LuanException( "bad argument #1 to 'write' (string or binary or Io.uri expected)" );
319 }
320
321 public LuanTable text_writer() throws IOException {
322 return textWriter(new BufferedWriter(new OutputStreamWriter(outputStream())));
323 }
324
325 public LuanTable binary_writer() throws IOException {
326 return binaryWriter(new BufferedOutputStream(outputStream()));
327 }
328
329 @Override public LuanTable table() {
330 LuanTable tbl = super.table();
331 try {
332 tbl.rawPut( "write", new LuanJavaFunction(
333 LuanIO.class.getMethod( "write", Object.class ), this
334 ) );
335 tbl.rawPut( "text_writer", new LuanJavaFunction(
336 LuanIO.class.getMethod( "text_writer" ), this
337 ) );
338 tbl.rawPut( "binary_writer", new LuanJavaFunction(
339 LuanIO.class.getMethod( "binary_writer" ), this
340 ) );
341 } catch(NoSuchMethodException e) {
342 throw new RuntimeException(e);
343 }
344 return tbl;
345 }
346 }
347
348 private static final LuanIO nullIO = new LuanIO() {
349 private final InputStream in = new InputStream() {
350 @Override public int read() {
351 return -1;
352 }
353 };
354 private final OutputStream out = new OutputStream() {
355 @Override public void write(int b) {}
356 };
357
358 @Override public InputStream inputStream() {
359 return in;
360 }
361
362 @Override OutputStream outputStream() {
363 return out;
364 }
365
366 @Override public String to_string() {
367 return "<null>";
368 }
369
370 @Override public String to_uri_string() {
371 return "null:";
372 }
373
374 };
375
376 public static final class LuanString extends LuanIO {
377 private String s;
378
379 private LuanString(String s) {
380 this.s = s;
381 }
382
383 @Override public InputStream inputStream() {
384 throw new UnsupportedOperationException();
385 }
386
387 @Override OutputStream outputStream() {
388 throw new UnsupportedOperationException();
389 }
390
391 @Override public String to_string() {
392 return "<string>";
393 }
394
395 @Override public String to_uri_string() {
396 return "string:" + s;
397 }
398
399 @Override public Reader reader() {
400 return new StringReader(s);
401 }
402
403 @Override public String read_text() {
404 return s;
405 }
406
407 @Override public boolean exists() {
408 return true;
409 }
410
411 @Override public LuanTable text_writer() throws IOException {
412 LuanWriter luanWriter = new LuanWriter() {
413 private final Writer out = new StringWriter();
414
415 public void write(LuanState luan,Object... args) throws LuanException, IOException {
416 for( Object obj : args ) {
417 out.write( luan.toString(obj) );
418 }
419 }
420
421 public void close() throws IOException {
422 s = out.toString();
423 }
424 };
425 return writer(luanWriter);
426 }
427 }
428
429 public static final class LuanFile extends LuanIO {
430 public final File file;
431
432 private LuanFile(LuanState luan,File file) throws LuanException {
433 this(file);
434 check(luan,"file:"+file.toString());
435 }
436
437 private LuanFile(File file) {
438 this.file = file;
439 }
440
441 @Override public InputStream inputStream() throws IOException {
442 return new FileInputStream(file);
443 }
444
445 @Override OutputStream outputStream() throws IOException {
446 return new FileOutputStream(file);
447 }
448
449 @Override public String to_string() {
450 return file.toString();
451 }
452
453 @Override public String to_uri_string() {
454 return "file:" + file.toString();
455 }
456
457 public LuanTable child(LuanState luan,String name) throws LuanException {
458 return new LuanFile(luan,new File(file,name)).table();
459 }
460
461 public LuanTable children(LuanState luan) throws LuanException {
462 File[] files = file.listFiles();
463 if( files==null )
464 return null;
465 LuanTable list = new LuanTable();
466 for( File f : files ) {
467 list.rawPut(list.rawLength()+1,new LuanFile(luan,f).table());
468 }
469 return list;
470 }
471
472 public LuanTable parent(LuanState luan) throws LuanException, IOException {
473 File parent = file.getParentFile();
474 if( parent==null )
475 parent = file.getCanonicalFile().getParentFile();
476 return new LuanFile(luan,parent).table();
477 }
478
479 @Override public boolean exists() {
480 return file.exists();
481 }
482
483 public void rename_to(Object destObj) throws LuanException {
484 File dest = objToFile(destObj);
485 if( dest==null )
486 throw new LuanException( "bad argument #1 to 'objToFile' (string or file table expected)" );
487 if( !file.renameTo(dest) )
488 throw new LuanException("couldn't rename file "+file+" to "+dest);
489 }
490
491 public LuanTable canonical(LuanState luan) throws LuanException, IOException {
492 return new LuanFile(luan,file.getCanonicalFile()).table();
493 }
494
495 public LuanTable create_temp_file(LuanState luan,String prefix,String suffix) throws LuanException, IOException {
496 File tmp = File.createTempFile(prefix,suffix,file);
497 return new LuanFile(luan,tmp).table();
498 }
499
500 public void delete() throws LuanException {
501 if( file.exists() )
502 delete(file);
503 }
504
505 private static void delete(File file) throws LuanException {
506 File[] children = file.listFiles();
507 if( children != null ) {
508 for( File child : children ) {
509 delete(child);
510 }
511 }
512 if( !file.delete() )
513 throw new LuanException("couldn't delete file "+file);
514 }
515
516 public void mkdir() throws LuanException {
517 if( !file.isDirectory() ) {
518 if( !file.mkdirs() )
519 throw new LuanException("couldn't make directory "+file);
520 }
521 }
522
523 public void set_last_modified(long time) throws LuanException {
524 if( !file.setLastModified(time) )
525 throw new LuanException("couldn't set_last_modified on "+file);
526 }
527
528 @Override public LuanTable table() {
529 LuanTable tbl = super.table();
530 try {
531 tbl.rawPut( "name", new LuanJavaFunction(
532 File.class.getMethod( "getName" ), file
533 ) );
534 tbl.rawPut( "is_directory", new LuanJavaFunction(
535 File.class.getMethod( "isDirectory" ), file
536 ) );
537 tbl.rawPut( "is_file", new LuanJavaFunction(
538 File.class.getMethod( "isFile" ), file
539 ) );
540 tbl.rawPut( "delete", new LuanJavaFunction(
541 LuanFile.class.getMethod( "delete" ), this
542 ) );
543 tbl.rawPut( "delete_on_exit", new LuanJavaFunction(
544 File.class.getMethod( "deleteOnExit" ), file
545 ) );
546 tbl.rawPut( "mkdir", new LuanJavaFunction(
547 LuanFile.class.getMethod( "mkdir" ), this
548 ) );
549 tbl.rawPut( "last_modified", new LuanJavaFunction(
550 File.class.getMethod( "lastModified" ), file
551 ) );
552 tbl.rawPut( "set_last_modified", new LuanJavaFunction(
553 LuanFile.class.getMethod( "set_last_modified", Long.TYPE ), this
554 ) );
555 tbl.rawPut( "length", new LuanJavaFunction(
556 File.class.getMethod( "length" ), file
557 ) );
558 tbl.rawPut( "child", new LuanJavaFunction(
559 LuanFile.class.getMethod( "child", LuanState.class, String.class ), this
560 ) );
561 tbl.rawPut( "children", new LuanJavaFunction(
562 LuanFile.class.getMethod( "children", LuanState.class ), this
563 ) );
564 tbl.rawPut( "parent", new LuanJavaFunction(
565 LuanFile.class.getMethod( "parent", LuanState.class ), this
566 ) );
567 tbl.rawPut( "rename_to", new LuanJavaFunction(
568 LuanFile.class.getMethod( "rename_to", Object.class ), this
569 ) );
570 tbl.rawPut( "canonical", new LuanJavaFunction(
571 LuanFile.class.getMethod( "canonical", LuanState.class ), this
572 ) );
573 tbl.rawPut( "create_temp_file", new LuanJavaFunction(
574 LuanFile.class.getMethod( "create_temp_file", LuanState.class, String.class, String.class ), this
575 ) );
576 } catch(NoSuchMethodException e) {
577 throw new RuntimeException(e);
578 }
579 return tbl;
580 }
581 }
582
583 public static LuanTable null_() {
584 return nullIO.table();
585 }
586
587 public static LuanTable string(String s) throws LuanException {
588 Utils.checkNotNull(s);
589 return new LuanString(s).table();
590 }
591
592 public static LuanTable file(LuanState luan,String name) throws LuanException {
593 File file = new File(name);
594 return new LuanFile(file).table();
595 }
596
597 public static LuanTable classpath(LuanState luan,String name) throws LuanException {
598 if( name.contains("//") )
599 return null;
600 String path = name;
601 check(luan,"classpath:"+path);
602 URL url;
603 if( !path.contains("#") ) {
604 url = ClassLoader.getSystemResource(path);
605 } else {
606 String[] a = path.split("#");
607 url = ClassLoader.getSystemResource(a[0]);
608 if( url==null ) {
609 for( int i=1; i<a.length; i++ ) {
610 url = ClassLoader.getSystemResource(a[0]+"/"+a[i]);
611 if( url != null ) {
612 try {
613 url = new URL(url,".");
614 } catch(MalformedURLException e) {
615 throw new RuntimeException(e);
616 }
617 break;
618 }
619 }
620 }
621 }
622 if( url != null )
623 return new LuanUrl(luan,url,null).table();
624
625 return null;
626 }
627
628 private static LuanTable url(LuanState luan,String url,LuanTable options) throws IOException, LuanException {
629 return new LuanUrl(luan,new URL(url),options).table();
630 }
631
632 public static LuanTable http(LuanState luan,String path,LuanTable options) throws IOException, LuanException {
633 return url(luan,"http:"+path,options);
634 }
635
636 public static LuanTable https(LuanState luan,String path,LuanTable options) throws IOException, LuanException {
637 return url(luan,"https:"+path,options);
638 }
639
640 public static LuanTable luan(LuanState luan,String path) throws LuanException {
641 return classpath( luan, "luan/modules/" + path );
642 }
643
644 public static LuanTable stdin(LuanState luan) throws LuanException {
645 LuanTable io = (LuanTable)PackageLuan.require(luan,"luan:Io.luan");
646 return (LuanTable)io.get(luan,"stdin");
647 }
648
649 public static LuanTable newSchemes() {
650 LuanTable schemes = new LuanTable();
651 try {
652 schemes.rawPut( "null", new LuanJavaFunction(IoLuan.class.getMethod("null_"),null) );
653 add( schemes, "string", String.class );
654 add( schemes, "file", LuanState.class, String.class );
655 add( schemes, "classpath", LuanState.class, String.class );
656 add( schemes, "socket", String.class );
657 add( schemes, "http", LuanState.class, String.class, LuanTable.class );
658 add( schemes, "https", LuanState.class, String.class, LuanTable.class );
659 add( schemes, "luan", LuanState.class, String.class );
660 add( schemes, "stdin", LuanState.class );
661 add( schemes, "os", LuanState.class, String.class, LuanTable.class );
662 } catch(NoSuchMethodException e) {
663 throw new RuntimeException(e);
664 }
665 return schemes;
666 }
667
668 private static LuanTable schemes(LuanState luan) throws LuanException {
669 LuanTable t = (LuanTable)PackageLuan.loaded(luan).rawGet("luan:Io.luan");
670 if( t == null )
671 return newSchemes();
672 t = (LuanTable)t.get(luan,"schemes");
673 if( t == null )
674 return newSchemes();
675 return t;
676 }
677
678 public static LuanTable uri(LuanState luan,String name,LuanTable options) throws LuanException {
679 int i = name.indexOf(':');
680 if( i == -1 )
681 throw new LuanException( "invalid Io.uri name '"+name+"', missing scheme" );
682 String scheme = name.substring(0,i);
683 String location = name.substring(i+1);
684 LuanTable schemes = schemes(luan);
685 LuanFunction opener = (LuanFunction)schemes.get(luan,scheme);
686 if( opener == null )
687 throw new LuanException( "invalid scheme '"+scheme+"' in '"+name+"'" );
688 return (LuanTable)Luan.first(opener.call(luan,new Object[]{location,options}));
689 }
690
691 public static final class LuanSocket extends LuanIO {
692 public final Socket socket;
693
694 private LuanSocket(String host,int port) throws LuanException {
695 try {
696 this.socket = new Socket(host,port);
697 } catch(IOException e) {
698 throw new LuanException(e.toString());
699 }
700 }
701
702 private LuanSocket(Socket socket) {
703 this.socket = socket;
704 }
705
706 @Override public InputStream inputStream() throws IOException {
707 return socket.getInputStream();
708 }
709
710 @Override OutputStream outputStream() throws IOException {
711 return socket.getOutputStream();
712 }
713
714 @Override public String to_string() {
715 return socket.toString();
716 }
717
718 @Override public String to_uri_string() {
719 throw new UnsupportedOperationException();
720 }
721 }
722
723 public static LuanTable socket(String name) throws LuanException, IOException {
724 int i = name.indexOf(':');
725 if( i == -1 )
726 throw new LuanException( "invalid socket '"+name+"', format is: <host>:<port>" );
727 String host = name.substring(0,i);
728 String portStr = name.substring(i+1);
729 int port = Integer.parseInt(portStr);
730 return new LuanSocket(host,port).table();
731 }
732
733 public static LuanFunction socket_server(int port) throws IOException {
734 final ServerSocket ss = new ServerSocket(port);
735 return new LuanFunction() {
736 @Override public Object call(LuanState luan,Object[] args) throws LuanException {
737 try {
738 if( args.length > 0 ) {
739 if( args.length > 1 || !"close".equals(args[0]) )
740 throw new LuanException( "the only argument allowed is 'close'" );
741 ss.close();
742 return null;
743 }
744 return new LuanSocket(ss.accept()).table();
745 } catch(IOException e) {
746 throw new LuanException(e);
747 }
748 }
749 };
750 }
751
752
753 public static final class LuanOs extends LuanIO {
754 private final String cmd;
755 private final Process proc;
756
757 private LuanOs(LuanState luan,String cmd,LuanTable options) throws IOException, LuanException {
758 this.cmd = cmd;
759 File dir = null;
760 if( options != null ) {
761 Map map = options.asMap(luan);
762 Object obj = map.remove("dir");
763 dir = objToFile(obj);
764 if( dir==null )
765 throw new LuanException( "bad option 'dir' (string or file table expected)" );
766 if( !map.isEmpty() )
767 throw new LuanException( "unrecognized options: "+map );
768 }
769 this.proc = Runtime.getRuntime().exec(cmd,null,dir);
770 }
771
772 @Override public InputStream inputStream() throws IOException {
773 return proc.getInputStream();
774 }
775
776 @Override OutputStream outputStream() throws IOException {
777 return proc.getOutputStream();
778 }
779
780 @Override public String to_string() {
781 return proc.toString();
782 }
783
784 @Override public String to_uri_string() {
785 throw new UnsupportedOperationException();
786 }
787
788 @Override public boolean exists() {
789 return true;
790 }
791
792 public void wait_for()
793 throws IOException, LuanException
794 {
795 try {
796 proc.waitFor();
797 } catch(InterruptedException e) {
798 throw new RuntimeException(e);
799 }
800 int exitVal = proc.exitValue();
801 if( exitVal != 0 ) {
802 Reader err = new InputStreamReader(proc.getErrorStream());
803 String error = "error in: "+cmd+"\n"+Utils.readAll(err);
804 err.close();
805 throw new LuanException(error);
806 }
807 }
808
809 @Override public String read_text() throws IOException, LuanException {
810 String s = super.read_text();
811 wait_for();
812 return s;
813 }
814
815 @Override public LuanTable table() {
816 LuanTable tbl = super.table();
817 try {
818 tbl.rawPut( "wait_for", new LuanJavaFunction(
819 LuanOs.class.getMethod( "wait_for" ), this
820 ) );
821 } catch(NoSuchMethodException e) {
822 throw new RuntimeException(e);
823 }
824 return tbl;
825 }
826 }
827
828 public static LuanTable os(LuanState luan,String cmd,LuanTable options) throws IOException, LuanException {
829 return new LuanOs(luan,cmd,options).table();
830 }
831
832
833 public static String ip(String domain) {
834 try {
835 return InetAddress.getByName(domain).getHostAddress();
836 } catch(UnknownHostException e) {
837 return null;
838 }
839 }
840
841 public static LuanTable my_ips() throws IOException {
842 LuanTable tbl = new LuanTable();
843 for( Enumeration<NetworkInterface> e1 = NetworkInterface.getNetworkInterfaces(); e1.hasMoreElements(); ) {
844 NetworkInterface ni = e1.nextElement();
845 for( Enumeration<InetAddress> e2 = ni.getInetAddresses(); e2.hasMoreElements(); ) {
846 InetAddress ia = e2.nextElement();
847 if( ia instanceof Inet4Address )
848 tbl.rawPut(ia.getHostAddress(),true);
849 }
850 }
851 return tbl;
852 }
853
854 /*
855 // files maps zip name to uri
856 public static void zip(LuanState luan,String zipUri,LuanTable files) throws LuanException, IOException {
857 Object obj = uri(luan,zipUri,null).rawGet("java");
858 if( !(obj instanceof LuanIO) )
859 throw new LuanException("invalid uri for zip");
860 LuanIO zipIo = (LuanIO)obj;
861 ZipOutputStream out = new ZipOutputStream(zipIo.outputStream());
862 for( Map.Entry<Object,Object> entry : files.iterable(luan) ) {
863 obj = entry.getKey();
864 if( !(obj instanceof String) )
865 throw new LuanException("zip file table keys must be strings");
866 String fileName = (String)obj;
867 obj = entry.getValue();
868 if( !(obj instanceof String) )
869 throw new LuanException("zip file table values must be strings");
870 String uriStr = (String)obj;
871 out.putNextEntry(new ZipEntry(fileName));
872 obj = uri(luan,uriStr,null).rawGet("java");
873 if( !(obj instanceof LuanIn) )
874 throw new LuanException("invalid uri for zip");
875 LuanIn zipIn = (LuanIn)obj;
876 InputStream in = zipIn.inputStream();
877 Utils.copyAll(in,out);
878 in.close();
879 out.closeEntry();
880 }
881 out.close();
882 }
883 */
884
885 // security
886
887 public interface Security {
888 public void check(LuanState luan,String name) throws LuanException;
889 }
890
891 private static String SECURITY_KEY = "Io.Security";
892
893 private static void check(LuanState luan,String name) throws LuanException {
894 Security s = (Security)luan.registry().get(SECURITY_KEY);
895 if( s!=null )
896 s.check(luan,name);
897 }
898
899 public static void setSecurity(LuanState luan,Security s) {
900 luan.registry().put(SECURITY_KEY,s);
901 }
902
903 private void IoLuan() {} // never
904 }