View Javadoc

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