Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: maddany/ChatServlet.java


1   package maddany;
2   
3   import java.io.*;
4   import java.net.*;
5   import javax.servlet.*;
6   import javax.servlet.http.*;
7   import java.util.Vector;
8   import java.util.Hashtable;
9   import java.util.Enumeration;
10  import java.util.StringTokenizer;
11  import java.util.Random;
12  
13  public class ChatServlet extends HttpServlet implements Analyzer, Wakable {
14      private final String validChars = "abcdefghijklmnopqrstuvwxyz";
15      public final static int IDENT_LENGTH = 3;
16      public final static int TIMEOUT = 120;
17      public final static int PORT = 4242;
18      private Vector pool;
19      private Random r; 
20      private ChatListener listener;
21    //  private ChatMainFrame win;
22  
23      public void init(ServletConfig conf) throws ServletException {
24          super.init(conf);
25          pool = new Vector();
26          r = new Random();
27          listener = new ChatListener(PORT, this);
28  
29    // en friche : une fenetre d'administration en local
30    /*    win = new ChatMainFrame("mad/chatmin");
31          win.resize(300, 200);
32          win.show();  */
33      }
34  
35      public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
36          res.setContentType("text/html");
37          PrintWriter out = res.getWriter();
38    //      String local = InetAddress.getLocalHost().getHostAddress();
39          out.println("<html><head><title>Welcome, you lamah</title>\n" +
40                      "<body>\n" +
41                    //  "<p align=center>Ready for some test version ?</p>\n" +
42                      "<p align=center>\n" +
43                      "    <applet code=ChatApplet.class codebase=/maddany/applet width=90% height=90%>\n" +
44                      "        <param name=port value="+PORT+">\n" +
45                      "    </applet>\n" +
46                      "</p>\n" +
47                      "</body>\n" +
48                      "</html>");
49          out.close();
50      }
51  
52      public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
53          String str;
54          str=req.getReader().readLine();
55    //      PrintWriter out = res.getWriter();
56          analyze(str, null);
57      }
58  
59      public synchronized String analyze(String toAnalyze, ChatHandler generator) {
60          String command = extractCommand(toAnalyze);
61          String param = extractParam(toAnalyze);
62          if(command==null|param==null) {
63              System.out.println("Missing args");
64              return "SERVER ERROR\r\n";   // "darn you"
65          }
66          String ident = param.length()>=IDENT_LENGTH?param.substring(0, IDENT_LENGTH).toUpperCase():"";
67  
68          //IDENT dans ChatHandshaker
69  
70          if(command.equals("SEND")) { 
71              int idx = param.indexOf(",");
72              if(idx>=0&&generator.isValid(new SequenceAuthenticator(param.substring(0, idx), IDENT_LENGTH))) {
73                  // argument : après l'authentificateur
74                  String str=param.substring(idx+1, param.length()).replace('<','?');    // /!\
75                  if(isValidInput(str)) {
76                      broadcast("<"+generator.getNick()+"> "+str, generator);
77                      return "SEND OK\r\n";
78                  } else {
79                      return "SEND GROU\r\n";
80                  }
81              } else {
82                  return "SEND GROU\r\n";
83              }
84          } else if(command.equals("AINT")) {
85              return "";
86          } else if(command.equals("LOGOUT")){
87              if(generator.isValid(new SequenceAuthenticator(param, IDENT_LENGTH))) {
88                  generator.write("LOGOUT BYE\r\n");
89                  logUserOut(ident);
90                  return "";
91              } else {
92                  return "LOGOUT GROU\r\n";
93              }
94          } else if(command.equals("LIST")) {
95              if(generator!=null&&generator.isValid(new SequenceAuthenticator(param, IDENT_LENGTH)))
96                  return "LIST "+singleList()+"\r\n";
97              else
98                  return "LIST GROU\r\n";
99          }
100         return "BAD CMD,"+command+"\r\n";
101     }
102 
103     private synchronized void broadcast(String tosend, ChatHandler generator) {
104         if(tosend.startsWith("<")) 
105             internalBroadcast("PUT "+tosend+"\r\n", generator);
106         else 
107             internalBroadcast(tosend, generator);
108     }
109 
110     private synchronized void internalBroadcast(String tosend, ChatHandler generator) {
111         Enumeration en = poolElements();
112         while(en.hasMoreElements()) {
113             ChatHandler sender = (ChatHandler)en.nextElement();
114             if(sender!=generator) {
115                 sender.write(tosend);
116             }
117         }
118     }
119 
120     public Vector getThreadPool() {
121         return pool;
122     }
123 
124     public void addToPool(Object obj) {
125         System.out.println("Adding "+obj.toString());
126         pool.add(obj);
127         broadcast("LIST "+singleList()+"\r\n", null);
128     }
129 
130     public void removeFromPool(Object obj) {
131         System.out.println("Removing "+obj.toString());
132         pool.remove(obj);
133         broadcast("LIST "+singleList()+"\r\n", null);
134     }
135 
136     public Enumeration poolElements() {
137         synchronized (pool) {
138             return pool.elements();
139         }
140     }
141 
142     public void wakeUp() {}
143 
144     public void wakeUp(Object obj) {
145         try {
146             ChatHandler handler = (ChatHandler)obj;
147             handler.start();   //addToPool inclus
148         } catch(ClassCastException e) {
149             e.printStackTrace();
150         }
151     }
152 
153     public synchronized String logUserIn(String nick, Socket sck) {
154         String ident = getIdent(nick);
155         if(!containsIdentifier(ident)&&isValidNick(nick)) {
156             long seq = r.nextLong();
157             wakeUp(new ChatHandler(sck, nick, new SequenceAuthenticator(ident, seq), this));
158             return String.valueOf(seq);
159         } else {
160             return null;
161         }
162     }
163 
164     private void logUserOut(String ident) {
165         ChatHandler handler = getHandlerByIdent(ident);
166         if(handler!=null) {
167             handler.stop();
168         }
169     }
170 
171     public synchronized boolean containsIdentifier(String ident) {
172         Enumeration e = poolElements();
173         while(e.hasMoreElements()) {
174             ChatHandler handler = (ChatHandler)e.nextElement();
175             if(ident.equalsIgnoreCase(handler.getIdentifier()))
176                 return true;
177         }
178         return false;
179     }
180 
181     public ChatHandler getHandlerByIdent(String ident) {
182         synchronized(pool) {
183             Enumeration e = pool.elements();
184             while(e.hasMoreElements()) {
185                 ChatHandler handler = (ChatHandler)e.nextElement();
186                 if(ident.equalsIgnoreCase(handler.getIdentifier()))
187                     return handler;
188             }
189             return null;
190         }
191     }
192 
193     private String getIdent(String nick) {
194         return nick.substring(0, IDENT_LENGTH).toUpperCase();
195     }
196 
197     private String singleList() {
198         synchronized(pool) {
199             StringBuffer buf = new StringBuffer();
200             Enumeration en = pool.elements();
201             while(en.hasMoreElements()) {
202                 buf.append(((ChatHandler)en.nextElement()).getNick());
203                 buf.append(',');
204             }
205             if(buf.length()>0)
206                 buf.deleteCharAt(buf.length()-1);
207             return buf.toString();
208         }
209     }
210 
211     private boolean isValidInput(String str) {
212         if(str.length()==0|str.length()>1800)
213             return false;
214         else
215             return true;
216     }
217 
218     private boolean isValidNick(String nick) {
219         if(nick.length()<3||nick.length()>10)
220             return false;
221         for(int i=0; i<nick.length(); i++) {
222             String ch = String.valueOf(nick.charAt(i));
223             if(validChars.indexOf(ch)<0)
224                 return false;
225         }
226         return true;
227     }
228 
229     public static String extractCommand(String response) {
230         if(response.indexOf(' ')>0)
231             return response.substring(0, response.indexOf(" "));
232         else
233             return "";
234     }
235 
236     public static String extractParam(String response) {
237         if(response.indexOf(' ')>0)
238             return response.substring(response.indexOf(" ")+1, response.length()).trim();
239         else
240             return "";
241     }
242 }
243 
244 
245 class ChatHandler implements Runnable {
246     private Analyzer parent;
247     private Socket sock;
248     private PrintWriter out;
249     private BufferedReader in;
250     private Thread gate;
251     private String nick;
252     private SequenceAuthenticator auth;
253     private SequenceAuthenticatorManager manager;
254     private InetAddress addr;
255 
256     public ChatHandler(Socket sock, String nick, SequenceAuthenticator auth, Analyzer parent) {
257         this.sock = sock;
258         this.parent = parent;
259         this.nick = nick;
260         this.auth = auth;
261         manager = new SequenceAuthenticatorManager();
262         manager.add(auth); 
263         addr = sock.getInetAddress();
264         gate = new Thread(this);
265     }
266 
267     public void start() {
268         try {
269             if(in==null) {
270                 in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
271                 out = new PrintWriter(sock.getOutputStream());
272                 parent.addToPool(this);
273                 gate.start();
274             }
275         } catch(IOException e) {
276             e.printStackTrace();
277         }
278     }
279 
280     public void stop() {
281         try {
282             if(gate!=null&&sock!=null) {
283                 write("CLOSE LINK\r\n");
284                 gate.interrupt();
285                 gate = null;
286                 sock.close();
287                 in.close();
288                 out.close();
289             }
290         } catch(IOException e) {
291             e.printStackTrace();
292         } finally {
293             parent.removeFromPool(this);
294         }
295     }
296 
297     public void run() {
298         try {
299             while(Thread.currentThread()==gate) {
300                 String str = in.readLine();
301               //  System.out.println(str+".");
302                 String response = parent.analyze(str, this);
303                 if(response.length()>0)
304                     write(response);
305             }
306         } catch(Exception e) {
307             System.out.println("Error message : "+e.getMessage());
308         } finally {
309             stop();
310         }
311     }
312 
313     public synchronized void write(String str) {
314         write(str, true);
315     }
316 
317     public synchronized void write(String str, boolean flush) {
318         out.write(str);
319         if(flush)
320             out.flush();
321     }
322 
323     public void flush() {
324         out.flush();
325     }
326 
327     public String getNick() {
328         return nick;
329     }
330 
331     public String getIdentifier() {
332         return auth.getIdentifier();
333     }
334 
335     public SequenceAuthenticator getSA() {
336         return auth;
337     }
338 
339     public SequenceAuthenticator incrementSA() {
340         auth.incrementSequence();   //updateTime() inclus
341         manager.setElementAt(auth, 0);
342         return auth;
343     }
344 
345     public boolean isValid(SequenceAuthenticator auth) {
346         return manager.isValid(auth);
347     }
348 
349     public String toString() {
350         StringBuffer buf = new StringBuffer(nick);
351         buf.append(" [");
352         buf.append(addr.getHostAddress());
353         buf.append("]; ");
354         buf.append(auth.toString());
355         return buf.toString();
356     }
357 }