Initial commit with hopefully working J2EE request handler.
[jsvc.git] / src / dolda / jsvc / util / ResponseBuffer.java
1 package dolda.jsvc.util;
2
3 import dolda.jsvc.*;
4 import java.io.*;
5 import java.util.*;
6
7 public abstract class ResponseBuffer implements Request {
8     private boolean flushed = false;
9     private int respcode = -1;
10     private String resptext = null;
11     private OutputStream out = null, wrapout = null;
12     private MultiMap<String, String> headers = new HeaderTreeMap() {
13             protected void modified() {
14                 ckflush();
15             }
16     };
17     
18     private void ckflush() {
19         if(flushed)
20             throw(new IllegalStateException("Response has been flushed; header information cannot be modified"));
21     }
22     
23     private void flush() {
24         if(flushed)
25             return;
26         if(respcode < 0) {
27             respcode = 200;
28             resptext = "OK";
29         }
30         backflush();
31         out = realoutput();
32         flushed = true;
33     }
34
35     private class FlushStream extends OutputStream {
36         private FlushStream() {
37         }
38         
39         public void flush() throws IOException {
40             ResponseBuffer.this.flush();
41             out.flush();
42         }
43         
44         public void close() throws IOException {
45             flush();
46             out.close();
47         }
48         
49         public void write(int b) throws IOException {
50             ResponseBuffer.this.flush();
51             out.write(b);
52         }
53         
54         public void write(byte[] b) throws IOException {
55             write(b, 0, b.length);
56         }
57         
58         public void write(byte[] b, int off, int len) throws IOException {
59             ResponseBuffer.this.flush();
60             out.write(b, off, len);
61         }
62     }
63
64     public OutputStream output() {
65         if(wrapout == null)
66             wrapout = new BufferedOutputStream(new FlushStream(), 16384);
67         return(wrapout);
68     }
69
70     public void status(int code) {
71         status(code, Misc.statustext(code));
72     }
73     
74     public void status(int code, String text) {
75         ckflush();
76         respcode = code;
77         resptext = text;
78     }
79     
80     public MultiMap<String, String> outheaders() {
81         return(headers);
82     }
83     
84     protected abstract void backflush();
85     protected abstract OutputStream realoutput();
86 }