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.json.transformers;
8   
9   import org.mule.api.MuleMessage;
10  import org.mule.api.lifecycle.InitialisationException;
11  import org.mule.api.transformer.TransformerException;
12  import org.mule.module.json.filters.IsJsonFilter;
13  import org.mule.transformer.types.DataTypeFactory;
14  
15  import org.apache.commons.logging.Log;
16  import org.apache.commons.logging.LogFactory;
17  
18  import java.io.IOException;
19  import java.io.StringWriter;
20  import java.io.UnsupportedEncodingException;
21  import java.util.ArrayList;
22  import java.util.HashMap;
23  import java.util.List;
24  import java.util.Map;
25  
26  /**
27   * Converts a java object to a JSON encoded object that can be consumed by other languages such as
28   * Javascript or Ruby.
29   * <p/>
30   * The returnClass for this transformer is always java.lang.String, there is no need to set this.
31   */
32  public class ObjectToJson extends AbstractJsonTransformer
33  {
34      /**
35       * logger used by this class
36       */
37      protected transient final Log logger = LogFactory.getLog(ObjectToJson.class);
38  
39      private Map<Class<?>, Class<?>> serializationMixins = new HashMap<Class<?>, Class<?>>();
40  
41      protected Class<?> sourceClass;
42  
43      private boolean handleException = false;
44  
45      private IsJsonFilter isJsonFilter = new IsJsonFilter();
46  
47      public ObjectToJson()
48      {
49          this.setReturnDataType(DataTypeFactory.JSON_STRING);
50      }
51  
52      @Override
53      public void initialise() throws InitialisationException
54      {
55          super.initialise();
56  
57          //restrict the handled types
58          if (getSourceClass() != null)
59          {
60              sourceTypes.clear();
61              registerSourceType(DataTypeFactory.create(getSourceClass()));
62          }
63  
64          //Add shared mixins first
65          for (Map.Entry<Class<?>, Class<?>> entry : getMixins().entrySet())
66          {
67              getMapper().getSerializationConfig().addMixInAnnotations(entry.getKey(), entry.getValue());
68          }
69  
70          for (Map.Entry<Class<?>, Class<?>> entry : serializationMixins.entrySet())
71          {
72              getMapper().getSerializationConfig().addMixInAnnotations(entry.getKey(), entry.getValue());
73          }
74      }
75  
76      @Override
77      public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException
78      {
79          Object src = message.getPayload();
80          if (src instanceof String && isJsonFilter.accept(src))
81          {
82              //Nothing to transform
83              return src;
84          }
85  
86          // Checks if there's an exception
87          if (message.getExceptionPayload() != null && this.isHandleException())
88          {
89              if (logger.isDebugEnabled())
90              {
91                  logger.debug("Found exception with null payload");
92              }
93              src = this.getException(message.getExceptionPayload().getException());
94          }
95  
96          StringWriter writer = new StringWriter();
97          try
98          {
99              getMapper().writeValue(writer, src);
100         }
101         catch (IOException e)
102         {
103             throw new TransformerException(this, e);
104         }
105         
106         if (returnType.getType().equals(byte[].class))
107         {
108             try
109             {
110                 return writer.toString().getBytes(outputEncoding);
111             }
112             catch (UnsupportedEncodingException uee)
113             {
114                 throw new TransformerException(this, uee);
115             }
116         }
117         else
118         {
119             return writer.toString();
120         }
121     }
122 
123     /**
124      * The reason of having this is because the original exception object is way too
125      * complex and it breaks JSON-lib.
126      */
127     private Exception getException(Throwable t)
128     {
129         Exception returnValue = null;
130         List<Throwable> causeStack = new ArrayList<Throwable>();
131 
132         for (Throwable tempCause = t; tempCause != null; tempCause = tempCause.getCause())
133         {
134             causeStack.add(tempCause);
135         }
136 
137         for (int i = causeStack.size() - 1; i >= 0; i--)
138         {
139             Throwable tempCause = causeStack.get(i);
140 
141             // There is no cause at the very root
142             if (i == causeStack.size())
143             {
144                 returnValue = new Exception(tempCause.getMessage());
145                 returnValue.setStackTrace(tempCause.getStackTrace());
146             }
147             else
148             {
149                 returnValue = new Exception(tempCause.getMessage(), returnValue);
150                 returnValue.setStackTrace(tempCause.getStackTrace());
151             }
152         }
153 
154         return returnValue;
155     }
156 
157     public boolean isHandleException()
158     {
159         return this.handleException;
160     }
161 
162     public void setHandleException(boolean handleException)
163     {
164         this.handleException = handleException;
165     }
166 
167     public Class<?> getSourceClass()
168     {
169         return sourceClass;
170     }
171 
172     public void setSourceClass(Class<?> sourceClass)
173     {
174         this.sourceClass = sourceClass;
175     }
176 
177     public Map<Class<?>, Class<?>> getSerializationMixins()
178     {
179         return serializationMixins;
180     }
181 
182     public void setSerializationMixins(Map<Class<?>, Class<?>> serializationMixins)
183     {
184         this.serializationMixins = serializationMixins;
185     }
186 }
187