source: nutchez-0.1/tomcat/webapps/examples/WEB-INF/classes/chat/ChatServlet.java @ 186

Last change on this file since 186 was 66, checked in by waue, 16 years ago

NutchEz - an easy way to nutch

File size: 9.1 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
19package chat;
20
21
22import java.io.IOException;
23import java.io.InputStream;
24import java.io.PrintWriter;
25import java.util.ArrayList;
26
27import org.apache.catalina.CometEvent;
28import org.apache.catalina.CometProcessor;
29
30import javax.servlet.ServletException;
31import javax.servlet.http.HttpServlet;
32import javax.servlet.http.HttpServletRequest;
33import javax.servlet.http.HttpServletResponse;
34
35
36/**
37 * Helper class to implement Comet functionality.
38 */
39public class ChatServlet
40    extends HttpServlet implements CometProcessor {
41
42    protected ArrayList<HttpServletResponse> connections = 
43        new ArrayList<HttpServletResponse>();
44    protected MessageSender messageSender = null;
45   
46    public void init() throws ServletException {
47        messageSender = new MessageSender();
48        Thread messageSenderThread = 
49            new Thread(messageSender, "MessageSender[" + getServletContext().getContextPath() + "]");
50        messageSenderThread.setDaemon(true);
51        messageSenderThread.start();
52    }
53
54    public void destroy() {
55        connections.clear();
56        messageSender.stop();
57        messageSender = null;
58    }
59
60    /**
61     * Process the given Comet event.
62     *
63     * @param event The Comet event that will be processed
64     * @throws IOException
65     * @throws ServletException
66     */
67    public void event(CometEvent event)
68        throws IOException, ServletException {
69
70        // Note: There should really be two servlets in this example, to avoid
71        // mixing Comet stuff with regular connection processing
72        HttpServletRequest request = event.getHttpServletRequest();
73        HttpServletResponse response = event.getHttpServletResponse();
74       
75        if (event.getEventType() == CometEvent.EventType.BEGIN) {
76            String action = request.getParameter("action");
77            if (action != null) {
78                if ("login".equals(action)) {
79                    String nickname = request.getParameter("nickname");
80                    request.getSession(true).setAttribute("nickname", nickname);
81                    response.sendRedirect("post.jsp");
82                    event.close();
83                    return;
84                } else {
85                    String nickname = (String) request.getSession(true).getAttribute("nickname");
86                    String message = request.getParameter("message");
87                    messageSender.send(nickname, message);
88                    response.sendRedirect("post.jsp");
89                    event.close();
90                    return;
91                }
92            } else {
93                if (request.getSession(true).getAttribute("nickname") == null) {
94                    // Redirect to "login"
95                    log("Redirect to login for session: " + request.getSession(true).getId());
96                    response.sendRedirect("login.jsp");
97                    event.close();
98                    return;
99                }
100            }
101            begin(event, request, response);
102        } else if (event.getEventType() == CometEvent.EventType.ERROR) {
103            error(event, request, response);
104        } else if (event.getEventType() == CometEvent.EventType.END) {
105            end(event, request, response);
106        } else if (event.getEventType() == CometEvent.EventType.READ) {
107            read(event, request, response);
108        }
109    }
110
111    protected void begin(CometEvent event, HttpServletRequest request, HttpServletResponse response)
112        throws IOException, ServletException {
113        log("Begin for session: " + request.getSession(true).getId());
114       
115        PrintWriter writer = response.getWriter();
116        writer.println("<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">");
117        writer.println("<html><head><title>JSP Chat</title></head><body bgcolor=\"#FFFFFF\">");
118        writer.flush();
119
120        synchronized(connections) {
121            connections.add(response);
122        }
123    }
124   
125    protected void end(CometEvent event, HttpServletRequest request, HttpServletResponse response)
126        throws IOException, ServletException {
127        log("End for session: " + request.getSession(true).getId());
128        synchronized(connections) {
129            connections.remove(response);
130        }
131       
132        PrintWriter writer = response.getWriter();
133        writer.println("</body></html>");
134       
135        event.close();
136       
137    }
138   
139    protected void error(CometEvent event, HttpServletRequest request, HttpServletResponse response)
140        throws IOException, ServletException {
141        log("Error for session: " + request.getSession(true).getId());
142        synchronized(connections) {
143            connections.remove(response);
144        }
145        event.close();
146    }
147   
148    protected void read(CometEvent event, HttpServletRequest request, HttpServletResponse response)
149        throws IOException, ServletException {
150        InputStream is = request.getInputStream();
151        byte[] buf = new byte[512];
152        while (is.available() > 0) {
153            log("Available: " + is.available());
154            int n = is.read(buf);
155            if (n > 0) {
156                log("Read " + n + " bytes: " + new String(buf, 0, n) 
157                        + " for session: " + request.getSession(true).getId());
158            } else if (n < 0) {
159                log("End of file: " + n);
160                end(event, request, response);
161                return;
162            }
163        }
164    }
165
166    protected void service(HttpServletRequest request, HttpServletResponse response)
167        throws IOException, ServletException {
168        // Compatibility method: equivalent method using the regular connection model
169        PrintWriter writer = response.getWriter();
170        writer.println("<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">");
171        writer.println("<html><head><title>JSP Chat</title></head><body bgcolor=\"#FFFFFF\">");
172        writer.println("Chat example only supports Comet processing");
173        writer.println("</body></html>");
174    }
175   
176
177    /**
178     * Poller class.
179     */
180    public class MessageSender implements Runnable {
181
182        protected boolean running = true;
183        protected ArrayList<String> messages = new ArrayList<String>();
184       
185        public MessageSender() {
186        }
187       
188        public void stop() {
189            running = false;
190        }
191
192        /**
193         * Add specified socket and associated pool to the poller. The socket will
194         * be added to a temporary array, and polled first after a maximum amount
195         * of time equal to pollTime (in most cases, latency will be much lower,
196         * however).
197         *
198         * @param socket to add to the poller
199         */
200        public void send(String user, String message) {
201            synchronized (messages) {
202                messages.add("[" + user + "]: " + message);
203                messages.notify();
204            }
205        }
206
207        /**
208         * The background thread that listens for incoming TCP/IP connections and
209         * hands them off to an appropriate processor.
210         */
211        public void run() {
212
213            // Loop until we receive a shutdown command
214            while (running) {
215                // Loop if endpoint is paused
216
217                if (messages.size() == 0) {
218                    try {
219                        synchronized (messages) {
220                            messages.wait();
221                        }
222                    } catch (InterruptedException e) {
223                        // Ignore
224                    }
225                }
226
227                synchronized (connections) {
228                    String[] pendingMessages = null;
229                    synchronized (messages) {
230                        pendingMessages = messages.toArray(new String[0]);
231                        messages.clear();
232                    }
233                    for (int i = 0; i < connections.size(); i++) {
234                        try {
235                            PrintWriter writer = connections.get(i).getWriter();
236                            for (int j = 0; j < pendingMessages.length; j++) {
237                                // FIXME: Add HTML filtering
238                                writer.println(pendingMessages[j] + "<br/>");
239                            }
240                            writer.flush();
241                        } catch (IOException e) {
242                            log("IOExeption sending message", e);
243                        }
244                    }
245                }
246
247            }
248
249        }
250
251    }
252
253
254
255
256}
Note: See TracBrowser for help on using the repository browser.