1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server;
15
16 import java.io.IOException;
17 import java.io.OutputStreamWriter;
18 import java.io.Writer;
19
20 import org.eclipse.jetty.http.AbstractGenerator;
21 import org.eclipse.jetty.util.ByteArrayOutputStream2;
22 import org.eclipse.jetty.util.StringUtil;
23
24
25
26
27
28
29
30
31
32 public class HttpWriter extends Writer
33 {
34 private static final int WRITE_CONV = 0;
35 private static final int WRITE_ISO1 = 1;
36 private static final int WRITE_UTF8 = 2;
37
38 final HttpOutput _out;
39 final AbstractGenerator _generator;
40 int _writeMode;
41 int _surrogate;
42
43
44 public HttpWriter(HttpOutput out)
45 {
46 _out=out;
47 _generator=_out._generator;
48
49 }
50
51
52 public void setCharacterEncoding(String encoding)
53 {
54 if (encoding == null || StringUtil.__ISO_8859_1.equalsIgnoreCase(encoding))
55 {
56 _writeMode = WRITE_ISO1;
57 }
58 else if (StringUtil.__UTF8.equalsIgnoreCase(encoding))
59 {
60 _writeMode = WRITE_UTF8;
61 }
62 else
63 {
64 _writeMode = WRITE_CONV;
65 if (_out._characterEncoding == null || !_out._characterEncoding.equalsIgnoreCase(encoding))
66 _out._converter = null;
67 }
68
69 _out._characterEncoding = encoding;
70 if (_out._bytes==null)
71 _out._bytes = new ByteArrayOutputStream2(AbstractGenerator.MAX_OUTPUT_CHARS);
72 }
73
74
75 public void close() throws IOException
76 {
77 _out.close();
78 }
79
80
81 public void flush() throws IOException
82 {
83 _out.flush();
84 }
85
86
87 public void write (String s,int offset, int length) throws IOException
88 {
89 while (length > AbstractGenerator.MAX_OUTPUT_CHARS)
90 {
91 write(s, offset, AbstractGenerator.MAX_OUTPUT_CHARS);
92 offset += AbstractGenerator.MAX_OUTPUT_CHARS;
93 length -= AbstractGenerator.MAX_OUTPUT_CHARS;
94 }
95
96 if (_out._chars==null)
97 {
98 _out._chars = new char[AbstractGenerator.MAX_OUTPUT_CHARS];
99 }
100 char[] chars = _out._chars;
101 s.getChars(offset, offset + length, chars, 0);
102 write(chars, 0, length);
103 }
104
105
106 public void write (char[] s,int offset, int length) throws IOException
107 {
108 HttpOutput out = _out;
109
110 while (length > 0)
111 {
112 out._bytes.reset();
113 int chars = length>AbstractGenerator.MAX_OUTPUT_CHARS?AbstractGenerator.MAX_OUTPUT_CHARS:length;
114
115 switch (_writeMode)
116 {
117 case WRITE_CONV:
118 {
119 Writer converter=getConverter();
120 converter.write(s, offset, chars);
121 converter.flush();
122 }
123 break;
124
125 case WRITE_ISO1:
126 {
127 byte[] buffer=out._bytes.getBuf();
128 int bytes=out._bytes.getCount();
129
130 if (chars>buffer.length-bytes)
131 chars=buffer.length-bytes;
132
133 for (int i = 0; i < chars; i++)
134 {
135 int c = s[offset+i];
136 buffer[bytes++]=(byte)(c<256?c:'?');
137 }
138 if (bytes>=0)
139 out._bytes.setCount(bytes);
140
141 break;
142 }
143
144 case WRITE_UTF8:
145 {
146 byte[] buffer=out._bytes.getBuf();
147 int bytes=out._bytes.getCount();
148
149 if (bytes+chars>buffer.length)
150 chars=buffer.length-bytes;
151
152 for (int i = 0; i < chars; i++)
153 {
154 int code = s[offset+i];
155
156 if ((code & 0xffffff80) == 0)
157 {
158
159 buffer[bytes++]=(byte)(code);
160 }
161 else if((code&0xfffff800)==0)
162 {
163
164 if (bytes+2>buffer.length)
165 {
166 chars=i;
167 break;
168 }
169 buffer[bytes++]=(byte)(0xc0|(code>>6));
170 buffer[bytes++]=(byte)(0x80|(code&0x3f));
171
172 if (bytes+chars-i-1>buffer.length)
173 chars-=1;
174 }
175 else if((code&0xffff0000)==0)
176 {
177
178 if (bytes+3>buffer.length)
179 {
180 chars=i;
181 break;
182 }
183 buffer[bytes++]=(byte)(0xe0|(code>>12));
184 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
185 buffer[bytes++]=(byte)(0x80|(code&0x3f));
186
187 if (bytes+chars-i-1>buffer.length)
188 chars-=2;
189 }
190 else if((code&0xff200000)==0)
191 {
192
193 if (bytes+4>buffer.length)
194 {
195 chars=i;
196 break;
197 }
198 buffer[bytes++]=(byte)(0xf0|(code>>18));
199 buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
200 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
201 buffer[bytes++]=(byte)(0x80|(code&0x3f));
202
203 if (bytes+chars-i-1>buffer.length)
204 chars-=3;
205 }
206 else if((code&0xf4000000)==0)
207 {
208
209 if (bytes+5>buffer.length)
210 {
211 chars=i;
212 break;
213 }
214 buffer[bytes++]=(byte)(0xf8|(code>>24));
215 buffer[bytes++]=(byte)(0x80|((code>>18)&0x3f));
216 buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
217 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
218 buffer[bytes++]=(byte)(0x80|(code&0x3f));
219
220 if (bytes+chars-i-1>buffer.length)
221 chars-=4;
222 }
223 else if((code&0x80000000)==0)
224 {
225
226 if (bytes+6>buffer.length)
227 {
228 chars=i;
229 break;
230 }
231 buffer[bytes++]=(byte)(0xfc|(code>>30));
232 buffer[bytes++]=(byte)(0x80|((code>>24)&0x3f));
233 buffer[bytes++]=(byte)(0x80|((code>>18)&0x3f));
234 buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
235 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
236 buffer[bytes++]=(byte)(0x80|(code&0x3f));
237
238 if (bytes+chars-i-1>buffer.length)
239 chars-=5;
240 }
241 else
242 {
243 buffer[bytes++]=(byte)('?');
244 }
245 }
246 out._bytes.setCount(bytes);
247 break;
248 }
249 default:
250 throw new IllegalStateException();
251 }
252
253 out._bytes.writeTo(out);
254 length-=chars;
255 offset+=chars;
256 }
257 }
258
259
260 private Writer getConverter() throws IOException
261 {
262 if (_out._converter == null)
263 _out._converter = new OutputStreamWriter(_out._bytes, _out._characterEncoding);
264 return _out._converter;
265 }
266 }