Source Code Cross Referenced for HttpGenerator.java in  » Sevlet-Container » jetty-modules » org » mortbay » jetty » 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 » jetty modules » org.mortbay.jetty 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        //========================================================================
002:        //$Id: HttpGenerator.java,v 1.7 2005/11/25 21:17:12 gregwilkins Exp $
003:        //Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
004:        //------------------------------------------------------------------------
005:        //Licensed under the Apache License, Version 2.0 (the "License");
006:        //you may not use this file except in compliance with the License.
007:        //You may obtain a copy of the License at 
008:        //http://www.apache.org/licenses/LICENSE-2.0
009:        //Unless required by applicable law or agreed to in writing, software
010:        //distributed under the License is distributed on an "AS IS" BASIS,
011:        //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012:        //See the License for the specific language governing permissions and
013:        //limitations under the License.
014:        //========================================================================
015:
016:        package org.mortbay.jetty;
017:
018:        import java.io.IOException;
019:        import java.util.Iterator;
020:
021:        import org.mortbay.io.Buffer;
022:        import org.mortbay.io.BufferUtil;
023:        import org.mortbay.io.Buffers;
024:        import org.mortbay.io.EndPoint;
025:        import org.mortbay.io.Portable;
026:        import org.mortbay.log.Log;
027:
028:        /* ------------------------------------------------------------ */
029:        /**
030:         * HttpGenerator. Builds HTTP Messages.
031:         * 
032:         * @author gregw
033:         * 
034:         */
035:        public class HttpGenerator extends AbstractGenerator {
036:            // common _content
037:            private static byte[] LAST_CHUNK = { (byte) '0', (byte) '\015',
038:                    (byte) '\012', (byte) '\015', (byte) '\012' };
039:            private static byte[] CONTENT_LENGTH_0 = Portable
040:                    .getBytes("Content-Length: 0\015\012");
041:            private static byte[] CONNECTION_KEEP_ALIVE = Portable
042:                    .getBytes("Connection: keep-alive\015\012");
043:            private static byte[] CONNECTION_CLOSE = Portable
044:                    .getBytes("Connection: close\015\012");
045:            private static byte[] TRANSFER_ENCODING_CHUNKED = Portable
046:                    .getBytes("Transfer-Encoding: chunked\015\012");
047:            private static byte[] SERVER = Portable
048:                    .getBytes("Server: Jetty(6.0.x)\015\012");
049:
050:            // other statics
051:            private static int CHUNK_SPACE = 12;
052:
053:            public static void setServerVersion(String version) {
054:                SERVER = Portable.getBytes("Server: Jetty(" + version
055:                        + ")\015\012");
056:            }
057:
058:            // data
059:            private boolean _bypass = false; // True if _content buffer can be written directly to endp and bypass the content buffer
060:            private boolean _needCRLF = false;
061:            private boolean _needEOC = false;
062:            private boolean _bufferChunked = false;
063:
064:            /* ------------------------------------------------------------------------------- */
065:            /**
066:             * Constructor.
067:             * 
068:             * @param buffers buffer pool
069:             * @param headerBufferSize Size of the buffer to allocate for HTTP header
070:             * @param contentBufferSize Size of the buffer to allocate for HTTP content
071:             */
072:            public HttpGenerator(Buffers buffers, EndPoint io,
073:                    int headerBufferSize, int contentBufferSize) {
074:                super (buffers, io, headerBufferSize, contentBufferSize);
075:            }
076:
077:            /* ------------------------------------------------------------------------------- */
078:            public void reset(boolean returnBuffers) {
079:                super .reset(returnBuffers);
080:                _bypass = false;
081:                _needCRLF = false;
082:                _needEOC = false;
083:                _bufferChunked = false;
084:                _method = null;
085:                _uri = null;
086:                _noContent = false;
087:            }
088:
089:            /* ------------------------------------------------------------ */
090:            /**
091:             * Add content.
092:             * 
093:             * @param content
094:             * @param last
095:             * @throws IllegalArgumentException if <code>content</code> is {@link Buffer#isImmutable immutable}.
096:             * @throws IllegalStateException If the request is not expecting any more content,
097:             *   or if the buffers are full and cannot be flushed.
098:             * @throws IOException if there is a problem flushing the buffers.
099:             */
100:            public void addContent(Buffer content, boolean last)
101:                    throws IOException {
102:                if (_noContent) {
103:                    content.clear();
104:                    return;
105:                }
106:
107:                if (_last || _state == STATE_END) {
108:                    Log.debug("Ignoring extra content {}", content);
109:                    content.clear();
110:                    return;
111:                }
112:                _last = last;
113:
114:                // Handle any unfinished business?
115:                if (_content != null && _content.length() > 0 || _bufferChunked) {
116:                    flush();
117:                    if (_content != null && _content.length() > 0
118:                            || _bufferChunked)
119:                        throw new IllegalStateException("FULL");
120:                }
121:
122:                _content = content;
123:                _contentWritten += content.length();
124:
125:                // Handle the _content
126:                if (_head) {
127:                    content.clear();
128:                    _content = null;
129:                } else if (_endp != null && _buffer == null
130:                        && content.length() > 0 && _last) {
131:                    // TODO - use bypass in more cases.
132:                    // Make _content a direct buffer
133:                    _bypass = true;
134:                } else {
135:                    // Yes - so we better check we have a buffer
136:                    if (_buffer == null)
137:                        _buffer = _buffers.getBuffer(_contentBufferSize);
138:
139:                    // Copy _content to buffer;
140:                    int len = _buffer.put(_content);
141:                    _content.skip(len);
142:                    if (_content.length() == 0)
143:                        _content = null;
144:                }
145:            }
146:
147:            /* ------------------------------------------------------------ */
148:            /**
149:             * Add content.
150:             * 
151:             * @param b byte
152:             * @return true if the buffers are full
153:             * @throws IOException
154:             */
155:            public boolean addContent(byte b) throws IOException {
156:                if (_noContent)
157:                    return false;
158:
159:                if (_last || _state == STATE_END) {
160:                    Log.debug("Ignoring extra content {}", new Byte(b));
161:                    return false;
162:                }
163:
164:                // Handle any unfinished business?
165:                if (_content != null && _content.length() > 0 || _bufferChunked) {
166:                    flush();
167:                    if (_content != null && _content.length() > 0
168:                            || _bufferChunked)
169:                        throw new IllegalStateException("FULL");
170:                }
171:
172:                _contentWritten++;
173:
174:                // Handle the _content
175:                if (_head)
176:                    return false;
177:
178:                // we better check we have a buffer
179:                if (_buffer == null)
180:                    _buffer = _buffers.getBuffer(_contentBufferSize);
181:
182:                // Copy _content to buffer;
183:                _buffer.put(b);
184:
185:                return _buffer.space() <= (_contentLength == HttpTokens.CHUNKED_CONTENT ? CHUNK_SPACE
186:                        : 0);
187:            }
188:
189:            /* ------------------------------------------------------------ */
190:            /** Prepare buffer for unchecked writes.
191:             * Prepare the generator buffer to receive unchecked writes
192:             * @return the available space in the buffer.
193:             * @throws IOException
194:             */
195:            protected int prepareUncheckedAddContent() throws IOException {
196:                if (_noContent)
197:                    return -1;
198:
199:                if (_last || _state == STATE_END) {
200:                    Log.debug("Ignoring extra content {}");
201:                    return -1;
202:                }
203:
204:                // Handle any unfinished business?
205:                Buffer content = _content;
206:                if (content != null && content.length() > 0 || _bufferChunked) {
207:                    flush();
208:                    if (content != null && content.length() > 0
209:                            || _bufferChunked)
210:                        throw new IllegalStateException("FULL");
211:                }
212:
213:                // we better check we have a buffer
214:                if (_buffer == null)
215:                    _buffer = _buffers.getBuffer(_contentBufferSize);
216:
217:                _contentWritten -= _buffer.length();
218:
219:                // Handle the _content
220:                if (_head)
221:                    return Integer.MAX_VALUE;
222:
223:                return _buffer.space()
224:                        - (_contentLength == HttpTokens.CHUNKED_CONTENT ? CHUNK_SPACE
225:                                : 0);
226:            }
227:
228:            /* ------------------------------------------------------------ */
229:            public boolean isBufferFull() {
230:                // Should we flush the buffers?
231:                boolean full = super .isBufferFull()
232:                        || _bypass
233:                        || (_contentLength == HttpTokens.CHUNKED_CONTENT
234:                                && _buffer != null && _buffer.space() < CHUNK_SPACE);
235:                return full;
236:            }
237:
238:            /* ------------------------------------------------------------ */
239:            public void completeHeader(HttpFields fields,
240:                    boolean allContentAdded) throws IOException {
241:                if (_state != STATE_HEADER)
242:                    return;
243:
244:                if (_last && !allContentAdded)
245:                    throw new IllegalStateException("last?");
246:                _last = _last | allContentAdded;
247:
248:                // get a header buffer
249:                if (_header == null)
250:                    _header = _buffers.getBuffer(_headerBufferSize);
251:
252:                boolean has_server = false;
253:
254:                if (_method != null) {
255:                    _close = false;
256:                    // Request
257:                    if (_version == HttpVersions.HTTP_0_9_ORDINAL) {
258:                        _contentLength = HttpTokens.NO_CONTENT;
259:                        _header.put(_method);
260:                        _header.put((byte) ' ');
261:                        _header.put(_uri.getBytes("utf-8")); // TODO WRONG!
262:                        _header.put(HttpTokens.CRLF);
263:                        _state = STATE_FLUSHING;
264:                        _noContent = true;
265:                        return;
266:                    } else {
267:                        _header.put(_method);
268:                        _header.put((byte) ' ');
269:                        _header.put(_uri.getBytes("utf-8")); // TODO WRONG!
270:                        _header.put((byte) ' ');
271:                        _header
272:                                .put(_version == HttpVersions.HTTP_1_0_ORDINAL ? HttpVersions.HTTP_1_0_BUFFER
273:                                        : HttpVersions.HTTP_1_1_BUFFER);
274:                        _header.put(HttpTokens.CRLF);
275:                    }
276:                } else {
277:                    // Response
278:                    if (_version == HttpVersions.HTTP_0_9_ORDINAL) {
279:                        _close = true;
280:                        _contentLength = HttpTokens.EOF_CONTENT;
281:                        _state = STATE_CONTENT;
282:                        return;
283:                    } else {
284:                        if (_version == HttpVersions.HTTP_1_0_ORDINAL)
285:                            _close = true;
286:
287:                        // add response line
288:                        Buffer line = HttpStatus.getResponseLine(_status);
289:
290:                        if (line == null) {
291:                            if (_reason == null)
292:                                _reason = getReasonBuffer(_status);
293:
294:                            _header.put(HttpVersions.HTTP_1_1_BUFFER);
295:                            _header.put((byte) ' ');
296:                            _header.put((byte) ('0' + _status / 100));
297:                            _header.put((byte) ('0' + (_status % 100) / 10));
298:                            _header.put((byte) ('0' + (_status % 10)));
299:                            _header.put((byte) ' ');
300:                            if (_reason == null) {
301:                                _header.put((byte) ('0' + _status / 100));
302:                                _header
303:                                        .put((byte) ('0' + (_status % 100) / 10));
304:                                _header.put((byte) ('0' + (_status % 10)));
305:                            } else
306:                                _header.put(_reason);
307:                            _header.put(HttpTokens.CRLF);
308:                        } else {
309:                            if (_reason == null)
310:                                _header.put(line);
311:                            else {
312:                                _header
313:                                        .put(line.array(), 0,
314:                                                HttpVersions.HTTP_1_1_BUFFER
315:                                                        .length() + 5);
316:                                _header.put(_reason);
317:                                _header.put(HttpTokens.CRLF);
318:                            }
319:                        }
320:
321:                        if (_status < 200 && _status >= 100) {
322:                            _noContent = true;
323:                            _content = null;
324:                            if (_buffer != null)
325:                                _buffer.clear();
326:                            // end the header.
327:                            _header.put(HttpTokens.CRLF);
328:                            _state = STATE_CONTENT;
329:                            return;
330:                        }
331:
332:                        if (_status == 204 || _status == 304) {
333:                            _noContent = true;
334:                            _content = null;
335:                            if (_buffer != null)
336:                                _buffer.clear();
337:                        }
338:                    }
339:                }
340:
341:                // Add headers
342:
343:                // key field values
344:                HttpFields.Field content_length = null;
345:                HttpFields.Field transfer_encoding = null;
346:                HttpFields.Field connection = null;
347:                boolean keep_alive = false;
348:
349:                if (fields != null) {
350:                    Iterator iter = fields.getFields();
351:
352:                    while (iter.hasNext()) {
353:                        HttpFields.Field field = (HttpFields.Field) iter.next();
354:
355:                        switch (field.getNameOrdinal()) {
356:                        case HttpHeaders.CONTENT_LENGTH_ORDINAL:
357:                            content_length = field;
358:                            _contentLength = field.getLongValue();
359:
360:                            if (_contentLength < _contentWritten || _last
361:                                    && _contentLength != _contentWritten)
362:                                content_length = null;
363:
364:                            // write the field to the header buffer
365:                            field.put(_header);
366:                            break;
367:
368:                        case HttpHeaders.CONTENT_TYPE_ORDINAL:
369:                            if (BufferUtil.isPrefix(
370:                                    MimeTypes.MULTIPART_BYTERANGES_BUFFER,
371:                                    field.getValueBuffer()))
372:                                _contentLength = HttpTokens.SELF_DEFINING_CONTENT;
373:
374:                            // write the field to the header buffer
375:                            field.put(_header);
376:                            break;
377:
378:                        case HttpHeaders.TRANSFER_ENCODING_ORDINAL:
379:                            if (_version == HttpVersions.HTTP_1_1_ORDINAL)
380:                                transfer_encoding = field;
381:                            // Do NOT add yet!
382:                            break;
383:
384:                        case HttpHeaders.CONNECTION_ORDINAL:
385:                            connection = field;
386:
387:                            int connection_value = field.getValueOrdinal();
388:
389:                            // TODO handle multivalue HttpConnection
390:                            _close = _method == null
391:                                    && HttpHeaderValues.CLOSE_ORDINAL == connection_value;
392:                            keep_alive = HttpHeaderValues.KEEP_ALIVE_ORDINAL == connection_value;
393:                            if (keep_alive
394:                                    && _version == HttpVersions.HTTP_1_0_ORDINAL
395:                                    && _method == null)
396:                                _close = false;
397:
398:                            if (_close
399:                                    && _contentLength == HttpTokens.UNKNOWN_CONTENT)
400:                                _contentLength = HttpTokens.EOF_CONTENT;
401:
402:                            // Do NOT add yet!
403:                            break;
404:
405:                        case HttpHeaders.SERVER_ORDINAL:
406:                            if (getSendServerVersion()) {
407:                                has_server = true;
408:                                field.put(_header);
409:                            }
410:                            break;
411:
412:                        default:
413:                            // write the field to the header buffer
414:                            field.put(_header);
415:                        }
416:                    }
417:                }
418:
419:                // Calculate how to end _content and connection, _content length and transfer encoding
420:                // settings.
421:                // From RFC 2616 4.4:
422:                // 1. No body for 1xx, 204, 304 & HEAD response
423:                // 2. Force _content-length?
424:                // 3. If Transfer-Encoding!=identity && HTTP/1.1 && !HttpConnection==close then chunk
425:                // 4. Content-Length
426:                // 5. multipart/byteranges
427:                // 6. close
428:                switch ((int) _contentLength) {
429:                case HttpTokens.UNKNOWN_CONTENT:
430:                    // It may be that we have no _content, or perhaps _content just has not been
431:                    // written yet?
432:
433:                    // Response known not to have a body
434:                    if (_contentWritten == 0
435:                            && (_status < 200 || _status == 204 || _status == 304))
436:                        _contentLength = HttpTokens.NO_CONTENT;
437:                    else if (_last) {
438:                        // we have seen all the _content there is
439:                        _contentLength = _contentWritten;
440:                        if (content_length == null) {
441:                            // known length but not actually set.
442:                            _header.put(HttpHeaders.CONTENT_LENGTH_BUFFER);
443:                            _header.put(HttpTokens.COLON);
444:                            _header.put((byte) ' ');
445:                            BufferUtil.putDecLong(_header, _contentLength);
446:                            _header.put(HttpTokens.CRLF);
447:                        }
448:                    } else {
449:                        // No idea, so we must assume that a body is coming
450:                        _contentLength = (_close || _version < HttpVersions.HTTP_1_1_ORDINAL) ? HttpTokens.EOF_CONTENT
451:                                : HttpTokens.CHUNKED_CONTENT;
452:                        if (_method != null
453:                                && _contentLength == HttpTokens.EOF_CONTENT)
454:                            throw new IllegalStateException("No Content-Length");
455:                    }
456:                    break;
457:
458:                case HttpTokens.NO_CONTENT:
459:                    if (content_length == null && _status >= 200
460:                            && _status != 204 && _status != 304)
461:                        _header.put(CONTENT_LENGTH_0);
462:                    break;
463:
464:                case HttpTokens.EOF_CONTENT:
465:                    _close = _method == null;
466:                    break;
467:
468:                case HttpTokens.CHUNKED_CONTENT:
469:                    break;
470:
471:                default:
472:                    // TODO - maybe allow forced chunking by setting te ???
473:                    break;
474:                }
475:
476:                // Add transfer_encoding if needed
477:                if (_contentLength == HttpTokens.CHUNKED_CONTENT) {
478:                    // try to use user supplied encoding as it may have other values.
479:                    if (transfer_encoding != null
480:                            && HttpHeaderValues.CHUNKED_ORDINAL != transfer_encoding
481:                                    .getValueOrdinal()) {
482:                        String c = transfer_encoding.getValue();
483:                        if (c.endsWith(HttpHeaderValues.CHUNKED))
484:                            transfer_encoding.put(_header);
485:                        else
486:                            throw new IllegalArgumentException("BAD TE");
487:                    } else
488:                        _header.put(TRANSFER_ENCODING_CHUNKED);
489:                }
490:
491:                // Handle connection if need be
492:                if ((_close || _contentLength == HttpTokens.EOF_CONTENT)) {
493:                    if (_version > HttpVersions.HTTP_1_0_ORDINAL
494:                            || connection != null)
495:                        _header.put(CONNECTION_CLOSE);
496:                    _close = true;
497:                } else if (keep_alive
498:                        && _version == HttpVersions.HTTP_1_0_ORDINAL)
499:                    _header.put(CONNECTION_KEEP_ALIVE);
500:                else if (connection != null)
501:                    connection.put(_header);
502:
503:                if (!has_server && _status > 100 && getSendServerVersion())
504:                    _header.put(SERVER);
505:
506:                // end the header.
507:                _header.put(HttpTokens.CRLF);
508:
509:                _state = STATE_CONTENT;
510:
511:            }
512:
513:            /* ------------------------------------------------------------ */
514:            /**
515:             * Complete the message.
516:             * 
517:             * @throws IOException
518:             */
519:            public void complete() throws IOException {
520:                if (_state == STATE_END)
521:                    return;
522:
523:                super .complete();
524:
525:                if (_state < STATE_FLUSHING) {
526:                    _state = STATE_FLUSHING;
527:                    if (_contentLength == HttpTokens.CHUNKED_CONTENT)
528:                        _needEOC = true;
529:                }
530:
531:                flush();
532:            }
533:
534:            /* ------------------------------------------------------------ */
535:            public long flush() throws IOException {
536:                try {
537:                    if (_state == STATE_HEADER)
538:                        throw new IllegalStateException("State==HEADER");
539:
540:                    prepareBuffers();
541:
542:                    if (_endp == null) {
543:                        if (_needCRLF && _buffer != null)
544:                            _buffer.put(HttpTokens.CRLF);
545:                        if (_needEOC && _buffer != null)
546:                            _buffer.put(LAST_CHUNK);
547:                        return 0;
548:                    }
549:
550:                    // Keep flushing while there is something to flush (except break below)
551:                    int total = 0;
552:                    long last_len = -1;
553:                    Flushing: while (true) {
554:                        int len = -1;
555:                        int to_flush = ((_header != null && _header.length() > 0) ? 4
556:                                : 0)
557:                                | ((_buffer != null && _buffer.length() > 0) ? 2
558:                                        : 0)
559:                                | ((_bypass && _content != null && _content
560:                                        .length() > 0) ? 1 : 0);
561:                        switch (to_flush) {
562:                        case 7:
563:                            throw new IllegalStateException(); // should never happen!
564:                        case 6:
565:                            len = _endp.flush(_header, _buffer, null);
566:                            break;
567:                        case 5:
568:                            len = _endp.flush(_header, _content, null);
569:                            break;
570:                        case 4:
571:                            len = _endp.flush(_header);
572:                            break;
573:                        case 3:
574:                            throw new IllegalStateException(); // should never happen!
575:                        case 2:
576:                            len = _endp.flush(_buffer);
577:                            break;
578:                        case 1:
579:                            len = _endp.flush(_content);
580:                            break;
581:                        case 0: {
582:                            // Nothing more we can write now.
583:                            if (_header != null)
584:                                _header.clear();
585:
586:                            _bypass = false;
587:                            _bufferChunked = false;
588:
589:                            if (_buffer != null) {
590:                                _buffer.clear();
591:                                if (_contentLength == HttpTokens.CHUNKED_CONTENT) {
592:                                    // reserve some space for the chunk header
593:                                    _buffer.setPutIndex(CHUNK_SPACE);
594:                                    _buffer.setGetIndex(CHUNK_SPACE);
595:
596:                                    // Special case handling for small left over buffer from
597:                                    // an addContent that caused a buffer flush.
598:                                    if (_content != null
599:                                            && _content.length() < _buffer
600:                                                    .space()
601:                                            && _state != STATE_FLUSHING) {
602:                                        _buffer.put(_content);
603:                                        _content.clear();
604:                                        _content = null;
605:                                        break Flushing;
606:                                    }
607:                                }
608:                            }
609:
610:                            // Are we completely finished for now?
611:                            if (!_needCRLF
612:                                    && !_needEOC
613:                                    && (_content == null || _content.length() == 0)) {
614:                                if (_state == STATE_FLUSHING)
615:                                    _state = STATE_END;
616:                                if (_state == STATE_END && _close)
617:                                    _endp.close();
618:
619:                                break Flushing;
620:                            }
621:
622:                            // Try to prepare more to write.
623:                            prepareBuffers();
624:                        }
625:                        }
626:
627:                        // If we failed to flush anything twice in a row break
628:                        if (len <= 0) {
629:                            if (last_len <= 0)
630:                                break Flushing;
631:                            break;
632:                        }
633:                        last_len = len;
634:                        total += len;
635:                    }
636:
637:                    return total;
638:                } catch (IOException e) {
639:                    Log.ignore(e);
640:                    throw (e instanceof  EofException) ? e : new EofException(e);
641:                }
642:            }
643:
644:            /* ------------------------------------------------------------ */
645:            private void prepareBuffers() {
646:                // if we are not flushing an existing chunk
647:                if (!_bufferChunked) {
648:                    // Refill buffer if possible
649:                    if (_content != null && _content.length() > 0
650:                            && _buffer != null && _buffer.space() > 0) {
651:                        int len = _buffer.put(_content);
652:                        _content.skip(len);
653:                        if (_content.length() == 0)
654:                            _content = null;
655:                    }
656:
657:                    // Chunk buffer if need be
658:                    if (_contentLength == HttpTokens.CHUNKED_CONTENT) {
659:                        int size = _buffer == null ? 0 : _buffer.length();
660:                        if (size > 0) {
661:                            // Prepare a chunk!
662:                            _bufferChunked = true;
663:
664:                            // Did we leave space at the start of the buffer.
665:                            if (_buffer.getIndex() == CHUNK_SPACE) {
666:                                // Oh yes, goodie! let's use it then!
667:                                _buffer.poke(_buffer.getIndex() - 2,
668:                                        HttpTokens.CRLF, 0, 2);
669:                                _buffer.setGetIndex(_buffer.getIndex() - 2);
670:                                BufferUtil.prependHexInt(_buffer, size);
671:
672:                                if (_needCRLF) {
673:                                    _buffer.poke(_buffer.getIndex() - 2,
674:                                            HttpTokens.CRLF, 0, 2);
675:                                    _buffer.setGetIndex(_buffer.getIndex() - 2);
676:                                    _needCRLF = false;
677:                                }
678:                            } else {
679:                                // No space so lets use the header buffer.
680:                                if (_needCRLF) {
681:                                    if (_header.length() > 0)
682:                                        throw new IllegalStateException("EOC");
683:                                    _header.put(HttpTokens.CRLF);
684:                                    _needCRLF = false;
685:                                }
686:                                BufferUtil.putHexInt(_header, size);
687:                                _header.put(HttpTokens.CRLF);
688:                            }
689:
690:                            // Add end chunk trailer.
691:                            if (_buffer.space() >= 2)
692:                                _buffer.put(HttpTokens.CRLF);
693:                            else
694:                                _needCRLF = true;
695:                        }
696:
697:                        // If we need EOC and everything written
698:                        if (_needEOC
699:                                && (_content == null || _content.length() == 0)) {
700:                            if (_needCRLF) {
701:                                if (_buffer == null && _header.space() >= 2) {
702:                                    _header.put(HttpTokens.CRLF);
703:                                    _needCRLF = false;
704:                                } else if (_buffer != null
705:                                        && _buffer.space() >= 2) {
706:                                    _buffer.put(HttpTokens.CRLF);
707:                                    _needCRLF = false;
708:                                }
709:                            }
710:
711:                            if (!_needCRLF && _needEOC) {
712:                                if (_buffer == null
713:                                        && _header.space() >= LAST_CHUNK.length) {
714:                                    _header.put(LAST_CHUNK);
715:                                    _bufferChunked = true;
716:                                    _needEOC = false;
717:                                } else if (_buffer != null
718:                                        && _buffer.space() >= LAST_CHUNK.length) {
719:                                    _buffer.put(LAST_CHUNK);
720:                                    _bufferChunked = true;
721:                                    _needEOC = false;
722:                                }
723:                            }
724:                        }
725:                    }
726:                }
727:
728:                if (_content != null && _content.length() == 0)
729:                    _content = null;
730:
731:            }
732:
733:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.