/**
* Copyright (c) 2012-2013 Nokia Corporation. All rights reserved.
* Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation.
* Oracle and Java are trademarks or registered trademarks of Oracle and/or its
* affiliates. Other product and company names mentioned herein may be trademarks
* or trade names of their respective owners.
* See LICENSE.TXT for license information.
*/
package com.nokia.example.rlinks;
import com.nokia.example.rlinks.network.HttpClient.CookieJar;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.microedition.rms.InvalidRecordIDException;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
/**
* Store and retrieve user session data in RMS storage.
*
* For simplicity, this class also implements the CookieJar interface
* so that a single datastore can be used also by HttpClient to store
* cookies sent by the API.
*/
public final class SessionManager implements CookieJar {
private static SessionManager instance = null;
private static final String RECORDSTORE_SESSION = "session";
private String category = null;
private String username = null;
private String modhash = null;
private Hashtable cookieTable = new Hashtable();
/**
* Initialize the SessionManager with data from last session (if any)
* when created for the first time.
*/
private SessionManager() {
load();
}
/**
* Get a shared SessionManager instance.
*
* @return SessionManager
*/
public static SessionManager getInstance() {
if (instance == null) {
instance = new SessionManager();
}
return instance;
}
/**
* Determine whether the user is logged in.
*
* @return True if logged in, false otherwise
*/
public boolean isLoggedIn() {
return modhash != null;
}
/**
* Return the currently selected category (subreddit).
*
* @return Name of the currently selected category, or null if front page
*/
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
save();
}
/**
* Return the modhash for the logged-in user.
*
* @return Modhash for the currently logged in user, or null if none
*/
public String getModhash() {
return modhash;
}
/**
* Return the username for the logged-in user.
*
* @return Username for the currently logged in user, or null if none
*/
public String getUsername() {
return username;
}
/**
* Set a user as logged-in.
*
* @param username Username logged in as
* @param modhash Modhash received upon login
*/
public void setLoggedIn(String username, String modhash) {
this.username = username;
this.modhash = modhash;
save();
}
/**
* Set a user as logged-out. Effectively clears modhash and any cookies.
*/
public void setLoggedOut() {
modhash = null;
cookieTable.clear();
save();
}
/**
* Load session data from RMS.
*/
private void load() {
RecordStore rs = null;
RecordEnumeration re = null;
ByteArrayInputStream bais = null;
DataInputStream dis = null;
try {
rs = RecordStore.openRecordStore(RECORDSTORE_SESSION, true);
re = rs.enumerateRecords(null, null, true);
// If no session data is found, skip retrieval and go by the defaults
if (!re.hasNextElement()) {
return;
}
int id = re.nextRecordId();
bais = new ByteArrayInputStream(rs.getRecord(id));
dis = new DataInputStream(bais);
try {
category = dis.readUTF();
category = category.equals("") ? null : category;
username = dis.readUTF();
username = username.equals("") ? null : username;
modhash = dis.readUTF();
modhash = modhash.equals("") ? null : modhash;
// Retrieve the cookieTable: first read the number of Strings
// to expect, then read the Strings and further parse and insert
// them as key/value values in the cookieTable
int numCookies = dis.readInt();
for (int i = 0; i < numCookies; i++) {
String tmp = dis.readUTF();
int index = tmp.indexOf('|');
String key = tmp.substring(0, index);
String value = tmp.substring(index + 1);
cookieTable.put(key, value);
}
}
catch (EOFException eofe) {
eofe.printStackTrace();
}
}
catch (InvalidRecordIDException ire) {
ire.printStackTrace();
}
catch (RecordStoreException rse) {
rse.printStackTrace();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
finally {
if (dis != null) {
try {
dis.close();
}
catch (IOException ex) {}
}
if (bais != null) {
try {
bais.close();
}
catch (IOException ex) {}
}
if (re != null) {
re.destroy();
}
if (rs != null) {
try {
rs.closeRecordStore();
}
catch (Exception ex) {}
}
}
}
/**
* Save session data into RMS.
*/
private void save() {
try {
RecordStore.deleteRecordStore(RECORDSTORE_SESSION); // Clear data
}
catch (Exception e) { /* Nothing to delete */ }
RecordStore rs = null;
ByteArrayOutputStream baos = null;
DataOutputStream dos = null;
try {
rs = RecordStore.openRecordStore(RECORDSTORE_SESSION, true);
baos = new ByteArrayOutputStream();
dos = new DataOutputStream(baos);
dos.writeUTF(category == null ? "" : category);
dos.writeUTF(username == null ? "" : username);
dos.writeUTF(modhash == null ? "" : modhash);
// Store the cookieTable: first an integer telling how many UTF-8
// encoded string entries to expect, then the Strings themselves
dos.writeInt(cookieTable.size());
Enumeration keys = cookieTable.keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
String value = (String) cookieTable.get(key);
dos.writeUTF(key + "|" + value);
}
// Add it to the record store
byte[] b = baos.toByteArray();
rs.addRecord(b, 0, b.length);
}
catch (RecordStoreException rse) {
rse.printStackTrace();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
finally {
if (rs != null) {
try {
rs.closeRecordStore();
}
catch (Exception ex) {}
}
}
}
/**
* Put a cookie in the cookie jar.
*
* @param cookieContent Contents of the HTTP "Set-Cookie" header
*/
public void put(String cookieContent) {
// The first token is sufficient for the scope of Reddit
cookieContent = cookieContent.substring(0, cookieContent.indexOf(';'));
int splitIdx = cookieContent.indexOf("=");
String cookieName = cookieContent.substring(0, splitIdx);
String cookieValue = cookieContent.substring(splitIdx + 1);
// Store the cookie in the jar
cookieTable.put(cookieName, cookieValue);
save();
}
/**
* Get a String representation of all the cookies stored in the jar.
*
* @return A string that can be directly set in the "Cookie" header
*/
public String getCookieHeader() {
StringBuffer cookieStr = new StringBuffer();
Enumeration e = cookieTable.keys();
while (e.hasMoreElements()) {
// name1=value1; name2=value2
String key = (String) e.nextElement();
cookieStr.append(key).append("=").append(cookieTable.get(key)).append("; ");
}
if ("".equals(cookieStr.toString())) {
return null;
}
return cookieStr.toString();
}
}