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.transport.ajax;
8   
9   import org.mule.DefaultMuleMessage;
10  import org.mule.api.DefaultMuleException;
11  import org.mule.api.MuleContext;
12  import org.mule.api.transport.MuleMessageFactory;
13  import org.mule.api.transport.PropertyScope;
14  import org.mule.module.json.JsonData;
15  import org.mule.module.json.filters.IsJsonFilter;
16  import org.mule.transport.AbstractMuleMessageFactory;
17  import org.mule.transport.ajax.embedded.AjaxConnector;
18  
19  import java.io.IOException;
20  import java.util.Map;
21  
22  import org.cometd.Bayeux;
23  
24  /**
25   * A {@link MuleMessageFactory} implementation for JSON messages. The payload can either be a 
26   * {@link Map} or a JSON encoded String.
27   * <p/>
28   * If the payload is a {@link Map}, this message factory will recognise the following keys:
29   * <ul>
30   * <li>data - the object to use a the payload, this can be a JSON encoded string. See {@link Bayeux#DATA_FIELD}</li>
31   * <li>replyTo - the return Ajax channel for this message. {@link AjaxConnector#REPLYTO_PARAM}</li>
32   * </ul>
33   */
34  public class AjaxMuleMessageFactory extends AbstractMuleMessageFactory
35  {
36      protected transient IsJsonFilter filter = new IsJsonFilter();
37  
38      public AjaxMuleMessageFactory(MuleContext context)
39      {
40          super(context);
41      }
42  
43      @Override
44      protected Class<?>[] getSupportedTransportMessageTypes()
45      {
46          return new Class[] { Object.class };
47      }
48  
49      @Override
50      protected Object extractPayload(Object transportMessage, String encoding) throws Exception
51      {
52          if (transportMessage instanceof Map<?, ?>)
53          {
54              return extractPayloadFromMap((Map<?, ?>) transportMessage);
55          }
56          else if (filter.accept(transportMessage))
57          {
58              return extractJsonPayload(transportMessage);
59          }
60          else
61          {
62              return transportMessage;
63          }
64      }
65      
66      @Override
67      protected void addProperties(DefaultMuleMessage muleMessage, Object transportMessage) throws Exception
68      {
69          if (transportMessage instanceof Map<?, ?>)
70          {
71              addPropertiesFromMap(muleMessage, (Map<?, ?>) transportMessage);
72          }
73          else if (filter.accept(transportMessage))
74          {
75              addPropertiesToFromJsonData(muleMessage, transportMessage);
76          }
77      }
78  
79      private Object extractPayloadFromMap(Map<?, ?> map)
80      {
81          Object data = map.remove(Bayeux.DATA_FIELD);
82          if (data == null)
83          {
84              throw new IllegalArgumentException(Bayeux.DATA_FIELD + " parameter not set in payload map"); 
85          }
86          return data;
87      }
88  
89      private Object extractJsonPayload(Object transportMessage) throws DefaultMuleException
90      {
91          String transportMessageString = transportMessage.toString();
92          if (transportMessageString.indexOf(Bayeux.DATA_FIELD) > -1)
93          {
94              try
95              {
96                  JsonData data = new JsonData(transportMessageString);
97                  return data.get(Bayeux.DATA_FIELD).toString();
98              }
99              catch (IOException e)
100             {
101                 throw new DefaultMuleException(e);
102             }
103         }
104         else
105         {
106             return transportMessage;
107         }
108     }
109 
110     @SuppressWarnings("unchecked")
111     private void addPropertiesFromMap(DefaultMuleMessage muleMessage, Map<?, ?> map)
112     {
113         Object replyTo = map.remove(AjaxConnector.REPLYTO_PARAM);
114         muleMessage.setReplyTo(replyTo);
115 
116         // remove the part of the map we process as payload
117         map.remove(Bayeux.DATA_FIELD);
118         
119         // the remainder of the map is used as message properties
120         Map<String, Object> messageProperties = (Map<String, Object>) map;
121         muleMessage.addProperties(messageProperties, PropertyScope.INVOCATION);
122     }
123     
124     private void addPropertiesToFromJsonData(DefaultMuleMessage muleMessage, Object transportMessage) throws IOException
125     {
126         JsonData data = new JsonData(transportMessage.toString());
127         if (data.hasNode(AjaxConnector.REPLYTO_PARAM))
128         {
129             muleMessage.setReplyTo(data.getAsString(AjaxConnector.REPLYTO_PARAM));
130         }
131     }
132 }