Source Code Cross Referenced for DefaultServlet.java in  » Web-Server » Rimfaxe-Web-Server » org » apache » catalina » servlets » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Server » Rimfaxe Web Server » org.apache.catalina.servlets 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/DefaultServlet.java,v 1.57 2002/06/14 03:19:43 remm Exp $
0003:         * $Revision: 1.57 $
0004:         * $Date: 2002/06/14 03:19:43 $
0005:         *
0006:         * ====================================================================
0007:         *
0008:         * The Apache Software License, Version 1.1
0009:         *
0010:         * Copyright (c) 1999 The Apache Software Foundation.  All rights
0011:         * reserved.
0012:         *
0013:         * Redistribution and use in source and binary forms, with or without
0014:         * modification, are permitted provided that the following conditions
0015:         * are met:
0016:         *
0017:         * 1. Redistributions of source code must retain the above copyright
0018:         *    notice, this list of conditions and the following disclaimer.
0019:         *
0020:         * 2. Redistributions in binary form must reproduce the above copyright
0021:         *    notice, this list of conditions and the following disclaimer in
0022:         *    the documentation and/or other materials provided with the
0023:         *    distribution.
0024:         *
0025:         * 3. The end-user documentation included with the redistribution, if
0026:         *    any, must include the following acknowlegement:
0027:         *       "This product includes software developed by the
0028:         *        Apache Software Foundation (http://www.apache.org/)."
0029:         *    Alternately, this acknowlegement may appear in the software itself,
0030:         *    if and wherever such third-party acknowlegements normally appear.
0031:         *
0032:         * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
0033:         *    Foundation" must not be used to endorse or promote products derived
0034:         *    from this software without prior written permission. For written
0035:         *    permission, please contact apache@apache.org.
0036:         *
0037:         * 5. Products derived from this software may not be called "Apache"
0038:         *    nor may "Apache" appear in their names without prior written
0039:         *    permission of the Apache Group.
0040:         *
0041:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0042:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0043:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0044:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0045:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0046:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0047:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0048:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0049:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0050:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0051:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0052:         * SUCH DAMAGE.
0053:         * ====================================================================
0054:         *
0055:         * This software consists of voluntary contributions made by many
0056:         * individuals on behalf of the Apache Software Foundation.  For more
0057:         * information on the Apache Software Foundation, please see
0058:         * <http://www.apache.org/>.
0059:         *
0060:         * [Additional notices, if required by prior licensing conditions]
0061:         *
0062:         */
0063:
0064:        package org.apache.catalina.servlets;
0065:
0066:        import java.io.BufferedInputStream;
0067:        import java.io.ByteArrayOutputStream;
0068:        import java.io.ByteArrayInputStream;
0069:        import java.io.File;
0070:        import java.io.FileInputStream;
0071:        import java.io.InputStream;
0072:        import java.io.IOException;
0073:        import java.io.PrintWriter;
0074:        import java.io.RandomAccessFile;
0075:        import java.io.Reader;
0076:        import java.io.InputStreamReader;
0077:        import java.io.Writer;
0078:        import java.io.OutputStreamWriter;
0079:        import java.net.MalformedURLException;
0080:        import java.net.URL;
0081:        import java.sql.Timestamp;
0082:        import java.util.Date;
0083:        import java.util.Enumeration;
0084:        import java.util.Vector;
0085:        import java.util.StringTokenizer;
0086:        import java.util.Locale;
0087:        import java.util.TimeZone;
0088:        import java.util.Hashtable;
0089:        import java.text.ParseException;
0090:        import java.text.SimpleDateFormat;
0091:        import java.security.MessageDigest;
0092:        import java.security.NoSuchAlgorithmException;
0093:        import javax.servlet.RequestDispatcher;
0094:        import javax.servlet.ServletException;
0095:        import javax.servlet.ServletContext;
0096:        import javax.servlet.ServletOutputStream;
0097:        import javax.servlet.http.HttpServlet;
0098:        import javax.servlet.http.HttpServletRequest;
0099:        import javax.servlet.http.HttpServletResponse;
0100:        import javax.naming.NamingException;
0101:        import javax.naming.InitialContext;
0102:        import javax.naming.Context;
0103:        import javax.naming.NamingEnumeration;
0104:        import javax.naming.NameClassPair;
0105:        import javax.naming.directory.DirContext;
0106:        import javax.naming.directory.Attribute;
0107:        import javax.naming.directory.Attributes;
0108:        import org.apache.naming.resources.Resource;
0109:        import org.apache.naming.resources.ResourceAttributes;
0110:        import org.apache.catalina.Globals;
0111:        import org.apache.catalina.util.FastHttpDateFormat;
0112:        import org.apache.catalina.util.MD5Encoder;
0113:        import org.apache.catalina.util.RequestUtil;
0114:        import org.apache.catalina.util.ServerInfo;
0115:        import org.apache.catalina.util.StringManager;
0116:        import org.apache.catalina.util.URLEncoder;
0117:
0118:        /**
0119:         * The default resource-serving servlet for most web applications,
0120:         * used to serve static resources such as HTML pages and images.
0121:         *
0122:         * @author Craig R. McClanahan
0123:         * @author Remy Maucherat
0124:         * @version $Revision: 1.57 $ $Date: 2002/06/14 03:19:43 $
0125:         */
0126:
0127:        public class DefaultServlet extends HttpServlet {
0128:
0129:            // ----------------------------------------------------- Instance Variables
0130:
0131:            /**
0132:             * The debugging detail level for this servlet.
0133:             */
0134:            protected int debug = 0;
0135:
0136:            /**
0137:             * The input buffer size to use when serving resources.
0138:             */
0139:            protected int input = 2048;
0140:
0141:            /**
0142:             * Should we generate directory listings when no welcome file is present?
0143:             */
0144:            protected boolean listings = true;
0145:
0146:            /**
0147:             * Read only flag. By default, it's set to true.
0148:             */
0149:            protected boolean readOnly = true;
0150:
0151:            /**
0152:             * The output buffer size to use when serving resources.
0153:             */
0154:            protected int output = 2048;
0155:
0156:            /**
0157:             * The set of welcome files for this web application
0158:             */
0159:            protected String welcomes[] = new String[0];
0160:
0161:            /**
0162:             * MD5 message digest provider.
0163:             */
0164:            protected static MessageDigest md5Helper;
0165:
0166:            /**
0167:             * The MD5 helper object for this class.
0168:             */
0169:            protected static final MD5Encoder md5Encoder = new MD5Encoder();
0170:
0171:            /**
0172:             * The set of SimpleDateFormat formats to use in getDateHeader().
0173:             */
0174:            protected static final SimpleDateFormat formats[] = {
0175:                    new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz",
0176:                            Locale.US),
0177:                    new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz",
0178:                            Locale.US),
0179:                    new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) };
0180:
0181:            protected final static TimeZone gmtZone = TimeZone
0182:                    .getTimeZone("GMT");
0183:
0184:            /**
0185:             * Array containing the safe characters set.
0186:             */
0187:            protected static URLEncoder urlEncoder;
0188:
0189:            /**
0190:             * GMT timezone - all HTTP dates are on GMT
0191:             */
0192:            // ----------------------------------------------------- Static Initializer
0193:            static {
0194:                formats[0].setTimeZone(gmtZone);
0195:                formats[1].setTimeZone(gmtZone);
0196:                formats[2].setTimeZone(gmtZone);
0197:
0198:                urlEncoder = new URLEncoder();
0199:                urlEncoder.addSafeCharacter('-');
0200:                urlEncoder.addSafeCharacter('_');
0201:                urlEncoder.addSafeCharacter('.');
0202:                urlEncoder.addSafeCharacter('*');
0203:                urlEncoder.addSafeCharacter('/');
0204:            }
0205:
0206:            /**
0207:             * MIME multipart separation string
0208:             */
0209:            protected static final String mimeSeparation = "CATALINA_MIME_BOUNDARY";
0210:
0211:            /**
0212:             * JNDI resources name.
0213:             */
0214:            protected static final String RESOURCES_JNDI_NAME = "java:/comp/Resources";
0215:
0216:            /**
0217:             * The string manager for this package.
0218:             */
0219:            protected static StringManager sm = StringManager
0220:                    .getManager(Constants.Package);
0221:
0222:            /**
0223:             * Size of file transfer buffer in bytes.
0224:             */
0225:            private static final int BUFFER_SIZE = 4096;
0226:
0227:            // --------------------------------------------------------- Public Methods
0228:
0229:            /**
0230:             * Finalize this servlet.
0231:             */
0232:            public void destroy() {
0233:
0234:                ; // No actions necessary
0235:
0236:            }
0237:
0238:            /**
0239:             * Initialize this servlet.
0240:             */
0241:            public void init() throws ServletException {
0242:                log("DefaultServlet.init: start");
0243:                // Set our properties from the initialization parameters
0244:                String value = null;
0245:                try {
0246:                    value = getServletConfig().getInitParameter("debug");
0247:                    debug = Integer.parseInt(value);
0248:                } catch (Throwable t) {
0249:                    ;
0250:                }
0251:                try {
0252:                    value = getServletConfig().getInitParameter("input");
0253:                    input = Integer.parseInt(value);
0254:                } catch (Throwable t) {
0255:                    ;
0256:                }
0257:                try {
0258:                    value = getServletConfig().getInitParameter("listings");
0259:                    listings = (new Boolean(value)).booleanValue();
0260:                } catch (Throwable t) {
0261:                    ;
0262:                }
0263:                try {
0264:                    value = getServletConfig().getInitParameter("readonly");
0265:                    if (value != null)
0266:                        readOnly = (new Boolean(value)).booleanValue();
0267:                } catch (Throwable t) {
0268:                    ;
0269:                }
0270:                try {
0271:                    value = getServletConfig().getInitParameter("output");
0272:                    output = Integer.parseInt(value);
0273:                } catch (Throwable t) {
0274:                    ;
0275:                }
0276:
0277:                // Sanity check on the specified buffer sizes
0278:                if (input < 256)
0279:                    input = 256;
0280:                if (output < 256)
0281:                    output = 256;
0282:
0283:                // Initialize the set of welcome files for this application
0284:                welcomes = (String[]) getServletContext().getAttribute(
0285:                        Globals.WELCOME_FILES_ATTR);
0286:
0287:                if (welcomes == null)
0288:                    welcomes = new String[0];
0289:
0290:                if (debug > 0) {
0291:                    log("DefaultServlet.init:  input buffer size=" + input
0292:                            + ", output buffer size=" + output);
0293:                    for (int i = 0; i < welcomes.length; i++) {
0294:                        log("DefaultServlet.init:  welcome file=" + welcomes[i]);
0295:                    }
0296:                }
0297:
0298:                // Load the MD5 helper used to calculate signatures.
0299:                try {
0300:                    md5Helper = MessageDigest.getInstance("MD5");
0301:                } catch (NoSuchAlgorithmException e) {
0302:                    e.printStackTrace(System.out);
0303:                    throw new IllegalStateException();
0304:                }
0305:
0306:                log("DefaultServlet.init: done!");
0307:            }
0308:
0309:            // ------------------------------------------------------ Protected Methods
0310:
0311:            /**
0312:             * Get resources. This method will try to retrieve the resources through
0313:             * JNDI first, then in the servlet context if JNDI has failed (it could be
0314:             * disabled). It will return null.
0315:             *
0316:             * @return A JNDI DirContext, or null.
0317:             */
0318:            protected DirContext getResources() {
0319:
0320:                DirContext result = null;
0321:
0322:                // Try the servlet context
0323:                try {
0324:                    result = (DirContext) getServletContext().getAttribute(
0325:                            Globals.RESOURCES_ATTR);
0326:                } catch (ClassCastException e) {
0327:                    // Failed : Not the right type
0328:                }
0329:
0330:                if (result != null)
0331:                    return result;
0332:
0333:                // Try JNDI
0334:                try {
0335:                    result = (DirContext) new InitialContext()
0336:                            .lookup(RESOURCES_JNDI_NAME);
0337:                } catch (NamingException e) {
0338:                    // Failed
0339:                } catch (ClassCastException e) {
0340:                    // Failed : Not the right type
0341:                }
0342:
0343:                return result;
0344:
0345:            }
0346:
0347:            /**
0348:             * Show HTTP header information.
0349:             */
0350:            protected void showRequestInfo(HttpServletRequest req) {
0351:
0352:                System.out.println();
0353:                System.out.println("SlideDAV Request Info");
0354:                System.out.println();
0355:
0356:                // Show generic info
0357:                System.out.println("Encoding : " + req.getCharacterEncoding());
0358:                System.out.println("Length : " + req.getContentLength());
0359:                System.out.println("Type : " + req.getContentType());
0360:
0361:                System.out.println();
0362:                System.out.println("Parameters");
0363:
0364:                Enumeration parameters = req.getParameterNames();
0365:
0366:                while (parameters.hasMoreElements()) {
0367:                    String paramName = (String) parameters.nextElement();
0368:                    String[] values = req.getParameterValues(paramName);
0369:                    System.out.print(paramName + " : ");
0370:                    for (int i = 0; i < values.length; i++) {
0371:                        System.out.print(values[i] + ", ");
0372:                    }
0373:                    System.out.println();
0374:                }
0375:
0376:                System.out.println();
0377:
0378:                System.out.println("Protocol : " + req.getProtocol());
0379:                System.out.println("Address : " + req.getRemoteAddr());
0380:                System.out.println("Host : " + req.getRemoteHost());
0381:                System.out.println("Scheme : " + req.getScheme());
0382:                System.out.println("Server Name : " + req.getServerName());
0383:                System.out.println("Server Port : " + req.getServerPort());
0384:
0385:                System.out.println();
0386:                System.out.println("Attributes");
0387:
0388:                Enumeration attributes = req.getAttributeNames();
0389:
0390:                while (attributes.hasMoreElements()) {
0391:                    String attributeName = (String) attributes.nextElement();
0392:                    System.out.print(attributeName + " : ");
0393:                    System.out.println(req.getAttribute(attributeName)
0394:                            .toString());
0395:                }
0396:
0397:                System.out.println();
0398:
0399:                // Show HTTP info
0400:                System.out.println();
0401:                System.out.println("HTTP Header Info");
0402:                System.out.println();
0403:
0404:                System.out
0405:                        .println("Authentication Type : " + req.getAuthType());
0406:                System.out.println("HTTP Method : " + req.getMethod());
0407:                System.out.println("Path Info : " + req.getPathInfo());
0408:                System.out.println("Path translated : "
0409:                        + req.getPathTranslated());
0410:                System.out.println("Query string : " + req.getQueryString());
0411:                System.out.println("Remote user : " + req.getRemoteUser());
0412:                System.out.println("Requested session id : "
0413:                        + req.getRequestedSessionId());
0414:                System.out.println("Request URI : " + req.getRequestURI());
0415:                System.out.println("Context path : " + req.getContextPath());
0416:                System.out.println("Servlet path : " + req.getServletPath());
0417:                System.out
0418:                        .println("User principal : " + req.getUserPrincipal());
0419:
0420:                System.out.println();
0421:                System.out.println("Headers : ");
0422:
0423:                Enumeration headers = req.getHeaderNames();
0424:
0425:                while (headers.hasMoreElements()) {
0426:                    String headerName = (String) headers.nextElement();
0427:                    System.out.print(headerName + " : ");
0428:                    System.out.println(req.getHeader(headerName));
0429:                }
0430:
0431:                System.out.println();
0432:                System.out.println();
0433:
0434:            }
0435:
0436:            /**
0437:             * Return the relative path associated with this servlet.
0438:             *
0439:             * @param request The servlet request we are processing
0440:             */
0441:            protected String getRelativePath(HttpServletRequest request) {
0442:
0443:                // Are we being processed by a RequestDispatcher.include()?
0444:                if (request.getAttribute("javax.servlet.include.request_uri") != null) {
0445:                    String result = (String) request
0446:                            .getAttribute("javax.servlet.include.path_info");
0447:                    if (result == null)
0448:                        result = (String) request
0449:                                .getAttribute("javax.servlet.include.servlet_path");
0450:                    if ((result == null) || (result.equals("")))
0451:                        result = "/";
0452:                    return (result);
0453:                }
0454:
0455:                // No, extract the desired path directly from the request
0456:                String result = request.getPathInfo();
0457:                if (result == null) {
0458:                    result = request.getServletPath();
0459:                }
0460:                if ((result == null) || (result.equals(""))) {
0461:                    result = "/";
0462:                }
0463:                return normalize(result);
0464:
0465:            }
0466:
0467:            /**
0468:             * Process a GET request for the specified resource.
0469:             *
0470:             * @param request The servlet request we are processing
0471:             * @param response The servlet response we are creating
0472:             *
0473:             * @exception IOException if an input/output error occurs
0474:             * @exception ServletException if a servlet-specified error occurs
0475:             */
0476:            protected void doGet(HttpServletRequest request,
0477:                    HttpServletResponse response) throws IOException,
0478:                    ServletException {
0479:
0480:                if (debug > 999)
0481:                    showRequestInfo(request);
0482:
0483:                // Serve the requested resource, including the data content
0484:                serveResource(request, response, true);
0485:
0486:            }
0487:
0488:            /**
0489:             * Process a HEAD request for the specified resource.
0490:             *
0491:             * @param request The servlet request we are processing
0492:             * @param response The servlet response we are creating
0493:             *
0494:             * @exception IOException if an input/output error occurs
0495:             * @exception ServletException if a servlet-specified error occurs
0496:             */
0497:            protected void doHead(HttpServletRequest request,
0498:                    HttpServletResponse response) throws IOException,
0499:                    ServletException {
0500:
0501:                // Serve the requested resource, without the data content
0502:                serveResource(request, response, false);
0503:
0504:            }
0505:
0506:            /**
0507:             * Process a POST request for the specified resource.
0508:             *
0509:             * @param request The servlet request we are processing
0510:             * @param response The servlet response we are creating
0511:             *
0512:             * @exception IOException if an input/output error occurs
0513:             * @exception ServletException if a servlet-specified error occurs
0514:             */
0515:            protected void doPost(HttpServletRequest request,
0516:                    HttpServletResponse response) throws IOException,
0517:                    ServletException {
0518:                doGet(request, response);
0519:            }
0520:
0521:            /**
0522:             * Process a POST request for the specified resource.
0523:             *
0524:             * @param request The servlet request we are processing
0525:             * @param response The servlet response we are creating
0526:             *
0527:             * @exception IOException if an input/output error occurs
0528:             * @exception ServletException if a servlet-specified error occurs
0529:             */
0530:            protected void doPut(HttpServletRequest req,
0531:                    HttpServletResponse resp) throws ServletException,
0532:                    IOException {
0533:
0534:                if (readOnly) {
0535:                    resp.sendError(HttpServletResponse.SC_FORBIDDEN);
0536:                    return;
0537:                }
0538:
0539:                String path = getRelativePath(req);
0540:
0541:                // Retrieve the resources
0542:                DirContext resources = getResources();
0543:
0544:                if (resources == null) {
0545:                    resp
0546:                            .sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
0547:                    return;
0548:                }
0549:
0550:                boolean exists = true;
0551:                try {
0552:                    resources.lookup(path);
0553:                } catch (NamingException e) {
0554:                    exists = false;
0555:                }
0556:
0557:                boolean result = true;
0558:
0559:                // Temp. content file used to support partial PUT
0560:                File contentFile = null;
0561:
0562:                // Input stream for temp. content file used to support partial PUT
0563:                FileInputStream contentFileInStream = null;
0564:
0565:                ResourceInfo resourceInfo = new ResourceInfo(path, resources);
0566:                Range range = parseContentRange(req, resp);
0567:
0568:                InputStream resourceInputStream = null;
0569:
0570:                // Append data specified in ranges to existing content for this
0571:                // resource - create a temp. file on the local filesystem to
0572:                // perform this operation
0573:                // Assume just one range is specified for now
0574:                if (range != null) {
0575:                    contentFile = executePartialPut(req, range, path);
0576:                    resourceInputStream = new FileInputStream(contentFile);
0577:                } else {
0578:                    resourceInputStream = req.getInputStream();
0579:                }
0580:
0581:                try {
0582:                    Resource newResource = new Resource(resourceInputStream);
0583:                    // FIXME: Add attributes
0584:                    if (exists) {
0585:                        resources.rebind(path, newResource);
0586:                    } else {
0587:                        resources.bind(path, newResource);
0588:                    }
0589:                } catch (NamingException e) {
0590:                    result = false;
0591:                }
0592:
0593:                if (result) {
0594:                    if (exists) {
0595:                        resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
0596:                    } else {
0597:                        resp.setStatus(HttpServletResponse.SC_CREATED);
0598:                    }
0599:                } else {
0600:                    resp.sendError(HttpServletResponse.SC_CONFLICT);
0601:                }
0602:
0603:            }
0604:
0605:            /**
0606:             * Handle a partial PUT.  New content specified in request is appended to 
0607:             * existing content in oldRevisionContent (if present). This code does 
0608:             * not support simultaneous partial updates to the same resource.
0609:             */
0610:            protected File executePartialPut(HttpServletRequest req,
0611:                    Range range, String path) throws IOException {
0612:
0613:                // Append data specified in ranges to existing content for this
0614:                // resource - create a temp. file on the local filesystem to
0615:                // perform this operation
0616:                File tempDir = (File) getServletContext().getAttribute(
0617:                        "javax.servlet.context.tempdir");
0618:                // Convert all '/' characters to '.' in resourcePath
0619:                String convertedResourcePath = path.replace('/', '.');
0620:                File contentFile = new File(tempDir, convertedResourcePath);
0621:                if (contentFile.createNewFile()) {
0622:                    // Clean up contentFile when Tomcat is terminated
0623:                    contentFile.deleteOnExit();
0624:                }
0625:
0626:                RandomAccessFile randAccessContentFile = new RandomAccessFile(
0627:                        contentFile, "rw");
0628:
0629:                Resource oldResource = null;
0630:                try {
0631:                    Object obj = getResources().lookup(path);
0632:                    if (obj instanceof  Resource)
0633:                        oldResource = (Resource) obj;
0634:                } catch (NamingException e) {
0635:                }
0636:
0637:                // Copy data in oldRevisionContent to contentFile
0638:                if (oldResource != null) {
0639:                    BufferedInputStream bufOldRevStream = new BufferedInputStream(
0640:                            oldResource.streamContent(), BUFFER_SIZE);
0641:
0642:                    int numBytesRead;
0643:                    byte[] copyBuffer = new byte[BUFFER_SIZE];
0644:                    while ((numBytesRead = bufOldRevStream.read(copyBuffer)) != -1) {
0645:                        randAccessContentFile
0646:                                .write(copyBuffer, 0, numBytesRead);
0647:                    }
0648:
0649:                    bufOldRevStream.close();
0650:                }
0651:
0652:                randAccessContentFile.setLength(range.length);
0653:
0654:                // Append data in request input stream to contentFile
0655:                randAccessContentFile.seek(range.start);
0656:                int numBytesRead;
0657:                byte[] transferBuffer = new byte[BUFFER_SIZE];
0658:                BufferedInputStream requestBufInStream = new BufferedInputStream(
0659:                        req.getInputStream(), BUFFER_SIZE);
0660:                while ((numBytesRead = requestBufInStream.read(transferBuffer)) != -1) {
0661:                    randAccessContentFile
0662:                            .write(transferBuffer, 0, numBytesRead);
0663:                }
0664:                randAccessContentFile.close();
0665:                requestBufInStream.close();
0666:
0667:                return contentFile;
0668:
0669:            }
0670:
0671:            /**
0672:             * Process a POST request for the specified resource.
0673:             *
0674:             * @param request The servlet request we are processing
0675:             * @param response The servlet response we are creating
0676:             *
0677:             * @exception IOException if an input/output error occurs
0678:             * @exception ServletException if a servlet-specified error occurs
0679:             */
0680:            protected void doDelete(HttpServletRequest req,
0681:                    HttpServletResponse resp) throws ServletException,
0682:                    IOException {
0683:
0684:                if (readOnly) {
0685:                    resp.sendError(HttpServletResponse.SC_FORBIDDEN);
0686:                    return;
0687:                }
0688:
0689:                String path = getRelativePath(req);
0690:
0691:                // Retrieve the Catalina context
0692:                // Retrieve the resources
0693:                DirContext resources = getResources();
0694:
0695:                if (resources == null) {
0696:                    resp
0697:                            .sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
0698:                    return;
0699:                }
0700:
0701:                boolean exists = true;
0702:                try {
0703:                    resources.lookup(path);
0704:                } catch (NamingException e) {
0705:                    exists = false;
0706:                }
0707:
0708:                if (exists) {
0709:                    boolean result = true;
0710:                    try {
0711:                        resources.unbind(path);
0712:                    } catch (NamingException e) {
0713:                        result = false;
0714:                    }
0715:                    if (result) {
0716:                        resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
0717:                    } else {
0718:                        resp
0719:                                .sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
0720:                    }
0721:                } else {
0722:                    resp.sendError(HttpServletResponse.SC_NOT_FOUND);
0723:                }
0724:
0725:            }
0726:
0727:            /**
0728:             * Check if the conditions specified in the optional If headers are
0729:             * satisfied.
0730:             *
0731:             * @param request The servlet request we are processing
0732:             * @param response The servlet response we are creating
0733:             * @param resourceInfo File object
0734:             * @return boolean true if the resource meets all the specified conditions,
0735:             * and false if any of the conditions is not satisfied, in which case
0736:             * request processing is stopped
0737:             */
0738:            protected boolean checkIfHeaders(HttpServletRequest request,
0739:                    HttpServletResponse response, ResourceInfo resourceInfo)
0740:                    throws IOException {
0741:
0742:                return checkIfMatch(request, response, resourceInfo)
0743:                        && checkIfModifiedSince(request, response, resourceInfo)
0744:                        && checkIfNoneMatch(request, response, resourceInfo)
0745:                        && checkIfUnmodifiedSince(request, response,
0746:                                resourceInfo);
0747:
0748:            }
0749:
0750:            /**
0751:             * Get the ETag associated with a file.
0752:             *
0753:             * @param resourceInfo File object
0754:             * @param strong True if we want a strong ETag, in which case a checksum
0755:             * of the file has to be calculated
0756:             */
0757:            protected String getETag(ResourceInfo resourceInfo) {
0758:                if (resourceInfo.strongETag != null) {
0759:                    return resourceInfo.strongETag;
0760:                } else if (resourceInfo.weakETag != null) {
0761:                    return resourceInfo.weakETag;
0762:                } else {
0763:                    return "W/\"" + resourceInfo.length + "-"
0764:                            + resourceInfo.date + "\"";
0765:                }
0766:            }
0767:
0768:            /**
0769:             * Return a context-relative path, beginning with a "/", that represents
0770:             * the canonical version of the specified path after ".." and "." elements
0771:             * are resolved out.  If the specified path attempts to go outside the
0772:             * boundaries of the current context (i.e. too many ".." path elements
0773:             * are present), return <code>null</code> instead.
0774:             *
0775:             * @param path Path to be normalized
0776:             */
0777:            protected String normalize(String path) {
0778:
0779:                if (path == null)
0780:                    return null;
0781:
0782:                // Create a place for the normalized path
0783:                String normalized = path;
0784:
0785:                /*
0786:                 * Commented out -- already URL-decoded in StandardContextMapper
0787:                 * Decoding twice leaves the container vulnerable to %25 --> '%'
0788:                 * attacks.
0789:                 *
0790:                 * if (normalized.indexOf('%') >= 0)
0791:                 *     normalized = RequestUtil.URLDecode(normalized, "UTF8");
0792:                 */
0793:
0794:                if (normalized == null)
0795:                    return (null);
0796:
0797:                if (normalized.equals("/."))
0798:                    return "/";
0799:
0800:                // Normalize the slashes and add leading slash if necessary
0801:                if (normalized.indexOf('\\') >= 0)
0802:                    normalized = normalized.replace('\\', '/');
0803:                if (!normalized.startsWith("/"))
0804:                    normalized = "/" + normalized;
0805:
0806:                // Resolve occurrences of "//" in the normalized path
0807:                while (true) {
0808:                    int index = normalized.indexOf("//");
0809:                    if (index < 0)
0810:                        break;
0811:                    normalized = normalized.substring(0, index)
0812:                            + normalized.substring(index + 1);
0813:                }
0814:
0815:                // Resolve occurrences of "/./" in the normalized path
0816:                while (true) {
0817:                    int index = normalized.indexOf("/./");
0818:                    if (index < 0)
0819:                        break;
0820:                    normalized = normalized.substring(0, index)
0821:                            + normalized.substring(index + 2);
0822:                }
0823:
0824:                // Resolve occurrences of "/../" in the normalized path
0825:                while (true) {
0826:                    int index = normalized.indexOf("/../");
0827:                    if (index < 0)
0828:                        break;
0829:                    if (index == 0)
0830:                        return (null); // Trying to go outside our context
0831:                    int index2 = normalized.lastIndexOf('/', index - 1);
0832:                    normalized = normalized.substring(0, index2)
0833:                            + normalized.substring(index + 3);
0834:                }
0835:
0836:                // Return the normalized path that we have completed
0837:                return (normalized);
0838:
0839:            }
0840:
0841:            /**
0842:             * URL rewriter.
0843:             *
0844:             * @param path Path which has to be rewiten
0845:             */
0846:            protected String rewriteUrl(String path) {
0847:                return urlEncoder.encode(path);
0848:            }
0849:
0850:            /**
0851:             * Display the size of a file.
0852:             */
0853:            protected void displaySize(StringBuffer buf, int filesize) {
0854:
0855:                int leftside = filesize / 1024;
0856:                int rightside = (filesize % 1024) / 103; // makes 1 digit
0857:                // To avoid 0.0 for non-zero file, we bump to 0.1
0858:                if (leftside == 0 && rightside == 0 && filesize != 0)
0859:                    rightside = 1;
0860:                buf.append(leftside).append(".").append(rightside);
0861:                buf.append(" KB");
0862:
0863:            }
0864:
0865:            /**
0866:             * Serve the specified resource, optionally including the data content.
0867:             *
0868:             * @param request The servlet request we are processing
0869:             * @param response The servlet response we are creating
0870:             * @param content Should the content be included?
0871:             *
0872:             * @exception IOException if an input/output error occurs
0873:             * @exception ServletException if a servlet-specified error occurs
0874:             */
0875:            protected void serveResource(HttpServletRequest request,
0876:                    HttpServletResponse response, boolean content)
0877:                    throws IOException, ServletException {
0878:
0879:                // Identify the requested resource path
0880:                String path = getRelativePath(request);
0881:
0882:                log("1");
0883:
0884:                if (debug > 0) {
0885:                    if (content)
0886:                        log("DefaultServlet.serveResource:  Serving resource '"
0887:                                + path + "' headers and data");
0888:                    else
0889:                        log("DefaultServlet.serveResource:  Serving resource '"
0890:                                + path + "' headers only");
0891:
0892:                }
0893:
0894:                log("2");
0895:
0896:                // Retrieve the Catalina context and Resources implementation
0897:                DirContext resources = getResources();
0898:                ResourceInfo resourceInfo = new ResourceInfo(path, resources);
0899:
0900:                log("3");
0901:
0902:                if (!resourceInfo.exists) {
0903:                    log("3+");
0904:                    response.sendError(HttpServletResponse.SC_NOT_FOUND,
0905:                            request.getRequestURI());
0906:                    return;
0907:                }
0908:
0909:                log("4");
0910:
0911:                // If the resource is not a collection, and the resource path
0912:                // ends with "/" or "\", return NOT FOUND
0913:                if (!resourceInfo.collection) {
0914:                    if (path.endsWith("/") || (path.endsWith("\\"))) {
0915:                        response.sendError(HttpServletResponse.SC_NOT_FOUND,
0916:                                request.getRequestURI());
0917:                        return;
0918:                    }
0919:                }
0920:
0921:                log("-");
0922:
0923:                // If the resource is a collection (aka a directory), we check
0924:                // the welcome files list.
0925:                if (resourceInfo.collection) {
0926:
0927:                    if (!request.getRequestURI().endsWith("/")) {
0928:                        String redirectPath = path;
0929:                        String contextPath = request.getContextPath();
0930:                        if ((contextPath != null) && (!contextPath.equals("/"))) {
0931:                            redirectPath = contextPath + redirectPath;
0932:                        }
0933:                        if (!(redirectPath.endsWith("/")))
0934:                            redirectPath = redirectPath + "/";
0935:                        redirectPath = appendParameters(request, redirectPath);
0936:                        response.sendRedirect(redirectPath);
0937:                        return;
0938:                    }
0939:
0940:                    ResourceInfo welcomeFileInfo = checkWelcomeFiles(path,
0941:                            resources);
0942:                    if (welcomeFileInfo != null) {
0943:                        String redirectPath = welcomeFileInfo.path;
0944:                        String contextPath = request.getContextPath();
0945:                        if ((contextPath != null) && (!contextPath.equals("/"))) {
0946:                            redirectPath = contextPath + redirectPath;
0947:                        }
0948:                        redirectPath = appendParameters(request, redirectPath);
0949:                        response.sendRedirect(redirectPath);
0950:                        return;
0951:                    }
0952:
0953:                } else {
0954:
0955:                    // Checking If headers
0956:                    boolean included = (request
0957:                            .getAttribute(Globals.CONTEXT_PATH_ATTR) != null);
0958:                    if (!included
0959:                            && !checkIfHeaders(request, response, resourceInfo)) {
0960:                        return;
0961:                    }
0962:
0963:                }
0964:
0965:                // Find content type.
0966:                String contentType = getServletContext().getMimeType(
0967:                        resourceInfo.path);
0968:
0969:                Vector ranges = null;
0970:
0971:                if (resourceInfo.collection) {
0972:                    // Skip directory listings if we have been configured to
0973:                    // suppress them
0974:                    if (!listings) {
0975:                        response.sendError(HttpServletResponse.SC_NOT_FOUND,
0976:                                request.getRequestURI());
0977:                        return;
0978:                    }
0979:                    contentType = "text/html;charset=UTF-8";
0980:
0981:                } else {
0982:
0983:                    // Parse range specifier
0984:
0985:                    ranges = parseRange(request, response, resourceInfo);
0986:
0987:                    // ETag header
0988:                    response.setHeader("ETag", getETag(resourceInfo));
0989:
0990:                    // Last-Modified header
0991:                    if (debug > 0)
0992:                        log("DefaultServlet.serveFile:  lastModified='"
0993:                                + (new Timestamp(resourceInfo.date)).toString()
0994:                                + "'");
0995:                    response.setHeader("Last-Modified", resourceInfo.httpDate);
0996:
0997:                }
0998:
0999:                ServletOutputStream ostream = null;
1000:                PrintWriter writer = null;
1001:
1002:                if (content) {
1003:
1004:                    // Trying to retrieve the servlet output stream
1005:
1006:                    try {
1007:                        ostream = response.getOutputStream();
1008:                    } catch (IllegalStateException e) {
1009:                        // If it fails, we try to get a Writer instead if we're
1010:                        // trying to serve a text file
1011:                        if ((contentType != null)
1012:                                && (contentType.startsWith("text"))) {
1013:                            writer = response.getWriter();
1014:                        } else {
1015:                            throw e;
1016:                        }
1017:                    }
1018:
1019:                }
1020:
1021:                if ((resourceInfo.collection)
1022:                        || (((ranges == null) || (ranges.isEmpty())) && (request
1023:                                .getHeader("Range") == null))) {
1024:
1025:                    // Set the appropriate output headers
1026:                    if (contentType != null) {
1027:                        if (debug > 0)
1028:                            log("DefaultServlet.serveFile:  contentType='"
1029:                                    + contentType + "'");
1030:                        response.setContentType(contentType);
1031:                    }
1032:                    long contentLength = resourceInfo.length;
1033:                    if ((!resourceInfo.collection) && (contentLength >= 0)) {
1034:                        if (debug > 0)
1035:                            log("DefaultServlet.serveFile:  contentLength="
1036:                                    + contentLength);
1037:                        response.setContentLength((int) contentLength);
1038:                    }
1039:
1040:                    if (resourceInfo.collection) {
1041:
1042:                        if (content) {
1043:                            // Serve the directory browser
1044:                            resourceInfo.setStream(render(request
1045:                                    .getContextPath(), resourceInfo));
1046:                        }
1047:
1048:                    }
1049:
1050:                    // Copy the input stream to our output stream (if requested)
1051:                    if (content) {
1052:                        try {
1053:                            response.setBufferSize(output);
1054:                        } catch (IllegalStateException e) {
1055:                            // Silent catch
1056:                        }
1057:                        if (ostream != null) {
1058:                            copy(resourceInfo, ostream);
1059:                        } else {
1060:                            copy(resourceInfo, writer);
1061:                        }
1062:                    }
1063:
1064:                } else {
1065:
1066:                    if ((ranges == null) || (ranges.isEmpty()))
1067:                        return;
1068:
1069:                    // Partial content response.
1070:
1071:                    response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
1072:
1073:                    if (ranges.size() == 1) {
1074:
1075:                        Range range = (Range) ranges.elementAt(0);
1076:                        response.addHeader("Content-Range", "bytes "
1077:                                + range.start + "-" + range.end + "/"
1078:                                + range.length);
1079:                        response.setContentLength((int) (range.end
1080:                                - range.start + 1));
1081:
1082:                        if (contentType != null) {
1083:                            if (debug > 0)
1084:                                log("DefaultServlet.serveFile:  contentType='"
1085:                                        + contentType + "'");
1086:                            response.setContentType(contentType);
1087:                        }
1088:
1089:                        if (content) {
1090:                            try {
1091:                                response.setBufferSize(output);
1092:                            } catch (IllegalStateException e) {
1093:                                // Silent catch
1094:                            }
1095:                            if (ostream != null) {
1096:                                copy(resourceInfo, ostream, range);
1097:                            } else {
1098:                                copy(resourceInfo, writer, range);
1099:                            }
1100:                        }
1101:
1102:                    } else {
1103:
1104:                        response
1105:                                .setContentType("multipart/byteranges; boundary="
1106:                                        + mimeSeparation);
1107:
1108:                        if (content) {
1109:                            try {
1110:                                response.setBufferSize(output);
1111:                            } catch (IllegalStateException e) {
1112:                                // Silent catch
1113:                            }
1114:                            if (ostream != null) {
1115:                                copy(resourceInfo, ostream, ranges.elements(),
1116:                                        contentType);
1117:                            } else {
1118:                                copy(resourceInfo, writer, ranges.elements(),
1119:                                        contentType);
1120:                            }
1121:                        }
1122:
1123:                    }
1124:
1125:                }
1126:
1127:            }
1128:
1129:            /**
1130:             * Parse the content-range header.
1131:             *
1132:             * @param request The servlet request we are processing
1133:             * @param response The servlet response we are creating
1134:             * @return Range
1135:             */
1136:            protected Range parseContentRange(HttpServletRequest request,
1137:                    HttpServletResponse response) throws IOException {
1138:
1139:                // Retrieving the content-range header (if any is specified
1140:                String rangeHeader = request.getHeader("Content-Range");
1141:
1142:                if (rangeHeader == null)
1143:                    return null;
1144:
1145:                // bytes is the only range unit supported
1146:                if (!rangeHeader.startsWith("bytes")) {
1147:                    response.sendError(HttpServletResponse.SC_BAD_REQUEST);
1148:                    return null;
1149:                }
1150:
1151:                rangeHeader = rangeHeader.substring(6).trim();
1152:
1153:                int dashPos = rangeHeader.indexOf('-');
1154:                int slashPos = rangeHeader.indexOf('/');
1155:
1156:                if (dashPos == -1) {
1157:                    response.sendError(HttpServletResponse.SC_BAD_REQUEST);
1158:                    return null;
1159:                }
1160:
1161:                if (slashPos == -1) {
1162:                    response.sendError(HttpServletResponse.SC_BAD_REQUEST);
1163:                    return null;
1164:                }
1165:
1166:                Range range = new Range();
1167:
1168:                try {
1169:                    range.start = Long.parseLong(rangeHeader.substring(0,
1170:                            dashPos));
1171:                    range.end = Long.parseLong(rangeHeader.substring(
1172:                            dashPos + 1, slashPos));
1173:                    range.length = Long.parseLong(rangeHeader.substring(
1174:                            slashPos + 1, rangeHeader.length()));
1175:                } catch (NumberFormatException e) {
1176:                    response.sendError(HttpServletResponse.SC_BAD_REQUEST);
1177:                    return null;
1178:                }
1179:
1180:                if (!range.validate()) {
1181:                    response.sendError(HttpServletResponse.SC_BAD_REQUEST);
1182:                    return null;
1183:                }
1184:
1185:                return range;
1186:
1187:            }
1188:
1189:            /**
1190:             * Parse the range header.
1191:             *
1192:             * @param request The servlet request we are processing
1193:             * @param response The servlet response we are creating
1194:             * @return Vector of ranges
1195:             */
1196:            protected Vector parseRange(HttpServletRequest request,
1197:                    HttpServletResponse response, ResourceInfo resourceInfo)
1198:                    throws IOException {
1199:
1200:                // Checking If-Range
1201:                String headerValue = request.getHeader("If-Range");
1202:                if (headerValue != null) {
1203:
1204:                    String eTag = getETag(resourceInfo);
1205:                    long lastModified = resourceInfo.date;
1206:
1207:                    Date date = null;
1208:
1209:                    // Parsing the HTTP Date
1210:                    for (int i = 0; (date == null) && (i < formats.length); i++) {
1211:                        try {
1212:                            date = formats[i].parse(headerValue);
1213:                        } catch (ParseException e) {
1214:                            ;
1215:                        }
1216:                    }
1217:
1218:                    if (date == null) {
1219:
1220:                        // If the ETag the client gave does not match the entity
1221:                        // etag, then the entire entity is returned.
1222:                        if (!eTag.equals(headerValue.trim()))
1223:                            return null;
1224:
1225:                    } else {
1226:
1227:                        // If the timestamp of the entity the client got is older than
1228:                        // the last modification date of the entity, the entire entity
1229:                        // is returned.
1230:                        if (lastModified > (date.getTime() + 1000))
1231:                            return null;
1232:
1233:                    }
1234:
1235:                }
1236:
1237:                long fileLength = resourceInfo.length;
1238:
1239:                if (fileLength == 0)
1240:                    return null;
1241:
1242:                // Retrieving the range header (if any is specified
1243:                String rangeHeader = request.getHeader("Range");
1244:
1245:                if (rangeHeader == null)
1246:                    return null;
1247:                // bytes is the only range unit supported (and I don't see the point
1248:                // of adding new ones).
1249:                if (!rangeHeader.startsWith("bytes")) {
1250:                    response
1251:                            .addHeader("Content-Range", "bytes */" + fileLength);
1252:                    response
1253:                            .sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
1254:                    return null;
1255:                }
1256:
1257:                rangeHeader = rangeHeader.substring(6);
1258:
1259:                // Vector which will contain all the ranges which are successfully
1260:                // parsed.
1261:                Vector result = new Vector();
1262:                StringTokenizer commaTokenizer = new StringTokenizer(
1263:                        rangeHeader, ",");
1264:
1265:                // Parsing the range list
1266:                while (commaTokenizer.hasMoreTokens()) {
1267:                    String rangeDefinition = commaTokenizer.nextToken();
1268:
1269:                    Range currentRange = new Range();
1270:                    currentRange.length = fileLength;
1271:
1272:                    int dashPos = rangeDefinition.indexOf('-');
1273:
1274:                    if (dashPos == -1) {
1275:                        response.addHeader("Content-Range", "bytes */"
1276:                                + fileLength);
1277:                        response
1278:                                .sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
1279:                        return null;
1280:                    }
1281:
1282:                    if (dashPos == 0) {
1283:
1284:                        try {
1285:                            long offset = Long.parseLong(rangeDefinition);
1286:                            currentRange.start = fileLength + offset;
1287:                            currentRange.end = fileLength - 1;
1288:                        } catch (NumberFormatException e) {
1289:                            response.addHeader("Content-Range", "bytes */"
1290:                                    + fileLength);
1291:                            response
1292:                                    .sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
1293:                            return null;
1294:                        }
1295:
1296:                    } else {
1297:
1298:                        try {
1299:                            currentRange.start = Long.parseLong(rangeDefinition
1300:                                    .substring(0, dashPos));
1301:                            if (dashPos < rangeDefinition.length() - 1)
1302:                                currentRange.end = Long
1303:                                        .parseLong(rangeDefinition.substring(
1304:                                                dashPos + 1, rangeDefinition
1305:                                                        .length()));
1306:                            else
1307:                                currentRange.end = fileLength - 1;
1308:                        } catch (NumberFormatException e) {
1309:                            response.addHeader("Content-Range", "bytes */"
1310:                                    + fileLength);
1311:                            response
1312:                                    .sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
1313:                            return null;
1314:                        }
1315:
1316:                    }
1317:
1318:                    if (!currentRange.validate()) {
1319:                        response.addHeader("Content-Range", "bytes */"
1320:                                + fileLength);
1321:                        response
1322:                                .sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
1323:                        return null;
1324:                    }
1325:
1326:                    result.addElement(currentRange);
1327:                }
1328:
1329:                return result;
1330:            }
1331:
1332:            /**
1333:             * Append the request parameters to the redirection string before calling
1334:             * sendRedirect.
1335:             */
1336:            protected String appendParameters(HttpServletRequest request,
1337:                    String redirectPath) {
1338:
1339:                StringBuffer result = new StringBuffer(rewriteUrl(redirectPath));
1340:
1341:                String query = request.getQueryString();
1342:                if (query != null)
1343:                    result.append("?").append(query);
1344:
1345:                return result.toString();
1346:
1347:            }
1348:
1349:            /**
1350:             * Return an InputStream to an HTML representation of the contents
1351:             * of this directory.
1352:             *
1353:             * @param contextPath Context path to which our internal paths are
1354:             *  relative
1355:             */
1356:            protected InputStream render
1357:        (String contextPath, ResourceInfo resourceInfo) {
1358:
1359:        String name = resourceInfo.path;
1360:
1361:        // Number of characters to trim from the beginnings of filenames
1362:        int trim = name.length();
1363:        if (!name.endsWith("/"))
1364:            trim += 1;
1365:        if (name.equals("/"))
1366:            trim = 1;
1367:
1368:        // Prepare a writer to a buffered area
1369:        ByteArrayOutputStream stream = new ByteArrayOutputStream();
1370:        OutputStreamWriter osWriter = null;
1371:        try {
1372:            osWriter = new OutputStreamWriter(stream, "UTF8");
1373:        } catch (Exception e) {
1374:            // Should never happen
1375:            osWriter = new OutputStreamWriter(stream);
1376:        }
1377:        PrintWriter writer = new PrintWriter(osWriter);
1378:
1379:        StringBuffer sb = new StringBuffer();
1380:
1381:        // Render the page header
1382:        sb.append("<html>\r\n");
1383:        sb.append("<head>\r\n");
1384:        sb.append("<title>");
1385:        sb.append(sm.getString("directory.title", name));
1386:        sb.append("</title>\r\n");
1387:        sb.append("<STYLE><!--");
1388:        sb.append("H1{font-family : sans-serif,Arial,Tahoma;color : white;background-color : #0086b2;} ");
1389:        sb.append("H3{font-family : sans-serif,Arial,Tahoma;color : white;background-color : #0086b2;} ");
1390:        sb.append("BODY{font-family : sans-serif,Arial,Tahoma;color : black;background-color : white;} ");
1391:        sb.append("B{color : white;background-color : #0086b2;} ");
1392:        sb.append("A{color : black;} ");
1393:        sb.append("HR{color : #0086b2;} ");
1394:        sb.append("--></STYLE> ");
1395:        sb.append("</head>\r\n");
1396:        sb.append("<body>");
1397:        sb.append("<h1>");
1398:        sb.append(sm.getString("directory.title", name));
1399:
1400:        // Render the link to our parent (if required)
1401:        String parentDirectory = name;
1402:        if (parentDirectory.endsWith("/")) {
1403:            parentDirectory =
1404:                parentDirectory.substring(0, parentDirectory.length() - 1);
1405:        }
1406:        int slash = parentDirectory.lastIndexOf('/');
1407:        if (slash >= 0) {
1408:            String parent = name.substring(0, slash);
1409:            sb.append(" - <a href=\"");
1410:            sb.append(rewriteUrl(contextPath));
1411:            if (parent.equals(""))
1412:                parent = "/";
1413:            sb.append(rewriteUrl(parent));
1414:            if (!parent.endsWith("/"))
1415:                sb.append("/");
1416:            sb.append("\">");
1417:            sb.append("<b>");
1418:            sb.append(sm.getString("directory.parent", parent));
1419:            sb.append("</b>");
1420:            sb.append("</a>");
1421:        }
1422:
1423:        sb.append("</h1>");
1424:        sb.append("<HR size=\"1\" noshade>");
1425:
1426:        sb.append("<table width=\"100%\" cellspacing=\"0\"" +
1427:                     " cellpadding=\"5\" align=\"center\">\r\n");
1428:
1429:        // Render the column headings
1430:        sb.append("<tr>\r\n");
1431:        sb.append("<td align=\"left\"><font size=\"+1\"><strong>");
1432:        sb.append(sm.getString("directory.filename"));
1433:        sb.append("</strong></font></td>\r\n");
1434:        sb.append("<td align=\"center\"><font size=\"+1\"><strong>");
1435:        sb.append(sm.getString("directory.size"));
1436:        sb.append("</strong></font></td>\r\n");
1437:        sb.append("<td align=\"right\"><font size=\"+1\"><strong>");
1438:        sb.append(sm.getString("directory.lastModified"));
1439:        sb.append("</strong></font></td>\r\n");
1440:        sb.append("</tr>");
1441:
1442:        try {
1443:
1444:            // Render the directory entries within this directory
1445:            DirContext directory = resourceInfo.directory;
1446:            NamingEnumeration enum =
1447:                resourceInfo.resources.list(resourceInfo.path);
1448:            boolean shade = false;
1449:            while (enum.hasMoreElements()) {
1450:
1451:                NameClassPair ncPair = (NameClassPair) enum.nextElement();
1452:                String resourceName = ncPair.getName();
1453:                ResourceInfo childResourceInfo =
1454:                    new ResourceInfo(resourceName, directory);
1455:
1456:                String trimmed = resourceName/*.substring(trim)*/;
1457:                if (trimmed.equalsIgnoreCase("WEB-INF") ||
1458:                    trimmed.equalsIgnoreCase("META-INF"))
1459:                    continue;
1460:
1461:                sb.append("<tr");
1462:                if (shade)
1463:                    sb.append(" bgcolor=\"eeeeee\"");
1464:                sb.append(">\r\n");
1465:                shade = !shade;
1466:
1467:                sb.append("<td align=\"left\">&nbsp;&nbsp;\r\n");
1468:                sb.append("<a href=\"");
1469:                sb.append(rewriteUrl(contextPath));
1470:                resourceName = rewriteUrl(name + resourceName);
1471:                sb.append(resourceName);
1472:                if (childResourceInfo.collection)
1473:                    sb.append("/");
1474:                sb.append("\"><tt>");
1475:                sb.append(trimmed);
1476:                if (childResourceInfo.collection)
1477:                    sb.append("/");
1478:                sb.append("</tt></a></td>\r\n");
1479:
1480:                sb.append("<td align=\"right\"><tt>");
1481:                if (childResourceInfo.collection)
1482:                    sb.append("&nbsp;");
1483:                else
1484:                    sb.append(renderSize(childResourceInfo.length));
1485:                sb.append("</tt></td>\r\n");
1486:
1487:                sb.append("<td align=\"right\"><tt>");
1488:                sb.append(childResourceInfo.httpDate);
1489:                sb.append("</tt></td>\r\n");
1490:
1491:                sb.append("</tr>\r\n");
1492:            }
1493:
1494:        } catch (NamingException e) {
1495:            // Something went wrong
1496:            e.printStackTrace();
1497:        }
1498:
1499:        // Render the page footer
1500:        sb.append("</table>\r\n");
1501:
1502:        sb.append("<HR size=\"1\" noshade>");
1503:        sb.append("<h3>").append(ServerInfo.getServerInfo()).append("</h3>");
1504:        sb.append("</body>\r\n");
1505:        sb.append("</html>\r\n");
1506:
1507:        // Return an input stream to the underlying bytes
1508:        writer.write(sb.toString());
1509:        writer.flush();
1510:        return (new ByteArrayInputStream(stream.toByteArray()));
1511:
1512:    }
1513:
1514:            /**
1515:             * Render the specified file size (in bytes).
1516:             *
1517:             * @param size File size (in bytes)
1518:             */
1519:            protected String renderSize(long size) {
1520:
1521:                long leftSide = size / 1024;
1522:                long rightSide = (size % 1024) / 103; // Makes 1 digit
1523:                if ((leftSide == 0) && (rightSide == 0) && (size > 0))
1524:                    rightSide = 1;
1525:
1526:                return ("" + leftSide + "." + rightSide + " kb");
1527:
1528:            }
1529:
1530:            // -------------------------------------------------------- Private Methods
1531:
1532:            /**
1533:             * Check if the if-match condition is satisfied.
1534:             *
1535:             * @param request The servlet request we are processing
1536:             * @param response The servlet response we are creating
1537:             * @param resourceInfo File object
1538:             * @return boolean true if the resource meets the specified condition,
1539:             * and false if the condition is not satisfied, in which case request 
1540:             * processing is stopped
1541:             */
1542:            private boolean checkIfMatch(HttpServletRequest request,
1543:                    HttpServletResponse response, ResourceInfo resourceInfo)
1544:                    throws IOException {
1545:
1546:                String eTag = getETag(resourceInfo);
1547:                String headerValue = request.getHeader("If-Match");
1548:                if (headerValue != null) {
1549:                    if (headerValue.indexOf('*') == -1) {
1550:
1551:                        StringTokenizer commaTokenizer = new StringTokenizer(
1552:                                headerValue, ",");
1553:                        boolean conditionSatisfied = false;
1554:
1555:                        while (!conditionSatisfied
1556:                                && commaTokenizer.hasMoreTokens()) {
1557:                            String currentToken = commaTokenizer.nextToken();
1558:                            if (currentToken.trim().equals(eTag))
1559:                                conditionSatisfied = true;
1560:                        }
1561:
1562:                        // If none of the given ETags match, 412 Precodition failed is
1563:                        // sent back
1564:                        if (!conditionSatisfied) {
1565:                            response
1566:                                    .sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
1567:                            return false;
1568:                        }
1569:
1570:                    }
1571:                }
1572:                return true;
1573:
1574:            }
1575:
1576:            /**
1577:             * Check if the if-modified-since condition is satisfied.
1578:             *
1579:             * @param request The servlet request we are processing
1580:             * @param response The servlet response we are creating
1581:             * @param resourceInfo File object
1582:             * @return boolean true if the resource meets the specified condition,
1583:             * and false if the condition is not satisfied, in which case request 
1584:             * processing is stopped
1585:             */
1586:            private boolean checkIfModifiedSince(HttpServletRequest request,
1587:                    HttpServletResponse response, ResourceInfo resourceInfo)
1588:                    throws IOException {
1589:                try {
1590:                    long headerValue = request
1591:                            .getDateHeader("If-Modified-Since");
1592:                    long lastModified = resourceInfo.date;
1593:                    if (headerValue != -1) {
1594:
1595:                        // If an If-None-Match header has been specified, if modified since
1596:                        // is ignored.
1597:                        if ((request.getHeader("If-None-Match") == null)
1598:                                && (lastModified <= headerValue + 1000)) {
1599:                            // The entity has not been modified since the date
1600:                            // specified by the client. This is not an error case.
1601:                            response
1602:                                    .setStatus(HttpServletResponse.SC_NOT_MODIFIED);
1603:                            return false;
1604:                        }
1605:                    }
1606:                } catch (IllegalArgumentException illegalArgument) {
1607:                    return false;
1608:                }
1609:                return true;
1610:
1611:            }
1612:
1613:            /**
1614:             * Check if the if-none-match condition is satisfied.
1615:             *
1616:             * @param request The servlet request we are processing
1617:             * @param response The servlet response we are creating
1618:             * @param resourceInfo File object
1619:             * @return boolean true if the resource meets the specified condition,
1620:             * and false if the condition is not satisfied, in which case request 
1621:             * processing is stopped
1622:             */
1623:            private boolean checkIfNoneMatch(HttpServletRequest request,
1624:                    HttpServletResponse response, ResourceInfo resourceInfo)
1625:                    throws IOException {
1626:
1627:                String eTag = getETag(resourceInfo);
1628:                String headerValue = request.getHeader("If-None-Match");
1629:                if (headerValue != null) {
1630:
1631:                    boolean conditionSatisfied = false;
1632:
1633:                    if (!headerValue.equals("*")) {
1634:
1635:                        StringTokenizer commaTokenizer = new StringTokenizer(
1636:                                headerValue, ",");
1637:
1638:                        while (!conditionSatisfied
1639:                                && commaTokenizer.hasMoreTokens()) {
1640:                            String currentToken = commaTokenizer.nextToken();
1641:                            if (currentToken.trim().equals(eTag))
1642:                                conditionSatisfied = true;
1643:                        }
1644:
1645:                    } else {
1646:                        conditionSatisfied = true;
1647:                    }
1648:
1649:                    if (conditionSatisfied) {
1650:
1651:                        // For GET and HEAD, we should respond with
1652:                        // 304 Not Modified.
1653:                        // For every other method, 412 Precondition Failed is sent
1654:                        // back.
1655:                        if (("GET".equals(request.getMethod()))
1656:                                || ("HEAD".equals(request.getMethod()))) {
1657:                            response
1658:                                    .setStatus(HttpServletResponse.SC_NOT_MODIFIED);
1659:                            return false;
1660:                        } else {
1661:                            response
1662:                                    .sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
1663:                            return false;
1664:                        }
1665:                    }
1666:                }
1667:                return true;
1668:
1669:            }
1670:
1671:            /**
1672:             * Check if the if-unmodified-since condition is satisfied.
1673:             *
1674:             * @param request The servlet request we are processing
1675:             * @param response The servlet response we are creating
1676:             * @param resourceInfo File object
1677:             * @return boolean true if the resource meets the specified condition,
1678:             * and false if the condition is not satisfied, in which case request 
1679:             * processing is stopped
1680:             */
1681:            private boolean checkIfUnmodifiedSince(HttpServletRequest request,
1682:                    HttpServletResponse response, ResourceInfo resourceInfo)
1683:                    throws IOException {
1684:                try {
1685:                    long lastModified = resourceInfo.date;
1686:                    long headerValue = request
1687:                            .getDateHeader("If-Unmodified-Since");
1688:                    if (headerValue != -1) {
1689:                        if (lastModified > headerValue) {
1690:                            // The entity has not been modified since the date
1691:                            // specified by the client. This is not an error case.
1692:                            response
1693:                                    .sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
1694:                            return false;
1695:                        }
1696:                    }
1697:                } catch (IllegalArgumentException illegalArgument) {
1698:                    return false;
1699:                }
1700:                return true;
1701:
1702:            }
1703:
1704:            /**
1705:             * Copy the contents of the specified input stream to the specified
1706:             * output stream, and ensure that both streams are closed before returning
1707:             * (even in the face of an exception).
1708:             *
1709:             * @param istream The input stream to read from
1710:             * @param ostream The output stream to write to
1711:             *
1712:             * @exception IOException if an input/output error occurs
1713:             */
1714:            private void copy(ResourceInfo resourceInfo,
1715:                    ServletOutputStream ostream) throws IOException {
1716:
1717:                IOException exception = null;
1718:
1719:                // FIXME : i18n ?
1720:                InputStream resourceInputStream = resourceInfo.getStream();
1721:                InputStream istream = new BufferedInputStream(
1722:                        resourceInputStream, input);
1723:
1724:                // Copy the input stream to the output stream
1725:                exception = copyRange(istream, ostream);
1726:
1727:                // Clean up the input stream
1728:                try {
1729:                    istream.close();
1730:                } catch (Throwable t) {
1731:                    ;
1732:                }
1733:
1734:                // Rethrow any exception that has occurred
1735:                if (exception != null)
1736:                    throw exception;
1737:
1738:            }
1739:
1740:            /**
1741:             * Copy the contents of the specified input stream to the specified
1742:             * output stream, and ensure that both streams are closed before returning
1743:             * (even in the face of an exception).
1744:             *
1745:             * @param istream The input stream to read from
1746:             * @param writer The writer to write to
1747:             *
1748:             * @exception IOException if an input/output error occurs
1749:             */
1750:            private void copy(ResourceInfo resourceInfo, PrintWriter writer)
1751:                    throws IOException {
1752:
1753:                IOException exception = null;
1754:
1755:                InputStream resourceInputStream = resourceInfo.getStream();
1756:                // FIXME : i18n ?
1757:                Reader reader = new InputStreamReader(resourceInputStream);
1758:
1759:                // Copy the input stream to the output stream
1760:                exception = copyRange(reader, writer);
1761:
1762:                // Clean up the reader
1763:                try {
1764:                    reader.close();
1765:                } catch (Throwable t) {
1766:                    ;
1767:                }
1768:
1769:                // Rethrow any exception that has occurred
1770:                if (exception != null)
1771:                    throw exception;
1772:
1773:            }
1774:
1775:            /**
1776:             * Copy the contents of the specified input stream to the specified
1777:             * output stream, and ensure that both streams are closed before returning
1778:             * (even in the face of an exception).
1779:             *
1780:             * @param resourceInfo The ResourceInfo object
1781:             * @param ostream The output stream to write to
1782:             * @param range Range the client wanted to retrieve
1783:             * @exception IOException if an input/output error occurs
1784:             */
1785:            private void copy(ResourceInfo resourceInfo,
1786:                    ServletOutputStream ostream, Range range)
1787:                    throws IOException {
1788:
1789:                IOException exception = null;
1790:
1791:                InputStream resourceInputStream = resourceInfo.getStream();
1792:                InputStream istream = new BufferedInputStream(
1793:                        resourceInputStream, input);
1794:                exception = copyRange(istream, ostream, range.start, range.end);
1795:
1796:                // Clean up the input stream
1797:                try {
1798:                    istream.close();
1799:                } catch (Throwable t) {
1800:                    ;
1801:                }
1802:
1803:                // Rethrow any exception that has occurred
1804:                if (exception != null)
1805:                    throw exception;
1806:
1807:            }
1808:
1809:            /**
1810:             * Copy the contents of the specified input stream to the specified
1811:             * output stream, and ensure that both streams are closed before returning
1812:             * (even in the face of an exception).
1813:             *
1814:             * @param resourceInfo The ResourceInfo object
1815:             * @param writer The writer to write to
1816:             * @param range Range the client wanted to retrieve
1817:             * @exception IOException if an input/output error occurs
1818:             */
1819:            private void copy(ResourceInfo resourceInfo, PrintWriter writer,
1820:                    Range range) throws IOException {
1821:
1822:                IOException exception = null;
1823:
1824:                InputStream resourceInputStream = resourceInfo.getStream();
1825:                Reader reader = new InputStreamReader(resourceInputStream);
1826:                exception = copyRange(reader, writer, range.start, range.end);
1827:
1828:                // Clean up the input stream
1829:                try {
1830:                    reader.close();
1831:                } catch (Throwable t) {
1832:                    ;
1833:                }
1834:
1835:                // Rethrow any exception that has occurred
1836:                if (exception != null)
1837:                    throw exception;
1838:
1839:            }
1840:
1841:            /**
1842:             * Copy the contents of the specified input stream to the specified
1843:             * output stream, and ensure that both streams are closed before returning
1844:             * (even in the face of an exception).
1845:             *
1846:             * @param resourceInfo The ResourceInfo object
1847:             * @param ostream The output stream to write to
1848:             * @param ranges Enumeration of the ranges the client wanted to retrieve
1849:             * @param contentType Content type of the resource
1850:             * @exception IOException if an input/output error occurs
1851:             */
1852:            private void copy(ResourceInfo resourceInfo,
1853:                    ServletOutputStream ostream, Enumeration ranges,
1854:                    String contentType) throws IOException {
1855:
1856:                IOException exception = null;
1857:
1858:                while ((exception == null) && (ranges.hasMoreElements())) {
1859:
1860:                    InputStream resourceInputStream = resourceInfo.getStream();
1861:                    InputStream istream = // FIXME: internationalization???????
1862:                    new BufferedInputStream(resourceInputStream, input);
1863:
1864:                    Range currentRange = (Range) ranges.nextElement();
1865:
1866:                    // Writing MIME header.
1867:                    ostream.println("--" + mimeSeparation);
1868:                    if (contentType != null)
1869:                        ostream.println("Content-Type: " + contentType);
1870:                    ostream.println("Content-Range: bytes "
1871:                            + currentRange.start + "-" + currentRange.end + "/"
1872:                            + currentRange.length);
1873:                    ostream.println();
1874:
1875:                    // Printing content
1876:                    exception = copyRange(istream, ostream, currentRange.start,
1877:                            currentRange.end);
1878:
1879:                    try {
1880:                        istream.close();
1881:                    } catch (Throwable t) {
1882:                        ;
1883:                    }
1884:
1885:                }
1886:
1887:                ostream.print("--" + mimeSeparation + "--");
1888:
1889:                // Rethrow any exception that has occurred
1890:                if (exception != null)
1891:                    throw exception;
1892:
1893:            }
1894:
1895:            /**
1896:             * Copy the contents of the specified input stream to the specified
1897:             * output stream, and ensure that both streams are closed before returning
1898:             * (even in the face of an exception).
1899:             *
1900:             * @param resourceInfo The ResourceInfo object
1901:             * @param writer The writer to write to
1902:             * @param ranges Enumeration of the ranges the client wanted to retrieve
1903:             * @param contentType Content type of the resource
1904:             * @exception IOException if an input/output error occurs
1905:             */
1906:            private void copy(ResourceInfo resourceInfo, PrintWriter writer,
1907:                    Enumeration ranges, String contentType) throws IOException {
1908:
1909:                IOException exception = null;
1910:
1911:                while ((exception == null) && (ranges.hasMoreElements())) {
1912:
1913:                    InputStream resourceInputStream = resourceInfo.getStream();
1914:                    Reader reader = new InputStreamReader(resourceInputStream);
1915:
1916:                    Range currentRange = (Range) ranges.nextElement();
1917:
1918:                    // Writing MIME header.
1919:                    writer.println("--" + mimeSeparation);
1920:                    if (contentType != null)
1921:                        writer.println("Content-Type: " + contentType);
1922:                    writer.println("Content-Range: bytes " + currentRange.start
1923:                            + "-" + currentRange.end + "/"
1924:                            + currentRange.length);
1925:                    writer.println();
1926:
1927:                    // Printing content
1928:                    exception = copyRange(reader, writer, currentRange.start,
1929:                            currentRange.end);
1930:
1931:                    try {
1932:                        reader.close();
1933:                    } catch (Throwable t) {
1934:                        ;
1935:                    }
1936:
1937:                }
1938:
1939:                writer.print("--" + mimeSeparation + "--");
1940:
1941:                // Rethrow any exception that has occurred
1942:                if (exception != null)
1943:                    throw exception;
1944:
1945:            }
1946:
1947:            /**
1948:             * Copy the contents of the specified input stream to the specified
1949:             * output stream, and ensure that both streams are closed before returning
1950:             * (even in the face of an exception).
1951:             *
1952:             * @param istream The input stream to read from
1953:             * @param ostream The output stream to write to
1954:             * @return Exception which occurred during processing
1955:             */
1956:            private IOException copyRange(InputStream istream,
1957:                    ServletOutputStream ostream) {
1958:
1959:                // Copy the input stream to the output stream
1960:                IOException exception = null;
1961:                byte buffer[] = new byte[input];
1962:                int len = buffer.length;
1963:                while (true) {
1964:                    try {
1965:                        len = istream.read(buffer);
1966:                        if (len == -1)
1967:                            break;
1968:                        ostream.write(buffer, 0, len);
1969:                    } catch (IOException e) {
1970:                        exception = e;
1971:                        len = -1;
1972:                        break;
1973:                    }
1974:                }
1975:                return exception;
1976:
1977:            }
1978:
1979:            /**
1980:             * Copy the contents of the specified input stream to the specified
1981:             * output stream, and ensure that both streams are closed before returning
1982:             * (even in the face of an exception).
1983:             *
1984:             * @param reader The reader to read from
1985:             * @param writer The writer to write to
1986:             * @return Exception which occurred during processing
1987:             */
1988:            private IOException copyRange(Reader reader, PrintWriter writer) {
1989:
1990:                // Copy the input stream to the output stream
1991:                IOException exception = null;
1992:                char buffer[] = new char[input];
1993:                int len = buffer.length;
1994:                while (true) {
1995:                    try {
1996:                        len = reader.read(buffer);
1997:                        if (len == -1)
1998:                            break;
1999:                        writer.write(buffer, 0, len);
2000:                    } catch (IOException e) {
2001:                        exception = e;
2002:                        len = -1;
2003:                        break;
2004:                    }
2005:                }
2006:                return exception;
2007:
2008:            }
2009:
2010:            /**
2011:             * Copy the contents of the specified input stream to the specified
2012:             * output stream, and ensure that both streams are closed before returning
2013:             * (even in the face of an exception).
2014:             *
2015:             * @param istream The input stream to read from
2016:             * @param ostream The output stream to write to
2017:             * @param start Start of the range which will be copied
2018:             * @param end End of the range which will be copied
2019:             * @return Exception which occurred during processing
2020:             */
2021:            private IOException copyRange(InputStream istream,
2022:                    ServletOutputStream ostream, long start, long end) {
2023:
2024:                if (debug > 10)
2025:                    System.out.println("Serving bytes:" + start + "-" + end);
2026:
2027:                try {
2028:                    istream.skip(start);
2029:                } catch (IOException e) {
2030:                    return e;
2031:                }
2032:
2033:                IOException exception = null;
2034:                long bytesToRead = end - start + 1;
2035:
2036:                byte buffer[] = new byte[input];
2037:                int len = buffer.length;
2038:                while ((bytesToRead > 0) && (len >= buffer.length)) {
2039:                    try {
2040:                        len = istream.read(buffer);
2041:                        if (bytesToRead >= len) {
2042:                            ostream.write(buffer, 0, len);
2043:                            bytesToRead -= len;
2044:                        } else {
2045:                            ostream.write(buffer, 0, (int) bytesToRead);
2046:                            bytesToRead = 0;
2047:                        }
2048:                    } catch (IOException e) {
2049:                        exception = e;
2050:                        len = -1;
2051:                    }
2052:                    if (len < buffer.length)
2053:                        break;
2054:                }
2055:
2056:                return exception;
2057:
2058:            }
2059:
2060:            /**
2061:             * Copy the contents of the specified input stream to the specified
2062:             * output stream, and ensure that both streams are closed before returning
2063:             * (even in the face of an exception).
2064:             *
2065:             * @param reader The reader to read from
2066:             * @param writer The writer to write to
2067:             * @param start Start of the range which will be copied
2068:             * @param end End of the range which will be copied
2069:             * @return Exception which occurred during processing
2070:             */
2071:            private IOException copyRange(Reader reader, PrintWriter writer,
2072:                    long start, long end) {
2073:
2074:                try {
2075:                    reader.skip(start);
2076:                } catch (IOException e) {
2077:                    return e;
2078:                }
2079:
2080:                IOException exception = null;
2081:                long bytesToRead = end - start + 1;
2082:
2083:                char buffer[] = new char[input];
2084:                int len = buffer.length;
2085:                while ((bytesToRead > 0) && (len >= buffer.length)) {
2086:                    try {
2087:                        len = reader.read(buffer);
2088:                        if (bytesToRead >= len) {
2089:                            writer.write(buffer, 0, len);
2090:                            bytesToRead -= len;
2091:                        } else {
2092:                            writer.write(buffer, 0, (int) bytesToRead);
2093:                            bytesToRead = 0;
2094:                        }
2095:                    } catch (IOException e) {
2096:                        exception = e;
2097:                        len = -1;
2098:                    }
2099:                    if (len < buffer.length)
2100:                        break;
2101:                }
2102:
2103:                return exception;
2104:
2105:            }
2106:
2107:            /**
2108:             * Check to see if a default page exists.
2109:             *
2110:             * @param pathname Pathname of the file to be served
2111:             */
2112:            private ResourceInfo checkWelcomeFiles(String pathname,
2113:                    DirContext resources) {
2114:
2115:                String collectionName = pathname;
2116:                if (!pathname.endsWith("/")) {
2117:                    collectionName += "/";
2118:                }
2119:
2120:                // Refresh our currently defined set of welcome files
2121:                synchronized (welcomes) {
2122:                    welcomes = (String[]) getServletContext().getAttribute(
2123:                            Globals.WELCOME_FILES_ATTR);
2124:                    if (welcomes == null)
2125:                        welcomes = new String[0];
2126:                }
2127:
2128:                // Serve a welcome resource or file if one exists
2129:                for (int i = 0; i < welcomes.length; i++) {
2130:
2131:                    // Does the specified resource exist?
2132:                    String resourceName = collectionName + welcomes[i];
2133:                    ResourceInfo resourceInfo = new ResourceInfo(resourceName,
2134:                            resources);
2135:                    if (resourceInfo.exists()) {
2136:                        return resourceInfo;
2137:                    }
2138:
2139:                }
2140:
2141:                return null;
2142:
2143:            }
2144:
2145:            // ------------------------------------------------------ Range Inner Class
2146:
2147:            private class Range {
2148:
2149:                public long start;
2150:                public long end;
2151:                public long length;
2152:
2153:                /**
2154:                 * Validate range.
2155:                 */
2156:                public boolean validate() {
2157:                    if (end >= length)
2158:                        end = length - 1;
2159:                    return ((start >= 0) && (end >= 0) && (start <= end) && (length > 0));
2160:                }
2161:
2162:                public void recycle() {
2163:                    start = 0;
2164:                    end = 0;
2165:                    length = 0;
2166:                }
2167:
2168:            }
2169:
2170:            // ----------------------------------------------  ResourceInfo Inner Class
2171:
2172:            protected class ResourceInfo {
2173:
2174:                /**
2175:                 * Constructor.
2176:                 *
2177:                 * @param pathname Path name of the file
2178:                 */
2179:                public ResourceInfo(String path, DirContext resources) {
2180:                    set(path, resources);
2181:                }
2182:
2183:                public Object object;
2184:                public DirContext directory;
2185:                public Resource file;
2186:                public Attributes attributes;
2187:                public String path;
2188:                public long creationDate;
2189:                public String httpDate;
2190:                public long date;
2191:                public long length;
2192:                public boolean collection;
2193:                public String weakETag;
2194:                public String strongETag;
2195:                public boolean exists;
2196:                public DirContext resources;
2197:                protected InputStream is;
2198:
2199:                public void recycle() {
2200:                    object = null;
2201:                    directory = null;
2202:                    file = null;
2203:                    attributes = null;
2204:                    path = null;
2205:                    creationDate = 0;
2206:                    httpDate = null;
2207:                    date = 0;
2208:                    length = -1;
2209:                    collection = true;
2210:                    weakETag = null;
2211:                    strongETag = null;
2212:                    exists = false;
2213:                    resources = null;
2214:                    is = null;
2215:                }
2216:
2217:                public void set(String path, DirContext resources) {
2218:
2219:                    recycle();
2220:
2221:                    this .path = path;
2222:                    this .resources = resources;
2223:                    exists = true;
2224:                    try {
2225:                        object = resources.lookup(path);
2226:                        if (object instanceof  Resource) {
2227:                            file = (Resource) object;
2228:                            collection = false;
2229:                        } else if (object instanceof  DirContext) {
2230:                            directory = (DirContext) object;
2231:                            collection = true;
2232:                        } else {
2233:                            // Don't know how to serve another object type
2234:                            exists = false;
2235:                        }
2236:                    } catch (NamingException e) {
2237:                        exists = false;
2238:                    }
2239:                    if (exists) {
2240:                        try {
2241:                            attributes = resources.getAttributes(path);
2242:                            if (attributes instanceof  ResourceAttributes) {
2243:                                ResourceAttributes tempAttrs = (ResourceAttributes) attributes;
2244:                                Date tempDate = tempAttrs.getCreationDate();
2245:                                if (tempDate != null)
2246:                                    creationDate = tempDate.getTime();
2247:                                tempDate = tempAttrs.getLastModifiedDate();
2248:                                if (tempDate != null) {
2249:                                    httpDate = FastHttpDateFormat
2250:                                            .getDate(tempDate);
2251:                                    date = tempDate.getTime();
2252:                                } else {
2253:                                    httpDate = FastHttpDateFormat
2254:                                            .getCurrentDate();
2255:                                }
2256:                                weakETag = tempAttrs.getETag();
2257:                                strongETag = tempAttrs.getETag(true);
2258:                                length = tempAttrs.getContentLength();
2259:                            }
2260:                        } catch (NamingException e) {
2261:                            // Shouldn't happen, the implementation of the DirContext
2262:                            // is probably broken
2263:                            exists = false;
2264:                        }
2265:                    }
2266:
2267:                }
2268:
2269:                /**
2270:                 * Test if the associated resource exists.
2271:                 */
2272:                public boolean exists() {
2273:                    return exists;
2274:                }
2275:
2276:                /**
2277:                 * String representation.
2278:                 */
2279:                public String toString() {
2280:                    return path;
2281:                }
2282:
2283:                /**
2284:                 * Set IS.
2285:                 */
2286:                public void setStream(InputStream is) {
2287:                    this .is = is;
2288:                }
2289:
2290:                /**
2291:                 * Get IS from resource.
2292:                 */
2293:                public InputStream getStream() throws IOException {
2294:                    if (is != null)
2295:                        return is;
2296:                    if (file != null)
2297:                        return (file.streamContent());
2298:                    else
2299:                        return null;
2300:                }
2301:
2302:            }
2303:
2304:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.