View Javadoc

1   /*
2    * $Id: DefaultMuleSession.java 20343 2010-11-24 21:02:10Z mike.schilling $
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.session;
12  
13  import org.mule.api.MuleContext;
14  import org.mule.api.MuleException;
15  import org.mule.api.MuleMessage;
16  import org.mule.api.MuleSession;
17  import org.mule.api.construct.FlowConstruct;
18  import org.mule.api.security.SecurityContext;
19  import org.mule.api.transport.SessionHandler;
20  import org.mule.config.i18n.CoreMessages;
21  import org.mule.util.CaseInsensitiveHashMap;
22  import org.mule.util.UUID;
23  import org.mule.util.store.DeserializationPostInitialisable;
24  
25  import java.io.IOException;
26  import java.io.ObjectInputStream;
27  import java.io.ObjectOutputStream;
28  import java.io.OptionalDataException;
29  import java.util.Collections;
30  import java.util.HashMap;
31  import java.util.Iterator;
32  import java.util.Map;
33  import java.util.Set;
34  
35  import org.apache.commons.collections.map.CaseInsensitiveMap;
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  
39  /**
40   * <code>DefaultMuleSession</code> manages the interaction and distribution of events for
41   * Mule Services.
42   */
43  
44  public final class DefaultMuleSession implements MuleSession, DeserializationPostInitialisable
45  {
46      /**
47       * Serial version
48       */
49      private static final long serialVersionUID = 3380926585676521866L;
50  
51      /**
52       * logger used by this class
53       */
54      private static Log logger = LogFactory.getLog(DefaultMuleSession.class);
55  
56      /**
57       * The Mule service associated with the session
58       * <p/>
59       * Note: This object uses custom serialization via the writeObject()/readObject() methods.
60       */
61      private transient FlowConstruct flowConstruct = null;
62  
63      /**
64       * Determines if the service is valid
65       */
66      private boolean valid = true;
67  
68      private String id;
69  
70      /**
71       * The security context associated with the session.
72       * Note that this context will only be serialized if the SecurityContext object is Serializable.
73       */
74      private SecurityContext securityContext;
75  
76      private Map<String, Object> properties = null;
77  
78      /**
79       * The Mule context
80       * <p/>
81       * Note: This object uses custom serialization via the readObject() method.
82       */
83      private transient MuleContext muleContext;
84  
85      private transient Map<String, Object> serializedData = null;
86  
87      public DefaultMuleSession(MuleContext muleContext)
88      {
89          this((FlowConstruct) null, muleContext);
90      }
91  
92      public DefaultMuleSession(FlowConstruct flowConstruct, MuleContext muleContext)
93      {
94          this.muleContext = muleContext;
95          properties = Collections.synchronizedMap(new CaseInsensitiveHashMap/*<String, Object>*/());
96          id = UUID.getUUID();
97          this.flowConstruct = flowConstruct;
98      }
99  
100     /**
101      * @deprecated Use DefaultMuleSession(Service service, MuleContext muleContext) instead
102      */
103     @Deprecated
104     public DefaultMuleSession(MuleMessage message,
105                               SessionHandler requestSessionHandler,
106                               FlowConstruct flowConstruct,
107                               MuleContext muleContext) throws MuleException
108     {
109         this(message, requestSessionHandler, muleContext);
110         if (flowConstruct == null)
111         {
112             throw new IllegalArgumentException(CoreMessages.propertiesNotSet("flowConstruct").toString());
113         }
114         this.flowConstruct = flowConstruct;
115     }
116 
117     /**
118      * @deprecated Use DefaultMuleSession(MuleContext muleContext) instead
119      */
120     @Deprecated
121     public DefaultMuleSession(MuleMessage message, SessionHandler requestSessionHandler, MuleContext muleContext) throws MuleException
122     {
123         this(muleContext);
124 
125         if (requestSessionHandler == null)
126         {
127             throw new IllegalArgumentException(
128                     CoreMessages.propertiesNotSet("requestSessionHandler").toString());
129         }
130 
131         if (message == null)
132         {
133             throw new IllegalArgumentException(
134                     CoreMessages.propertiesNotSet("message").toString());
135         }
136 
137         properties = new CaseInsensitiveMap/*<String, Object>*/();
138         requestSessionHandler.retrieveSessionInfoFromMessage(message, this);
139         id = getProperty(requestSessionHandler.getSessionIDKey());
140         if (id == null)
141         {
142             id = UUID.getUUID();
143             if (logger.isDebugEnabled())
144             {
145                 logger.debug("There is no session id on the request using key: "
146                         + requestSessionHandler.getSessionIDKey() + ". Generating new session id: " + id);
147             }
148         }
149         else if (logger.isDebugEnabled())
150         {
151             logger.debug("Got session with id: " + id);
152         }
153     }
154 
155     public DefaultMuleSession(MuleSession session, MuleContext muleContext)
156     {
157         this.muleContext = muleContext;
158         this.id = session.getId();
159         this.securityContext = session.getSecurityContext();
160         this.flowConstruct = session.getFlowConstruct();
161         this.valid = session.isValid();
162 
163         this.properties = new HashMap<String, Object>();
164         for (String key : session.getPropertyNamesAsSet())
165         {
166             this.properties.put(key, session.getProperty(key));
167         }
168     }
169 
170     /**
171      * Copy the session, changing only the flow construct.  This can be used for
172      * synchronous calls from one flow construct to another.
173      */
174     public DefaultMuleSession(MuleSession source, FlowConstruct flowConstruct)
175     {
176         this.flowConstruct = flowConstruct;
177         DefaultMuleSession session = (DefaultMuleSession) source;
178         this.id = session.id;
179         this.muleContext = session.muleContext;
180         this.properties = session.properties;
181         this.securityContext = session.securityContext;
182         this.valid = session.valid;
183     }
184 
185     public String getId()
186     {
187         return id;
188     }
189 
190     public boolean isValid()
191     {
192         return valid;
193     }
194 
195     public void setValid(boolean value)
196     {
197         valid = value;
198     }
199 
200     /**
201      * @return Returns the service.
202      */
203     public FlowConstruct getFlowConstruct()
204     {
205         return flowConstruct;
206     }
207 
208     public void setFlowConstruct(FlowConstruct flowConstruct)
209     {
210         this.flowConstruct = flowConstruct;
211     }
212 
213     /**
214      * The security context for this session. If not null outbound, inbound and/or
215      * method invocations will be authenticated using this context
216      *
217      * @param context the context for this session or null if the request is not
218      *                secure.
219      */
220     public void setSecurityContext(SecurityContext context)
221     {
222         securityContext = context;
223     }
224 
225     /**
226      * The security context for this session. If not null outbound, inbound and/or
227      * method invocations will be authenticated using this context
228      *
229      * @return the context for this session or null if the request is not secure.
230      */
231     public SecurityContext getSecurityContext()
232     {
233         return securityContext;
234     }
235 
236     /**
237      * Will set a session level property. These will either be stored and retrieved
238      * using the underlying transport mechanism of stored using a default mechanism
239      *
240      * @param key   the key for the object data being stored on the session
241      * @param value the value of the session data
242      */
243     public void setProperty(String key, Object value)
244     {
245         properties.put(key, value);
246     }
247 
248     /**
249      * Will retrieve a session level property.
250      *
251      * @param key the key for the object data being stored on the session
252      * @return the value of the session data or null if the property does not exist
253      */
254     @SuppressWarnings("unchecked")
255     public <T> T getProperty(Object key)
256     {
257         return (T) properties.get(key);
258     }
259 
260     /**
261      * Will retrieve a session level property and remove it from the session
262      *
263      * @param key the key for the object data being stored on the session
264      * @return the value of the session data or null if the property does not exist
265      */
266     public Object removeProperty(Object key)
267     {
268         return properties.remove(key);
269     }
270 
271     /**
272      * Returns an iterater of property keys for the session properties on this
273      * session
274      *
275      * @return an iterater of property keys for the session properties on this
276      *         session
277      * @deprecated Use getPropertyNamesAsSet() instead
278      */
279     @Deprecated
280     public Iterator<String> getPropertyNames()
281     {
282         return properties.keySet().iterator();
283     }
284 
285     public Set<String> getPropertyNamesAsSet()
286     {
287         return Collections.unmodifiableSet(properties.keySet());
288     }
289 
290     ////////////////////////////
291     // Serialization methods
292     ////////////////////////////
293 
294     private void writeObject(ObjectOutputStream out) throws IOException
295     {
296         out.defaultWriteObject();
297         //Can be null if service call originates from MuleClient
298         if (getFlowConstruct() != null)
299         {
300             out.writeObject(getFlowConstruct() != null ? getFlowConstruct().getName() : "null");
301         }
302     }
303 
304     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
305     {
306         in.defaultReadObject();
307         serializedData = new HashMap<String, Object>();
308 
309         try
310         {
311             //Optional
312             serializedData.put("serviceName", in.readObject());
313         }
314         catch (OptionalDataException e)
315         {
316             //ignore
317         }
318     }
319 
320     /**
321      * Invoked after deserialization. This is called when the marker interface
322      * {@link org.mule.util.store.DeserializationPostInitialisable} is used. This will get invoked
323      * after the object has been deserialized passing in the current mulecontext when using either
324      * {@link org.mule.transformer.wire.SerializationWireFormat},
325      * {@link org.mule.transformer.wire.SerializedMuleMessageWireFormat}, or the
326      * {@link org.mule.transformer.simple.ByteArrayToSerializable} transformer.
327      *
328      * @param muleContext the current muleContext instance
329      * @throws MuleException if there is an error initializing
330      */
331     public void initAfterDeserialisation(MuleContext muleContext) throws MuleException
332     {
333         String serviceName = (String) serializedData.get("serviceName");
334         //Can be null if service call originates from MuleClient
335         if (serviceName != null)
336         {
337             flowConstruct = muleContext.getRegistry().lookupService(serviceName);
338         }
339         serializedData = null;
340     }
341 
342 }