/**
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import("dateutils");
import("fastJSON");
import("fileutils");
import("jsutils.{eachProperty,keys}");
import("stringutils.{randomHash,startsWith,endsWith}");
import("sync");
jimport("net.appjet.common.util.ExpiringMapping");
//----------------------------------------------------------------
var _DEFAULT_COOKIE_NAME = "SessionID";
var _DEFAULT_SERVER_EXPIRATION = 3*24*60*60*1000; // 72 hours
function getSessionId(cookieName, createIfNotPresent, domain) {
if (request.isComet || request.isCron) {
return null;
}
if (request.cookies[cookieName]) {
return request.cookies[cookieName];
}
if (!createIfNotPresent) {
return null;
}
// Keep sessionId in requestCache so this function can be called multiple
// times per request without multiple calls to setCookie().
if (!appjet.requestCache.sessionId) {
var sessionId = randomHash(16);
response.setCookie({
name: cookieName,
value: sessionId,
path: "/",
domain: (domain || undefined)
});
appjet.requestCache.sessionId = sessionId;
}
return appjet.requestCache.sessionId;
}
function _getExpiringSessionMap(db) {
sync.callsyncIfTrue(db,
function() { return (!db.map); },
function() { db.map = new ExpiringMapping(_DEFAULT_SERVER_EXPIRATION); });
return db.map;
}
function _getCachedDb() {
return appjet.cacheRoot("net.appjet.ajstdlib.session");
}
//----------------------------------------------------------------
function getSession(opts) {
// Session options.
if (!opts) { opts = {}; }
var cookieName = opts.cookieName || _DEFAULT_COOKIE_NAME;
// get cookie ID (sets response cookie if necessary)
var sessionId = getSessionId(cookieName, true, opts.domain);
// get expiring session map
var db = _getCachedDb();
var map = _getExpiringSessionMap(db);
// get session data object
var domainKey = (opts.domain ? opts.domain : "");
var dataKey = [domainKey, sessionId].join('$');
var sessionData = map.get(dataKey);
if (!sessionData) {
sessionData = {};
map.put(dataKey, sessionData);
}
else {
map.touch(dataKey);
}
return sessionData;
}
function writeSessionsToDisk() {
var dateString = dateutils.dateFormat(new Date(), "yyyy-MM-dd");
var dataFile = new Packages.java.io.File(appjet.config.sessionStoreDir+"/sessions-"+dateString+".jslog");
dataFile.getParentFile().mkdirs();
var writer = new java.io.FileWriter(dataFile);
var map = _getCachedDb().map;
if (! map) { return; }
var keyIterator = map.listAllKeys().iterator();
while (keyIterator.hasNext()) {
var key = keyIterator.next();
var session = map.get(key);
if (keys(session).length == 0) { continue; }
var obj = { key: key, session: session };
var json = fastJSON.stringify(obj);
writer.write(json);
writer.write("\n");
}
writer.flush();
writer.close();
}
function _extractDate(fname) {
var datePart = fname.substr("sessions-".length, "2009-09-24".length);
return Number(datePart.split("-").join(""));
}
function readLatestSessionsFromDisk() {
var dir = new Packages.java.io.File(appjet.config.sessionStoreDir);
if (! dir.exists()) { return; }
var files = dir.listFiles(new Packages.java.io.FilenameFilter({
accept: function(dir, name) {
return startsWith(name, "sessions") && endsWith(name, ".jslog")
}
}));
if (files.length == 0) { return; }
var latestFile = files[0];
for (var i = 1; i < files.length; ++i) {
if (_extractDate(files[i].getName()) > _extractDate(latestFile.getName())) {
latestFile = files[i];
}
}
var map = _getExpiringSessionMap(_getCachedDb());
fileutils.eachFileLine(latestFile, function(json) {
try {
var obj = fastJSON.parse(json);
var key = obj.key;
var session = obj.session;
map.put(key, session);
} catch (err) {
Packages.java.lang.System.out.println("Error reading sessions file on line '"+json+"': "+String(err));
}
});
latestFile.renameTo(new Packages.java.io.File(latestFile.getParent()+"/used-"+latestFile.getName()));
}