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