Source Code Cross Referenced for DefaultServlet.java in  » Sevlet-Container » tomcat-catalina » 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 » Sevlet Container » tomcat catalina » org.apache.catalina.servlets 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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