View Javadoc

1   /*
2    * $Id: AbstractXStreamTransformer.java 20297 2010-11-22 18:49:18Z 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.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  
26  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicReference;
27  
28  /**
29   * <code>AbstractXStreamTransformer</code> is a base class for all XStream based
30   * transformers. It takes care of creating and configuring the XStream parser.
31   */
32  
33  public abstract class AbstractXStreamTransformer extends AbstractMessageTransformer
34  {
35      private final AtomicReference/* XStream */xstream = new AtomicReference();
36      private volatile String driverClass = XStreamFactory.XSTREAM_XPP_DRIVER;
37      private volatile Map<String, Class> aliases = new HashMap<String, Class>();
38      private volatile Set<Class <? extends Converter>> converters = new HashSet<Class <? extends Converter>>();
39  
40      @Override
41      public void initialise() throws InitialisationException
42      {
43          super.initialise();
44          try
45          {
46              // Create XStream instance as part of initialization so that we can set
47              // the context classloader that will be required to load classes.
48              XStream xStreamInstance = getXStream();
49              xStreamInstance.setClassLoader(Thread.currentThread().getContextClassLoader());
50          }
51          catch (TransformerException e)
52          {
53              throw new InitialisationException(e, this);
54          }
55      }
56      
57      public final XStream getXStream() throws TransformerException
58      {
59          XStream instance = (XStream) xstream.get();
60  
61          if (instance == null)
62          {
63              try
64              {
65                  instance = new XStreamFactory(driverClass, aliases, converters).getInstance();
66                  if (!xstream.compareAndSet(null, instance))
67                  {
68                      instance = (XStream)xstream.get();
69                  }
70              }
71              catch (Exception e)
72              {
73                  throw new TransformerException(MessageFactory.createStaticMessage("Unable to initialize XStream"), e);
74              }
75          }
76  
77          return instance;
78      }
79  
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 }