Source Code Cross Referenced for DatatypeConverterImpl.java in  » 6.0-JDK-Modules » jaxb-api » javax » xml » bind » 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 » 6.0 JDK Modules » jaxb api » javax.xml.bind 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package javax.xml.bind;
002:
003:        import javax.xml.namespace.QName;
004:        import javax.xml.namespace.NamespaceContext;
005:        import javax.xml.datatype.DatatypeFactory;
006:        import javax.xml.datatype.DatatypeConfigurationException;
007:        import java.math.BigInteger;
008:        import java.math.BigDecimal;
009:        import java.util.Calendar;
010:        import java.util.GregorianCalendar;
011:        import java.util.TimeZone;
012:
013:        /**
014:         * This class is the JAXB RI's default implementation of the
015:         * {@link DatatypeConverterInterface}.
016:         *
017:         * <p>
018:         * When client apps specify the use of the static print/parse
019:         * methods in {@link DatatypeConverter}, it will delegate
020:         * to this class.
021:         *
022:         * <p>
023:         * This class is responsible for whitespace normalization.
024:         *
025:         * @author <ul><li>Ryan Shoemaker, Sun Microsystems, Inc.</li></ul>
026:         * @version $Revision: 1.1 $
027:         * @since JAXB2.1
028:         */
029:        final class DatatypeConverterImpl implements  DatatypeConverterInterface {
030:
031:            /**
032:             * To avoid re-creating instances, we cache one instance.
033:             */
034:            public static final DatatypeConverterInterface theInstance = new DatatypeConverterImpl();
035:
036:            protected DatatypeConverterImpl() {
037:            }
038:
039:            public String parseString(String lexicalXSDString) {
040:                return lexicalXSDString;
041:            }
042:
043:            public BigInteger parseInteger(String lexicalXSDInteger) {
044:                return _parseInteger(lexicalXSDInteger);
045:            }
046:
047:            public static BigInteger _parseInteger(CharSequence s) {
048:                return new BigInteger(removeOptionalPlus(
049:                        WhiteSpaceProcessor.trim(s)).toString());
050:            }
051:
052:            public String printInteger(BigInteger val) {
053:                return _printInteger(val);
054:            }
055:
056:            public static String _printInteger(BigInteger val) {
057:                return val.toString();
058:            }
059:
060:            public int parseInt(String s) {
061:                return _parseInt(s);
062:            }
063:
064:            /**
065:             * Faster but less robust String->int conversion.
066:             *
067:             * Note that:
068:             * <ol>
069:             *  <li>XML Schema allows '+', but {@link Integer#valueOf(String)} is not.
070:             *  <li>XML Schema allows leading and trailing (but not in-between) whitespaces..
071:             *      {@link Integer#valueOf(String)} doesn't allow any.
072:             * </ol>
073:             */
074:            public static int _parseInt(CharSequence s) {
075:                int len = s.length();
076:                int sign = 1;
077:
078:                int r = 0;
079:
080:                for (int i = 0; i < len; i++) {
081:                    char ch = s.charAt(i);
082:                    if (WhiteSpaceProcessor.isWhiteSpace(ch)) {
083:                        // skip whitespace
084:                    } else if ('0' <= ch && ch <= '9') {
085:                        r = r * 10 + (ch - '0');
086:                    } else if (ch == '-') {
087:                        sign = -1;
088:                    } else if (ch == '+') {
089:                        // noop
090:                    } else
091:                        throw new NumberFormatException("Not a number: " + s);
092:                }
093:
094:                return r * sign;
095:            }
096:
097:            public long parseLong(String lexicalXSLong) {
098:                return _parseLong(lexicalXSLong);
099:            }
100:
101:            public static long _parseLong(CharSequence s) {
102:                return Long.valueOf(removeOptionalPlus(
103:                        WhiteSpaceProcessor.trim(s)).toString());
104:            }
105:
106:            public short parseShort(String lexicalXSDShort) {
107:                return _parseShort(lexicalXSDShort);
108:            }
109:
110:            public static short _parseShort(CharSequence s) {
111:                return (short) _parseInt(s);
112:            }
113:
114:            public String printShort(short val) {
115:                return _printShort(val);
116:            }
117:
118:            public static String _printShort(short val) {
119:                return String.valueOf(val);
120:            }
121:
122:            public BigDecimal parseDecimal(String content) {
123:                return _parseDecimal(content);
124:            }
125:
126:            public static BigDecimal _parseDecimal(CharSequence content) {
127:                content = WhiteSpaceProcessor.trim(content);
128:
129:                return new BigDecimal(content.toString());
130:
131:                // from purely XML Schema perspective,
132:                // this implementation has a problem, since
133:                // in xs:decimal "1.0" and "1" is equal whereas the above
134:                // code will return different values for those two forms.
135:                //
136:                // the code was originally using com.sun.msv.datatype.xsd.NumberType.load,
137:                // but a profiling showed that the process of normalizing "1.0" into "1"
138:                // could take non-trivial time.
139:                //
140:                // also, from the user's point of view, one might be surprised if
141:                // 1 (not 1.0) is returned from "1.000"
142:            }
143:
144:            public float parseFloat(String lexicalXSDFloat) {
145:                return _parseFloat(lexicalXSDFloat);
146:            }
147:
148:            public static float _parseFloat(CharSequence _val) {
149:                String s = WhiteSpaceProcessor.trim(_val).toString();
150:                /* Incompatibilities of XML Schema's float "xfloat" and Java's float "jfloat"
151:
152:                 * jfloat.valueOf ignores leading and trailing whitespaces,
153:                      whereas this is not allowed in xfloat.
154:                 * jfloat.valueOf allows "float type suffix" (f, F) to be
155:                      appended after float literal (e.g., 1.52e-2f), whereare
156:                      this is not the case of xfloat.
157:
158:                    gray zone
159:                    ---------
160:                 * jfloat allows ".523". And there is no clear statement that mentions
161:                      this case in xfloat. Although probably this is allowed.
162:                 *
163:                 */
164:
165:                if (s.equals("NaN"))
166:                    return Float.NaN;
167:                if (s.equals("INF"))
168:                    return Float.POSITIVE_INFINITY;
169:                if (s.equals("-INF"))
170:                    return Float.NEGATIVE_INFINITY;
171:
172:                if (s.length() == 0 || !isDigitOrPeriodOrSign(s.charAt(0))
173:                        || !isDigitOrPeriodOrSign(s.charAt(s.length() - 1)))
174:                    throw new NumberFormatException();
175:
176:                // these screening process is necessary due to the wobble of Float.valueOf method
177:                return Float.parseFloat(s);
178:            }
179:
180:            public String printFloat(float v) {
181:                return _printFloat(v);
182:            }
183:
184:            public static String _printFloat(float v) {
185:                if (v == Float.NaN)
186:                    return "NaN";
187:                if (v == Float.POSITIVE_INFINITY)
188:                    return "INF";
189:                if (v == Float.NEGATIVE_INFINITY)
190:                    return "-INF";
191:                return String.valueOf(v);
192:            }
193:
194:            public double parseDouble(String lexicalXSDDouble) {
195:                return _parseDouble(lexicalXSDDouble);
196:            }
197:
198:            public static double _parseDouble(CharSequence _val) {
199:                String val = WhiteSpaceProcessor.trim(_val).toString();
200:
201:                if (val.equals("NaN"))
202:                    return Double.NaN;
203:                if (val.equals("INF"))
204:                    return Double.POSITIVE_INFINITY;
205:                if (val.equals("-INF"))
206:                    return Double.NEGATIVE_INFINITY;
207:
208:                if (val.length() == 0 || !isDigitOrPeriodOrSign(val.charAt(0))
209:                        || !isDigitOrPeriodOrSign(val.charAt(val.length() - 1)))
210:                    throw new NumberFormatException(val);
211:
212:                // these screening process is necessary due to the wobble of Float.valueOf method
213:                return Double.parseDouble(val);
214:            }
215:
216:            public boolean parseBoolean(String lexicalXSDBoolean) {
217:                return _parseBoolean(lexicalXSDBoolean);
218:            }
219:
220:            public static boolean _parseBoolean(CharSequence literal) {
221:                int i = 0;
222:                int len = literal.length();
223:                char ch;
224:                do {
225:                    ch = literal.charAt(i++);
226:                } while (WhiteSpaceProcessor.isWhiteSpace(ch) && i < len);
227:
228:                // if we are strict about errors, check i==len. and report an error
229:
230:                if (ch == 't' || ch == '1')
231:                    return true;
232:                if (ch == 'f' || ch == '0')
233:                    return false;
234:                return false;
235:            }
236:
237:            public String printBoolean(boolean val) {
238:                return val ? "true" : "false";
239:            }
240:
241:            public static String _printBoolean(boolean val) {
242:                return val ? "true" : "false";
243:            }
244:
245:            public byte parseByte(String lexicalXSDByte) {
246:                return _parseByte(lexicalXSDByte);
247:            }
248:
249:            public static byte _parseByte(CharSequence literal) {
250:                return (byte) _parseInt(literal);
251:            }
252:
253:            public String printByte(byte val) {
254:                return _printByte(val);
255:            }
256:
257:            public static String _printByte(byte val) {
258:                return String.valueOf(val);
259:            }
260:
261:            public QName parseQName(String lexicalXSDQName, NamespaceContext nsc) {
262:                return _parseQName(lexicalXSDQName, nsc);
263:            }
264:
265:            /**
266:             * @return null if fails to convert.
267:             */
268:            public static QName _parseQName(CharSequence text,
269:                    NamespaceContext nsc) {
270:                int length = text.length();
271:
272:                // trim whitespace
273:                int start = 0;
274:                while (start < length
275:                        && WhiteSpaceProcessor.isWhiteSpace(text.charAt(start)))
276:                    start++;
277:
278:                int end = length;
279:                while (end > start
280:                        && WhiteSpaceProcessor.isWhiteSpace(text
281:                                .charAt(end - 1)))
282:                    end--;
283:
284:                if (end == start)
285:                    throw new IllegalArgumentException("input is empty");
286:
287:                String uri;
288:                String localPart;
289:                String prefix;
290:
291:                // search ':'
292:                int idx = start + 1; // no point in searching the first char. that's not valid.
293:                while (idx < end && text.charAt(idx) != ':')
294:                    idx++;
295:
296:                if (idx == end) {
297:                    uri = nsc.getNamespaceURI("");
298:                    localPart = text.subSequence(start, end).toString();
299:                    prefix = "";
300:                } else {
301:                    // Prefix exists, check everything
302:                    prefix = text.subSequence(start, idx).toString();
303:                    localPart = text.subSequence(idx + 1, end).toString();
304:                    uri = nsc.getNamespaceURI(prefix);
305:                    // uri can never be null according to javadoc,
306:                    // but some users reported that there are implementations that return null.
307:                    if (uri == null || uri.length() == 0) // crap. the NamespaceContext interface is broken.
308:                        // error: unbound prefix
309:                        throw new IllegalArgumentException("prefix " + prefix
310:                                + " is not bound to a namespace");
311:                }
312:
313:                return new QName(uri, localPart, prefix);
314:            }
315:
316:            public Calendar parseDateTime(String lexicalXSDDateTime) {
317:                return _parseDateTime(lexicalXSDDateTime);
318:            }
319:
320:            public static GregorianCalendar _parseDateTime(CharSequence s) {
321:                String val = WhiteSpaceProcessor.trim(s).toString();
322:                return datatypeFactory.newXMLGregorianCalendar(val)
323:                        .toGregorianCalendar();
324:            }
325:
326:            public String printDateTime(Calendar val) {
327:                return _printDateTime(val);
328:            }
329:
330:            public static String _printDateTime(Calendar val) {
331:                return CalendarFormatter.doFormat("%Y-%M-%DT%h:%m:%s%z", val);
332:            }
333:
334:            public byte[] parseBase64Binary(String lexicalXSDBase64Binary) {
335:                return _parseBase64Binary(lexicalXSDBase64Binary);
336:            }
337:
338:            public byte[] parseHexBinary(String s) {
339:                final int len = s.length();
340:
341:                // "111" is not a valid hex encoding.
342:                if (len % 2 != 0)
343:                    throw new IllegalArgumentException(
344:                            "hexBinary needs to be even-length: " + s);
345:
346:                byte[] out = new byte[len / 2];
347:
348:                for (int i = 0; i < len; i += 2) {
349:                    int h = hexToBin(s.charAt(i));
350:                    int l = hexToBin(s.charAt(i + 1));
351:                    if (h == -1 || l == -1)
352:                        throw new IllegalArgumentException(
353:                                "contains illegal character for hexBinary: "
354:                                        + s);
355:
356:                    out[i / 2] = (byte) (h * 16 + l);
357:                }
358:
359:                return out;
360:            }
361:
362:            private static int hexToBin(char ch) {
363:                if ('0' <= ch && ch <= '9')
364:                    return ch - '0';
365:                if ('A' <= ch && ch <= 'F')
366:                    return ch - 'A' + 10;
367:                if ('a' <= ch && ch <= 'f')
368:                    return ch - 'a' + 10;
369:                return -1;
370:            }
371:
372:            private static final char[] hexCode = "0123456789ABCDEF"
373:                    .toCharArray();
374:
375:            public String printHexBinary(byte[] data) {
376:                StringBuilder r = new StringBuilder(data.length * 2);
377:                for (byte b : data) {
378:                    r.append(hexCode[(b >> 4) & 0xF]);
379:                    r.append(hexCode[(b & 0xF)]);
380:                }
381:                return r.toString();
382:            }
383:
384:            public long parseUnsignedInt(String lexicalXSDUnsignedInt) {
385:                return _parseLong(lexicalXSDUnsignedInt);
386:            }
387:
388:            public String printUnsignedInt(long val) {
389:                return _printLong(val);
390:            }
391:
392:            public int parseUnsignedShort(String lexicalXSDUnsignedShort) {
393:                return _parseInt(lexicalXSDUnsignedShort);
394:            }
395:
396:            public Calendar parseTime(String lexicalXSDTime) {
397:                return datatypeFactory.newXMLGregorianCalendar(lexicalXSDTime)
398:                        .toGregorianCalendar();
399:            }
400:
401:            public String printTime(Calendar val) {
402:                return CalendarFormatter.doFormat("%h:%m:%s%z", val);
403:            }
404:
405:            public Calendar parseDate(String lexicalXSDDate) {
406:                return datatypeFactory.newXMLGregorianCalendar(lexicalXSDDate)
407:                        .toGregorianCalendar();
408:            }
409:
410:            public String printDate(Calendar val) {
411:
412:                return CalendarFormatter
413:                        .doFormat((new StringBuilder("%Y-%M-%D").append("%z"))
414:                                .toString(), val);
415:            }
416:
417:            public String parseAnySimpleType(String lexicalXSDAnySimpleType) {
418:                return lexicalXSDAnySimpleType;
419:                //        return (String)SimpleURType.theInstance._createValue( lexicalXSDAnySimpleType, null );
420:            }
421:
422:            public String printString(String val) {
423:                //        return StringType.theInstance.convertToLexicalValue( val, null );
424:                return val;
425:            }
426:
427:            public String printInt(int val) {
428:                return _printInt(val);
429:            }
430:
431:            public static String _printInt(int val) {
432:                return String.valueOf(val);
433:            }
434:
435:            public String printLong(long val) {
436:                return _printLong(val);
437:            }
438:
439:            public static String _printLong(long val) {
440:                return String.valueOf(val);
441:            }
442:
443:            public String printDecimal(BigDecimal val) {
444:                return _printDecimal(val);
445:            }
446:
447:            public static String _printDecimal(BigDecimal val) {
448:                return val.toPlainString();
449:            }
450:
451:            public String printDouble(double v) {
452:                return _printDouble(v);
453:            }
454:
455:            public static String _printDouble(double v) {
456:                if (v == Double.NaN)
457:                    return "NaN";
458:                if (v == Double.POSITIVE_INFINITY)
459:                    return "INF";
460:                if (v == Double.NEGATIVE_INFINITY)
461:                    return "-INF";
462:                return String.valueOf(v);
463:            }
464:
465:            public String printQName(QName val, NamespaceContext nsc) {
466:                return _printQName(val, nsc);
467:            }
468:
469:            public static String _printQName(QName val, NamespaceContext nsc) {
470:                // Double-check
471:                String qname;
472:                String prefix = nsc.getPrefix(val.getNamespaceURI());
473:                String localPart = val.getLocalPart();
474:
475:                if (prefix == null || prefix.length() == 0) { // be defensive
476:                    qname = localPart;
477:                } else {
478:                    qname = prefix + ':' + localPart;
479:                }
480:
481:                return qname;
482:            }
483:
484:            public String printBase64Binary(byte[] val) {
485:                return _printBase64Binary(val);
486:            }
487:
488:            public String printUnsignedShort(int val) {
489:                return String.valueOf(val);
490:            }
491:
492:            public String printAnySimpleType(String val) {
493:                return val;
494:            }
495:
496:            /**
497:             * Just return the string passed as a parameter but
498:             * installs an instance of this class as the DatatypeConverter
499:             * implementation. Used from static fixed value initializers.
500:             */
501:            public static String installHook(String s) {
502:                DatatypeConverter.setDatatypeConverter(theInstance);
503:                return s;
504:            }
505:
506:            // base64 decoder
507:            //====================================
508:
509:            private static final byte[] decodeMap = initDecodeMap();
510:            private static final byte PADDING = 127;
511:
512:            private static byte[] initDecodeMap() {
513:                byte[] map = new byte[128];
514:                int i;
515:                for (i = 0; i < 128; i++)
516:                    map[i] = -1;
517:
518:                for (i = 'A'; i <= 'Z'; i++)
519:                    map[i] = (byte) (i - 'A');
520:                for (i = 'a'; i <= 'z'; i++)
521:                    map[i] = (byte) (i - 'a' + 26);
522:                for (i = '0'; i <= '9'; i++)
523:                    map[i] = (byte) (i - '0' + 52);
524:                map['+'] = 62;
525:                map['/'] = 63;
526:                map['='] = PADDING;
527:
528:                return map;
529:            }
530:
531:            /**
532:             * computes the length of binary data speculatively.
533:             *
534:             * <p>
535:             * Our requirement is to create byte[] of the exact length to store the binary data.
536:             * If we do this in a straight-forward way, it takes two passes over the data.
537:             * Experiments show that this is a non-trivial overhead (35% or so is spent on
538:             * the first pass in calculating the length.)
539:             *
540:             * <p>
541:             * So the approach here is that we compute the length speculatively, without looking
542:             * at the whole contents. The obtained speculative value is never less than the
543:             * actual length of the binary data, but it may be bigger. So if the speculation
544:             * goes wrong, we'll pay the cost of reallocation and buffer copying.
545:             *
546:             * <p>
547:             * If the base64 text is tightly packed with no indentation nor illegal char
548:             * (like what most web services produce), then the speculation of this method
549:             * will be correct, so we get the performance benefit.
550:             */
551:            private static int guessLength(String text) {
552:                final int len = text.length();
553:
554:                // compute the tail '=' chars
555:                int j = len - 1;
556:                for (; j >= 0; j--) {
557:                    byte code = decodeMap[text.charAt(j)];
558:                    if (code == PADDING)
559:                        continue;
560:                    if (code == -1)
561:                        // most likely this base64 text is indented. go with the upper bound
562:                        return text.length() / 4 * 3;
563:                    break;
564:                }
565:
566:                j++; // text.charAt(j) is now at some base64 char, so +1 to make it the size
567:                int padSize = len - j;
568:                if (padSize > 2) // something is wrong with base64. be safe and go with the upper bound
569:                    return text.length() / 4 * 3;
570:
571:                // so far this base64 looks like it's unindented tightly packed base64.
572:                // take a chance and create an array with the expected size
573:                return text.length() / 4 * 3 - padSize;
574:            }
575:
576:            /**
577:             * @param text
578:             *      base64Binary data is likely to be long, and decoding requires
579:             *      each character to be accessed twice (once for counting length, another
580:             *      for decoding.)
581:             *
582:             *      A benchmark showed that taking {@link String} is faster, presumably
583:             *      because JIT can inline a lot of string access (with data of 1K chars, it was twice as fast)
584:             */
585:            public static byte[] _parseBase64Binary(String text) {
586:                final int buflen = guessLength(text);
587:                final byte[] out = new byte[buflen];
588:                int o = 0;
589:
590:                final int len = text.length();
591:                int i;
592:
593:                final byte[] quadruplet = new byte[4];
594:                int q = 0;
595:
596:                // convert each quadruplet to three bytes.
597:                for (i = 0; i < len; i++) {
598:                    char ch = text.charAt(i);
599:                    byte v = decodeMap[ch];
600:
601:                    if (v != -1)
602:                        quadruplet[q++] = v;
603:
604:                    if (q == 4) {
605:                        // quadruplet is now filled.
606:                        out[o++] = (byte) ((quadruplet[0] << 2) | (quadruplet[1] >> 4));
607:                        if (quadruplet[2] != PADDING)
608:                            out[o++] = (byte) ((quadruplet[1] << 4) | (quadruplet[2] >> 2));
609:                        if (quadruplet[3] != PADDING)
610:                            out[o++] = (byte) ((quadruplet[2] << 6) | (quadruplet[3]));
611:                        q = 0;
612:                    }
613:                }
614:
615:                if (buflen == o) // speculation worked out to be OK
616:                    return out;
617:
618:                // we overestimated, so need to create a new buffer
619:                byte[] nb = new byte[o];
620:                System.arraycopy(out, 0, nb, 0, o);
621:                return nb;
622:            }
623:
624:            private static final char[] encodeMap = initEncodeMap();
625:
626:            private static char[] initEncodeMap() {
627:                char[] map = new char[64];
628:                int i;
629:                for (i = 0; i < 26; i++)
630:                    map[i] = (char) ('A' + i);
631:                for (i = 26; i < 52; i++)
632:                    map[i] = (char) ('a' + (i - 26));
633:                for (i = 52; i < 62; i++)
634:                    map[i] = (char) ('0' + (i - 52));
635:                map[62] = '+';
636:                map[63] = '/';
637:
638:                return map;
639:            }
640:
641:            public static char encode(int i) {
642:                return encodeMap[i & 0x3F];
643:            }
644:
645:            public static byte encodeByte(int i) {
646:                return (byte) encodeMap[i & 0x3F];
647:            }
648:
649:            public static String _printBase64Binary(byte[] input) {
650:                return _printBase64Binary(input, 0, input.length);
651:            }
652:
653:            public static String _printBase64Binary(byte[] input, int offset,
654:                    int len) {
655:                char[] buf = new char[((len + 2) / 3) * 4];
656:                int ptr = _printBase64Binary(input, offset, len, buf, 0);
657:                assert ptr == buf.length;
658:                return new String(buf);
659:            }
660:
661:            /**
662:             * Encodes a byte array into a char array by doing base64 encoding.
663:             *
664:             * The caller must supply a big enough buffer.
665:             *
666:             * @return
667:             *      the value of {@code ptr+((len+2)/3)*4}, which is the new offset
668:             *      in the output buffer where the further bytes should be placed.
669:             */
670:            public static int _printBase64Binary(byte[] input, int offset,
671:                    int len, char[] buf, int ptr) {
672:                for (int i = offset; i < len; i += 3) {
673:                    switch (len - i) {
674:                    case 1:
675:                        buf[ptr++] = encode(input[i] >> 2);
676:                        buf[ptr++] = encode(((input[i]) & 0x3) << 4);
677:                        buf[ptr++] = '=';
678:                        buf[ptr++] = '=';
679:                        break;
680:                    case 2:
681:                        buf[ptr++] = encode(input[i] >> 2);
682:                        buf[ptr++] = encode(((input[i] & 0x3) << 4)
683:                                | ((input[i + 1] >> 4) & 0xF));
684:                        buf[ptr++] = encode((input[i + 1] & 0xF) << 2);
685:                        buf[ptr++] = '=';
686:                        break;
687:                    default:
688:                        buf[ptr++] = encode(input[i] >> 2);
689:                        buf[ptr++] = encode(((input[i] & 0x3) << 4)
690:                                | ((input[i + 1] >> 4) & 0xF));
691:                        buf[ptr++] = encode(((input[i + 1] & 0xF) << 2)
692:                                | ((input[i + 2] >> 6) & 0x3));
693:                        buf[ptr++] = encode(input[i + 2] & 0x3F);
694:                        break;
695:                    }
696:                }
697:                return ptr;
698:            }
699:
700:            /**
701:             * Encodes a byte array into another byte array by first doing base64 encoding
702:             * then encoding the result in ASCII.
703:             *
704:             * The caller must supply a big enough buffer.
705:             *
706:             * @return
707:             *      the value of {@code ptr+((len+2)/3)*4}, which is the new offset
708:             *      in the output buffer where the further bytes should be placed.
709:             */
710:            public static int _printBase64Binary(byte[] input, int offset,
711:                    int len, byte[] out, int ptr) {
712:                byte[] buf = out;
713:                int max = len + offset;
714:                for (int i = offset; i < max; i += 3) {
715:                    switch (max - i) {
716:                    case 1:
717:                        buf[ptr++] = encodeByte(input[i] >> 2);
718:                        buf[ptr++] = encodeByte(((input[i]) & 0x3) << 4);
719:                        buf[ptr++] = '=';
720:                        buf[ptr++] = '=';
721:                        break;
722:                    case 2:
723:                        buf[ptr++] = encodeByte(input[i] >> 2);
724:                        buf[ptr++] = encodeByte(((input[i] & 0x3) << 4)
725:                                | ((input[i + 1] >> 4) & 0xF));
726:                        buf[ptr++] = encodeByte((input[i + 1] & 0xF) << 2);
727:                        buf[ptr++] = '=';
728:                        break;
729:                    default:
730:                        buf[ptr++] = encodeByte(input[i] >> 2);
731:                        buf[ptr++] = encodeByte(((input[i] & 0x3) << 4)
732:                                | ((input[i + 1] >> 4) & 0xF));
733:                        buf[ptr++] = encodeByte(((input[i + 1] & 0xF) << 2)
734:                                | ((input[i + 2] >> 6) & 0x3));
735:                        buf[ptr++] = encodeByte(input[i + 2] & 0x3F);
736:                        break;
737:                    }
738:                }
739:
740:                return ptr;
741:            }
742:
743:            private static CharSequence removeOptionalPlus(CharSequence s) {
744:                int len = s.length();
745:
746:                if (len <= 1 || s.charAt(0) != '+')
747:                    return s;
748:
749:                s = s.subSequence(1, len);
750:                char ch = s.charAt(0);
751:                if ('0' <= ch && ch <= '9')
752:                    return s;
753:                if ('.' == ch)
754:                    return s;
755:
756:                throw new NumberFormatException();
757:            }
758:
759:            private static boolean isDigitOrPeriodOrSign(char ch) {
760:                if ('0' <= ch && ch <= '9')
761:                    return true;
762:                if (ch == '+' || ch == '-' || ch == '.')
763:                    return true;
764:                return false;
765:            }
766:
767:            private static final DatatypeFactory datatypeFactory;
768:
769:            static {
770:                try {
771:                    datatypeFactory = DatatypeFactory.newInstance();
772:                } catch (DatatypeConfigurationException e) {
773:                    throw new Error(e);
774:                }
775:            }
776:
777:            private static final class CalendarFormatter {
778:                public static String doFormat(String format, Calendar cal)
779:                        throws IllegalArgumentException {
780:                    int fidx = 0;
781:                    int flen = format.length();
782:                    StringBuilder buf = new StringBuilder();
783:
784:                    while (fidx < flen) {
785:                        char fch = format.charAt(fidx++);
786:
787:                        if (fch != '%') { // not a meta character
788:                            buf.append(fch);
789:                            continue;
790:                        }
791:
792:                        // seen meta character. we don't do error check against the format
793:                        switch (format.charAt(fidx++)) {
794:                        case 'Y': // year
795:                            formatYear(cal, buf);
796:                            break;
797:
798:                        case 'M': // month
799:                            formatMonth(cal, buf);
800:                            break;
801:
802:                        case 'D': // days
803:                            formatDays(cal, buf);
804:                            break;
805:
806:                        case 'h': // hours
807:                            formatHours(cal, buf);
808:                            break;
809:
810:                        case 'm': // minutes
811:                            formatMinutes(cal, buf);
812:                            break;
813:
814:                        case 's': // parse seconds.
815:                            formatSeconds(cal, buf);
816:                            break;
817:
818:                        case 'z': // time zone
819:                            formatTimeZone(cal, buf);
820:                            break;
821:
822:                        default:
823:                            // illegal meta character. impossible.
824:                            throw new InternalError();
825:                        }
826:                    }
827:
828:                    return buf.toString();
829:                }
830:
831:                private static void formatYear(Calendar cal, StringBuilder buf) {
832:                    int year = cal.get(Calendar.YEAR);
833:
834:                    String s;
835:                    if (year <= 0) // negative value
836:                        s = Integer.toString(1 - year);
837:                    else
838:                        // positive value
839:                        s = Integer.toString(year);
840:
841:                    while (s.length() < 4)
842:                        s = '0' + s;
843:                    if (year <= 0)
844:                        s = '-' + s;
845:
846:                    buf.append(s);
847:                }
848:
849:                private static void formatMonth(Calendar cal, StringBuilder buf) {
850:                    formatTwoDigits(cal.get(Calendar.MONTH) + 1, buf);
851:                }
852:
853:                private static void formatDays(Calendar cal, StringBuilder buf) {
854:                    formatTwoDigits(cal.get(Calendar.DAY_OF_MONTH), buf);
855:                }
856:
857:                private static void formatHours(Calendar cal, StringBuilder buf) {
858:                    formatTwoDigits(cal.get(Calendar.HOUR_OF_DAY), buf);
859:                }
860:
861:                private static void formatMinutes(Calendar cal,
862:                        StringBuilder buf) {
863:                    formatTwoDigits(cal.get(Calendar.MINUTE), buf);
864:                }
865:
866:                private static void formatSeconds(Calendar cal,
867:                        StringBuilder buf) {
868:                    formatTwoDigits(cal.get(Calendar.SECOND), buf);
869:                    if (cal.isSet(Calendar.MILLISECOND)) { // milliseconds
870:                        int n = cal.get(Calendar.MILLISECOND);
871:                        if (n != 0) {
872:                            String ms = Integer.toString(n);
873:                            while (ms.length() < 3)
874:                                ms = '0' + ms; // left 0 paddings.
875:
876:                            buf.append('.');
877:                            buf.append(ms);
878:                        }
879:                    }
880:                }
881:
882:                /** formats time zone specifier. */
883:                private static void formatTimeZone(Calendar cal,
884:                        StringBuilder buf) {
885:                    TimeZone tz = cal.getTimeZone();
886:
887:                    if (tz == null)
888:                        return;
889:
890:                    // otherwise print out normally.
891:                    int offset;
892:                    if (tz.inDaylightTime(cal.getTime())) {
893:                        offset = tz.getRawOffset()
894:                                + (tz.useDaylightTime() ? 3600000 : 0);
895:                    } else {
896:                        offset = tz.getRawOffset();
897:                    }
898:
899:                    if (offset == 0) {
900:                        buf.append('Z');
901:                        return;
902:                    }
903:
904:                    if (offset >= 0)
905:                        buf.append('+');
906:                    else {
907:                        buf.append('-');
908:                        offset *= -1;
909:                    }
910:
911:                    offset /= 60 * 1000; // offset is in milli-seconds
912:
913:                    formatTwoDigits(offset / 60, buf);
914:                    buf.append(':');
915:                    formatTwoDigits(offset % 60, buf);
916:                }
917:
918:                /** formats Integer into two-character-wide string. */
919:                private static void formatTwoDigits(int n, StringBuilder buf) {
920:                    // n is always non-negative.
921:                    if (n < 10)
922:                        buf.append('0');
923:                    buf.append(n);
924:                }
925:            }
926:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.