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