/**
* Sahi - Web Automation and Test Tool
*
* Copyright 2006 V Narayan Raman
*
* 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.
*/
package net.sf.sahi.session;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import net.sf.sahi.command.MockResponder;
import net.sf.sahi.config.Configuration;
import net.sf.sahi.nashorn.NashornScriptRunner;
import net.sf.sahi.playback.RequestCredentials;
import net.sf.sahi.playback.SahiScript;
import net.sf.sahi.record.Recorder;
import net.sf.sahi.report.Report;
import net.sf.sahi.test.BrowserLauncher;
import net.sf.sahi.test.SahiTestSuite;
import net.sf.sahi.util.Utils;
import org.apache.log4j.Logger;
/**
* User: nraman Date: Jun 21, 2005 Time: 8:03:28 PM
*/
public class Session {
private static final Logger logger = Logger.getLogger(Session.class);
private final Hashtable<String, String> ajaxRedirects = new Hashtable<String, String>();
private Status status;
private static Map<String, Session> sessions = new HashMap<String, Session>();
private String sessionId;
private boolean isWindowOpen = false;
private Recorder recorder;
private SahiScript script;
private Map<String, String> variables;
private String xhrReadyStatesToWaitFor;
private MockResponder mockResponder = new MockResponder();
private Report report;
private long timestamp = System.currentTimeMillis();
private NashornScriptRunner scriptRunner;
private boolean sendHTMLResponseAfterFileDownload = false;
private Map<String, RequestCredentials> requestCredentials = new HashMap<String, RequestCredentials>();
private BrowserLauncher launcher;
private boolean isPlaying;
private boolean isRecording;
private boolean isReadyForDriver;
private Map<String, Object> objectVariables = new HashMap<String, Object>();
private boolean is204;
static double playbackInactiveTimeout = Configuration.getMaxInactiveTimeForScript() * 1.5;
static double recorderInactiveTimeout = 20 * 60 * 1000; // 20 minutes
static {
Timer stepTimer = new Timer();
stepTimer.schedule(new TimerTask() {
@Override
public void run() {
removeInactiveSessions();
}
}, 0, 10000);
}
public Report getReport() {
return report;
}
public void setReport(final Report report) {
this.report = report;
}
public static void removeInstance(final String sessionId) {
sessions.remove(sessionId);
}
public static synchronized Session getInstance(final String sessionId) {
if (!sessions.containsKey(sessionId)) {
sessions.put(sessionId, new Session(sessionId));
}
Session session = sessions.get(sessionId);
session.touch();
return session;
}
public static synchronized boolean hasInstance(final String sessionId) {
if (sessions.containsKey(sessionId)) {
return true;
}
return false;
}
public static synchronized Session getExistingInstance(final String sessionId) {
return sessions.get(sessionId);
}
public Session(final String sessionId) {
this.sessionId = sessionId;
this.variables = new HashMap<String, String>();
this.status = Status.INITIAL;
}
public String id() {
return sessionId;
}
public void setIsWindowOpen(final boolean isWindowOpen) {
this.isWindowOpen = isWindowOpen;
}
public boolean isWindowOpen() {
return isWindowOpen;
}
public boolean sendHTMLResponseAfterFileDownload() {
return this.sendHTMLResponseAfterFileDownload;
}
public void setSendHTMLResponseAfterFileDownload(boolean b) {
this.sendHTMLResponseAfterFileDownload = b;
}
public Recorder getRecorder() {
if (this.recorder == null) {
this.recorder = new Recorder();
}
return recorder;
}
public String getVariable(final String name) {
logger.debug("get name="+name + " value=" + (String) (variables.get(name)));
return (String) (variables.get(name));
}
public void removeVariables(final String pattern) {
for (Iterator<String> iterator = variables.keySet().iterator(); iterator.hasNext(); ) {
String s = iterator.next();
if (s.matches(pattern)) {
iterator.remove();
}
}
}
public void setVariable(final String name, final String value) {
logger.debug("set name="+name + " value=" + value);
variables.put(name, value);
if (scriptRunner != null)
scriptRunner.setVariable(name, value);
}
public SahiScript xgetScript() {
return script;
}
public SahiTestSuite getSuite() {
return SahiTestSuite.getSuite(this.id());
}
public MockResponder mockResponder() {
return mockResponder;
}
public boolean isPlaying() {
// return scriptRunner != null;
return this.isPlaying;
}
public void setIsPlaying(boolean isPlaying) {
this.isPlaying = isPlaying;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public void touch() {
timestamp = System.currentTimeMillis();
}
public long lastActiveTime() {
return timestamp;
}
public NashornScriptRunner getScriptRunner() {
return scriptRunner;
}
public void setScriptRunner(NashornScriptRunner scriptRunner) {
this.scriptRunner = scriptRunner;
scriptRunner.setSession(this);
}
public void setLauncher(BrowserLauncher launcher) {
this.launcher = launcher;
}
public BrowserLauncher getLauncher() {
return launcher;
}
public void addRequestCredentials(String realm, String username, String password) {
realm = realm.trim();
logger.info(">>> Credentials added: " + realm + " " + username);
requestCredentials.put(realm, new RequestCredentials(realm, username, password));
}
public void removeRequestCredentials(String realm) {
requestCredentials.remove(realm);
}
public void removeAllRequestCredentials() {
requestCredentials.clear();
}
public RequestCredentials getMatchingCredentials(String realm, String scheme) {
String key = Utils.isBlankOrNull(realm) ? scheme : realm;
RequestCredentials cred = requestCredentials.get(key.trim());
if (cred == null || cred.used()) return null;
return cred;
}
public boolean isRecording() {
return isRecording;
}
public void setIsRecording(boolean isRecording) {
this.isRecording = isRecording;
}
public void setIsReadyForDriver(boolean isReadyForDriver) {
this.isReadyForDriver = isReadyForDriver;
}
public boolean isReadyForDriver() {
return isReadyForDriver;
}
public boolean isPaused() {
return "1".equals(getVariable("sahi_paused"));
}
public String getInfoJSON() {
StringBuilder sb = new StringBuilder();
sb.append("{");
sb.append("'isRecording':" + isRecording());
sb.append(",");
sb.append("'isPlaying':" + isPlaying());
sb.append(",");
sb.append("'isPaused':" + isPaused());
sb.append(",");
sb.append("'sessionId':'" + sessionId + "'");
sb.append("}");
return sb.toString();
}
public double getInactiveTimeout() {
return isPlaying() ? playbackInactiveTimeout : recorderInactiveTimeout;
}
public static void removeInactiveSessions() {
long timeNow = System.currentTimeMillis();
try {
for (Iterator<Session> iterator = sessions.values().iterator(); iterator.hasNext(); ) {
Session s = (Session) iterator.next();
if (timeNow - s.lastActiveTime() > s.getInactiveTimeout()) {
iterator.remove();
}
}
} catch (Exception e) {
e.printStackTrace();
}
System.gc();
logger.debug("sessions.size() = " + sessions.size());
}
public void setObject(String key, Object value) {
this.objectVariables.put(key, value);
}
public Object getObject(String key) {
return this.objectVariables.get(key);
}
public void addAjaxRedirect(String redirectedTo) {
logger.debug("Adding AJAX redirect for: " + redirectedTo);
ajaxRedirects.put(redirectedTo, redirectedTo);
}
public boolean isAjaxRedirect(String url) {
boolean isRedirect = ajaxRedirects.containsKey(url);
logger.debug("AJAX redirect for: " + url + ": " + isRedirect);
if (isRedirect) ajaxRedirects.remove(url);
return isRedirect;
}
public void set204(boolean is204) {
this.is204 = is204;
logger.debug("Setting is204 = " + is204);
}
public boolean is204() {
logger.debug("is204 = " + is204);
return is204;
}
public String getXHRReadyStatesToWaitFor() {
return xhrReadyStatesToWaitFor;
}
public void setXHRReadyStatesToWaitFor(String states) {
this.xhrReadyStatesToWaitFor = states;
}
}