Source Code Cross Referenced for CharsetEncoder.java in  » Apache-Harmony-Java-SE » java-package » java » nio » charset » 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 » Apache Harmony Java SE » java package » java.nio.charset 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* Licensed to the Apache Software Foundation (ASF) under one or more
002:         * contributor license agreements.  See the NOTICE file distributed with
003:         * this work for additional information regarding copyright ownership.
004:         * The ASF licenses this file to You under the Apache License, Version 2.0
005:         * (the "License"); you may not use this file except in compliance with
006:         * the License.  You may obtain a copy of the License at
007:         * 
008:         *     http://www.apache.org/licenses/LICENSE-2.0
009:         * 
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package java.nio.charset;
018:
019:        import java.nio.BufferOverflowException;
020:        import java.nio.BufferUnderflowException;
021:        import java.nio.ByteBuffer;
022:        import java.nio.CharBuffer;
023:
024:        import org.apache.harmony.niochar.internal.nls.Messages;
025:
026:        /**
027:         * An converter that can convert 16-bit Unicode character sequence to byte
028:         * sequence in some charset .
029:         * <p>
030:         * The input character sequence is wrapped by
031:         * {@link java.nio.CharBuffer CharBuffer} and the output character sequence is
032:         * {@link java.nio.ByteBuffer ByteBuffer}. A encoder instance should be used in
033:         * following sequence, which is referred to as a encoding operation:
034:         * <ol>
035:         * <li>Invoking the {@link #reset() reset} method to reset the encoder if the
036:         * encoder has been used;</li>
037:         * <li>Invoking the {@link #encode(CharBuffer, ByteBuffer, boolean) encode}
038:         * method until the additional input is not needed, the <code>endOfInput</code>
039:         * parameter must be set to false, the input buffer must be filled and the
040:         * output buffer must be flushed between invocations;</li>
041:         * <li>Invoking the {@link #encode(CharBuffer, ByteBuffer, boolean) encode}
042:         * method last time, and the the <code>endOfInput</code> parameter must be set
043:         * to true</li>
044:         * <li>Invoking the {@link #flush(ByteBuffer) flush} method to flush the
045:         * output.</li>
046:         * </ol>
047:         * </p>
048:         * <p>
049:         * The {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method will
050:         * convert as many characters as possible, and the process won't stop except the
051:         * input characters has been run out of, the output buffer has been filled or
052:         * some error has happened. A {@link CoderResult CoderResult} instance will be
053:         * returned to indicate the stop reason, and the invoker can identify the result
054:         * and choose further action, which can include filling the input buffer,
055:         * flushing the output buffer, recovering from error and trying again.
056:         * </p>
057:         * <p>
058:         * There are two common encoding errors. One is named as malformed and it is
059:         * returned when the input content is illegal 16-bit Unicode character sequence,
060:         * the other is named as unmappable character and occurs when there is a problem
061:         * mapping the input to a valid byte sequence in the specific charset.
062:         * </p>
063:         * <p>
064:         * The two errors can be handled in three ways, the default one is to report the
065:         * error to the invoker by a {@link CoderResult CoderResult} instance, and the
066:         * alternatives are to ignore it or to replace the erroneous input with the
067:         * replacement byte array. The replacement byte array is {(byte)'?'} by default
068:         * and can be changed by invoking {@link #replaceWith(byte[]) replaceWith}
069:         * method. The invoker of this encoder can choose one way by specifying a
070:         * {@link CodingErrorAction CodingErrorAction} instance for each error type via
071:         * {@link #onMalformedInput(CodingErrorAction) onMalformedInput} method and
072:         * {@link #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter}
073:         * method.
074:         * </p>
075:         * <p>
076:         * This class is abstract class and encapsulate many common operations of
077:         * encoding process for all charsets. encoder for specific charset should extend
078:         * this class and need only implement
079:         * {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} method for basic
080:         * encoding loop. If a subclass maintains internal state, it should override the
081:         * {@link #implFlush(ByteBuffer) implFlush} method and
082:         * {@link #implReset() implReset} method in addition.
083:         * </p>
084:         * <p>
085:         * This class is not thread-safe.
086:         * </p>
087:         * 
088:         * @see java.nio.charset.Charset
089:         * @see java.nio.charset.CharsetDecoder
090:         */
091:        public abstract class CharsetEncoder {
092:            /*
093:             * --------------------------------------- Consts
094:             * ---------------------------------------
095:             */
096:            /*
097:             * internal status consts
098:             */
099:            private static final int INIT = 0;
100:
101:            private static final int ONGOING = 1;
102:
103:            private static final int END = 2;
104:
105:            private static final int FLUSH = 3;
106:
107:            /*
108:             * --------------------------------------- Instance variables
109:             * ---------------------------------------
110:             */
111:            // the Charset which creates this encoder
112:            private Charset cs;
113:
114:            // average bytes per character created by this encoder
115:            private float averBytes;
116:
117:            // maximum bytes per character can be created by this encoder
118:            private float maxBytes;
119:
120:            // replacement byte array
121:            private byte[] replace;
122:
123:            // internal status
124:            private int status;
125:
126:            // action for malformed input
127:            private CodingErrorAction malformAction;
128:
129:            // action for unmapped char input
130:            private CodingErrorAction unmapAction;
131:
132:            // decoder instance for this encoder's charset, used for replacement value
133:            // checking
134:            private CharsetDecoder decoder;
135:
136:            /*
137:             * --------------------------------------- Constructors
138:             * ---------------------------------------
139:             */
140:
141:            /**
142:             * Construct a new <code>CharsetEncoder</code> using given
143:             * <code>Charset</code>, average number and maximum number of bytes
144:             * created by this encoder for one input character.
145:             * 
146:             * @param cs
147:             *            this encoder's <code>Charset</code>, which create this
148:             *            encoder
149:             * @param averageBytesPerChar
150:             *            average number of bytes created by this encoder for one input
151:             *            character, must be positive
152:             * @param maxBytesPerChar
153:             *            maximum number of bytes which can be created by this encoder
154:             *            for one input character, must be positive
155:             * @throws IllegalArgumentException
156:             *             if <code>maxBytesPerChar</code> or
157:             *             <code>averageBytePerChar</code> is negative
158:             */
159:            protected CharsetEncoder(Charset cs, float averageBytesPerChar,
160:                    float maxBytesPerChar) {
161:                this (cs, averageBytesPerChar, maxBytesPerChar,
162:                        new byte[] { (byte) '?' });
163:            }
164:
165:            /**
166:             * Construct a new <code>CharsetEncoder</code> using given
167:             * <code>Charset</code>, replace byte array, average number and maximum
168:             * number of bytes created by this encoder for one input character.
169:             * 
170:             * @param cs
171:             *            the this encoder's <code>Charset</code>, which create this
172:             *            encoder
173:             * @param averageBytesPerChar
174:             *            average number of bytes created by this encoder for single
175:             *            input character, must be positive
176:             * @param maxBytesPerChar
177:             *            maximum number of bytes which can be created by this encoder
178:             *            for single input character, must be positive
179:             * @param replacement
180:             *            the replacement byte array, cannot be null or empty, its
181:             *            length cannot larger than <code>maxBytesPerChar</code>, and
182:             *            must be legal replacement, which can be justified by
183:             *            {@link #isLegalReplacement(byte[]) isLegalReplacement}
184:             * @throws IllegalArgumentException
185:             *             if any parameters are invalid
186:             */
187:            protected CharsetEncoder(Charset cs, float averageBytesPerChar,
188:                    float maxBytesPerChar, byte[] replacement) {
189:                if (averageBytesPerChar <= 0 || maxBytesPerChar <= 0) {
190:                    // niochar.02=Bytes number for one character must be positive.
191:                    throw new IllegalArgumentException(Messages
192:                            .getString("niochar.02")); //$NON-NLS-1$
193:                }
194:                if (averageBytesPerChar > maxBytesPerChar) {
195:                    // niochar.03=averageBytesPerChar is greater than maxBytesPerChar.
196:                    throw new IllegalArgumentException(Messages
197:                            .getString("niochar.03")); //$NON-NLS-1$
198:                }
199:                this .cs = cs;
200:                averBytes = averageBytesPerChar;
201:                maxBytes = maxBytesPerChar;
202:                status = INIT;
203:                malformAction = CodingErrorAction.REPORT;
204:                unmapAction = CodingErrorAction.REPORT;
205:                replaceWith(replacement);
206:            }
207:
208:            /*
209:             * --------------------------------------- Methods
210:             * ---------------------------------------
211:             */
212:            /**
213:             * get the average number of bytes created by this encoder for single input
214:             * character
215:             * 
216:             * @return the average number of bytes created by this encoder for single
217:             *         input character
218:             */
219:            public final float averageBytesPerChar() {
220:                return averBytes;
221:            }
222:
223:            /**
224:             * Check if given character can be encoded by this encoder.
225:             * 
226:             * Note that this method can change the internal status of this encoder, so
227:             * it should not be called when another encode process is ongoing, otherwise
228:             * it will throw <code>IllegalStateException</code>.
229:             * 
230:             * This method can be overridden for performance improvement.
231:             * 
232:             * @param c
233:             *            the given encoder
234:             * @return true if given character can be encoded by this encoder
235:             * @throws IllegalStateException
236:             *             if another encode process is ongoing so that current internal
237:             *             status is neither RESET or FLUSH
238:             */
239:            public boolean canEncode(char c) {
240:                return implCanEncode(CharBuffer.wrap(new char[] { c }));
241:            }
242:
243:            // implementation of canEncode
244:            private boolean implCanEncode(CharBuffer cb) {
245:                if (status == FLUSH) {
246:                    status = INIT;
247:                }
248:                if (status != INIT) {
249:                    // niochar.0B=Another encoding process is ongoing\!
250:                    throw new IllegalStateException(Messages
251:                            .getString("niochar.0B")); //$NON-NLS-1$
252:                }
253:                CodingErrorAction malformBak = malformAction;
254:                CodingErrorAction unmapBak = unmapAction;
255:                onMalformedInput(CodingErrorAction.REPORT);
256:                onUnmappableCharacter(CodingErrorAction.REPORT);
257:                boolean result = true;
258:                try {
259:                    this .encode(cb);
260:                } catch (CharacterCodingException e) {
261:                    result = false;
262:                }
263:                onMalformedInput(malformBak);
264:                onUnmappableCharacter(unmapBak);
265:                reset();
266:                return result;
267:            }
268:
269:            /**
270:             * Check if given <code>CharSequence</code> can be encoded by this
271:             * encoder.
272:             * 
273:             * Note that this method can change the internal status of this encoder, so
274:             * it should not be called when another encode process is ongoing, otherwise
275:             * it will throw <code>IllegalStateException</code>.
276:             * 
277:             * This method can be overridden for performance improvement.
278:             * 
279:             * @param sequence
280:             *            the given <code>CharSequence</code>
281:             * @return true if given <code>CharSequence</code> can be encoded by this
282:             *         encoder
283:             * @throws IllegalStateException
284:             *             if current internal status is neither RESET or FLUSH
285:             */
286:            public boolean canEncode(CharSequence sequence) {
287:                CharBuffer cb;
288:                if (sequence instanceof  CharBuffer) {
289:                    cb = ((CharBuffer) sequence).duplicate();
290:                } else {
291:                    cb = CharBuffer.wrap(sequence);
292:                }
293:                return implCanEncode(cb);
294:            }
295:
296:            /**
297:             * Get the <code>Charset</code> which creates this encoder.
298:             * 
299:             * @return the <code>Charset</code> which creates this encoder
300:             */
301:            public final Charset charset() {
302:                return cs;
303:            }
304:
305:            /**
306:             * This is a facade method for encoding operation.
307:             * <p>
308:             * This method encodes the remaining character sequence of the given
309:             * character buffer into a new byte buffer. This method performs a complete
310:             * encoding operation, resets at first, then encodes, and flushes at last.
311:             * </p>
312:             * <p>
313:             * This method should not be invoked if another encode operation is ongoing.
314:             * </p>
315:             * 
316:             * @param in
317:             *            the input buffer
318:             * @return a new <code>ByteBuffer</code> containing the the bytes produced
319:             *         by this encoding operation. The buffer's limit will be the
320:             *         position of last byte in buffer, and the position will be zero
321:             * @throws IllegalStateException
322:             *             if another encoding operation is ongoing
323:             * @throws MalformedInputException
324:             *             if illegal input character sequence for this charset
325:             *             encountered, and the action for malformed error is
326:             *             {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}
327:             * @throws UnmappableCharacterException
328:             *             if legal but unmappable input character sequence for this
329:             *             charset encountered, and the action for unmappable character
330:             *             error is
331:             *             {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.
332:             *             Unmappable means the Unicode character sequence at the input
333:             *             buffer's current position cannot be mapped to a equivalent
334:             *             byte sequence.
335:             * @throws CharacterCodingException
336:             *             if other exception happened during the encode operation
337:             */
338:            public final ByteBuffer encode(CharBuffer in)
339:                    throws CharacterCodingException {
340:                if (in.remaining() == 0) {
341:                    return ByteBuffer.allocate(0);
342:                }
343:                reset();
344:                int length = (int) (in.remaining() * averBytes);
345:                ByteBuffer output = ByteBuffer.allocate(length);
346:                CoderResult result = null;
347:                while (true) {
348:                    result = encode(in, output, false);
349:                    if (result == CoderResult.UNDERFLOW) {
350:                        break;
351:                    } else if (result == CoderResult.OVERFLOW) {
352:                        output = allocateMore(output);
353:                        continue;
354:                    }
355:                    checkCoderResult(result);
356:                }
357:                result = encode(in, output, true);
358:                checkCoderResult(result);
359:
360:                while (true) {
361:                    result = flush(output);
362:                    if (result == CoderResult.UNDERFLOW) {
363:                        output.flip();
364:                        break;
365:                    } else if (result == CoderResult.OVERFLOW) {
366:                        output = allocateMore(output);
367:                        continue;
368:                    }
369:                    checkCoderResult(result);
370:                    output.flip();
371:                    if (result.isMalformed()) {
372:                        throw new MalformedInputException(result.length());
373:                    } else if (result.isUnmappable()) {
374:                        throw new UnmappableCharacterException(result.length());
375:                    }
376:                    break;
377:                }
378:                status = FLUSH;
379:                return output;
380:            }
381:
382:            /*
383:             * checks the result whether it needs to throw CharacterCodingException.
384:             */
385:            private void checkCoderResult(CoderResult result)
386:                    throws CharacterCodingException {
387:                if (malformAction == CodingErrorAction.REPORT
388:                        && result.isMalformed()) {
389:                    throw new MalformedInputException(result.length());
390:                } else if (unmapAction == CodingErrorAction.REPORT
391:                        && result.isUnmappable()) {
392:                    throw new UnmappableCharacterException(result.length());
393:                }
394:            }
395:
396:            // allocate more spaces to the given ByteBuffer
397:            private ByteBuffer allocateMore(ByteBuffer output) {
398:                if (output.capacity() == 0) {
399:                    return ByteBuffer.allocate(1);
400:                }
401:                ByteBuffer result = ByteBuffer.allocate(output.capacity() * 2);
402:                output.flip();
403:                result.put(output);
404:                return result;
405:            }
406:
407:            /**
408:             * Encodes characters starting at the current position of the given input
409:             * buffer, and writes the equivalent byte sequence into the given output
410:             * buffer from its current position.
411:             * <p>
412:             * The buffers' position will be changed with the reading and writing
413:             * operation, but their limits and marks will be kept intact.
414:             * </p>
415:             * <p>
416:             * A <code>CoderResult</code> instance will be returned according to
417:             * following rules:
418:             * <ul>
419:             * <li>A {@link CoderResult#malformedForLength(int) malformed input} result
420:             * indicates that some malformed input error encountered, and the erroneous
421:             * characters start at the input buffer's position and their number can be
422:             * got by result's {@link CoderResult#length() length}. This kind of result
423:             * can be returned only if the malformed action is
424:             * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}. </li>
425:             * <li>{@link CoderResult#UNDERFLOW CoderResult.UNDERFLOW} indicates that
426:             * as many characters as possible in the input buffer has been encoded. If
427:             * there is no further input and no characters left in the input buffer then
428:             * this task is complete. If this is not the case then the client should
429:             * call this method again supplying some more input characters.</li>
430:             * <li>{@link CoderResult#OVERFLOW CoderResult.OVERFLOW} indicates that the
431:             * output buffer has been filled, while there are still some characters
432:             * remaining in the input buffer. This method should be invoked again with a
433:             * non-full output buffer </li>
434:             * <li>A {@link CoderResult#unmappableForLength(int) unmappable character}
435:             * result indicates that some unmappable character error was encountered,
436:             * and the erroneous characters start at the input buffer's position and
437:             * their number can be got by result's {@link CoderResult#length() length}.
438:             * This kind of result can be returned only on
439:             * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}. </li>
440:             * </ul>
441:             * </p>
442:             * <p>
443:             * The <code>endOfInput</code> parameter indicates that if the invoker can
444:             * provider further input. This parameter is true if and only if the
445:             * characters in current input buffer are all inputs for this encoding
446:             * operation. Note that it is common and won't cause error that the invoker
447:             * sets false and then finds no more input available; while it may cause
448:             * error that the invoker always sets true in several consecutive
449:             * invocations so that any remaining input will be treated as malformed
450:             * input.
451:             * </p>
452:             * <p>
453:             * This method invokes
454:             * {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} method to
455:             * implement basic encode logic for specific charset.
456:             * </p>
457:             * 
458:             * @param in
459:             *            the input buffer
460:             * @param out
461:             *            the output buffer
462:             * @param endOfInput
463:             *            true if all the input characters have been provided
464:             * @return a <code>CoderResult</code> instance indicating the result
465:             * @throws IllegalStateException
466:             *             if the encoding operation has already started or no more
467:             *             input needed in this encoding progress.
468:             * @throws CoderMalfunctionError
469:             *             If the {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop}
470:             *             method threw an <code>BufferUnderflowException</code> or
471:             *             <code>BufferUnderflowException</code>
472:             */
473:            public final CoderResult encode(CharBuffer in, ByteBuffer out,
474:                    boolean endOfInput) {
475:                if ((status == FLUSH) || (!endOfInput && status == END)) {
476:                    throw new IllegalStateException();
477:                }
478:
479:                CoderResult result;
480:                while (true) {
481:                    try {
482:                        result = encodeLoop(in, out);
483:                    } catch (BufferOverflowException e) {
484:                        throw new CoderMalfunctionError(e);
485:                    } catch (BufferUnderflowException e) {
486:                        throw new CoderMalfunctionError(e);
487:                    }
488:                    if (result == CoderResult.UNDERFLOW) {
489:                        status = endOfInput ? END : ONGOING;
490:                        if (endOfInput) {
491:                            int remaining = in.remaining();
492:                            if (remaining > 0) {
493:                                result = CoderResult
494:                                        .malformedForLength(remaining);
495:                            } else {
496:                                return result;
497:                            }
498:                        } else {
499:                            return result;
500:                        }
501:                    } else if (result == CoderResult.OVERFLOW) {
502:                        status = endOfInput ? END : ONGOING;
503:                        return result;
504:                    }
505:                    CodingErrorAction action = malformAction;
506:                    if (result.isUnmappable()) {
507:                        action = unmapAction;
508:                    }
509:                    // If the action is IGNORE or REPLACE, we should continue
510:                    // encoding.
511:                    if (action == CodingErrorAction.REPLACE) {
512:                        if (out.remaining() < replace.length) {
513:                            return CoderResult.OVERFLOW;
514:                        }
515:                        out.put(replace);
516:                    } else {
517:                        if (action != CodingErrorAction.IGNORE) {
518:                            return result;
519:                        }
520:                    }
521:                    in.position(in.position() + result.length());
522:                }
523:            }
524:
525:            /**
526:             * Encode characters into bytes. This method is called by
527:             * {@link #encode(CharBuffer, ByteBuffer, boolean) encode}.
528:             * 
529:             * This method will implement the essential encoding operation, and it won't
530:             * stop encoding until either all the input characters are read, the output
531:             * buffer is filled, or some exception encountered. And then it will return
532:             * a <code>CoderResult</code> object indicating the result of current
533:             * encoding operation. The rules to construct the <code>CoderResult</code>
534:             * is same as the {@link #encode(CharBuffer, ByteBuffer, boolean) encode}.
535:             * When exception encountered in the encoding operation, most implementation
536:             * of this method will return a relevant result object to
537:             * {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method, and some
538:             * performance optimized implementation may handle the exception and
539:             * implement the error action itself.
540:             * 
541:             * The buffers are scanned from their current positions, and their positions
542:             * will be modified accordingly, while their marks and limits will be
543:             * intact. At most {@link CharBuffer#remaining() in.remaining()} characters
544:             * will be read, and {@link ByteBuffer#remaining() out.remaining()} bytes
545:             * will be written.
546:             * 
547:             * Note that some implementation may pre-scan the input buffer and return
548:             * <code>CoderResult.UNDERFLOW</code> until it receives sufficient input.
549:             * 
550:             * @param in
551:             *            the input buffer
552:             * @param out
553:             *            the output buffer
554:             * @return a <code>CoderResult</code> instance indicating the result
555:             */
556:            protected abstract CoderResult encodeLoop(CharBuffer in,
557:                    ByteBuffer out);
558:
559:            /**
560:             * Flush this encoder.
561:             * 
562:             * This method will call {@link #implFlush(ByteBuffer) implFlush}. Some
563:             * encoders may need to write some bytes to the output buffer when they have
564:             * read all input characters, subclasses can overridden
565:             * {@link #implFlush(ByteBuffer) implFlush} to perform writing action.
566:             * 
567:             * The maximum number of written bytes won't larger than
568:             * {@link ByteBuffer#remaining() out.remaining()}. If some encoder want to
569:             * write more bytes than output buffer's remaining spaces, then
570:             * <code>CoderResult.OVERFLOW</code> will be returned, and this method
571:             * must be called again with a byte buffer has more spaces. Otherwise this
572:             * method will return <code>CoderResult.UNDERFLOW</code>, which means one
573:             * encoding process has been completed successfully.
574:             * 
575:             * During the flush, the output buffer's position will be changed
576:             * accordingly, while its mark and limit will be intact.
577:             * 
578:             * @param out
579:             *            the given output buffer
580:             * @return <code>CoderResult.UNDERFLOW</code> or
581:             *         <code>CoderResult.OVERFLOW</code>
582:             * @throws IllegalStateException
583:             *             if this encoder hasn't read all input characters during one
584:             *             encoding process, which means neither after calling
585:             *             {@link #encode(CharBuffer) encode(CharBuffer)} nor after
586:             *             calling {@link #encode(CharBuffer, ByteBuffer, boolean) 
587:             *             encode(CharBuffer, ByteBuffer, boolean)} with true value for
588:             *             the last boolean parameter
589:             */
590:            public final CoderResult flush(ByteBuffer out) {
591:                if (status != END && status != INIT) {
592:                    throw new IllegalStateException();
593:                }
594:                CoderResult result = implFlush(out);
595:                if (result == CoderResult.UNDERFLOW) {
596:                    status = FLUSH;
597:                }
598:                return result;
599:            }
600:
601:            /**
602:             * Flush this encoder. Default implementation does nothing and always return
603:             * <code>CoderResult.UNDERFLOW</code>, and this method can be overridden
604:             * if needed.
605:             * 
606:             * @param out
607:             *            the output buffer
608:             * @return <code>CoderResult.UNDERFLOW</code> or
609:             *         <code>CoderResult.OVERFLOW</code>
610:             */
611:            protected CoderResult implFlush(ByteBuffer out) {
612:                return CoderResult.UNDERFLOW;
613:            }
614:
615:            /**
616:             * Notify that this encoder's <code>CodingErrorAction</code> specified for
617:             * malformed input error has been changed. Default implementation does
618:             * nothing, and this method can be overridden if needed.
619:             * 
620:             * @param newAction
621:             *            The new action
622:             */
623:            protected void implOnMalformedInput(CodingErrorAction newAction) {
624:                // default implementation is empty
625:            }
626:
627:            /**
628:             * Notify that this encoder's <code>CodingErrorAction</code> specified for
629:             * unmappable character error has been changed. Default implementation does
630:             * nothing, and this method can be overridden if needed.
631:             * 
632:             * @param newAction
633:             *            The new action
634:             */
635:            protected void implOnUnmappableCharacter(CodingErrorAction newAction) {
636:                // default implementation is empty
637:            }
638:
639:            /**
640:             * Notify that this encoder's replacement has been changed. Default
641:             * implementation does nothing, and this method can be overridden if needed.
642:             * 
643:             * @param newReplacement
644:             *            the new replacement string
645:             */
646:            protected void implReplaceWith(byte[] newReplacement) {
647:                // default implementation is empty
648:            }
649:
650:            /**
651:             * Reset this encoder's charset related state. Default implementation does
652:             * nothing, and this method can be overridden if needed.
653:             */
654:            protected void implReset() {
655:                // default implementation is empty
656:            }
657:
658:            /**
659:             * Check if the given argument is legal as this encoder's replacement byte
660:             * array.
661:             * 
662:             * The given byte array is legal if and only if it can be decode into
663:             * sixteen bits Unicode characters.
664:             * 
665:             * This method can be overridden for performance improvement.
666:             * 
667:             * @param repl
668:             *            the given byte array to be checked
669:             * @return true if the the given argument is legal as this encoder's
670:             *         replacement byte array.
671:             */
672:            public boolean isLegalReplacement(byte[] repl) {
673:                if (decoder == null) {
674:                    decoder = cs.newDecoder();
675:                }
676:
677:                CodingErrorAction malform = decoder.malformedInputAction();
678:                CodingErrorAction unmap = decoder.unmappableCharacterAction();
679:                decoder.onMalformedInput(CodingErrorAction.REPORT);
680:                decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
681:                ByteBuffer in = ByteBuffer.wrap(repl);
682:                CharBuffer out = CharBuffer
683:                        .allocate((int) (repl.length * decoder
684:                                .maxCharsPerByte()));
685:                CoderResult result = decoder.decode(in, out, true);
686:                decoder.onMalformedInput(malform);
687:                decoder.onUnmappableCharacter(unmap);
688:                return !result.isError();
689:            }
690:
691:            /**
692:             * Gets this encoder's <code>CodingErrorAction</code> when malformed input
693:             * occurred during encoding process.
694:             * 
695:             * @return this encoder's <code>CodingErrorAction</code> when malformed
696:             *         input occurred during encoding process.
697:             */
698:            public CodingErrorAction malformedInputAction() {
699:                return malformAction;
700:            }
701:
702:            /**
703:             * Get the maximum number of bytes which can be created by this encoder for
704:             * one input character, must be positive
705:             * 
706:             * @return the maximum number of bytes which can be created by this encoder
707:             *         for one input character, must be positive
708:             */
709:            public final float maxBytesPerChar() {
710:                return maxBytes;
711:            }
712:
713:            /**
714:             * Set this encoder's action on malformed input error.
715:             * 
716:             * This method will call the
717:             * {@link #implOnMalformedInput(CodingErrorAction) implOnMalformedInput}
718:             * method with the given new action as argument.
719:             * 
720:             * @param newAction
721:             *            the new action on malformed input error
722:             * @return this encoder
723:             * @throws IllegalArgumentException
724:             *             if the given newAction is null
725:             */
726:            public final CharsetEncoder onMalformedInput(
727:                    CodingErrorAction newAction) {
728:                if (null == newAction) {
729:                    // niochar.0C=Action on malformed input error cannot be null\!
730:                    throw new IllegalArgumentException(Messages
731:                            .getString("niochar.0C")); //$NON-NLS-1$
732:                }
733:                malformAction = newAction;
734:                implOnMalformedInput(newAction);
735:                return this ;
736:            }
737:
738:            /**
739:             * Set this encoder's action on unmappable character error.
740:             * 
741:             * This method will call the
742:             * {@link #implOnUnmappableCharacter(CodingErrorAction) implOnUnmappableCharacter}
743:             * method with the given new action as argument.
744:             * 
745:             * @param newAction
746:             *            the new action on unmappable character error
747:             * @return this encoder
748:             * @throws IllegalArgumentException
749:             *             if the given newAction is null
750:             */
751:            public final CharsetEncoder onUnmappableCharacter(
752:                    CodingErrorAction newAction) {
753:                if (null == newAction) {
754:                    // niochar.0D=Action on unmappable character error cannot be null\!
755:                    throw new IllegalArgumentException(Messages
756:                            .getString("niochar.0D")); //$NON-NLS-1$
757:                }
758:                unmapAction = newAction;
759:                implOnUnmappableCharacter(newAction);
760:                return this ;
761:            }
762:
763:            /**
764:             * Get the replacement byte array, which is never null or empty, and it is
765:             * legal
766:             * 
767:             * @return the replacement byte array, cannot be null or empty, and it is
768:             *         legal
769:             */
770:            public final byte[] replacement() {
771:                return replace;
772:            }
773:
774:            /**
775:             * Set new replacement value.
776:             * 
777:             * This method first checks the given replacement's validity, then changes
778:             * the replacement value, and at last calls
779:             * {@link #implReplaceWith(byte[]) implReplaceWith} method with the given
780:             * new replacement as argument.
781:             * 
782:             * @param replacement
783:             *            the replacement byte array, cannot be null or empty, its
784:             *            length cannot larger than <code>maxBytesPerChar</code>, and
785:             *            must be legal replacement, which can be justified by
786:             *            <code>isLegalReplacement(byte[] repl)</code>
787:             * @return this encoder
788:             * @throws IllegalArgumentException
789:             *             if the given replacement cannot satisfy the requirement
790:             *             mentioned above
791:             */
792:            public final CharsetEncoder replaceWith(byte[] replacement) {
793:                if (null == replacement || 0 == replacement.length
794:                        || maxBytes < replacement.length
795:                        || !isLegalReplacement(replacement)) {
796:                    // niochar.0E=Replacement is illegal
797:                    throw new IllegalArgumentException(Messages
798:                            .getString("niochar.0E")); //$NON-NLS-1$
799:                }
800:                replace = replacement;
801:                implReplaceWith(replacement);
802:                return this ;
803:            }
804:
805:            /**
806:             * Reset this encoder. This method will reset internal status, and then call
807:             * <code>implReset()</code> to reset any status related to specific
808:             * charset.
809:             * 
810:             * @return this encoder
811:             */
812:            public final CharsetEncoder reset() {
813:                status = INIT;
814:                implReset();
815:                return this ;
816:            }
817:
818:            /**
819:             * Gets this encoder's <code>CodingErrorAction</code> when unmappable
820:             * character occurred during encoding process.
821:             * 
822:             * @return this encoder's <code>CodingErrorAction</code> when unmappable
823:             *         character occurred during encoding process.
824:             */
825:            public CodingErrorAction unmappableCharacterAction() {
826:                return unmapAction;
827:            }
828:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.