View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.module.xml.transformer;
8   
9   import org.mule.api.lifecycle.InitialisationException;
10  import org.mule.api.transformer.TransformerException;
11  import org.mule.config.i18n.MessageFactory;
12  import org.mule.transformer.AbstractMessageTransformer;
13  
14  import com.thoughtworks.xstream.XStream;
15  import com.thoughtworks.xstream.converters.Converter;
16  
17  import java.util.HashMap;
18  import java.util.HashSet;
19  import java.util.Map;
20  import java.util.Set;
21  
22  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicReference;
23  
24  /**
25   * <code>AbstractXStreamTransformer</code> is a base class for all XStream based
26   * transformers. It takes care of creating and configuring the XStream parser.
27   */
28  
29  public abstract class AbstractXStreamTransformer extends AbstractMessageTransformer
30  {
31      private final AtomicReference/* XStream */xstream = new AtomicReference();
32      private volatile String driverClass = XStreamFactory.XSTREAM_XPP_DRIVER;
33      private volatile Map<String, Class<?>> aliases = new HashMap<String, Class<?>>();
34      private volatile Set<Class <? extends Converter>> converters = new HashSet<Class <? extends Converter>>();
35  
36      @Override
37      public void initialise() throws InitialisationException
38      {
39          super.initialise();
40          try
41          {
42              // Create XStream instance as part of initialization so that we can set
43              // the context classloader that will be required to load classes.
44              XStream xStreamInstance = getXStream();
45              xStreamInstance.setClassLoader(Thread.currentThread().getContextClassLoader());
46          }
47          catch (TransformerException e)
48          {
49              throw new InitialisationException(e, this);
50          }
51      }
52  
53      public final XStream getXStream() throws TransformerException
54      {
55          XStream instance = (XStream) xstream.get();
56  
57          if (instance == null)
58          {
59              try
60              {
61                  instance = new XStreamFactory(driverClass, aliases, converters).getInstance();
62                  if (!xstream.compareAndSet(null, instance))
63                  {
64                      instance = (XStream)xstream.get();
65                  }
66              }
67              catch (Exception e)
68              {
69                  throw new TransformerException(MessageFactory.createStaticMessage("Unable to initialize XStream"), e);
70              }
71          }
72  
73          return instance;
74      }
75  
76      @Override
77      public Object clone() throws CloneNotSupportedException
78      {
79          AbstractXStreamTransformer clone = (AbstractXStreamTransformer) super.clone();
80          clone.setDriverClass(driverClass);
81  
82          if (aliases != null)
83          {
84              clone.setAliases(new HashMap<String, Class<?>>(aliases));
85          }
86  
87          if (converters != null)
88          {
89              clone.setConverters(new HashSet<Class <? extends Converter>>(converters));
90          }
91  
92          return clone;
93      }
94  
95      public String getDriverClass()
96      {
97          return driverClass;
98      }
99  
100     public void setDriverClass(String driverClass)
101     {
102         this.driverClass = driverClass;
103         // force XStream instance update
104         this.xstream.set(null);
105     }
106 
107     public Map<String, Class<?>> getAliases()
108     {
109         return aliases;
110     }
111 
112     public void setAliases(Map<String, Class<?>> aliases)
113     {
114         this.aliases = aliases;
115         // force XStream instance update
116         this.xstream.set(null);
117     }
118 
119     public Set<Class <? extends Converter>> getConverters()
120     {
121         return converters;
122     }
123 
124     public void setConverters(Set<Class <? extends Converter>> converters)
125     {
126         this.converters = converters;
127         // force XStream instance update
128         this.xstream.set(null);
129     }
130 
131     public void addAlias(String alias, Class<?> aClass)
132     {
133         aliases.put(alias, aClass);
134     }
135 
136     public Class<?> removeAlias(String alias)
137     {
138         return aliases.remove(alias);
139     }
140 
141     public void addConverter(Class<? extends Converter> converterClass)
142     {
143         converters.add(converterClass);
144     }
145 
146     public boolean removeAlias(Class<? extends Converter> converterClass)
147     {
148         return converters.remove(converterClass);
149     }
150 }