/*
* $Id: SessionClient.java,v 1.3 2002/09/16 08:05:07 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.session.net;
import java.net.Socket;
import java.net.SocketException;
import java.net.InetAddress;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintStream;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.BufferedOutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.StringTokenizer;
import javax.servlet.ServletOutputStream;
import anvil.Log;
import anvil.core.Serialization;
import anvil.core.UnserializationException;
import anvil.core.Any;
import anvil.server.Zone;
import anvil.java.lang.Task;
import anvil.java.io.GenericInputStream;
import anvil.java.util.BindingEnumeration;
import anvil.session.Session;
import anvil.script.Context;
import anvil.util.Conversions;
/**
* class SessionClient
*
* @author: Jani Lehtim�ki
*/
public class SessionClient implements Task
{
private ServerSessionContainer _container;
private SessionServer _listener;
private Zone _zone;
private Log _log;
private Socket _socket;
private ByteArrayOutputStream _buffer = null;
private Context _context = null;
public SessionClient(SessionServer listener, Socket socket)
{
_container = listener.getContainer();
_listener = listener;
_zone = listener.getZone();
_log = listener.log();
_socket = socket;
}
public void shutdown()
{
synchronized(_socket) {
if (_socket != null) {
try {
_socket.close();
} catch (Throwable t) {
}
_socket = null;
}
}
}
public void overload()
{
synchronized(_socket) {
if (_socket != null) {
try {
_socket.close();
} catch (Throwable t) {
}
_socket = null;
}
}
}
public void run()
{
Socket socket;
synchronized(_socket) {
socket = _socket;
if (socket == null) {
return;
}
}
_context = new Context(_zone);
InetAddress address = socket.getInetAddress();
GenericInputStream input = null;
PrintStream output = null;
String hostname = address.getHostName();
_log.info("Connection from "+hostname);
try {
boolean firstrequest = true;
socket.setSoTimeout(0);
input = new GenericInputStream(socket.getInputStream());
output = new PrintStream(new BufferedOutputStream(socket.getOutputStream()));
handleRequest(input, output);
} catch (InterruptedIOException e) {
_log.debug("Connection from "+address.getHostName()+" timed out.");
} catch (SocketException e) {
_log.error("Connection from "+address.getHostName()+": "+e.getMessage());
} catch (IOException e) {
_log.error("Connection from "+address.getHostName(), e);
} catch (Throwable t) {
_log.error("Connection from "+address.getHostName(), t);
} finally {
if (input != null) {
try {
input.close();
} catch (Throwable t) {
}
}
if (output != null) {
try {
output.close();
} catch (Throwable t) {
}
}
if (socket != null) {
try {
socket.close();
} catch (Throwable t) {
}
}
_context.destroy();
_context = null;
_socket = null;
}
_log.info("Connection from "+address.getHostName()+" closed");
}
public void handleRequest(GenericInputStream input, PrintStream output) throws IOException
{
try {
while(true) {
if (output.checkError()) {
break;
}
String line = input.readLine();
if (line == null) {
break;
}
StringTokenizer tokenizer = new StringTokenizer(line, ",");
int n = tokenizer.countTokens();
if (n > 0) {
String request[] = new String[n];
for(int i=0; i<n; i++) {
request[i] = tokenizer.nextToken();
}
String verb = request[0];
if (verb.equals("bye")) {
break;
} else if (verb.equals("create")) {
handleCreate(input, output, request);
} else if (verb.equals("get")) {
handleGet(input, output, request);
} else if (verb.equals("touch")) {
handleTouch(input, output, request);
} else if (verb.equals("invalidate")) {
handleInvalidate(input, output, request);
} else if (verb.equals("validate")) {
handleValidate(input, output, request);
} else if (verb.equals("store")) {
handleStore(input, output, request);
} else if (verb.equals("dispose")) {
handleDispose(input, output, request);
} else if (verb.equals("fetch")) {
handleFetch(input, output, request);
} else if (verb.equals("names")) {
handleNames(input, output, request);
} else if (verb.equals("list")) {
handleList(input, output, request);
} else if (verb.equals("getcitizen")) {
handleGetCitizen(input, output, request);
} else if (verb.equals("setcitizen")) {
handleSetCitizen(input, output, request);
} else {
// skip
}
}
}
} catch (InterruptedIOException e) {
}
}
// create,<lifetime>,<timeout>
public static final int parseInt(String str, int defaultValue)
{
try {
return Integer.parseInt(str);
} catch (NumberFormatException e) {
return defaultValue;
}
}
protected void printSession(PrintStream output, Session session)
{
output.println(session.getId());
output.println(session.getCreationTime());
output.println(session.getLastAccessTime());
}
public void handleCreate(GenericInputStream input, PrintStream output, String[] request) throws IOException
{
int lifetime = 3600;
int timeout = 3000;
int n = request.length;
if (n>1) {
lifetime = parseInt(request[2], 3600);
if (n>2) {
timeout = parseInt(request[2], 3000);
}
}
Session session = _container.createSession(lifetime, timeout);
printSession(output, session);
output.flush();
}
public void handleList(GenericInputStream input, PrintStream output, String[] request) throws IOException
{
Session[] sessions = _container.getSessions();
int n = sessions.length;
output.println(n);
for(int i=0; i<n; i++) {
printSession(output, sessions[i]);
}
output.flush();
}
public void handleTouch(GenericInputStream input, PrintStream output, String[] request) throws IOException
{
int n = request.length;
if (n>1) {
String id = request[1];
Session session = _container.getSession(id);
if (session != null) {
//session.touch();
output.println("ok");
output.flush();
return;
}
}
output.println("fail");
output.flush();
}
public void handleGet(GenericInputStream input, PrintStream output, String[] request) throws IOException
{
int n = request.length;
if (n>1) {
String id = request[1];
Session session = _container.getSession(id);
if (session != null) {
//session.touch();
output.println("ok");
printSession(output, session);
output.flush();
return;
}
}
output.println("fail");
output.flush();
}
public void handleInvalidate(GenericInputStream input, PrintStream output, String[] request) throws IOException
{
if (request.length>1) {
String id = request[1];
Session session = _container.getSession(id);
if (session != null) {
session.invalidate();
output.println("ok");
output.flush();
return;
}
}
output.println("fail");
output.flush();
}
public void handleValidate(GenericInputStream input, PrintStream output, String[] request) throws IOException
{
if (request.length>1) {
String id = request[1];
Session session = _container.getSession(id);
if (session != null) {
if (session.validate()) {
output.println("valid");
} else {
output.println("invalid");
}
output.flush();
return;
}
}
output.println("fail");
output.flush();
}
public void handleStore(GenericInputStream input, PrintStream output, String[] request) throws IOException
{
if (request.length>2) {
String id = request[1];
String name = Conversions.URLDecode(request[2]);
Session session = _container.getSession(id);
if (session != null) {
try {
Any data = Serialization.unserialize(_context, input);
session.setAttribute(name, data);
output.println("ok");
output.flush();
return;
} catch (UnserializationException e) {
}
}
}
output.println("fail");
output.flush();
}
public void handleFetch(GenericInputStream input, PrintStream output, String[] request) throws IOException
{
if (request.length>2) {
String id = request[1];
String name = Conversions.URLDecode(request[2]);
Session session = _container.getSession(id);
if (session != null) {
Object obj = session.getAttribute(name);
if (obj != null) {
Any data = Any.create(obj);
output.println("ok");
Serialization.serialize(_context, data, output);
output.flush();
return;
}
}
}
output.println("fail");
output.flush();
}
public void handleDispose(GenericInputStream input, PrintStream output, String[] request) throws IOException
{
if (request.length>2) {
String id = request[1];
String name = Conversions.URLDecode(request[2]);
Session session = _container.getSession(id);
if (session != null) {
session.removeAttribute(name);
output.println("ok");
output.flush();
return;
}
}
output.println("fail");
output.flush();
}
public void handleNames(GenericInputStream input, PrintStream output, String[] request) throws IOException
{
if (request.length>1) {
String id = request[1];
Session session = _container.getSession(id);
if (session != null) {
output.println("ok");
BindingEnumeration enum = session.enumeration();
ArrayList list = new ArrayList();
while(enum.hasMoreElements()) {
list.add(enum.nextKey());
enum.nextElement();
}
int n = list.size();
output.println(n);
for(int i=0; i<n; i++) {
output.println(list.get(i));
}
output.flush();
return;
}
}
output.println("fail");
output.flush();
}
public void handleSetCitizen(GenericInputStream input, PrintStream output, String[] request) throws IOException
{
if (request.length>2) {
String id = request[1];
String citizen = Conversions.URLDecode(request[2]);
Session session = _container.getSession(id);
if (session != null) {
session.setCitizen(citizen);
output.println("ok");
output.flush();
return;
}
}
output.println("fail");
output.flush();
}
public void handleGetCitizen(GenericInputStream input, PrintStream output, String[] request) throws IOException
{
if (request.length>1) {
String id = request[1];
Session session = _container.getSession(id);
if (session != null) {
String citizen = session.getCitizen();
output.println("ok");
if (citizen != null) {
output.println(citizen);
} else {
output.println();
}
output.flush();
return;
}
}
output.println("fail");
output.flush();
}
}