Source Code Cross Referenced for HTTPFrame.java in  » Web-Server » Jigsaw » org » w3c » jigsaw » frames » Java Source Code / Java DocumentationJava Source Code and Java Documentation

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


0001:        // HTTPFrame.java
0002:        // $Id: HTTPFrame.java,v 1.115 2007/03/10 12:35:21 ylafon Exp $
0003:        // (c) COPYRIGHT MIT and INRIA, 1997.
0004:        // Please first read the full copyright statement in file COPYRIGHT.html
0005:
0006:        package org.w3c.jigsaw.frames;
0007:
0008:        import java.io.ByteArrayInputStream;
0009:        import java.io.ByteArrayOutputStream;
0010:        import java.io.File;
0011:        import java.io.FileInputStream;
0012:        import java.io.FileNotFoundException;
0013:        import java.io.InputStream;
0014:        import java.io.IOException;
0015:        import java.net.MalformedURLException;
0016:        import java.net.URL;
0017:        import java.net.URLEncoder;
0018:        import java.util.Enumeration;
0019:        import java.util.Hashtable;
0020:        import java.util.Vector;
0021:
0022:        import org.w3c.tools.codec.Base64Encoder;
0023:        import org.w3c.tools.sorter.Sorter;
0024:        import org.w3c.tools.resources.Attribute;
0025:        import org.w3c.tools.resources.AttributeRegistry;
0026:        import org.w3c.tools.resources.BooleanAttribute;
0027:        import org.w3c.tools.resources.IntegerAttribute;
0028:        import org.w3c.tools.resources.LongAttribute;
0029:        import org.w3c.tools.resources.DoubleAttribute;
0030:        import org.w3c.tools.resources.StringAttribute;
0031:        import org.w3c.tools.resources.StringArrayAttribute;
0032:        import org.w3c.tools.resources.ProtocolFrame;
0033:        import org.w3c.tools.resources.ProtocolFrame;
0034:        import org.w3c.tools.resources.LookupState;
0035:        import org.w3c.tools.resources.LookupResult;
0036:        import org.w3c.tools.resources.ResourceReference;
0037:        import org.w3c.tools.resources.InvalidResourceException;
0038:        import org.w3c.tools.resources.MultipleLockException;
0039:        import org.w3c.tools.resources.Resource;
0040:        import org.w3c.tools.resources.FramedResource;
0041:        import org.w3c.tools.resources.ContainerInterface;
0042:        import org.w3c.tools.resources.ContainerResource;
0043:        import org.w3c.tools.resources.DirectoryResource;
0044:        import org.w3c.tools.resources.FileResource;
0045:        import org.w3c.tools.resources.RequestInterface;
0046:        import org.w3c.tools.resources.ReplyInterface;
0047:        import org.w3c.tools.resources.event.AttributeChangedEvent;
0048:        import org.w3c.jigsaw.http.Client;
0049:        import org.w3c.jigsaw.http.ClientException;
0050:        import org.w3c.jigsaw.http.httpd;
0051:        import org.w3c.jigsaw.http.Request;
0052:        import org.w3c.jigsaw.http.Reply;
0053:        import org.w3c.jigsaw.http.HTTPException;
0054:
0055:        import org.w3c.jigsaw.html.HtmlGenerator;
0056:        import org.w3c.jigsaw.html.HtmlLink;
0057:        import org.w3c.www.mime.MimeType;
0058:        import org.w3c.www.http.ByteRangeOutputStream;
0059:        import org.w3c.www.http.HTTP;
0060:        import org.w3c.www.http.HttpContentRange;
0061:        import org.w3c.www.http.HttpDate;
0062:        import org.w3c.www.http.HttpEntityTag;
0063:        import org.w3c.www.http.HttpFactory;
0064:        import org.w3c.www.http.HttpInteger;
0065:        import org.w3c.www.http.HttpMimeType;
0066:        import org.w3c.www.http.HttpRange;
0067:        import org.w3c.www.http.HttpString;
0068:        import org.w3c.www.http.HttpTokenList;
0069:
0070:        import org.w3c.tools.crypt.Md5;
0071:
0072:        import org.w3c.tools.resources.ProtocolException;
0073:        import org.w3c.tools.resources.ResourceException;
0074:
0075:        /**
0076:         * Default class to handle the HTTP protocol, manage FileResource and
0077:         * DirectoryResource.
0078:         */
0079:        public class HTTPFrame extends ProtocolFrame {
0080:
0081:            public static final String STATE_CONTENT_LOCATION = "org.w3c.jigsaw.frames.HTTPFrame.cl";
0082:
0083:            private static final boolean debug = false;
0084:
0085:            /**
0086:             * Condition check return code - Condition existed but failed.
0087:             */
0088:            public static final int COND_FAILED = 1;
0089:            /**
0090:             * Condition check return code - Condition existed and succeeded.
0091:             */
0092:            public static final int COND_OK = 2;
0093:            /**
0094:             * Condition check return code - Condition existed and succeeded 
0095:             *                               but is a weak validation.
0096:             */
0097:            public static final int COND_WEAK = 3;
0098:
0099:            private static HttpTokenList _accept_ranges = null;
0100:            static {
0101:                String accept_ranges[] = { "bytes" };
0102:                _accept_ranges = HttpFactory.makeStringList(accept_ranges);
0103:            }
0104:            /**
0105:             * Methods allowed by instances of that class in particular:
0106:             */
0107:            protected HttpTokenList allowed = null;
0108:
0109:            /**
0110:             * Attributes index - The index for the quality attribute.
0111:             */
0112:            protected static int ATTR_QUALITY = -1;
0113:            /**
0114:             * Attribute index - The index for the title attribute.
0115:             */
0116:            protected static int ATTR_TITLE = -1;
0117:            /**
0118:             * Attribute index - The index for the content languages attribute.
0119:             */
0120:            protected static int ATTR_CONTENT_LANGUAGE = -1;
0121:            /**
0122:             * Attribute index - The index for the content encodings attribute.
0123:             */
0124:            protected static int ATTR_CONTENT_ENCODING = -1;
0125:            /**
0126:             * Attribute index - The index for the content type attribute.
0127:             */
0128:            protected static int ATTR_CONTENT_TYPE = -1;
0129:            /**
0130:             * Attribute index - The index for the charset attribute.
0131:             */
0132:            protected static int ATTR_CHARSET = -1;
0133:            /**
0134:             * Attribute index - The index for the content length attribute.
0135:             */
0136:            protected static int ATTR_CONTENT_LENGTH = -1;
0137:            /**
0138:             * Attribute index - The icon (if any) associated to the resource.
0139:             */
0140:            protected static int ATTR_ICON = -1;
0141:            /**
0142:             * Attribute index - Max age: the maximum drift allowed from reality.
0143:             */
0144:            protected static int ATTR_MAXAGE = -1;
0145:            /**
0146:             * Attribute index - Send MD5 Digest: the md5 digest of the resource sent
0147:             */
0148:            protected static int ATTR_MD5 = -1;
0149:            /**
0150:             * Attribute index - delete allowed for the associated resource ?
0151:             */
0152:            protected static int ATTR_ALLOW_DEL = -1;
0153:
0154:            //
0155:            // Attribute relative to FileResource
0156:            //
0157:
0158:            /**
0159:             * Attribute index - Do we allow PUT method on this file.
0160:             */
0161:            protected static int ATTR_PUTABLE = -1;
0162:
0163:            //
0164:            // Attribute relative to DirectoryResource
0165:            //
0166:
0167:            /**
0168:             * Attribute index - The index for our relocate attribute.
0169:             */
0170:            protected static int ATTR_RELOCATE = -1;
0171:            /**
0172:             * Attribute index - our index resource name.
0173:             */
0174:            protected static int ATTR_INDEX = -1;
0175:            /**
0176:             * Attribute index - our indexes resource name.
0177:             */
0178:            protected static int ATTR_INDEXES = -1;
0179:            /**
0180:             * Attribute index - The icon directory to use in dir listing.
0181:             */
0182:            protected static int ATTR_ICONDIR = -1;
0183:            /**
0184:             * Attribute index - Allow the GNN browse method.
0185:             */
0186:            protected static int ATTR_BROWSABLE = -1;
0187:            /**
0188:             * Attribute index - Style sheet for directory listing
0189:             */
0190:            protected static int ATTR_STYLE_LINK = -1;
0191:
0192:            static {
0193:                Attribute a = null;
0194:                Class cls = null;
0195:
0196:                // Get a pointer to our class:
0197:                try {
0198:                    cls = Class.forName("org.w3c.jigsaw.frames.HTTPFrame");
0199:                } catch (Exception ex) {
0200:                    ex.printStackTrace();
0201:                    System.exit(1);
0202:                }
0203:                // The quality attribute:
0204:                a = new DoubleAttribute("quality", new Double(1.0),
0205:                        Attribute.EDITABLE);
0206:                ATTR_QUALITY = AttributeRegistry.registerAttribute(cls, a);
0207:                // The title attribute:
0208:                a = new StringAttribute("title", null, Attribute.EDITABLE);
0209:                ATTR_TITLE = AttributeRegistry.registerAttribute(cls, a);
0210:                // The content language attribute:
0211:                a = new LanguageAttribute("content-language", null,
0212:                        Attribute.EDITABLE);
0213:                ATTR_CONTENT_LANGUAGE = AttributeRegistry.registerAttribute(
0214:                        cls, a);
0215:                // The content encoding attribute:
0216:                a = new EncodingAttribute("content-encoding", null,
0217:                        Attribute.EDITABLE);
0218:                ATTR_CONTENT_ENCODING = AttributeRegistry.registerAttribute(
0219:                        cls, a);
0220:                // The content type attribute:
0221:                a = new MimeTypeAttribute("content-type", null,
0222:                        Attribute.EDITABLE);
0223:                ATTR_CONTENT_TYPE = AttributeRegistry.registerAttribute(cls, a);
0224:                // The Charset attribute:
0225:                a = new StringAttribute("charset", null, Attribute.EDITABLE);
0226:                ATTR_CHARSET = AttributeRegistry.registerAttribute(cls, a);
0227:                // The content length attribute:
0228:                a = new IntegerAttribute("content-length", null,
0229:                        Attribute.COMPUTED);
0230:                ATTR_CONTENT_LENGTH = AttributeRegistry.registerAttribute(cls,
0231:                        a);
0232:                // The icon attribute:
0233:                a = new StringAttribute("icon", null, Attribute.EDITABLE);
0234:                ATTR_ICON = AttributeRegistry.registerAttribute(cls, a);
0235:                // The max age attribute (in ms)
0236:                a = new LongAttribute("maxage", null, Attribute.EDITABLE);
0237:                ATTR_MAXAGE = AttributeRegistry.registerAttribute(cls, a);
0238:                // Should we send MD5 digest?
0239:                a = new BooleanAttribute("send-md5", Boolean.FALSE,
0240:                        Attribute.EDITABLE);
0241:                ATTR_MD5 = AttributeRegistry.registerAttribute(cls, a);
0242:                // delete allowed for the associated resource ?
0243:                a = new BooleanAttribute("allow-delete", Boolean.FALSE,
0244:                        Attribute.EDITABLE);
0245:                ATTR_ALLOW_DEL = AttributeRegistry.registerAttribute(cls, a);
0246:
0247:                //
0248:                // Attribute relative to a FileResource
0249:                //
0250:
0251:                // The putable flag:
0252:                a = new BooleanAttribute("putable", Boolean.FALSE,
0253:                        Attribute.EDITABLE);
0254:                ATTR_PUTABLE = AttributeRegistry.registerAttribute(cls, a);
0255:
0256:                //
0257:                // Attribute relative to a DirectoryResource
0258:                //
0259:
0260:                //Should we relocate invalid request to this directory ?
0261:                a = new BooleanAttribute("relocate", Boolean.TRUE,
0262:                        Attribute.EDITABLE);
0263:                ATTR_RELOCATE = AttributeRegistry.registerAttribute(cls, a);
0264:                // Our index resource name (optional).
0265:                a = new StringAttribute("index", null, Attribute.EDITABLE);
0266:                ATTR_INDEX = AttributeRegistry.registerAttribute(cls, a);
0267:                // Our indexes resource name 
0268:                a = new StringArrayAttribute("indexes", null,
0269:                        Attribute.EDITABLE);
0270:                ATTR_INDEXES = AttributeRegistry.registerAttribute(cls, a);
0271:                // Our icon directory.
0272:                a = new StringAttribute("icondir", null, Attribute.EDITABLE);
0273:                ATTR_ICONDIR = AttributeRegistry.registerAttribute(cls, a);
0274:                // The browsable flag:
0275:                a = new BooleanAttribute("browsable", Boolean.FALSE,
0276:                        Attribute.EDITABLE);
0277:                ATTR_BROWSABLE = AttributeRegistry.registerAttribute(cls, a);
0278:                // The style sheet attribute:
0279:                a = new StringAttribute("style-sheet-link", null,
0280:                        Attribute.EDITABLE);
0281:                ATTR_STYLE_LINK = AttributeRegistry.registerAttribute(cls, a);
0282:            }
0283:
0284:            /**
0285:             * The associated DirectoryResource (if any)
0286:             */
0287:            protected DirectoryResource dresource = null;
0288:
0289:            /**
0290:             * The associated FileResource (if any)
0291:             */
0292:            protected FileResource fresource = null;
0293:
0294:            /**
0295:             * Register this frame to the given resource.
0296:             * @param resource The resource associated with this frame.
0297:             */
0298:            public void registerResource(FramedResource resource) {
0299:                super .registerResource(resource);
0300:                if (resource instanceof  FileResource)
0301:                    fresource = (FileResource) resource;
0302:                else if (resource instanceof  DirectoryResource)
0303:                    dresource = (DirectoryResource) resource;
0304:            }
0305:
0306:            /**
0307:             * Get the associated FileResource (if any)
0308:             * @return a FileResource instance or <strong>null</strong>
0309:             * if no FileResource is associated with this frame.
0310:             */
0311:            public FileResource getFileResource() {
0312:                return fresource;
0313:            }
0314:
0315:            /**
0316:             * Get the associated DirectoryResource (if any)
0317:             * @return a DirectoryResource instance or <strong>null</strong>
0318:             * if no DirectoryResource is associated with this frame.
0319:             */
0320:            public DirectoryResource getDirectoryResource() {
0321:                return dresource;
0322:            }
0323:
0324:            /**
0325:             * use this one instead of registerResource if the resource type 
0326:             * doesn't matter or if this is not a file or a directory resource.
0327:             * In subclasses you should have to do that:
0328:             * <pre>
0329:             *  public void registerResource(FramedResource resource) {
0330:             *   super.registerOtherResource(resource);
0331:             *  }
0332:             * </pre>
0333:             * @param the resource to register.
0334:             */
0335:            public void registerOtherResource(FramedResource resource) {
0336:                super .registerResource(resource);
0337:                dresource = null;
0338:                fresource = null;
0339:            }
0340:
0341:            // The HTTPResource keeps a cache of ready to use Http values. This 
0342:            // allows to save converting to/from wire rep these objects. Not 
0343:            // much CPU time, but also memory is spared.
0344:            HttpMimeType contenttype = null;
0345:            HttpInteger contentlength = null;
0346:            HttpDate lastmodified = null;
0347:            HttpTokenList contentencoding = null;
0348:            HttpTokenList contentlanguage = null;
0349:
0350:            // The Http entity tag for this resource (for FileResource only)
0351:            HttpEntityTag etag = null;
0352:            // the MD5 digest for this resource (for FileResource only)
0353:            HttpString md5Digest = null;
0354:
0355:            /**
0356:             * Get this resource's help url.
0357:             * @return An URL, encoded as a String, or <strong>null</strong> if not
0358:             * available.
0359:             */
0360:
0361:            public String getHelpURL() {
0362:                httpd server = (httpd) getServer();
0363:                if (server == null)
0364:                    return null;
0365:                String docurl = server.getDocumentationURL();
0366:                if (docurl == null)
0367:                    return null;
0368:                return docurl + "/" + getClass().getName() + ".html";
0369:            }
0370:
0371:            /**
0372:             * Get the help URL for that resource's attribute.
0373:             * @param topic The topic (can be an attribute name, or a property, etc).
0374:             * @return A String encoded URL, or <strong>null</strong>.
0375:             */
0376:
0377:            public String getHelpURL(String topic) {
0378:                httpd server = (httpd) getServer();
0379:                if (server == null)
0380:                    return null;
0381:                String docurl = server.getDocumentationURL();
0382:                if (docurl == null)
0383:                    return null;
0384:                Class defines = AttributeRegistry.getAttributeClass(getClass(),
0385:                        topic);
0386:                if (defines != null)
0387:                    return docurl + "/" + defines.getName() + ".html";
0388:                return null;
0389:            }
0390:
0391:            /** 
0392:             * give the md5 digest from cache or calculate it
0393:             * @return the HttpString version of the digest
0394:             */
0395:
0396:            private HttpString getMd5Digest() {
0397:                if (md5Digest != null)
0398:                    return md5Digest;
0399:                // not found, compute it if necessary!
0400:                Resource r = getResource();
0401:                if (r instanceof  FileResource) {
0402:                    try {
0403:                        Md5 md5 = new Md5(new FileInputStream(
0404:                                ((FileResource) r).getFile()));
0405:                        String s = null;
0406:                        try {
0407:                            byte b[] = md5.getDigest();
0408:                            Base64Encoder b64;
0409:                            ByteArrayOutputStream bos = new ByteArrayOutputStream();
0410:                            b64 = new Base64Encoder(
0411:                                    new ByteArrayInputStream(b), bos);
0412:                            b64.process();
0413:                            s = bos.toString();
0414:                            md5Digest = HttpFactory.makeString(s);
0415:                        } catch (Exception mdex) {
0416:                            // error, set it to null
0417:                            md5Digest = null;
0418:                        }
0419:                        return md5Digest;
0420:                    } catch (FileNotFoundException ex) {
0421:                        // silent fail
0422:                        md5Digest = null;
0423:                    }
0424:                }
0425:                return null;
0426:            }
0427:
0428:            /**
0429:             * Listen its resource.
0430:             */
0431:            public void attributeChanged(AttributeChangedEvent evt) {
0432:                super .attributeChanged(evt);
0433:                String name = evt.getAttribute().getName();
0434:                if (name.equals("file-stamp")) {
0435:                    etag = null;
0436:                    lastmodified = null;
0437:                    md5Digest = null;
0438:                } else if (name.equals("file-length")) {
0439:                    setValue(ATTR_CONTENT_LENGTH, evt.getNewValue());
0440:                } else if (name.equals("last-modified")) {
0441:                    setValue(ATTR_LAST_MODIFIED, evt.getNewValue());
0442:                } else {
0443:                    lastmodified = null;
0444:                }
0445:            }
0446:
0447:            /**
0448:             * Catch setValue, to maintain cached header values correctness.
0449:             * @param idx The index of the attribute to be set.
0450:             * @param value The new value for the attribute.
0451:             */
0452:
0453:            public synchronized void setValue(int idx, Object value) {
0454:                super .setValue(idx, value);
0455:                if (idx == ATTR_CONTENT_TYPE) {
0456:                    contenttype = null;
0457:                } else if (idx == ATTR_CHARSET) {
0458:                    contenttype = null;
0459:                } else if (idx == ATTR_CONTENT_LENGTH) {
0460:                    contentlength = null;
0461:                } else if (idx == ATTR_CONTENT_ENCODING) {
0462:                    contentencoding = null;
0463:                } else if (idx == ATTR_CONTENT_LANGUAGE) {
0464:                    contentlanguage = null;
0465:                } else if (idx == ATTR_PUTABLE) {
0466:                    allowed = null;
0467:                } else if (idx == ATTR_ALLOW_DEL) {
0468:                    allowed = null;
0469:                } else if (idx == ATTR_MD5) {
0470:                    md5Digest = null; // reset the digest state
0471:                }
0472:                // Any attribute setting modifies the last modified time:
0473:                lastmodified = null;
0474:            }
0475:
0476:            /**
0477:             * Get the full URL for that resource.
0478:             * @return An URL instance.
0479:             */
0480:            public URL getURL(Request request) {
0481:                try {
0482:                    return new URL(request.getURL(), resource
0483:                            .unsafeGetURLPath());
0484:                } catch (MalformedURLException ex) {
0485:                    throw new RuntimeException("unable to build "
0486:                            + getURLPath() + " full URL, from server "
0487:                            + getServer().getURL());
0488:                }
0489:            }
0490:
0491:            /**
0492:             * Get this resource quality.
0493:             * @return The resource quality, or some negative value if not defined.
0494:             */
0495:
0496:            public double getQuality() {
0497:                return getDouble(ATTR_QUALITY, -1.0);
0498:            }
0499:
0500:            /**
0501:             * Get this resource quality.
0502:             * @return The resource quality, or some negative value if not defined.
0503:             */
0504:
0505:            public double unsafeGetQuality() {
0506:                return unsafeGetDouble(ATTR_QUALITY, -1.0);
0507:            }
0508:
0509:            /**
0510:             * Get this resource title.
0511:             * @return This resource's title, or <strong>null</strong> if not 
0512:             *    defined.
0513:             */
0514:
0515:            public String getTitle() {
0516:                return getString(ATTR_TITLE, null);
0517:            }
0518:
0519:            /**
0520:             * Get this resource content language.
0521:             * Language are stored as a comma separated String of tokens.
0522:             * @return A comma separated string of language tokens, or
0523:             *    <strong>null</strong> if undefined.
0524:             */
0525:
0526:            public String getContentLanguage() {
0527:                return (String) getValue(ATTR_CONTENT_LANGUAGE, null);
0528:            }
0529:
0530:            /**
0531:             * Get this resource content encoding.
0532:             * The content encoding of a resource is stored as a comma separated
0533:             * list of tokens (as decribed in the Content_encoding header of the
0534:             * HTTP specification, and in the order they should appear in the header).
0535:             * @return A string of comma separated encoding tokens, or
0536:             *    <strong>null</strong> if not defined.
0537:             */
0538:
0539:            public String getContentEncoding() {
0540:                String def = (String) attributes[ATTR_CONTENT_ENCODING]
0541:                        .getDefault();
0542:                String s = (String) getString(ATTR_CONTENT_ENCODING, def);
0543:                return (String) getString(ATTR_CONTENT_ENCODING, def);
0544:            }
0545:
0546:            /**
0547:             * Get this resource charset.
0548:             * @return A String, or <strong>null</strong> if not
0549:             *    defined.
0550:             */
0551:            public String getCharset() {
0552:                return (String) getValue(ATTR_CHARSET, null);
0553:            }
0554:
0555:            /**
0556:             * Get this resource content type.
0557:             * @return An instance of MIMEType, or <strong>null</strong> if not
0558:             *    defined.
0559:             */
0560:            public MimeType getContentType() {
0561:                return (MimeType) getValue(ATTR_CONTENT_TYPE, null);
0562:            }
0563:
0564:            /**
0565:             * Compute the ETag string
0566:             * @return a string or null if not applicable
0567:             */
0568:            public String computeETag() {
0569:                String etag_s = null;
0570:                if (fresource != null) {
0571:                    long lstamp = fresource.getFileStamp();
0572:                    if (lstamp >= 0L) {
0573:                        StringBuffer sb = new StringBuffer(32);
0574:                        sb.append(Integer.toString(getOid(), 32));
0575:                        sb.append(':');
0576:                        sb.append(Long.toString(lstamp, 32));
0577:                        etag_s = sb.toString();
0578:                    }
0579:                }
0580:                return etag_s;
0581:            }
0582:
0583:            /**
0584:             * Get this resource Etag
0585:             * @return an instance of HttpEntityTag, or <strong>null</strong> if not
0586:             *    defined.
0587:             */
0588:
0589:            public HttpEntityTag getETag() {
0590:                if (etag == null) {
0591:                    String etag_s = computeETag();
0592:                    // no luck, exit
0593:                    if (etag_s == null) {
0594:                        return null;
0595:                    }
0596:                    etag = HttpFactory.makeETag(false, etag_s);
0597:                }
0598:                return etag;
0599:            }
0600:
0601:            /**
0602:             * Get this resource content length.
0603:             * @return The resource content length, or <strong>-1</strong> if not
0604:             *    defined.
0605:             */
0606:
0607:            public int getContentLength() {
0608:                return getInt(ATTR_CONTENT_LENGTH, -1);
0609:            }
0610:
0611:            /**
0612:             * Get this resource's icon.
0613:             */
0614:
0615:            public String getIcon() {
0616:                return getString(ATTR_ICON, null);
0617:            }
0618:
0619:            /**
0620:             * Get this resource's max age.
0621:             * The max age of a resource indicates how much drift is allowed between
0622:             * the physicall version of the resource, and any in-memory cached version
0623:             * of it.
0624:             * <p>The max age attribute is a long number giving the number of 
0625:             * milliseconds of allowed drift.
0626:             */
0627:
0628:            public long getMaxAge() {
0629:                return getLong(ATTR_MAXAGE, (long) -1);
0630:            }
0631:
0632:            //
0633:            // Relative to FileResource ...
0634:            //
0635:
0636:            /**
0637:             * Does this resource support byte ranges.
0638:             */
0639:            protected boolean acceptRanges = false;
0640:
0641:            /**
0642:             * Get the PUT'able flag (are we allow to PUT to the resource ?)
0643:             */
0644:            public boolean getPutableFlag() {
0645:                return getBoolean(ATTR_PUTABLE, false);
0646:            }
0647:
0648:            /**
0649:             * Do we send the MD5 digest?
0650:             */
0651:            public boolean getMD5Flag() {
0652:                return getBoolean(ATTR_MD5, false);
0653:            }
0654:
0655:            /**
0656:             * delete allowed for the associated resource ?
0657:             */
0658:            public boolean getAllowDeleteFlag() {
0659:                return getBoolean(ATTR_ALLOW_DEL, false);
0660:            }
0661:
0662:            /**
0663:             * get the Allowed methods for this resource
0664:             * @return an HttpTokenList
0665:             */
0666:            protected HttpTokenList getAllow() {
0667:                if (allowed != null) {
0668:                    return allowed;
0669:                }
0670:                int size = 4; // the default HEAD GET OPTIONS TRACE
0671:                if (getPutableFlag()) {
0672:                    size++;
0673:                }
0674:                if (getAllowDeleteFlag()) {
0675:                    size++;
0676:                }
0677:                String allow_str[] = new String[size];
0678:                int i = 0;
0679:                if (getAllowDeleteFlag()) {
0680:                    allow_str[i++] = "DELETE";
0681:                }
0682:                allow_str[i++] = "HEAD";
0683:                allow_str[i++] = "GET";
0684:                allow_str[i++] = "OPTIONS";
0685:                if (getPutableFlag()) {
0686:                    allow_str[i++] = "PUT";
0687:                }
0688:                allow_str[i] = "TRACE";
0689:                allowed = HttpFactory.makeStringList(allow_str);
0690:                return allowed;
0691:            }
0692:
0693:            /**
0694:             * handles a Range Request
0695:             * @param request, the request
0696:             * @param r, the HttpRange
0697:             * @return a Reply if range is valid, or null if there is a change in the
0698:             * resource, or if the HttpRange is not valid ( 4-2, for example).
0699:             * @exception ProtocolException If processsing the request failed.
0700:             */
0701:
0702:            public Reply handleRangeRequest(Request request, HttpRange r)
0703:                    throws ProtocolException {
0704:                // Should we check against a IfRange header ?
0705:                HttpEntityTag t = request.getIfRange();
0706:
0707:                if (t != null) {
0708:                    if (t.isWeak() || !t.getTag().equals(etag.getTag()))
0709:                        return null;
0710:                }
0711:                // Check the range:
0712:                int cl = getContentLength();
0713:                int fb = r.getFirstPosition();
0714:                int lb = r.getLastPosition();
0715:                int sz;
0716:
0717:                if (fb > cl - 1) { // first byte already out of range
0718:                    HttpContentRange cr = HttpFactory.makeContentRange("bytes",
0719:                            0, cl - 1, cl);
0720:                    Reply rr;
0721:                    rr = createDefaultReply(request,
0722:                            HTTP.REQUESTED_RANGE_NOT_SATISFIABLE);
0723:                    rr.setContentLength(-1);
0724:                    rr.setHeaderValue(rr.H_CONTENT_RANGE, cr);
0725:                    if (getMD5Flag())
0726:                        rr.setContentMD5(null);
0727:                    return rr;
0728:                }
0729:
0730:                if ((fb < 0) && (lb >= 0)) { // ex: bytes=-20 final 20 bytes
0731:                    if (lb >= cl) // cut the end
0732:                        lb = cl;
0733:                    sz = lb;
0734:                    fb = cl - lb;
0735:                    lb = cl - 1;
0736:                } else if (lb < 0) { // ex: bytes=10- the last size - 10
0737:                    lb = cl - 1;
0738:                    sz = lb - fb + 1;
0739:                } else { // ex: bytes=10-20
0740:                    if (lb >= cl) // cut the end
0741:                        lb = cl - 1;
0742:                    sz = lb - fb + 1;
0743:                }
0744:                if ((fb < 0) || (lb < 0) || (fb <= lb)) {
0745:                    HttpContentRange cr = null;
0746:                    fb = (fb < 0) ? 0 : fb;
0747:                    lb = ((lb > cl) || (lb < 0)) ? cl : lb;
0748:                    cr = HttpFactory.makeContentRange("bytes", fb, lb, cl);
0749:                    // Emit reply:
0750:                    Reply rr = createDefaultReply(request, HTTP.PARTIAL_CONTENT);
0751:                    // FIXME check for MD5 of only the subpart
0752:                    try { // create the MD5 for the subpart
0753:                        if (getMD5Flag()) {
0754:                            String s = null;
0755:                            try {
0756:                                ByteRangeOutputStream br;
0757:                                br = new ByteRangeOutputStream(fresource
0758:                                        .getFile(), fb, lb + 1);
0759:                                Md5 md5 = new Md5(br);
0760:                                byte b[] = md5.getDigest();
0761:                                Base64Encoder b64;
0762:                                ByteArrayOutputStream bs = new ByteArrayOutputStream();
0763:                                b64 = new Base64Encoder(
0764:                                        new ByteArrayInputStream(b), bs);
0765:                                b64.process();
0766:                                s = bs.toString();
0767:                            } catch (Exception md_ex) {
0768:                                // default to null, no action here then
0769:                            }
0770:                            if (s == null)
0771:                                rr.setContentMD5(null);
0772:                            else
0773:                                rr.setContentMD5(s);
0774:                        }
0775:                        rr.setContentLength(sz);
0776:                        rr.setHeaderValue(rr.H_CONTENT_RANGE, cr);
0777:                        rr.setStream(new ByteRangeOutputStream(fresource
0778:                                .getFile(), fb, lb + 1));
0779:                        return rr;
0780:                    } catch (IOException ex) {
0781:                    }
0782:                }
0783:                return null;
0784:            }
0785:
0786:            //
0787:            // Relative to DirectoryResource ...
0788:            //
0789:
0790:            /**
0791:             * Get this class browsable flag.
0792:             */
0793:            public boolean getBrowsableFlag() {
0794:                return getBoolean(ATTR_BROWSABLE, false);
0795:            }
0796:
0797:            /**
0798:             * Get this frame style sheet link
0799:             */
0800:            public String getStyleSheetURL() {
0801:                return getString(ATTR_STYLE_LINK, null);
0802:            }
0803:
0804:            /**
0805:             * Our current (cached) directory listing.
0806:             */
0807:            protected HtmlGenerator listing = null;
0808:            /**
0809:             * The time at which we generated the directory index.
0810:             */
0811:            protected long listing_stamp = -1;
0812:
0813:            private String getUnextendedName(String name) {
0814:                int strlen = name.length();
0815:                for (int i = 0; i < strlen; i++) {
0816:                    // FIXME: Should use the system props to get the right sep
0817:                    if (name.charAt(i) == '.') {
0818:                        if (i == 0)
0819:                            return null;
0820:                        return name.substring(0, i);
0821:                    }
0822:                }
0823:                return null;
0824:            }
0825:
0826:            /**
0827:             * Get the optional icon directory.
0828:             */
0829:            public String getIconDirectory() {
0830:                return getString(ATTR_ICONDIR, "/icons");
0831:            }
0832:
0833:            /**
0834:             * Should we relocate invalid requests to this directory.
0835:             * @return A boolean <strong>true</strong> if we should relocate.
0836:             */
0837:            public boolean getRelocateFlag() {
0838:                return getBoolean(ATTR_RELOCATE, true);
0839:            }
0840:
0841:            /**
0842:             * Get the optional main index name for this directory listing.
0843:             * @return The name of the resource responsible to list that container.
0844:             */
0845:            public String getIndex() {
0846:                return (String) getValue(ATTR_INDEX, null);
0847:            }
0848:
0849:            /**
0850:             * Get the optional index name array for this directory listing.
0851:             * @return The index name array (including the main index)
0852:             * @see #getIndex
0853:             */
0854:            public String[] getIndexes() {
0855:                String mainIndex = getIndex();
0856:                if (mainIndex != null) {
0857:                    String indexes[] = (String[]) getValue(ATTR_INDEXES, null);
0858:                    if (indexes != null) {
0859:                        int len = indexes.length + 1;
0860:                        String mergeIndex[] = new String[len];
0861:                        mergeIndex[0] = mainIndex;
0862:                        System.arraycopy(indexes, 0, mergeIndex, 1, len - 1);
0863:                        return mergeIndex;
0864:                    } else {
0865:                        indexes = new String[1];
0866:                        indexes[0] = mainIndex;
0867:                        return indexes;
0868:                    }
0869:                } else {
0870:                    return (String[]) getValue(ATTR_INDEXES, null);
0871:                }
0872:            }
0873:
0874:            /**
0875:             * Add our own Style Sheet to the HtmlGenerator.
0876:             * @param g The HtmlGenerator.
0877:             */
0878:            public void addStyleSheet(HtmlGenerator g) {
0879:                // Add style link
0880:                String css_url = getStyleSheetURL();
0881:                if (css_url != null) {
0882:                    g.addLink(new HtmlLink("STYLESHEET", css_url));
0883:                }
0884:            }
0885:
0886:            /**
0887:             * Get ContainerResource listing
0888:             * @param refresh should we refresh the listing?
0889:             * @return a boolean (true if refreshed)
0890:             */
0891:            public boolean computeContainerListing(boolean refresh) {
0892:                ContainerResource cresource = (ContainerResource) resource;
0893:                synchronized (cresource) {
0894:                    if ((refresh) || (listing == null)
0895:                            || (cresource.getLastModified() > listing_stamp)
0896:                            || (getLastModified() > listing_stamp)) {
0897:
0898:                        Class http_class = null;
0899:                        try {
0900:                            http_class = Class
0901:                                    .forName("org.w3c.jigsaw.frames.HTTPFrame");
0902:                        } catch (ClassNotFoundException ex) {
0903:                            http_class = null;
0904:                        }
0905:
0906:                        Enumeration e = cresource
0907:                                .enumerateResourceIdentifiers();
0908:                        Vector resources = Sorter.sortStringEnumeration(e);
0909:                        HtmlGenerator g = new HtmlGenerator("Index of "
0910:                                + cresource.getIdentifier());
0911:                        // Add style link
0912:                        addStyleSheet(g);
0913:                        g.append("<h1>" + cresource.getIdentifier() + "</h1>");
0914:                        // Link to the parent, when possible:
0915:                        if (cresource.getParent() != null) {
0916:                            g.append("<p><a href=\"..\">Parent</a><br>");
0917:                        }
0918:                        // List the children:
0919:                        for (int i = 0; i < resources.size(); i++) {
0920:                            String name = (String) resources.elementAt(i);
0921:                            ResourceReference rr = null;
0922:                            long size = -1;
0923:                            rr = cresource.lookup(name);
0924:                            FramedResource resource = null;
0925:                            if (rr != null) {
0926:                                try {
0927:                                    resource = (FramedResource) rr.unsafeLock();
0928:                                    // remove manually deleted FileResources
0929:                                    if (resource instanceof  FileResource) {
0930:                                        FileResource fr = (FileResource) resource;
0931:                                        if (!fr.getFile().exists()) {
0932:                                            try {
0933:                                                fr.delete();
0934:                                            } catch (MultipleLockException ex) {
0935:                                            }
0936:                                            ;
0937:                                            continue;
0938:                                        } else {
0939:                                            size = fr.getFile().length();
0940:                                        }
0941:                                    }
0942:                                    HTTPFrame itsframe = null;
0943:                                    if (http_class != null)
0944:                                        itsframe = (HTTPFrame) resource
0945:                                                .getFrame(http_class);
0946:                                    if (itsframe != null) {
0947:                                        // Icon first, if available
0948:                                        String icon = itsframe.getIcon();
0949:                                        if (icon != null) {
0950:                                            g.append("<img src=\""
0951:                                                    + getIconDirectory() + "/"
0952:                                                    + icon + "\" alt=\"" + icon
0953:                                                    + "\">");
0954:                                        }
0955:                                        // Resource's name with link:
0956:                                        if (resource instanceof  ContainerInterface) {
0957:                                            g.append("<a href=\"", URLEncoder
0958:                                                    .encode(name), "/\">"
0959:                                                    + name + "</a>");
0960:                                        } else {
0961:                                            g.append("<a href=\"", URLEncoder
0962:                                                    .encode(name), "\">" + name
0963:                                                    + "</a>");
0964:                                        }
0965:                                        // resource's title, if any:
0966:                                        String title = itsframe.getTitle();
0967:                                        if (title != null) {
0968:                                            g.append(" " + title);
0969:                                        }
0970:                                        //size (if any)
0971:                                        if (size != -1) {
0972:                                            String s = null;
0973:                                            if (size > 1023) {
0974:                                                s = " [" + (size / 1024)
0975:                                                        + " KB]";
0976:                                            } else {
0977:                                                s = " [" + size + " bytes]";
0978:                                            }
0979:                                            g.append(s);
0980:                                        }
0981:                                        g.append("<br>\n");
0982:                                    } else {
0983:                                        // Resource's name with link:
0984:                                        g
0985:                                                .append(name
0986:                                                        + " (<i>Not available via HTTP.</i>)");
0987:                                        g.append("<br>\n");
0988:                                    }
0989:                                } catch (InvalidResourceException ex) {
0990:                                    g
0991:                                            .append(name
0992:                                                    + " cannot be loaded (server misconfigured)");
0993:                                    g.append("<br>\n");
0994:                                    continue;
0995:                                } finally {
0996:                                    rr.unlock();
0997:                                }
0998:                            }
0999:                        }
1000:                        g.close();
1001:                        listing_stamp = getLastModified();
1002:                        listing = g;
1003:                        return true;
1004:                    }
1005:                }
1006:                return false;
1007:            }
1008:
1009:            /**
1010:             * Reply with an HTML doc listing the resources of this container.
1011:             * This function takes special care not to regenerate a listing
1012:             * when one is available. It also caches the date of the
1013:             * listing, so that it can win big with NOT_MODIFIED.
1014:             * <p>Using a modem, I know that each place I can reply with an 
1015:             * NOT_MODIFIED, <strong>is</strong> a big win.
1016:             * @param request The request to handle.
1017:             * @exception ProtocolException If processsing the request failed.
1018:             * @exception ResourceException If the resource got a fatal error.
1019:             */
1020:
1021:            public Reply getDirectoryListing(Request request)
1022:                    throws ProtocolException, ResourceException {
1023:                if (!(resource instanceof  ContainerResource)) {
1024:                    throw new ResourceException(
1025:                            "this frame is not attached to a "
1026:                                    + "ContainerResource. ("
1027:                                    + resource.getIdentifier() + ")");
1028:                }
1029:                // delete us if the directory was deleted
1030:                boolean refresh = false;
1031:                if (dresource != null) {
1032:                    synchronized (dresource) {
1033:                        if (!dresource.getDirectory().exists()) {
1034:                            //delete us and emit an error
1035:                            String msg = dresource.getIdentifier()
1036:                                    + ": deleted, removing the DirectoryResource";
1037:                            getServer().errlog(dresource, msg);
1038:                            try {
1039:                                dresource.delete();
1040:                            } catch (MultipleLockException ex) {
1041:                            }
1042:                            // Emit an error back:
1043:                            Reply error = request.makeReply(HTTP.NOT_FOUND);
1044:                            error.setContent("<h1>Document not found</h1>"
1045:                                    + "<p>The document " + request.getURL()
1046:                                    + " is indexed but not available."
1047:                                    + "<p>The server is misconfigured.");
1048:                            throw new HTTPException(error);
1049:                        }
1050:                        refresh = (dresource.getDirectory().lastModified() > listing_stamp);
1051:                    }
1052:                }
1053:                if ((!computeContainerListing(refresh))
1054:                        && (checkIfModifiedSince(request) == COND_FAILED)) {
1055:                    // Is it an IMS request ?
1056:                    Reply reply = createDefaultReply(request, HTTP.NOT_MODIFIED);
1057:                    return reply;
1058:                }
1059:                // New content or need update:
1060:                Reply reply = createDefaultReply(request, HTTP.OK);
1061:                reply.setLastModified(listing_stamp);
1062:                reply.setStream(listing);
1063:                // check MD5
1064:                return reply;
1065:            }
1066:
1067:            //
1068:            // Commom part.
1069:            //
1070:
1071:            /**
1072:             * Update the cached headers value.
1073:             * Each resource maintains a set of cached values for headers, this
1074:             * allows for a nice sped-up in headers marshalling, which - as the 
1075:             * complexity of the protocol increases - becomes a bottleneck.
1076:             */
1077:
1078:            protected void updateCachedHeaders() {
1079:                // Precompute a set of header values to keep by:
1080:                if (contenttype == null) {
1081:                    String charset = getCharset();
1082:                    if (charset == null)
1083:                        contenttype = HttpFactory
1084:                                .makeMimeType(getContentType());
1085:                    else {
1086:                        MimeType ctype = getContentType().getClone();
1087:                        ctype.addParameter("charset", charset);
1088:                        contenttype = HttpFactory.makeMimeType(ctype);
1089:                    }
1090:                }
1091:                if (contentlength == null) {
1092:                    int cl = -1;
1093:                    if (fresource != null)
1094:                        cl = fresource.getFileLength();
1095:                    if (cl >= 0) {
1096:                        if (cl != getInt(ATTR_CONTENT_LENGTH, -1)) {
1097:                            setValue(ATTR_CONTENT_LENGTH, new Integer(cl));
1098:                        }
1099:                        contentlength = HttpFactory.makeInteger(cl);
1100:                    }
1101:                }
1102:                if (lastmodified == null) {
1103:                    long lm = getLastModified();
1104:                    if (lm > 0)
1105:                        lastmodified = HttpFactory.makeDate(lm);
1106:                }
1107:                if (definesAttribute(ATTR_CONTENT_ENCODING)
1108:                        && (contentencoding == null))
1109:                    contentencoding = HttpFactory
1110:                            .makeStringList(getContentEncoding());
1111:                if (definesAttribute(ATTR_CONTENT_LANGUAGE)
1112:                        && (contentlanguage == null))
1113:                    contentlanguage = HttpFactory
1114:                            .makeStringList(getContentLanguage());
1115:
1116:                if (fresource != null) {
1117:                    // We only take care of etag here:
1118:                    if (etag == null) {
1119:                        getETag();
1120:                    }
1121:                    if (getMD5Flag() && (md5Digest == null)) {
1122:                        getMd5Digest();
1123:                    }
1124:                }
1125:            }
1126:
1127:            /**
1128:             * Create a reply to answer to request on this file.
1129:             * This method will create a suitable reply (matching the given request)
1130:             * and will set all its default header values to the appropriate 
1131:             * values.
1132:             * @param request The request to make a reply for.
1133:             * @return An instance of Reply, suited to answer this request.
1134:             */
1135:
1136:            public Reply createDefaultReply(Request request, int status) {
1137:                Reply reply = request.makeReply(status);
1138:                updateCachedHeaders();
1139:                if (status != HTTP.NOT_MODIFIED) {
1140:                    if (contentlength != null)
1141:                        reply.setHeaderValue(Reply.H_CONTENT_LENGTH,
1142:                                contentlength);
1143:                    if (contenttype != null)
1144:                        reply.setHeaderValue(Reply.H_CONTENT_TYPE, contenttype);
1145:                    if (lastmodified != null)
1146:                        reply.setHeaderValue(Reply.H_LAST_MODIFIED,
1147:                                lastmodified);
1148:                    if (contentencoding != null) {
1149:                        reply.setHeaderValue(Reply.H_CONTENT_ENCODING,
1150:                                contentencoding);
1151:                    }
1152:                    if (contentlanguage != null)
1153:                        reply.setHeaderValue(Reply.H_CONTENT_LANGUAGE,
1154:                                contentlanguage);
1155:
1156:                }
1157:                long maxage = getMaxAge();
1158:                if (maxage >= 0) {
1159:                    if (reply.getMajorVersion() >= 1) {
1160:                        if (reply.getMinorVersion() >= 1) {
1161:                            reply.setMaxAge((int) (maxage / 1000));
1162:                        }
1163:                        // If max-age is zero, say what you mean:
1164:                        long expires = (System.currentTimeMillis() + ((maxage == 0) ? -1000
1165:                                : maxage));
1166:                        reply.setExpires(expires);
1167:                    }
1168:                }
1169:                // Set the date of the reply (round it to secs):
1170:                reply.setDate((System.currentTimeMillis() / 1000L) * 1000L);
1171:
1172:                if (fresource != null) {
1173:                    // Set the entity tag:
1174:                    if (getETag() != null) {
1175:                        reply.setETag(etag);
1176:                    }
1177:                    if (status != HTTP.NOT_MODIFIED) {
1178:                        if (acceptRanges) {
1179:                            reply.setHeaderValue(reply.H_ACCEPT_RANGES,
1180:                                    _accept_ranges);
1181:                        }
1182:                        if (getMD5Flag()) {
1183:                            reply.setHeaderValue(reply.H_CONTENT_MD5,
1184:                                    getMd5Digest());
1185:                        }
1186:                    }
1187:                }
1188:                return reply;
1189:            }
1190:
1191:            /**
1192:             * Check the <code>If-Match</code> condition of that request.
1193:             * @param request The request to check.
1194:             * @return An integer, either <code>COND_FAILED</cond> if condition
1195:             * was checked, but failed, <code>COND_OK</code> if condition was checked
1196:             * and succeeded, or <strong>0</strong> if the condition was not checked
1197:             * at all (eg because the resource or the request didn't support it).
1198:             */
1199:
1200:            public int checkIfMatch(Request request) {
1201:                if (fresource != null) {
1202:                    HttpEntityTag tags[] = request.getIfMatch();
1203:                    if (tags != null) {
1204:                        // Good, real validators in use:
1205:                        if (etag != null) {
1206:                            // Note: if etag is null this means that the resource has 
1207:                            // changed and has not been even emited since then...
1208:                            for (int i = 0; i < tags.length; i++) {
1209:                                HttpEntityTag t = tags[i];
1210:                                if (t.getTag().equals(etag.getTag())) {
1211:                                    if (t.isWeak() || etag.isWeak()) {
1212:                                        return COND_WEAK;
1213:                                    } else {
1214:                                        return COND_OK;
1215:                                    }
1216:                                }
1217:                            }
1218:                        }
1219:                        return COND_FAILED;
1220:                    }
1221:                }
1222:                return 0;
1223:            }
1224:
1225:            /**
1226:             * Check the <code>If-None-Match</code> condition of that request.
1227:             * @param request The request to check.
1228:             * @return An integer, either <code>COND_FAILED</cond> if condition
1229:             * was checked, but failed, <code>COND_OK</code> if condition was checked
1230:             * and succeeded, or <strong>0</strong> if the condition was not checked
1231:             * at all (eg because the resource or the request didn't support it).
1232:             */
1233:
1234:            public int checkIfNoneMatch(Request request) {
1235:                if (fresource != null) {
1236:                    // Check for an If-None-Match conditional:
1237:                    HttpEntityTag tags[] = request.getIfNoneMatch();
1238:                    if (tags != null) {
1239:                        if (etag == null) {
1240:                            return COND_OK;
1241:                        }
1242:                        int status = COND_OK;
1243:                        for (int i = 0; i < tags.length; i++) {
1244:                            HttpEntityTag t = tags[i];
1245:                            if (t.getTag().equals(etag.getTag())) {
1246:                                if (t.isWeak() || etag.isWeak()) {
1247:                                    status = COND_WEAK;
1248:                                } else {
1249:                                    return COND_FAILED;
1250:                                }
1251:                            }
1252:                            if (t.getTag().equals("*")) {
1253:                                if (fresource != null) {
1254:                                    File f = fresource.getFile();
1255:                                    if (f.exists()) {
1256:                                        return COND_FAILED;
1257:                                    }
1258:                                } else {
1259:                                    return COND_FAILED;
1260:                                }
1261:                            }
1262:                        }
1263:                        return status;
1264:                    }
1265:                }
1266:                return 0;
1267:            }
1268:
1269:            /**
1270:             * Check the <code>If-Modified-Since</code> condition of that request.
1271:             * @param request The request to check.
1272:             * @return An integer, either <code>COND_FAILED</cond> if condition
1273:             * was checked, but failed, <code>COND_OK</code> if condition was checked
1274:             * and succeeded, or <strong>0</strong> if the condition was not checked
1275:             * at all (eg because the resource or the request didn't support it).
1276:             */
1277:
1278:            public int checkIfModifiedSince(Request request) {
1279:                // Check for an If-Modified-Since conditional:
1280:                long ims = request.getIfModifiedSince();
1281:                if (dresource != null) {
1282:                    if (ims >= 0) {
1283:                        if (listing_stamp > 0) {
1284:                            long s_listing_stamp = listing_stamp / 1000;
1285:                            long s_ims = ims / 1000;
1286:                            if (s_listing_stamp < s_ims) {
1287:                                return COND_FAILED;
1288:                            } else if (s_listing_stamp == s_ims) {
1289:                                return COND_WEAK;
1290:                            }
1291:                            return COND_OK;
1292:                        }
1293:                    }
1294:                } else if (fresource != null) {
1295:                    long cmt = getLastModified();
1296:                    if (ims >= 0) {
1297:                        if (cmt > 0) {
1298:                            long s_cmt = cmt / 1000;
1299:                            long s_ims = ims / 1000;
1300:                            if (s_cmt < s_ims) {
1301:                                return COND_FAILED;
1302:                            } else if (s_cmt == s_ims) {
1303:                                return COND_WEAK;
1304:                            }
1305:                            return COND_OK;
1306:                        }
1307:                    }
1308:                }
1309:                return 0;
1310:            }
1311:
1312:            /**
1313:             * Check the <code>If-Unmodified-Since</code> condition of that request.
1314:             * @param request The request to check.
1315:             * @return An integer, either <code>COND_FAILED</cond> if condition
1316:             * was checked, but failed, <code>COND_OK</code> if condition was checked
1317:             * and succeeded, or <strong>0</strong> if the condition was not checked
1318:             * at all (eg because the resource or the request didn't support it).
1319:             */
1320:
1321:            public int checkIfUnmodifiedSince(Request request) {
1322:                if (fresource != null) {
1323:                    // Check for an If-Unmodified-Since conditional:
1324:                    long iums = request.getIfUnmodifiedSince();
1325:                    long cmt = getLastModified();
1326:                    if (iums >= 0)
1327:                        return ((cmt > 0) && (cmt - 1000) >= iums) ? COND_FAILED
1328:                                : COND_OK;
1329:                }
1330:                return 0;
1331:            }
1332:
1333:            /**
1334:             * Check the <code>Expect</code> condition of that request
1335:             * @param request The request to check.
1336:             * @return A boolean <code>true</code> if the requirement is known
1337:             */
1338:
1339:            public boolean checkExpect(Request request) {
1340:                // crude for now as we only support 100-continue
1341:                // so FIXME for a more evolved version of this.
1342:                String exp = request.getExpect();
1343:                if (exp != null) {
1344:                    if (!exp.equalsIgnoreCase(HTTP.HTTP_100_CONTINUE)) {
1345:                        return false;
1346:                    }
1347:                }
1348:                return true;
1349:            }
1350:
1351:            /**
1352:             * check the validators namely LMT/Etags according to rfc2616 rules
1353:             * @return An integer, either <code>COND_FAILED</cond> if condition
1354:             * was checked, but failed, <code>COND_OK</code> if condition was checked
1355:             * and succeeded, or <strong>0</strong> if the condition was not checked
1356:             * at all (eg because the resource or the request didn't support it).
1357:             */
1358:            public int checkValidators(Request request) {
1359:                int v_inm = checkIfNoneMatch(request);
1360:                int v_ims = checkIfModifiedSince(request);
1361:
1362:                if ((v_inm == COND_OK) || (v_ims == COND_OK)) {
1363:                    return COND_OK;
1364:                }
1365:                if ((v_inm == COND_FAILED) || (v_ims == COND_FAILED)) {
1366:                    return COND_FAILED;
1367:                }
1368:                if ((v_inm == COND_WEAK) || (v_ims == COND_WEAK)) {
1369:                    return COND_FAILED;
1370:                }
1371:                return 0;
1372:            }
1373:
1374:            /**
1375:             * Lookup the target resource. Lookup filters and then resource.
1376:             * @param ls The current lookup state
1377:             * @param lr The result
1378:             * @return true if lookup is done.
1379:             * @exception ProtocolException If an error relative to the protocol occurs
1380:             * @see org.w3c.tools.resources.ResourceFrame#lookupFilters
1381:             * @see #lookupResource
1382:             */
1383:            public boolean lookup(LookupState ls, LookupResult lr)
1384:                    throws ProtocolException {
1385:                RequestInterface req = ls.getRequest();
1386:                if (!checkRequest(req))
1387:                    return false;
1388:                if (lookupFilters(ls, lr))
1389:                    return true;
1390:                return lookupResource(ls, lr);
1391:            }
1392:
1393:            /**
1394:             * Lookup the target resource (dispath to more specific lookup methods).
1395:             * @param ls The current lookup state
1396:             * @param lr The result
1397:             * @return true if lookup is done.
1398:             * @exception ProtocolException If an error relative to the protocol occurs
1399:             * @see #lookupDirectory
1400:             * @see #lookupFile
1401:             * @see #lookupOther
1402:             */
1403:            protected boolean lookupResource(LookupState ls, LookupResult lr)
1404:                    throws ProtocolException {
1405:                if (fresource != null) {
1406:                    return lookupFile(ls, lr);
1407:                } else if (dresource != null) {
1408:                    return lookupDirectory(ls, lr);
1409:                } else {
1410:                    return lookupOther(ls, lr);
1411:                }
1412:            }
1413:
1414:            /**
1415:             * Lookup the target resource when associated with a DirectoryResource.
1416:             * @param ls The current lookup state
1417:             * @param lr The result
1418:             * @return true if lookup is done.
1419:             * @exception ProtocolException If an error relative to the protocol
1420:             * occurs
1421:             */
1422:            protected boolean lookupDirectory(LookupState ls, LookupResult lr)
1423:                    throws ProtocolException {
1424:                // Give a chance to our super-class to run its own lookup scheme:
1425:                // do we have to create a resource (PUT) ?
1426:                if ((ls.hasMoreComponents()) && getPutableFlag()) {
1427:                    Request request = (Request) ls.getRequest();
1428:                    if ((request == null) || request.getMethod().equals("PUT")) {
1429:                        // We might well want to create a resource:
1430:                        String name = ls.peekNextComponent();
1431:                        ResourceReference rr = dresource.lookup(name);
1432:                        if ((rr == null) && (dresource.getExtensibleFlag())) {
1433:                            if (ls.countRemainingComponents() == 1)
1434:                                rr = dresource.createResource(name, request);
1435:                            else
1436:                                rr = dresource.createDirectoryResource(name);
1437:                            if (rr == null) {
1438:                                Reply error = request
1439:                                        .makeReply(HTTP.UNSUPPORTED_MEDIA_TYPE);
1440:                                error
1441:                                        .setContent("Failed to create resource "
1442:                                                + name
1443:                                                + " : "
1444:                                                + "Unable to create the appropriate file:"
1445:                                                + request.getURLPath()
1446:                                                + " this media type is not supported");
1447:                                throw new HTTPException(error);
1448:                            }
1449:                        } else if (rr == null) {
1450:                            Reply error = request.makeReply(HTTP.FORBIDDEN);
1451:                            error
1452:                                    .setContent("You are not allowed to create resource "
1453:                                            + name
1454:                                            + " : "
1455:                                            + dresource.getIdentifier()
1456:                                            + " is not extensible.");
1457:                            throw new HTTPException(error);
1458:                        }
1459:                    }
1460:                }
1461:                if (super .lookup(ls, lr)) {
1462:                    if (!ls.isDirectory() && !ls.isInternal()) {
1463:                        // The directory lookup URL doesn't end with a slash:
1464:                        Request request = (Request) ls.getRequest();
1465:                        if (request == null) {
1466:                            lr.setTarget(null);
1467:                            return true;
1468:                        }
1469:                        URL url = null;
1470:                        try {
1471:                            if ((request != null)
1472:                                    && request.hasState(Request.ORIG_URL_STATE)) {
1473:                                URL oldurl;
1474:                                oldurl = (URL) request
1475:                                        .getState(Request.ORIG_URL_STATE);
1476:                                url = new URL(oldurl, oldurl.getFile() + "/");
1477:                            } else {
1478:                                url = (ls.hasRequest() ? getURL(request)
1479:                                        : new URL(getServer().getURL(),
1480:                                                resource.getURLPath()));
1481:                            }
1482:                        } catch (MalformedURLException ex) {
1483:                            getServer().errlog(this ,
1484:                                    "unable to build full URL.");
1485:                            throw new HTTPException("Internal server error");
1486:                        }
1487:                        String msg = "Invalid requested URL: the directory resource "
1488:                                + " you are trying to reach is available only through "
1489:                                + " its full URL: <a href=\""
1490:                                + url
1491:                                + "\">"
1492:                                + url + "</a>.";
1493:                        if (getRelocateFlag()) {
1494:                            // Emit an error (with reloc if allowed)
1495:                            Reply reloc = request.makeReply(HTTP.FOUND);
1496:                            reloc.setContent(msg);
1497:                            reloc.setLocation(url);
1498:                            lr.setTarget(null);
1499:                            lr.setReply(reloc);
1500:                            return true;
1501:                        } else {
1502:                            Reply error = request.makeReply(HTTP.NOT_FOUND);
1503:                            error.setContent(msg);
1504:                            lr.setTarget(null);
1505:                            lr.setReply(error);
1506:                            return true;
1507:                        }
1508:                    } else if (!ls.isInternal()) {
1509:                        Request request = (Request) ls.getRequest();
1510:                        request.setState(STATE_CONTENT_LOCATION, "true");
1511:                        // return the index file.
1512:                        String indexes[] = getIndexes();
1513:                        if (indexes != null) {
1514:                            for (int i = 0; i < indexes.length; i++) {
1515:                                String index = indexes[i];
1516:                                if (index != null && index.length() > 0) {
1517:                                    DirectoryResource dir = (DirectoryResource) resource;
1518:                                    ResourceReference rr = dir.lookup(index);
1519:                                    if (rr != null) {
1520:                                        try {
1521:                                            FramedResource rindex = (FramedResource) rr
1522:                                                    .lock();
1523:                                            return rindex.lookup(ls, lr);
1524:                                        } catch (InvalidResourceException ex) {
1525:                                        } finally {
1526:                                            rr.unlock();
1527:                                        }
1528:                                    }
1529:                                }
1530:                            }
1531:                        }
1532:                    }
1533:                    return true;
1534:                }
1535:                return false;
1536:            }
1537:
1538:            /**
1539:             * Lookup the target resource when associated with a FileResource.
1540:             * @param ls The current lookup state
1541:             * @param lr The result
1542:             * @return true if lookup is done.
1543:             * @exception ProtocolException If an error relative to the protocol occurs
1544:             */
1545:            protected boolean lookupFile(LookupState ls, LookupResult lr)
1546:                    throws ProtocolException {
1547:                return super .lookup(ls, lr);
1548:            }
1549:
1550:            /**
1551:             * Lookup the target resource when associated with an unknown resource.
1552:             * @param ls The current lookup state
1553:             * @param lr The result
1554:             * @return true if lookup is done.
1555:             * @exception ProtocolException If an error relative to the protocol occurs
1556:             */
1557:            protected boolean lookupOther(LookupState ls, LookupResult lr)
1558:                    throws ProtocolException {
1559:                return super .lookup(ls, lr);
1560:            }
1561:
1562:            /**
1563:             * Check the request.
1564:             * @param request the incomming request.
1565:             * @return true if the request is an HTTP Request. 
1566:             */
1567:            public boolean checkRequest(RequestInterface request) {
1568:                return ((request == null) ? true
1569:                        : (request instanceof  org.w3c.jigsaw.http.Request));
1570:            }
1571:
1572:            /**
1573:             * Perform the request on all the frames of that resource. The
1574:             * Reply returned is the first non-null reply.
1575:             * @param request A RequestInterface instance.
1576:             * @return A ReplyInterface instance.
1577:             * @exception ProtocolException If an error relative to the protocol occurs
1578:             * @exception ResourceException If an error not relative to the 
1579:             * protocol occurs
1580:             */
1581:            protected ReplyInterface performFrames(RequestInterface request)
1582:                    throws ProtocolException, ResourceException {
1583:                return super .performFrames(request);
1584:            }
1585:
1586:            /**
1587:             * Perform the request
1588:             * @param req The request to handle.
1589:             * @exception ProtocolException If processsing the request failed.
1590:             * @exception ResourceException If the resource got a fatal error.
1591:             */
1592:
1593:            public ReplyInterface perform(RequestInterface req)
1594:                    throws ProtocolException, ResourceException {
1595:                ReplyInterface repi = super .perform(req);
1596:                if (repi != null)
1597:                    return repi;
1598:
1599:                if (!checkRequest(req))
1600:                    return null;
1601:
1602:                Reply reply = null;
1603:                Request request = (Request) req;
1604:                String method = request.getMethod();
1605:                // Perform the request:
1606:                if (method.equals("GET")) {
1607:                    reply = get(request);
1608:                } else if (method.equals("HEAD")) {
1609:                    reply = head(request);
1610:                } else if (method.equals("POST")) {
1611:                    reply = post(request);
1612:                } else if (method.equals("PUT")) {
1613:                    reply = put(request);
1614:                } else if (method.equals("OPTIONS")) {
1615:                    reply = options(request);
1616:                } else if (method.equals("DELETE")) {
1617:                    reply = delete(request);
1618:                } else if (method.equals("LINK")) {
1619:                    reply = link(request);
1620:                } else if (method.equals("UNLINK")) {
1621:                    reply = unlink(request);
1622:                } else if (method.equals("TRACE")) {
1623:                    reply = trace(request);
1624:                } else {
1625:                    reply = extended(request);
1626:                }
1627:                return reply;
1628:            }
1629:
1630:            /**
1631:             * The default GET method.
1632:             * @param request The request to handle.
1633:             * @exception ProtocolException If processsing the request failed.
1634:             * @exception ResourceException If the resource got a fatal error.
1635:             */
1636:
1637:            public Reply get(Request request) throws ProtocolException,
1638:                    ResourceException {
1639:                if (dresource != null) {
1640:                    // we manage a DirectoryResource
1641:                    return getDirectoryResource(request);
1642:                } else if (fresource != null) {
1643:                    // we manage a FileResource
1644:                    return getFileResource(request);
1645:                } else {
1646:                    return getOtherResource(request);
1647:                }
1648:            }
1649:
1650:            /**
1651:             * The default GET method for other king of associated resource
1652:             * @param request The request to handle.
1653:             * @exception ProtocolException If processsing the request failed.
1654:             * @exception ResourceException If the resource got a fatal error.
1655:             */
1656:            protected Reply getOtherResource(Request request)
1657:                    throws ProtocolException, ResourceException {
1658:                if (resource instanceof  ContainerResource) {
1659:                    return getDirectoryResource(request);
1660:                } else {
1661:                    // we don't manage this kind of resource
1662:                    Reply error = request.makeReply(HTTP.NOT_IMPLEMENTED);
1663:                    error.setContent("Method GET not implemented.");
1664:                    throw new HTTPException(error);
1665:                }
1666:            }
1667:
1668:            /**
1669:             * Create the reply relative to the given file.
1670:             * @param request the incomming request.
1671:             * @return A Reply instance
1672:             * @exception ProtocolException If processsing the request failed.
1673:             * @exception ResourceException If the resource got a fatal error.
1674:             */
1675:            protected Reply createFileReply(Request request)
1676:                    throws ProtocolException, ResourceException {
1677:                File file = fresource.getFile();
1678:                Reply reply = null;
1679:                // Check for a range request:
1680:                HttpRange ranges[] = request.getRange();
1681:                if ((ranges != null) && (ranges.length == 1)) {
1682:                    Reply rangereply = handleRangeRequest(request, ranges[0]);
1683:                    if (rangereply != null)
1684:                        return rangereply;
1685:                }
1686:                // Default to full reply:
1687:                reply = createDefaultReply(request, HTTP.OK);
1688:                try {
1689:                    reply.setStream(new FileInputStream(file));
1690:                } catch (IOException ex) {
1691:                    Reply error = request.makeReply(HTTP.SERVICE_UNAVAILABLE);
1692:                    error.setContent("Error while accessing filesystem");
1693:                    return error;
1694:                }
1695:                return reply;
1696:            }
1697:
1698:            /**
1699:             * Alway throws an HTTPException
1700:             */
1701:            protected Reply deleteMe(Request request) throws HTTPException {
1702:                // Delete the resource if parent is extensible:
1703:                boolean shrinkable = false;
1704:                ResourceReference rr = fresource.getParent();
1705:                ResourceReference rrtemp = null;
1706:                Resource p = null;
1707:                while (true) {
1708:                    try {
1709:                        if (rr == null)
1710:                            break;
1711:                        p = rr.lock();
1712:                        if (p instanceof  DirectoryResource) {
1713:                            shrinkable = ((DirectoryResource) p)
1714:                                    .getShrinkableFlag();
1715:                            break;
1716:                        }
1717:                        rrtemp = p.getParent();
1718:                    } catch (InvalidResourceException ex) {
1719:                        break;
1720:                    } finally {
1721:                        if (rr != null)
1722:                            rr.unlock();
1723:                    }
1724:                    rr = rrtemp;
1725:                }
1726:                if (shrinkable) {
1727:                    // The resource is indexed but has no file, emit an error
1728:                    String msg = fresource.getFile()
1729:                            + ": deleted, removing the FileResource.";
1730:                    getServer().errlog(fresource, msg);
1731:                    try {
1732:                        fresource.delete();
1733:                    } catch (MultipleLockException ex) {
1734:                        Reply error = request.makeReply(HTTP.GONE);
1735:                        error.setContentMD5(null); // FIXME must compute it!
1736:                        error.setContent("<h1>Document Gone</h1>"
1737:                                + "<p>The document " + request.getURL()
1738:                                + " is indexed but no longer available.</p>"
1739:                                + "<p>" + ex.getMessage() + "</p>");
1740:                        throw new HTTPException(error);
1741:                    }
1742:                }
1743:                // Emit an error back:
1744:                Reply error = request.makeReply(HTTP.GONE);
1745:                error.setContentMD5(null);
1746:                error.setContent("<h1>Document Gone</h1>" + "<p>The document "
1747:                        + request.getURL()
1748:                        + " is indexed but no longer available.</p>");
1749:                return error;
1750:            }
1751:
1752:            /**
1753:             * Get for FileResource
1754:             * @param request the incomming request.
1755:             * @return A Reply instance
1756:             * @exception ProtocolException If processsing the request failed.
1757:             * @exception ResourceException If the resource got a fatal error.
1758:             */
1759:            protected Reply getFileResource(Request request)
1760:                    throws ProtocolException, ResourceException {
1761:                if (fresource == null)
1762:                    throw new ResourceException(
1763:                            "this frame is not attached to a "
1764:                                    + "FileResource. ("
1765:                                    + resource.getIdentifier() + ")");
1766:                Reply reply = null;
1767:                if (!checkExpect(request)) {
1768:                    reply = createDefaultReply(request, HTTP.EXPECTATION_FAILED);
1769:                    reply.setContent("The requested expectation could not be"
1770:                            + " met by the resource");
1771:                    return reply;
1772:                }
1773:                File file = fresource.getFile();
1774:                fresource.checkContent();
1775:                updateCachedHeaders();
1776:                // Check validators:
1777:                int cim = checkIfMatch(request);
1778:                if ((cim == COND_FAILED) || (cim == COND_WEAK)) {
1779:                    reply = request.makeReply(HTTP.PRECONDITION_FAILED);
1780:                    reply.setContent("Pre-conditions failed.");
1781:                    reply.setContentMD5(null);
1782:                    return reply;
1783:                }
1784:                if (checkIfUnmodifiedSince(request) == COND_FAILED) {
1785:                    reply = request.makeReply(HTTP.PRECONDITION_FAILED);
1786:                    reply.setContent("Pre-conditions failed.");
1787:                    reply.setContentMD5(null);
1788:                    return reply;
1789:                }
1790:                if (checkValidators(request) == COND_FAILED) {
1791:                    reply = createDefaultReply(request, HTTP.NOT_MODIFIED);
1792:                    return reply;
1793:                }
1794:                // Does this file really exists, if so send it back
1795:                if (file.exists()) {
1796:                    reply = createFileReply(request);
1797:                    if (request.hasState(STATE_CONTENT_LOCATION))
1798:                        reply.setContentLocation(getURL(request)
1799:                                .toExternalForm());
1800:                    return reply;
1801:                } else {
1802:                    return deleteMe(request);
1803:                }
1804:            }
1805:
1806:            /**
1807:             * Perform a GET for the associated DirectoryResource.
1808:             * @param request the incomming request.
1809:             * @return A Reply instance.
1810:             * @exception ProtocolException if request processing failed.
1811:             * @exception ResourceException If the resource got a fatal error.
1812:             */
1813:            protected Reply getDirectoryResource(Request request)
1814:                    throws ProtocolException, ResourceException {
1815:                if (!checkExpect(request)) {
1816:                    Reply reply = createDefaultReply(request,
1817:                            HTTP.EXPECTATION_FAILED);
1818:                    reply.setContent("The requested expectation could not be"
1819:                            + " met by the resource");
1820:                    return reply;
1821:                }
1822:                String index = getIndex();
1823:                if (index != null && index.length() > 0) {
1824:                    if (index.equals("*forbid*")) {
1825:                        Reply rep = request.makeReply(HTTP.FORBIDDEN);
1826:                        rep.setContent("<h1>Forbidden</h1>"
1827:                                + "The directory resource " + request.getURL()
1828:                                + " cannot be browsed");
1829:                        return rep;
1830:                    }
1831:                }
1832:                return getDirectoryListing(request);
1833:            }
1834:
1835:            /**
1836:             * The default HEAD method replies does a GET and removes entity.
1837:             * @param request The request to handle.
1838:             * @exception ProtocolException Always thrown, to return a NOT_IMPLEMENTED
1839:             * error.
1840:             * @exception ResourceException If the resource got a fatal error.
1841:             */
1842:
1843:            public Reply head(Request request) throws ProtocolException,
1844:                    ResourceException {
1845:                if (dresource != null) {
1846:                    return headDirectoryResource(request);
1847:                } else if (fresource != null) {
1848:                    return headFileResource(request);
1849:                } else {
1850:                    return headOtherResource(request);
1851:                }
1852:            }
1853:
1854:            /**
1855:             * Perform a HEAD request for the associated resource.
1856:             * @param request the incomming request.
1857:             * @return A Reply instance
1858:             * @exception ProtocolException If processsing the request failed.
1859:             * @exception ResourceException If the resource got a fatal error.
1860:             */
1861:            protected Reply headOtherResource(Request request)
1862:                    throws ProtocolException, ResourceException {
1863:                Reply reply = null;
1864:                reply = getOtherResource(request);
1865:                reply.setStream((InputStream) null);
1866:                return reply;
1867:            }
1868:
1869:            /**
1870:             * Perform a HEAD request for the associated DirectoryResource.
1871:             * @param request the incomming request.
1872:             * @return A Reply instance
1873:             * @exception ProtocolException If processsing the request failed.
1874:             * @exception ResourceException If the resource got a fatal error.
1875:             */
1876:            protected Reply headDirectoryResource(Request request)
1877:                    throws ProtocolException, ResourceException {
1878:                Reply reply = null;
1879:                reply = getDirectoryResource(request);
1880:                reply.setStream((InputStream) null);
1881:                return reply;
1882:            }
1883:
1884:            /**
1885:             * Perform a HEAD request for the associated FileResource.
1886:             * @param request the incomming request.
1887:             * @return A Reply instance
1888:             * @exception ProtocolException If processsing the request failed.
1889:             * @exception ResourceException If the resource got a fatal error.
1890:             */
1891:            protected Reply headFileResource(Request request)
1892:                    throws ProtocolException, ResourceException {
1893:                if (fresource == null)
1894:                    throw new ResourceException(
1895:                            "this frame is not attached to a "
1896:                                    + "FileResource. ("
1897:                                    + resource.getIdentifier() + ")");
1898:                Reply reply = null;
1899:                if (!checkExpect(request)) {
1900:                    reply = createDefaultReply(request, HTTP.EXPECTATION_FAILED);
1901:                    reply.setContent("The requested expectation could not be"
1902:                            + " met by the resource");
1903:                    return reply;
1904:                }
1905:                fresource.checkContent();
1906:                updateCachedHeaders();
1907:                // Conditional check:
1908:                int cim = checkIfMatch(request);
1909:                if ((cim == COND_FAILED) || (cim == COND_WEAK)) {
1910:                    Reply r = request.makeReply(HTTP.PRECONDITION_FAILED);
1911:                    r.setContent("Pre-conditions failed.");
1912:                    return r;
1913:                }
1914:                if (checkIfUnmodifiedSince(request) == COND_FAILED) {
1915:                    Reply r = request.makeReply(HTTP.PRECONDITION_FAILED);
1916:                    r.setContent("Pre-conditions failed.");
1917:                    return r;
1918:                }
1919:                if (checkValidators(request) == COND_FAILED) {
1920:                    return createDefaultReply(request, HTTP.NOT_MODIFIED);
1921:                }
1922:                if (!fresource.getFile().exists()) {
1923:                    return deleteMe(request);
1924:                }
1925:                reply = createDefaultReply(request, HTTP.OK);
1926:                if (request.hasState(STATE_CONTENT_LOCATION))
1927:                    reply.setContentLocation(getURL(request).toExternalForm());
1928:                return reply;
1929:
1930:            }
1931:
1932:            /**
1933:             * The default POST method replies with a not implemented.
1934:             * @param request The request to handle.
1935:             * @exception ProtocolException Always thrown, to return a NOT_IMPLEMENTED
1936:             *    error.
1937:             * @exception ResourceException If the resource got a fatal error.
1938:             */
1939:
1940:            public Reply post(Request request) throws ProtocolException,
1941:                    ResourceException {
1942:                if (!checkExpect(request)) {
1943:                    Reply reply = createDefaultReply(request,
1944:                            HTTP.EXPECTATION_FAILED);
1945:                    reply.setContent("The requested expectation could not be"
1946:                            + " met by the resource");
1947:                    return reply;
1948:                }
1949:                Reply error = request.makeReply(HTTP.NOT_ALLOWED);
1950:                error.setHeaderValue(Reply.H_ALLOW, getAllow());
1951:                error.setContent("Method POST not allowed on this resource.");
1952:                throw new HTTPException(error);
1953:            }
1954:
1955:            /**
1956:             * The default PUT method.
1957:             * @param request The request to handle.
1958:             * @exception ProtocolException If processsing the request failed.
1959:             * @exception ResourceException If the resource got a fatal error.
1960:             */
1961:
1962:            public Reply put(Request request) throws ProtocolException,
1963:                    ResourceException {
1964:                if (fresource != null) {
1965:                    return putFileResource(request);
1966:                } else {
1967:                    return putOtherResource(request);
1968:                }
1969:            }
1970:
1971:            /**
1972:             * Always throw a ProtocolException.
1973:             * @param request The incmming request.
1974:             * @return a Reply instance.
1975:             * @exception ProtocolException (Always thrown).
1976:             */
1977:            protected Reply putOtherResource(Request request)
1978:                    throws ProtocolException {
1979:                Reply error = request.makeReply(HTTP.NOT_IMPLEMENTED);
1980:                error.setContent("Method PUT not implemented.");
1981:                throw new HTTPException(error);
1982:            }
1983:
1984:            /**
1985:             * Change the content of the associated FileResource.
1986:             * @param request The incomming request.
1987:             * @exception org.w3c.tools.resources.ProtocolException if a protocol 
1988:             * error occurs
1989:             * @exception ResourceException If the resource got a fatal error.
1990:             */
1991:            protected Reply putFileResource(Request request)
1992:                    throws ProtocolException, ResourceException {
1993:                Reply reply = null;
1994:                int status = HTTP.OK;
1995:
1996:                if (!checkExpect(request)) {
1997:                    reply = createDefaultReply(request, HTTP.EXPECTATION_FAILED);
1998:                    reply.setContent("The requested expectation could not be"
1999:                            + " met by the resource");
2000:                    return reply;
2001:                }
2002:                fresource.checkContent();
2003:                updateCachedHeaders();
2004:                // Is this resource writable ?
2005:                if (!getPutableFlag()) {
2006:                    Reply error = request.makeReply(HTTP.NOT_ALLOWED);
2007:                    error.setHeaderValue(Reply.H_ALLOW, getAllow());
2008:                    error.setContent("Method PUT not allowed.");
2009:                    throw new HTTPException(error);
2010:                }
2011:                // Check validators:
2012:                int cim = checkIfMatch(request);
2013:                if ((cim == COND_FAILED) || (cim == COND_WEAK)
2014:                        || (checkIfNoneMatch(request) == COND_FAILED)
2015:                        || (checkIfModifiedSince(request) == COND_FAILED)
2016:                        || (checkIfUnmodifiedSince(request) == COND_FAILED)) {
2017:                    Reply r = request.makeReply(HTTP.PRECONDITION_FAILED);
2018:                    r.setContent("Pre-condition failed.");
2019:                    return r;
2020:                }
2021:                // Check the request:
2022:                InputStream in = null;
2023:                try {
2024:                    in = request.getInputStream();
2025:                    if (in == null) {
2026:                        Reply error = request.makeReply(HTTP.BAD_REQUEST);
2027:                        error
2028:                                .setContent("<p>Request doesn't have a valid content.");
2029:                        throw new HTTPException(error);
2030:                    }
2031:                } catch (IOException ex) {
2032:                    throw new ClientException(request.getClient(), ex);
2033:                }
2034:                // We do not support (for the time being) put with ranges:
2035:                if (request.hasContentRange()) {
2036:                    Reply error = request.makeReply(HTTP.NOT_IMPLEMENTED);
2037:                    error.setContent("partial PUT not supported.");
2038:                    throw new HTTPException(error);
2039:                }
2040:                // REMOVED as it is impossile for clients to behave properly.
2041:                // Of course it is fare more unsafe now, but it was too impractical IRL.
2042:                // Check that if some type is provided it doesn't conflict:
2043:                //	if ( request.hasContentType() ) {
2044:                //	    MimeType rtype = request.getContentType() ;
2045:                //	    MimeType type  = getContentType() ;
2046:                //	    if ( type == null ) {
2047:                //		setValue (ATTR_CONTENT_TYPE, rtype) ;
2048:                //	    } else if ( (rtype.match (type) < 0 ) && !rtype.equiv(type) ) {
2049:                //		if (debug) {
2050:                //		    System.out.println("No match between: ["+
2051:                //				       rtype.toString()+"] and ["+
2052:                //				       type.toString()+"]");
2053:                //		}
2054:                //		Reply error = request.makeReply(HTTP.UNSUPPORTED_MEDIA_TYPE) ;
2055:                //		error.setContent ("<p>Invalid content type: "+rtype.toString()
2056:                //				  + " is not matching resource MIME type: "
2057:                //				  +type.toString());
2058:                //		throw new HTTPException (error) ;
2059:                //	    }
2060:                //	}
2061:                // Write the body back to the file:
2062:                try {
2063:                    // We are about to accept the put, notify client before continuing
2064:                    Client client = request.getClient();
2065:                    if (client != null && request.getExpect() != null) {
2066:                        // FIXME we should check for "100-continue" explicitely
2067:                        client.sendContinue();
2068:                    }
2069:                    if (fresource.newContent(request.getInputStream()))
2070:                        status = HTTP.CREATED;
2071:                    else
2072:                        status = HTTP.NO_CONTENT;
2073:                } catch (IOException ex) {
2074:                    if (debug)
2075:                        ex.printStackTrace();
2076:                    // so we have a problem replacing or creating the content
2077:                    // it is then a configuration problem (access right for the 
2078:                    // underlying fle resource for example...
2079:                    Reply error = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
2080:                    error.setReason("File Access Error");
2081:                    error.setContent("<p>Unable to save " + request.getURL()
2082:                            + " due to IO problems");
2083:                    throw new HTTPException(error);
2084:                }
2085:                if (status == HTTP.CREATED) {
2086:                    reply = request.makeReply(status);
2087:                    reply.setContent("<P>Resource succesfully created");
2088:                    if (request.hasState(STATE_CONTENT_LOCATION))
2089:                        reply.setContentLocation(getURL(request)
2090:                                .toExternalForm());
2091:                    // Henrik's fix, create the Etag on 201
2092:                    if (fresource != null) {
2093:                        // We only take car eof etag here:
2094:                        if (etag == null) {
2095:                            reply.setETag(getETag());
2096:                        }
2097:                    }
2098:                    reply.setLocation(getURL(request));
2099:                    reply.setContent("<p>Entity body saved succesfully !");
2100:                } else {
2101:                    reply = createDefaultReply(request, status);
2102:                }
2103:                return reply;
2104:            }
2105:
2106:            /**
2107:             * The default OPTIONS method replies with a not implemented.
2108:             * @param request The request to handle.
2109:             * @exception ProtocolException In case of errors.
2110:             * @exception ResourceException If the resource got a fatal error.
2111:             */
2112:
2113:            public Reply options(Request request) throws ProtocolException,
2114:                    ResourceException {
2115:                if (!checkExpect(request)) {
2116:                    Reply reply = createDefaultReply(request,
2117:                            HTTP.EXPECTATION_FAILED);
2118:                    reply.setContent("The requested expectation could not be"
2119:                            + " met by the resource");
2120:                    return reply;
2121:                }
2122:                Reply reply = createDefaultReply(request, HTTP.OK);
2123:                // set size to 0 according to rfc2616 9.2
2124:                reply.setContentLength(0);
2125:                // Removed unused headers:
2126:                reply.setContentType(null);
2127:                // Add the allow header:
2128:                reply.setHeaderValue(Reply.H_ALLOW, getAllow());
2129:                return reply;
2130:            }
2131:
2132:            /**
2133:             * The default DELETE method, actually the resource (file, directory)
2134:             * is moved into the trash directory which is not accessible via HTTP.
2135:             * @param request The request to handle.
2136:             * @exception ProtocolException If processsing the request failed.
2137:             * @exception ResourceException If the resource got a fatal error.
2138:             */
2139:
2140:            public Reply delete(Request request) throws ProtocolException,
2141:                    ResourceException {
2142:                if (getAllowDeleteFlag()) {
2143:                    if (dresource != null) {
2144:                        // we manage a DirectoryResource
2145:                        return deleteDirectoryResource(request);
2146:                    } else if (fresource != null) {
2147:                        // we manage a FileResource
2148:                        return deleteFileResource(request);
2149:                    } else {
2150:                        return deleteOtherResource(request);
2151:                    }
2152:                } else {
2153:                    Reply error = request.makeReply(HTTP.NOT_ALLOWED);
2154:                    error.setContent("Method DELETE not allowed.");
2155:                    error.setHeaderValue(Reply.H_ALLOW, getAllow());
2156:                    throw new HTTPException(error);
2157:                }
2158:            }
2159:
2160:            protected File computeTrashFile(File file) {
2161:                File trashdir = new File(getServer().getTrashDirectory());
2162:                if (!trashdir.exists()) {
2163:                    trashdir.mkdirs();
2164:                }
2165:                String filename = file.getName();
2166:                File trashfile = new File(trashdir, filename);
2167:                int nb = 1;
2168:                while (trashfile.exists()) {
2169:                    trashfile = new File(trashdir, filename + "." + nb);
2170:                    nb++;
2171:                }
2172:                return trashfile;
2173:            }
2174:
2175:            protected File computeTrashDir(File dir) {
2176:                return computeTrashFile(dir);
2177:            }
2178:
2179:            /**
2180:             * Perform a DELETE for the associated DirectoryResource.
2181:             * @param request the incomming request.
2182:             * @return A Reply instance.
2183:             * @exception ProtocolException if request processing failed.
2184:             * @exception ResourceException If the resource got a fatal error.
2185:             */
2186:            protected Reply deleteDirectoryResource(Request request)
2187:                    throws ProtocolException, ResourceException {
2188:                if (!checkExpect(request)) {
2189:                    Reply reply = createDefaultReply(request,
2190:                            HTTP.EXPECTATION_FAILED);
2191:                    reply.setContent("The requested expectation could not be"
2192:                            + " met by the resource");
2193:                    return reply;
2194:                }
2195:                File olddir = dresource.getDirectory();
2196:                File newdir = computeTrashDir(olddir);
2197:                try {
2198:                    //delete the FileResource
2199:                    dresource.delete();
2200:                } catch (MultipleLockException ex) {
2201:                    Reply error = request.makeReply(HTTP.FORBIDDEN);
2202:                    error.setContent("Can't delete resource: "
2203:                            + resource.getIdentifier()
2204:                            + " is locked. Try again later.");
2205:                    throw new HTTPException(error);
2206:                }
2207:                olddir.renameTo(newdir);
2208:                return request.makeReply(HTTP.NO_CONTENT);
2209:            }
2210:
2211:            /**
2212:             * Perform a DELETE for the associated FileResource.
2213:             * @param request the incomming request.
2214:             * @return A Reply instance.
2215:             * @exception ProtocolException if request processing failed.
2216:             * @exception ResourceException If the resource got a fatal error.
2217:             */
2218:            protected Reply deleteFileResource(Request request)
2219:                    throws ProtocolException, ResourceException {
2220:                if (!checkExpect(request)) {
2221:                    Reply reply = createDefaultReply(request,
2222:                            HTTP.EXPECTATION_FAILED);
2223:                    reply.setContent("The requested expectation could not be"
2224:                            + " met by the resource");
2225:                    return reply;
2226:                }
2227:                File oldfile = fresource.getFile();
2228:                File newfile = computeTrashFile(oldfile);
2229:                try {
2230:                    //delete the FileResource
2231:                    fresource.delete();
2232:                } catch (MultipleLockException ex) {
2233:                    Reply error = request.makeReply(HTTP.FORBIDDEN);
2234:                    error.setContent("Can't delete resource: "
2235:                            + resource.getIdentifier()
2236:                            + " is locked. Try again later.");
2237:                    throw new HTTPException(error);
2238:                }
2239:                oldfile.renameTo(newfile);
2240:                return request.makeReply(HTTP.NO_CONTENT);
2241:            }
2242:
2243:            /**
2244:             * Perform a DELETE for the associated resource.
2245:             * @param request the incomming request.
2246:             * @return A Reply instance.
2247:             * @exception ProtocolException if request processing failed.
2248:             * @exception ResourceException If the resource got a fatal error.
2249:             */
2250:            protected Reply deleteOtherResource(Request request)
2251:                    throws ProtocolException, ResourceException {
2252:                // we don't manage this kind of resource
2253:                if (!checkExpect(request)) {
2254:                    Reply reply = createDefaultReply(request,
2255:                            HTTP.EXPECTATION_FAILED);
2256:                    reply.setContent("The requested expectation could not be"
2257:                            + " met by the resource");
2258:                    return reply;
2259:                }
2260:                Reply error = request.makeReply(HTTP.NOT_IMPLEMENTED);
2261:                error.setContent("Method DELETE not implemented.");
2262:                throw new HTTPException(error);
2263:            }
2264:
2265:            /**
2266:             * The default LINK method replies with a not implemented.
2267:             * @param request The request to handle.
2268:             * @exception ProtocolException Always thrown, to return a NOT_IMPLEMENTED
2269:             * error.
2270:             * @exception ResourceException If the resource got a fatal error.
2271:             */
2272:
2273:            public Reply link(Request request) throws ProtocolException,
2274:                    ResourceException {
2275:                if (!checkExpect(request)) {
2276:                    Reply reply = createDefaultReply(request,
2277:                            HTTP.EXPECTATION_FAILED);
2278:                    reply.setContent("The requested expectation could not be"
2279:                            + " met by the resource");
2280:                    return reply;
2281:                }
2282:                Reply error = request.makeReply(HTTP.NOT_IMPLEMENTED);
2283:                error.setContent("Method LINK not implemented.");
2284:                throw new HTTPException(error);
2285:            }
2286:
2287:            /**
2288:             * The default UNLINK method replies with a not implemented.
2289:             * @param request The request to handle.
2290:             * @exception ProtocolException Always thrown, to return a NOT_IMPLEMENTED
2291:             *    error.
2292:             * @exception ResourceException If the resource got a fatal error.
2293:             */
2294:
2295:            public Reply unlink(Request request) throws ProtocolException,
2296:                    ResourceException {
2297:                if (!checkExpect(request)) {
2298:                    Reply reply = createDefaultReply(request,
2299:                            HTTP.EXPECTATION_FAILED);
2300:                    reply.setContent("The requested expectation could not be"
2301:                            + " met by the resource");
2302:                    return reply;
2303:                }
2304:                Reply error = request.makeReply(HTTP.NOT_IMPLEMENTED);
2305:                error.setContent("Method UNLINK not implemented.");
2306:                throw new HTTPException(error);
2307:            }
2308:
2309:            /**
2310:             * The default TRACE method replies with a not implemented
2311:             * @param request The request to handle.
2312:             * @exception HTTPException In case of errors.
2313:             * @exception ClientException If the client instance controling the
2314:             * request processing got a fatal error.
2315:             */
2316:
2317:            public Reply trace(Request request) throws HTTPException,
2318:                    ClientException {
2319:                Reply reply = null;
2320:                if (!checkExpect(request)) {
2321:                    reply = createDefaultReply(request, HTTP.EXPECTATION_FAILED);
2322:                    reply.setContent("The requested expectation could not be"
2323:                            + " met by the resource");
2324:                    return reply;
2325:                }
2326:                reply = createDefaultReply(request, HTTP.OK);
2327:                reply.setNoCache(); // don't cache this
2328:                reply.setMaxAge(-1); // 
2329:                reply.setContentMD5(null);
2330:                // Dump the request as the body
2331:                // Removed unused headers:
2332:                // FIXME should be something else for chuncked stream
2333:                ByteArrayOutputStream ba = new ByteArrayOutputStream();
2334:                try {
2335:                    reply.setContentType(new MimeType("message/http"));
2336:                    request.dump(ba);
2337:                    reply.setContentLength(ba.size());
2338:                } catch (Exception ex) {
2339:                    ex.printStackTrace();
2340:                }
2341:                reply.setStream(new ByteArrayInputStream(ba.toByteArray()));
2342:                return reply;
2343:            }
2344:
2345:            public Reply extended(Request request) throws ProtocolException,
2346:                    ResourceException {
2347:                String method = request.getMethod();
2348:                Reply error = request.makeReply(HTTP.NOT_IMPLEMENTED);
2349:                error.setContent("Method " + method + " not implemented.");
2350:                throw new HTTPException(error);
2351:            }
2352:
2353:            /**
2354:             * The Browse Mime type.
2355:             */
2356:            protected static MimeType browsetype = null;
2357:
2358:            /**
2359:             * Get the Browse Mime type.
2360:             */
2361:
2362:            protected synchronized MimeType getBrowseType() {
2363:                if (browsetype == null) {
2364:                    try {
2365:                        browsetype = new MimeType("application/x-navibrowse");
2366:                    } catch (Exception ex) {
2367:                        ex.printStackTrace();
2368:                    }
2369:                }
2370:                return browsetype;
2371:            }
2372:
2373:            /**
2374:             * A present to GNNPress users !
2375:             * This method implements the <code>BROWSE</code> method that
2376:             * AOL press (or GNN press, or whatever its last name is) expects.
2377:             * @param request The request to process.
2378:             * @exception ProtocolException If some error occurs.
2379:             * @return A Reply instance.
2380:             */
2381:
2382:            public Reply browse(Request request) throws ProtocolException {
2383:                if (dresource == null) {
2384:                    Reply error = request.makeReply(HTTP.NOT_IMPLEMENTED);
2385:                    error.setContent("Method " + request.getMethod()
2386:                            + " not implemented.");
2387:                    throw new HTTPException(error);
2388:                }
2389:
2390:                Enumeration e = dresource.enumerateResourceIdentifiers();
2391:                Vector resources = Sorter.sortStringEnumeration(e);
2392:                int rsize = ((resources == null) ? 0 : resources.size());
2393:                StringBuffer sb = new StringBuffer();
2394:
2395:                // As we have enumerated all resources, just looking the store is ok
2396:                for (int i = 0; i < rsize; i++) {
2397:                    String rname = (String) resources.elementAt(i);
2398:                    ResourceReference rr = null;
2399:                    Resource r = null;
2400:                    try {
2401:                        rr = dresource.lookup(rname);
2402:                        r = rr.lock();
2403:                        // may throw InvalidResourceException
2404:
2405:                        if (r instanceof  DirectoryResource) {
2406:                            sb
2407:                                    .append("application/x-navidir " + rname
2408:                                            + "\r\n");
2409:                        } else {
2410:                            HTTPFrame itsframe = (HTTPFrame) resource
2411:                                    .getFrame(getClass());
2412:                            if (itsframe != null) {
2413:                                sb.append(itsframe.getContentType().toString()
2414:                                        + " " + rname + "\r\n");
2415:                            }
2416:                        }
2417:                    } catch (InvalidResourceException ex) {
2418:                        continue;
2419:                    } finally {
2420:                        rr.unlock();
2421:                    }
2422:                }
2423:                Reply reply = request.makeReply(HTTP.OK);
2424:                reply.addPragma("no-cache");
2425:                reply.setNoCache();
2426:                reply.setContent(sb.toString());
2427:                reply.setContentType(getBrowseType());
2428:                return reply;
2429:            }
2430:
2431:            /**
2432:             * Set the values. (MUST be called before initialize).
2433:             * @param defs The Hashtable containing the values.
2434:             */
2435:            public void pickleValues(Hashtable defs) {
2436:                Object nvalues[] = new Object[attributes.length];
2437:                for (int i = 0; i < nvalues.length; i++) {
2438:                    String attrname = attributes[i].getName();
2439:                    Object def = defs.get(attrname);
2440:                    // note that protocol frames have usually names in the
2441:                    // frame-XX serie, so it is valid to save (big) on this.
2442:                    if ((def != null)
2443:                            && ((i == ATTR_HELP_URL) || (i == ATTR_IDENTIFIER)
2444:                                    || (i == ATTR_TITLE) || (i == ATTR_CHARSET)
2445:                                    || (i == ATTR_CONTENT_LANGUAGE)
2446:                                    || (i == ATTR_CONTENT_ENCODING)
2447:                                    || (i == ATTR_ICON) || (i == ATTR_INDEX)
2448:                                    || (i == ATTR_ICONDIR) || (i == ATTR_STYLE_LINK))
2449:                            && (def instanceof  String)) {
2450:                        nvalues[i] = ((String) def).intern();
2451:                    } else {
2452:                        nvalues[i] = def;
2453:                    }
2454:                }
2455:                this .values = nvalues;
2456:            }
2457:
2458:            /**
2459:             * Initialization method for attribute holders.
2460:             * This method allows to initialize an attribute holder by providing
2461:             * its attributes values through a Hashtable mapping attribute names
2462:             * to attribute values.
2463:             * @param defs The Hashtable containing the default values.
2464:             */
2465:
2466:            public void initialize(Hashtable defs) {
2467:                Object values[] = ((this .values == null) ? new Object[attributes.length]
2468:                        : this .values);
2469:                for (int i = 0; i < values.length; i++) {
2470:                    String attrname = attributes[i].getName();
2471:                    Object def = defs.get(attrname);
2472:                    if (values[i] == null) {
2473:                        // for help_url, we can save lots of space by using 
2474:                        // String.intern()
2475:                        // Those attribute are not, in practise, very variables
2476:                        // So it is a valid optimisation to intern them.
2477:                        if ((def != null)
2478:                                && ((i == ATTR_HELP_URL)
2479:                                        || (i == ATTR_IDENTIFIER)
2480:                                        || (i == ATTR_TITLE)
2481:                                        || (i == ATTR_CHARSET)
2482:                                        || (i == ATTR_CONTENT_LANGUAGE)
2483:                                        || (i == ATTR_CONTENT_ENCODING)
2484:                                        || (i == ATTR_ICON)
2485:                                        || (i == ATTR_INDEX)
2486:                                        || (i == ATTR_ICONDIR) || (i == ATTR_STYLE_LINK))
2487:                                && (def instanceof  String)) {
2488:                            values[i] = ((String) def).intern();
2489:                        } else {
2490:                            values[i] = def;
2491:                        }
2492:                    }
2493:                }
2494:                initialize(values);
2495:            }
2496:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.