2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
5 package org.opendaylight.controller.clustersession;
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;
22 import java.util.Map.Entry;
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;
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
40 public class ClusterSessionUtil {
42 private static final Logger LOGGER = LoggerFactory.getLogger(ClusterSessionUtil.class);
44 private ClusterSessionUtil() {
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
54 public static ClusterSessionData getSerializableSession(ClusterSession session) {
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);
69 sessionData.setUserName((String) session.getNote(Constants.FORM_USERNAME));
70 sessionData.setPassword((String) session.getNote(Constants.FORM_PASSWORD));
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
84 public static ClusterSession getDeserializedSession(ClusterSessionData sessionData, ClusterSessionService sessionService,
85 ClusterSessionManager manager) {
86 if(sessionData == null){
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());
96 if(sessionData.getPrincipalData() != null && sessionData.getPrincipalData().length > 0){
97 session.setPrincipalInternal(deserializePrincipal(sessionData.getPrincipalData()));
99 if(sessionData.getSavedPrincipalData() != null && sessionData.getSavedPrincipalData().length > 0){
100 session.setNoteInternal(Constants.FORM_PRINCIPAL_NOTE, deserializePrincipal(sessionData.getSavedPrincipalData()));
102 if(sessionData.getSavedRequestData() != null && sessionData.getSavedRequestData().length > 0){
103 session.setNoteInternal(Constants.FORM_REQUEST_NOTE, deserializeSavedRequest(sessionData.getSavedRequestData()));
105 if(sessionData.getUserName() != null){
106 session.setNoteInternal(Constants.FORM_USERNAME, sessionData.getUserName());
108 if(sessionData.getPassword() != null){
109 session.setNoteInternal(Constants.FORM_PASSWORD, sessionData.getPassword());
114 private static byte[] serializePrincipal(final Principal principal){
115 if(principal == null) {
118 ByteArrayOutputStream bos = null;
119 ObjectOutputStream oos = null;
121 bos = new ByteArrayOutputStream();
122 oos = new ObjectOutputStream(bos);
123 SerializablePrincipal.writePrincipal((GenericPrincipal) principal, oos );
125 return bos.toByteArray();
126 } catch (IOException e) {
127 throw new IllegalArgumentException( "Non-serializable object", e);
134 private static byte[] serializeSavedRequest(final Object obj) {
138 final SavedRequest savedRequest = (SavedRequest) obj;
139 ByteArrayOutputStream bos = null;
140 ObjectOutputStream oos = null;
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());
152 return bos.toByteArray();
153 } catch (IOException e) {
154 throw new IllegalArgumentException( "Non-serializable object", e);
161 private static Principal deserializePrincipal(final byte[] data) {
162 ByteArrayInputStream bis = null;
163 ObjectInputStream ois = null;
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);
178 @SuppressWarnings("unchecked")
179 private static SavedRequest deserializeSavedRequest(final byte[] data) {
180 ByteArrayInputStream bis = null;
181 ObjectInputStream ois = null;
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());
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 );
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);
212 private static <T> List<T> newArrayList(final Iterator<T> iter) {
213 if(!iter.hasNext()) {
214 return Collections.emptyList();
216 final List<T> result = new ArrayList<T>();
217 while (iter.hasNext()) {
218 result.add(iter.next());
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();
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);
250 private static void closeSilently(final OutputStream os) {
254 } catch (final IOException f) {
255 LOGGER.debug("Exception occurred while closing output stream", f.toString());
260 private static void closeSilently(final InputStream is) {
264 } catch (final IOException f) {
265 LOGGER.debug("Exception occurred while closing input stream", f.toString());