src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeBuiltinLeafInfoImpl.java

Fri, 14 Feb 2014 10:53:55 +0100

author
mkos
date
Fri, 14 Feb 2014 10:53:55 +0100
changeset 514
29a761eaff0d
parent 450
b0c2840e2513
child 637
9c07ef4934dd
child 721
06807f9a6835
permissions
-rw-r--r--

8025030: Enhance stream handling
Summary: Avoiding caching data initialized via TCCL in static context; fix also reviewed by Iaroslav Savytskyi, Alexander Fomin
Reviewed-by: ahgross, mgrebac, skoivu

ohair@286 1 /*
mkos@514 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
ohair@286 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ohair@286 4 *
ohair@286 5 * This code is free software; you can redistribute it and/or modify it
ohair@286 6 * under the terms of the GNU General Public License version 2 only, as
ohair@286 7 * published by the Free Software Foundation. Oracle designates this
ohair@286 8 * particular file as subject to the "Classpath" exception as provided
ohair@286 9 * by Oracle in the LICENSE file that accompanied this code.
ohair@286 10 *
ohair@286 11 * This code is distributed in the hope that it will be useful, but WITHOUT
ohair@286 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ohair@286 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ohair@286 14 * version 2 for more details (a copy is included in the LICENSE file that
ohair@286 15 * accompanied this code).
ohair@286 16 *
ohair@286 17 * You should have received a copy of the GNU General Public License version
ohair@286 18 * 2 along with this work; if not, write to the Free Software Foundation,
ohair@286 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ohair@286 20 *
ohair@286 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@286 22 * or visit www.oracle.com if you need additional information or have any
ohair@286 23 * questions.
ohair@286 24 */
ohair@286 25
ohair@286 26 package com.sun.xml.internal.bind.v2.model.impl;
ohair@286 27
alanb@368 28 import java.awt.Component;
alanb@368 29 import java.awt.Graphics;
alanb@368 30 import java.awt.Image;
alanb@368 31 import java.awt.MediaTracker;
ohair@286 32 import java.awt.image.BufferedImage;
ohair@286 33 import java.io.ByteArrayInputStream;
ohair@286 34 import java.io.File;
ohair@286 35 import java.io.IOException;
ohair@286 36 import java.io.InputStream;
ohair@286 37 import java.io.OutputStreamWriter;
ohair@286 38 import java.io.UnsupportedEncodingException;
ohair@286 39 import java.lang.reflect.Type;
ohair@286 40 import java.math.BigDecimal;
ohair@286 41 import java.math.BigInteger;
ohair@286 42 import java.net.MalformedURLException;
ohair@286 43 import java.net.URI;
ohair@286 44 import java.net.URISyntaxException;
ohair@286 45 import java.net.URL;
ohair@286 46 import java.util.ArrayList;
ohair@286 47 import java.util.Calendar;
ohair@286 48 import java.util.Collections;
ohair@286 49 import java.util.Date;
ohair@286 50 import java.util.GregorianCalendar;
ohair@286 51 import java.util.HashMap;
ohair@286 52 import java.util.Iterator;
ohair@286 53 import java.util.List;
ohair@286 54 import java.util.Map;
ohair@286 55 import java.util.UUID;
ohair@286 56
ohair@286 57 import javax.activation.DataHandler;
ohair@286 58 import javax.activation.DataSource;
ohair@286 59 import javax.activation.MimeType;
ohair@286 60 import javax.activation.MimeTypeParseException;
ohair@286 61 import javax.imageio.ImageIO;
ohair@286 62 import javax.imageio.ImageWriter;
ohair@286 63 import javax.imageio.stream.ImageOutputStream;
ohair@286 64 import javax.xml.bind.ValidationEvent;
ohair@286 65 import javax.xml.bind.helpers.ValidationEventImpl;
ohair@286 66 import javax.xml.datatype.DatatypeConstants;
ohair@286 67 import javax.xml.datatype.Duration;
ohair@286 68 import javax.xml.datatype.XMLGregorianCalendar;
ohair@286 69 import javax.xml.namespace.QName;
ohair@286 70 import javax.xml.stream.XMLStreamException;
ohair@286 71 import javax.xml.transform.OutputKeys;
ohair@286 72 import javax.xml.transform.Source;
ohair@286 73 import javax.xml.transform.Transformer;
ohair@286 74 import javax.xml.transform.TransformerException;
ohair@286 75 import javax.xml.transform.stream.StreamResult;
ohair@286 76
ohair@286 77 import com.sun.istack.internal.ByteArrayDataSource;
ohair@286 78 import com.sun.xml.internal.bind.DatatypeConverterImpl;
ohair@286 79 import com.sun.xml.internal.bind.WhiteSpaceProcessor;
ohair@286 80 import com.sun.xml.internal.bind.api.AccessorException;
ohair@286 81 import com.sun.xml.internal.bind.v2.TODO;
ohair@286 82 import com.sun.xml.internal.bind.v2.WellKnownNamespace;
ohair@286 83 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeBuiltinLeafInfo;
ohair@286 84 import com.sun.xml.internal.bind.v2.runtime.Name;
ohair@286 85 import com.sun.xml.internal.bind.v2.runtime.Transducer;
ohair@286 86 import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
ohair@286 87 import com.sun.xml.internal.bind.v2.runtime.output.Pcdata;
ohair@286 88 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data;
ohair@286 89 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
ohair@286 90 import com.sun.xml.internal.bind.v2.util.ByteArrayOutputStreamEx;
ohair@286 91 import com.sun.xml.internal.bind.v2.util.DataSourceSource;
ohair@286 92
ohair@286 93 import org.xml.sax.SAXException;
ohair@286 94
ohair@286 95 /**
ohair@286 96 * {@link BuiltinLeafInfoImpl} with a support for runtime.
ohair@286 97 *
ohair@286 98 * <p>
ohair@286 99 * In particular this class defines {@link Transducer}s for the built-in types.
ohair@286 100 *
ohair@286 101 * @author Kohsuke Kawaguchi
ohair@286 102 */
ohair@286 103 public abstract class RuntimeBuiltinLeafInfoImpl<T> extends BuiltinLeafInfoImpl<Type,Class>
ohair@286 104 implements RuntimeBuiltinLeafInfo, Transducer<T> {
ohair@286 105
ohair@286 106 private RuntimeBuiltinLeafInfoImpl(Class type, QName... typeNames) {
ohair@286 107 super(type, typeNames);
ohair@286 108 LEAVES.put(type,this);
ohair@286 109 }
ohair@286 110
ohair@286 111 public final Class getClazz() {
ohair@286 112 return (Class)getType();
ohair@286 113 }
ohair@286 114
ohair@286 115
ohair@286 116 public final Transducer getTransducer() {
ohair@286 117 return this;
ohair@286 118 }
ohair@286 119
ohair@286 120 public boolean useNamespace() {
ohair@286 121 return false;
ohair@286 122 }
ohair@286 123
ohair@286 124 public final boolean isDefault() {
ohair@286 125 return true;
ohair@286 126 }
ohair@286 127
ohair@286 128 public void declareNamespace(T o, XMLSerializer w) throws AccessorException {
ohair@286 129 }
ohair@286 130
ohair@286 131 public QName getTypeName(T instance) {
ohair@286 132 return null;
ohair@286 133 }
ohair@286 134
ohair@286 135 /**
ohair@286 136 * Those built-in types that print to {@link String}.
ohair@286 137 */
ohair@286 138 private static abstract class StringImpl<T> extends RuntimeBuiltinLeafInfoImpl<T> {
ohair@286 139 protected StringImpl(Class type, QName... typeNames) {
ohair@286 140 super(type,typeNames);
ohair@286 141 }
ohair@286 142
ohair@286 143 public abstract String print(T o) throws AccessorException;
ohair@286 144
ohair@286 145 public void writeText(XMLSerializer w, T o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
ohair@286 146 w.text(print(o),fieldName);
ohair@286 147 }
ohair@286 148
ohair@286 149 public void writeLeafElement(XMLSerializer w, Name tagName, T o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
ohair@286 150 w.leafElement(tagName,print(o),fieldName);
ohair@286 151 }
ohair@286 152 }
ohair@286 153
ohair@286 154 /**
ohair@286 155 * Those built-in types that print to {@link Pcdata}.
ohair@286 156 */
ohair@286 157 private static abstract class PcdataImpl<T> extends RuntimeBuiltinLeafInfoImpl<T> {
ohair@286 158 protected PcdataImpl(Class type, QName... typeNames) {
ohair@286 159 super(type,typeNames);
ohair@286 160 }
ohair@286 161
ohair@286 162 public abstract Pcdata print(T o) throws AccessorException;
ohair@286 163
ohair@286 164 public final void writeText(XMLSerializer w, T o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
ohair@286 165 w.text(print(o),fieldName);
ohair@286 166 }
ohair@286 167
ohair@286 168 public final void writeLeafElement(XMLSerializer w, Name tagName, T o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
ohair@286 169 w.leafElement(tagName,print(o),fieldName);
ohair@286 170 }
ohair@286 171
ohair@286 172 }
ohair@286 173
ohair@286 174 /**
ohair@286 175 * All instances of {@link RuntimeBuiltinLeafInfoImpl}s keyed by their type.
ohair@286 176 */
ohair@286 177 public static final Map<Type,RuntimeBuiltinLeafInfoImpl<?>> LEAVES = new HashMap<Type, RuntimeBuiltinLeafInfoImpl<?>>();
ohair@286 178
ohair@286 179 private static QName createXS(String typeName) {
ohair@286 180 return new QName(WellKnownNamespace.XML_SCHEMA,typeName);
ohair@286 181 }
ohair@286 182
ohair@286 183 public static final RuntimeBuiltinLeafInfoImpl<String> STRING;
ohair@286 184
ohair@286 185 private static final String DATE = "date";
ohair@286 186
ohair@286 187 /**
ohair@286 188 * List of all {@link RuntimeBuiltinLeafInfoImpl}s.
ohair@286 189 *
ohair@286 190 * <p>
ohair@286 191 * This corresponds to the built-in Java classes that are specified to be
ohair@286 192 * handled differently than ordinary classes. See table 8-2 "Mapping of Standard Java classes".
ohair@286 193 */
ohair@286 194 public static final List<RuntimeBuiltinLeafInfoImpl<?>> builtinBeanInfos;
ohair@286 195
ohair@286 196 public static final String MAP_ANYURI_TO_URI = "mapAnyUriToUri";
ohair@286 197
ohair@286 198 static {
ohair@286 199
ohair@286 200 QName[] qnames = (System.getProperty(MAP_ANYURI_TO_URI) == null) ? new QName[] {
ohair@286 201 createXS("string"),
ohair@286 202 createXS("anySimpleType"),
ohair@286 203 createXS("normalizedString"),
ohair@286 204 createXS("anyURI"),
ohair@286 205 createXS("token"),
ohair@286 206 createXS("language"),
ohair@286 207 createXS("Name"),
ohair@286 208 createXS("NCName"),
ohair@286 209 createXS("NMTOKEN"),
ohair@286 210 createXS("ENTITY")}
ohair@286 211 :
ohair@286 212 new QName[] {
ohair@286 213 createXS("string"),
ohair@286 214 createXS("anySimpleType"),
ohair@286 215 createXS("normalizedString"),
ohair@286 216 createXS("token"),
ohair@286 217 createXS("language"),
ohair@286 218 createXS("Name"),
ohair@286 219 createXS("NCName"),
ohair@286 220 createXS("NMTOKEN"),
ohair@286 221 createXS("ENTITY")};
ohair@286 222
ohair@286 223 STRING = new StringImplImpl(String.class, qnames);
ohair@286 224
ohair@286 225 ArrayList<RuntimeBuiltinLeafInfoImpl<?>> secondaryList = new ArrayList<RuntimeBuiltinLeafInfoImpl<?>>();
ohair@286 226 /*
ohair@286 227 There are cases where more than one Java classes map to the same XML type.
ohair@286 228 But when we see the same XML type in an incoming document, we only pick
ohair@286 229 one of those Java classes to unmarshal. This Java class is called 'primary'.
ohair@286 230 The rest are called 'secondary'.
ohair@286 231
ohair@286 232 Currently we lack the proper infrastructure to handle those nicely.
ohair@286 233 For now, we rely on a hack.
ohair@286 234
ohair@286 235 We define secondary mappings first, then primary ones later. GrammarInfo
ohair@286 236 builds a map from type name to BeanInfo. By defining primary ones later,
ohair@286 237 those primary bindings will overwrite the secondary ones.
ohair@286 238 */
ohair@286 239
ohair@286 240 /*
ohair@286 241 secondary bindings
ohair@286 242 */
ohair@286 243 secondaryList.add(
ohair@286 244 new StringImpl<Character>(Character.class, createXS("unsignedShort")) {
ohair@286 245 public Character parse(CharSequence text) {
ohair@286 246 // TODO.checkSpec("default mapping for char is not defined yet");
ohair@286 247 return (char)DatatypeConverterImpl._parseInt(text);
ohair@286 248 }
ohair@286 249 public String print(Character v) {
ohair@286 250 return Integer.toString(v);
ohair@286 251 }
ohair@286 252 });
ohair@286 253 secondaryList.add(
ohair@286 254 new StringImpl<Calendar>(Calendar.class, DatatypeConstants.DATETIME) {
ohair@286 255 public Calendar parse(CharSequence text) {
ohair@286 256 return DatatypeConverterImpl._parseDateTime(text.toString());
ohair@286 257 }
ohair@286 258 public String print(Calendar v) {
ohair@286 259 return DatatypeConverterImpl._printDateTime(v);
ohair@286 260 }
ohair@286 261 });
ohair@286 262 secondaryList.add(
ohair@286 263 new StringImpl<GregorianCalendar>(GregorianCalendar.class, DatatypeConstants.DATETIME) {
ohair@286 264 public GregorianCalendar parse(CharSequence text) {
ohair@286 265 return DatatypeConverterImpl._parseDateTime(text.toString());
ohair@286 266 }
ohair@286 267 public String print(GregorianCalendar v) {
ohair@286 268 return DatatypeConverterImpl._printDateTime(v);
ohair@286 269 }
ohair@286 270 });
ohair@286 271 secondaryList.add(
ohair@286 272 new StringImpl<Date>(Date.class, DatatypeConstants.DATETIME) {
ohair@286 273 public Date parse(CharSequence text) {
ohair@286 274 return DatatypeConverterImpl._parseDateTime(text.toString()).getTime();
ohair@286 275 }
ohair@286 276 public String print(Date v) {
ohair@286 277 XMLSerializer xs = XMLSerializer.getInstance();
ohair@286 278 QName type = xs.getSchemaType();
ohair@286 279 GregorianCalendar cal = new GregorianCalendar(0,0,0);
ohair@286 280 cal.setTime(v);
ohair@286 281 if ((type != null) && (WellKnownNamespace.XML_SCHEMA.equals(type.getNamespaceURI())) &&
ohair@286 282 DATE.equals(type.getLocalPart())) {
ohair@286 283 return DatatypeConverterImpl._printDate(cal);
ohair@286 284 } else {
ohair@286 285 return DatatypeConverterImpl._printDateTime(cal);
ohair@286 286 }
ohair@286 287 }
ohair@286 288 });
ohair@286 289 secondaryList.add(
ohair@286 290 new StringImpl<File>(File.class, createXS("string")) {
ohair@286 291 public File parse(CharSequence text) {
ohair@286 292 return new File(WhiteSpaceProcessor.trim(text).toString());
ohair@286 293 }
ohair@286 294 public String print(File v) {
ohair@286 295 return v.getPath();
ohair@286 296 }
ohair@286 297 });
ohair@286 298 secondaryList.add(
ohair@286 299 new StringImpl<URL>(URL.class, createXS("anyURI")) {
ohair@286 300 public URL parse(CharSequence text) throws SAXException {
ohair@286 301 TODO.checkSpec("JSR222 Issue #42");
ohair@286 302 try {
ohair@286 303 return new URL(WhiteSpaceProcessor.trim(text).toString());
ohair@286 304 } catch (MalformedURLException e) {
ohair@286 305 UnmarshallingContext.getInstance().handleError(e);
ohair@286 306 return null;
ohair@286 307 }
ohair@286 308 }
ohair@286 309 public String print(URL v) {
ohair@286 310 return v.toExternalForm();
ohair@286 311 }
ohair@286 312 });
ohair@286 313 if (System.getProperty(MAP_ANYURI_TO_URI) == null) {
ohair@286 314 secondaryList.add(
ohair@286 315 new StringImpl<URI>(URI.class, createXS("string")) {
ohair@286 316 public URI parse(CharSequence text) throws SAXException {
ohair@286 317 try {
ohair@286 318 return new URI(text.toString());
ohair@286 319 } catch (URISyntaxException e) {
ohair@286 320 UnmarshallingContext.getInstance().handleError(e);
ohair@286 321 return null;
ohair@286 322 }
ohair@286 323 }
ohair@286 324
ohair@286 325 public String print(URI v) {
ohair@286 326 return v.toString();
ohair@286 327 }
ohair@286 328 });
ohair@286 329 }
ohair@286 330 secondaryList.add(
ohair@286 331 new StringImpl<Class>(Class.class, createXS("string")) {
ohair@286 332 public Class parse(CharSequence text) throws SAXException {
ohair@286 333 TODO.checkSpec("JSR222 Issue #42");
ohair@286 334 try {
ohair@286 335 String name = WhiteSpaceProcessor.trim(text).toString();
ohair@286 336 ClassLoader cl = UnmarshallingContext.getInstance().classLoader;
ohair@286 337 if(cl==null)
ohair@286 338 cl = Thread.currentThread().getContextClassLoader();
ohair@286 339
ohair@286 340 if(cl!=null)
ohair@286 341 return cl.loadClass(name);
ohair@286 342 else
ohair@286 343 return Class.forName(name);
ohair@286 344 } catch (ClassNotFoundException e) {
ohair@286 345 UnmarshallingContext.getInstance().handleError(e);
ohair@286 346 return null;
ohair@286 347 }
ohair@286 348 }
ohair@286 349 public String print(Class v) {
ohair@286 350 return v.getName();
ohair@286 351 }
ohair@286 352 });
ohair@286 353
ohair@286 354 /*
ohair@286 355 classes that map to base64Binary / MTOM related classes.
ohair@286 356 a part of the secondary binding.
ohair@286 357 */
ohair@286 358 secondaryList.add(
ohair@286 359 new PcdataImpl<Image>(Image.class, createXS("base64Binary")) {
ohair@286 360 public Image parse(CharSequence text) throws SAXException {
ohair@286 361 try {
ohair@286 362 InputStream is;
ohair@286 363 if(text instanceof Base64Data)
ohair@286 364 is = ((Base64Data)text).getInputStream();
ohair@286 365 else
ohair@286 366 is = new ByteArrayInputStream(decodeBase64(text)); // TODO: buffering is inefficient
ohair@286 367
ohair@286 368 // technically we should check the MIME type here, but
ohair@286 369 // normally images can be content-sniffed.
ohair@286 370 // so the MIME type check will only make us slower and draconian, both of which
ohair@286 371 // JAXB 2.0 isn't interested.
ohair@286 372 try {
ohair@286 373 return ImageIO.read(is);
ohair@286 374 } finally {
ohair@286 375 is.close();
ohair@286 376 }
ohair@286 377 } catch (IOException e) {
ohair@286 378 UnmarshallingContext.getInstance().handleError(e);
ohair@286 379 return null;
ohair@286 380 }
ohair@286 381 }
ohair@286 382
ohair@286 383 private BufferedImage convertToBufferedImage(Image image) throws IOException {
ohair@286 384 if (image instanceof BufferedImage) {
ohair@286 385 return (BufferedImage)image;
ohair@286 386
ohair@286 387 } else {
ohair@286 388 MediaTracker tracker = new MediaTracker(new Component(){}); // not sure if this is the right thing to do.
ohair@286 389 tracker.addImage(image, 0);
ohair@286 390 try {
ohair@286 391 tracker.waitForAll();
ohair@286 392 } catch (InterruptedException e) {
ohair@286 393 throw new IOException(e.getMessage());
ohair@286 394 }
ohair@286 395 BufferedImage bufImage = new BufferedImage(
ohair@286 396 image.getWidth(null),
ohair@286 397 image.getHeight(null),
ohair@286 398 BufferedImage.TYPE_INT_ARGB);
ohair@286 399
ohair@286 400 Graphics g = bufImage.createGraphics();
ohair@286 401 g.drawImage(image, 0, 0, null);
ohair@286 402 return bufImage;
ohair@286 403 }
ohair@286 404 }
ohair@286 405
ohair@286 406 public Base64Data print(Image v) {
ohair@286 407 ByteArrayOutputStreamEx imageData = new ByteArrayOutputStreamEx();
ohair@286 408 XMLSerializer xs = XMLSerializer.getInstance();
ohair@286 409
ohair@286 410 String mimeType = xs.getXMIMEContentType();
ohair@286 411 if(mimeType==null || mimeType.startsWith("image/*"))
ohair@286 412 // because PNG is lossless, it's a good default
ohair@286 413 //
ohair@286 414 // mime type can be a range, in which case we can't just pass that
ohair@286 415 // to ImageIO.getImageWritersByMIMEType, so here I'm just assuming
ohair@286 416 // the default of PNG. Not sure if this is complete.
ohair@286 417 mimeType = "image/png";
ohair@286 418
ohair@286 419 try {
ohair@286 420 Iterator<ImageWriter> itr = ImageIO.getImageWritersByMIMEType(mimeType);
ohair@286 421 if(itr.hasNext()) {
ohair@286 422 ImageWriter w = itr.next();
ohair@286 423 ImageOutputStream os = ImageIO.createImageOutputStream(imageData);
ohair@286 424 w.setOutput(os);
ohair@286 425 w.write(convertToBufferedImage(v));
ohair@286 426 os.close();
ohair@286 427 w.dispose();
ohair@286 428 } else {
ohair@286 429 // no encoder
ohair@286 430 xs.handleEvent(new ValidationEventImpl(
ohair@286 431 ValidationEvent.ERROR,
ohair@286 432 Messages.NO_IMAGE_WRITER.format(mimeType),
ohair@286 433 xs.getCurrentLocation(null) ));
ohair@286 434 // TODO: proper error reporting
ohair@286 435 throw new RuntimeException("no encoder for MIME type "+mimeType);
ohair@286 436 }
ohair@286 437 } catch (IOException e) {
ohair@286 438 xs.handleError(e);
ohair@286 439 // TODO: proper error reporting
ohair@286 440 throw new RuntimeException(e);
ohair@286 441 }
ohair@286 442 Base64Data bd = new Base64Data();
ohair@286 443 imageData.set(bd,mimeType);
ohair@286 444 return bd;
ohair@286 445 }
ohair@286 446 });
ohair@286 447 secondaryList.add(
ohair@286 448 new PcdataImpl<DataHandler>(DataHandler.class, createXS("base64Binary")) {
ohair@286 449 public DataHandler parse(CharSequence text) {
ohair@286 450 if(text instanceof Base64Data)
ohair@286 451 return ((Base64Data)text).getDataHandler();
ohair@286 452 else
ohair@286 453 return new DataHandler(new ByteArrayDataSource(decodeBase64(text),
ohair@286 454 UnmarshallingContext.getInstance().getXMIMEContentType()));
ohair@286 455 }
ohair@286 456
ohair@286 457 public Base64Data print(DataHandler v) {
ohair@286 458 Base64Data bd = new Base64Data();
ohair@286 459 bd.set(v);
ohair@286 460 return bd;
ohair@286 461 }
ohair@286 462 });
ohair@286 463 secondaryList.add(
ohair@286 464 new PcdataImpl<Source>(Source.class, createXS("base64Binary")) {
ohair@286 465 public Source parse(CharSequence text) throws SAXException {
ohair@286 466 try {
ohair@286 467 if(text instanceof Base64Data)
ohair@286 468 return new DataSourceSource( ((Base64Data)text).getDataHandler() );
ohair@286 469 else
ohair@286 470 return new DataSourceSource(new ByteArrayDataSource(decodeBase64(text),
ohair@286 471 UnmarshallingContext.getInstance().getXMIMEContentType()));
ohair@286 472 } catch (MimeTypeParseException e) {
ohair@286 473 UnmarshallingContext.getInstance().handleError(e);
ohair@286 474 return null;
ohair@286 475 }
ohair@286 476 }
ohair@286 477
ohair@286 478 public Base64Data print(Source v) {
ohair@286 479 XMLSerializer xs = XMLSerializer.getInstance();
ohair@286 480 Base64Data bd = new Base64Data();
ohair@286 481
ohair@286 482 String contentType = xs.getXMIMEContentType();
ohair@286 483 MimeType mt = null;
ohair@286 484 if(contentType!=null)
ohair@286 485 try {
ohair@286 486 mt = new MimeType(contentType);
ohair@286 487 } catch (MimeTypeParseException e) {
ohair@286 488 xs.handleError(e);
ohair@286 489 // recover by ignoring the content type specification
ohair@286 490 }
ohair@286 491
ohair@286 492 if( v instanceof DataSourceSource ) {
ohair@286 493 // if so, we already have immutable DataSource so
ohair@286 494 // this can be done efficiently
ohair@286 495 DataSource ds = ((DataSourceSource)v).getDataSource();
ohair@286 496
ohair@286 497 String dsct = ds.getContentType();
ohair@286 498 if(dsct!=null && (contentType==null || contentType.equals(dsct))) {
ohair@286 499 bd.set(new DataHandler(ds));
ohair@286 500 return bd;
ohair@286 501 }
ohair@286 502 }
ohair@286 503
ohair@286 504 // general case. slower.
ohair@286 505
ohair@286 506 // find out the encoding
ohair@286 507 String charset=null;
ohair@286 508 if(mt!=null)
ohair@286 509 charset = mt.getParameter("charset");
ohair@286 510 if(charset==null)
ohair@286 511 charset = "UTF-8";
ohair@286 512
ohair@286 513 try {
ohair@286 514 ByteArrayOutputStreamEx baos = new ByteArrayOutputStreamEx();
ohair@286 515 Transformer tr = xs.getIdentityTransformer();
ohair@286 516 String defaultEncoding = tr.getOutputProperty(OutputKeys.ENCODING);
ohair@286 517 tr.setOutputProperty(OutputKeys.ENCODING, charset);
ohair@286 518 tr.transform(v, new StreamResult(new OutputStreamWriter(baos,charset)));
ohair@286 519 tr.setOutputProperty(OutputKeys.ENCODING, defaultEncoding);
ohair@286 520 baos.set(bd,"application/xml; charset="+charset);
ohair@286 521 return bd;
ohair@286 522 } catch (TransformerException e) {
ohair@286 523 // TODO: marshaller error handling
ohair@286 524 xs.handleError(e);
ohair@286 525 } catch (UnsupportedEncodingException e) {
ohair@286 526 xs.handleError(e);
ohair@286 527 }
ohair@286 528
ohair@286 529 // error recoverly
ohair@286 530 bd.set(new byte[0],"application/xml");
ohair@286 531 return bd;
ohair@286 532 }
ohair@286 533 });
ohair@286 534 secondaryList.add(
ohair@286 535 new StringImpl<XMLGregorianCalendar>(XMLGregorianCalendar.class,
ohair@286 536 createXS("anySimpleType"),
ohair@286 537 DatatypeConstants.DATE,
ohair@286 538 DatatypeConstants.DATETIME,
ohair@286 539 DatatypeConstants.TIME,
ohair@286 540 DatatypeConstants.GMONTH,
ohair@286 541 DatatypeConstants.GDAY,
ohair@286 542 DatatypeConstants.GYEAR,
ohair@286 543 DatatypeConstants.GYEARMONTH,
ohair@286 544 DatatypeConstants.GMONTHDAY
ohair@286 545 ) {
ohair@286 546 public String print(XMLGregorianCalendar cal) {
ohair@286 547 XMLSerializer xs = XMLSerializer.getInstance();
ohair@286 548
ohair@286 549 QName type = xs.getSchemaType();
ohair@286 550 if (type != null) {
ohair@286 551 try {
ohair@286 552 checkXmlGregorianCalendarFieldRef(type, cal);
ohair@286 553 String format = xmlGregorianCalendarFormatString.get(type);
ohair@286 554 if (format != null) {
ohair@286 555 return format(format, cal);
ohair@286 556 }
ohair@286 557 } catch (javax.xml.bind.MarshalException e) {
ohair@286 558 // see issue 649
ohair@286 559 xs.handleEvent(new ValidationEventImpl(ValidationEvent.WARNING, e.getMessage(),
ohair@286 560 xs.getCurrentLocation(null) ));
ohair@286 561 return "";
ohair@286 562 }
ohair@286 563 }
ohair@286 564 return cal.toXMLFormat();
ohair@286 565 }
ohair@286 566
ohair@286 567 public XMLGregorianCalendar parse(CharSequence lexical) throws SAXException {
ohair@286 568 try {
mkos@514 569 return DatatypeConverterImpl.getDatatypeFactory()
mkos@514 570 .newXMLGregorianCalendar(lexical.toString().trim()); // (.trim() - issue 396)
ohair@286 571 } catch (Exception e) {
ohair@286 572 UnmarshallingContext.getInstance().handleError(e);
ohair@286 573 return null;
ohair@286 574 }
ohair@286 575 }
ohair@286 576
ohair@286 577 // code duplicated from JAXP RI 1.3. See 6277586
ohair@286 578 private String format( String format, XMLGregorianCalendar value ) {
ohair@286 579 StringBuilder buf = new StringBuilder();
ohair@286 580 int fidx=0,flen=format.length();
ohair@286 581
ohair@286 582 while(fidx<flen) {
ohair@286 583 char fch = format.charAt(fidx++);
ohair@286 584 if(fch!='%') {// not a meta char
ohair@286 585 buf.append(fch);
ohair@286 586 continue;
ohair@286 587 }
ohair@286 588
ohair@286 589 switch(format.charAt(fidx++)) {
ohair@286 590 case 'Y':
ohair@286 591 printNumber(buf,value.getEonAndYear(), 4);
ohair@286 592 break;
ohair@286 593 case 'M':
ohair@286 594 printNumber(buf,value.getMonth(),2);
ohair@286 595 break;
ohair@286 596 case 'D':
ohair@286 597 printNumber(buf,value.getDay(),2);
ohair@286 598 break;
ohair@286 599 case 'h':
ohair@286 600 printNumber(buf,value.getHour(),2);
ohair@286 601 break;
ohair@286 602 case 'm':
ohair@286 603 printNumber(buf,value.getMinute(),2);
ohair@286 604 break;
ohair@286 605 case 's':
ohair@286 606 printNumber(buf,value.getSecond(),2);
ohair@286 607 if (value.getFractionalSecond() != null) {
ohair@286 608 String frac = value.getFractionalSecond().toPlainString();
ohair@286 609 //skip leading zero.
ohair@286 610 buf.append(frac.substring(1, frac.length()));
ohair@286 611 }
ohair@286 612 break;
ohair@286 613 case 'z':
ohair@286 614 int offset = value.getTimezone();
ohair@286 615 if(offset == 0) {
ohair@286 616 buf.append('Z');
ohair@286 617 } else if (offset != DatatypeConstants.FIELD_UNDEFINED) {
ohair@286 618 if(offset<0) {
ohair@286 619 buf.append('-');
ohair@286 620 offset *= -1;
ohair@286 621 } else {
ohair@286 622 buf.append('+');
ohair@286 623 }
ohair@286 624 printNumber(buf,offset/60,2);
ohair@286 625 buf.append(':');
ohair@286 626 printNumber(buf,offset%60,2);
ohair@286 627 }
ohair@286 628 break;
ohair@286 629 default:
ohair@286 630 throw new InternalError(); // impossible
ohair@286 631 }
ohair@286 632 }
ohair@286 633
ohair@286 634 return buf.toString();
ohair@286 635 }
ohair@286 636 private void printNumber( StringBuilder out, BigInteger number, int nDigits) {
ohair@286 637 String s = number.toString();
ohair@286 638 for( int i=s.length(); i<nDigits; i++ )
ohair@286 639 out.append('0');
ohair@286 640 out.append(s);
ohair@286 641 }
ohair@286 642 private void printNumber( StringBuilder out, int number, int nDigits ) {
ohair@286 643 String s = String.valueOf(number);
ohair@286 644 for( int i=s.length(); i<nDigits; i++ )
ohair@286 645 out.append('0');
ohair@286 646 out.append(s);
ohair@286 647 }
ohair@286 648 @Override
ohair@286 649 public QName getTypeName(XMLGregorianCalendar cal) {
ohair@286 650 return cal.getXMLSchemaType();
ohair@286 651 }
ohair@286 652 });
ohair@286 653
ohair@286 654 ArrayList<RuntimeBuiltinLeafInfoImpl<?>> primaryList = new ArrayList<RuntimeBuiltinLeafInfoImpl<?>>();
ohair@286 655
ohair@286 656 /*
ohair@286 657 primary bindings
ohair@286 658 */
ohair@286 659 primaryList.add(STRING);
ohair@286 660 primaryList.add(new StringImpl<Boolean>(Boolean.class,
ohair@286 661 createXS("boolean")
ohair@286 662 ) {
ohair@286 663 public Boolean parse(CharSequence text) {
ohair@286 664 return DatatypeConverterImpl._parseBoolean(text);
ohair@286 665 }
ohair@286 666
ohair@286 667 public String print(Boolean v) {
ohair@286 668 return v.toString();
ohair@286 669 }
ohair@286 670 });
ohair@286 671 primaryList.add(new PcdataImpl<byte[]>(byte[].class,
ohair@286 672 createXS("base64Binary"),
ohair@286 673 createXS("hexBinary")
ohair@286 674 ) {
ohair@286 675 public byte[] parse(CharSequence text) {
ohair@286 676 return decodeBase64(text);
ohair@286 677 }
ohair@286 678
ohair@286 679 public Base64Data print(byte[] v) {
ohair@286 680 XMLSerializer w = XMLSerializer.getInstance();
ohair@286 681 Base64Data bd = new Base64Data();
ohair@286 682 String mimeType = w.getXMIMEContentType();
ohair@286 683 bd.set(v,mimeType);
ohair@286 684 return bd;
ohair@286 685 }
ohair@286 686 });
ohair@286 687 primaryList.add(new StringImpl<Byte>(Byte.class,
ohair@286 688 createXS("byte")
ohair@286 689 ) {
ohair@286 690 public Byte parse(CharSequence text) {
ohair@286 691 return DatatypeConverterImpl._parseByte(text);
ohair@286 692 }
ohair@286 693
ohair@286 694 public String print(Byte v) {
ohair@286 695 return DatatypeConverterImpl._printByte(v);
ohair@286 696 }
ohair@286 697 });
ohair@286 698 primaryList.add(new StringImpl<Short>(Short.class,
ohair@286 699 createXS("short"),
ohair@286 700 createXS("unsignedByte")
ohair@286 701 ) {
ohair@286 702 public Short parse(CharSequence text) {
ohair@286 703 return DatatypeConverterImpl._parseShort(text);
ohair@286 704 }
ohair@286 705
ohair@286 706 public String print(Short v) {
ohair@286 707 return DatatypeConverterImpl._printShort(v);
ohair@286 708 }
ohair@286 709 });
ohair@286 710 primaryList.add(new StringImpl<Integer>(Integer.class,
ohair@286 711 createXS("int"),
ohair@286 712 createXS("unsignedShort")
ohair@286 713 ) {
ohair@286 714 public Integer parse(CharSequence text) {
ohair@286 715 return DatatypeConverterImpl._parseInt(text);
ohair@286 716 }
ohair@286 717
ohair@286 718 public String print(Integer v) {
ohair@286 719 return DatatypeConverterImpl._printInt(v);
ohair@286 720 }
ohair@286 721 });
ohair@286 722 primaryList.add(
ohair@286 723 new StringImpl<Long>(Long.class,
ohair@286 724 createXS("long"),
ohair@286 725 createXS("unsignedInt")
ohair@286 726 ) {
ohair@286 727 public Long parse(CharSequence text) {
ohair@286 728 return DatatypeConverterImpl._parseLong(text);
ohair@286 729 }
ohair@286 730
ohair@286 731 public String print(Long v) {
ohair@286 732 return DatatypeConverterImpl._printLong(v);
ohair@286 733 }
ohair@286 734 });
ohair@286 735 primaryList.add(
ohair@286 736 new StringImpl<Float>(Float.class,
ohair@286 737 createXS("float")
ohair@286 738 ) {
ohair@286 739 public Float parse(CharSequence text) {
ohair@286 740 return DatatypeConverterImpl._parseFloat(text.toString());
ohair@286 741 }
ohair@286 742
ohair@286 743 public String print(Float v) {
ohair@286 744 return DatatypeConverterImpl._printFloat(v);
ohair@286 745 }
ohair@286 746 });
ohair@286 747 primaryList.add(
ohair@286 748 new StringImpl<Double>(Double.class,
ohair@286 749 createXS("double")
ohair@286 750 ) {
ohair@286 751 public Double parse(CharSequence text) {
ohair@286 752 return DatatypeConverterImpl._parseDouble(text);
ohair@286 753 }
ohair@286 754
ohair@286 755 public String print(Double v) {
ohair@286 756 return DatatypeConverterImpl._printDouble(v);
ohair@286 757 }
ohair@286 758 });
ohair@286 759 primaryList.add(
ohair@286 760 new StringImpl<BigInteger>(BigInteger.class,
ohair@286 761 createXS("integer"),
ohair@286 762 createXS("positiveInteger"),
ohair@286 763 createXS("negativeInteger"),
ohair@286 764 createXS("nonPositiveInteger"),
ohair@286 765 createXS("nonNegativeInteger"),
ohair@286 766 createXS("unsignedLong")
ohair@286 767 ) {
ohair@286 768 public BigInteger parse(CharSequence text) {
ohair@286 769 return DatatypeConverterImpl._parseInteger(text);
ohair@286 770 }
ohair@286 771
ohair@286 772 public String print(BigInteger v) {
ohair@286 773 return DatatypeConverterImpl._printInteger(v);
ohair@286 774 }
ohair@286 775 });
ohair@286 776 primaryList.add(
ohair@286 777 new StringImpl<BigDecimal>(BigDecimal.class,
ohair@286 778 createXS("decimal")
ohair@286 779 ) {
ohair@286 780 public BigDecimal parse(CharSequence text) {
ohair@286 781 return DatatypeConverterImpl._parseDecimal(text.toString());
ohair@286 782 }
ohair@286 783
ohair@286 784 public String print(BigDecimal v) {
ohair@286 785 return DatatypeConverterImpl._printDecimal(v);
ohair@286 786 }
ohair@286 787 });
ohair@286 788 primaryList.add(
ohair@286 789 new StringImpl<QName>(QName.class,
ohair@286 790 createXS("QName")
ohair@286 791 ) {
ohair@286 792 public QName parse(CharSequence text) throws SAXException {
ohair@286 793 try {
ohair@286 794 return DatatypeConverterImpl._parseQName(text.toString(),UnmarshallingContext.getInstance());
ohair@286 795 } catch (IllegalArgumentException e) {
ohair@286 796 UnmarshallingContext.getInstance().handleError(e);
ohair@286 797 return null;
ohair@286 798 }
ohair@286 799 }
ohair@286 800
ohair@286 801 public String print(QName v) {
ohair@286 802 return DatatypeConverterImpl._printQName(v,XMLSerializer.getInstance().getNamespaceContext());
ohair@286 803 }
ohair@286 804
ohair@286 805 @Override
ohair@286 806 public boolean useNamespace() {
ohair@286 807 return true;
ohair@286 808 }
ohair@286 809
ohair@286 810 @Override
ohair@286 811 public void declareNamespace(QName v, XMLSerializer w) {
ohair@286 812 w.getNamespaceContext().declareNamespace(v.getNamespaceURI(),v.getPrefix(),false);
ohair@286 813 }
ohair@286 814 });
ohair@286 815 if (System.getProperty(MAP_ANYURI_TO_URI) != null) {
ohair@286 816 primaryList.add(
ohair@286 817 new StringImpl<URI>(URI.class, createXS("anyURI")) {
ohair@286 818 public URI parse(CharSequence text) throws SAXException {
ohair@286 819 try {
ohair@286 820 return new URI(text.toString());
ohair@286 821 } catch (URISyntaxException e) {
ohair@286 822 UnmarshallingContext.getInstance().handleError(e);
ohair@286 823 return null;
ohair@286 824 }
ohair@286 825 }
ohair@286 826
ohair@286 827 public String print(URI v) {
ohair@286 828 return v.toString();
ohair@286 829 }
ohair@286 830 });
ohair@286 831 }
ohair@286 832 primaryList.add(
ohair@286 833 new StringImpl<Duration>(Duration.class, createXS("duration")) {
ohair@286 834 public String print(Duration duration) {
ohair@286 835 return duration.toString();
ohair@286 836 }
ohair@286 837
ohair@286 838 public Duration parse(CharSequence lexical) {
ohair@286 839 TODO.checkSpec("JSR222 Issue #42");
mkos@514 840 return DatatypeConverterImpl.getDatatypeFactory().newDuration(lexical.toString());
ohair@286 841 }
ohair@286 842 });
ohair@286 843 primaryList.add(
ohair@286 844 new StringImpl<Void>(Void.class) {
ohair@286 845 // 'void' binding isn't defined by the spec, but when the JAX-RPC processes user-defined
ohair@286 846 // methods like "int actionFoo()", they need this pseudo-void property.
ohair@286 847
ohair@286 848 public String print(Void value) {
ohair@286 849 return "";
ohair@286 850 }
ohair@286 851
ohair@286 852 public Void parse(CharSequence lexical) {
ohair@286 853 return null;
ohair@286 854 }
ohair@286 855 });
ohair@286 856
ohair@286 857 List<RuntimeBuiltinLeafInfoImpl<?>> l = new ArrayList<RuntimeBuiltinLeafInfoImpl<?>>(secondaryList.size()+primaryList.size()+1);
ohair@286 858 l.addAll(secondaryList);
ohair@286 859
ohair@286 860 // UUID may fail to load if we are running on JDK 1.4. Handle gracefully
ohair@286 861 try {
ohair@286 862 l.add(new UUIDImpl());
ohair@286 863 } catch (LinkageError e) {
ohair@286 864 // ignore
ohair@286 865 }
ohair@286 866
ohair@286 867 l.addAll(primaryList);
ohair@286 868
ohair@286 869 builtinBeanInfos = Collections.unmodifiableList(l);
ohair@286 870 }
ohair@286 871
ohair@286 872 private static byte[] decodeBase64(CharSequence text) {
ohair@286 873 if (text instanceof Base64Data) {
ohair@286 874 Base64Data base64Data = (Base64Data) text;
ohair@286 875 return base64Data.getExact();
ohair@286 876 } else {
ohair@286 877 return DatatypeConverterImpl._parseBase64Binary(text.toString());
ohair@286 878 }
ohair@286 879 }
ohair@286 880
ohair@286 881 private static void checkXmlGregorianCalendarFieldRef(QName type,
ohair@286 882 XMLGregorianCalendar cal)throws javax.xml.bind.MarshalException{
ohair@286 883 StringBuilder buf = new StringBuilder();
ohair@286 884 int bitField = xmlGregorianCalendarFieldRef.get(type);
ohair@286 885 final int l = 0x1;
ohair@286 886 int pos = 0;
ohair@286 887 while (bitField != 0x0){
ohair@286 888 int bit = bitField & l;
ohair@286 889 bitField >>>= 4;
ohair@286 890 pos++;
ohair@286 891
ohair@286 892 if (bit == 1) {
ohair@286 893 switch(pos){
ohair@286 894 case 1:
ohair@286 895 if (cal.getSecond() == DatatypeConstants.FIELD_UNDEFINED){
ohair@286 896 buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_SEC);
ohair@286 897 }
ohair@286 898 break;
ohair@286 899 case 2:
ohair@286 900 if (cal.getMinute() == DatatypeConstants.FIELD_UNDEFINED){
ohair@286 901 buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_MIN);
ohair@286 902 }
ohair@286 903 break;
ohair@286 904 case 3:
ohair@286 905 if (cal.getHour() == DatatypeConstants.FIELD_UNDEFINED){
ohair@286 906 buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_HR);
ohair@286 907 }
ohair@286 908 break;
ohair@286 909 case 4:
ohair@286 910 if (cal.getDay() == DatatypeConstants.FIELD_UNDEFINED){
ohair@286 911 buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_DAY);
ohair@286 912 }
ohair@286 913 break;
ohair@286 914 case 5:
ohair@286 915 if (cal.getMonth() == DatatypeConstants.FIELD_UNDEFINED){
ohair@286 916 buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_MONTH);
ohair@286 917 }
ohair@286 918 break;
ohair@286 919 case 6:
ohair@286 920 if (cal.getYear() == DatatypeConstants.FIELD_UNDEFINED){
ohair@286 921 buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_YEAR);
ohair@286 922 }
ohair@286 923 break;
ohair@286 924 case 7: // ignore timezone setting
ohair@286 925 break;
ohair@286 926 }
ohair@286 927 }
ohair@286 928 }
ohair@286 929 if (buf.length() > 0){
ohair@286 930 throw new javax.xml.bind.MarshalException(
ohair@286 931 Messages.XMLGREGORIANCALENDAR_INVALID.format(type.getLocalPart())
ohair@286 932 + buf.toString());
ohair@286 933 }
ohair@286 934 }
ohair@286 935
ohair@286 936 /**
ohair@286 937 * Format string for the {@link XMLGregorianCalendar}.
ohair@286 938 */
ohair@286 939 private static final Map<QName,String> xmlGregorianCalendarFormatString = new HashMap<QName, String>();
ohair@286 940
ohair@286 941 static {
ohair@286 942 Map<QName,String> m = xmlGregorianCalendarFormatString;
ohair@286 943 // See 4971612: be careful for SCCS substitution
ohair@286 944 m.put(DatatypeConstants.DATETIME, "%Y-%M-%DT%h:%m:%s"+ "%z");
ohair@286 945 m.put(DatatypeConstants.DATE, "%Y-%M-%D" +"%z");
ohair@286 946 m.put(DatatypeConstants.TIME, "%h:%m:%s"+ "%z");
mkos@450 947 m.put(DatatypeConstants.GMONTH, "--%M--%z");
ohair@286 948 m.put(DatatypeConstants.GDAY, "---%D" + "%z");
ohair@286 949 m.put(DatatypeConstants.GYEAR, "%Y" + "%z");
ohair@286 950 m.put(DatatypeConstants.GYEARMONTH, "%Y-%M" + "%z");
ohair@286 951 m.put(DatatypeConstants.GMONTHDAY, "--%M-%D" +"%z");
ohair@286 952 }
ohair@286 953
ohair@286 954 /**
ohair@286 955 * Field designations for XMLGregorianCalendar format string.
ohair@286 956 * sec 0x0000001
ohair@286 957 * min 0x0000010
ohair@286 958 * hrs 0x0000100
ohair@286 959 * day 0x0001000
ohair@286 960 * month 0x0010000
ohair@286 961 * year 0x0100000
ohair@286 962 * timezone 0x1000000
ohair@286 963 */
ohair@286 964 private static final Map<QName, Integer> xmlGregorianCalendarFieldRef =
ohair@286 965 new HashMap<QName, Integer>();
ohair@286 966 static {
ohair@286 967 Map<QName, Integer> f = xmlGregorianCalendarFieldRef;
ohair@286 968 f.put(DatatypeConstants.DATETIME, 0x1111111);
ohair@286 969 f.put(DatatypeConstants.DATE, 0x1111000);
ohair@286 970 f.put(DatatypeConstants.TIME, 0x1000111);
ohair@286 971 f.put(DatatypeConstants.GDAY, 0x1001000);
ohair@286 972 f.put(DatatypeConstants.GMONTH, 0x1010000);
ohair@286 973 f.put(DatatypeConstants.GYEAR, 0x1100000);
ohair@286 974 f.put(DatatypeConstants.GYEARMONTH, 0x1110000);
ohair@286 975 f.put(DatatypeConstants.GMONTHDAY, 0x1011000);
ohair@286 976 }
ohair@286 977
ohair@286 978 /**
ohair@286 979 * {@link RuntimeBuiltinLeafInfoImpl} for {@link UUID}.
ohair@286 980 *
ohair@286 981 * This class is given a name so that failing to load this class won't cause a fatal problem.
ohair@286 982 */
ohair@286 983 private static class UUIDImpl extends StringImpl<UUID> {
ohair@286 984 public UUIDImpl() {
ohair@286 985 super(UUID.class, RuntimeBuiltinLeafInfoImpl.createXS("string"));
ohair@286 986 }
ohair@286 987
ohair@286 988 public UUID parse(CharSequence text) throws SAXException {
ohair@286 989 TODO.checkSpec("JSR222 Issue #42");
ohair@286 990 try {
ohair@286 991 return UUID.fromString(WhiteSpaceProcessor.trim(text).toString());
ohair@286 992 } catch (IllegalArgumentException e) {
ohair@286 993 UnmarshallingContext.getInstance().handleError(e);
ohair@286 994 return null;
ohair@286 995 }
ohair@286 996 }
ohair@286 997
ohair@286 998 public String print(UUID v) {
ohair@286 999 return v.toString();
ohair@286 1000 }
ohair@286 1001 }
ohair@286 1002
ohair@286 1003 private static class StringImplImpl extends StringImpl<String> {
ohair@286 1004
ohair@286 1005 public StringImplImpl(Class type, QName[] typeNames) {
ohair@286 1006 super(type, typeNames);
ohair@286 1007 }
ohair@286 1008
ohair@286 1009 public String parse(CharSequence text) {
ohair@286 1010 return text.toString();
ohair@286 1011 }
ohair@286 1012
ohair@286 1013 public String print(String s) {
ohair@286 1014 return s;
ohair@286 1015 }
ohair@286 1016
ohair@286 1017 @Override
ohair@286 1018 public final void writeText(XMLSerializer w, String o, String fieldName) throws IOException, SAXException, XMLStreamException {
ohair@286 1019 w.text(o, fieldName);
ohair@286 1020 }
ohair@286 1021
ohair@286 1022 @Override
ohair@286 1023 public final void writeLeafElement(XMLSerializer w, Name tagName, String o, String fieldName) throws IOException, SAXException, XMLStreamException {
ohair@286 1024 w.leafElement(tagName, o, fieldName);
ohair@286 1025 }
ohair@286 1026 }
ohair@286 1027 }

mercurial