Source Code Cross Referenced for DefaultServlet.java in  » J2EE » fleXive » com » flexive » war » webdav » 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 » J2EE » fleXive » com.flexive.war.webdav 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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