View Javadoc

1   /*
2    * $Id: XStreamFactory.java 21944 2011-05-18 15:10:28Z aperepel $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.module.xml.transformer;
12  
13  import org.mule.util.ClassUtils;
14  
15  import com.thoughtworks.xstream.XStream;
16  import com.thoughtworks.xstream.converters.Converter;
17  import com.thoughtworks.xstream.converters.SingleValueConverter;
18  import com.thoughtworks.xstream.converters.collections.MapConverter;
19  import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
20  import com.thoughtworks.xstream.mapper.Mapper;
21  
22  import java.util.Map;
23  import java.util.Set;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  /**
29   * Initializes the XStream utility for converting Objects to XML and XML to Objects.
30   */
31  // @Immutable
32  public class XStreamFactory
33  {
34      public static final String XSTREAM_DOM_DRIVER = "com.thoughtworks.xstream.io.xml.DomDriver";
35      public static final String XSTREAM_DOM4J_DRIVER = "com.thoughtworks.xstream.io.xml.Dom4JDriver";
36      public static final String XSTREAM_JDOM_DRIVER = "com.thoughtworks.xstream.io.xml.JDomDriver";
37      public static final String XSTREAM_STAX_DRIVER = "com.thoughtworks.xstream.io.xml.StaxDriver";
38      public static final String XSTREAM_XPP_DRIVER = "com.thoughtworks.xstream.io.xml.XppDriver";
39  
40      private static final Log logger = LogFactory.getLog(XStreamFactory.class);
41  
42      private final XStream xstream;
43  
44      public XStreamFactory() throws ClassNotFoundException, InstantiationException, IllegalAccessException
45      {
46          this(XSTREAM_XPP_DRIVER, null, null);
47      }
48  
49      public XStreamFactory(String driverClassName, Map<String, Class<?>> aliases, Set<Class <? extends Converter>> converters)
50          throws ClassNotFoundException, InstantiationException, IllegalAccessException
51      {
52          Class<?> driverClass = ClassUtils.loadClass(driverClassName, this.getClass());
53          xstream = new XStream((HierarchicalStreamDriver) driverClass.newInstance());
54  
55          // We must always register this converter as the Mule Message uses
56          // ConcurrentHashMaps, but XStream currently does not support them out of the
57          // box.
58          xstream.registerConverter(new XStreamFactory.ConcurrentHashMapConverter(xstream.getMapper()), -1);
59  
60          registerAliases(aliases);
61          registerConverters(converters);
62      }
63  
64      private void registerAliases(Map<String, Class<?>> aliases)
65      {
66          if (aliases != null)
67          {
68              for (Map.Entry<String, Class<?>> entry : aliases.entrySet())
69              {
70                  xstream.alias(entry.getKey(), entry.getValue());
71              }
72          }
73      }
74  
75      private void registerConverters(Set<Class <? extends Converter>> converters) throws InstantiationException, IllegalAccessException
76      {
77          if (converters != null)
78          {
79              for (Class<?> converter : converters)
80              {
81                  Object converterInstance = converter.newInstance();
82                  if (converterInstance instanceof Converter)
83                  {
84                      xstream.registerConverter((Converter) converterInstance);
85                  }
86                  else if (converterInstance instanceof SingleValueConverter)
87                  {
88                      xstream.registerConverter((SingleValueConverter) converterInstance);
89                  }
90                  else
91                  {
92                      logger.warn("Invalid converter class specified - ignoring: " + converter.getName());
93                  }
94              }
95          }
96      }
97  
98      public final XStream getInstance()
99      {
100         return xstream;
101     }
102 
103     private class ConcurrentHashMapConverter extends MapConverter
104     {
105         public ConcurrentHashMapConverter(Mapper mapper) throws ClassNotFoundException
106         {
107             super(mapper);
108         }
109 
110         @Override
111         @SuppressWarnings("rawtypes")
112         public boolean canConvert(Class aClass)
113         {
114             String className = aClass.getName();
115             return className.equals("java.util.concurrent.ConcurrentHashMap");
116         }
117     }
118 }