1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
10 import java.util.zip.*;
11 import org.ibex.util.*;
14 /** a source of streams */
15 public interface Fountain {
17 public Stream getStream();
18 public long getLength();
19 public int getNumLines();
21 public static class File implements Fountain {
22 private final java.io.File file;
23 public File(java.io.File file) { this.file = file; }
24 public Stream getStream() { return new Stream(file); }
25 public long getLength() { return (int)file.length(); }
26 public int getNumLines() { return Stream.countLines(getStream()); }
29 // sketchy since the bytes can be modified
30 public static class ByteArray implements Fountain {
31 private final byte[] bytes;
32 private final int off;
33 private final int len;
34 protected ByteArray(String s) {
36 byte[] bytes = s.getBytes("UTF-8");
39 this.len = bytes.length;
40 } catch (UnsupportedEncodingException e) {
41 throw new RuntimeException(e);
44 public ByteArray(byte[] bytes) { this(bytes, 0, bytes.length); }
45 public ByteArray(byte[] bytes, int off, int len) { this.bytes = bytes; this.off=off; this.len=len; }
46 public Stream getStream() { return new Stream(bytes, off, len); }
47 public long getLength() { return len; }
48 public int getNumLines() { return Stream.countLines(getStream()); }
52 public static class StringFountain extends ByteArray {
53 public StringFountain(String s) { super(s); }
56 public static class SubFountain implements Fountain {
57 private final Fountain f;
58 private final int start;
59 private final int len;
60 public SubFountain(Fountain f, int start) { this(f, start, -1); }
61 public SubFountain(Fountain f, int start, int len) {
66 public Stream getStream() {
67 Stream s = f.getStream();
68 // FIXME: this is really fragile and IMAP needs it
71 long result = s.skip(start);
72 Log.error("skip", result + " / " + start);
73 if (result == -1) return s;
76 if (len != -1) s.setLimit(len);
79 public long getLength() {
80 if (len == -1) return f.getLength()-start;
81 return Math.min(f.getLength()-start, len);
83 public int getNumLines() { return Stream.countLines(getStream()); }
86 public static class Concatenate implements Fountain {
87 private Fountain[] founts;
88 public Concatenate(Fountain f1, Fountain f2) { this(new Fountain[] { f1, f2 }); }
89 public Concatenate(Fountain[] f) { this.founts = f; }
90 public Stream getStream() {
92 for(int i=founts.length-1; i>=0; i--)
93 ret = ret==null ? founts[i].getStream() : founts[i].getStream().appendStream(ret);
96 public long getLength() {
98 for(int i=0; i<founts.length; i++)
99 ret += founts[i].getLength();
102 public int getNumLines() {
104 for(int i=0; i<founts.length; i++)
105 ret += founts[i].getNumLines();
111 // note: only one ResultSet is allowed per Statement
112 public static class DatabaseColumn implements Fountain {
113 private ResultSet rs;
116 public DatabaseColumn(ResultSet rs, int column) throws SQLException {
117 this(rs, column, rs.getRow());
119 public DatabaseColumn(ResultSet rs, int column, int row) throws SQLException {
122 this.column = column;
124 int type = rs.getType();
125 if ((type | ResultSet.TYPE_SCROLL_INSENSITIVE) == 0)
126 throw new RuntimeException("Fountain.DatabaseColumn(ResultSet,int) requires a SCROLL_INSENSITIVE ResultSet");
127 if ((type | ResultSet.TYPE_FORWARD_ONLY) != 0)
128 throw new RuntimeException("Fountain.DatabaseColumn(ResultSet,int) cannot use TYPE_FORWARD_ONLY ResultSets");
130 // FIXME: do we want to check HOLD_CURSORS_OVER_COMMIT ?
132 private Blob getBlob() throws SQLException {
134 if (!rs.absolute(row))
135 throw new RuntimeException("resultset was unable to move to desired row");
136 return rs.getBlob(column);
139 public Stream getStream() {
142 return new Stream(rs.getBinaryStream(column));
144 } catch (SQLException e) { throw new RuntimeException(e); }
146 public long getLength() {
149 return getBlob().length();
151 } catch (SQLException e) { throw new RuntimeException(e); }
153 public int getNumLines() {
154 throw new RuntimeException("not implemented");
159 //public static class LazyCachingStreamFountain implements Fountain {
163 public static interface Transformer {
164 public Fountain transform(Fountain in);
166 public static class Lift implements Fountain.Transformer {
167 private final Stream.Transformer func;
168 public Lift(Stream.Transformer func) { this.func = func; }
169 public Fountain transform(final Fountain in) {
170 return new Fountain() {
171 public Stream getStream() {
172 return func.transform(in.getStream()); } };
178 public static class Util {
179 public static Fountain subFountain(Fountain f, int start) { return new SubFountain(f, start); }
180 public static Fountain subFountain(Fountain f, int start, int len) { return new SubFountain(f, start, len); }
181 public static Fountain create(String s) { return new StringFountain(s); }
182 public static Fountain concat(Fountain[] f) { return new Concatenate(f); }
183 public static Fountain concat(Fountain f1, Fountain f2) {
184 return new Concatenate(f1, f2);
186 public static Fountain concat(Fountain f1, Fountain f2, Fountain f3) {
187 return new Concatenate(f1, new Concatenate(f2, f3));