Source Code Cross Referenced for InternalOutputBuffer.java in  » Sevlet-Container » tomcat-connectors » 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 » tomcat connectors » org.apache.coyote.http11 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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