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 }