2003/09/19 05:26:46
[org.ibex.core.git] / src / org / xwt / ByteStream.java
1 // Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL]
2
3 package org.xwt;
4 import java.io.*;
5 import java.util.*;
6 import org.xwt.js.*;
7 import org.xwt.util.*;
8
9 /** A ByteStream encapsulates a <i>source</i> of a stream of bytes --
10  *  currently either a local file or a Base64-encoded XMLRPC/SOAP element */
11 public class ByteStream extends JS.Obj {
12
13     private byte[] bytes = null;
14     private File file = null;
15
16     private ByteStream() { setSeal(true); }
17     ByteStream(String filename) { this(); this.file = new File(filename); }
18     ByteStream(byte[] bytes) { this(); this.bytes = bytes; }
19
20     public String toString() { return "ByteStream, source=" + (file == null ? "memory" : file.getAbsolutePath()); }
21
22     public Object get(Object name) {
23         if (name.equals("getUTF")) return getUTF;
24         else if (name.equals("getDOM")) return getDOM;
25         else if (name.equals("fileName")) return file == null ? null : file.getAbsolutePath();
26         else return null;
27     }
28
29     private class XMLHelper extends XML {
30         Vector obStack = new Vector();
31
32         public XMLHelper() { super(BUFFER_SIZE); }
33
34         public void startElement(XML.Element c) throws XML.SchemaException {
35             JS o = new JS.Obj();
36             o.put("$name", c.localName);
37             for(int i=0; i<c.len; i++) o.put(c.keys[i], c.vals[i]);
38             o.put("$numchildren", new Integer(0));
39             obStack.addElement(o);
40         }
41
42         public void endElement(XML.Element c) throws XML.SchemaException {
43             if (obStack.size() == 1) return;
44             JS me = (JS)obStack.lastElement();
45             obStack.setSize(obStack.size() - 1);
46             JS parent = (JS)obStack.lastElement();
47             int numchildren = ((Integer)parent.get("$numchildren")).intValue();
48             parent.put("$numchildren", new Integer(numchildren + 1));
49             parent.put(new Integer(numchildren), me);
50         }
51
52         public void characters(char[] ch, int start, int length) throws XML.SchemaException {
53             String s = new String(ch, start, length);
54             JS parent = (JS)obStack.lastElement();
55             int numchildren = ((Integer)parent.get("$numchildren")).intValue();
56             Object lastChild = parent.get(new Integer(numchildren - 1));
57             if (lastChild instanceof String) {
58                 parent.put(new Integer(numchildren - 1), lastChild + s);
59             } else {
60                 parent.put("$numchildren", new Integer(numchildren + 1));
61                 parent.put(new Integer(numchildren), s);
62             }
63         }
64
65         public void whitespace(char[] ch, int start, int length) {}
66
67         public JS doParse() throws JS.Exn {
68             try { 
69                 InputStream is = getInputStream();
70                 BufferedReader r = new BufferedReader(new InputStreamReader(is));
71                 parse(r);
72             } catch (XML.XMLException e) {
73                 throw new JS.Exn("error parsing XML: " + e.toString());
74             } catch (IOException e) {
75                 if (Log.on) Log.log(ByteStream.class, "IO Exception while reading from file");
76                 if (Log.on) Log.log(ByteStream.class, e);
77                 throw new JS.Exn("error reading from ByteStream");
78             }
79             return obStack.size() >= 1 ? (JS)obStack.elementAt(0) : null;
80         }
81     }
82
83     public InputStream getInputStream() throws IOException {
84         return file == null ?
85             (InputStream)(new ByteArrayInputStream(bytes)) :
86             (InputStream)(new FileInputStream(file));
87     }
88
89     public void writeTo(OutputStream os) throws IOException {
90         InputStream is = getInputStream();
91         byte[] buf = new byte[1024];
92         while(true) {
93             int numread = is.read(buf, 0, 1024);
94             if (numread == -1) break;
95             if (Log.on) Log.log(this, "wrote " + numread + " bytes");
96             os.write(buf, 0, numread);
97         }
98         os.flush();
99
100         // we have to close this because flush() doesn't work on Win32-GCJ
101         os.close();
102     }
103
104     private final JS.Callable getDOM = new JS.Callable() {
105             public Object call(JS.Array args) throws JS.Exn {
106                 if (args.length() != 0) return null;
107                 return new XMLHelper().doParse();
108             }
109         };
110
111     private final JS.Callable getUTF = new JS.Callable() {
112             public Object call(JS.Array args) throws JS.Exn {
113                 if (args.length() != 0) return null;
114                 try {
115                     CharArrayWriter caw = new CharArrayWriter();
116                     InputStream is = getInputStream();
117                     BufferedReader r = new BufferedReader(new InputStreamReader(is));
118                     char[] buf = new char[1024];
119                     while(true) {
120                         int numread = r.read(buf, 0, 1024);
121                         if (numread == -1) break;
122                         caw.write(buf, 0, numread);
123                     }
124                     return caw.toString();
125                 } catch (IOException e) {
126                     if (Log.on) Log.log(ByteStream.class, "IO Exception while reading from file");
127                     if (Log.on) Log.log(ByteStream.class, e);
128                     throw new JS.Exn("error while reading from ByteStream");
129                 }
130             }
131         };
132
133 }
134