KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > servlet > servlets > FileServerServlet


1
2 /*
3  * Enhydra Java Application Server Project
4  *
5  * The contents of this file are subject to the Enhydra Public License
6  * Version 1.1 (the "License"); you may not use this file except in
7  * compliance with the License. You may obtain a copy of the License on
8  * the Enhydra web site ( http://www.enhydra.org/ ).
9  *
10  * Software distributed under the License is distributed on an "AS IS"
11  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
12  * the License for the specific terms governing rights and limitations
13  * under the License.
14  *
15  * The Initial Developer of the Enhydra Application Server is Lutris
16  * Technologies, Inc. The Enhydra Application Server and portions created
17  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
18  * All Rights Reserved.
19  *
20  * Contributor(s):
21  *
22  * $Id: FileServerServlet.java,v 1.3 2005/03/24 10:51:25 slobodan Exp $
23  */

24
25 package org.enhydra.servlet.servlets;
26
27 import java.io.File JavaDoc;
28 import java.io.FileInputStream JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.io.InputStream JavaDoc;
31 import java.io.OutputStream JavaDoc;
32
33 import javax.servlet.ServletConfig JavaDoc;
34 import javax.servlet.ServletContext JavaDoc;
35 import javax.servlet.ServletException JavaDoc;
36 import javax.servlet.ServletOutputStream JavaDoc;
37 import javax.servlet.http.HttpServlet JavaDoc;
38 import javax.servlet.http.HttpServletRequest JavaDoc;
39 import javax.servlet.http.HttpServletResponse JavaDoc;
40
41 import com.lutris.http.MimeType;
42 import com.lutris.logging.LogChannel;
43 import com.lutris.logging.Logger;
44 import com.lutris.logging.StandardLogger;
45 //SV import org.enhydra.servlet.connectionMethods.http.*;
46
//SV import org.enhydra.servlet.servletManager.EnhydraServletContext;
47

48
49 /**
50  * This class serves files from HTTP request. Currently only a
51  * limited Http GET request will be processed. CGI arguments will
52  * not be processed. The initial parameter 'index=something.html' can
53  * for the default html page. If this parameter is not set then it
54  * will default to "index.html".
55  *
56  * @version 1.8, 3/98
57  * @auther Mark Sanguinetti
58  */

59
60 public class FileServerServlet
61     extends HttpServlet JavaDoc {
62
63     /**
64      * Buffer size for writeing one stream to another.
65      */

66     private static final int buffer_size = 1024*1;
67
68     /**
69      * Html text to send clent for a file not found.
70      */

71     private final static String JavaDoc NOT_FOUND_MSG =
72         "<TITLE>Not Found</TITLE><H1>Not Found</H1> " +
73         "The requested object does not exist on this Enhydra Server. " +
74         "The link you followed is either outdated, inaccurate, " +
75         "or the server has been instructed not to let you have it.";
76
77     /**
78      * Html text to send client when Access to file denied.
79      */

80     private final static String JavaDoc ACCESS_DENIED_MSG =
81         "<TITLE>Access Denied</TITLE><H1>Access Denied</H1> " +
82         "Access is not allowed to the requested file. ";
83
84     /**
85      *
86      */

87     private final static String JavaDoc SC_MOVED_PERMANENTLY_MSG =
88         "<TITLE>Moved Permanently</TITLE><H1>Moved Permanently</H1> " +
89         "Resouce has been moved";
90
91     /**
92      * Default html page.
93      */

94     private String JavaDoc defaultPage = null;
95
96     /**
97      * The logging channel.
98      */

99     private LogChannel logChannel;
100     
101     /*
102      * If we create the central logger, we save a copy of it for later
103      * initialization. If we didn't create it, this will be null.
104      */

105     private StandardLogger standardLogger;
106     
107     /*
108      * If we create the central logger, we will need to initialize it later
109      * when init() is called.
110      */

111     private boolean needToConfigureLogChannel = false;
112     
113     
114     /**
115      * The Sevelet context.
116      */

117     private ServletContext JavaDoc myContext;
118
119     /**
120      * The document root for the file server and is
121      * specified in servlet context.
122      */

123     private Path docRoot = null;
124
125     /**
126      * Number of file served by this servlet.
127      */

128     private long numServed = 0;
129
130     /**
131      * Class for determing the mime type of a file
132      */

133     private MimeType mimetypes = new MimeType();
134
135
136     /**
137      * Mime type extension for executing a cgi script in thr Doc Root.
138      */

139     private String JavaDoc cgiType = null;
140     
141     /**
142      * Create a new FileServerServlet.
143      */

144     public FileServerServlet() {
145         super();
146         if (Logger.getCentralLogger() == null) {
147             standardLogger = new StandardLogger(true);
148             needToConfigureLogChannel = true;
149         }
150         logChannel = Logger.getCentralLogger().getChannel("Enhydra");
151     }
152     
153     
154     /**
155      * This initializes the servlet and sets the variables docRoot and
156      * log logging options.
157      *
158      * @param config The servlet configuration object.
159      * @exception If an exception occured during initialztion
160      */

161     public void init(ServletConfig JavaDoc config)
162         throws ServletException JavaDoc {
163         super.init(config);
164         myContext = config.getServletContext();
165
166         // FIX: check for docRoot == null
167
docRoot = new Path(myContext.getRealPath(""));
168
169         // get defaultPage form parameters
170
defaultPage = config.getInitParameter("index");
171         if (defaultPage == null) {
172             defaultPage = "index.html";
173         }
174
175         // cgi extension, if any.
176
cgiType = config.getInitParameter("cgi");
177
178         //Try to get the logging channel, if we are being run under
179
// the MultiServer.
180
//SV if (myContext instanceof
181
//SV org.enhydra.servlet.servletManager.EnhydraServletContext) {
182
//SV EnhydraServletContext lbsContext =
183
//SV (EnhydraServletContext) myContext;
184
//SV logChannel = lbsContext.getLogChannel();
185
//SV }
186
logInfo("Starting File Server Servlet with docRoot " + docRoot.getFilePath());
187     }
188
189     /**
190      * This method will process a limited http GET request for a file.
191      * The method will serve files, but will not process cgi arguments.
192      *
193      * @param req encapsulates the request to the servlet.
194      * @param res encapsulates the response from the servlet.
195      * @exception if the request could not be handled.
196      * @exception if detected when processing.
197      */

198     public void doGet (HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
199     throws ServletException JavaDoc, IOException JavaDoc {
200
201         /* FIX: Path object is used because the file object doesn't
202          * fix multiple file separator char and also problems with
203          * converting URL path to a File path with platform specific
204          * file separator char.
205          */

206
207         String JavaDoc pathInfo = req.getPathInfo();
208         String JavaDoc path = docRoot.appendFilePath(pathInfo);
209         File JavaDoc file = new File JavaDoc(path);
210         if (isAuth(file.getPath())) {
211             // check for cgi
212
if (cgiType != null) {
213                 String JavaDoc scriptPath = getScriptPath(path);
214                 if (scriptPath != null) {
215                     // process cgi
216
String JavaDoc scriptPathInfo = getScriptPathInfo(path, scriptPath);
217                     String JavaDoc scriptName = getScriptName(docRoot.getUrlPath(), scriptPath);
218                     CgiProcessor cgi = new CgiProcessor();
219                     cgi.processCgiRequest(req, res, scriptPath, scriptPathInfo, scriptName);
220                 } else {
221                     // process file request
222
processFileRequest(file, req, res);
223                 }
224             } else {
225                 // process file request
226
processFileRequest(file, req, res);
227             }
228         } else {
229             // path containing '..' is not authorized
230
res.sendError(res.SC_NOT_FOUND, NOT_FOUND_MSG);
231             logInfo("FileServerServlet: File " + file + " not Found.");
232         }
233     }
234
235     /**
236      *
237      */

238     private String JavaDoc getScriptName(String JavaDoc docRoot, String JavaDoc scriptPath) {
239
240         return scriptPath.substring(docRoot.length() + 1);
241     }
242
243     /**
244      *
245      */

246     private String JavaDoc getScriptPathInfo(String JavaDoc path, String JavaDoc scriptPath) {
247
248         int index = path.indexOf(scriptPath);
249         if (index == -1) {
250             return "";
251         }
252         return path.substring(index + scriptPath.length());
253     }
254
255     /**
256      *
257      */

258     private String JavaDoc getScriptPath(String JavaDoc path) {
259
260         String JavaDoc cgi = "." + cgiType;
261         int index = path.indexOf(cgi);
262         if (index == -1) {
263             return null;
264         }
265         return path.substring(0, index + cgi.length());
266     }
267
268
269     /**
270      *
271      */

272     private void processFileRequest(File JavaDoc file, HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res) throws IOException JavaDoc {
273
274         if (file.exists()) {
275             // file exists
276
if (file.isDirectory()) {
277                 // send dir. index page of list dir.
278
processDirectory(req, res);
279             } else {
280                 // send requested file
281
sendPage(file, res);
282             }
283         } else {
284             // file doesn't exist
285
res.sendError(res.SC_NOT_FOUND, NOT_FOUND_MSG);
286             logInfo("FileServerServlet: File " + file + " not Found.");
287         }
288     }
289
290     /**
291      *
292      */

293     private void processDirectory(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
294         throws IOException JavaDoc {
295
296         String JavaDoc pathInfo = req.getPathInfo();
297         if (pathInfo == null) {
298             pathInfo = "/";
299         }
300
301         Path path = new Path(docRoot.getUrlPath(), pathInfo);
302         if (pathInfo.endsWith("/")) {
303             String JavaDoc indexPath = path.appendFilePath(defaultPage);
304             File JavaDoc indexFile = new File JavaDoc(indexPath);
305             if (indexFile.exists()) {
306                 // send index file
307
sendPage(indexFile, res);
308             } else {
309                 // list directory
310
File JavaDoc dir = new File JavaDoc(path.getFilePath());
311                 listDirectory(dir, req, res);
312             }
313         } else {
314             sendDirectoryRedirect(req, res);
315         }
316     }
317
318     /**
319      *
320      */

321     private void sendDirectoryRedirect(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
322         throws IOException JavaDoc {
323
324         String JavaDoc location = req.getRequestURI() + "/";
325         res.setHeader("Location", location);
326         res.sendError(res.SC_MOVED_PERMANENTLY, SC_MOVED_PERMANENTLY_MSG);
327     }
328
329     /**
330      * Reconstruct the URL for this request.
331      *
332      * @param request to the servlet.
333      * @return url.
334      */

335     String JavaDoc getUrl(HttpServletRequest JavaDoc request) {
336
337         String JavaDoc host = request.getScheme() + "://";
338         host += request.getServerName();
339         int port;
340         if ((port = request.getServerPort()) != 80) {
341             host += ":" + port;
342         }
343         return request.getRequestURI();
344     }
345
346     /**
347      * Generates an html listing of a directory.
348      *
349      * FIX: should create a temp file, set a content-length aheadr
350      * and output like a normal file.
351      *
352      * @param root Directory of interest.
353      * @param req
354      * @param res
355      */

356     private void listDirectory(File JavaDoc root, HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
357         throws IOException JavaDoc {
358
359         res.setContentType("text/html");
360         ServletOutputStream JavaDoc out = res.getOutputStream();
361
362         String JavaDoc vPath = (req.getPathInfo() == null ? "/" : req.getPathInfo());
363         String JavaDoc vParent = (vPath.equals("/") ? "" : "../" );
364         out.println("<html>");
365         out.println("<head><title>Index of " + vPath + "</title></head>");
366         out.println("<body>");
367         out.println("<h1>Index of " + vPath + "</h1>\n<hr>");
368         out.println("<pre>");
369         out.println("<a HREF=\"" + vParent + "\">Parent Directory</a>");
370
371         String JavaDoc href = null;
372         String JavaDoc files[] = root.list();
373         String JavaDoc path = root.getPath();
374         for (int i = 0; i < files.length; i++) {
375             File JavaDoc f = new File JavaDoc(path + "/" + files[i]);
376             if (f.isDirectory()) {
377                 href = "<a HREF=\"" + files[i] + "/\">" + files[i] + "</a>";
378             } else {
379                 href = "<a HREF=\"" + files[i] + "\">" + files[i] + "</a>";
380             }
381             out.println(href);
382         }
383         out.println("</pre>");
384         out.println("</body>");
385         out.println("</html>");
386     }
387
388     /**
389      * Test if is authorized. A path is authorized if
390      * it does not contain a '..'. The browser should resolve
391      * the '..'.
392      *
393      * @param path requested path
394      * @return true if path is authorized
395      */

396     private boolean isAuth(String JavaDoc path) {
397
398         if (path.indexOf("..") == -1) {
399             return true;
400         }
401         return false;
402     }
403
404     /**
405      *
406      *
407      */

408     private void sendPage(File JavaDoc file, HttpServletResponse JavaDoc res)
409         throws IOException JavaDoc {
410
411         String JavaDoc filetype = mimetypes.getType(file.getName());
412         res.setContentType(filetype);
413         Long JavaDoc len = new Long JavaDoc(file.length());
414         res.setHeader("Content-Length", len.toString());
415         ServletOutputStream JavaDoc out = res.getOutputStream();
416         FileInputStream JavaDoc in = new FileInputStream JavaDoc(file);
417         writeFile(out, in);
418         in.close();
419         numServed++;
420     }
421
422     /**
423      * Http POST command is currently not supported and indicates
424      * this sending a message to the client.
425      *
426      * @param req encapsulates the request to the servlet.
427      * @param res encapsulates the response from the servlet.
428      * @exception if the request could not be handled.
429      * @exception if detected when processing.
430      */

431     public void doPost (HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
432     throws ServletException JavaDoc, IOException JavaDoc {
433         res.sendError(res.SC_NOT_IMPLEMENTED);
434         logInfo("FileServerServlet: Access Denied.");
435     }
436
437     /**
438      * Returns a string containing servlet infoemation including name,
439      * and docRoot.
440      *
441      * @return Servlet informatioon.
442      */

443     public String JavaDoc getServletInfo() {
444         return "A FileServerServlet, with doc root " + docRoot.getFilePath();
445     }
446
447     /**
448      * Extra status info, shown by the Enhydra Server admin status page.
449      */

450     public String JavaDoc toHtml() {
451         return "Serving files from the directory " + docRoot.getFilePath() + ".<BR>\n" +
452                numServed + " files served.";
453     }
454
455     /**
456      * Transfers to one stream to another via a buffer. In this case
457      * the input stream is a file to be transferred and the output
458      * stream is servlet output stream.
459      *
460      * @param out The destination stream.
461      * @param in The source stream.
462      * @exception if an error occured during IO operations.
463      */

464     private void writeFile(OutputStream JavaDoc out, InputStream JavaDoc in)
465         throws IOException JavaDoc {
466
467         byte buffer[] = new byte[buffer_size];
468         while (true) {
469             int n = in.read(buffer);
470             if (n == -1) break;
471             out.write(buffer, 0, n);
472         }
473     }
474
475     /**
476      * Write standard (non error) information to the log. If logChannel
477      * is not null then the information will be logged to the lbs
478      * logged channel defined in lbsContext otherwise the information
479      * will be logged to the standard servlet log.
480      *
481      * @param msg The message to be logged.
482      */

483     private void logInfo(String JavaDoc msg) {
484 // v. strahinja, 01 okt 2002
485
if (logChannel != null)
486 // if (logger != null)
487
// v. strahinja, 26 sep 2002
488
logChannel.write(Logger.INFO, msg);
489 // logger.log(Level.INFO, msg);
490
else
491             myContext.log(msg);
492     }
493
494     /**
495      * Write error information to the log. If logChannel is not null
496      * then the information will be logged to the lbs logged channel
497      * defined in lbsContext otherwise the information will be logged to
498      * the standard servlet log.
499      *
500      *@param err The error message to be logged.
501      *@param e The exception to be logged.
502      */

503     private void logError(String JavaDoc err, Exception JavaDoc e) {
504 // v. strahinja, 01 okt 2002
505
if (logChannel != null)
506 // if (logger != null)
507
// v. strahinja, 26 sep 2002
508
logChannel.write(Logger.ERROR, err, e);
509 // logger.log(Level.ERROR, err, e);
510
else
511             myContext.log(e, err);
512     }
513 }
514
Popular Tags