View Javadoc

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