Source Code Cross Referenced for AbstractGenerator.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.io.OutputStreamWriter;
020:        import java.io.Writer;
021:        import java.lang.reflect.Field;
022:        import java.lang.reflect.Modifier;
023:
024:        import javax.servlet.ServletOutputStream;
025:        import javax.servlet.http.HttpServletResponse;
026:
027:        import org.mortbay.io.Buffer;
028:        import org.mortbay.io.Buffers;
029:        import org.mortbay.io.ByteArrayBuffer;
030:        import org.mortbay.io.EndPoint;
031:        import org.mortbay.io.View;
032:        import org.mortbay.log.Log;
033:        import org.mortbay.util.ByteArrayOutputStream2;
034:        import org.mortbay.util.StringUtil;
035:        import org.mortbay.util.TypeUtil;
036:
037:        /* ------------------------------------------------------------ */
038:        /**
039:         * Abstract Generator. Builds HTTP Messages.
040:         * 
041:         * Currently this class uses a system parameter "jetty.direct.writers" to control
042:         * two optional writer to byte conversions. buffer.writers=true will probably be 
043:         * faster, but will consume more memory.   This option is just for testing and tuning.
044:         * 
045:         * @author gregw
046:         * 
047:         */
048:        public abstract class AbstractGenerator implements  Generator {
049:            // states
050:            public final static int STATE_HEADER = 0;
051:            public final static int STATE_CONTENT = 2;
052:            public final static int STATE_FLUSHING = 3;
053:            public final static int STATE_END = 4;
054:
055:            private static byte[] NO_BYTES = {};
056:            private static int MAX_OUTPUT_CHARS = 1024;
057:
058:            private static Buffer[] __reasons = new Buffer[505];
059:            static {
060:                Field[] fields = HttpServletResponse.class.getDeclaredFields();
061:                for (int i = 0; i < fields.length; i++) {
062:                    if ((fields[i].getModifiers() & Modifier.STATIC) != 0
063:                            && fields[i].getName().startsWith("SC_")) {
064:                        try {
065:                            int code = fields[i].getInt(null);
066:                            if (code < __reasons.length)
067:                                __reasons[code] = new ByteArrayBuffer(fields[i]
068:                                        .getName().substring(3));
069:                        } catch (IllegalAccessException e) {
070:                        }
071:                    }
072:                }
073:            }
074:
075:            protected static Buffer getReasonBuffer(int code) {
076:                Buffer reason = (code < __reasons.length) ? __reasons[code]
077:                        : null;
078:                return reason == null ? null : reason;
079:            }
080:
081:            public static String getReason(int code) {
082:                Buffer reason = (code < __reasons.length) ? __reasons[code]
083:                        : null;
084:                return reason == null ? TypeUtil.toString(code) : reason
085:                        .toString();
086:            }
087:
088:            // data
089:            protected int _state = STATE_HEADER;
090:
091:            protected int _status = 0;
092:            protected int _version = HttpVersions.HTTP_1_1_ORDINAL;
093:            protected Buffer _reason;
094:            protected Buffer _method;
095:            protected String _uri;
096:
097:            protected long _contentWritten = 0;
098:            protected long _contentLength = HttpTokens.UNKNOWN_CONTENT;
099:            protected boolean _last = false;
100:            protected boolean _head = false;
101:            protected boolean _noContent = false;
102:            protected boolean _close = false;
103:
104:            protected Buffers _buffers; // source of buffers
105:            protected EndPoint _endp;
106:
107:            protected int _headerBufferSize;
108:            protected int _contentBufferSize;
109:
110:            protected Buffer _header; // Buffer for HTTP header (and maybe small _content)
111:            protected Buffer _buffer; // Buffer for copy of passed _content
112:            protected Buffer _content; // Buffer passed to addContent
113:
114:            private boolean _sendServerVersion;
115:
116:            /* ------------------------------------------------------------------------------- */
117:            /**
118:             * Constructor.
119:             * 
120:             * @param buffers buffer pool
121:             * @param headerBufferSize Size of the buffer to allocate for HTTP header
122:             * @param contentBufferSize Size of the buffer to allocate for HTTP content
123:             */
124:            public AbstractGenerator(Buffers buffers, EndPoint io,
125:                    int headerBufferSize, int contentBufferSize) {
126:                this ._buffers = buffers;
127:                this ._endp = io;
128:                _headerBufferSize = headerBufferSize;
129:                _contentBufferSize = contentBufferSize;
130:            }
131:
132:            /* ------------------------------------------------------------------------------- */
133:            public void reset(boolean returnBuffers) {
134:                _state = STATE_HEADER;
135:                _status = 0;
136:                _version = HttpVersions.HTTP_1_1_ORDINAL;
137:                _last = false;
138:                _head = false;
139:                _noContent = false;
140:                _close = false;
141:                _contentWritten = 0;
142:                _contentLength = HttpTokens.UNKNOWN_CONTENT;
143:
144:                if (returnBuffers) {
145:                    if (_header != null)
146:                        _buffers.returnBuffer(_header);
147:                    _header = null;
148:                    if (_buffer != null)
149:                        _buffers.returnBuffer(_buffer);
150:                    _buffer = null;
151:                } else {
152:                    if (_header != null)
153:                        _header.clear();
154:
155:                    if (_buffer != null) {
156:                        _buffers.returnBuffer(_buffer);
157:                        _buffer = null;
158:                    }
159:                }
160:                _content = null;
161:                _method = null;
162:            }
163:
164:            /* ------------------------------------------------------------------------------- */
165:            public void resetBuffer() {
166:                if (_state >= STATE_FLUSHING)
167:                    throw new IllegalStateException("Flushed");
168:
169:                _last = false;
170:                _close = false;
171:                _contentWritten = 0;
172:                _contentLength = HttpTokens.UNKNOWN_CONTENT;
173:                _content = null;
174:                if (_buffer != null)
175:                    _buffer.clear();
176:            }
177:
178:            /* ------------------------------------------------------------ */
179:            /**
180:             * @return Returns the contentBufferSize.
181:             */
182:            public int getContentBufferSize() {
183:                return _contentBufferSize;
184:            }
185:
186:            /* ------------------------------------------------------------ */
187:            /**
188:             * @param contentBufferSize The contentBufferSize to set.
189:             */
190:            public void increaseContentBufferSize(int contentBufferSize) {
191:                if (contentBufferSize > _contentBufferSize) {
192:                    _contentBufferSize = contentBufferSize;
193:                    if (_buffer != null) {
194:                        Buffer nb = _buffers.getBuffer(_contentBufferSize);
195:                        nb.put(_buffer);
196:                        _buffers.returnBuffer(_buffer);
197:                        _buffer = nb;
198:                    }
199:                }
200:            }
201:
202:            /* ------------------------------------------------------------ */
203:            public Buffer getUncheckedBuffer() {
204:                return _buffer;
205:            }
206:
207:            /* ------------------------------------------------------------ */
208:            public boolean getSendServerVersion() {
209:                return _sendServerVersion;
210:            }
211:
212:            /* ------------------------------------------------------------ */
213:            public void setSendServerVersion(boolean sendServerVersion) {
214:                _sendServerVersion = sendServerVersion;
215:            }
216:
217:            /* ------------------------------------------------------------ */
218:            public int getState() {
219:                return _state;
220:            }
221:
222:            /* ------------------------------------------------------------ */
223:            public boolean isState(int state) {
224:                return _state == state;
225:            }
226:
227:            /* ------------------------------------------------------------ */
228:            public boolean isComplete() {
229:                return _state == STATE_END;
230:            }
231:
232:            /* ------------------------------------------------------------ */
233:            public boolean isIdle() {
234:                return _state == STATE_HEADER && _method == null
235:                        && _status == 0;
236:            }
237:
238:            /* ------------------------------------------------------------ */
239:            public boolean isCommitted() {
240:                return _state != STATE_HEADER;
241:            }
242:
243:            /* ------------------------------------------------------------ */
244:            /**
245:             * @return Returns the head.
246:             */
247:            public boolean isHead() {
248:                return _head;
249:            }
250:
251:            /* ------------------------------------------------------------ */
252:            public void setContentLength(long value) {
253:                _contentLength = value;
254:            }
255:
256:            /* ------------------------------------------------------------ */
257:            /**
258:             * @param head The head to set.
259:             */
260:            public void setHead(boolean head) {
261:                _head = head;
262:            }
263:
264:            /* ------------------------------------------------------------ */
265:            /**
266:             * @return <code>false</code> if the connection should be closed after a request has been read,
267:             * <code>true</code> if it should be used for additional requests.
268:             */
269:            public boolean isPersistent() {
270:                return !_close;
271:            }
272:
273:            /* ------------------------------------------------------------ */
274:            public void setPersistent(boolean persistent) {
275:                _close = !persistent;
276:            }
277:
278:            /* ------------------------------------------------------------ */
279:            /**
280:             * @param version The version of the client the response is being sent to (NB. Not the version
281:             *            in the response, which is the version of the server).
282:             */
283:            public void setVersion(int version) {
284:                if (_state != STATE_HEADER)
285:                    throw new IllegalStateException("STATE!=START");
286:                _version = version;
287:                if (_version == HttpVersions.HTTP_0_9_ORDINAL
288:                        && _method != null)
289:                    _noContent = true;
290:            }
291:
292:            /* ------------------------------------------------------------ */
293:            public int getVersion() {
294:                return _version;
295:            }
296:
297:            /* ------------------------------------------------------------ */
298:            /**
299:             */
300:            public void setRequest(String method, String uri) {
301:                if (method == null || HttpMethods.GET.equals(method))
302:                    _method = HttpMethods.GET_BUFFER;
303:                else
304:                    _method = HttpMethods.CACHE.lookup(method);
305:                _uri = uri;
306:                if (_version == HttpVersions.HTTP_0_9_ORDINAL)
307:                    _noContent = true;
308:            }
309:
310:            /* ------------------------------------------------------------ */
311:            /**
312:             * @param status The status code to send.
313:             * @param reason the status message to send.
314:             */
315:            public void setResponse(int status, String reason) {
316:                if (_state != STATE_HEADER)
317:                    throw new IllegalStateException("STATE!=START");
318:
319:                _status = status;
320:                if (reason != null) {
321:                    int len = reason.length();
322:                    if (len > _headerBufferSize / 2)
323:                        len = _headerBufferSize / 2;
324:                    _reason = new ByteArrayBuffer(len);
325:                    for (int i = 0; i < len; i++) {
326:                        char ch = reason.charAt(i);
327:                        if (Character.isWhitespace(ch))
328:                            _reason.put((byte) '_');
329:                        else if (Character.isJavaIdentifierPart(ch))
330:                            _reason.put((byte) ch);
331:                    }
332:                }
333:            }
334:
335:            /* ------------------------------------------------------------ */
336:            /** Prepare buffer for unchecked writes.
337:             * Prepare the generator buffer to receive unchecked writes
338:             * @return the available space in the buffer.
339:             * @throws IOException
340:             */
341:            protected abstract int prepareUncheckedAddContent()
342:                    throws IOException;
343:
344:            /* ------------------------------------------------------------ */
345:            void uncheckedAddContent(int b) {
346:                _buffer.put((byte) b);
347:            }
348:
349:            /* ------------------------------------------------------------ */
350:            void completeUncheckedAddContent() {
351:                if (_noContent) {
352:                    if (_buffer != null)
353:                        _buffer.clear();
354:                    return;
355:                } else {
356:                    _contentWritten += _buffer.length();
357:                    if (_head)
358:                        _buffer.clear();
359:                }
360:            }
361:
362:            /* ------------------------------------------------------------ */
363:            public boolean isBufferFull() {
364:                // Should we flush the buffers?
365:                boolean full = (_state == STATE_FLUSHING || (_buffer != null && _buffer
366:                        .space() == 0));
367:                return full;
368:            }
369:
370:            /* ------------------------------------------------------------ */
371:            public boolean isContentWritten() {
372:                return _contentLength >= 0 && _contentWritten >= _contentLength;
373:            }
374:
375:            /* ------------------------------------------------------------ */
376:            public abstract void completeHeader(HttpFields fields,
377:                    boolean allContentAdded) throws IOException;
378:
379:            /* ------------------------------------------------------------ */
380:            /**
381:             * Complete the message.
382:             * 
383:             * @throws IOException
384:             */
385:            public void complete() throws IOException {
386:                if (_state == STATE_HEADER) {
387:                    throw new IllegalStateException("State==HEADER");
388:                }
389:
390:                if (_contentLength >= 0 && _contentLength != _contentWritten
391:                        && !_head) {
392:                    if (Log.isDebugEnabled())
393:                        Log.debug("ContentLength written==" + _contentWritten
394:                                + " != contentLength==" + _contentLength);
395:                    _close = true;
396:                }
397:            }
398:
399:            /* ------------------------------------------------------------ */
400:            public abstract long flush() throws IOException;
401:
402:            /* ------------------------------------------------------------ */
403:            /**
404:             * Utility method to send an error response. If the builder is not committed, this call is
405:             * equivalent to a setResponse, addcontent and complete call.
406:             * 
407:             * @param code
408:             * @param reason
409:             * @param content
410:             * @param close
411:             * @throws IOException
412:             */
413:            public void sendError(int code, String reason, String content,
414:                    boolean close) throws IOException {
415:                if (!isCommitted()) {
416:                    setResponse(code, reason);
417:                    _close = close;
418:                    completeHeader(null, false);
419:                    if (content != null)
420:                        addContent(new View(new ByteArrayBuffer(content)),
421:                                Generator.LAST);
422:                    complete();
423:                }
424:            }
425:
426:            /* ------------------------------------------------------------ */
427:            /**
428:             * @return Returns the contentWritten.
429:             */
430:            public long getContentWritten() {
431:                return _contentWritten;
432:            }
433:
434:            /* ------------------------------------------------------------ */
435:            /* ------------------------------------------------------------ */
436:            /* ------------------------------------------------------------ */
437:            /* ------------------------------------------------------------ */
438:            /** Output.
439:             * 
440:             * <p>
441:             * Implements  {@link javax.servlet.ServletOutputStream} from the {@link javax.servlet} package.   
442:             * </p>
443:             * A {@link ServletOutputStream} implementation that writes content
444:             * to a {@link AbstractGenerator}.   The class is designed to be reused
445:             * and can be reopened after a close.
446:             */
447:            public static class Output extends ServletOutputStream {
448:                protected AbstractGenerator _generator;
449:                protected long _maxIdleTime;
450:                protected ByteArrayBuffer _buf = new ByteArrayBuffer(NO_BYTES);
451:                protected boolean _closed;
452:
453:                // These are held here for reuse by Writer
454:                String _characterEncoding;
455:                Writer _converter;
456:                char[] _chars;
457:                ByteArrayOutputStream2 _bytes;
458:
459:                /* ------------------------------------------------------------ */
460:                public Output(AbstractGenerator generator, long maxIdleTime) {
461:                    _generator = generator;
462:                    _maxIdleTime = maxIdleTime;
463:                }
464:
465:                /* ------------------------------------------------------------ */
466:                /*
467:                 * @see java.io.OutputStream#close()
468:                 */
469:                public void close() throws IOException {
470:                    _closed = true;
471:                }
472:
473:                /* ------------------------------------------------------------ */
474:                void blockForOutput() throws IOException {
475:                    if (_generator._endp.isBlocking()) {
476:                        try {
477:                            flush();
478:                        } catch (IOException e) {
479:                            _generator._endp.close();
480:                            throw e;
481:                        }
482:                    } else {
483:                        if (!_generator._endp.blockWritable(_maxIdleTime)) {
484:                            _generator._endp.close();
485:                            throw new EofException("timeout");
486:                        }
487:
488:                        _generator.flush();
489:                    }
490:                }
491:
492:                /* ------------------------------------------------------------ */
493:                void reopen() {
494:                    _closed = false;
495:                }
496:
497:                /* ------------------------------------------------------------ */
498:                public void flush() throws IOException {
499:                    // block until everything is flushed
500:                    Buffer content = _generator._content;
501:                    Buffer buffer = _generator._buffer;
502:                    if (content != null && content.length() > 0
503:                            || buffer != null && buffer.length() > 0) {
504:                        _generator.flush();
505:
506:                        while ((content != null && content.length() > 0 || buffer != null
507:                                && buffer.length() > 0)
508:                                && _generator._endp.isOpen())
509:                            blockForOutput();
510:                    }
511:                }
512:
513:                /* ------------------------------------------------------------ */
514:                public void write(byte[] b, int off, int len)
515:                        throws IOException {
516:                    _buf.wrap(b, off, len);
517:                    write(_buf);
518:                }
519:
520:                /* ------------------------------------------------------------ */
521:                /*
522:                 * @see java.io.OutputStream#write(byte[])
523:                 */
524:                public void write(byte[] b) throws IOException {
525:                    _buf.wrap(b);
526:                    write(_buf);
527:                }
528:
529:                /* ------------------------------------------------------------ */
530:                /*
531:                 * @see java.io.OutputStream#write(int)
532:                 */
533:                public void write(int b) throws IOException {
534:                    if (_closed)
535:                        throw new IOException("Closed");
536:
537:                    // Block until we can add _content.
538:                    while (_generator.isBufferFull()
539:                            && _generator._endp.isOpen())
540:                        blockForOutput();
541:
542:                    // Add the _content
543:                    if (_generator.addContent((byte) b)
544:                            || _generator.isContentWritten()) {
545:                        // Buffers are full so flush.
546:                        flush();
547:                    }
548:                }
549:
550:                /* ------------------------------------------------------------ */
551:                private void write(Buffer buffer) throws IOException {
552:                    if (_closed)
553:                        throw new IOException("Closed");
554:
555:                    // Block until we can add _content.
556:                    while (_generator.isBufferFull()
557:                            && _generator._endp.isOpen())
558:                        blockForOutput();
559:
560:                    // Add the _content
561:                    _generator.addContent(buffer, Generator.MORE);
562:
563:                    // Have to flush and complete headers?
564:                    if (_generator.isBufferFull()
565:                            || _generator.isContentWritten())
566:                        flush();
567:
568:                    // Block until our buffer is free
569:                    while (buffer.length() > 0 && _generator._endp.isOpen())
570:                        blockForOutput();
571:                }
572:
573:                /* ------------------------------------------------------------ */
574:                /* 
575:                 * @see javax.servlet.ServletOutputStream#print(java.lang.String)
576:                 */
577:                public void print(String s) throws IOException {
578:                    write(s.getBytes());
579:                }
580:            }
581:
582:            /* ------------------------------------------------------------ */
583:            /* ------------------------------------------------------------ */
584:            /* ------------------------------------------------------------ */
585:            /** OutputWriter.
586:             * A writer that can wrap a {@link Output} stream and provide
587:             * character encodings.
588:             *
589:             * The UTF-8 encoding is done by this class and no additional 
590:             * buffers or Writers are used.
591:             * The UTF-8 code was inspired by http://javolution.org
592:             */
593:            public static class OutputWriter extends Writer {
594:                private static final int WRITE_CONV = 0;
595:                private static final int WRITE_ISO1 = 1;
596:                private static final int WRITE_UTF8 = 2;
597:
598:                Output _out;
599:                AbstractGenerator _generator;
600:                int _writeMode;
601:                int _surrogate;
602:
603:                /* ------------------------------------------------------------ */
604:                public OutputWriter(Output out) {
605:                    _out = out;
606:                    _generator = _out._generator;
607:
608:                }
609:
610:                /* ------------------------------------------------------------ */
611:                public void setCharacterEncoding(String encoding) {
612:                    if (encoding == null
613:                            || StringUtil.__ISO_8859_1
614:                                    .equalsIgnoreCase(encoding)) {
615:                        _writeMode = WRITE_ISO1;
616:                    } else if (StringUtil.__UTF8.equalsIgnoreCase(encoding)) {
617:                        _writeMode = WRITE_UTF8;
618:                    } else {
619:                        _writeMode = WRITE_CONV;
620:                        if (_out._characterEncoding == null
621:                                || !_out._characterEncoding
622:                                        .equalsIgnoreCase(encoding))
623:                            _out._converter = null; // Set lazily in getConverter()
624:                    }
625:
626:                    _out._characterEncoding = encoding;
627:                    if (_out._bytes == null)
628:                        _out._bytes = new ByteArrayOutputStream2(
629:                                MAX_OUTPUT_CHARS * 6);
630:                }
631:
632:                /* ------------------------------------------------------------ */
633:                public void close() throws IOException {
634:                    _out.close();
635:                }
636:
637:                /* ------------------------------------------------------------ */
638:                public void flush() throws IOException {
639:                    _out.flush();
640:                }
641:
642:                /* ------------------------------------------------------------ */
643:                public void write(String s, int offset, int length)
644:                        throws IOException {
645:                    while (length > MAX_OUTPUT_CHARS) {
646:                        write(s, offset, MAX_OUTPUT_CHARS);
647:                        offset += MAX_OUTPUT_CHARS;
648:                        length -= MAX_OUTPUT_CHARS;
649:                    }
650:
651:                    if (_out._chars == null)
652:                        _out._chars = new char[MAX_OUTPUT_CHARS];
653:                    char[] chars = _out._chars;
654:                    s.getChars(offset, offset + length, chars, 0);
655:                    write(chars, 0, length);
656:                }
657:
658:                /* ------------------------------------------------------------ */
659:                public void write(char[] s, int offset, int length)
660:                        throws IOException {
661:                    while (length > MAX_OUTPUT_CHARS) {
662:                        write(s, offset, MAX_OUTPUT_CHARS);
663:                        offset += MAX_OUTPUT_CHARS;
664:                        length -= MAX_OUTPUT_CHARS;
665:                    }
666:
667:                    Output out = _out;
668:
669:                    switch (_writeMode) {
670:                    case WRITE_CONV: {
671:                        Writer converter = getConverter();
672:                        converter.write(s, offset, length);
673:                        converter.flush();
674:                    }
675:                        break;
676:
677:                    case WRITE_ISO1: {
678:
679:                        byte[] buffer = out._bytes.getBuf();
680:                        int count = out._bytes.getCount();
681:
682:                        for (int i = 0; i < length; i++) {
683:                            int c = s[offset + i];
684:                            buffer[count++] = (byte) ((c >= 0 && c < 256) ? c
685:                                    : '?'); // ISO-1 and UTF-8 match for 0 - 255
686:                        }
687:                        if (count >= 0)
688:                            out._bytes.setCount(count);
689:
690:                        break;
691:                    }
692:
693:                    case WRITE_UTF8: {
694:                        byte[] buffer = out._bytes.getBuf();
695:                        int count = out._bytes.getCount();
696:                        for (int i = 0; i < length; i++) {
697:                            int code = s[offset + i];
698:
699:                            if ((code & 0xffffff80) == 0) {
700:                                // 1b
701:                                buffer[count++] = (byte) (code);
702:                            } else if ((code & 0xfffff800) == 0) {
703:                                // 2b
704:                                buffer[count++] = (byte) (0xc0 | (code >> 6));
705:                                buffer[count++] = (byte) (0x80 | (code & 0x3f));
706:                            } else if ((code & 0xffff0000) == 0) {
707:                                // 3b
708:                                buffer[count++] = (byte) (0xe0 | (code >> 12));
709:                                buffer[count++] = (byte) (0x80 | ((code >> 6) & 0x3f));
710:                                buffer[count++] = (byte) (0x80 | (code & 0x3f));
711:                            } else if ((code & 0xff200000) == 0) {
712:                                // 4b
713:                                buffer[count++] = (byte) (0xf0 | (code >> 18));
714:                                buffer[count++] = (byte) (0x80 | ((code >> 12) & 0x3f));
715:                                buffer[count++] = (byte) (0x80 | ((code >> 6) & 0x3f));
716:                                buffer[count++] = (byte) (0x80 | (code & 0x3f));
717:                            } else if ((code & 0xf4000000) == 0) {
718:                                // 5
719:                                buffer[count++] = (byte) (0xf8 | (code >> 24));
720:                                buffer[count++] = (byte) (0x80 | ((code >> 18) & 0x3f));
721:                                buffer[count++] = (byte) (0x80 | ((code >> 12) & 0x3f));
722:                                buffer[count++] = (byte) (0x80 | ((code >> 6) & 0x3f));
723:                                buffer[count++] = (byte) (0x80 | (code & 0x3f));
724:                            } else if ((code & 0x80000000) == 0) {
725:                                // 6b
726:                                buffer[count++] = (byte) (0xfc | (code >> 30));
727:                                buffer[count++] = (byte) (0x80 | ((code >> 24) & 0x3f));
728:                                buffer[count++] = (byte) (0x80 | ((code >> 18) & 0x3f));
729:                                buffer[count++] = (byte) (0x80 | ((code >> 12) & 0x3f));
730:                                buffer[count++] = (byte) (0x80 | ((code >> 6) & 0x3f));
731:                                buffer[count++] = (byte) (0x80 | (code & 0x3f));
732:                            } else {
733:                                buffer[count++] = (byte) ('?');
734:                            }
735:                        }
736:                        out._bytes.setCount(count);
737:                        break;
738:                    }
739:                    default:
740:                        throw new IllegalStateException();
741:                    }
742:                    out._bytes.writeTo(out);
743:                    out._bytes.reset();
744:                }
745:
746:                /* ------------------------------------------------------------ */
747:                private Writer getConverter() throws IOException {
748:                    if (_out._converter == null)
749:                        _out._converter = new OutputStreamWriter(_out._bytes,
750:                                _out._characterEncoding);
751:                    return _out._converter;
752:                }
753:            }
754:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.