//======================================================================== //$Id: ChatFilter.java,v 1.4 2005/11/14 11:00:33 gregwilkins Exp $ //Copyright 2004-2005 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //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 com.acme; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.mortbay.util.ajax.AjaxFilter; import org.mortbay.util.ajax.Continuation; import org.mortbay.util.ajax.ContinuationSupport; /** * @author gregw * @deprecated Use Cometd */ public class ChatFilter extends AjaxFilter { private Map chatrooms; /* ------------------------------------------------------------ */ /* * @see org.mortbay.ajax.AjaxFilter#init(javax.servlet.FilterConfig) */ public void init(FilterConfig filterConfig) throws ServletException { super.init(filterConfig); chatrooms=new HashMap(); } /* ------------------------------------------------------------ */ /* * @see org.mortbay.ajax.AjaxFilter#destroy() */ public void destroy() { super.destroy(); chatrooms.clear(); chatrooms=null; } /* ------------------------------------------------------------ */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpSession session = ((HttpServletRequest)request).getSession(true); super.doFilter(request,response,chain); } /* ------------------------------------------------------------ */ /* * @see org.mortbay.ajax.AjaxFilter#handle(java.lang.String, javax.servlet.http.HttpServletRequest, org.mortbay.ajax.AjaxFilter.AjaxResponse) */ public void handle(String method, String message, HttpServletRequest request, AjaxResponse response) { request.getSession(true); String roomName=request.getParameter("room"); if (roomName==null) roomName="0"; Map room = null; synchronized(this) { room=(Map)chatrooms.get(roomName); if (room==null) { room=new HashMap(); chatrooms.put(roomName,room); } } if ("join".equals(method)) doJoinChat(room,message,request, response); else if ("chat".equals(method)) doChat(room,message,request,response); else if ("poll".equals(method)) doPoll(room,request,response); else if ("leave".equals(method)) doLeaveChat(room,message,request,response); else super.handle(method, message,request, response); } /* ------------------------------------------------------------ */ private void doJoinChat(Map room, String name, HttpServletRequest request, AjaxResponse response) { HttpSession session = request.getSession(true); String id = session.getId(); if (name==null || name.length()==0) name="Newbie"; Member member=null; synchronized (room) { member=(Member)room.get(id); if (member==null) { member = new Member(session,name); room.put(session.getId(),member); } else member.setName(name); // exists already, so just update name sendMessage(room,member,"has joined the chat",true); //response.objectResponse("joined", ""); sendMembers(room,response); } } /* ------------------------------------------------------------ */ private void doLeaveChat(Map room, String name, HttpServletRequest request, AjaxResponse response) { HttpSession session = request.getSession(true); String id = session.getId(); Member member=null; synchronized (room) { member = (Member)room.get(id); if (member==null) return; if ("Elvis".equals(member.getName())) sendMessage(room,member,"has left the building",true); else sendMessage(room,member,"has left the chat",true); room.remove(id); member.setName(null); } //response.objectResponse("left", ""); sendMembers(room,response); } /* ------------------------------------------------------------ */ private void doChat(Map room, String text, HttpServletRequest request, AjaxResponse response) { HttpSession session = request.getSession(true); String id = session.getId(); Member member=null; synchronized (room) { member = (Member)room.get(id); if (member==null) return; sendMessage(room, member, text, false); } } /* ------------------------------------------------------------ */ private void doPoll(Map room, HttpServletRequest request, AjaxResponse response) { HttpSession session = request.getSession(true); String id = session.getId(); long timeoutMS = 60000L; if (request.getParameter("timeout")!=null) timeoutMS=Long.parseLong(request.getParameter("timeout")); if (session.isNew()) timeoutMS=1; Member member=null; synchronized (room) { member = (Member)room.get(id); if (member==null) { member = new Member(session,null); room.put(session.getId(),member); } Continuation continuation = ContinuationSupport.getContinuation(request, room); if (!member.hasMessages()) { if (member.getContinuation()!=null && member.getContinuation()!=continuation) { // duplicate frames! Message duplicate = new Message("System","Multiple frames/tabs/windows from same browser!",true); Message action = new Message("System","Please use only one frame/tab/window",true); member.addMessage(duplicate); member.addMessage(action); try { Thread.sleep(5000); } catch(Exception e) {} } else { member.setContinuation(continuation); continuation.suspend(timeoutMS); } } if (member.getContinuation()==continuation) member.setContinuation(null); if (member.sendMessages(response)) sendMembers(room,response); } } /* ------------------------------------------------------------ */ private void sendMessage(Map room, Member member, String text, boolean alert) { Message event=new Message(member.getName(),text,alert); ArrayList invalids=null; synchronized (room) { Iterator iter = room.values().iterator(); while (iter.hasNext()) { Member m = (Member)iter.next(); try { m.getSession().getAttribute("anything"); m.addMessage(event); } catch(IllegalStateException e) { if (invalids==null) invalids=new ArrayList(); invalids.add(m); iter.remove(); } } } for (int i=0;invalids!=null && i\n"); synchronized (room) { Iterator iter = room.values().iterator(); while (iter.hasNext()) { Member m = (Member)iter.next(); if (m.getName()==null) continue; buf.append("
  • "); buf.append(encodeText(m.getName())); buf.append("
  • \n"); } } buf.append("\n"); response.elementResponse("members", buf.toString()); } private static class Message { private String _from; private String _text; private boolean _alert; Message(String from, String text, boolean alert) { _from=from; _text=text; _alert=alert; } boolean isAlert() { return _alert; } public String toString() { return ""+encodeText(_text)+""; } } private class Member { private HttpSession _session; private String _name; private List _messages = new ArrayList(); private Continuation _continuation; Member(HttpSession session, String name) { _session=session; _name=name; } /* ------------------------------------------------------------ */ /** * @return Returns the name. */ public String getName() { return _name; } /* ------------------------------------------------------------ */ /** * @param name The name to set. */ public void setName(String name) { _name = name; } /* ------------------------------------------------------------ */ /** * @return Returns the session. */ public HttpSession getSession() { return _session; } /* ------------------------------------------------------------ */ /** * @param continuation The continuation to set. */ public Continuation getContinuation() { return _continuation; } /* ------------------------------------------------------------ */ /** * @param continuation The continuation to set. */ public void setContinuation(Continuation continuation) { if (continuation!=null && _continuation!=null && _continuation!=continuation) _continuation.resume(); _continuation=continuation; } /* ------------------------------------------------------------ */ public void addMessage(Message event) { if (_name==null) return; _messages.add(event); if (_continuation!=null) _continuation.resume(); } /* ------------------------------------------------------------ */ public boolean hasMessages() { return _messages!=null && _messages.size()>0; } /* ------------------------------------------------------------ */ public void rename(Map room,String name) { String oldName = getName(); setName(name); if (oldName!=null) ChatFilter.this.sendMessage(room,this,oldName+" has been renamed to "+name,true); } /* ------------------------------------------------------------ */ public boolean sendMessages(AjaxResponse response) { synchronized (this) { boolean alerts=false; for (int i=0;i<_messages.size();i++) { Message event = (Message)_messages.get(i); response.objectResponse("chat", event.toString()); alerts |= event.isAlert(); } _messages.clear(); return alerts; } } } }