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>&lt;com.blah.MyThing&gt;</code> to <code>&lt;my-thing&gt;</code> by registering an
174     * alias for the class.
175     * <p>
176     * <hr>
177     * <blockquote>
178     *
179     * <pre>
180     * xstream.alias(&quot;my-thing&quot;, 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&ouml;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 &lt;object-stream&gt;), 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 &lt;object-stream&gt;), 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 &lt;object-stream&gt;), 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, &quot;things&quot;);
1638         *   out.writeInt(123);
1639         *   out.writeObject(&quot;Hello&quot;);
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    }