Source Code Cross Referenced for InternalOutputBuffer.java in  » Sevlet-Container » apache-tomcat-6.0.14 » org » apache » coyote » http11 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Sevlet Container » apache tomcat 6.0.14 » org.apache.coyote.http11 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
003:         *  contributor license agreements.  See the NOTICE file distributed with
004:         *  this work for additional information regarding copyright ownership.
005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
006:         *  (the "License"); you may not use this file except in compliance with
007:         *  the License.  You may obtain a copy of the License at
008:         *
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         *  Unless required by applicable law or agreed to in writing, software
012:         *  distributed under the License is distributed on an "AS IS" BASIS,
013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         *  See the License for the specific language governing permissions and
015:         *  limitations under the License.
016:         */
017:
018:        package org.apache.coyote.http11;
019:
020:        import java.io.IOException;
021:        import java.io.OutputStream;
022:        import java.security.AccessController;
023:        import java.security.PrivilegedAction;
024:
025:        import org.apache.tomcat.util.buf.ByteChunk;
026:        import org.apache.tomcat.util.buf.CharChunk;
027:        import org.apache.tomcat.util.buf.MessageBytes;
028:        import org.apache.tomcat.util.http.HttpMessages;
029:        import org.apache.tomcat.util.http.MimeHeaders;
030:        import org.apache.tomcat.util.res.StringManager;
031:
032:        import org.apache.coyote.ActionCode;
033:        import org.apache.coyote.OutputBuffer;
034:        import org.apache.coyote.Response;
035:
036:        /**
037:         * Output buffer.
038:         * 
039:         * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
040:         */
041:        public class InternalOutputBuffer implements  OutputBuffer,
042:                ByteChunk.ByteOutputChannel {
043:
044:            // -------------------------------------------------------------- Constants
045:
046:            // ----------------------------------------------------------- Constructors
047:
048:            /**
049:             * Default constructor.
050:             */
051:            public InternalOutputBuffer(Response response) {
052:                this (response, Constants.DEFAULT_HTTP_HEADER_BUFFER_SIZE);
053:            }
054:
055:            /**
056:             * Alternate constructor.
057:             */
058:            public InternalOutputBuffer(Response response, int headerBufferSize) {
059:
060:                this .response = response;
061:
062:                headers = response.getMimeHeaders();
063:
064:                buf = new byte[headerBufferSize];
065:
066:                outputStreamOutputBuffer = new OutputStreamOutputBuffer();
067:
068:                filterLibrary = new OutputFilter[0];
069:                activeFilters = new OutputFilter[0];
070:                lastActiveFilter = -1;
071:
072:                socketBuffer = new ByteChunk();
073:                socketBuffer.setByteOutputChannel(this );
074:
075:                committed = false;
076:                finished = false;
077:
078:            }
079:
080:            // -------------------------------------------------------------- Variables
081:
082:            /**
083:             * The string manager for this package.
084:             */
085:            protected static StringManager sm = StringManager
086:                    .getManager(Constants.Package);
087:
088:            // ----------------------------------------------------- Instance Variables
089:
090:            /**
091:             * Associated Coyote response.
092:             */
093:            protected Response response;
094:
095:            /**
096:             * Headers of the associated request.
097:             */
098:            protected MimeHeaders headers;
099:
100:            /**
101:             * Committed flag.
102:             */
103:            protected boolean committed;
104:
105:            /**
106:             * Finished flag.
107:             */
108:            protected boolean finished;
109:
110:            /**
111:             * The buffer used for header composition.
112:             */
113:            protected byte[] buf;
114:
115:            /**
116:             * Position in the buffer.
117:             */
118:            protected int pos;
119:
120:            /**
121:             * Underlying output stream.
122:             */
123:            protected OutputStream outputStream;
124:
125:            /**
126:             * Underlying output buffer.
127:             */
128:            protected OutputBuffer outputStreamOutputBuffer;
129:
130:            /**
131:             * Filter library.
132:             * Note: Filter[0] is always the "chunked" filter.
133:             */
134:            protected OutputFilter[] filterLibrary;
135:
136:            /**
137:             * Active filter (which is actually the top of the pipeline).
138:             */
139:            protected OutputFilter[] activeFilters;
140:
141:            /**
142:             * Index of the last active filter.
143:             */
144:            protected int lastActiveFilter;
145:
146:            /**
147:             * Socket buffer.
148:             */
149:            protected ByteChunk socketBuffer;
150:
151:            /**
152:             * Socket buffer (extra buffering to reduce number of packets sent).
153:             */
154:            protected boolean useSocketBuffer = false;
155:
156:            // ------------------------------------------------------------- Properties
157:
158:            /**
159:             * Set the underlying socket output stream.
160:             */
161:            public void setOutputStream(OutputStream outputStream) {
162:
163:                // FIXME: Check for null ?
164:
165:                this .outputStream = outputStream;
166:
167:            }
168:
169:            /**
170:             * Get the underlying socket output stream.
171:             */
172:            public OutputStream getOutputStream() {
173:
174:                return outputStream;
175:
176:            }
177:
178:            /**
179:             * Set the socket buffer size.
180:             */
181:            public void setSocketBuffer(int socketBufferSize) {
182:
183:                if (socketBufferSize > 500) {
184:                    useSocketBuffer = true;
185:                    socketBuffer.allocate(socketBufferSize, socketBufferSize);
186:                } else {
187:                    useSocketBuffer = false;
188:                }
189:
190:            }
191:
192:            /**
193:             * Add an output filter to the filter library.
194:             */
195:            public void addFilter(OutputFilter filter) {
196:
197:                OutputFilter[] newFilterLibrary = new OutputFilter[filterLibrary.length + 1];
198:                for (int i = 0; i < filterLibrary.length; i++) {
199:                    newFilterLibrary[i] = filterLibrary[i];
200:                }
201:                newFilterLibrary[filterLibrary.length] = filter;
202:                filterLibrary = newFilterLibrary;
203:
204:                activeFilters = new OutputFilter[filterLibrary.length];
205:
206:            }
207:
208:            /**
209:             * Get filters.
210:             */
211:            public OutputFilter[] getFilters() {
212:
213:                return filterLibrary;
214:
215:            }
216:
217:            /**
218:             * Clear filters.
219:             */
220:            public void clearFilters() {
221:
222:                filterLibrary = new OutputFilter[0];
223:                lastActiveFilter = -1;
224:
225:            }
226:
227:            /**
228:             * Add an output filter to the filter library.
229:             */
230:            public void addActiveFilter(OutputFilter filter) {
231:
232:                if (lastActiveFilter == -1) {
233:                    filter.setBuffer(outputStreamOutputBuffer);
234:                } else {
235:                    for (int i = 0; i <= lastActiveFilter; i++) {
236:                        if (activeFilters[i] == filter)
237:                            return;
238:                    }
239:                    filter.setBuffer(activeFilters[lastActiveFilter]);
240:                }
241:
242:                activeFilters[++lastActiveFilter] = filter;
243:
244:                filter.setResponse(response);
245:
246:            }
247:
248:            // --------------------------------------------------------- Public Methods
249:
250:            /**
251:             * Flush the response.
252:             * 
253:             * @throws IOException an undelying I/O error occured
254:             */
255:            public void flush() throws IOException {
256:
257:                if (!committed) {
258:
259:                    // Send the connector a request for commit. The connector should
260:                    // then validate the headers, send them (using sendHeader) and 
261:                    // set the filters accordingly.
262:                    response.action(ActionCode.ACTION_COMMIT, null);
263:
264:                }
265:
266:                // Flush the current buffer
267:                if (useSocketBuffer) {
268:                    socketBuffer.flushBuffer();
269:                }
270:
271:            }
272:
273:            /**
274:             * Reset current response.
275:             * 
276:             * @throws IllegalStateException if the response has already been committed
277:             */
278:            public void reset() {
279:
280:                if (committed)
281:                    throw new IllegalStateException(/*FIXME:Put an error message*/);
282:
283:                // Recycle Request object
284:                response.recycle();
285:
286:            }
287:
288:            /**
289:             * Recycle the output buffer. This should be called when closing the 
290:             * connection.
291:             */
292:            public void recycle() {
293:
294:                // Recycle Request object
295:                response.recycle();
296:                socketBuffer.recycle();
297:
298:                outputStream = null;
299:                pos = 0;
300:                lastActiveFilter = -1;
301:                committed = false;
302:                finished = false;
303:
304:            }
305:
306:            /**
307:             * End processing of current HTTP request.
308:             * Note: All bytes of the current request should have been already 
309:             * consumed. This method only resets all the pointers so that we are ready
310:             * to parse the next HTTP request.
311:             */
312:            public void nextRequest() {
313:
314:                // Recycle Request object
315:                response.recycle();
316:                socketBuffer.recycle();
317:
318:                // Recycle filters
319:                for (int i = 0; i <= lastActiveFilter; i++) {
320:                    activeFilters[i].recycle();
321:                }
322:
323:                // Reset pointers
324:                pos = 0;
325:                lastActiveFilter = -1;
326:                committed = false;
327:                finished = false;
328:
329:            }
330:
331:            /**
332:             * End request.
333:             * 
334:             * @throws IOException an undelying I/O error occured
335:             */
336:            public void endRequest() throws IOException {
337:
338:                if (!committed) {
339:
340:                    // Send the connector a request for commit. The connector should
341:                    // then validate the headers, send them (using sendHeader) and 
342:                    // set the filters accordingly.
343:                    response.action(ActionCode.ACTION_COMMIT, null);
344:
345:                }
346:
347:                if (finished)
348:                    return;
349:
350:                if (lastActiveFilter != -1)
351:                    activeFilters[lastActiveFilter].end();
352:
353:                if (useSocketBuffer) {
354:                    socketBuffer.flushBuffer();
355:                }
356:
357:                finished = true;
358:
359:            }
360:
361:            // ------------------------------------------------ HTTP/1.1 Output Methods
362:
363:            /**
364:             * Send an acknoledgement.
365:             */
366:            public void sendAck() throws IOException {
367:
368:                if (!committed)
369:                    outputStream.write(Constants.ACK_BYTES);
370:
371:            }
372:
373:            /**
374:             * Send the response status line.
375:             */
376:            public void sendStatus() {
377:
378:                // Write protocol name
379:                write(Constants.HTTP_11_BYTES);
380:                buf[pos++] = Constants.SP;
381:
382:                // Write status code
383:                int status = response.getStatus();
384:                switch (status) {
385:                case 200:
386:                    write(Constants._200_BYTES);
387:                    break;
388:                case 400:
389:                    write(Constants._400_BYTES);
390:                    break;
391:                case 404:
392:                    write(Constants._404_BYTES);
393:                    break;
394:                default:
395:                    write(status);
396:                }
397:
398:                buf[pos++] = Constants.SP;
399:
400:                // Write message
401:                String message = response.getMessage();
402:                if (message == null) {
403:                    write(getMessage(status));
404:                } else {
405:                    write(message);
406:                }
407:
408:                // End the response status line
409:                if (org.apache.coyote.Constants.IS_SECURITY_ENABLED) {
410:                    AccessController.doPrivileged(new PrivilegedAction() {
411:                        public Object run() {
412:                            buf[pos++] = Constants.CR;
413:                            buf[pos++] = Constants.LF;
414:                            return null;
415:                        }
416:                    });
417:                } else {
418:                    buf[pos++] = Constants.CR;
419:                    buf[pos++] = Constants.LF;
420:                }
421:
422:            }
423:
424:            private String getMessage(final int message) {
425:                if (org.apache.coyote.Constants.IS_SECURITY_ENABLED) {
426:                    return (String) AccessController
427:                            .doPrivileged(new PrivilegedAction() {
428:                                public Object run() {
429:                                    return HttpMessages.getMessage(message);
430:                                }
431:                            });
432:                } else {
433:                    return HttpMessages.getMessage(message);
434:                }
435:            }
436:
437:            /**
438:             * Send a header.
439:             * 
440:             * @param name Header name
441:             * @param value Header value
442:             */
443:            public void sendHeader(MessageBytes name, MessageBytes value) {
444:
445:                write(name);
446:                buf[pos++] = Constants.COLON;
447:                buf[pos++] = Constants.SP;
448:                write(value);
449:                buf[pos++] = Constants.CR;
450:                buf[pos++] = Constants.LF;
451:
452:            }
453:
454:            /**
455:             * Send a header.
456:             * 
457:             * @param name Header name
458:             * @param value Header value
459:             */
460:            public void sendHeader(ByteChunk name, ByteChunk value) {
461:
462:                write(name);
463:                buf[pos++] = Constants.COLON;
464:                buf[pos++] = Constants.SP;
465:                write(value);
466:                buf[pos++] = Constants.CR;
467:                buf[pos++] = Constants.LF;
468:
469:            }
470:
471:            /**
472:             * Send a header.
473:             * 
474:             * @param name Header name
475:             * @param value Header value
476:             */
477:            public void sendHeader(String name, String value) {
478:
479:                write(name);
480:                buf[pos++] = Constants.COLON;
481:                buf[pos++] = Constants.SP;
482:                write(value);
483:                buf[pos++] = Constants.CR;
484:                buf[pos++] = Constants.LF;
485:
486:            }
487:
488:            /**
489:             * End the header block.
490:             */
491:            public void endHeaders() {
492:
493:                buf[pos++] = Constants.CR;
494:                buf[pos++] = Constants.LF;
495:
496:            }
497:
498:            // --------------------------------------------------- OutputBuffer Methods
499:
500:            /**
501:             * Write the contents of a byte chunk.
502:             * 
503:             * @param chunk byte chunk
504:             * @return number of bytes written
505:             * @throws IOException an undelying I/O error occured
506:             */
507:            public int doWrite(ByteChunk chunk, Response res)
508:                    throws IOException {
509:
510:                if (!committed) {
511:
512:                    // Send the connector a request for commit. The connector should
513:                    // then validate the headers, send them (using sendHeaders) and 
514:                    // set the filters accordingly.
515:                    response.action(ActionCode.ACTION_COMMIT, null);
516:
517:                }
518:
519:                if (lastActiveFilter == -1)
520:                    return outputStreamOutputBuffer.doWrite(chunk, res);
521:                else
522:                    return activeFilters[lastActiveFilter].doWrite(chunk, res);
523:
524:            }
525:
526:            // ------------------------------------------------------ Protected Methods
527:
528:            /**
529:             * Commit the response.
530:             * 
531:             * @throws IOException an undelying I/O error occured
532:             */
533:            protected void commit() throws IOException {
534:
535:                // The response is now committed
536:                committed = true;
537:                response.setCommitted(true);
538:
539:                if (pos > 0) {
540:                    // Sending the response header buffer
541:                    if (useSocketBuffer) {
542:                        socketBuffer.append(buf, 0, pos);
543:                    } else {
544:                        outputStream.write(buf, 0, pos);
545:                    }
546:                }
547:
548:            }
549:
550:            /**
551:             * This method will write the contents of the specyfied message bytes 
552:             * buffer to the output stream, without filtering. This method is meant to
553:             * be used to write the response header.
554:             * 
555:             * @param mb data to be written
556:             */
557:            protected void write(MessageBytes mb) {
558:
559:                if (mb.getType() == MessageBytes.T_BYTES) {
560:                    ByteChunk bc = mb.getByteChunk();
561:                    write(bc);
562:                } else if (mb.getType() == MessageBytes.T_CHARS) {
563:                    CharChunk cc = mb.getCharChunk();
564:                    write(cc);
565:                } else {
566:                    write(mb.toString());
567:                }
568:
569:            }
570:
571:            /**
572:             * This method will write the contents of the specyfied message bytes 
573:             * buffer to the output stream, without filtering. This method is meant to
574:             * be used to write the response header.
575:             * 
576:             * @param bc data to be written
577:             */
578:            protected void write(ByteChunk bc) {
579:
580:                // Writing the byte chunk to the output buffer
581:                int length = bc.getLength();
582:                System
583:                        .arraycopy(bc.getBytes(), bc.getStart(), buf, pos,
584:                                length);
585:                pos = pos + length;
586:
587:            }
588:
589:            /**
590:             * This method will write the contents of the specyfied char 
591:             * buffer to the output stream, without filtering. This method is meant to
592:             * be used to write the response header.
593:             * 
594:             * @param cc data to be written
595:             */
596:            protected void write(CharChunk cc) {
597:
598:                int start = cc.getStart();
599:                int end = cc.getEnd();
600:                char[] cbuf = cc.getBuffer();
601:                for (int i = start; i < end; i++) {
602:                    char c = cbuf[i];
603:                    // Note:  This is clearly incorrect for many strings,
604:                    // but is the only consistent approach within the current
605:                    // servlet framework.  It must suffice until servlet output
606:                    // streams properly encode their output.
607:                    if ((c <= 31) && (c != 9)) {
608:                        c = ' ';
609:                    } else if (c == 127) {
610:                        c = ' ';
611:                    }
612:                    buf[pos++] = (byte) c;
613:                }
614:
615:            }
616:
617:            /**
618:             * This method will write the contents of the specyfied byte 
619:             * buffer to the output stream, without filtering. This method is meant to
620:             * be used to write the response header.
621:             * 
622:             * @param b data to be written
623:             */
624:            public void write(byte[] b) {
625:
626:                // Writing the byte chunk to the output buffer
627:                System.arraycopy(b, 0, buf, pos, b.length);
628:                pos = pos + b.length;
629:
630:            }
631:
632:            /**
633:             * This method will write the contents of the specyfied String to the 
634:             * output stream, without filtering. This method is meant to be used to 
635:             * write the response header.
636:             * 
637:             * @param s data to be written
638:             */
639:            protected void write(String s) {
640:
641:                if (s == null)
642:                    return;
643:
644:                // From the Tomcat 3.3 HTTP/1.0 connector
645:                int len = s.length();
646:                for (int i = 0; i < len; i++) {
647:                    char c = s.charAt(i);
648:                    // Note:  This is clearly incorrect for many strings,
649:                    // but is the only consistent approach within the current
650:                    // servlet framework.  It must suffice until servlet output
651:                    // streams properly encode their output.
652:                    if ((c <= 31) && (c != 9)) {
653:                        c = ' ';
654:                    } else if (c == 127) {
655:                        c = ' ';
656:                    }
657:                    buf[pos++] = (byte) c;
658:                }
659:
660:            }
661:
662:            /**
663:             * This method will print the specified integer to the output stream, 
664:             * without filtering. This method is meant to be used to write the 
665:             * response header.
666:             * 
667:             * @param i data to be written
668:             */
669:            protected void write(int i) {
670:
671:                write(String.valueOf(i));
672:
673:            }
674:
675:            /**
676:             * Callback to write data from the buffer.
677:             */
678:            public void realWriteBytes(byte cbuf[], int off, int len)
679:                    throws IOException {
680:                if (len > 0) {
681:                    outputStream.write(cbuf, off, len);
682:                }
683:            }
684:
685:            // ----------------------------------- OutputStreamOutputBuffer Inner Class
686:
687:            /**
688:             * This class is an output buffer which will write data to an output
689:             * stream.
690:             */
691:            protected class OutputStreamOutputBuffer implements  OutputBuffer {
692:
693:                /**
694:                 * Write chunk.
695:                 */
696:                public int doWrite(ByteChunk chunk, Response res)
697:                        throws IOException {
698:
699:                    int length = chunk.getLength();
700:                    if (useSocketBuffer) {
701:                        socketBuffer.append(chunk.getBuffer(),
702:                                chunk.getStart(), length);
703:                    } else {
704:                        outputStream.write(chunk.getBuffer(), chunk.getStart(),
705:                                length);
706:                    }
707:                    return length;
708:
709:                }
710:
711:            }
712:
713:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.