Merge "fix for BUG-709 - mixed up flow cookie and connection cookie"
[controller.git] / opendaylight / samples / clustersession / src / main / java / org / opendaylight / controller / clustersession / ClusterSessionUtil.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  */
5 package org.opendaylight.controller.clustersession;
6
7 import java.io.ByteArrayInputStream;
8 import java.io.ByteArrayOutputStream;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.ObjectInputStream;
12 import java.io.ObjectOutputStream;
13 import java.io.OutputStream;
14 import java.security.Principal;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.Locale;
21 import java.util.Map;
22 import java.util.Map.Entry;
23
24 import org.apache.catalina.authenticator.Constants;
25 import org.apache.catalina.authenticator.SavedRequest;
26 import org.apache.catalina.ha.session.SerializablePrincipal;
27 import org.apache.catalina.realm.GenericPrincipal;
28 import org.opendaylight.controller.clustersession.service.ClusterSessionService;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 /**
33  * ClusterSessionUtil will be used to convert ClusterSession object into ClusterSessionData object,
34  * which is serializable and can be passed for storage. This class also perform deserialization to
35  * create ClusterSession object
36  * @author harman singh
37  *
38  */
39
40 public class ClusterSessionUtil {
41
42   private static final Logger LOGGER = LoggerFactory.getLogger(ClusterSessionUtil.class);
43
44   private ClusterSessionUtil() {
45
46   }
47
48   /**
49    * Serialize the ClusterSession object to provide ClusterSessionData object,
50    * that will be used for storage like in inifinispan or memcache etc.
51    * @param session an instance of ClusterSession
52    * @return an instance of ClusterSessionData
53    */
54   public static ClusterSessionData getSerializableSession(ClusterSession session) {
55     if(session == null){
56       return null;
57     }
58     ClusterSessionData sessionData = new ClusterSessionData();
59     sessionData.setSession(session);
60     sessionData.setAuthType(session.getAuthType());
61     sessionData.setPrincipalData(serializePrincipal(session.getPrincipal()));
62     sessionData.setSavedRequestData(serializeSavedRequest(session.getNote(Constants.FORM_REQUEST_NOTE)));
63     Principal notePrincipal = (Principal) session.getNote(Constants.FORM_PRINCIPAL_NOTE);
64     byte[] principalBytes = serializePrincipal(notePrincipal);
65     sessionData.setSavedPrincipalData(principalBytes);
66     if(session.getPrincipal() == null && notePrincipal != null){
67       sessionData.setPrincipalData(principalBytes);
68     }
69     sessionData.setUserName((String) session.getNote(Constants.FORM_USERNAME));
70     sessionData.setPassword((String) session.getNote(Constants.FORM_PASSWORD));
71     return sessionData;
72   }
73
74   /**
75    * Deserialize the ClusterSessionData object that usually comes from storage
76    * to provide ClusterSession object,
77    * that will be used by Session Manager
78    * @param sessionData an instance of ClusterSessionData
79    * @param sessionService an instance of ClusterSessionService
80    * @param manager an instance of ClusterSessionManager
81    * @return an instance of ClusterSession
82    */
83
84   public static ClusterSession getDeserializedSession(ClusterSessionData sessionData, ClusterSessionService sessionService,
85       ClusterSessionManager manager) {
86     if(sessionData == null){
87       return null;
88     }
89     ClusterSession session = sessionData.getSession();
90     session.afterDeserialization();
91     session.setManager(manager);
92     session.setSessionService(sessionService);
93     if(sessionData.getAuthType() != null) {
94       session.setAuthTypeInternal(sessionData.getAuthType());
95     }
96     if(sessionData.getPrincipalData() != null && sessionData.getPrincipalData().length > 0){
97       session.setPrincipalInternal(deserializePrincipal(sessionData.getPrincipalData()));
98     }
99     if(sessionData.getSavedPrincipalData() != null && sessionData.getSavedPrincipalData().length > 0){
100       session.setNoteInternal(Constants.FORM_PRINCIPAL_NOTE, deserializePrincipal(sessionData.getSavedPrincipalData()));
101     }
102     if(sessionData.getSavedRequestData() != null && sessionData.getSavedRequestData().length > 0){
103       session.setNoteInternal(Constants.FORM_REQUEST_NOTE, deserializeSavedRequest(sessionData.getSavedRequestData()));
104     }
105     if(sessionData.getUserName() != null){
106       session.setNoteInternal(Constants.FORM_USERNAME, sessionData.getUserName());
107     }
108     if(sessionData.getPassword() != null){
109       session.setNoteInternal(Constants.FORM_PASSWORD, sessionData.getPassword());
110     }
111     return session;
112   }
113
114   private static byte[] serializePrincipal(final Principal principal){
115     if(principal == null) {
116       return new byte[0];
117     }
118     ByteArrayOutputStream bos = null;
119     ObjectOutputStream oos = null;
120     try {
121       bos = new ByteArrayOutputStream();
122       oos = new ObjectOutputStream(bos);
123       SerializablePrincipal.writePrincipal((GenericPrincipal) principal, oos );
124       oos.flush();
125       return bos.toByteArray();
126     } catch (IOException e) {
127       throw new IllegalArgumentException( "Non-serializable object", e);
128     } finally {
129       closeSilently(bos);
130       closeSilently(oos);
131     }
132   }
133
134   private static byte[] serializeSavedRequest(final Object obj) {
135     if(obj == null) {
136       return new byte[0];
137     }
138     final SavedRequest savedRequest = (SavedRequest) obj;
139     ByteArrayOutputStream bos = null;
140     ObjectOutputStream oos = null;
141     try {
142       bos = new ByteArrayOutputStream();
143       oos = new ObjectOutputStream(bos);
144       oos.writeObject(savedRequest.getContentType());
145       oos.writeObject(getHeaders(savedRequest));
146       oos.writeObject(newArrayList(savedRequest.getLocales()));
147       oos.writeObject(savedRequest.getMethod());
148       oos.writeObject(savedRequest.getQueryString());
149       oos.writeObject(savedRequest.getRequestURI());
150       oos.writeObject(savedRequest.getDecodedRequestURI());
151       oos.flush();
152       return bos.toByteArray();
153     } catch (IOException e) {
154       throw new IllegalArgumentException( "Non-serializable object", e);
155     } finally {
156       closeSilently(bos);
157       closeSilently(oos);
158     }
159   }
160
161   private static Principal deserializePrincipal(final byte[] data) {
162     ByteArrayInputStream bis = null;
163     ObjectInputStream ois = null;
164     try {
165       bis = new ByteArrayInputStream(data);
166       ois = new ObjectInputStream(bis);
167       return SerializablePrincipal.readPrincipal(ois);
168     } catch (IOException e) {
169       throw new IllegalArgumentException( "Could not deserialize principal", e);
170     } catch (ClassNotFoundException e) {
171       throw new IllegalArgumentException( "Could not deserialize principal", e);
172     } finally {
173       closeSilently(bis);
174       closeSilently(ois);
175     }
176   }
177
178   @SuppressWarnings("unchecked")
179   private static SavedRequest deserializeSavedRequest(final byte[] data) {
180     ByteArrayInputStream bis = null;
181     ObjectInputStream ois = null;
182     try {
183       bis = new ByteArrayInputStream(data);
184       ois = new ObjectInputStream(bis);
185       final SavedRequest savedRequest = new SavedRequest();
186       savedRequest.setContentType((String) ois.readObject());
187       setHeaders(savedRequest, (Map<String, List<String>>) ois.readObject());
188       setLocales(savedRequest, (List<Locale>) ois.readObject());
189       savedRequest.setMethod((String) ois.readObject());
190       savedRequest.setQueryString((String) ois.readObject());
191       savedRequest.setRequestURI((String) ois.readObject());
192       savedRequest.setDecodedRequestURI((String) ois.readObject());
193       return savedRequest;
194     } catch (final IOException e) {
195       throw new IllegalArgumentException( "Could not deserialize SavedRequest", e );
196     } catch (final ClassNotFoundException e) {
197       throw new IllegalArgumentException( "Could not deserialize SavedRequest", e );
198     } finally {
199       closeSilently(bis);
200       closeSilently(ois);
201     }
202   }
203
204   private static void setLocales(final SavedRequest savedRequest, final List<Locale> locales) {
205     if(locales != null && !locales.isEmpty()) {
206       for (final Locale locale : locales) {
207         savedRequest.addLocale(locale);
208       }
209     }
210   }
211
212   private static <T> List<T> newArrayList(final Iterator<T> iter) {
213     if(!iter.hasNext()) {
214       return Collections.emptyList();
215     }
216     final List<T> result = new ArrayList<T>();
217     while (iter.hasNext()) {
218       result.add(iter.next());
219     }
220     return result;
221   }
222
223   private static Map<String, List<String>> getHeaders(final SavedRequest obj) {
224     final Map<String, List<String>> result = new HashMap<String, List<String>>();
225     final Iterator<String> namesIter = obj.getHeaderNames();
226     while (namesIter.hasNext()) {
227       final String name = namesIter.next();
228       final List<String> values = new ArrayList<String>();
229       result.put(name, values);
230       final Iterator<String> valuesIter = obj.getHeaderValues(name);
231       while (valuesIter.hasNext()) {
232         final String value = valuesIter.next();
233         values.add(value);
234       }
235     }
236     return result;
237   }
238
239   private static void setHeaders(final SavedRequest obj, final Map<String, List<String>> headers) {
240     if(headers != null) {
241       for (final Entry<String, List<String>> entry : headers.entrySet()) {
242         final List<String> values = entry.getValue();
243         for (final String value : values) {
244           obj.addHeader(entry.getKey(), value);
245         }
246       }
247     }
248   }
249
250   private static void closeSilently(final OutputStream os) {
251     if (os != null) {
252       try {
253         os.close();
254       } catch (final IOException f) {
255         LOGGER.debug("Exception occurred while closing output stream",  f.toString());
256       }
257     }
258   }
259
260   private static void closeSilently(final InputStream is) {
261     if (is != null) {
262       try {
263         is.close();
264       } catch (final IOException f) {
265         LOGGER.debug("Exception occurred while closing input stream", f.toString());
266       }
267     }
268   }
269 }