View Javadoc

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