001 /* 002 * Copyright (C) 2003, 2004, 2005, 2006 Joe Walnes. 003 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 XStream Committers. 004 * All rights reserved. 005 * 006 * The software in this package is published under the terms of the BSD 007 * style license a copy of which has been included with this distribution in 008 * the LICENSE.txt file. 009 * 010 * Created on 26. September 2003 by Joe Walnes 011 */ 012 package com.thoughtworks.xstream; 013 014 import java.io.EOFException; 015 import java.io.File; 016 import java.io.IOException; 017 import java.io.InputStream; 018 import java.io.NotActiveException; 019 import java.io.ObjectInputStream; 020 import java.io.ObjectInputValidation; 021 import java.io.ObjectOutputStream; 022 import java.io.OutputStream; 023 import java.io.Reader; 024 import java.io.StringReader; 025 import java.io.StringWriter; 026 import java.io.Writer; 027 import java.lang.reflect.Constructor; 028 import java.lang.reflect.Field; 029 import java.lang.reflect.Method; 030 import java.math.BigDecimal; 031 import java.math.BigInteger; 032 import java.net.URI; 033 import java.net.URL; 034 import java.util.ArrayList; 035 import java.util.BitSet; 036 import java.util.Calendar; 037 import java.util.Collections; 038 import java.util.Date; 039 import java.util.GregorianCalendar; 040 import java.util.HashMap; 041 import java.util.HashSet; 042 import java.util.Hashtable; 043 import java.util.LinkedList; 044 import java.util.List; 045 import java.util.Locale; 046 import java.util.Map; 047 import java.util.Properties; 048 import java.util.Set; 049 import java.util.SortedSet; 050 import java.util.TreeMap; 051 import java.util.TreeSet; 052 import java.util.Vector; 053 import java.util.regex.Pattern; 054 055 import com.thoughtworks.xstream.converters.ConversionException; 056 import com.thoughtworks.xstream.converters.Converter; 057 import com.thoughtworks.xstream.converters.ConverterLookup; 058 import com.thoughtworks.xstream.converters.ConverterRegistry; 059 import com.thoughtworks.xstream.converters.DataHolder; 060 import com.thoughtworks.xstream.converters.SingleValueConverter; 061 import com.thoughtworks.xstream.converters.SingleValueConverterWrapper; 062 import com.thoughtworks.xstream.converters.basic.BigDecimalConverter; 063 import com.thoughtworks.xstream.converters.basic.BigIntegerConverter; 064 import com.thoughtworks.xstream.converters.basic.BooleanConverter; 065 import com.thoughtworks.xstream.converters.basic.ByteConverter; 066 import com.thoughtworks.xstream.converters.basic.CharConverter; 067 import com.thoughtworks.xstream.converters.basic.DateConverter; 068 import com.thoughtworks.xstream.converters.basic.DoubleConverter; 069 import com.thoughtworks.xstream.converters.basic.FloatConverter; 070 import com.thoughtworks.xstream.converters.basic.IntConverter; 071 import com.thoughtworks.xstream.converters.basic.LongConverter; 072 import com.thoughtworks.xstream.converters.basic.NullConverter; 073 import com.thoughtworks.xstream.converters.basic.ShortConverter; 074 import com.thoughtworks.xstream.converters.basic.StringBufferConverter; 075 import com.thoughtworks.xstream.converters.basic.StringConverter; 076 import com.thoughtworks.xstream.converters.basic.URIConverter; 077 import com.thoughtworks.xstream.converters.basic.URLConverter; 078 import com.thoughtworks.xstream.converters.collections.ArrayConverter; 079 import com.thoughtworks.xstream.converters.collections.BitSetConverter; 080 import com.thoughtworks.xstream.converters.collections.CharArrayConverter; 081 import com.thoughtworks.xstream.converters.collections.CollectionConverter; 082 import com.thoughtworks.xstream.converters.collections.MapConverter; 083 import com.thoughtworks.xstream.converters.collections.PropertiesConverter; 084 import com.thoughtworks.xstream.converters.collections.SingletonCollectionConverter; 085 import com.thoughtworks.xstream.converters.collections.SingletonMapConverter; 086 import com.thoughtworks.xstream.converters.collections.TreeMapConverter; 087 import com.thoughtworks.xstream.converters.collections.TreeSetConverter; 088 import com.thoughtworks.xstream.converters.extended.ColorConverter; 089 import com.thoughtworks.xstream.converters.extended.DynamicProxyConverter; 090 import com.thoughtworks.xstream.converters.extended.EncodedByteArrayConverter; 091 import com.thoughtworks.xstream.converters.extended.FileConverter; 092 import com.thoughtworks.xstream.converters.extended.FontConverter; 093 import com.thoughtworks.xstream.converters.extended.GregorianCalendarConverter; 094 import com.thoughtworks.xstream.converters.extended.JavaClassConverter; 095 import com.thoughtworks.xstream.converters.extended.JavaFieldConverter; 096 import com.thoughtworks.xstream.converters.extended.JavaMethodConverter; 097 import com.thoughtworks.xstream.converters.extended.LocaleConverter; 098 import com.thoughtworks.xstream.converters.extended.LookAndFeelConverter; 099 import com.thoughtworks.xstream.converters.extended.SqlDateConverter; 100 import com.thoughtworks.xstream.converters.extended.SqlTimeConverter; 101 import com.thoughtworks.xstream.converters.extended.SqlTimestampConverter; 102 import com.thoughtworks.xstream.converters.extended.TextAttributeConverter; 103 import com.thoughtworks.xstream.converters.reflection.ExternalizableConverter; 104 import com.thoughtworks.xstream.converters.reflection.ReflectionConverter; 105 import com.thoughtworks.xstream.converters.reflection.ReflectionProvider; 106 import com.thoughtworks.xstream.converters.reflection.SelfStreamingInstanceChecker; 107 import com.thoughtworks.xstream.converters.reflection.SerializableConverter; 108 import com.thoughtworks.xstream.core.DefaultConverterLookup; 109 import com.thoughtworks.xstream.core.JVM; 110 import com.thoughtworks.xstream.core.MapBackedDataHolder; 111 import com.thoughtworks.xstream.core.ReferenceByIdMarshallingStrategy; 112 import com.thoughtworks.xstream.core.ReferenceByXPathMarshallingStrategy; 113 import com.thoughtworks.xstream.core.TreeMarshallingStrategy; 114 import com.thoughtworks.xstream.core.util.ClassLoaderReference; 115 import com.thoughtworks.xstream.core.util.CompositeClassLoader; 116 import com.thoughtworks.xstream.core.util.CustomObjectInputStream; 117 import com.thoughtworks.xstream.core.util.CustomObjectOutputStream; 118 import com.thoughtworks.xstream.io.HierarchicalStreamDriver; 119 import com.thoughtworks.xstream.io.HierarchicalStreamReader; 120 import com.thoughtworks.xstream.io.HierarchicalStreamWriter; 121 import com.thoughtworks.xstream.io.StatefulWriter; 122 import com.thoughtworks.xstream.io.xml.XppDriver; 123 import com.thoughtworks.xstream.mapper.AnnotationConfiguration; 124 import com.thoughtworks.xstream.mapper.ArrayMapper; 125 import com.thoughtworks.xstream.mapper.AttributeAliasingMapper; 126 import com.thoughtworks.xstream.mapper.AttributeMapper; 127 import com.thoughtworks.xstream.mapper.CachingMapper; 128 import com.thoughtworks.xstream.mapper.ClassAliasingMapper; 129 import com.thoughtworks.xstream.mapper.DefaultImplementationsMapper; 130 import com.thoughtworks.xstream.mapper.DefaultMapper; 131 import com.thoughtworks.xstream.mapper.DynamicProxyMapper; 132 import com.thoughtworks.xstream.mapper.FieldAliasingMapper; 133 import com.thoughtworks.xstream.mapper.ImmutableTypesMapper; 134 import com.thoughtworks.xstream.mapper.ImplicitCollectionMapper; 135 import com.thoughtworks.xstream.mapper.LocalConversionMapper; 136 import com.thoughtworks.xstream.mapper.Mapper; 137 import com.thoughtworks.xstream.mapper.MapperWrapper; 138 import com.thoughtworks.xstream.mapper.OuterClassMapper; 139 import com.thoughtworks.xstream.mapper.PackageAliasingMapper; 140 import com.thoughtworks.xstream.mapper.SystemAttributeAliasingMapper; 141 import com.thoughtworks.xstream.mapper.XStream11XmlFriendlyMapper; 142 import com.thoughtworks.xstream.security.AnyTypePermission; 143 import com.thoughtworks.xstream.security.ExplicitTypePermission; 144 import com.thoughtworks.xstream.security.NoPermission; 145 import com.thoughtworks.xstream.security.NoTypePermission; 146 import com.thoughtworks.xstream.security.RegExpTypePermission; 147 import com.thoughtworks.xstream.security.TypeHierarchyPermission; 148 import com.thoughtworks.xstream.security.TypePermission; 149 import com.thoughtworks.xstream.security.WildcardTypePermission; 150 import com.thoughtworks.xstream.mapper.SecurityMapper; 151 152 153 /** 154 * Simple facade to XStream library, a Java-XML serialization tool. <p/> 155 * <p> 156 * <hr> 157 * <b>Example</b><blockquote> 158 * 159 * <pre> 160 * XStream xstream = new XStream(); 161 * String xml = xstream.toXML(myObject); // serialize to XML 162 * Object myObject2 = xstream.fromXML(xml); // deserialize from XML 163 * </pre> 164 * 165 * </blockquote> 166 * <hr> 167 * <p/> 168 * <h3>Aliasing classes</h3> 169 * <p/> 170 * <p> 171 * To create shorter XML, you can specify aliases for classes using the <code>alias()</code> 172 * method. For example, you can shorten all occurrences of element 173 * <code><com.blah.MyThing></code> to <code><my-thing></code> by registering an 174 * alias for the class. 175 * <p> 176 * <hr> 177 * <blockquote> 178 * 179 * <pre> 180 * xstream.alias("my-thing", MyThing.class); 181 * </pre> 182 * 183 * </blockquote> 184 * <hr> 185 * <p/> 186 * <h3>Converters</h3> 187 * <p/> 188 * <p> 189 * XStream contains a map of {@link com.thoughtworks.xstream.converters.Converter} instances, each 190 * of which acts as a strategy for converting a particular type of class to XML and back again. Out 191 * of the box, XStream contains converters for most basic types (String, Date, int, boolean, etc) 192 * and collections (Map, List, Set, Properties, etc). For other objects reflection is used to 193 * serialize each field recursively. 194 * </p> 195 * <p/> 196 * <p> 197 * Extra converters can be registered using the <code>registerConverter()</code> method. Some 198 * non-standard converters are supplied in the {@link com.thoughtworks.xstream.converters.extended} 199 * package and you can create your own by implementing the 200 * {@link com.thoughtworks.xstream.converters.Converter} interface. 201 * </p> 202 * <p/> 203 * <p> 204 * <hr> 205 * <b>Example</b><blockquote> 206 * 207 * <pre> 208 * xstream.registerConverter(new SqlTimestampConverter()); 209 * xstream.registerConverter(new DynamicProxyConverter()); 210 * </pre> 211 * 212 * </blockquote> 213 * <hr> 214 * <p> 215 * The converters can be registered with an explicit priority. By default they are registered with 216 * XStream.PRIORITY_NORMAL. Converters of same priority will be used in the reverse sequence 217 * they have been registered. The default converter, i.e. the converter which will be used if 218 * no other registered converter is suitable, can be registered with priority 219 * XStream.PRIORITY_VERY_LOW. XStream uses by default the 220 * {@link com.thoughtworks.xstream.converters.reflection.ReflectionConverter} as the fallback 221 * converter. 222 * </p> 223 * <p/> 224 * <p> 225 * <hr> 226 * <b>Example</b><blockquote> 227 * 228 * <pre> 229 * xstream.registerConverter(new CustomDefaultConverter(), XStream.PRIORITY_VERY_LOW); 230 * </pre> 231 * 232 * </blockquote> 233 * <hr> 234 * <p/> 235 * <h3>Object graphs</h3> 236 * <p/> 237 * <p> 238 * XStream has support for object graphs; a deserialized object graph will keep references intact, 239 * including circular references. 240 * </p> 241 * <p/> 242 * <p> 243 * XStream can signify references in XML using either relative/absolute XPath or IDs. The mode can be changed using 244 * <code>setMode()</code>: 245 * </p> 246 * <p/> 247 * <table border='1'> 248 * <tr> 249 * <td><code>xstream.setMode(XStream.XPATH_RELATIVE_REFERENCES);</code></td> 250 * <td><i>(Default)</i> Uses XPath relative references to signify duplicate references. This produces XML 251 * with the least clutter.</td> 252 * </tr> 253 * <tr> 254 * <td><code>xstream.setMode(XStream.XPATH_ABSOLUTE_REFERENCES);</code></td> 255 * <td>Uses XPath absolute references to signify duplicate 256 * references. This produces XML with the least clutter.</td> 257 * </tr> 258 * <tr> 259 * <td><code>xstream.setMode(XStream.SINGLE_NODE_XPATH_RELATIVE_REFERENCES);</code></td> 260 * <td>Uses XPath relative references to signify duplicate references. The XPath expression ensures that 261 * a single node only is selected always.</td> 262 * </tr> 263 * <tr> 264 * <td><code>xstream.setMode(XStream.SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES);</code></td> 265 * <td>Uses XPath absolute references to signify duplicate references. The XPath expression ensures that 266 * a single node only is selected always.</td> 267 * </tr> 268 * <tr> 269 * <td><code>xstream.setMode(XStream.ID_REFERENCES);</code></td> 270 * <td>Uses ID references to signify duplicate references. In some scenarios, such as when using 271 * hand-written XML, this is easier to work with.</td> 272 * </tr> 273 * <tr> 274 * <td><code>xstream.setMode(XStream.NO_REFERENCES);</code></td> 275 * <td>This disables object graph support and treats the object structure like a tree. Duplicate 276 * references are treated as two separate objects and circular references cause an exception. This 277 * is slightly faster and uses less memory than the other two modes.</td> 278 * </tr> 279 * </table> 280 * <h3>Thread safety</h3> 281 * <p> 282 * The XStream instance is thread-safe. That is, once the XStream instance has been created and 283 * configured, it may be shared across multiple threads allowing objects to be 284 * serialized/deserialized concurrently. <em>Note, that this only applies if annotations are not 285 * auto-detected on -the-fly.</em> 286 * </p> 287 * <h3>Implicit collections</h3> 288 * <p/> 289 * <p> 290 * To avoid the need for special tags for collections, you can define implicit collections using one 291 * of the <code>addImplicitCollection</code> methods. 292 * </p> 293 * 294 * @author Joe Walnes 295 * @author Jörg Schaible 296 * @author Mauro Talevi 297 * @author Guilherme Silveira 298 */ 299 public class XStream { 300 301 // CAUTION: The sequence of the fields is intentional for an optimal XML output of a 302 // self-serialization! 303 private ReflectionProvider reflectionProvider; 304 private HierarchicalStreamDriver hierarchicalStreamDriver; 305 private ClassLoaderReference classLoaderReference; 306 private MarshallingStrategy marshallingStrategy; 307 private ConverterLookup converterLookup; 308 private ConverterRegistry converterRegistry; 309 private Mapper mapper; 310 311 private PackageAliasingMapper packageAliasingMapper; 312 private ClassAliasingMapper classAliasingMapper; 313 private FieldAliasingMapper fieldAliasingMapper; 314 private AttributeAliasingMapper attributeAliasingMapper; 315 private SystemAttributeAliasingMapper systemAttributeAliasingMapper; 316 private AttributeMapper attributeMapper; 317 private DefaultImplementationsMapper defaultImplementationsMapper; 318 private ImmutableTypesMapper immutableTypesMapper; 319 private ImplicitCollectionMapper implicitCollectionMapper; 320 private LocalConversionMapper localConversionMapper; 321 private AnnotationConfiguration annotationConfiguration; 322 private SecurityMapper securityMapper; 323 324 private transient JVM jvm = new JVM(); 325 326 public static final int NO_REFERENCES = 1001; 327 public static final int ID_REFERENCES = 1002; 328 public static final int XPATH_RELATIVE_REFERENCES = 1003; 329 public static final int XPATH_ABSOLUTE_REFERENCES = 1004; 330 public static final int SINGLE_NODE_XPATH_RELATIVE_REFERENCES = 1005; 331 public static final int SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES = 1006; 332 333 public static final int PRIORITY_VERY_HIGH = 10000; 334 public static final int PRIORITY_NORMAL = 0; 335 public static final int PRIORITY_LOW = -10; 336 public static final int PRIORITY_VERY_LOW = -20; 337 338 private static final String ANNOTATION_MAPPER_TYPE = "com.thoughtworks.xstream.mapper.AnnotationMapper"; 339 private static final Pattern IGNORE_ALL = Pattern.compile(".*"); 340 341 /** 342 * Constructs a default XStream. The instance will use the {@link XppDriver} as default and 343 * tries to determine the best match for the {@link ReflectionProvider} on its own. 344 * 345 * @throws InitializationException in case of an initialization problem 346 */ 347 public XStream() { 348 this(null, (Mapper)null, new XppDriver()); 349 } 350 351 /** 352 * Constructs an XStream with a special {@link ReflectionProvider}. The instance will use 353 * the {@link XppDriver} as default. 354 * 355 * @throws InitializationException in case of an initialization problem 356 */ 357 public XStream(ReflectionProvider reflectionProvider) { 358 this(reflectionProvider, (Mapper)null, new XppDriver()); 359 } 360 361 /** 362 * Constructs an XStream with a special {@link HierarchicalStreamDriver}. The instance will 363 * tries to determine the best match for the {@link ReflectionProvider} on its own. 364 * 365 * @throws InitializationException in case of an initialization problem 366 */ 367 public XStream(HierarchicalStreamDriver hierarchicalStreamDriver) { 368 this(null, (Mapper)null, hierarchicalStreamDriver); 369 } 370 371 /** 372 * Constructs an XStream with a special {@link HierarchicalStreamDriver} and 373 * {@link ReflectionProvider}. 374 * 375 * @throws InitializationException in case of an initialization problem 376 */ 377 public XStream( 378 ReflectionProvider reflectionProvider, HierarchicalStreamDriver hierarchicalStreamDriver) { 379 this(reflectionProvider, (Mapper)null, hierarchicalStreamDriver); 380 } 381 382 /** 383 * Constructs an XStream with a special {@link HierarchicalStreamDriver} and 384 * {@link ReflectionProvider} and additionally with a prepared {@link Mapper}. 385 * 386 * @throws InitializationException in case of an initialization problem 387 * @deprecated As of 1.3, use 388 * {@link #XStream(ReflectionProvider, HierarchicalStreamDriver, ClassLoader, Mapper)} 389 * instead 390 */ 391 public XStream( 392 ReflectionProvider reflectionProvider, Mapper mapper, HierarchicalStreamDriver driver) { 393 this( 394 reflectionProvider, driver, new ClassLoaderReference(new CompositeClassLoader()), 395 mapper, new DefaultConverterLookup(), null); 396 } 397 398 /** 399 * Constructs an XStream with a special {@link HierarchicalStreamDriver} and 400 * {@link ReflectionProvider} and additionally with a prepared {@link ClassLoader} to use. 401 * 402 * @throws InitializationException in case of an initialization problem 403 * @since 1.3 404 */ 405 public XStream( 406 ReflectionProvider reflectionProvider, HierarchicalStreamDriver driver, 407 ClassLoader classLoader) { 408 this(reflectionProvider, driver, classLoader, null); 409 } 410 411 /** 412 * Constructs an XStream with a special {@link HierarchicalStreamDriver} and 413 * {@link ReflectionProvider} and additionally with a prepared {@link Mapper} and the 414 * {@link ClassLoader} in use. 415 * <p> 416 * Note, if the class loader should be changed later again, you should provide a 417 * {@link ClassLoaderReference} as {@link ClassLoader} that is also use in the 418 * {@link Mapper} chain. 419 * </p> 420 * 421 * @throws InitializationException in case of an initialization problem 422 * @since 1.3 423 */ 424 public XStream( 425 ReflectionProvider reflectionProvider, HierarchicalStreamDriver driver, 426 ClassLoader classLoader, Mapper mapper) { 427 this( 428 reflectionProvider, driver, classLoader, mapper, new DefaultConverterLookup(), null); 429 } 430 431 /** 432 * Constructs an XStream with a special {@link HierarchicalStreamDriver}, 433 * {@link ReflectionProvider}, a prepared {@link Mapper} and the {@link ClassLoader} in use 434 * and an own {@link ConverterRegistry}. 435 * <p> 436 * Note, if the class loader should be changed later again, you should provide a 437 * {@link ClassLoaderReference} as {@link ClassLoader} that is also use in the 438 * {@link Mapper} chain. 439 * </p> 440 * 441 * @throws InitializationException in case of an initialization problem 442 * @since 1.3 443 */ 444 public XStream( 445 ReflectionProvider reflectionProvider, HierarchicalStreamDriver driver, 446 ClassLoader classLoader, Mapper mapper, ConverterLookup converterLookup, 447 ConverterRegistry converterRegistry) { 448 jvm = new JVM(); 449 if (reflectionProvider == null) { 450 reflectionProvider = jvm.bestReflectionProvider(); 451 } 452 this.reflectionProvider = reflectionProvider; 453 this.hierarchicalStreamDriver = driver; 454 this.classLoaderReference = classLoader instanceof ClassLoaderReference 455 ? (ClassLoaderReference)classLoader 456 : new ClassLoaderReference(classLoader); 457 this.converterLookup = converterLookup; 458 this.converterRegistry = converterRegistry != null 459 ? converterRegistry 460 : (converterLookup instanceof ConverterRegistry 461 ? (ConverterRegistry)converterLookup 462 : null); 463 this.mapper = mapper == null ? buildMapper() : mapper; 464 465 setupMappers(); 466 setupAliases(); 467 setupDefaultImplementations(); 468 setupConverters(); 469 setupImmutableTypes(); 470 setMode(XPATH_RELATIVE_REFERENCES); 471 } 472 473 private Mapper buildMapper() { 474 Mapper mapper = new DefaultMapper(classLoaderReference); 475 if (useXStream11XmlFriendlyMapper()) { 476 mapper = new XStream11XmlFriendlyMapper(mapper); 477 } 478 mapper = new DynamicProxyMapper(mapper); 479 mapper = new PackageAliasingMapper(mapper); 480 mapper = new ClassAliasingMapper(mapper); 481 mapper = new FieldAliasingMapper(mapper); 482 mapper = new AttributeAliasingMapper(mapper); 483 mapper = new SystemAttributeAliasingMapper(mapper); 484 mapper = new ImplicitCollectionMapper(mapper); 485 mapper = new OuterClassMapper(mapper); 486 mapper = new ArrayMapper(mapper); 487 mapper = new DefaultImplementationsMapper(mapper); 488 mapper = new AttributeMapper(mapper, converterLookup, reflectionProvider); 489 if (JVM.is15()) { 490 mapper = buildMapperDynamically( 491 "com.thoughtworks.xstream.mapper.EnumMapper", new Class[]{Mapper.class}, 492 new Object[]{mapper}); 493 } 494 mapper = new LocalConversionMapper(mapper); 495 mapper = new ImmutableTypesMapper(mapper); 496 if (JVM.is15()) { 497 mapper = buildMapperDynamically(ANNOTATION_MAPPER_TYPE, new Class[]{ 498 Mapper.class, ConverterRegistry.class, ConverterLookup.class, 499 ClassLoader.class, ReflectionProvider.class, JVM.class}, new Object[]{ 500 mapper, converterLookup, converterLookup, classLoaderReference, 501 reflectionProvider, jvm}); 502 } 503 mapper = wrapMapper((MapperWrapper)mapper); 504 mapper = new CachingMapper(mapper); 505 return mapper; 506 } 507 508 private Mapper buildMapperDynamically(String className, Class[] constructorParamTypes, 509 Object[] constructorParamValues) { 510 try { 511 Class type = Class.forName(className, false, classLoaderReference.getReference()); 512 Constructor constructor = type.getConstructor(constructorParamTypes); 513 return (Mapper)constructor.newInstance(constructorParamValues); 514 } catch (Exception e) { 515 throw new com.thoughtworks.xstream.InitializationException( 516 "Could not instantiate mapper : " + className, e); 517 } 518 } 519 520 protected MapperWrapper wrapMapper(MapperWrapper next) { 521 return next; 522 } 523 524 protected boolean useXStream11XmlFriendlyMapper() { 525 return false; 526 } 527 528 private void setupMappers() { 529 packageAliasingMapper = (PackageAliasingMapper)this.mapper 530 .lookupMapperOfType(PackageAliasingMapper.class); 531 classAliasingMapper = (ClassAliasingMapper)this.mapper 532 .lookupMapperOfType(ClassAliasingMapper.class); 533 fieldAliasingMapper = (FieldAliasingMapper)this.mapper 534 .lookupMapperOfType(FieldAliasingMapper.class); 535 attributeMapper = (AttributeMapper)this.mapper 536 .lookupMapperOfType(AttributeMapper.class); 537 attributeAliasingMapper = (AttributeAliasingMapper)this.mapper 538 .lookupMapperOfType(AttributeAliasingMapper.class); 539 systemAttributeAliasingMapper = (SystemAttributeAliasingMapper)this.mapper 540 .lookupMapperOfType(SystemAttributeAliasingMapper.class); 541 implicitCollectionMapper = (ImplicitCollectionMapper)this.mapper 542 .lookupMapperOfType(ImplicitCollectionMapper.class); 543 defaultImplementationsMapper = (DefaultImplementationsMapper)this.mapper 544 .lookupMapperOfType(DefaultImplementationsMapper.class); 545 immutableTypesMapper = (ImmutableTypesMapper)this.mapper 546 .lookupMapperOfType(ImmutableTypesMapper.class); 547 localConversionMapper = (LocalConversionMapper)this.mapper 548 .lookupMapperOfType(LocalConversionMapper.class); 549 annotationConfiguration = (AnnotationConfiguration)this.mapper 550 .lookupMapperOfType(AnnotationConfiguration.class); 551 } 552 553 protected void setupAliases() { 554 if (classAliasingMapper == null) { 555 return; 556 } 557 558 alias("null", Mapper.Null.class); 559 alias("int", Integer.class); 560 alias("float", Float.class); 561 alias("double", Double.class); 562 alias("long", Long.class); 563 alias("short", Short.class); 564 alias("char", Character.class); 565 alias("byte", Byte.class); 566 alias("boolean", Boolean.class); 567 alias("number", Number.class); 568 alias("object", Object.class); 569 alias("big-int", BigInteger.class); 570 alias("big-decimal", BigDecimal.class); 571 572 alias("string-buffer", StringBuffer.class); 573 alias("string", String.class); 574 alias("java-class", Class.class); 575 alias("method", Method.class); 576 alias("constructor", Constructor.class); 577 alias("field", Field.class); 578 alias("date", Date.class); 579 alias("uri", URI.class); 580 alias("url", URL.class); 581 alias("bit-set", BitSet.class); 582 583 alias("map", Map.class); 584 alias("entry", Map.Entry.class); 585 alias("properties", Properties.class); 586 alias("list", List.class); 587 alias("set", Set.class); 588 alias("sorted-set", SortedSet.class); 589 590 alias("linked-list", LinkedList.class); 591 alias("vector", Vector.class); 592 alias("tree-map", TreeMap.class); 593 alias("tree-set", TreeSet.class); 594 alias("hashtable", Hashtable.class); 595 596 alias("empty-list", Collections.EMPTY_LIST.getClass()); 597 alias("empty-map", Collections.EMPTY_MAP.getClass()); 598 alias("empty-set", Collections.EMPTY_SET.getClass()); 599 alias("singleton-list", Collections.singletonList(this).getClass()); 600 alias("singleton-map", Collections.singletonMap(this, null).getClass()); 601 alias("singleton-set", Collections.singleton(this).getClass()); 602 603 if (jvm.supportsAWT()) { 604 // Instantiating these two classes starts the AWT system, which is undesirable. 605 // Calling loadClass ensures a reference to the class is found but they are not 606 // instantiated. 607 alias("awt-color", jvm.loadClass("java.awt.Color")); 608 alias("awt-font", jvm.loadClass("java.awt.Font")); 609 alias("awt-text-attribute", jvm.loadClass("java.awt.font.TextAttribute")); 610 } 611 612 if (jvm.supportsSQL()) { 613 alias("sql-timestamp", jvm.loadClass("java.sql.Timestamp")); 614 alias("sql-time", jvm.loadClass("java.sql.Time")); 615 alias("sql-date", jvm.loadClass("java.sql.Date")); 616 } 617 618 alias("file", File.class); 619 alias("locale", Locale.class); 620 alias("gregorian-calendar", Calendar.class); 621 622 if (JVM.is14()) { 623 aliasDynamically("auth-subject", "javax.security.auth.Subject"); 624 alias("linked-hash-map", jvm.loadClass("java.util.LinkedHashMap")); 625 alias("linked-hash-set", jvm.loadClass("java.util.LinkedHashSet")); 626 alias("trace", jvm.loadClass("java.lang.StackTraceElement")); 627 alias("currency", jvm.loadClass("java.util.Currency")); 628 aliasType("charset", jvm.loadClass("java.nio.charset.Charset")); 629 } 630 631 if (JVM.is15()) { 632 aliasDynamically("duration", "javax.xml.datatype.Duration"); 633 alias("enum-set", jvm.loadClass("java.util.EnumSet")); 634 alias("enum-map", jvm.loadClass("java.util.EnumMap")); 635 alias("string-builder", jvm.loadClass("java.lang.StringBuilder")); 636 alias("uuid", jvm.loadClass("java.util.UUID")); 637 } 638 } 639 640 private void aliasDynamically(String alias, String className) { 641 Class type = jvm.loadClass(className); 642 if (type != null) { 643 alias(alias, type); 644 } 645 } 646 647 protected void setupDefaultImplementations() { 648 if (defaultImplementationsMapper == null) { 649 return; 650 } 651 addDefaultImplementation(HashMap.class, Map.class); 652 addDefaultImplementation(ArrayList.class, List.class); 653 addDefaultImplementation(HashSet.class, Set.class); 654 addDefaultImplementation(TreeSet.class, SortedSet.class); 655 addDefaultImplementation(GregorianCalendar.class, Calendar.class); 656 } 657 658 protected void setupConverters() { 659 final ReflectionConverter reflectionConverter = new ReflectionConverter( 660 mapper, reflectionProvider); 661 registerConverter(reflectionConverter, PRIORITY_VERY_LOW); 662 663 registerConverter( 664 new SerializableConverter(mapper, reflectionProvider, classLoaderReference), PRIORITY_LOW); 665 registerConverter(new ExternalizableConverter(mapper, classLoaderReference), PRIORITY_LOW); 666 667 registerConverter(new NullConverter(), PRIORITY_VERY_HIGH); 668 registerConverter(new IntConverter(), PRIORITY_NORMAL); 669 registerConverter(new FloatConverter(), PRIORITY_NORMAL); 670 registerConverter(new DoubleConverter(), PRIORITY_NORMAL); 671 registerConverter(new LongConverter(), PRIORITY_NORMAL); 672 registerConverter(new ShortConverter(), PRIORITY_NORMAL); 673 registerConverter((Converter)new CharConverter(), PRIORITY_NORMAL); 674 registerConverter(new BooleanConverter(), PRIORITY_NORMAL); 675 registerConverter(new ByteConverter(), PRIORITY_NORMAL); 676 677 registerConverter(new StringConverter(), PRIORITY_NORMAL); 678 registerConverter(new StringBufferConverter(), PRIORITY_NORMAL); 679 registerConverter(new DateConverter(), PRIORITY_NORMAL); 680 registerConverter(new BitSetConverter(), PRIORITY_NORMAL); 681 registerConverter(new URIConverter(), PRIORITY_NORMAL); 682 registerConverter(new URLConverter(), PRIORITY_NORMAL); 683 registerConverter(new BigIntegerConverter(), PRIORITY_NORMAL); 684 registerConverter(new BigDecimalConverter(), PRIORITY_NORMAL); 685 686 registerConverter(new ArrayConverter(mapper), PRIORITY_NORMAL); 687 registerConverter(new CharArrayConverter(), PRIORITY_NORMAL); 688 registerConverter(new CollectionConverter(mapper), PRIORITY_NORMAL); 689 registerConverter(new MapConverter(mapper), PRIORITY_NORMAL); 690 registerConverter(new TreeMapConverter(mapper), PRIORITY_NORMAL); 691 registerConverter(new TreeSetConverter(mapper), PRIORITY_NORMAL); 692 registerConverter(new SingletonCollectionConverter(mapper), PRIORITY_NORMAL); 693 registerConverter(new SingletonMapConverter(mapper), PRIORITY_NORMAL); 694 registerConverter(new PropertiesConverter(), PRIORITY_NORMAL); 695 registerConverter((Converter)new EncodedByteArrayConverter(), PRIORITY_NORMAL); 696 697 registerConverter(new FileConverter(), PRIORITY_NORMAL); 698 if (jvm.supportsSQL()) { 699 registerConverter(new SqlTimestampConverter(), PRIORITY_NORMAL); 700 registerConverter(new SqlTimeConverter(), PRIORITY_NORMAL); 701 registerConverter(new SqlDateConverter(), PRIORITY_NORMAL); 702 } 703 registerConverter( 704 new DynamicProxyConverter(mapper, classLoaderReference), PRIORITY_NORMAL); 705 registerConverter(new JavaClassConverter(classLoaderReference), PRIORITY_NORMAL); 706 registerConverter(new JavaMethodConverter(classLoaderReference), PRIORITY_NORMAL); 707 registerConverter(new JavaFieldConverter(classLoaderReference), PRIORITY_NORMAL); 708 if (jvm.supportsAWT()) { 709 registerConverter(new FontConverter(), PRIORITY_NORMAL); 710 registerConverter(new ColorConverter(), PRIORITY_NORMAL); 711 registerConverter(new TextAttributeConverter(), PRIORITY_NORMAL); 712 } 713 if (jvm.supportsSwing()) { 714 registerConverter( 715 new LookAndFeelConverter(mapper, reflectionProvider), PRIORITY_NORMAL); 716 } 717 registerConverter(new LocaleConverter(), PRIORITY_NORMAL); 718 registerConverter(new GregorianCalendarConverter(), PRIORITY_NORMAL); 719 720 if (JVM.is14()) { 721 // late bound converters - allows XStream to be compiled on earlier JDKs 722 registerConverterDynamically( 723 "com.thoughtworks.xstream.converters.extended.SubjectConverter", 724 PRIORITY_NORMAL, new Class[]{Mapper.class}, new Object[]{mapper}); 725 registerConverterDynamically( 726 "com.thoughtworks.xstream.converters.extended.ThrowableConverter", 727 PRIORITY_NORMAL, new Class[]{Converter.class}, 728 new Object[]{reflectionConverter}); 729 registerConverterDynamically( 730 "com.thoughtworks.xstream.converters.extended.StackTraceElementConverter", 731 PRIORITY_NORMAL, null, null); 732 registerConverterDynamically( 733 "com.thoughtworks.xstream.converters.extended.CurrencyConverter", 734 PRIORITY_NORMAL, null, null); 735 registerConverterDynamically( 736 "com.thoughtworks.xstream.converters.extended.RegexPatternConverter", 737 PRIORITY_NORMAL, new Class[]{Converter.class}, 738 new Object[]{reflectionConverter}); 739 registerConverterDynamically( 740 "com.thoughtworks.xstream.converters.extended.CharsetConverter", 741 PRIORITY_NORMAL, null, null); 742 } 743 744 if (JVM.is15()) { 745 // late bound converters - allows XStream to be compiled on earlier JDKs 746 if (jvm.loadClass("javax.xml.datatype.Duration") != null) { 747 registerConverterDynamically( 748 "com.thoughtworks.xstream.converters.extended.DurationConverter", 749 PRIORITY_NORMAL, null, null); 750 } 751 registerConverterDynamically( 752 "com.thoughtworks.xstream.converters.enums.EnumConverter", PRIORITY_NORMAL, 753 null, null); 754 registerConverterDynamically( 755 "com.thoughtworks.xstream.converters.enums.EnumSetConverter", PRIORITY_NORMAL, 756 new Class[]{Mapper.class}, new Object[]{mapper}); 757 registerConverterDynamically( 758 "com.thoughtworks.xstream.converters.enums.EnumMapConverter", PRIORITY_NORMAL, 759 new Class[]{Mapper.class}, new Object[]{mapper}); 760 registerConverterDynamically( 761 "com.thoughtworks.xstream.converters.basic.StringBuilderConverter", 762 PRIORITY_NORMAL, null, null); 763 registerConverterDynamically( 764 "com.thoughtworks.xstream.converters.basic.UUIDConverter", PRIORITY_NORMAL, 765 null, null); 766 } 767 768 registerConverter( 769 new SelfStreamingInstanceChecker(reflectionConverter, this), PRIORITY_NORMAL); 770 } 771 772 private void registerConverterDynamically(String className, int priority, 773 Class[] constructorParamTypes, Object[] constructorParamValues) { 774 try { 775 Class type = Class.forName(className, false, classLoaderReference.getReference()); 776 Constructor constructor = type.getConstructor(constructorParamTypes); 777 Object instance = constructor.newInstance(constructorParamValues); 778 if (instance instanceof Converter) { 779 registerConverter((Converter)instance, priority); 780 } else if (instance instanceof SingleValueConverter) { 781 registerConverter((SingleValueConverter)instance, priority); 782 } 783 } catch (Exception e) { 784 throw new com.thoughtworks.xstream.InitializationException( 785 "Could not instantiate converter : " + className, e); 786 } 787 } 788 789 protected void setupImmutableTypes() { 790 if (immutableTypesMapper == null) { 791 return; 792 } 793 794 // primitives are always immutable 795 addImmutableType(boolean.class); 796 addImmutableType(Boolean.class); 797 addImmutableType(byte.class); 798 addImmutableType(Byte.class); 799 addImmutableType(char.class); 800 addImmutableType(Character.class); 801 addImmutableType(double.class); 802 addImmutableType(Double.class); 803 addImmutableType(float.class); 804 addImmutableType(Float.class); 805 addImmutableType(int.class); 806 addImmutableType(Integer.class); 807 addImmutableType(long.class); 808 addImmutableType(Long.class); 809 addImmutableType(short.class); 810 addImmutableType(Short.class); 811 812 // additional types 813 addImmutableType(Mapper.Null.class); 814 addImmutableType(BigDecimal.class); 815 addImmutableType(BigInteger.class); 816 addImmutableType(String.class); 817 addImmutableType(URI.class); 818 addImmutableType(URL.class); 819 addImmutableType(File.class); 820 addImmutableType(Class.class); 821 822 addImmutableType(Collections.EMPTY_LIST.getClass()); 823 addImmutableType(Collections.EMPTY_SET.getClass()); 824 addImmutableType(Collections.EMPTY_MAP.getClass()); 825 826 if (jvm.supportsAWT()) { 827 addImmutableTypeDynamically("java.awt.font.TextAttribute"); 828 } 829 830 if (JVM.is14()) { 831 // late bound types - allows XStream to be compiled on earlier JDKs 832 addImmutableTypeDynamically("java.nio.charset.Charset"); 833 addImmutableTypeDynamically("java.util.Currency"); 834 } 835 } 836 837 private void addImmutableTypeDynamically(String className) { 838 Class type = jvm.loadClass(className); 839 if (type != null) { 840 addImmutableType(type); 841 } 842 } 843 844 public void setMarshallingStrategy(MarshallingStrategy marshallingStrategy) { 845 this.marshallingStrategy = marshallingStrategy; 846 } 847 848 /** 849 * Serialize an object to a pretty-printed XML String. 850 * 851 * @throws XStreamException if the object cannot be serialized 852 */ 853 public String toXML(Object obj) { 854 Writer writer = new StringWriter(); 855 toXML(obj, writer); 856 return writer.toString(); 857 } 858 859 /** 860 * Serialize an object to the given Writer as pretty-printed XML. The Writer will be flushed 861 * afterwards and in case of an exception. 862 * 863 * @throws XStreamException if the object cannot be serialized 864 */ 865 public void toXML(Object obj, Writer out) { 866 HierarchicalStreamWriter writer = hierarchicalStreamDriver.createWriter(out); 867 try { 868 marshal(obj, writer); 869 } finally { 870 writer.flush(); 871 } 872 } 873 874 /** 875 * Serialize an object to the given OutputStream as pretty-printed XML. The OutputStream 876 * will be flushed afterwards and in case of an exception. 877 * 878 * @throws XStreamException if the object cannot be serialized 879 */ 880 public void toXML(Object obj, OutputStream out) { 881 HierarchicalStreamWriter writer = hierarchicalStreamDriver.createWriter(out); 882 try { 883 marshal(obj, writer); 884 } finally { 885 writer.flush(); 886 } 887 } 888 889 /** 890 * Serialize and object to a hierarchical data structure (such as XML). 891 * 892 * @throws XStreamException if the object cannot be serialized 893 */ 894 public void marshal(Object obj, HierarchicalStreamWriter writer) { 895 marshal(obj, writer, null); 896 } 897 898 /** 899 * Serialize and object to a hierarchical data structure (such as XML). 900 * 901 * @param dataHolder Extra data you can use to pass to your converters. Use this as you 902 * want. If not present, XStream shall create one lazily as needed. 903 * @throws XStreamException if the object cannot be serialized 904 */ 905 public void marshal(Object obj, HierarchicalStreamWriter writer, DataHolder dataHolder) { 906 marshallingStrategy.marshal(writer, obj, converterLookup, mapper, dataHolder); 907 } 908 909 /** 910 * Deserialize an object from an XML String. 911 * 912 * @throws XStreamException if the object cannot be deserialized 913 */ 914 public Object fromXML(String xml) { 915 return fromXML(new StringReader(xml)); 916 } 917 918 /** 919 * Deserialize an object from an XML Reader. 920 * 921 * @throws XStreamException if the object cannot be deserialized 922 */ 923 public Object fromXML(Reader reader) { 924 return unmarshal(hierarchicalStreamDriver.createReader(reader), null); 925 } 926 927 /** 928 * Deserialize an object from an XML InputStream. 929 * 930 * @throws XStreamException if the object cannot be deserialized 931 */ 932 public Object fromXML(InputStream input) { 933 return unmarshal(hierarchicalStreamDriver.createReader(input), null); 934 } 935 936 /** 937 * Deserialize an object from a URL. 938 * 939 * Depending on the parser implementation, some might take the file path as SystemId to 940 * resolve additional references. 941 * 942 * @throws XStreamException if the object cannot be deserialized 943 * @since 1.4 944 */ 945 public Object fromXML(URL url) { 946 return unmarshal(hierarchicalStreamDriver.createReader(url), null); 947 } 948 949 /** 950 * Deserialize an object from a file. 951 * 952 * Depending on the parser implementation, some might take the file path as SystemId to 953 * resolve additional references. 954 * 955 * @throws XStreamException if the object cannot be deserialized 956 * @since 1.4 957 */ 958 public Object fromXML(File file) { 959 return unmarshal(hierarchicalStreamDriver.createReader(file), null); 960 } 961 962 /** 963 * Deserialize an object from an XML String, populating the fields of the given root object 964 * instead of instantiating a new one. Note, that this is a special use case! With the 965 * ReflectionConverter XStream will write directly into the raw memory area of the existing 966 * object. Use with care! 967 * 968 * @throws XStreamException if the object cannot be deserialized 969 */ 970 public Object fromXML(String xml, Object root) { 971 return fromXML(new StringReader(xml), root); 972 } 973 974 /** 975 * Deserialize an object from an XML Reader, populating the fields of the given root object 976 * instead of instantiating a new one. Note, that this is a special use case! With the 977 * ReflectionConverter XStream will write directly into the raw memory area of the existing 978 * object. Use with care! 979 * 980 * @throws XStreamException if the object cannot be deserialized 981 */ 982 public Object fromXML(Reader xml, Object root) { 983 return unmarshal(hierarchicalStreamDriver.createReader(xml), root); 984 } 985 986 /** 987 * Deserialize an object from a URL, populating the fields of the given root 988 * object instead of instantiating a new one. Note, that this is a special use case! With 989 * the ReflectionConverter XStream will write directly into the raw memory area of the 990 * existing object. Use with care! 991 * 992 * Depending on the parser implementation, some might take the file path as SystemId to 993 * resolve additional references. 994 * 995 * @throws XStreamException if the object cannot be deserialized 996 * @since 1.4 997 */ 998 public Object fromXML(URL url, Object root) { 999 return unmarshal(hierarchicalStreamDriver.createReader(url), root); 1000 } 1001 1002 /** 1003 * Deserialize an object from a file, populating the fields of the given root 1004 * object instead of instantiating a new one. Note, that this is a special use case! With 1005 * the ReflectionConverter XStream will write directly into the raw memory area of the 1006 * existing object. Use with care! 1007 * 1008 * Depending on the parser implementation, some might take the file path as SystemId to 1009 * resolve additional references. 1010 * 1011 * @throws XStreamException if the object cannot be deserialized 1012 * @since 1.4 1013 */ 1014 public Object fromXML(File file, Object root) { 1015 return unmarshal(hierarchicalStreamDriver.createReader(file), root); 1016 } 1017 1018 /** 1019 * Deserialize an object from an XML InputStream, populating the fields of the given root 1020 * object instead of instantiating a new one. Note, that this is a special use case! With 1021 * the ReflectionConverter XStream will write directly into the raw memory area of the 1022 * existing object. Use with care! 1023 * 1024 * @throws XStreamException if the object cannot be deserialized 1025 */ 1026 public Object fromXML(InputStream input, Object root) { 1027 return unmarshal(hierarchicalStreamDriver.createReader(input), root); 1028 } 1029 1030 /** 1031 * Deserialize an object from a hierarchical data structure (such as XML). 1032 * 1033 * @throws XStreamException if the object cannot be deserialized 1034 */ 1035 public Object unmarshal(HierarchicalStreamReader reader) { 1036 return unmarshal(reader, null, null); 1037 } 1038 1039 /** 1040 * Deserialize an object from a hierarchical data structure (such as XML), populating the 1041 * fields of the given root object instead of instantiating a new one. Note, that this is a 1042 * special use case! With the ReflectionConverter XStream will write directly into the raw 1043 * memory area of the existing object. Use with care! 1044 * 1045 * @throws XStreamException if the object cannot be deserialized 1046 */ 1047 public Object unmarshal(HierarchicalStreamReader reader, Object root) { 1048 return unmarshal(reader, root, null); 1049 } 1050 1051 /** 1052 * Deserialize an object from a hierarchical data structure (such as XML). 1053 * 1054 * @param root If present, the passed in object will have its fields populated, as opposed 1055 * to XStream creating a new instance. Note, that this is a special use case! 1056 * With the ReflectionConverter XStream will write directly into the raw memory 1057 * area of the existing object. Use with care! 1058 * @param dataHolder Extra data you can use to pass to your converters. Use this as you 1059 * want. If not present, XStream shall create one lazily as needed. 1060 * @throws XStreamException if the object cannot be deserialized 1061 */ 1062 public Object unmarshal(HierarchicalStreamReader reader, Object root, DataHolder dataHolder) { 1063 try { 1064 return marshallingStrategy.unmarshal( 1065 root, reader, dataHolder, converterLookup, mapper); 1066 1067 } catch (ConversionException e) { 1068 Package pkg = getClass().getPackage(); 1069 e.add("version", pkg != null ? pkg.getImplementationVersion() : "not available"); 1070 throw e; 1071 } 1072 } 1073 1074 /** 1075 * Alias a Class to a shorter name to be used in XML elements. 1076 * 1077 * @param name Short name 1078 * @param type Type to be aliased 1079 * @throws InitializationException if no {@link ClassAliasingMapper} is available 1080 */ 1081 public void alias(String name, Class type) { 1082 if (classAliasingMapper == null) { 1083 throw new com.thoughtworks.xstream.InitializationException("No " 1084 + ClassAliasingMapper.class.getName() 1085 + " available"); 1086 } 1087 classAliasingMapper.addClassAlias(name, type); 1088 } 1089 1090 /** 1091 * Alias a type to a shorter name to be used in XML elements. Any class that is assignable 1092 * to this type will be aliased to the same name. 1093 * 1094 * @param name Short name 1095 * @param type Type to be aliased 1096 * @since 1.2 1097 * @throws InitializationException if no {@link ClassAliasingMapper} is available 1098 */ 1099 public void aliasType(String name, Class type) { 1100 if (classAliasingMapper == null) { 1101 throw new com.thoughtworks.xstream.InitializationException("No " 1102 + ClassAliasingMapper.class.getName() 1103 + " available"); 1104 } 1105 classAliasingMapper.addTypeAlias(name, type); 1106 } 1107 1108 /** 1109 * Alias a Class to a shorter name to be used in XML elements. 1110 * 1111 * @param name Short name 1112 * @param type Type to be aliased 1113 * @param defaultImplementation Default implementation of type to use if no other specified. 1114 * @throws InitializationException if no {@link DefaultImplementationsMapper} or no 1115 * {@link ClassAliasingMapper} is available 1116 */ 1117 public void alias(String name, Class type, Class defaultImplementation) { 1118 alias(name, type); 1119 addDefaultImplementation(defaultImplementation, type); 1120 } 1121 1122 /** 1123 * Alias a package to a shorter name to be used in XML elements. 1124 * 1125 * @param name Short name 1126 * @param pkgName package to be aliased 1127 * @throws InitializationException if no {@link DefaultImplementationsMapper} or no 1128 * {@link PackageAliasingMapper} is available 1129 * @since 1.3.1 1130 */ 1131 public void aliasPackage(String name, String pkgName) { 1132 if (packageAliasingMapper == null) { 1133 throw new com.thoughtworks.xstream.InitializationException("No " 1134 + PackageAliasingMapper.class.getName() 1135 + " available"); 1136 } 1137 packageAliasingMapper.addPackageAlias(name, pkgName); 1138 } 1139 1140 /** 1141 * Create an alias for a field name. 1142 * 1143 * @param alias the alias itself 1144 * @param definedIn the type that declares the field 1145 * @param fieldName the name of the field 1146 * @throws InitializationException if no {@link FieldAliasingMapper} is available 1147 */ 1148 public void aliasField(String alias, Class definedIn, String fieldName) { 1149 if (fieldAliasingMapper == null) { 1150 throw new com.thoughtworks.xstream.InitializationException("No " 1151 + FieldAliasingMapper.class.getName() 1152 + " available"); 1153 } 1154 fieldAliasingMapper.addFieldAlias(alias, definedIn, fieldName); 1155 } 1156 1157 /** 1158 * Create an alias for an attribute 1159 * 1160 * @param alias the alias itself 1161 * @param attributeName the name of the attribute 1162 * @throws InitializationException if no {@link AttributeAliasingMapper} is available 1163 */ 1164 public void aliasAttribute(String alias, String attributeName) { 1165 if (attributeAliasingMapper == null) { 1166 throw new com.thoughtworks.xstream.InitializationException("No " 1167 + AttributeAliasingMapper.class.getName() 1168 + " available"); 1169 } 1170 attributeAliasingMapper.addAliasFor(attributeName, alias); 1171 } 1172 1173 /** 1174 * Create an alias for a system attribute. XStream will not write a system attribute if its 1175 * alias is set to <code>null</code>. However, this is not reversible, i.e. deserialization 1176 * of the result is likely to fail afterwards and will not produce an object equal to the 1177 * originally written one. 1178 * 1179 * @param alias the alias itself (may be <code>null</code>) 1180 * @param systemAttributeName the name of the system attribute 1181 * @throws InitializationException if no {@link SystemAttributeAliasingMapper} is available 1182 * @since 1.3.1 1183 */ 1184 public void aliasSystemAttribute(String alias, String systemAttributeName) { 1185 if (systemAttributeAliasingMapper == null) { 1186 throw new com.thoughtworks.xstream.InitializationException("No " 1187 + SystemAttributeAliasingMapper.class.getName() 1188 + " available"); 1189 } 1190 systemAttributeAliasingMapper.addAliasFor(systemAttributeName, alias); 1191 } 1192 1193 /** 1194 * Create an alias for an attribute. 1195 * 1196 * @param definedIn the type where the attribute is defined 1197 * @param attributeName the name of the attribute 1198 * @param alias the alias itself 1199 * @throws InitializationException if no {@link AttributeAliasingMapper} is available 1200 * @since 1.2.2 1201 */ 1202 public void aliasAttribute(Class definedIn, String attributeName, String alias) { 1203 aliasField(alias, definedIn, attributeName); 1204 useAttributeFor(definedIn, attributeName); 1205 } 1206 1207 /** 1208 * Use an attribute for a field or a specific type. 1209 * 1210 * @param fieldName the name of the field 1211 * @param type the Class of the type to be rendered as XML attribute 1212 * @throws InitializationException if no {@link AttributeMapper} is available 1213 * @since 1.2 1214 */ 1215 public void useAttributeFor(String fieldName, Class type) { 1216 if (attributeMapper == null) { 1217 throw new com.thoughtworks.xstream.InitializationException("No " 1218 + AttributeMapper.class.getName() 1219 + " available"); 1220 } 1221 attributeMapper.addAttributeFor(fieldName, type); 1222 } 1223 1224 /** 1225 * Use an attribute for a field declared in a specific type. 1226 * 1227 * @param fieldName the name of the field 1228 * @param definedIn the Class containing such field 1229 * @throws InitializationException if no {@link AttributeMapper} is available 1230 * @since 1.2.2 1231 */ 1232 public void useAttributeFor(Class definedIn, String fieldName) { 1233 if (attributeMapper == null) { 1234 throw new com.thoughtworks.xstream.InitializationException("No " 1235 + AttributeMapper.class.getName() 1236 + " available"); 1237 } 1238 attributeMapper.addAttributeFor(definedIn, fieldName); 1239 } 1240 1241 /** 1242 * Use an attribute for an arbitrary type. 1243 * 1244 * @param type the Class of the type to be rendered as XML attribute 1245 * @throws InitializationException if no {@link AttributeMapper} is available 1246 * @since 1.2 1247 */ 1248 public void useAttributeFor(Class type) { 1249 if (attributeMapper == null) { 1250 throw new com.thoughtworks.xstream.InitializationException("No " 1251 + AttributeMapper.class.getName() 1252 + " available"); 1253 } 1254 attributeMapper.addAttributeFor(type); 1255 } 1256 1257 /** 1258 * Associate a default implementation of a class with an object. Whenever XStream encounters 1259 * an instance of this type, it will use the default implementation instead. For example, 1260 * java.util.ArrayList is the default implementation of java.util.List. 1261 * 1262 * @param defaultImplementation 1263 * @param ofType 1264 * @throws InitializationException if no {@link DefaultImplementationsMapper} is available 1265 */ 1266 public void addDefaultImplementation(Class defaultImplementation, Class ofType) { 1267 if (defaultImplementationsMapper == null) { 1268 throw new com.thoughtworks.xstream.InitializationException("No " 1269 + DefaultImplementationsMapper.class.getName() 1270 + " available"); 1271 } 1272 defaultImplementationsMapper.addDefaultImplementation(defaultImplementation, ofType); 1273 } 1274 1275 /** 1276 * Add immutable types. The value of the instances of these types will always be written 1277 * into the stream even if they appear multiple times. 1278 * 1279 * @throws InitializationException if no {@link ImmutableTypesMapper} is available 1280 */ 1281 public void addImmutableType(Class type) { 1282 if (immutableTypesMapper == null) { 1283 throw new com.thoughtworks.xstream.InitializationException("No " 1284 + ImmutableTypesMapper.class.getName() 1285 + " available"); 1286 } 1287 immutableTypesMapper.addImmutableType(type); 1288 } 1289 1290 public void registerConverter(Converter converter) { 1291 registerConverter(converter, PRIORITY_NORMAL); 1292 } 1293 1294 public void registerConverter(Converter converter, int priority) { 1295 if (converterRegistry != null) { 1296 converterRegistry.registerConverter(converter, priority); 1297 } 1298 } 1299 1300 public void registerConverter(SingleValueConverter converter) { 1301 registerConverter(converter, PRIORITY_NORMAL); 1302 } 1303 1304 public void registerConverter(SingleValueConverter converter, int priority) { 1305 if (converterRegistry != null) { 1306 converterRegistry.registerConverter( 1307 new SingleValueConverterWrapper(converter), priority); 1308 } 1309 } 1310 1311 /** 1312 * Register a local {@link Converter} for a field. 1313 * 1314 * @param definedIn the class type the field is defined in 1315 * @param fieldName the field name 1316 * @param converter the converter to use 1317 * @since 1.3 1318 */ 1319 public void registerLocalConverter(Class definedIn, String fieldName, Converter converter) { 1320 if (localConversionMapper == null) { 1321 throw new com.thoughtworks.xstream.InitializationException("No " 1322 + LocalConversionMapper.class.getName() 1323 + " available"); 1324 } 1325 localConversionMapper.registerLocalConverter(definedIn, fieldName, converter); 1326 } 1327 1328 /** 1329 * Register a local {@link SingleValueConverter} for a field. 1330 * 1331 * @param definedIn the class type the field is defined in 1332 * @param fieldName the field name 1333 * @param converter the converter to use 1334 * @since 1.3 1335 */ 1336 public void registerLocalConverter(Class definedIn, String fieldName, 1337 SingleValueConverter converter) { 1338 registerLocalConverter( 1339 definedIn, fieldName, (Converter)new SingleValueConverterWrapper(converter)); 1340 } 1341 1342 /** 1343 * Retrieve the {@link Mapper}. This is by default a chain of {@link MapperWrapper 1344 * MapperWrappers}. 1345 * 1346 * @return the mapper 1347 * @since 1.2 1348 */ 1349 public Mapper getMapper() { 1350 return mapper; 1351 } 1352 1353 /** 1354 * Retrieve the {@link ReflectionProvider} in use. 1355 * 1356 * @return the mapper 1357 * @since 1.2.1 1358 */ 1359 public ReflectionProvider getReflectionProvider() { 1360 return reflectionProvider; 1361 } 1362 1363 public ConverterLookup getConverterLookup() { 1364 return converterLookup; 1365 } 1366 1367 /** 1368 * Change mode for dealing with duplicate references. Valid values are 1369 * <code>XPATH_ABSOLUTE_REFERENCES</code>, <code>XPATH_RELATIVE_REFERENCES</code>, 1370 * <code>XStream.ID_REFERENCES</code> and <code>XStream.NO_REFERENCES</code>. 1371 * 1372 * @throws IllegalArgumentException if the mode is not one of the declared types 1373 * @see #XPATH_ABSOLUTE_REFERENCES 1374 * @see #XPATH_RELATIVE_REFERENCES 1375 * @see #ID_REFERENCES 1376 * @see #NO_REFERENCES 1377 */ 1378 public void setMode(int mode) { 1379 switch (mode) { 1380 case NO_REFERENCES: 1381 setMarshallingStrategy(new TreeMarshallingStrategy()); 1382 break; 1383 case ID_REFERENCES: 1384 setMarshallingStrategy(new ReferenceByIdMarshallingStrategy()); 1385 break; 1386 case XPATH_RELATIVE_REFERENCES: 1387 setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy( 1388 ReferenceByXPathMarshallingStrategy.RELATIVE)); 1389 break; 1390 case XPATH_ABSOLUTE_REFERENCES: 1391 setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy( 1392 ReferenceByXPathMarshallingStrategy.ABSOLUTE)); 1393 break; 1394 case SINGLE_NODE_XPATH_RELATIVE_REFERENCES: 1395 setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy( 1396 ReferenceByXPathMarshallingStrategy.RELATIVE 1397 | ReferenceByXPathMarshallingStrategy.SINGLE_NODE)); 1398 break; 1399 case SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES: 1400 setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy( 1401 ReferenceByXPathMarshallingStrategy.ABSOLUTE 1402 | ReferenceByXPathMarshallingStrategy.SINGLE_NODE)); 1403 break; 1404 default: 1405 throw new IllegalArgumentException("Unknown mode : " + mode); 1406 } 1407 } 1408 1409 /** 1410 * Adds a default implicit collection which is used for any unmapped XML tag. 1411 * 1412 * @param ownerType class owning the implicit collection 1413 * @param fieldName name of the field in the ownerType. This field must be a concrete 1414 * collection type or matching the default implementation type of the collection 1415 * type. 1416 */ 1417 public void addImplicitCollection(Class ownerType, String fieldName) { 1418 addImplicitCollection(ownerType, fieldName, null, null); 1419 } 1420 1421 /** 1422 * Adds implicit collection which is used for all items of the given itemType. 1423 * 1424 * @param ownerType class owning the implicit collection 1425 * @param fieldName name of the field in the ownerType. This field must be a concrete 1426 * collection type or matching the default implementation type of the collection 1427 * type. 1428 * @param itemType type of the items to be part of this collection 1429 * @throws InitializationException if no {@link ImplicitCollectionMapper} is available 1430 */ 1431 public void addImplicitCollection(Class ownerType, String fieldName, Class itemType) { 1432 addImplicitCollection(ownerType, fieldName, null, itemType); 1433 } 1434 1435 /** 1436 * Adds implicit collection which is used for all items of the given element name defined by 1437 * itemFieldName. 1438 * 1439 * @param ownerType class owning the implicit collection 1440 * @param fieldName name of the field in the ownerType. This field must be a concrete 1441 * collection type or matching the default implementation type of the collection 1442 * type. 1443 * @param itemFieldName element name of the implicit collection 1444 * @param itemType item type to be aliases be the itemFieldName 1445 * @throws InitializationException if no {@link ImplicitCollectionMapper} is available 1446 */ 1447 public void addImplicitCollection(Class ownerType, String fieldName, String itemFieldName, 1448 Class itemType) { 1449 addImplicitMap(ownerType, fieldName, itemFieldName, itemType, null); 1450 } 1451 1452 /** 1453 * Adds an implicit array. 1454 * 1455 * @param ownerType class owning the implicit array 1456 * @param fieldName name of the array field 1457 * @since 1.4 1458 */ 1459 public void addImplicitArray(Class ownerType, String fieldName) { 1460 addImplicitCollection(ownerType, fieldName); 1461 } 1462 1463 /** 1464 * Adds an implicit array which is used for all items of the given itemType when the array 1465 * type matches. 1466 * 1467 * @param ownerType class owning the implicit array 1468 * @param fieldName name of the array field in the ownerType 1469 * @param itemType type of the items to be part of this array 1470 * @throws InitializationException if no {@link ImplicitCollectionMapper} is available or the 1471 * array type does not match the itemType 1472 * @since 1.4 1473 */ 1474 public void addImplicitArray(Class ownerType, String fieldName, Class itemType) { 1475 addImplicitCollection(ownerType, fieldName, itemType); 1476 } 1477 1478 /** 1479 * Adds an implicit array which is used for all items of the given element name defined by 1480 * itemName. 1481 * 1482 * @param ownerType class owning the implicit array 1483 * @param fieldName name of the array field in the ownerType 1484 * @param itemName alias name of the items 1485 * @throws InitializationException if no {@link ImplicitCollectionMapper} is available 1486 * @since 1.4 1487 */ 1488 public void addImplicitArray(Class ownerType, String fieldName, String itemName) { 1489 addImplicitCollection(ownerType, fieldName, itemName, null); 1490 } 1491 1492 /** 1493 * Adds an implicit map. 1494 * 1495 * @param ownerType class owning the implicit map 1496 * @param fieldName name of the field in the ownerType. This field must be a concrete 1497 * map type or matching the default implementation type of the map 1498 * type. 1499 * @param itemType type of the items to be part of this map as value 1500 * @param keyFieldName the name of the filed of the itemType that is used for the key in the map 1501 * @since 1.4 1502 */ 1503 public void addImplicitMap(Class ownerType, String fieldName, Class itemType, String keyFieldName) { 1504 addImplicitMap(ownerType, fieldName, null, itemType, keyFieldName); 1505 } 1506 1507 /** 1508 * Adds an implicit map. 1509 * 1510 * @param ownerType class owning the implicit map 1511 * @param fieldName name of the field in the ownerType. This field must be a concrete 1512 * map type or matching the default implementation type of the map 1513 * type. 1514 * @param itemType type of the items to be part of this map as value 1515 * @param keyFieldName the name of the filed of the itemType that is used for the key in the map 1516 * @since 1.4 1517 */ 1518 public void addImplicitMap(Class ownerType, String fieldName, String itemFieldName, 1519 Class itemType, String keyFieldName) { 1520 if (implicitCollectionMapper == null) { 1521 throw new com.thoughtworks.xstream.InitializationException("No " 1522 + ImplicitCollectionMapper.class.getName() 1523 + " available"); 1524 } 1525 implicitCollectionMapper.add(ownerType, fieldName, itemFieldName, itemType, keyFieldName); 1526 } 1527 1528 /** 1529 * Create a DataHolder that can be used to pass data to the converters. The DataHolder is 1530 * provided with a call to {@link #marshal(Object, HierarchicalStreamWriter, DataHolder)} or 1531 * {@link #unmarshal(HierarchicalStreamReader, Object, DataHolder)}. 1532 * 1533 * @return a new {@link DataHolder} 1534 */ 1535 public DataHolder newDataHolder() { 1536 return new MapBackedDataHolder(); 1537 } 1538 1539 /** 1540 * Creates an ObjectOutputStream that serializes a stream of objects to the writer using 1541 * XStream. 1542 * <p> 1543 * To change the name of the root element (from <object-stream>), use 1544 * {@link #createObjectOutputStream(java.io.Writer, String)}. 1545 * </p> 1546 * 1547 * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, 1548 * String) 1549 * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) 1550 * @since 1.0.3 1551 */ 1552 public ObjectOutputStream createObjectOutputStream(Writer writer) throws IOException { 1553 return createObjectOutputStream( 1554 hierarchicalStreamDriver.createWriter(writer), "object-stream"); 1555 } 1556 1557 /** 1558 * Creates an ObjectOutputStream that serializes a stream of objects to the writer using 1559 * XStream. 1560 * <p> 1561 * To change the name of the root element (from <object-stream>), use 1562 * {@link #createObjectOutputStream(java.io.Writer, String)}. 1563 * </p> 1564 * 1565 * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, 1566 * String) 1567 * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) 1568 * @since 1.0.3 1569 */ 1570 public ObjectOutputStream createObjectOutputStream(HierarchicalStreamWriter writer) 1571 throws IOException { 1572 return createObjectOutputStream(writer, "object-stream"); 1573 } 1574 1575 /** 1576 * Creates an ObjectOutputStream that serializes a stream of objects to the writer using 1577 * XStream. 1578 * 1579 * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, 1580 * String) 1581 * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) 1582 * @since 1.0.3 1583 */ 1584 public ObjectOutputStream createObjectOutputStream(Writer writer, String rootNodeName) 1585 throws IOException { 1586 return createObjectOutputStream( 1587 hierarchicalStreamDriver.createWriter(writer), rootNodeName); 1588 } 1589 1590 /** 1591 * Creates an ObjectOutputStream that serializes a stream of objects to the OutputStream 1592 * using XStream. 1593 * <p> 1594 * To change the name of the root element (from <object-stream>), use 1595 * {@link #createObjectOutputStream(java.io.Writer, String)}. 1596 * </p> 1597 * 1598 * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, 1599 * String) 1600 * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) 1601 * @since 1.3 1602 */ 1603 public ObjectOutputStream createObjectOutputStream(OutputStream out) throws IOException { 1604 return createObjectOutputStream( 1605 hierarchicalStreamDriver.createWriter(out), "object-stream"); 1606 } 1607 1608 /** 1609 * Creates an ObjectOutputStream that serializes a stream of objects to the OutputStream 1610 * using XStream. 1611 * 1612 * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, 1613 * String) 1614 * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) 1615 * @since 1.3 1616 */ 1617 public ObjectOutputStream createObjectOutputStream(OutputStream out, String rootNodeName) 1618 throws IOException { 1619 return createObjectOutputStream( 1620 hierarchicalStreamDriver.createWriter(out), rootNodeName); 1621 } 1622 1623 /** 1624 * Creates an ObjectOutputStream that serializes a stream of objects to the writer using 1625 * XStream. 1626 * <p> 1627 * Because an ObjectOutputStream can contain multiple items and XML only allows a single 1628 * root node, the stream must be written inside an enclosing node. 1629 * </p> 1630 * <p> 1631 * It is necessary to call ObjectOutputStream.close() when done, otherwise the stream will 1632 * be incomplete. 1633 * </p> 1634 * <h3>Example</h3> 1635 * 1636 * <pre> 1637 * ObjectOutputStream out = xstream.createObjectOutputStream(aWriter, "things"); 1638 * out.writeInt(123); 1639 * out.writeObject("Hello"); 1640 * out.writeObject(someObject) 1641 * out.close(); 1642 * </pre> 1643 * 1644 * @param writer The writer to serialize the objects to. 1645 * @param rootNodeName The name of the root node enclosing the stream of objects. 1646 * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) 1647 * @since 1.0.3 1648 */ 1649 public ObjectOutputStream createObjectOutputStream(final HierarchicalStreamWriter writer, 1650 String rootNodeName) throws IOException { 1651 final StatefulWriter statefulWriter = new StatefulWriter(writer); 1652 statefulWriter.startNode(rootNodeName, null); 1653 return new CustomObjectOutputStream(new CustomObjectOutputStream.StreamCallback() { 1654 public void writeToStream(Object object) { 1655 marshal(object, statefulWriter); 1656 } 1657 1658 public void writeFieldsToStream(Map fields) throws NotActiveException { 1659 throw new NotActiveException("not in call to writeObject"); 1660 } 1661 1662 public void defaultWriteObject() throws NotActiveException { 1663 throw new NotActiveException("not in call to writeObject"); 1664 } 1665 1666 public void flush() { 1667 statefulWriter.flush(); 1668 } 1669 1670 public void close() { 1671 if (statefulWriter.state() != StatefulWriter.STATE_CLOSED) { 1672 statefulWriter.endNode(); 1673 statefulWriter.close(); 1674 } 1675 } 1676 }); 1677 } 1678 1679 /** 1680 * Creates an ObjectInputStream that deserializes a stream of objects from a reader using 1681 * XStream. 1682 * 1683 * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) 1684 * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, 1685 * String) 1686 * @since 1.0.3 1687 */ 1688 public ObjectInputStream createObjectInputStream(Reader xmlReader) throws IOException { 1689 return createObjectInputStream(hierarchicalStreamDriver.createReader(xmlReader)); 1690 } 1691 1692 /** 1693 * Creates an ObjectInputStream that deserializes a stream of objects from an InputStream 1694 * using XStream. 1695 * 1696 * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) 1697 * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, 1698 * String) 1699 * @since 1.3 1700 */ 1701 public ObjectInputStream createObjectInputStream(InputStream in) throws IOException { 1702 return createObjectInputStream(hierarchicalStreamDriver.createReader(in)); 1703 } 1704 1705 /** 1706 * Creates an ObjectInputStream that deserializes a stream of objects from a reader using 1707 * XStream. <h3>Example</h3> 1708 * 1709 * <pre> 1710 * ObjectInputStream in = xstream.createObjectOutputStream(aReader); 1711 * int a = out.readInt(); 1712 * Object b = out.readObject(); 1713 * Object c = out.readObject(); 1714 * </pre> 1715 * 1716 * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, 1717 * String) 1718 * @since 1.0.3 1719 */ 1720 public ObjectInputStream createObjectInputStream(final HierarchicalStreamReader reader) 1721 throws IOException { 1722 return new CustomObjectInputStream(new CustomObjectInputStream.StreamCallback() { 1723 public Object readFromStream() throws EOFException { 1724 if (!reader.hasMoreChildren()) { 1725 throw new EOFException(); 1726 } 1727 reader.moveDown(); 1728 Object result = unmarshal(reader); 1729 reader.moveUp(); 1730 return result; 1731 } 1732 1733 public Map readFieldsFromStream() throws IOException { 1734 throw new NotActiveException("not in call to readObject"); 1735 } 1736 1737 public void defaultReadObject() throws NotActiveException { 1738 throw new NotActiveException("not in call to readObject"); 1739 } 1740 1741 public void registerValidation(ObjectInputValidation validation, int priority) 1742 throws NotActiveException { 1743 throw new NotActiveException("stream inactive"); 1744 } 1745 1746 public void close() { 1747 reader.close(); 1748 } 1749 }, classLoaderReference); 1750 } 1751 1752 /** 1753 * Change the ClassLoader XStream uses to load classes. Creating an XStream instance it will 1754 * register for all kind of classes and types of the current JDK, but not for any 3rd party 1755 * type. To ensure that all other types are loaded with your class loader, you should call 1756 * this method as early as possible - or consider to provide the class loader directly in 1757 * the constructor. 1758 * 1759 * @since 1.1.1 1760 */ 1761 public void setClassLoader(ClassLoader classLoader) { 1762 classLoaderReference.setReference(classLoader); 1763 } 1764 1765 /** 1766 * Retrieve the ClassLoader XStream uses to load classes. 1767 * 1768 * @since 1.1.1 1769 */ 1770 public ClassLoader getClassLoader() { 1771 return classLoaderReference.getReference(); 1772 } 1773 1774 /** 1775 * Add pattern for unknown element names to ignore. 1776 * 1777 * @param pattern the name pattern as regular expression 1778 * @since 1.4.5 1779 */ 1780 private void ignoreUnknownElements(Pattern pattern) { 1781 if (fieldAliasingMapper == null) { 1782 throw new com.thoughtworks.xstream.InitializationException("No " 1783 + FieldAliasingMapper.class.getName() 1784 + " available"); 1785 } 1786 fieldAliasingMapper.addFieldsToIgnore(pattern); 1787 } 1788 1789 /** 1790 * Process the annotations of the given types and configure the XStream. 1791 * 1792 * @param types the types with XStream annotations 1793 * @since 1.3 1794 */ 1795 public void processAnnotations(final Class[] types) { 1796 if (annotationConfiguration == null) { 1797 throw new com.thoughtworks.xstream.InitializationException("No " 1798 + ANNOTATION_MAPPER_TYPE 1799 + " available"); 1800 } 1801 annotationConfiguration.processAnnotations(types); 1802 } 1803 1804 /** 1805 * Process the annotations of the given type and configure the XStream. A call of this 1806 * method will automatically turn the auto-detection mode for annotations off. 1807 * 1808 * @param type the type with XStream annotations 1809 * @since 1.3 1810 */ 1811 public void processAnnotations(final Class type) { 1812 processAnnotations(new Class[]{type}); 1813 } 1814 1815 /** 1816 * Set the auto-detection mode of the AnnotationMapper. Note that auto-detection implies 1817 * that the XStream is configured while it is processing the XML steams. This is a potential 1818 * concurrency problem. Also is it technically not possible to detect all class aliases at 1819 * deserialization. You have been warned! 1820 * 1821 * @param mode <code>true</code> if annotations are auto-detected 1822 * @since 1.3 1823 */ 1824 public void autodetectAnnotations(boolean mode) { 1825 if (annotationConfiguration != null) { 1826 annotationConfiguration.autodetectAnnotations(mode); 1827 } 1828 } 1829 1830 /** 1831 * Add a new security permission. 1832 * 1833 * <p> 1834 * Permissions are evaluated in the added sequence. An instance of {@link NoTypePermission} or 1835 * {@link AnyTypePermission} will implicitly wipe any existing permission. 1836 * </p> 1837 * 1838 * @param permission the permission to add 1839 * @since 1.4.7 1840 */ 1841 public void addPermission(TypePermission permission) { 1842 if (securityMapper != null) { 1843 securityMapper.addPermission(permission); 1844 } 1845 } 1846 1847 public void allowTypesByWildcard(String[] patterns) { 1848 addPermission(new WildcardTypePermission(patterns)); 1849 } 1850 1851 /** 1852 * Add security permission for explicit types by name. 1853 * 1854 * @param names the type names to allow 1855 * @since 1.4.7 1856 */ 1857 public void allowTypes(String[] names) { 1858 addPermission(new ExplicitTypePermission(names)); 1859 } 1860 1861 /** 1862 * Add security permission for explicit types. 1863 * 1864 * @param types the types to allow 1865 * @since 1.4.7 1866 */ 1867 public void allowTypes(Class[] types) { 1868 addPermission(new ExplicitTypePermission(types)); 1869 } 1870 /** 1871 * Prevents a field from being serialized. To omit a field you must always provide the 1872 * declaring type and not necessarily the type that is converted. 1873 * 1874 * @since 1.1.3 1875 * @throws InitializationException if no {@link FieldAliasingMapper} is available 1876 */ 1877 public void omitField(Class definedIn, String fieldName) { 1878 if (fieldAliasingMapper == null) { 1879 throw new com.thoughtworks.xstream.InitializationException("No " 1880 + FieldAliasingMapper.class.getName() 1881 + " available"); 1882 } 1883 fieldAliasingMapper.omitField(definedIn, fieldName); 1884 } 1885 1886 /** 1887 * Add security permission for a type hierarchy. 1888 * 1889 * @param type the base type to allow 1890 * @since 1.4.7 1891 */ 1892 public void allowTypeHierarchy(Class type) { 1893 addPermission(new TypeHierarchyPermission(type)); 1894 } 1895 /** 1896 * Ignore all unknown elements. 1897 * 1898 * @since 1.4.5 1899 */ 1900 public void ignoreUnknownElements() { 1901 ignoreUnknownElements(IGNORE_ALL); 1902 } 1903 1904 /** 1905 * @deprecated As of 1.3, use {@link InitializationException} instead 1906 */ 1907 public static class InitializationException extends XStreamException { 1908 /** 1909 * @deprecated As of 1.3, use {@link InitializationException} instead 1910 */ 1911 public InitializationException(String message, Throwable cause) { 1912 super(message, cause); 1913 } 1914 1915 /** 1916 * @deprecated As of 1.3, use {@link InitializationException} instead 1917 */ 1918 public InitializationException(String message) { 1919 super(message); 1920 } 1921 } 1922 1923 private Object readResolve() { 1924 jvm = new JVM(); 1925 return this; 1926 } 1927 1928 }