package webIM;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
/**
* Title: Monitor
* Description: This servlet is first invoked when the user selects the link of an
* online buddy from the buddy list. It receives the buddy's name in
* a cookie, and completes the initialization of the conversation.
* This first invocation is via the form submitted from the static
* page, talk.html.
*
* Afterwards, this servlet receives POST requests from the Talk
* frame containing new chat text from the local user. It also receives
* GET requests from the buddy's Chat servlet that have a query parameter
* equal to the remote filename. Local chat submissions are written to disk
* and the filename is added to the newFilesList. The filenames from
* remote submissions are added to the newFilesList. The text form
* is redisplayed by including talk.jsp.
* Copyright: Copyright (c) 2001
* Company: UCCS Computer Science Department
* @author Merlin Vincent
* @version 1.0
*/
public class Monitor extends HttpServlet
{
private static final String CONTENT_TYPE = "text/html";
private static String endl = System.getProperty("file.separator");
// A number used to order local files. Filename format: user_buddy_ext
private int nextLocalFileExt = 0;
/**Initialize global variables*/
public void init(ServletConfig config) throws ServletException
{
super.init(config);
}
/**
* Process the HTTP Get request. This is NEVER invoked by the local user.
* The initial GET for the text input form is from a static HTML page
* rather than from this servlet.
*
* This GET is invoked when the remote user's Chat servlet has new text
* that we should retrieve. This servlet is invoked with:
*
*
*
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
ServletContext context = getServletContext();
ArrayList newFilesList = null;
// Get the newChat query parameter
String newFile = request.getParameter("newChat").trim();
if (newFile == null)
throw new ServletException("Monitor GET: no newRemoteFile parameter");
/**
* Parse out the names of the talkers so we can retrieve the global
* sequence number, whose key is of the form userBuddySeqNo.
* The new chat filename, e.g., "buddy_user_n".
*/
int endBuddy = newFile.indexOf("_");
int endUser = newFile.lastIndexOf("_");
String buddyName = newFile.substring(0, endBuddy).trim();
String userNickName = newFile.substring(endBuddy + 1, endUser).trim();
String contextKey = userNickName + buddyName;
/**
* If the buddy submits text before the local user does, the newFilesList
* will not exist - create it, and capture the selected buddy's name
* and the sequence number that tracks all received/submitted messages.
*/
newFilesList = (ArrayList) context.getAttribute( contextKey+"NewChat");
if (newFilesList == null) {
newFilesList = new ArrayList();
context.setAttribute( contextKey+"NewChat", newFilesList );
context.setAttribute( userNickName+"selectedBuddy", buddyName );
context.setAttribute( contextKey+"SeqNo", new Integer(0));
}
// Capture the buddy's filename and bump the sequence number.
synchronized (newFilesList) {
newFilesList.add( newFile );
Integer seqNo = (Integer) context.getAttribute( contextKey+"SeqNo" );
int sequenceNumber = seqNo.intValue();
context.setAttribute( contextKey+"SeqNo", new Integer(sequenceNumber + 1));
}
// Send an error response so the will fail quickly.
response.setStatus( HttpServletResponse.SC_NOT_FOUND );
}
/**Process the HTTP Post request*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String buddyName = null;
String userName = null;
String nickName = null;
int sequenceNumber = 0;
HttpSession session = request.getSession(false);
ServletContext context = getServletContext();
ArrayList newFilesList = null;
//Get the submitted text - if none, just redisplay the text input form
if (request.getContentLength() == 0) {
RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher( "/talk.jsp" );
dispatcher.include(request, response);
return;
}
// Retrieve the existing session and its variables.
if (session == null)
throw new ServletException("Monitor POST: no HttpSession");
userName = (String) session.getAttribute("username");
if (userName == null)
throw new ServletException("Monitor POST: no username in session");
nickName = (String) session.getAttribute("nickname");
if (userName == null)
throw new ServletException("Monitor POST: no nickname in session");
buddyName = (String) context.getAttribute(nickName+"selectedBuddy");
if (buddyName == null)
throw new ServletException("Monitor POST: no buddy name in session");
/**
* If this is the first call, get the selected buddy's name, init the
* sequence number that tracks all received/submitted messages, and
* create the newFilesList to hold the messages.
*/
if (buddyName.equals("none")) {
Cookie cookie;
Cookie[] cookies = request.getCookies();
if (cookies == null)
throw new ServletException("Monitor POST: no cookies available");
for(int i=0; i < cookies.length; i++) {
cookie = cookies[i];
if (cookie.getName().equals("selectedBuddy")) {
buddyName = cookie.getValue().trim();
break;
}
}
if (buddyName == null)
throw new ServletException("Monitor POST: no selectedBuddy cookie");
context.setAttribute(nickName+"selectedBuddy", buddyName);
context.setAttribute( nickName+buddyName+"SeqNo", new Integer(0));
newFilesList = new ArrayList();
context.setAttribute( nickName+buddyName+"NewChat", newFilesList );
}
/**
* Build the local filename for the submitted text. This name always
* includes the full path, so it starts with a slash. The filenames for
* remote submissions start with a character, and can be differentiated.
*/
String filename = new String(
nickName + "_" + buddyName + "_" + ( nextLocalFileExt++ ));
String path = new String("/users/server/students/" + userName +"/public_html/webIM/");
// Get the submitted text and write it to the disk file
String input = request.getParameter("inputText");
writeFile((path + filename), input);
// Add the new file and increment the global sequence number.
newFilesList = (ArrayList) context.getAttribute( nickName+buddyName+"NewChat");
if (newFilesList == null)
throw new ServletException("Monitor POST: no new files list in session");
synchronized (newFilesList) {
Integer seqNo = (Integer) context.getAttribute(nickName+buddyName+"SeqNo");
sequenceNumber = seqNo.intValue();
context.setAttribute( nickName+buddyName+"SeqNo", new Integer(sequenceNumber + 1));
newFilesList.add( path + filename );
}
// Redisplay the text input form.
RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher( "/talk.jsp" );
dispatcher.include(request, response);
}
/**
* This method writes the text submitted by the user to a disk file
* named /users/server/students/user/public_html/webIM/user_buddy_
* where is the message sequence number.
*/
private void writeFile (String filename, String inputText) throws ServletException {
File f = null;
FileOutputStream fos = null;
try {
f = new File(filename);
f.createNewFile();
if (f.exists() && f.isFile() && f.canWrite()) {
fos = new FileOutputStream( f );
byte[] txtBytes = inputText.getBytes();
fos.write( txtBytes );
fos.close();
fos = null;
}
} catch (IOException e) {
throw new ServletException("Monitor writeFile: unable to write file "+ filename);
}
finally {
if (fos != null) {
try {fos.close();} catch (IOException ioe){}
fos = null;
}
f = null;
}
}
/**Clean up resources*/
public void destroy()
{
}
}