KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > go > teaservlet > DetachedResponseImpl


1 /* ====================================================================
2  * TeaServlet - Copyright (c) 1999-2000 Walt Disney Internet Group
3  * ====================================================================
4  * The Tea Software License, Version 1.1
5  *
6  * Copyright (c) 2000 Walt Disney Internet Group. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Walt Disney Internet Group (http://opensource.go.com/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact opensource@dig.com.
31  *
32  * 5. Products derived from this software may not be called "Tea",
33  * "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet",
34  * "Kettle", "Trove" or "BeanDoc" appear in their name, without prior
35  * written permission of the Walt Disney Internet Group.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE WALT DISNEY INTERNET GROUP OR ITS
41  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * For more information about Tea, please see http://opensource.go.com/.
51  */

52
53 package com.go.teaservlet;
54
55 import java.io.IOException JavaDoc;
56 import java.io.OutputStream JavaDoc;
57 import java.io.Serializable JavaDoc;
58 import java.util.Locale JavaDoc;
59 import java.util.List JavaDoc;
60 import java.util.ArrayList JavaDoc;
61 import javax.servlet.http.HttpServletResponse JavaDoc;
62 import javax.servlet.http.Cookie JavaDoc;
63 import com.go.teaservlet.io.CharToByteBuffer;
64 import com.go.teaservlet.io.DefaultCharToByteBuffer;
65 import com.go.teaservlet.io.InternedCharToByteBuffer;
66 import com.go.trove.io.ByteData;
67 import com.go.trove.io.ByteBuffer;
68 import com.go.trove.io.DefaultByteBuffer;
69 import com.go.trove.io.ByteBufferOutputStream;
70 import com.go.trove.util.Deflater;
71 import com.go.trove.util.DeflaterPool;
72 import com.go.trove.util.DeflaterOutputStream;
73 import com.go.trove.log.Log;
74 import com.go.tea.runtime.Substitution;
75
76 /******************************************************************************
77  *
78  * @author Brian S O'Neill
79  * @version
80  * <!--$$Revision:--> 9 <!-- $-->, <!--$$JustDate:--> 01/07/11 <!-- $-->
81  */

82 class DetachedResponseImpl extends ApplicationResponseImpl {
83     // Minimum data size to compress.
84
private static final int MINIMUM_SIZE = 100;
85
86     static ByteData compressByteData(ByteData original, int level) {
87         ByteBuffer compressed = new DefaultByteBuffer();
88         OutputStream JavaDoc cout = new ByteBufferOutputStream(compressed);
89
90         try {
91             if (original.getByteCount() < MINIMUM_SIZE) {
92                 level = Deflater.NO_COMPRESSION;
93             }
94             
95             Deflater d = DeflaterPool.get(level, true);
96             
97             DeflaterOutputStream dout = new DeflaterOutputStream(cout, d, 512);
98             original.writeTo(dout);
99             dout.fullFlush();
100
101             DeflaterPool.put(d);
102         }
103         catch (IOException JavaDoc e) {
104             throw new InternalError JavaDoc(e.toString());
105         }
106
107         return compressed;
108     }
109
110     private final SwappableBuffer mSwappableBuffer;
111     private final Data mData;
112
113     DetachedResponseImpl(HttpServletResponse JavaDoc response, Log log)
114         throws IOException JavaDoc
115     {
116         this(response, log, new SwappableBuffer());
117     }
118
119     private DetachedResponseImpl(HttpServletResponse JavaDoc response,
120                                  Log log,
121                                  SwappableBuffer sb)
122         throws IOException JavaDoc
123     {
124         super(response, log, sb);
125         sb.setBuffer(new DefaultByteBuffer());
126         mSwappableBuffer = sb;
127         mData = new Data();
128         mData.addCommand(new AddByteData(sb.mBuffer));
129     }
130
131     DetachedData getData() throws IOException JavaDoc {
132         drain();
133         return mData;
134     }
135
136     public void setContentType(String JavaDoc type) {
137         try {
138             mBuffer.setEncoding(getCharacterEncoding());
139             mData.addCommand(new SetContentType(type));
140         }
141         catch (IOException JavaDoc e) {
142             Thread JavaDoc t = Thread.currentThread();
143             t.getThreadGroup().uncaughtException(t, e);
144         }
145     }
146
147     public void reset() {
148         // Ignore.
149
}
150
151     public void setLocale(Locale JavaDoc locale) {
152         getHttpContext().setLocale(locale);
153     }
154
155     public void addCookie(Cookie JavaDoc cookie) {
156         mData.addCommand(new AddCookie(cookie));
157     }
158
159     public void sendError(int statusCode, String JavaDoc msg) throws IOException JavaDoc {
160         mState |= 1;
161         mData.addCommand(new SendError(statusCode, msg));
162     }
163
164     public void sendError(int statusCode) throws IOException JavaDoc {
165         mState |= 1;
166         mData.addCommand(new SendError(statusCode, null));
167     }
168
169     public void sendRedirect(String JavaDoc location) throws IOException JavaDoc {
170         mState |= 1;
171         mData.addCommand(new SendRedirect(location));
172     }
173
174     public void setHeader(String JavaDoc name, String JavaDoc value) {
175         mData.addCommand(new SetHeader(name, value));
176     }
177
178     public void setDateHeader(String JavaDoc name, long date) {
179         mData.addCommand(new SetHeader(name, new Long JavaDoc(date)));
180     }
181
182     public void setIntHeader(String JavaDoc name, int value) {
183         mData.addCommand(new SetHeader(name, new Integer JavaDoc(value)));
184     }
185
186     public void addHeader(String JavaDoc name, String JavaDoc value) {
187         mData.addCommand(new AddHeader(name, value));
188     }
189
190     public void addDateHeader(String JavaDoc name, long date) {
191         mData.addCommand(new AddHeader(name, new Long JavaDoc(date)));
192     }
193
194     public void addIntHeader(String JavaDoc name, int value) {
195         mData.addCommand(new AddHeader(name, new Integer JavaDoc(value)));
196     }
197
198     public void setStatus(int sc) {
199         mData.addCommand(new SetStatus(sc, null));
200     }
201
202     /**
203      * @deprecated
204      */

205     public void setStatus(int sc, String JavaDoc msg) {
206         mData.addCommand(new SetStatus(sc, msg));
207     }
208
209     public boolean insertCommand(Command command) throws Exception JavaDoc {
210         mData.addCommand(command);
211         addByteDataCommand();
212         return true;
213     }
214
215     public void finish() {
216         // Detached - nothing to finish to.
217
}
218
219     private void addByteDataCommand() throws IOException JavaDoc {
220         drain();
221         ByteBuffer bb = new DefaultByteBuffer();
222         mSwappableBuffer.setBuffer(bb);
223         mData.addCommand(new AddByteData(bb));
224     }
225
226     private void drain() throws IOException JavaDoc {
227         if (mBuffer != null) {
228             mBuffer.drain();
229         }
230     }
231
232     // A wrapper that allows another buffer to be swapped in.
233
private static class SwappableBuffer implements ByteBuffer {
234         private ByteBuffer mBuffer;
235
236         SwappableBuffer() {
237         }
238
239         public void setBuffer(ByteBuffer bb) {
240             mBuffer = bb;
241         }
242
243         public long getByteCount() throws IOException JavaDoc {
244             return mBuffer.getByteCount();
245         }
246
247         public void writeTo(OutputStream JavaDoc out) throws IOException JavaDoc {
248             mBuffer.writeTo(out);
249         }
250
251         public void reset() throws IOException JavaDoc {
252             mBuffer.reset();
253         }
254
255         public long getBaseByteCount() throws IOException JavaDoc {
256             return mBuffer.getBaseByteCount();
257         }
258
259         public void append(byte b) throws IOException JavaDoc {
260             mBuffer.append(b);
261         }
262
263         public void append(byte[] bytes) throws IOException JavaDoc {
264             mBuffer.append(bytes);
265         }
266
267         public void append(byte[] bytes, int offset, int length)
268             throws IOException JavaDoc
269         {
270             mBuffer.append(bytes, offset, length);
271         }
272
273         public void appendSurrogate(com.go.trove.io.ByteData s)
274             throws IOException JavaDoc
275         {
276             mBuffer.appendSurrogate(s);
277         }
278
279         public void addCaptureBuffer(com.go.trove.io.ByteBuffer buffer)
280             throws IOException JavaDoc
281         {
282             mBuffer.addCaptureBuffer(buffer);
283         }
284
285         public void removeCaptureBuffer(com.go.trove.io.ByteBuffer buffer)
286             throws IOException JavaDoc
287         {
288             mBuffer.removeCaptureBuffer(buffer);
289         }
290     }
291
292     private static class Data implements DetachedData, Serializable JavaDoc {
293         private List JavaDoc mCommands;
294         private boolean mCompressed;
295
296         public void playback(ApplicationRequest request,
297                              ApplicationResponse response) throws Exception JavaDoc {
298             if (mCommands != null) {
299                 int size = mCommands.size();
300                 for (int i=0; i<size; i++) {
301                     ((Command)mCommands.get(i)).execute(request, response);
302                 }
303             }
304         }
305
306         public void compress() {
307             compress(Deflater.DEFAULT_COMPRESSION);
308         }
309
310         public synchronized void compress(int level) {
311             if (!mCompressed) {
312                 mCompressed = true;
313                 List JavaDoc commands = mCommands;
314                 int size = commands.size();
315
316                 // Check if enough to compress.
317
enough: {
318                     for (int i=0; i<size; i++) {
319                         Object JavaDoc command = commands.get(i);
320                         if (command instanceof AddByteData) {
321                             ByteData bytes = ((AddByteData)command).mBytes;
322                             try {
323                                 if (bytes.getByteCount() >= MINIMUM_SIZE) {
324                                     break enough;
325                                 }
326                             }
327                             catch (IOException JavaDoc e) {
328                                 throw new InternalError JavaDoc(e.toString());
329                             }
330                         }
331                     }
332                     
333                     // Not enough.
334
return;
335                 }
336
337                 for (int i=0; i<size; i++) {
338                     Object JavaDoc command = commands.get(i);
339                     if (command instanceof AddByteData) {
340                         ByteData original = ((AddByteData)command).mBytes;
341                         try {
342                             if (original.getByteCount() > 0) {
343                                 command = new CompressedByteData
344                                     (compressByteData(original, level),
345                                      original);
346                                 mCommands.set(i, command);
347                             }
348                         }
349                         catch (IOException JavaDoc e) {
350                             throw new InternalError JavaDoc(e.toString());
351                         }
352                     }
353                 }
354             }
355         }
356
357         void addCommand(Command c) {
358             if (mCommands == null) {
359                 mCommands = new ArrayList JavaDoc();
360             }
361             mCommands.add(c);
362         }
363     }
364
365     private static class SetContentType implements Command, Serializable JavaDoc {
366         private final String JavaDoc mContentType;
367
368         SetContentType(String JavaDoc type) {
369             mContentType = type;
370         }
371
372         public void execute(ApplicationRequest request,
373                             ApplicationResponse response) {
374             response.setContentType(mContentType);
375         }
376     }
377
378     private static class AddCookie implements Command, Serializable JavaDoc {
379         private transient Cookie JavaDoc mCookie;
380
381         AddCookie(Cookie JavaDoc cookie) {
382             mCookie = cookie;
383         }
384
385         public void execute(ApplicationRequest request,
386                             ApplicationResponse response) {
387             response.addCookie(mCookie);
388         }
389
390         private void writeObject(java.io.ObjectOutputStream JavaDoc out)
391             throws IOException JavaDoc
392         {
393             out.writeUTF(mCookie.getName());
394             out.writeUTF(mCookie.getValue());
395             out.writeUTF(mCookie.getComment());
396             out.writeUTF(mCookie.getDomain());
397             out.writeInt(mCookie.getMaxAge());
398             out.writeUTF(mCookie.getPath());
399             out.writeBoolean(mCookie.getSecure());
400             out.writeInt(mCookie.getVersion());
401         }
402
403         private void readObject(java.io.ObjectInputStream JavaDoc in)
404             throws IOException JavaDoc, ClassNotFoundException JavaDoc
405         {
406             mCookie = new Cookie JavaDoc(in.readUTF(), in.readUTF());
407             mCookie.setComment(in.readUTF());
408             mCookie.setDomain(in.readUTF());
409             mCookie.setMaxAge(in.readInt());
410             mCookie.setPath(in.readUTF());
411             mCookie.setSecure(in.readBoolean());
412             mCookie.setVersion(in.readInt());
413         }
414     }
415
416     private static class SetHeader implements Command, Serializable JavaDoc {
417         protected final String JavaDoc mName;
418         protected final Object JavaDoc mValue;
419
420         SetHeader(String JavaDoc name, Object JavaDoc value) {
421             mName = name;
422             mValue = value;
423         }
424
425         public void execute(ApplicationRequest request,
426                             ApplicationResponse response) {
427             if (mValue instanceof String JavaDoc) {
428                 response.setHeader(mName, (String JavaDoc)mValue);
429             }
430             else if (mValue instanceof Long JavaDoc) {
431                 response.setDateHeader(mName, ((Long JavaDoc)mValue).longValue());
432             }
433             else {
434                 response.setIntHeader(mName, ((Integer JavaDoc)mValue).intValue());
435             }
436         }
437     }
438
439     private static class AddHeader extends SetHeader
440         implements Command, Serializable JavaDoc
441     {
442         AddHeader(String JavaDoc name, Object JavaDoc value) {
443             super(name, value);
444         }
445
446         public void execute(ApplicationRequest request,
447                             ApplicationResponse response) {
448             if (mValue instanceof String JavaDoc) {
449                 response.addHeader(mName, (String JavaDoc)mValue);
450             }
451             else if (mValue instanceof Long JavaDoc) {
452                 response.addDateHeader(mName, ((Long JavaDoc)mValue).longValue());
453             }
454             else {
455                 response.addIntHeader(mName, ((Integer JavaDoc)mValue).intValue());
456             }
457         }
458     }
459
460     private static class SetStatus implements Command, Serializable JavaDoc {
461         protected final int mCode;
462         protected final String JavaDoc mMessage;
463
464         SetStatus(int code, String JavaDoc message) {
465             mCode = code;
466             mMessage = message;
467         }
468
469         public void execute(ApplicationRequest request,
470                             ApplicationResponse response) throws IOException JavaDoc {
471             if (mMessage == null) {
472                 response.setStatus(mCode);
473             }
474             else {
475                 response.setStatus(mCode, mMessage);
476             }
477         }
478     }
479
480     private static class SendError extends SetStatus
481         implements Command, Serializable JavaDoc
482     {
483         SendError(int code, String JavaDoc message) {
484             super(code, message);
485         }
486
487         public void execute(ApplicationRequest request,
488                             ApplicationResponse response) throws IOException JavaDoc {
489             if (mMessage == null) {
490                 response.sendError(mCode);
491             }
492             else {
493                 response.sendError(mCode, mMessage);
494             }
495         }
496     }
497
498     private static class SendRedirect implements Command, Serializable JavaDoc {
499         private final String JavaDoc mLocation;
500
501         SendRedirect(String JavaDoc location) {
502             mLocation = location;
503         }
504
505         public void execute(ApplicationRequest request,
506                             ApplicationResponse response) throws IOException JavaDoc {
507             response.sendRedirect(mLocation);
508         }
509     }
510
511     private static class AddByteData implements Command, Serializable JavaDoc {
512         final ByteData mBytes;
513
514         AddByteData(ByteData bytes) {
515             mBytes = bytes;
516         }
517
518         public void execute(ApplicationRequest request,
519                             ApplicationResponse response) throws IOException JavaDoc {
520             response.getResponseBuffer().appendSurrogate(mBytes);
521         }
522     }
523
524     private static class CompressedByteData implements Command, Serializable JavaDoc {
525         private final ByteData mCompressed;
526         private final ByteData mOriginal;
527
528         CompressedByteData(ByteData compressed, ByteData original) {
529             mCompressed = compressed;
530             mOriginal = original;
531         }
532
533         public void execute(ApplicationRequest request,
534                             ApplicationResponse response) throws IOException JavaDoc {
535
536             if (request.isCompressionAccepted()) {
537                 try {
538                     ApplicationResponseImpl impl =
539                         (ApplicationResponseImpl)response;
540                     impl.appendCompressed(mCompressed, mOriginal);
541                     return;
542                 }
543                 catch (ClassCastException JavaDoc e) {
544                 }
545             }
546
547             response.getResponseBuffer().appendSurrogate(mOriginal);
548         }
549     }
550 }
551
Popular Tags