aboutsummaryrefslogblamecommitdiffstats
path: root/infrastructure/framework-src/modules/sessions.js
blob: 3d0041bdedc634ab5f33a5d28593adbce353377c (plain) (tree)



























































































































































                                                                                                            
/**
 * 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()));
}