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 */
012package com.thoughtworks.xstream;
013
014import java.io.EOFException;
015import java.io.File;
016import java.io.IOException;
017import java.io.InputStream;
018import java.io.NotActiveException;
019import java.io.ObjectInputStream;
020import java.io.ObjectInputValidation;
021import java.io.ObjectOutputStream;
022import java.io.OutputStream;
023import java.io.Reader;
024import java.io.StringReader;
025import java.io.StringWriter;
026import java.io.Writer;
027import java.lang.reflect.Constructor;
028import java.lang.reflect.Field;
029import java.lang.reflect.Method;
030import java.math.BigDecimal;
031import java.math.BigInteger;
032import java.net.URI;
033import java.net.URL;
034import java.util.ArrayList;
035import java.util.BitSet;
036import java.util.Calendar;
037import java.util.Collections;
038import java.util.Date;
039import java.util.GregorianCalendar;
040import java.util.HashMap;
041import java.util.HashSet;
042import java.util.Hashtable;
043import java.util.LinkedList;
044import java.util.List;
045import java.util.Locale;
046import java.util.Map;
047import java.util.Properties;
048import java.util.Set;
049import java.util.SortedSet;
050import java.util.TreeMap;
051import java.util.TreeSet;
052import java.util.Vector;
053import java.util.regex.Pattern;
054
055import com.thoughtworks.xstream.converters.ConversionException;
056import com.thoughtworks.xstream.converters.Converter;
057import com.thoughtworks.xstream.converters.ConverterLookup;
058import com.thoughtworks.xstream.converters.ConverterRegistry;
059import com.thoughtworks.xstream.converters.DataHolder;
060import com.thoughtworks.xstream.converters.SingleValueConverter;
061import com.thoughtworks.xstream.converters.SingleValueConverterWrapper;
062import com.thoughtworks.xstream.converters.basic.BigDecimalConverter;
063import com.thoughtworks.xstream.converters.basic.BigIntegerConverter;
064import com.thoughtworks.xstream.converters.basic.BooleanConverter;
065import com.thoughtworks.xstream.converters.basic.ByteConverter;
066import com.thoughtworks.xstream.converters.basic.CharConverter;
067import com.thoughtworks.xstream.converters.basic.DateConverter;
068import com.thoughtworks.xstream.converters.basic.DoubleConverter;
069import com.thoughtworks.xstream.converters.basic.FloatConverter;
070import com.thoughtworks.xstream.converters.basic.IntConverter;
071import com.thoughtworks.xstream.converters.basic.LongConverter;
072import com.thoughtworks.xstream.converters.basic.NullConverter;
073import com.thoughtworks.xstream.converters.basic.ShortConverter;
074import com.thoughtworks.xstream.converters.basic.StringBufferConverter;
075import com.thoughtworks.xstream.converters.basic.StringConverter;
076import com.thoughtworks.xstream.converters.basic.URIConverter;
077import com.thoughtworks.xstream.converters.basic.URLConverter;
078import com.thoughtworks.xstream.converters.collections.ArrayConverter;
079import com.thoughtworks.xstream.converters.collections.BitSetConverter;
080import com.thoughtworks.xstream.converters.collections.CharArrayConverter;
081import com.thoughtworks.xstream.converters.collections.CollectionConverter;
082import com.thoughtworks.xstream.converters.collections.MapConverter;
083import com.thoughtworks.xstream.converters.collections.PropertiesConverter;
084import com.thoughtworks.xstream.converters.collections.SingletonCollectionConverter;
085import com.thoughtworks.xstream.converters.collections.SingletonMapConverter;
086import com.thoughtworks.xstream.converters.collections.TreeMapConverter;
087import com.thoughtworks.xstream.converters.collections.TreeSetConverter;
088import com.thoughtworks.xstream.converters.extended.ColorConverter;
089import com.thoughtworks.xstream.converters.extended.DynamicProxyConverter;
090import com.thoughtworks.xstream.converters.extended.EncodedByteArrayConverter;
091import com.thoughtworks.xstream.converters.extended.FileConverter;
092import com.thoughtworks.xstream.converters.extended.FontConverter;
093import com.thoughtworks.xstream.converters.extended.GregorianCalendarConverter;
094import com.thoughtworks.xstream.converters.extended.JavaClassConverter;
095import com.thoughtworks.xstream.converters.extended.JavaFieldConverter;
096import com.thoughtworks.xstream.converters.extended.JavaMethodConverter;
097import com.thoughtworks.xstream.converters.extended.LocaleConverter;
098import com.thoughtworks.xstream.converters.extended.LookAndFeelConverter;
099import com.thoughtworks.xstream.converters.extended.SqlDateConverter;
100import com.thoughtworks.xstream.converters.extended.SqlTimeConverter;
101import com.thoughtworks.xstream.converters.extended.SqlTimestampConverter;
102import com.thoughtworks.xstream.converters.extended.TextAttributeConverter;
103import com.thoughtworks.xstream.converters.reflection.ExternalizableConverter;
104import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
105import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
106import com.thoughtworks.xstream.converters.reflection.SelfStreamingInstanceChecker;
107import com.thoughtworks.xstream.converters.reflection.SerializableConverter;
108import com.thoughtworks.xstream.core.DefaultConverterLookup;
109import com.thoughtworks.xstream.core.JVM;
110import com.thoughtworks.xstream.core.MapBackedDataHolder;
111import com.thoughtworks.xstream.core.ReferenceByIdMarshallingStrategy;
112import com.thoughtworks.xstream.core.ReferenceByXPathMarshallingStrategy;
113import com.thoughtworks.xstream.core.TreeMarshallingStrategy;
114import com.thoughtworks.xstream.core.util.ClassLoaderReference;
115import com.thoughtworks.xstream.core.util.CompositeClassLoader;
116import com.thoughtworks.xstream.core.util.CustomObjectInputStream;
117import com.thoughtworks.xstream.core.util.CustomObjectOutputStream;
118import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
119import com.thoughtworks.xstream.io.HierarchicalStreamReader;
120import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
121import com.thoughtworks.xstream.io.StatefulWriter;
122import com.thoughtworks.xstream.io.xml.XppDriver;
123import com.thoughtworks.xstream.mapper.AnnotationConfiguration;
124import com.thoughtworks.xstream.mapper.ArrayMapper;
125import com.thoughtworks.xstream.mapper.AttributeAliasingMapper;
126import com.thoughtworks.xstream.mapper.AttributeMapper;
127import com.thoughtworks.xstream.mapper.CachingMapper;
128import com.thoughtworks.xstream.mapper.ClassAliasingMapper;
129import com.thoughtworks.xstream.mapper.DefaultImplementationsMapper;
130import com.thoughtworks.xstream.mapper.DefaultMapper;
131import com.thoughtworks.xstream.mapper.DynamicProxyMapper;
132import com.thoughtworks.xstream.mapper.FieldAliasingMapper;
133import com.thoughtworks.xstream.mapper.ImmutableTypesMapper;
134import com.thoughtworks.xstream.mapper.ImplicitCollectionMapper;
135import com.thoughtworks.xstream.mapper.LocalConversionMapper;
136import com.thoughtworks.xstream.mapper.Mapper;
137import com.thoughtworks.xstream.mapper.MapperWrapper;
138import com.thoughtworks.xstream.mapper.OuterClassMapper;
139import com.thoughtworks.xstream.mapper.PackageAliasingMapper;
140import com.thoughtworks.xstream.mapper.SystemAttributeAliasingMapper;
141import com.thoughtworks.xstream.mapper.XStream11XmlFriendlyMapper;
142import com.thoughtworks.xstream.security.AnyTypePermission;
143import com.thoughtworks.xstream.security.ExplicitTypePermission;
144import com.thoughtworks.xstream.security.NoPermission;
145import com.thoughtworks.xstream.security.NoTypePermission;
146import com.thoughtworks.xstream.security.RegExpTypePermission;
147import com.thoughtworks.xstream.security.TypeHierarchyPermission;
148import com.thoughtworks.xstream.security.TypePermission;
149import com.thoughtworks.xstream.security.WildcardTypePermission;
150import 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 */
299public 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}