public StringFountain(String s) { super(s); }
}
+ public static class SubFountain implements Fountain {
+ private final Fountain f;
+ private final int start;
+ private final int len;
+ public SubFountain(Fountain f, int start) { this(f, start, -1); }
+ public SubFountain(Fountain f, int start, int len) {
+ this.f = f;
+ this.start = start;
+ this.len = len;
+ }
+ public Stream getStream() {
+ Stream s = f.getStream();
+ // FIXME: this is really fragile and IMAP needs it
+ int remain = start;
+ while(remain > 0) {
+ long result = s.skip(start);
+ Log.error("skip", result + " / " + start);
+ if (result == -1) return s;
+ remain -= result;
+ }
+ if (len != -1) s.setLimit(len);
+ return s;
+ }
+ public long getLength() {
+ if (len == -1) return f.getLength()-start;
+ return Math.min(f.getLength()-start, len);
+ }
+ public int getNumLines() { return Stream.countLines(getStream()); }
+ }
+
public static class Concatenate implements Fountain {
private Fountain[] founts;
public Concatenate(Fountain f1, Fountain f2) { this(new Fountain[] { f1, f2 }); }
}
}
+ // FIXME: untested
+ // note: only one ResultSet is allowed per Statement
+ public static class DatabaseColumn implements Fountain {
+ private ResultSet rs;
+ private int row;
+ private int column;
+ public DatabaseColumn(ResultSet rs, int column) throws SQLException {
+ this(rs, column, rs.getRow());
+ }
+ public DatabaseColumn(ResultSet rs, int column, int row) throws SQLException {
+ this.rs = rs;
+ this.row = row;
+ this.column = column;
+ synchronized(rs) {
+ int type = rs.getType();
+ if ((type | ResultSet.TYPE_SCROLL_INSENSITIVE) == 0)
+ throw new RuntimeException("Fountain.DatabaseColumn(ResultSet,int) requires a SCROLL_INSENSITIVE ResultSet");
+ if ((type | ResultSet.TYPE_FORWARD_ONLY) != 0)
+ throw new RuntimeException("Fountain.DatabaseColumn(ResultSet,int) cannot use TYPE_FORWARD_ONLY ResultSets");
+ }
+ // FIXME: do we want to check HOLD_CURSORS_OVER_COMMIT ?
+ }
+ private Blob getBlob() throws SQLException {
+ synchronized(rs) {
+ if (!rs.absolute(row))
+ throw new RuntimeException("resultset was unable to move to desired row");
+ return rs.getBlob(column);
+ }
+ }
+ public Stream getStream() {
+ try {
+ synchronized(rs) {
+ return new Stream(rs.getBinaryStream(column));
+ }
+ } catch (SQLException e) { throw new RuntimeException(e); }
+ }
+ public long getLength() {
+ try {
+ synchronized(rs) {
+ return getBlob().length();
+ }
+ } catch (SQLException e) { throw new RuntimeException(e); }
+ }
+ public int getNumLines() {
+ throw new RuntimeException("not implemented");
+ }
+ }
+
+
//public static class LazyCachingStreamFountain implements Fountain {
//}
*/
public static class Util {
+ public static Fountain subFountain(Fountain f, int start) { return new SubFountain(f, start); }
+ public static Fountain subFountain(Fountain f, int start, int len) { return new SubFountain(f, start, len); }
public static Fountain create(String s) { return new StringFountain(s); }
public static Fountain concat(Fountain[] f) { return new Concatenate(f); }
public static Fountain concat(Fountain f1, Fountain f2) {