KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > roblisa > classfinder > WebHandler


1 /**
2  * ClassFinder - a javadoc webserver.
3  * Copyright (C) 2003 Rob Nielsen
4  * rob@roblisa.com
5  * http://www.roblisa.com/java/classfinder/
6  *
7  * Released under the GNU GPL - http://www.gnu.org/copyleft/gpl.html
8  */

9 package com.roblisa.classfinder;
10
11 import java.io.*;
12 import java.net.*;
13 import java.util.*;
14 import java.text.*;
15
16 public abstract class WebHandler implements Runnable
17 {
18     /** 2XX: generally "OK" */
19     public static final int HTTP_OK = 200;
20     public static final int HTTP_CREATED = 201;
21     public static final int HTTP_ACCEPTED = 202;
22     public static final int HTTP_NOT_AUTHORITATIVE = 203;
23     public static final int HTTP_NO_CONTENT = 204;
24     public static final int HTTP_RESET = 205;
25     public static final int HTTP_PARTIAL = 206;
26
27     /** 3XX: relocation/redirect */
28     public static final int HTTP_MULT_CHOICE = 300;
29     public static final int HTTP_MOVED_PERM = 301;
30     public static final int HTTP_MOVED_TEMP = 302;
31     public static final int HTTP_SEE_OTHER = 303;
32     public static final int HTTP_NOT_MODIFIED = 304;
33     public static final int HTTP_USE_PROXY = 305;
34
35     /** 4XX: client error */
36     public static final int HTTP_BAD_REQUEST = 400;
37     public static final int HTTP_UNAUTHORIZED = 401;
38     public static final int HTTP_PAYMENT_REQUIRED = 402;
39     public static final int HTTP_FORBIDDEN = 403;
40     public static final int HTTP_NOT_FOUND = 404;
41     public static final int HTTP_BAD_METHOD = 405;
42     public static final int HTTP_NOT_ACCEPTABLE = 406;
43     public static final int HTTP_PROXY_AUTH = 407;
44     public static final int HTTP_CLIENT_TIMEOUT = 408;
45     public static final int HTTP_CONFLICT = 409;
46     public static final int HTTP_GONE = 410;
47     public static final int HTTP_LENGTH_REQUIRED = 411;
48     public static final int HTTP_PRECON_FAILED = 412;
49     public static final int HTTP_ENTITY_TOO_LARGE = 413;
50     public static final int HTTP_REQ_TOO_LONG = 414;
51     public static final int HTTP_UNSUPPORTED_TYPE = 415;
52
53     /** 5XX: server error */
54     public static final int HTTP_SERVER_ERROR = 500;
55     public static final int HTTP_INTERNAL_ERROR = 501;
56     public static final int HTTP_BAD_GATEWAY = 502;
57     public static final int HTTP_UNAVAILABLE = 503;
58     public static final int HTTP_GATEWAY_TIMEOUT = 504;
59     public static final int HTTP_VERSION = 505;
60
61     private static final int MAX_HANDLERS=5;
62
63     private static final String IF_MODIFIED_SINCE="If-Modified-Since: ";
64
65      /* mapping of file extensions to content-types */
66     private static final Map mimeTypes = new HashMap();
67
68     static
69     {
70         mimeTypes.put("", "content/unknown");
71         mimeTypes.put(".uu", "application/octet-stream");
72         mimeTypes.put(".exe", "application/octet-stream");
73         mimeTypes.put(".ps", "application/postscript");
74         mimeTypes.put(".zip", "application/zip");
75         mimeTypes.put(".sh", "application/x-shar");
76         mimeTypes.put(".tar", "application/x-tar");
77         mimeTypes.put(".snd", "audio/basic");
78         mimeTypes.put(".au", "audio/basic");
79         mimeTypes.put(".wav", "audio/x-wav");
80         mimeTypes.put(".gif", "image/gif");
81         mimeTypes.put(".jpg", "image/jpeg");
82         mimeTypes.put(".jpeg", "image/jpeg");
83         mimeTypes.put(".htm", "text/html");
84         mimeTypes.put(".html", "text/html");
85         mimeTypes.put(".text", "text/plain");
86         mimeTypes.put(".c", "text/plain");
87         mimeTypes.put(".cc", "text/plain");
88         mimeTypes.put(".c++", "text/plain");
89         mimeTypes.put(".h", "text/plain");
90         mimeTypes.put(".pl", "text/plain");
91         mimeTypes.put(".txt", "text/plain");
92         mimeTypes.put(".java", "text/x-java-source");
93         mimeTypes.put(".lnk", "text/plain");
94         mimeTypes.put(".css", "text/css");
95     }
96
97     private static DateFormat df=new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss zzz");
98     static
99     {
100         df.setTimeZone(TimeZone.getTimeZone("GMT"));
101     }
102
103     static final byte[] EOL = {(byte)'\r', (byte)'\n' };
104     static List handlers=new ArrayList();
105     static PrintStream log = System.out;
106
107     private Socket s;
108     private PrintStream ps;
109     private ByteArrayOutputStream content;
110     long ifModifiedSince=-1;
111     long lastModified=-1;
112     String path;
113     boolean responseSent=false;
114     boolean doingGet=false;
115
116     public boolean isLocalHost()
117     {
118         return s!=null&&s.getInetAddress().getHostAddress().equals("127.0.0.1");
119     }
120
121     public static void setLog(PrintStream ps)
122     {
123         log=ps;
124     }
125
126     protected static void log(String s) {
127         synchronized (log) {
128             log.println(s);
129             log.flush();
130         }
131     }
132
133
134     public long parseDate(String date)
135     {
136         try
137         {
138             return df.parse(date).getTime();
139         }
140         catch(ParseException e)
141         {
142             log("Can't parse date: "+date);
143             return -1;
144         }
145     }
146
147     public String formatDate(long date)
148     {
149         return df.format(new Date(date));
150     }
151
152     public String getServerName()
153     {
154         return "WebHandler";
155     }
156
157     synchronized void setSocket(Socket s)
158     {
159         this.s = s;
160         notify();
161     }
162
163     public void getStream(InputStream is,OutputStream os) throws IOException
164     {
165         byte[] buf=new byte[4096];
166         try {
167             int n;
168             while ((n = is.read(buf)) > 0) {
169                 os.write(buf, 0, n);
170             }
171         } finally {
172             is.close();
173         }
174     }
175
176     public boolean responseHasBeenSent()
177     {
178         return responseSent;
179     }
180
181     public void sendResponse(int rCode,String comment) throws IOException
182     {
183         responseSent=true;
184         ps.print("HTTP/1.1 ");
185         ps.print(rCode);
186         ps.print(' ');
187         ps.print(comment);
188         ps.write(EOL);
189
190         log("From " +s.getInetAddress().getHostAddress()+": GET " +
191             path+"-->"+rCode);
192         ps.print("Server: "+getServerName());
193         ps.write(EOL);
194         ps.print("Date: " + formatDate(System.currentTimeMillis()));
195         ps.write(EOL);
196         ps.print("Connection: keep-alive");
197         ps.write(EOL);
198         if (lastModified!=-1)
199         {
200             ps.print("Last-modified: "+formatDate(lastModified));
201             ps.write(EOL);
202         }
203         if (rCode==HTTP_MOVED_TEMP||rCode==HTTP_MOVED_PERM)
204         {
205             ps.print("Location: ");
206             ps.print(comment);
207             ps.write(EOL);
208         }
209
210         String contentType="text/html";
211         if (rCode==HTTP_OK)
212         {
213             int q=path.lastIndexOf('?');
214             if (q==-1)
215                 q=path.length();
216             int slash=path.lastIndexOf('/',q-1);
217             int dot=path.lastIndexOf('.',q-1);
218
219             if (dot==-1||dot<slash)
220             {
221                 ps.print("text/html");
222             }
223             else
224             {
225                 String s=(String)mimeTypes.get(path.substring(dot,q));
226                 if (s!=null)
227                     contentType=s;
228             }
229         }
230         byte[] bytes=null;
231         if (rCode==HTTP_OK||rCode==HTTP_NOT_FOUND)
232         {
233             bytes=content.toByteArray();
234
235             ps.print("Content-type: ");
236             ps.print(contentType);
237             ps.write(EOL);
238
239             ps.print("Content-length: ");
240             ps.print(bytes.length);
241             ps.write(EOL);
242         }
243         ps.write(EOL);
244         if (bytes!=null&&doingGet)
245         {
246             ps.write(bytes);
247         }
248         ps.flush();
249     }
250
251     public boolean setLastModified(long lastModified)
252     {
253         this.lastModified=lastModified;
254         return !(lastModified<=ifModifiedSince);
255     }
256
257     public void handleClient(InputStream is,OutputStream os) throws IOException
258     {
259         BufferedReader br = new BufferedReader(new InputStreamReader(is));
260         ps = new PrintStream(new BufferedOutputStream(os));
261         content=new ByteArrayOutputStream();
262         PrintStream cps=new PrintStream(content);
263
264         log("************* NEW CONNECTION ***********");
265
266         try
267         {
268             while(true)
269             {
270                 responseSent=false;
271                 content.reset();
272                 String line=br.readLine();
273                 if (line==null)
274                 {
275                     log("Client returned null. Closing.");
276                     s.close();
277                     return;
278                 }
279                 String x=null;
280                 ifModifiedSince=-1;
281                 while((x=br.readLine())!=null&&x.length()>0)
282                 {
283                     if (x.startsWith(IF_MODIFIED_SINCE))
284                     {
285                         ifModifiedSince=parseDate(x.substring(IF_MODIFIED_SINCE.length()));
286                     }
287                 }
288
289                 StringTokenizer st=new StringTokenizer(line);
290                 String method=st.nextToken();
291                 path=st.nextToken();
292                 boolean valid=true;
293                 doingGet=false;
294                 LibClass cla=null;
295                 File tempFile=null;
296
297                 if (method!=null&&path!=null)
298                 {
299                     if (method.equals("GET"))
300                         doingGet=true;
301                     else
302                     if (method.equals("HEAD"))
303                         doingGet=false;
304                     else
305                         valid=false;
306                 }
307                 else
308                     valid=false;
309
310                 if (!valid)
311                 {
312                     /* we don't support this method */
313                     sendResponse(HTTP_BAD_METHOD,"Unsupported method type: "+method);
314                     continue;
315                 }
316
317                 try
318                 {
319                     lastModified=-1;
320                     handleGet(path,cps);
321                     if (responseHasBeenSent())
322                         continue;
323                 }
324                 catch(IOException e)
325                 {
326                     System.out.println("Error handling: "+path+":"+e);
327                 }
328                 send404(path,cps);
329                 continue;
330             }
331         }
332         catch(IOException e)
333         {
334             System.out.println(e);
335         }
336         finally
337         {
338             s.close();
339         }
340         System.out.println("*** SOCKET CLOSED ***");
341     }
342
343     public void handleGet(String path,PrintStream ps) throws IOException
344     {
345     }
346
347     void send404(String path,PrintStream ps) throws IOException
348     {
349         ps.println("<html><head><title>File Not Found</title></head>");
350         ps.println("<body><center><h1>File Not Found</h1>");
351         ps.print("The file you were looking for:<br><b>");
352         ps.print(path);
353         ps.println("</b><br>was not found. Tough luck!");
354         ps.println("</center></body></html>");
355         sendResponse(HTTP_NOT_FOUND,"File not found");
356     }
357
358     public synchronized void run()
359     {
360         while(true)
361         {
362             if (s == null)
363             {
364                 /* nothing to do */
365                 try
366                 {
367                     wait();
368                 }
369                 catch (InterruptedException e)
370                 {
371                     /* should not happen */
372                     continue;
373                 }
374             }
375             try
376             {
377                 handleClient(s.getInputStream(),s.getOutputStream());
378             }
379             catch (Exception e)
380             {
381                 e.printStackTrace();
382             }
383             /* go back in wait queue if there's fewer
384              * than numHandler connections.
385              */

386             s = null;
387             synchronized (handlers)
388             {
389                 if (handlers.size() >= MAX_HANDLERS)
390                 {
391                     /* too many threads, exit this one */
392                     return;
393                 }
394                 else
395                 {
396                     handlers.add(this);
397                 }
398             }
399         }
400     }
401 }
402
Popular Tags