Actually set the HTTP status code...
[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 ResettableRequest {
8     private boolean flushed = false;
9     protected int respcode = -1;
10     protected String resptext = null;
11     private OutputStream out = null, wrapout = null;
12     private MultiMap<String, String> headers;
13     
14     public ResponseBuffer() {
15         init();
16     }
17
18     private void init() {
19         ckflush();
20         wrapout = null;
21         respcode = -1;
22         headers = new HeaderTreeMap() {
23                 protected void modified() {
24                     ckflush();
25                 }
26             };
27     }
28     
29     private void ckflush() {
30         if(flushed)
31             throw(new IllegalStateException("Response has been flushed; header information cannot be modified"));
32     }
33     
34     private void flush() {
35         if(flushed)
36             return;
37         if(respcode < 0) {
38             respcode = 200;
39             resptext = "OK";
40         }
41         backflush();
42         out = realoutput();
43         flushed = true;
44     }
45
46     private class FlushStream extends OutputStream {
47         private FlushStream() {
48         }
49         
50         public void flush() throws IOException {
51             ResponseBuffer.this.flush();
52             out.flush();
53         }
54         
55         public void close() throws IOException {
56             flush();
57             out.close();
58         }
59         
60         public void write(int b) throws IOException {
61             ResponseBuffer.this.flush();
62             out.write(b);
63         }
64         
65         public void write(byte[] b) throws IOException {
66             write(b, 0, b.length);
67         }
68         
69         public void write(byte[] b, int off, int len) throws IOException {
70             ResponseBuffer.this.flush();
71             out.write(b, off, len);
72         }
73     }
74
75     public OutputStream output() {
76         if(wrapout == null)
77             wrapout = new BufferedOutputStream(new FlushStream(), 16384);
78         return(wrapout);
79     }
80
81     public void status(int code) {
82         status(code, Misc.statustext(code));
83     }
84     
85     public void status(int code, String text) {
86         ckflush();
87         respcode = code;
88         resptext = text;
89     }
90     
91     public MultiMap<String, String> outheaders() {
92         return(headers);
93     }
94     
95     public boolean canreset() {
96         return(!flushed);
97     }
98     
99     public void reset() {
100         init();
101     }
102     
103     protected abstract void backflush();
104     protected abstract OutputStream realoutput();
105 }