--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"\r
+ "http://www.w3.org/TR/REC-html40/strict.dtd">\r
+<html>\r
+ <head>\r
+ <title>HTTPFrame.java</title>\r
+ <meta name="Author" content="Benoit Mahe">\r
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">\r
+ <meta name="Generator" content="*emacs: emacs-css">\r
+\r
+ <link rel="Stylesheet" media="screen" type="text/css" href="default-html.css">\r
+ </head>\r
+ <body>\r
+\r
+ <pre>\r
+<span class="comment">// HTTPFrame.java\r
+// $Id: HTTPFrame.html,v 1.1 2010/06/15 12:20:08 smhuang Exp $\r
+// (c) COPYRIGHT MIT and INRIA, 1997.\r
+// Please first read the full copyright statement in file COPYRIGHT.html\r
+</span>\r
+<span class="keyword">package</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">jigsaw</span>.<span class="type">frames</span>;\r
+\r
+<span class="keyword">import</span> <span class="reference">java</span>.<span class="reference">io</span>.*;\r
+<span class="keyword">import</span> <span class="reference">java</span>.<span class="reference">net</span>.*;\r
+<span class="keyword">import</span> <span class="reference">java</span>.<span class="reference">util</span>.*;\r
+\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">tools</span>.<span class="reference">codec</span>.*;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">tools</span>.<span class="reference">sorter</span>.*;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">tools</span>.<span class="reference">resources</span>.*;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">tools</span>.<span class="reference">resources</span>.<span class="reference">event</span>.*;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">jigsaw</span>.<span class="reference">http</span>.* ;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">jigsaw</span>.<span class="reference">html</span>.* ;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">www</span>.<span class="reference">mime</span>.*;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">www</span>.<span class="reference">http</span>.*;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">tools</span>.<span class="reference">crypt</span>.<span class="type">Md5</span>;\r
+\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">tools</span>.<span class="reference">resources</span>.<span class="type">ProtocolException</span>;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">tools</span>.<span class="reference">resources</span>.<span class="type">NotAProtocolException</span>;\r
+\r
+<span class="comment">/**\r
+ * Default class to handle the HTTP protocol, manage FileResource and\r
+ * DirectoryResource.\r
+ */</span>\r
+<span class="reference">public</span> <span class="keyword">class</span> <span class="function-name">HTTPFrame</span> <span class="keyword">extends</span> <span class="type">ProtocolFrame</span> {\r
+\r
+ <span class="comment">/**\r
+ * The special class of filter.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">Class</span> <span class="variable-name">filterClass</span> = <span class="keyword">null</span>;\r
+\r
+ <span class="comment">/**\r
+ * Condition check return code - Condition existed but failed.\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">static</span> <span class="type">final</span> <span class="type">int</span> <span class="variable-name">COND_FAILED</span> = 1;\r
+ <span class="comment">/**\r
+ * Condition check return code - Condition existed and succeeded.\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">static</span> <span class="type">final</span> <span class="type">int</span> <span class="variable-name">COND_OK</span> = 2;\r
+ \r
+ <span class="comment">// Methods allowed by that class in general:\r
+</span> <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">HttpTokenList</span> <span class="variable-name">_allowed</span> = <span class="keyword">null</span>;\r
+ <span class="string">private</span> <span class="type">static</span> <span class="type">HttpTokenList</span> <span class="variable-name">_put_allowed</span> = <span class="keyword">null</span>;\r
+ <span class="string">private</span> <span class="type">static</span> <span class="type">HttpTokenList</span> <span class="variable-name">_browse_allowed</span> = <span class="keyword">null</span>;\r
+ <span class="string">private</span> <span class="type">static</span> <span class="type">HttpTokenList</span> <span class="variable-name">_accept_ranges</span> = <span class="keyword">null</span>;\r
+\r
+ <span class="type">static</span> {\r
+ <span class="comment">// allowed shares _allowed value, that's a feature.\r
+</span> <span class="type">String</span> <span class="variable-name">str_allowed</span>[] = { "<span class="string">GET</span>", "<span class="string">HEAD</span>", "<span class="string">OPTIONS</span>", "<span class="string">TRACE</span>"};\r
+ _allowed = HttpFactory.makeStringList(str_allowed);\r
+ <span class="type">String</span> <span class="variable-name">str_allow</span>[] = { "<span class="string">HEAD</span>" , "<span class="string">GET</span>" , "<span class="string">PUT</span>" , "<span class="string">OPTIONS</span>", "<span class="string">TRACE</span>" };\r
+ _put_allowed = HttpFactory.makeStringList(str_allow);\r
+ <span class="type">String</span> <span class="variable-name">str_all</span>[] = { "<span class="string">HEAD</span>" , "<span class="string">GET</span>" , "<span class="string">BROWSE</span>" , "<span class="string">OPTIONS</span>","<span class="string">TRACE</span>" };\r
+ _browse_allowed = HttpFactory.makeStringList(str_allow);\r
+ <span class="type">String</span> <span class="variable-name">accept_ranges</span>[] = { "<span class="string">bytes</span>" };\r
+ _accept_ranges = HttpFactory.makeStringList(accept_ranges);\r
+ }\r
+ <span class="comment">// Methods allowed by instances of that class in particular:\r
+</span> <span class="preprocessor">protected</span> <span class="type">HttpTokenList</span> <span class="variable-name">allowed</span> = _allowed;\r
+\r
+\r
+ <span class="comment">/**\r
+ * Attributes index - The index for the quality attribute.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_QUALITY</span> = -1 ;\r
+ <span class="comment">/**\r
+ * Attribute index - The index for the title attribute.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_TITLE</span> = -1 ;\r
+ <span class="comment">/**\r
+ * Attribute index - The index for the content languages attribute.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_CONTENT_LANGUAGE</span> = -1 ;\r
+ <span class="comment">/**\r
+ * Attribute index - The index for the content encodings attribute.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_CONTENT_ENCODING</span> = -1 ;\r
+ <span class="comment">/**\r
+ * Attribute index - The index for the content type attribute.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_CONTENT_TYPE</span> = -1 ;\r
+ <span class="comment">/**\r
+ * Attribute index - The index for the content length attribute.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_CONTENT_LENGTH</span> = -1 ;\r
+ <span class="comment">/**\r
+ * Attribute index - The icon (if any) associated to the resource.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_ICON</span> = -1 ;\r
+ <span class="comment">/**\r
+ * Attribute index - Max age: the maximum drift allowed from reality.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_MAXAGE</span> = -1 ;\r
+ <span class="comment">/**\r
+ * Attribute index - Send MD5 Digest: the md5 digest of the resource sent\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_MD5</span> = -1;\r
+\r
+\r
+ <span class="comment">//\r
+</span> <span class="comment">// Attribute relative to FileResource\r
+</span> <span class="comment">//\r
+</span>\r
+ <span class="comment">/**\r
+ * Attribute index - Do we allow PUT method on this file.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_PUTABLE</span> = -1 ;\r
+\r
+ <span class="comment">//\r
+</span> <span class="comment">// Attribute relative to DirectoryResource\r
+</span> <span class="comment">//\r
+</span>\r
+ <span class="comment">/**\r
+ * Attribute index - The index for our relocate attribute.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_RELOCATE</span> = -1 ;\r
+ <span class="comment">/**\r
+ * Attribute index - our index resource name.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_INDEX</span> = -1 ;\r
+ <span class="comment">/**\r
+ * Attribute index - The icon directory to use in dir listing.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_ICONDIR</span> = -1 ;\r
+ <span class="comment">/**\r
+ * Attribute index - Allow the GNN browse method.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_BROWSABLE</span> = -1 ;\r
+ <span class="comment">/**\r
+ * Attribute index - Style sheet for directory listing\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_STYLE_LINK</span> = -1 ;\r
+\r
+ <span class="type">static</span> {\r
+ <span class="type">Attribute</span> <span class="variable-name">a</span> = <span class="keyword">null</span> ;\r
+ <span class="type">Class</span> <span class="variable-name">cls</span> = <span class="keyword">null</span> ;\r
+\r
+ <span class="keyword">try</span> {\r
+ filterClass = \r
+ Class.forName("<span class="string">org.w3c.tools.resources.ResourceFilter</span>");\r
+ } <span class="keyword">catch</span> (<span class="type">Exception</span> <span class="variable-name">ex</span>) {\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">RuntimeException</span>("<span class="string">No ResourceFilter class found.</span>");\r
+ }\r
+\r
+ <span class="comment">// Get a pointer to our class:\r
+</span> <span class="keyword">try</span> {\r
+ cls = Class.forName("<span class="string">org.w3c.jigsaw.frames.HTTPFrame</span>") ;\r
+ } <span class="keyword">catch</span> (<span class="type">Exception</span> <span class="variable-name">ex</span>) {\r
+ ex.printStackTrace() ;\r
+ System.exit(1) ;\r
+ }\r
+ <span class="comment">// The quality attribute:\r
+</span> a = <span class="keyword">new</span> <span class="type">DoubleAttribute</span>("<span class="string">quality</span>"\r
+ , <span class="keyword">new</span> <span class="type">Double</span>(1.0) \r
+ , Attribute.EDITABLE);\r
+ ATTR_QUALITY = AttributeRegistry.registerAttribute(cls, a) ;\r
+ <span class="comment">// The title attribute:\r
+</span> a = <span class="keyword">new</span> <span class="type">StringAttribute</span>("<span class="string">title</span>"\r
+ , <span class="keyword">null</span>\r
+ , Attribute.EDITABLE) ;\r
+ ATTR_TITLE = AttributeRegistry.registerAttribute(cls, a) ;\r
+ <span class="comment">// The content language attribute:\r
+</span> a = <span class="keyword">new</span> <span class="type">LanguageAttribute</span>("<span class="string">content-language</span>"\r
+ , <span class="keyword">null</span>\r
+ , Attribute.EDITABLE) ;\r
+ ATTR_CONTENT_LANGUAGE = AttributeRegistry.registerAttribute(cls,a);\r
+ <span class="comment">// The content encoding attribute:\r
+</span> a = <span class="keyword">new</span> <span class="type">EncodingAttribute</span>("<span class="string">content-encoding</span>"\r
+ , <span class="keyword">null</span>\r
+ , Attribute.EDITABLE) ;\r
+ ATTR_CONTENT_ENCODING = AttributeRegistry.registerAttribute(cls,a);\r
+ <span class="comment">// The content type attribute:\r
+</span> a = <span class="keyword">new</span> <span class="type">MimeTypeAttribute</span>("<span class="string">content-type</span>"\r
+ , <span class="reference">MimeType</span>.<span class="type">TEXT_PLAIN</span>\r
+ , Attribute.EDITABLE) ;\r
+ ATTR_CONTENT_TYPE = AttributeRegistry.registerAttribute(cls,a);\r
+ <span class="comment">// The content length attribute:\r
+</span> a = <span class="keyword">new</span> <span class="type">IntegerAttribute</span>("<span class="string">content-length</span>"\r
+ , <span class="keyword">null</span>\r
+ , Attribute.COMPUTED);\r
+ ATTR_CONTENT_LENGTH = AttributeRegistry.registerAttribute(cls,a);\r
+ <span class="comment">// The icon attribute:\r
+</span> a = <span class="keyword">new</span> <span class="type">StringAttribute</span>("<span class="string">icon</span>"\r
+ , <span class="keyword">null</span>\r
+ , Attribute.EDITABLE) ;\r
+ ATTR_ICON = AttributeRegistry.registerAttribute(cls, a) ;\r
+ <span class="comment">// The max age attribute (in ms)\r
+</span> a = <span class="keyword">new</span> <span class="type">LongAttribute</span>("<span class="string">maxage</span>"\r
+ , <span class="keyword">null</span>\r
+ , Attribute.EDITABLE) ;\r
+ ATTR_MAXAGE = AttributeRegistry.registerAttribute(cls, a) ;\r
+ <span class="comment">// Should we send MD5 digest?\r
+</span> a = <span class="keyword">new</span> <span class="type">BooleanAttribute</span>("<span class="string">send-md5</span>"\r
+ , <span class="reference">Boolean</span>.<span class="type">FALSE</span>\r
+ , Attribute.EDITABLE);\r
+ ATTR_MD5 = AttributeRegistry.registerAttribute(cls, a) ;\r
+\r
+ <span class="comment">//\r
+</span> <span class="comment">// Attribute relative to a FileResource\r
+</span> <span class="comment">//\r
+</span>\r
+ <span class="comment">// The putable flag:\r
+</span> a = <span class="keyword">new</span> <span class="type">BooleanAttribute</span>("<span class="string">putable</span>"\r
+ , <span class="reference">Boolean</span>.<span class="type">FALSE</span>\r
+ , Attribute.EDITABLE) ;\r
+ ATTR_PUTABLE = AttributeRegistry.registerAttribute(cls, a) ;\r
+\r
+ <span class="comment">//\r
+</span> <span class="comment">// Attribute relative to a DirectoryResource\r
+</span> <span class="comment">//\r
+</span>\r
+ <span class="comment">//Should we relocate invalid request to this directory ?\r
+</span> a = <span class="keyword">new</span> <span class="type">BooleanAttribute</span>("<span class="string">relocate</span>"\r
+ , <span class="reference">Boolean</span>.<span class="type">TRUE</span>\r
+ , Attribute.EDITABLE);\r
+ ATTR_RELOCATE = AttributeRegistry.registerAttribute(cls, a) ;\r
+ <span class="comment">// Our index resource name (optional).\r
+</span> a = <span class="keyword">new</span> <span class="type">StringAttribute</span>("<span class="string">index</span>"\r
+ , <span class="keyword">null</span>\r
+ , Attribute.EDITABLE) ;\r
+ ATTR_INDEX = AttributeRegistry.registerAttribute(cls, a) ;\r
+ <span class="comment">// Our icon directory.\r
+</span> a = <span class="keyword">new</span> <span class="type">StringAttribute</span>("<span class="string">icondir</span>"\r
+ , <span class="keyword">null</span>\r
+ , Attribute.EDITABLE) ;\r
+ ATTR_ICONDIR = AttributeRegistry.registerAttribute(cls,a);\r
+ <span class="comment">// The browsable flag:\r
+</span> a = <span class="keyword">new</span> <span class="type">BooleanAttribute</span>("<span class="string">browsable</span>"\r
+ , <span class="reference">Boolean</span>.<span class="type">FALSE</span>\r
+ , Attribute.EDITABLE) ;\r
+ ATTR_BROWSABLE = AttributeRegistry.registerAttribute(cls, a) ;\r
+ <span class="comment">// The style sheet attribute:\r
+</span> a = <span class="keyword">new</span> <span class="type">StringAttribute</span>("<span class="string">style-sheet-link</span>"\r
+ , <span class="keyword">null</span>\r
+ , Attribute.EDITABLE) ;\r
+ ATTR_STYLE_LINK = AttributeRegistry.registerAttribute(cls, a) ;\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">DirectoryResource</span> <span class="variable-name">dresource</span> = <span class="keyword">null</span>;\r
+ <span class="preprocessor">protected</span> <span class="type">FileResource</span> <span class="variable-name">fresource</span> = <span class="keyword">null</span>;\r
+\r
+ <span class="reference">public</span> <span class="type">void</span> <span class="function-name">registerResource</span>(<span class="type">FramedResource</span> <span class="variable-name">resource</span>) {\r
+ <span class="reference">super</span>.registerResource(resource);\r
+ <span class="keyword">if</span> (resource <span class="keyword">instanceof</span> <span class="type">FileResource</span>)\r
+ fresource = (<span class="type">FileResource</span>) resource;\r
+ <span class="keyword">else</span> <span class="keyword">if</span> (resource <span class="keyword">instanceof</span> <span class="type">DirectoryResource</span>)\r
+ dresource = (<span class="type">DirectoryResource</span>) resource;\r
+ }\r
+\r
+ <span class="reference">public</span> <span class="type">FileResource</span> <span class="function-name">getFileResource</span>() {\r
+ <span class="keyword">return</span> fresource;\r
+ }\r
+\r
+ <span class="reference">public</span> <span class="type">DirectoryResource</span> <span class="function-name">getDirectoryResource</span>() {\r
+ <span class="keyword">return</span> dresource;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * use this one instead of registerResource if the resource type \r
+ * doesn't matter or if this is not a file or a directory resource.\r
+ * In subclasses you should have to do that:\r
+ * <pre>\r
+ * public void registerResource(FramedResource resource) {\r
+ * super.registerOtherResource(resource);\r
+ * }\r
+ * </pre>\r
+ * </span><span class="keyword">@param </span><span class="variable-name">the</span><span class="comment"> resource to register.\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">void</span> <span class="function-name">registerOtherResource</span>(<span class="type">FramedResource</span> <span class="variable-name">resource</span>) {\r
+ <span class="reference">super</span>.registerResource(resource);\r
+ dresource = <span class="keyword">null</span>;\r
+ fresource = <span class="keyword">null</span>;\r
+ }\r
+\r
+ <span class="comment">// The HTTPResource keeps a cache of ready to use Http values. This \r
+</span> <span class="comment">// allows to save converting to/from wire rep these objects. Not \r
+</span> <span class="comment">// much CPU time, but also memory is spared.\r
+</span> <span class="type">HttpMimeType</span> <span class="variable-name">contenttype</span> = <span class="keyword">null</span>;\r
+ <span class="type">HttpInteger</span> <span class="variable-name">contentlength</span> = <span class="keyword">null</span>;\r
+ <span class="type">HttpDate</span> <span class="variable-name">lastmodified</span> = <span class="keyword">null</span>;\r
+ <span class="type">HttpTokenList</span> <span class="variable-name">contentencoding</span> = <span class="keyword">null</span>;\r
+ <span class="type">HttpTokenList</span> <span class="variable-name">contentlanguage</span> = <span class="keyword">null</span>;\r
+\r
+ <span class="comment">// The Http entity tag for this resource (for FileResource only)\r
+</span> <span class="type">HttpEntityTag</span> <span class="variable-name">etag</span> = <span class="keyword">null</span>;\r
+ <span class="comment">// the MD5 digest for this resource (for FileResource only)\r
+</span> <span class="type">HttpString</span> <span class="variable-name">md5Digest</span> = <span class="keyword">null</span>;\r
+\r
+ <span class="comment">/**\r
+ * Get this resource's help url.\r
+ * </span><span class="keyword">@return </span><span class="comment">An URL, encoded as a String, or <strong>null</strong> if not\r
+ * available.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">String</span> <span class="function-name">getHelpURL</span>() {\r
+ httpd server = (httpd) getServer();\r
+ <span class="keyword">if</span> ( server == <span class="keyword">null</span> ) \r
+ <span class="keyword">return</span> <span class="keyword">null</span>;\r
+ <span class="type">String</span> <span class="variable-name">docurl</span> = server.getDocumentationURL();\r
+ <span class="keyword">if</span> ( docurl == <span class="keyword">null</span> )\r
+ <span class="keyword">return</span> <span class="keyword">null</span>;\r
+ <span class="keyword">return</span> docurl + "<span class="string">/</span>" + getClass().getName() + "<span class="string">.html</span>";\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Get the help URL for that resource's attribute.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">topic</span><span class="comment"> The topic (can be an attribute name, or a property, etc).\r
+ * </span><span class="keyword">@return </span><span class="comment">A String encoded URL, or <strong>null</strong>.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">String</span> <span class="function-name">getHelpURL</span>(<span class="type">String</span> <span class="variable-name">topic</span>) {\r
+ httpd server = (httpd) getServer();\r
+ <span class="keyword">if</span> ( server == <span class="keyword">null</span> ) \r
+ <span class="keyword">return</span> <span class="keyword">null</span>;\r
+ <span class="type">String</span> <span class="variable-name">docurl</span> = server.getDocumentationURL();\r
+ <span class="keyword">if</span> ( docurl == <span class="keyword">null</span> )\r
+ <span class="keyword">return</span> <span class="keyword">null</span>;\r
+ <span class="type">Class</span> <span class="variable-name">defines</span> = AttributeRegistry.getAttributeClass(getClass(), topic);\r
+ <span class="keyword">if</span> ( defines != <span class="keyword">null</span> ) \r
+ <span class="keyword">return</span> docurl + "<span class="string">/</span>" + defines.getName() + "<span class="string">.html</span>";\r
+ <span class="keyword">return</span> <span class="keyword">null</span>;\r
+ }\r
+\r
+ <span class="comment">/** \r
+ * give the md5 digest from cache or calculate it\r
+ * </span><span class="keyword">@return </span><span class="comment">the HttpString version of the digest\r
+ */</span>\r
+\r
+ <span class="string">private</span> <span class="type">HttpString</span> <span class="function-name">getMd5Digest</span>() {\r
+ <span class="keyword">if</span> (md5Digest != <span class="keyword">null</span>)\r
+ <span class="keyword">return</span> md5Digest;\r
+ <span class="comment">// not found, compute it if necessary!\r
+</span> <span class="type">Resource</span> <span class="variable-name">r</span> = getResource();\r
+ <span class="keyword">if</span> (r <span class="keyword">instanceof</span> <span class="type">FileResource</span>) {\r
+ <span class="keyword">try</span> {\r
+ <span class="type">Md5</span> <span class="variable-name">md5</span> = <span class="keyword">new</span> <span class="type">Md5</span> (\r
+ <span class="keyword">new</span> <span class="type">FileInputStream</span>(((<span class="type">FileResource</span>)r).getFile()));\r
+ <span class="type">String</span> <span class="variable-name">s</span> = <span class="keyword">null</span>;\r
+ <span class="keyword">try</span> {\r
+ <span class="type">byte</span> <span class="variable-name">b</span>[] = md5.getDigest();\r
+ <span class="type">Base64Encoder</span> <span class="variable-name">b64</span>;\r
+ <span class="type">ByteArrayOutputStream</span> <span class="variable-name">bos</span> = <span class="keyword">new</span> <span class="type">ByteArrayOutputStream</span>();\r
+ b64 = <span class="keyword">new</span> <span class="type">Base64Encoder</span>(<span class="keyword">new</span> <span class="type">ByteArrayInputStream</span>(b), bos);\r
+ b64.process();\r
+ s = bos.toString();\r
+ md5Digest = HttpFactory.makeString(s);\r
+ } <span class="keyword">catch</span> (<span class="type">Exception</span> <span class="variable-name">mdex</span>) {\r
+ <span class="comment">// error, set it to null\r
+</span> md5Digest = <span class="keyword">null</span>;\r
+ }\r
+ <span class="keyword">return</span> md5Digest;\r
+ } <span class="keyword">catch</span> (<span class="type">FileNotFoundException</span> <span class="variable-name">ex</span>) {\r
+ <span class="comment">// silent fail\r
+</span> md5Digest = <span class="keyword">null</span>;\r
+ }\r
+ }\r
+ <span class="keyword">return</span> <span class="keyword">null</span>;\r
+ }\r
+ \r
+ <span class="comment">/**\r
+ * Listen its resource.\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">void</span> <span class="function-name">attributeChanged</span>(<span class="type">AttributeChangedEvent</span> <span class="variable-name">evt</span>) {\r
+ <span class="reference">super</span>.attributeChanged(evt);\r
+ <span class="type">String</span> <span class="variable-name">name</span> = evt.getAttribute().getName();\r
+ <span class="keyword">if</span> (name.equals("<span class="string">file-stamp</span>")) {\r
+ etag = <span class="keyword">null</span>;\r
+ lastmodified = <span class="keyword">null</span>;\r
+ md5Digest = <span class="keyword">null</span>;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (name.equals("<span class="string">file-length</span>")) {\r
+ setValue(ATTR_CONTENT_LENGTH, evt.getNewValue());\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (name.equals("<span class="string">last-modified</span>")) {\r
+ setValue(ATTR_LAST_MODIFIED, evt.getNewValue());\r
+ } <span class="keyword">else</span> {\r
+ lastmodified = <span class="keyword">null</span>;\r
+ }\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Catch setValue, to maintain cached header values correctness.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">idx</span><span class="comment"> The index of the attribute to be set.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">value</span><span class="comment"> The new value for the attribute.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">synchronized</span> <span class="type">void</span> <span class="function-name">setValue</span>(<span class="type">int</span> <span class="variable-name">idx</span>, <span class="type">Object</span> <span class="variable-name">value</span>) {\r
+ <span class="reference">super</span>.setValue(idx, value);\r
+ <span class="keyword">if</span> (idx == ATTR_CONTENT_TYPE)\r
+ contenttype = <span class="keyword">null</span>;\r
+ <span class="keyword">if</span> (idx == ATTR_CONTENT_LENGTH)\r
+ contentlength = <span class="keyword">null</span>;\r
+ <span class="keyword">if</span> ( idx == ATTR_CONTENT_ENCODING )\r
+ contentencoding = <span class="keyword">null</span>;\r
+ <span class="keyword">if</span> ( idx == ATTR_CONTENT_LANGUAGE )\r
+ contentlanguage = <span class="keyword">null</span>;\r
+ <span class="keyword">if</span> ( idx == ATTR_PUTABLE) {\r
+ <span class="keyword">if</span> (fresource != <span class="keyword">null</span>) {\r
+ <span class="keyword">if</span> (value == Boolean.TRUE)\r
+ allowed = _put_allowed;\r
+ <span class="keyword">else</span>\r
+ allowed = _allowed;\r
+ }\r
+ }\r
+ <span class="keyword">if</span> (idx == ATTR_MD5) {\r
+ md5Digest = <span class="keyword">null</span>; <span class="comment">// reset the digest state\r
+</span> }\r
+ <span class="comment">// Any attribute setting modifies the last modified time:\r
+</span> lastmodified = <span class="keyword">null</span>;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Get the full URL for that resource.\r
+ * </span><span class="keyword">@return </span><span class="comment">An URL instance.\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">URL</span> <span class="function-name">getURL</span>(<span class="type">Request</span> <span class="variable-name">request</span>) {\r
+ <span class="keyword">try</span> {\r
+ <span class="keyword">return</span> <span class="keyword">new</span> <span class="type">URL</span>(request.getURL(), resource.getURLPath());\r
+ } <span class="keyword">catch</span> (<span class="type">MalformedURLException</span> <span class="variable-name">ex</span>) {\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">RuntimeException</span>("<span class="string">unable to build </span>"+\r
+ getURLPath()+\r
+ "<span class="string"> full URL, from server </span>"+\r
+ getServer().getURL());\r
+ }\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Get this resource quality.\r
+ * </span><span class="keyword">@return </span><span class="comment">The resource quality, or some negative value if not defined.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">double</span> <span class="function-name">getQuality</span>() {\r
+ <span class="keyword">return</span> getDouble(ATTR_QUALITY, -1.0) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Get this resource title.\r
+ * </span><span class="keyword">@return </span><span class="comment">This resource's title, or <strong>null</strong> if not \r
+ * defined.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">String</span> <span class="function-name">getTitle</span>() {\r
+ <span class="keyword">return</span> getString(ATTR_TITLE, <span class="keyword">null</span>) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Get this resource content language.\r
+ * Language are stored as a comma separated String of tokens.\r
+ * </span><span class="keyword">@return </span><span class="comment">A comma separated string of language tokens, or\r
+ * <strong>null</strong> if undefined.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">String</span> <span class="function-name">getContentLanguage</span>() {\r
+ <span class="keyword">return</span> (<span class="type">String</span>) getValue(ATTR_CONTENT_LANGUAGE, <span class="keyword">null</span>) ;\r
+ } \r
+\r
+ <span class="comment">/**\r
+ * Get this resource content encoding.\r
+ * The content encoding of a resource is stored as a comma separated\r
+ * list of tokens (as decribed in the Content_encoding header of the\r
+ * HTTP specification, and in the order they should appear in the header).\r
+ * </span><span class="keyword">@return </span><span class="comment">A string of comma separated encoding tokens, or\r
+ * <strong>null</strong> if not defined.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">String</span> <span class="function-name">getContentEncoding</span>() {\r
+ <span class="type">String</span> <span class="variable-name">def</span> = (<span class="type">String</span>) attributes[ATTR_CONTENT_ENCODING].getDefault();\r
+ System.out.println("<span class="string">Default [</span>"+def+"<span class="string">]</span>");\r
+ <span class="type">String</span> <span class="variable-name">s</span> = (<span class="type">String</span>) getString (ATTR_CONTENT_ENCODING, def) ;\r
+ System.out.println("<span class="string">Defaulted to [</span>"+s+"<span class="string">]</span>");\r
+\r
+ <span class="keyword">return</span> (<span class="type">String</span>) getString (ATTR_CONTENT_ENCODING, def) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Get this resource content type.\r
+ * </span><span class="keyword">@return </span><span class="comment">An instance of MIMEType, or <strong>null</strong> if not\r
+ * defined.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">MimeType</span> <span class="function-name">getContentType</span>() {\r
+ <span class="keyword">return</span> (<span class="type">MimeType</span>) getValue(ATTR_CONTENT_TYPE, <span class="keyword">null</span>);\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Get this resource content length.\r
+ * </span><span class="keyword">@return </span><span class="comment">The resource content length, or <strong>-1</strong> if not\r
+ * defined.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">int</span> <span class="function-name">getContentLength</span>() {\r
+ <span class="keyword">return</span> getInt(ATTR_CONTENT_LENGTH, -1) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Get this resource's icon.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">String</span> <span class="function-name">getIcon</span>() {\r
+ <span class="keyword">return</span> getString(ATTR_ICON, <span class="keyword">null</span>) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Get this resource's max age.\r
+ * The max age of a resource indicates how much drift is allowed between\r
+ * the physicall version of the resource, and any in-memory cached version\r
+ * of it.\r
+ * <p>The max age attribute is a long number giving the number of \r
+ * milliseconds of allowed drift.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">long</span> <span class="function-name">getMaxAge</span>() {\r
+ <span class="keyword">return</span> getLong(ATTR_MAXAGE, (<span class="type">long</span>) -1) ;\r
+ }\r
+\r
+ <span class="comment">//\r
+</span> <span class="comment">// Relative to FileResource ...\r
+</span> <span class="comment">//\r
+</span>\r
+ <span class="comment">/**\r
+ * Does this resource support byte ranges.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">boolean</span> <span class="variable-name">acceptRanges</span> = <span class="keyword">false</span>;\r
+\r
+ <span class="comment">/**\r
+ * Get the PUT'able flag (are we allow to PUT to the resource ?)\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">boolean</span> <span class="function-name">getPutableFlag</span>() {\r
+ <span class="keyword">return</span> getBoolean(ATTR_PUTABLE, <span class="keyword">false</span>) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Do we send the MD5 digest?\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">boolean</span> <span class="function-name">getMD5Flag</span>() {\r
+ <span class="keyword">return</span> getBoolean(ATTR_MD5, <span class="keyword">false</span>) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * handles a Range Request\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment">, the request\r
+ * </span><span class="keyword">@param </span><span class="variable-name">r</span><span class="comment">, the HttpRange\r
+ * </span><span class="keyword">@return </span><span class="comment">a Reply if range is valid, or null if there is a change in the\r
+ * resource, or if the HttpRange is not valid ( 4-2, for example).\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">handleRangeRequest</span>(<span class="type">Request</span> <span class="variable-name">request</span>, <span class="type">HttpRange</span> <span class="variable-name">r</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>\r
+ {\r
+ <span class="comment">// Should we check against a IfRange header ?\r
+</span> <span class="type">HttpEntityTag</span> <span class="variable-name">t</span> = request.getIfRange();\r
+\r
+ <span class="keyword">if</span> ( t != <span class="keyword">null</span> ) {\r
+ <span class="keyword">if</span> (t.isWeak() || ! t.getTag().equals(etag.getTag()))\r
+ <span class="keyword">return</span> <span class="keyword">null</span>;\r
+ }\r
+ <span class="comment">// Check the range:\r
+</span> <span class="type">int</span> <span class="variable-name">cl</span> = getContentLength();\r
+ <span class="type">int</span> <span class="variable-name">fb</span> = r.getFirstPosition();\r
+ <span class="type">int</span> <span class="variable-name">lb</span> = r.getLastPosition();\r
+ <span class="type">int</span> <span class="variable-name">sz</span>;\r
+\r
+ <span class="keyword">if</span> (fb > cl-1) { <span class="comment">// first byte already out of range\r
+</span> <span class="type">HttpContentRange</span> <span class="variable-name">cr</span> = HttpFactory.makeContentRange("<span class="string">bytes</span>", 0,\r
+ cl - 1, cl);\r
+ <span class="type">Reply</span> <span class="variable-name">rr</span>;\r
+ rr = createDefaultReply(request, \r
+ HTTP.REQUESTED_RANGE_NOT_SATISFIABLE);\r
+ rr.setContentLength(-1);\r
+ rr.setHeaderValue(rr.H_CONTENT_RANGE, cr);\r
+ <span class="keyword">if</span> (getMD5Flag()) \r
+ rr.setContentMD5(<span class="keyword">null</span>);\r
+ <span class="keyword">return</span> rr;\r
+ }\r
+\r
+ <span class="keyword">if</span> ((fb < 0) && (lb >= 0)) { <span class="comment">// ex: bytes=-20 final 20 bytes\r
+</span> <span class="keyword">if</span> (lb >= cl) <span class="comment">// cut the end\r
+</span> lb = cl;\r
+ sz = lb;\r
+ fb = cl - lb;\r
+ lb = cl - 1;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (lb < 0) { <span class="comment">// ex: bytes=10- the last size - 10\r
+</span> lb = cl-1;\r
+ sz = lb-fb+1;\r
+ } <span class="keyword">else</span> { <span class="comment">// ex: bytes=10-20\r
+</span> <span class="keyword">if</span> (lb >= cl) <span class="comment">// cut the end\r
+</span> lb = cl-1;\r
+ sz = lb-fb+1;\r
+ }\r
+ <span class="keyword">if</span> ((fb < 0) || (lb < 0) || (fb <= lb)) {\r
+ <span class="type">HttpContentRange</span> <span class="variable-name">cr</span> = <span class="keyword">null</span>;\r
+ fb = (fb < 0) ? 0 : fb;\r
+ lb = ((lb > cl) || (lb < 0)) ? cl : lb;\r
+ cr = HttpFactory.makeContentRange("<span class="string">bytes</span>", fb, lb, cl);\r
+ <span class="comment">// Emit reply:\r
+</span> <span class="type">Reply</span> <span class="variable-name">rr</span> = createDefaultReply(request, HTTP.PARTIAL_CONTENT);\r
+ <span class="comment">// FIXME check for MD5 of only the subpart\r
+</span> <span class="keyword">try</span> { <span class="comment">// create the MD5 for the subpart\r
+</span> <span class="keyword">if</span> (getMD5Flag()) {\r
+ <span class="type">String</span> <span class="variable-name">s</span> = <span class="keyword">null</span>;\r
+ <span class="keyword">try</span> {\r
+ <span class="type">ByteRangeOutputStream</span> <span class="variable-name">br</span>;\r
+ br = <span class="keyword">new</span> <span class="type">ByteRangeOutputStream</span>(fresource.getFile(),\r
+ fb, lb+1);\r
+ <span class="type">Md5</span> <span class="variable-name">md5</span> = <span class="keyword">new</span> <span class="type">Md5</span> (br);\r
+ <span class="type">byte</span> <span class="variable-name">b</span>[] = md5.getDigest();\r
+ <span class="type">Base64Encoder</span> <span class="variable-name">b64</span>;\r
+ <span class="type">ByteArrayOutputStream</span> <span class="variable-name">bs</span> = <span class="keyword">new</span> <span class="type">ByteArrayOutputStream</span>();\r
+ b64 = <span class="keyword">new</span> <span class="type">Base64Encoder</span>(<span class="keyword">new</span> <span class="type">ByteArrayInputStream</span>(b),\r
+ bs);\r
+ b64.process();\r
+ s = bs.toString();\r
+ } <span class="keyword">catch</span> (<span class="type">Exception</span> <span class="variable-name">md_ex</span>) {\r
+ <span class="comment">// default to null, no action here then\r
+</span> }\r
+ <span class="keyword">if</span> (s == <span class="keyword">null</span>)\r
+ rr.setContentMD5(<span class="keyword">null</span>); \r
+ <span class="keyword">else</span> \r
+ rr.setContentMD5(s);\r
+ }\r
+ rr.setContentLength(sz);\r
+ rr.setHeaderValue(rr.H_CONTENT_RANGE, cr);\r
+ rr.setStream(<span class="keyword">new</span> <span class="type">ByteRangeOutputStream</span>(fresource.getFile(),\r
+ fb,\r
+ lb+1));\r
+ <span class="keyword">return</span> rr;\r
+ } <span class="keyword">catch</span> (<span class="type">IOException</span> <span class="variable-name">ex</span>) {\r
+ }\r
+ } \r
+ <span class="keyword">return</span> <span class="keyword">null</span>;\r
+ }\r
+\r
+ <span class="comment">//\r
+</span> <span class="comment">// Relative to DirectoryResource ...\r
+</span> <span class="comment">//\r
+</span>\r
+ <span class="comment">/**\r
+ * Get this class browsable flag.\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">boolean</span> <span class="function-name">getBrowsableFlag</span>() {\r
+ <span class="keyword">return</span> getBoolean (ATTR_BROWSABLE, <span class="keyword">false</span>) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Get this frame style sheet link\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">String</span> <span class="function-name">getStyleSheetURL</span>() {\r
+ <span class="keyword">return</span> getString (ATTR_STYLE_LINK, <span class="keyword">null</span>);\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Our current (cached) directory listing.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">HtmlGenerator</span> <span class="variable-name">listing</span> = <span class="keyword">null</span> ;\r
+ <span class="comment">/**\r
+ * The time at which we generated the directory index.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">long</span> <span class="variable-name">listing_stamp</span> = -1 ;\r
+\r
+ <span class="string">private</span> <span class="type">String</span> <span class="function-name">getUnextendedName</span>(<span class="type">String</span> <span class="variable-name">name</span>) {\r
+ <span class="type">int</span> <span class="variable-name">strlen</span> = name.length() ;\r
+ <span class="keyword">for</span> (<span class="type">int</span> <span class="variable-name">i</span> = 0 ; i < strlen ; i++) {\r
+ <span class="comment">// FIXME: Should use the system props to get the right sep\r
+</span> <span class="keyword">if</span> ( name.charAt(i) == '<span class="string">.</span>' ) {\r
+ <span class="keyword">if</span> ( i == 0 )\r
+ <span class="keyword">return</span> <span class="keyword">null</span> ;\r
+ <span class="keyword">return</span> name.substring(0, i) ;\r
+ }\r
+ }\r
+ <span class="keyword">return</span> <span class="keyword">null</span> ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Get the optional icon directory.\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">String</span> <span class="function-name">getIconDirectory</span>() { \r
+ <span class="keyword">return</span> getString(ATTR_ICONDIR, "<span class="string">/icons</span>") ;\r
+ }\r
+\r
+\r
+\r
+ <span class="comment">/**\r
+ * Should we relocate invalid requests to this directory.\r
+ * </span><span class="keyword">@return </span><span class="comment">A boolean <strong>true</strong> if we should relocate.\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">boolean</span> <span class="function-name">getRelocateFlag</span>() {\r
+ <span class="keyword">return</span> getBoolean(ATTR_RELOCATE, <span class="keyword">true</span>) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Get the optinal index name for this directory listing.\r
+ * </span><span class="keyword">@return </span><span class="comment">The name of the resource responsible to list that container.\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">String</span> <span class="function-name">getIndex</span>() {\r
+ <span class="keyword">return</span> (<span class="type">String</span>) getValue(ATTR_INDEX, <span class="keyword">null</span>) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Add our own Style Sheet to the HtmlGenerator.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">g</span><span class="comment"> The HtmlGenerator.\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">void</span> <span class="function-name">addStyleSheet</span>(<span class="type">HtmlGenerator</span> <span class="variable-name">g</span>) {\r
+ <span class="comment">// Add style link\r
+</span> <span class="type">String</span> <span class="variable-name">css_url</span> = getStyleSheetURL();\r
+ <span class="keyword">if</span> (css_url != <span class="keyword">null</span>) {\r
+ g.addLink( <span class="keyword">new</span> <span class="type">HtmlLink</span>("<span class="string">STYLESHEET</span>", \r
+ css_url, \r
+ MimeType.TEXT_CSS));\r
+ }\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Reply with an HTML doc listing the resources of this directory.\r
+ * This function takes special care not to regenerate a directory listing\r
+ * when one is available. It also caches the date of the directory \r
+ * listing, so that it can win big with NOT_MODIFIED.\r
+ * <p>Using a modem, I know that each place I can reply with an \r
+ * NOT_MODIFIED, <strong>is</strong> a big win.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to handle.\r
+ * </span><span class="keyword">@exception </span><span class="type">ProtocolException</span><span class="comment"> If processsing the request failed.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">synchronized</span> <span class="type">Reply</span> <span class="function-name">getDirectoryListing</span>(<span class="type">Request</span> <span class="variable-name">request</span>)\r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="keyword">if</span> (dresource == <span class="keyword">null</span>) \r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">NotAProtocolException</span>("<span class="string">this frame is not attached to a </span>"+\r
+ "<span class="string">DirectoryResource. (</span>"+\r
+ resource.getIdentifier()+"<span class="string">)</span>");\r
+ <span class="comment">// delete us if the directory was deleted\r
+</span> <span class="keyword">if</span> (! dresource.getDirectory().exists()) {\r
+ <span class="comment">//delete us and emit an error\r
+</span> <span class="type">String</span> <span class="variable-name">msg</span> = dresource.getIdentifier()+\r
+ "<span class="string">: deleted, removing the DirectoryResource</span>";\r
+ getServer().errlog(dresource, msg);\r
+ <span class="keyword">try</span> {\r
+ dresource.delete();\r
+ } <span class="keyword">catch</span> (<span class="type">MultipleLockException</span> <span class="variable-name">ex</span>) {\r
+ }\r
+ <span class="comment">// Emit an error back:\r
+</span> <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_FOUND) ;\r
+ error.setContent ("<span class="string"><h1>Document not found</h1></span>"+\r
+ "<span class="string"><p>The document </span>"+\r
+ request.getURL()+\r
+ "<span class="string"> is indexed but not available.</span>"+\r
+ "<span class="string"><p>The server is misconfigured.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+ <span class="comment">// Have we already an up-to-date computed a listing ?\r
+</span> <span class="keyword">if</span> ((listing == <span class="keyword">null</span>) \r
+ || (dresource.getDirectory().lastModified() > listing_stamp)\r
+ || (dresource.getLastModified() > listing_stamp)\r
+ || (getLastModified() > listing_stamp)) {\r
+ \r
+ <span class="type">Class</span> <span class="variable-name">http_class</span> = <span class="keyword">null</span>;\r
+ <span class="keyword">try</span> {\r
+ http_class = Class.forName("<span class="string">org.w3c.jigsaw.frames.HTTPFrame</span>");\r
+ } <span class="keyword">catch</span> (<span class="type">ClassNotFoundException</span> <span class="variable-name">ex</span>) {\r
+ http_class = <span class="keyword">null</span>;\r
+ }\r
+\r
+ <span class="type">Enumeration</span> <span class="variable-name">enum</span> = \r
+ dresource.enumerateResourceIdentifiers() ;\r
+ <span class="type">Vector</span> <span class="variable-name">resources</span> = Sorter.sortStringEnumeration(enum) ;\r
+ <span class="type">HtmlGenerator</span> <span class="variable-name">g</span> = \r
+ <span class="keyword">new</span> <span class="type">HtmlGenerator</span>("<span class="string">Directory of </span>"+\r
+ dresource.getIdentifier());\r
+ <span class="comment">// Add style link\r
+</span> addStyleSheet(g);\r
+ g.append("<span class="string"><h1></span>"+dresource.getIdentifier()+"<span class="string"></h1></span>");\r
+ <span class="comment">// Link to the parent, when possible:\r
+</span> <span class="keyword">if</span> ( dresource.getParent() != <span class="keyword">null</span> )\r
+ g.append("<span class="string"><p><a href=\"..\">Parent</a><br></span>");\r
+ <span class="comment">// List the children:\r
+</span> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable-name">i</span> = 0 ; i < resources.size() ; i++) {\r
+ <span class="type">String</span> <span class="variable-name">name</span> = (<span class="type">String</span>) resources.elementAt(i);\r
+ <span class="type">ResourceReference</span> <span class="variable-name">rr</span> = <span class="keyword">null</span>;\r
+ rr = dresource.lookup(name);\r
+ <span class="type">FramedResource</span> <span class="variable-name">resource</span> = <span class="keyword">null</span>;\r
+ <span class="keyword">if</span> (rr != <span class="keyword">null</span>) {\r
+ <span class="keyword">try</span> {\r
+ resource = (<span class="type">FramedResource</span>) rr.lock();\r
+ <span class="type">HTTPFrame</span> <span class="variable-name">itsframe</span> = <span class="keyword">null</span>;\r
+ <span class="keyword">if</span> (http_class != <span class="keyword">null</span>)\r
+ itsframe = \r
+ (<span class="type">HTTPFrame</span>) resource.getFrame(http_class);\r
+ <span class="keyword">if</span> (itsframe != <span class="keyword">null</span>) {\r
+ <span class="comment">// Icon first, if available\r
+</span> <span class="type">String</span> <span class="variable-name">icon</span> = itsframe.getIcon() ;\r
+ <span class="keyword">if</span> ( icon != <span class="keyword">null</span> ) \r
+ g.append("<span class="string"><img src=\"</span>"+\r
+ getIconDirectory() +"<span class="string">/</span>" + icon+\r
+ "<span class="string">\"></span>");\r
+ <span class="comment">// Resource's name with link:\r
+</span> g.append("<span class="string"><a href=\"</span>" \r
+ , resource.getURLPath()\r
+ , "<span class="string">\"></span>"+name+"<span class="string"></a></span>");\r
+ <span class="comment">// resource's title, if any:\r
+</span> <span class="type">String</span> <span class="variable-name">title</span> = itsframe.getTitle();\r
+ <span class="keyword">if</span> ( title != <span class="keyword">null</span> )\r
+ g.append("<span class="string"> </span>"+title);\r
+ g.append("<span class="string"><br></span>");\r
+ } <span class="keyword">else</span> {\r
+ <span class="comment">// Resource's name with link:\r
+</span> g.append(name+"<span class="string"> (<i>Not available via HTTP.</i>)</span>");\r
+ g.append("<span class="string"><br></span>");\r
+ }\r
+ } <span class="keyword">catch</span> (<span class="type">InvalidResourceException</span> <span class="variable-name">ex</span>) {\r
+ g.append(name+\r
+ "<span class="string"> cannot be loaded (server misconfigured)</span>");\r
+ g.append("<span class="string"><br></span>");\r
+ <span class="keyword">continue</span>;\r
+ } <span class="keyword">finally</span> { \r
+ rr.unlock();\r
+ }\r
+ }\r
+ }\r
+ g.close() ;\r
+ listing_stamp = getLastModified() ;\r
+ listing = g ;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> ( checkIfModifiedSince(request) == COND_FAILED ) {\r
+ <span class="comment">// Is it an IMS request ?\r
+</span> <span class="type">Reply</span> <span class="variable-name">reply</span> = createDefaultReply(request, HTTP.NOT_MODIFIED) ;\r
+ reply.setContentMD5(<span class="keyword">null</span>);\r
+ <span class="keyword">return</span> reply;\r
+ }\r
+ <span class="comment">// New content or need update:\r
+</span> <span class="type">Reply</span> <span class="variable-name">reply</span> = createDefaultReply(request, HTTP.OK) ;\r
+ reply.setLastModified(listing_stamp) ;\r
+ reply.setStream(listing) ;\r
+ <span class="comment">// check MD5\r
+</span> <span class="keyword">return</span> reply ;\r
+ }\r
+\r
+ <span class="comment">//\r
+</span> <span class="comment">// Commom part.\r
+</span> <span class="comment">//\r
+</span>\r
+\r
+\r
+ <span class="comment">/**\r
+ * Update the cached headers value.\r
+ * Each resource maintains a set of cached values for headers, this\r
+ * allows for a nice sped-up in headers marshalling, which - as the \r
+ * complexity of the protocol increases - becomes a bottleneck.\r
+ */</span>\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">void</span> <span class="function-name">updateCachedHeaders</span>() {\r
+ <span class="comment">// Precompute a set of header values to keep by:\r
+</span> <span class="keyword">if</span> ( contenttype == <span class="keyword">null</span> )\r
+ contenttype = HttpFactory.makeMimeType(getContentType());\r
+ <span class="keyword">if</span> (contentlength == <span class="keyword">null</span>) {\r
+ <span class="type">int</span> <span class="variable-name">cl</span> = -1;\r
+ <span class="keyword">if</span> (fresource != <span class="keyword">null</span>) \r
+ cl = fresource.getFileLength();\r
+ <span class="keyword">if</span> ( cl >= 0 ) {\r
+ setValue(ATTR_CONTENT_LENGTH, <span class="keyword">new</span> <span class="type">Integer</span>(cl));\r
+ contentlength = HttpFactory.makeInteger(cl);\r
+ }\r
+ }\r
+ <span class="keyword">if</span> ( lastmodified == <span class="keyword">null</span> ) {\r
+ <span class="type">long</span> <span class="variable-name">lm</span> = getLastModified();\r
+ <span class="keyword">if</span> ( lm > 0 )\r
+ lastmodified = HttpFactory.makeDate(getLastModified());\r
+ }\r
+ <span class="keyword">if</span> (definesAttribute(ATTR_CONTENT_ENCODING) &&(contentencoding==<span class="keyword">null</span>))\r
+ contentencoding = HttpFactory.makeStringList(getContentEncoding());\r
+ <span class="keyword">if</span> (definesAttribute(ATTR_CONTENT_LANGUAGE) &&(contentlanguage==<span class="keyword">null</span>))\r
+ contentlanguage = HttpFactory.makeStringList(getContentLanguage());\r
+\r
+ <span class="keyword">if</span> (fresource != <span class="keyword">null</span>) {\r
+ <span class="comment">// We only take car eof etag here:\r
+</span> <span class="keyword">if</span> ( etag == <span class="keyword">null</span> ) {\r
+ <span class="type">long</span> <span class="variable-name">lstamp</span> = fresource.getFileStamp();\r
+ <span class="keyword">if</span> ( lstamp >= 0L ) {\r
+ <span class="type">String</span> <span class="variable-name">soid</span> = Integer.toString(getOid(), 32);\r
+ <span class="type">String</span> <span class="variable-name">stamp</span> = Long.toString(lstamp, 32);\r
+ etag = HttpFactory.makeETag(<span class="keyword">false</span>, soid+"<span class="string">:</span>"+stamp);\r
+ }\r
+ }\r
+ <span class="keyword">if</span> (getMD5Flag() && (md5Digest == <span class="keyword">null</span>)) {\r
+ getMd5Digest();\r
+ }\r
+ }\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Create a reply to answer to request on this file.\r
+ * This method will create a suitable reply (matching the given request)\r
+ * and will set all its default header values to the appropriate \r
+ * values.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to make a reply for.\r
+ * </span><span class="keyword">@return </span><span class="comment">An instance of Reply, suited to answer this request.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">createDefaultReply</span>(<span class="type">Request</span> <span class="variable-name">request</span>, <span class="type">int</span> <span class="variable-name">status</span>) {\r
+ <span class="type">Reply</span> <span class="variable-name">reply</span> = request.makeReply(status);\r
+ updateCachedHeaders();\r
+ <span class="keyword">if</span> ( status != HTTP.NOT_MODIFIED ) {\r
+ <span class="keyword">if</span> ( contentlength != <span class="keyword">null</span> )\r
+ reply.setHeaderValue(Reply.H_CONTENT_LENGTH, contentlength);\r
+ <span class="keyword">if</span> ( contenttype != <span class="keyword">null</span> )\r
+ reply.setHeaderValue(Reply.H_CONTENT_TYPE, contenttype);\r
+ <span class="keyword">if</span> ( lastmodified != <span class="keyword">null</span> )\r
+ reply.setHeaderValue(Reply.H_LAST_MODIFIED, lastmodified);\r
+ <span class="keyword">if</span> ( contentencoding != <span class="keyword">null</span> ) {\r
+System.out.println("<span class="string">Content Encoding [</span>" + contentencoding +"<span class="string">]</span>");\r
+ reply.setHeaderValue(Reply.H_CONTENT_ENCODING,contentencoding);\r
+ }\r
+ <span class="keyword">if</span> ( contentlanguage != <span class="keyword">null</span> )\r
+ reply.setHeaderValue(Reply.H_CONTENT_LANGUAGE,contentlanguage);\r
+ \r
+ }\r
+ <span class="type">long</span> <span class="variable-name">maxage</span> = getMaxAge();\r
+ <span class="keyword">if</span> ( maxage >= 0 ) {\r
+ <span class="keyword">if</span> (reply.getMajorVersion() >= 1 ) {\r
+ <span class="keyword">if</span> (reply.getMinorVersion() >= 1) {\r
+ reply.setMaxAge((<span class="type">int</span>) (maxage / 1000));\r
+ } \r
+ <span class="comment">// If max-age is zero, say what you mean:\r
+</span> <span class="type">long</span> <span class="variable-name">expires</span> = (System.currentTimeMillis()\r
+ + ((maxage == 0) ? -1000 : maxage));\r
+ reply.setExpires(expires);\r
+ }\r
+ }\r
+ <span class="comment">// Set the date of the reply (round it to secs):\r
+</span> reply.setDate((System.currentTimeMillis() / 1000L) * 1000L);\r
+ \r
+ <span class="keyword">if</span> (fresource != <span class="keyword">null</span>) {\r
+ <span class="comment">// Set the entity tag:\r
+</span> <span class="keyword">if</span> ( etag != <span class="keyword">null</span> )\r
+ reply.setHeaderValue(reply.H_ETAG, etag);\r
+ <span class="keyword">if</span> ( acceptRanges )\r
+ reply.setHeaderValue(reply.H_ACCEPT_RANGES, _accept_ranges);\r
+ <span class="keyword">if</span> ( getMD5Flag()) {\r
+ reply.setHeaderValue(reply.H_CONTENT_MD5, getMd5Digest());\r
+ }\r
+ }\r
+\r
+ <span class="keyword">return</span> reply;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Check the <code>If-Match</code> condition of that request.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to check.\r
+ * </span><span class="keyword">@return </span><span class="comment">An integer, either <code>COND_FAILED</cond> if condition\r
+ * was checked, but failed, <code>COND_OK</code> if condition was checked\r
+ * and succeeded, or <strong>0</strong> if the condition was not checked\r
+ * at all (eg because the resource or the request didn't support it).\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">int</span> <span class="function-name">checkIfMatch</span>(<span class="type">Request</span> <span class="variable-name">request</span>) {\r
+ <span class="keyword">if</span> (fresource != <span class="keyword">null</span>) {\r
+ <span class="type">HttpEntityTag</span> <span class="variable-name">tags</span>[] = request.getIfMatch();\r
+ <span class="keyword">if</span> ( tags != <span class="keyword">null</span> ) {\r
+ <span class="comment">// Good, real validators in use:\r
+</span> <span class="keyword">if</span> ( etag != <span class="keyword">null</span> ) {\r
+ <span class="comment">// Note: if etag is null this means that the resource has \r
+</span> <span class="comment">// changed and has not been even emited since then...\r
+</span> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable-name">i</span> = 0 ; i < tags.length ; i++) {\r
+ <span class="type">HttpEntityTag</span> <span class="variable-name">t</span> = tags[i];\r
+ <span class="keyword">if</span> ((!t.isWeak()) && t.getTag().equals(etag.getTag()))\r
+ <span class="keyword">return</span> COND_OK;\r
+ }\r
+ }\r
+ <span class="keyword">return</span> COND_FAILED;\r
+ }\r
+ }\r
+ <span class="keyword">return</span> 0;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Check the <code>If-None-Match</code> condition of that request.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to check.\r
+ * </span><span class="keyword">@return </span><span class="comment">An integer, either <code>COND_FAILED</cond> if condition\r
+ * was checked, but failed, <code>COND_OK</code> if condition was checked\r
+ * and succeeded, or <strong>0</strong> if the condition was not checked\r
+ * at all (eg because the resource or the request didn't support it).\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">int</span> <span class="function-name">checkIfNoneMatch</span>(<span class="type">Request</span> <span class="variable-name">request</span>) {\r
+ <span class="keyword">if</span> (fresource != <span class="keyword">null</span>) {\r
+ <span class="comment">// Check for an If-None-Match conditional:\r
+</span> <span class="type">HttpEntityTag</span> <span class="variable-name">tags</span>[] = request.getIfNoneMatch();\r
+ <span class="keyword">if</span> ( tags != <span class="keyword">null</span> ) {\r
+ <span class="keyword">if</span> ( etag == <span class="keyword">null</span> )\r
+ <span class="keyword">return</span> COND_OK;\r
+ <span class="keyword">for</span> (<span class="type">int</span> <span class="variable-name">i</span> = 0 ; i < tags.length ; i++) {\r
+ <span class="type">HttpEntityTag</span> <span class="variable-name">t</span> = tags[i];\r
+ <span class="keyword">if</span> (( ! t.isWeak()) && t.getTag().equals(etag.getTag()))\r
+ <span class="keyword">return</span> COND_FAILED;\r
+ }\r
+ <span class="keyword">return</span> COND_OK;\r
+ }\r
+ }\r
+ <span class="keyword">return</span> 0;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Check the <code>If-Modified-Since</code> condition of that request.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to check.\r
+ * </span><span class="keyword">@return </span><span class="comment">An integer, either <code>COND_FAILED</cond> if condition\r
+ * was checked, but failed, <code>COND_OK</code> if condition was checked\r
+ * and succeeded, or <strong>0</strong> if the condition was not checked\r
+ * at all (eg because the resource or the request didn't support it).\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">int</span> <span class="function-name">checkIfModifiedSince</span>(<span class="type">Request</span> <span class="variable-name">request</span>) {\r
+ <span class="comment">// Check for an If-Modified-Since conditional:\r
+</span> <span class="type">long</span> <span class="variable-name">ims</span> = request.getIfModifiedSince();\r
+ <span class="keyword">if</span> (dresource != <span class="keyword">null</span>) {\r
+ <span class="keyword">if</span> (ims >= 0) \r
+ <span class="keyword">return</span> (((listing_stamp > 0) && (listing_stamp - 1000 <= ims))\r
+ ? <span class="type">COND_FAILED</span>\r
+ : COND_OK);\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (fresource != <span class="keyword">null</span>) {\r
+ <span class="type">long</span> <span class="variable-name">cmt</span> = getLastModified();\r
+ <span class="keyword">if</span> ( ims >= 0 )\r
+ <span class="keyword">return</span> ((cmt > 0) && (cmt - 1000 <= ims)) \r
+ ? COND_FAILED : COND_OK;\r
+ }\r
+ <span class="keyword">return</span> 0;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Check the <code>If-Unmodified-Since</code> condition of that request.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to check.\r
+ * </span><span class="keyword">@return </span><span class="comment">An integer, either <code>COND_FAILED</cond> if condition\r
+ * was checked, but failed, <code>COND_OK</code> if condition was checked\r
+ * and succeeded, or <strong>0</strong> if the condition was not checked\r
+ * at all (eg because the resource or the request didn't support it).\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">int</span> <span class="function-name">checkIfUnmodifiedSince</span>(<span class="type">Request</span> <span class="variable-name">request</span>) {\r
+ <span class="keyword">if</span> (fresource != <span class="keyword">null</span>) {\r
+ <span class="comment">// Check for an If-Unmodified-Since conditional:\r
+</span> <span class="type">long</span> <span class="variable-name">iums</span> = request.getIfUnmodifiedSince();\r
+ <span class="type">long</span> <span class="variable-name">cmt</span> = getLastModified();\r
+ <span class="keyword">if</span> ( iums >= 0 ) \r
+ <span class="keyword">return</span> ((cmt > 0) && (cmt - 1000) >= iums) \r
+ ? COND_FAILED : COND_OK;\r
+ }\r
+ <span class="keyword">return</span> 0;\r
+ }\r
+\r
+ <span class="reference">public</span> <span class="type">boolean</span> <span class="function-name">lookup</span>(<span class="type">LookupState</span> <span class="variable-name">ls</span>, <span class="type">LookupResult</span> <span class="variable-name">lr</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>\r
+ {\r
+ <span class="type">RequestInterface</span> <span class="variable-name">req</span> = ls.getRequest(); \r
+ <span class="keyword">if</span> (! checkRequest(req)) \r
+ <span class="keyword">return</span> <span class="keyword">false</span>;\r
+ <span class="keyword">if</span> (lookupFilters(ls,lr))\r
+ <span class="keyword">return</span> <span class="keyword">true</span>;\r
+ <span class="keyword">return</span> lookupResource(ls,lr);\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">boolean</span> <span class="function-name">lookupResource</span>(<span class="type">LookupState</span> <span class="variable-name">ls</span>, <span class="type">LookupResult</span> <span class="variable-name">lr</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>\r
+ {\r
+ <span class="keyword">if</span> (fresource != <span class="keyword">null</span>) {\r
+ <span class="keyword">return</span> lookupFile(ls,lr);\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (dresource != <span class="keyword">null</span>) {\r
+ <span class="keyword">return</span> lookupDirectory(ls,lr);\r
+ } <span class="keyword">else</span> {\r
+ <span class="keyword">return</span> lookupOther(ls,lr);\r
+ }\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">boolean</span> <span class="function-name">lookupFilters</span>(<span class="type">LookupState</span> <span class="variable-name">ls</span>, <span class="type">LookupResult</span> <span class="variable-name">lr</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>\r
+ {\r
+ <span class="type">ResourceFilter</span> <span class="variable-name">filters</span>[] = getFilters();\r
+ <span class="keyword">if</span> ( filters != <span class="keyword">null</span> ) {\r
+ <span class="comment">// Mark filters, for them to be called at outgoing time:\r
+</span> lr.addFilters(filters);\r
+ <span class="comment">// Some clever filter around ?\r
+</span> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable-name">i</span> = 0 ; i < filters.length ; i++) {\r
+ <span class="keyword">if</span> ( filters[i] == <span class="keyword">null</span> )\r
+ <span class="keyword">continue</span>;\r
+ <span class="keyword">if</span> ( filters[i].lookup(ls, lr) )\r
+ <span class="keyword">return</span> <span class="keyword">true</span>;\r
+ }\r
+ }\r
+ <span class="keyword">return</span> <span class="keyword">false</span>;\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">boolean</span> <span class="function-name">lookupDirectory</span>(<span class="type">LookupState</span> <span class="variable-name">ls</span>, <span class="type">LookupResult</span> <span class="variable-name">lr</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>\r
+ {\r
+ <span class="comment">// Give a chance to our super-class to run its own lookup scheme:\r
+</span> <span class="comment">// do we have to create a resource (PUT) ?\r
+</span> <span class="keyword">if</span> ((ls.hasMoreComponents()) && getPutableFlag()) {\r
+ <span class="type">Request</span> <span class="variable-name">request</span> = (<span class="type">Request</span>) ls.getRequest() ;\r
+ <span class="keyword">if</span> ((request == <span class="keyword">null</span>) || request.getMethod().equals("<span class="string">PUT</span>")) {\r
+ <span class="comment">// We might well want to create a resource:\r
+</span> <span class="type">String</span> <span class="variable-name">name</span> = ls.peekNextComponent() ;\r
+ <span class="type">ResourceReference</span> <span class="variable-name">rr</span> = dresource.lookup(name);\r
+ <span class="keyword">if</span> ((rr == <span class="keyword">null</span>) && (dresource.getExtensibleFlag())) {\r
+ <span class="keyword">if</span> (ls.countRemainingComponents() == 1)\r
+ rr = dresource.createResource(name, request);\r
+ <span class="keyword">else</span>\r
+ rr = dresource.createDirectoryResource(name);\r
+ <span class="keyword">if</span> (rr == <span class="keyword">null</span>) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = \r
+ request.makeReply(HTTP.UNSUPPORTED_MEDIA_TYPE);\r
+ error.setContent(\r
+ "<span class="string">Failed to create resource </span>"+\r
+ name +"<span class="string"> : </span>"+\r
+ "<span class="string">Unable to create the appropriate file:</span>"+\r
+ request.getURLPath()+\r
+ "<span class="string"> this media type is not supported</span>");\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error);\r
+ }\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (rr == <span class="keyword">null</span>) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.FORBIDDEN) ;\r
+ error.setContent("<span class="string">You are not allowed to create resource </span>"+\r
+ name +"<span class="string"> : </span>"+\r
+ dresource.getIdentifier()+\r
+ "<span class="string"> is not extensible.</span>");\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error);\r
+ }\r
+ }\r
+ }\r
+ <span class="keyword">if</span> ( <span class="reference">super</span>.lookup(ls, lr) ) {\r
+ <span class="keyword">if</span> ( ! ls.isDirectory() && ! ls.isInternal() ) {\r
+ <span class="comment">// The directory lookup URL doesn't end with a slash:\r
+</span> <span class="type">Request</span> <span class="variable-name">request</span> = (<span class="type">Request</span>)ls.getRequest() ;\r
+ <span class="keyword">if</span> ( request == <span class="keyword">null</span> ) {\r
+ lr.setTarget(<span class="keyword">null</span>);\r
+ <span class="keyword">return</span> <span class="keyword">true</span>;\r
+ }\r
+ <span class="type">URL</span> <span class="variable-name">url</span> = <span class="keyword">null</span>;\r
+ <span class="keyword">try</span> {\r
+ url = (ls.hasRequest() \r
+ ? getURL(request)\r
+ : <span class="keyword">new</span> <span class="type">URL</span>(getServer().getURL(), \r
+ resource.getURLPath()));\r
+ } <span class="keyword">catch</span> (<span class="type">MalformedURLException</span> <span class="variable-name">ex</span>) {\r
+ getServer().errlog(<span class="reference">this</span>, "<span class="string">unable to build full URL.</span>");\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span>("<span class="string">Internal server error</span>");\r
+ }\r
+ <span class="type">String</span> <span class="variable-name">msg</span> = "<span class="string">Invalid requested URL: the directory resource </span>"+\r
+ "<span class="string"> you are trying to reach is available only through </span>"+\r
+ "<span class="string"> its full URL: <a href=\"</span>"+\r
+ url + "<span class="string">\"></span>" + url + "<span class="string"></a>.</span>";\r
+ <span class="keyword">if</span> ( getRelocateFlag() ) {\r
+ <span class="comment">// Emit an error (with reloc if allowed)\r
+</span> <span class="type">Reply</span> <span class="variable-name">reloc</span> = request.makeReply(HTTP.FOUND);\r
+ reloc.setContent(msg) ;\r
+ reloc.setLocation(url);\r
+ lr.setTarget(<span class="keyword">null</span>);\r
+ lr.setReply(reloc);\r
+ <span class="keyword">return</span> <span class="keyword">true</span>;\r
+ } <span class="keyword">else</span> {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_FOUND) ;\r
+ error.setContent(msg) ;\r
+ lr.setTarget(<span class="keyword">null</span>);\r
+ lr.setReply(error);\r
+ <span class="keyword">return</span> <span class="keyword">true</span>;\r
+ }\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> ( ! ls.isInternal() ) {\r
+ <span class="comment">// return the index file.\r
+</span> <span class="type">String</span> <span class="variable-name">index</span> = getIndex();\r
+ <span class="keyword">if</span> ( index != <span class="keyword">null</span> && index.length() > 0) {\r
+ <span class="type">DirectoryResource</span> <span class="variable-name">dir</span> = (<span class="type">DirectoryResource</span>) resource;\r
+ <span class="type">ResourceReference</span> <span class="variable-name">rr</span> = dir.lookup(index);\r
+ <span class="keyword">if</span> (rr != <span class="keyword">null</span>) {\r
+ <span class="keyword">try</span> {\r
+ <span class="type">FramedResource</span> <span class="variable-name">rindex</span> = (<span class="type">FramedResource</span>) rr.lock();\r
+ <span class="keyword">return</span> rindex.lookup(ls,lr);\r
+ } <span class="keyword">catch</span> (<span class="type">InvalidResourceException</span> <span class="variable-name">ex</span>) {\r
+ } <span class="keyword">finally</span> {\r
+ rr.unlock();\r
+ }\r
+ }\r
+ }\r
+ }\r
+ <span class="keyword">return</span> <span class="keyword">true</span>;\r
+ }\r
+ <span class="keyword">return</span> <span class="keyword">false</span>;\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">boolean</span> <span class="function-name">lookupFile</span>(<span class="type">LookupState</span> <span class="variable-name">ls</span>, <span class="type">LookupResult</span> <span class="variable-name">lr</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>\r
+ {\r
+ <span class="keyword">return</span> <span class="reference">super</span>.lookup(ls,lr);\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">boolean</span> <span class="function-name">lookupOther</span>(<span class="type">LookupState</span> <span class="variable-name">ls</span>, <span class="type">LookupResult</span> <span class="variable-name">lr</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>\r
+ {\r
+ <span class="keyword">return</span> <span class="reference">super</span>.lookup(ls,lr);\r
+ }\r
+\r
+ <span class="reference">public</span> <span class="type">boolean</span> <span class="function-name">checkRequest</span>(<span class="type">RequestInterface</span> <span class="variable-name">request</span>) {\r
+ <span class="keyword">return</span> ((request == <span class="keyword">null</span>) \r
+ ? <span class="keyword">true</span> \r
+ :(request <span class="keyword">instanceof</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">jigsaw</span>.<span class="reference">http</span>.<span class="type">Request</span>));\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">ReplyInterface</span> <span class="function-name">performFrames</span>(<span class="type">RequestInterface</span> <span class="variable-name">request</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="keyword">return</span> <span class="reference">super</span>.performFrames(request);\r
+ }\r
+\r
+ <span class="reference">public</span> <span class="type">ReplyInterface</span> <span class="function-name">perform</span>(<span class="type">RequestInterface</span> <span class="variable-name">req</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="type">ReplyInterface</span> <span class="variable-name">repi</span> = <span class="reference">super</span>.perform(req);\r
+ <span class="keyword">if</span> (repi != <span class="keyword">null</span>)\r
+ <span class="keyword">return</span> repi;\r
+\r
+ <span class="keyword">if</span> (! checkRequest(req))\r
+ <span class="keyword">return</span> <span class="keyword">null</span>;\r
+\r
+ <span class="type">Reply</span> <span class="variable-name">reply</span> = <span class="keyword">null</span>;\r
+ <span class="type">Request</span> <span class="variable-name">request</span> = (<span class="type">Request</span>) req;\r
+ <span class="type">String</span> <span class="variable-name">method</span> = request.getMethod () ;\r
+ <span class="comment">// Perform the request:\r
+</span> <span class="keyword">if</span> ( method.equals("<span class="string">GET</span>") ) {\r
+ reply = get(request) ;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> ( method.equals("<span class="string">HEAD</span>") ) {\r
+ reply = head(request) ;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> ( method.equals("<span class="string">POST</span>") ) {\r
+ reply = post(request) ;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> ( method.equals("<span class="string">PUT</span>") ) {\r
+ reply = put(request) ;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> ( method.equals("<span class="string">OPTIONS</span>") ) {\r
+ reply = options(request);\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> ( method.equals("<span class="string">DELETE</span>") ) {\r
+ reply = delete(request) ;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> ( method.equals("<span class="string">LINK</span>") ) {\r
+ reply = link(request) ;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> ( method.equals("<span class="string">UNLINK</span>") ) {\r
+ reply = unlink(request) ;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> ( method.equals("<span class="string">TRACE</span>") ) {\r
+ reply = trace(request) ;\r
+ } <span class="keyword">else</span> {\r
+ reply = extended(request) ;\r
+ }\r
+ <span class="keyword">return</span> reply;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * The default GET method.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to handle.\r
+ * </span><span class="keyword">@exception </span><span class="type">ProtocolException</span><span class="comment"> if processing the request failed.\r
+ * </span><span class="keyword">@exception </span><span class="type">NotAProtocolException</span><span class="comment"> If the client instance controling the\r
+ * request processing got a fatal error.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">get</span>(<span class="type">Request</span> <span class="variable-name">request</span>)\r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="keyword">if</span> (dresource != <span class="keyword">null</span>) {\r
+ <span class="comment">// we manage a DirectoryResource\r
+</span> <span class="keyword">return</span> getDirectoryResource(request) ;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (fresource != <span class="keyword">null</span>) {\r
+ <span class="comment">// we manage a FileResource\r
+</span> <span class="keyword">return</span> getFileResource(request);\r
+ } <span class="keyword">else</span> {\r
+ <span class="keyword">return</span> getOtherResource(request);\r
+ }\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">Reply</span> <span class="function-name">getOtherResource</span>(<span class="type">Request</span> <span class="variable-name">request</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="comment">// we don't manage this kind of resource\r
+</span> <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_IMPLEMENTED) ;\r
+ error.setContent("<span class="string">Method GET not implemented.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Create the reply relative to the given file.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> the incomming request.\r
+ * </span><span class="keyword">@return </span><span class="comment">A Reply instance\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">Reply</span> <span class="function-name">createFileReply</span>(<span class="type">Request</span> <span class="variable-name">request</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="type">File</span> <span class="variable-name">file</span> = fresource.getFile() ;\r
+ <span class="type">Reply</span> <span class="variable-name">reply</span> = <span class="keyword">null</span>;\r
+ <span class="comment">// Check for a range request:\r
+</span> <span class="type">HttpRange</span> <span class="variable-name">ranges</span>[] = request.getRange();\r
+ <span class="keyword">if</span> ((ranges != <span class="keyword">null</span>) && (ranges.length == 1)) {\r
+ <span class="type">Reply</span> <span class="variable-name">rangereply</span> = handleRangeRequest(request, ranges[0]);\r
+ <span class="keyword">if</span> ( rangereply != <span class="keyword">null</span> )\r
+ <span class="keyword">return</span> rangereply;\r
+ }\r
+ <span class="comment">// Default to full reply:\r
+</span> reply = createDefaultReply(request, HTTP.OK) ;\r
+ <span class="keyword">try</span> { \r
+ reply.setStream(<span class="keyword">new</span> <span class="type">FileInputStream</span>(file));\r
+ } <span class="keyword">catch</span> (<span class="type">IOException</span> <span class="variable-name">ex</span>) {\r
+ <span class="comment">// I hate to have to loose time in tries\r
+</span> }\r
+ <span class="keyword">return</span> reply ;\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">Reply</span> <span class="function-name">getFileResource</span>(<span class="type">Request</span> <span class="variable-name">request</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="keyword">if</span> (fresource == <span class="keyword">null</span>) \r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">NotAProtocolException</span>("<span class="string">this frame is not attached to a </span>"+\r
+ "<span class="string">FileResource. (</span>"+\r
+ resource.getIdentifier()+"<span class="string">)</span>");\r
+ <span class="type">Reply</span> <span class="variable-name">reply</span> = <span class="keyword">null</span>;\r
+ <span class="type">File</span> <span class="variable-name">file</span> = fresource.getFile() ;\r
+ fresource.checkContent();\r
+ updateCachedHeaders();\r
+ <span class="comment">// Check validators:\r
+</span> <span class="keyword">if</span> ( checkIfMatch(request) == COND_FAILED ) {\r
+ reply = request.makeReply(HTTP.PRECONDITION_FAILED);\r
+ reply.setContent("<span class="string">Pre-conditions failed.</span>");\r
+ reply.setContentMD5(<span class="keyword">null</span>);\r
+ <span class="keyword">return</span> reply;\r
+ }\r
+ <span class="keyword">if</span> ( checkIfNoneMatch(request) == COND_FAILED ) {\r
+ reply = createDefaultReply(request, HTTP.NOT_MODIFIED);\r
+ reply.setContentMD5(<span class="keyword">null</span>);\r
+ <span class="keyword">return</span> reply;\r
+ }\r
+ <span class="keyword">if</span> ( checkIfModifiedSince(request) == COND_FAILED ) {\r
+ reply = createDefaultReply(request, HTTP.NOT_MODIFIED);\r
+ reply.setContentMD5(<span class="keyword">null</span>);\r
+ <span class="keyword">return</span> reply;\r
+ }\r
+ <span class="keyword">if</span> ( checkIfUnmodifiedSince(request) == COND_FAILED ) {\r
+ reply = request.makeReply(HTTP.PRECONDITION_FAILED);\r
+ reply.setContent("<span class="string">Pre-conditions failed.</span>");\r
+ reply.setContentMD5(<span class="keyword">null</span>);\r
+ <span class="keyword">return</span> reply;\r
+ }\r
+ <span class="comment">// Does this file really exists, if so send it back\r
+</span> <span class="keyword">if</span> ( file.exists() ) {\r
+ <span class="keyword">return</span> createFileReply(request);\r
+ } <span class="keyword">else</span> {\r
+ <span class="comment">// Delete the resource if parent is extensible:\r
+</span> <span class="type">boolean</span> <span class="variable-name">extensible</span> = <span class="keyword">false</span>;\r
+ <span class="type">ResourceReference</span> <span class="variable-name">rr</span> = fresource.getParent();\r
+ <span class="type">ResourceReference</span> <span class="variable-name">rrtemp</span> = <span class="keyword">null</span>;\r
+ <span class="type">Resource</span> <span class="variable-name">p</span> = <span class="keyword">null</span>;\r
+ <span class="keyword">while</span> ( <span class="keyword">true</span> ) {\r
+ <span class="keyword">try</span> {\r
+ <span class="keyword">if</span> (rr == <span class="keyword">null</span>)\r
+ <span class="keyword">break</span>;\r
+ p = rr.lock();\r
+ <span class="keyword">if</span> (p <span class="keyword">instanceof</span> <span class="type">DirectoryResource</span>) {\r
+ extensible = \r
+ ((<span class="type">DirectoryResource</span>)p).getExtensibleFlag();\r
+ <span class="keyword">break</span>;\r
+ }\r
+ rrtemp = p.getParent();\r
+ } <span class="keyword">catch</span> (<span class="type">InvalidResourceException</span> <span class="variable-name">ex</span>) {\r
+ <span class="keyword">break</span>;\r
+ } <span class="keyword">finally</span> {\r
+ <span class="keyword">if</span> (rr != <span class="keyword">null</span>)\r
+ rr.unlock();\r
+ }\r
+ rr = rrtemp;\r
+ }\r
+ <span class="keyword">if</span> (extensible) {\r
+ <span class="comment">// The resource is indexed but has no file, emit an error\r
+</span> <span class="type">String</span> <span class="variable-name">msg</span> = fresource.getFile()+\r
+ "<span class="string">: deleted, removing the FileResource.</span>";\r
+ getServer().errlog(fresource, msg);\r
+ <span class="keyword">try</span> {\r
+ fresource.delete();\r
+ } <span class="keyword">catch</span> (<span class="type">MultipleLockException</span> <span class="variable-name">ex</span>) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_FOUND) ;\r
+ error.setContentMD5(<span class="keyword">null</span>); <span class="comment">// FIXME must compute it!\r
+</span> error.setContent ("<span class="string"><h1>Document not found</h1></span>"+\r
+ "<span class="string"><p>The document </span>"+\r
+ request.getURL()+\r
+ "<span class="string"> is indexed but not available.</span>"+\r
+ "<span class="string"><p></span>"+ex.getMessage()+\r
+ "<span class="string"><p>The server is misconfigured.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+ }\r
+ <span class="comment">// Emit an error back:\r
+</span> <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_FOUND) ;\r
+ error.setContentMD5(<span class="keyword">null</span>);\r
+ error.setContent ("<span class="string"><h1>Document not found</h1></span>"+\r
+ "<span class="string"><p>The document </span>"+\r
+ request.getURL()+\r
+ "<span class="string"> is indexed but not available.</span>"+\r
+ "<span class="string"><p>The server is misconfigured.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">Reply</span> <span class="function-name">getDirectoryResource</span>(<span class="type">Request</span> <span class="variable-name">request</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="keyword">return</span> getDirectoryListing(request) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * The default HEAD method replies does a GET and removes entity.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to handle.\r
+ * </span><span class="keyword">@exception </span><span class="type">ProtocolException</span><span class="comment"> Always thrown, to return a NOT_IMPLEMENTED\r
+ * error.\r
+ * </span><span class="keyword">@exception </span><span class="type">NotAProtocolException</span><span class="comment"> If the client instance controling the\r
+ * request processing got a fatal error.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">head</span>(<span class="type">Request</span> <span class="variable-name">request</span>)\r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="keyword">if</span> (dresource != <span class="keyword">null</span>) {\r
+ <span class="keyword">return</span> headDirectoryResource(request);\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (fresource != <span class="keyword">null</span>) {\r
+ <span class="keyword">return</span> headFileResource(request);\r
+ } <span class="keyword">else</span> {\r
+ <span class="keyword">return</span> headOtherResource(request);\r
+ }\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">Reply</span> <span class="function-name">headOtherResource</span>(<span class="type">Request</span> <span class="variable-name">request</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="type">Reply</span> <span class="variable-name">reply</span> = <span class="keyword">null</span>;\r
+ reply = getOtherResource(request) ;\r
+ reply.setStream((<span class="type">InputStream</span>) <span class="keyword">null</span>);\r
+ <span class="keyword">return</span> reply;\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">Reply</span> <span class="function-name">headDirectoryResource</span>(<span class="type">Request</span> <span class="variable-name">request</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="type">Reply</span> <span class="variable-name">reply</span> = <span class="keyword">null</span>;\r
+ reply = getDirectoryResource(request) ;\r
+ reply.setStream((<span class="type">InputStream</span>) <span class="keyword">null</span>);\r
+ <span class="keyword">return</span> reply;\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">Reply</span> <span class="function-name">headFileResource</span>(<span class="type">Request</span> <span class="variable-name">request</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="keyword">if</span> (fresource == <span class="keyword">null</span>) \r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">NotAProtocolException</span>("<span class="string">this frame is not attached to a </span>"+\r
+ "<span class="string">FileResource. (</span>"+\r
+ resource.getIdentifier()+"<span class="string">)</span>");\r
+ <span class="type">Reply</span> <span class="variable-name">reply</span> = <span class="keyword">null</span>;\r
+ fresource.checkContent();\r
+ updateCachedHeaders();\r
+ <span class="comment">// Conditional check:\r
+</span> <span class="keyword">if</span> ( checkIfMatch(request) == COND_FAILED ) {\r
+ <span class="type">Reply</span> <span class="variable-name">r</span> = request.makeReply(HTTP.PRECONDITION_FAILED);\r
+ r.setContent("<span class="string">Pre-conditions failed.</span>");\r
+ <span class="keyword">return</span> r;\r
+ }\r
+ <span class="keyword">if</span> ( checkIfNoneMatch(request) == COND_FAILED )\r
+ <span class="keyword">return</span> createDefaultReply(request, HTTP.NOT_MODIFIED);\r
+ <span class="keyword">if</span> ( checkIfModifiedSince(request) == COND_FAILED )\r
+ <span class="keyword">return</span> createDefaultReply(request, HTTP.NOT_MODIFIED);\r
+ <span class="keyword">if</span> ( checkIfUnmodifiedSince(request) == COND_FAILED ) {\r
+ <span class="type">Reply</span> <span class="variable-name">r</span> = request.makeReply(HTTP.PRECONDITION_FAILED);\r
+ r.setContent("<span class="string">Pre-conditions failed.</span>");\r
+ <span class="keyword">return</span> r;\r
+ }\r
+ <span class="keyword">if</span> (! fresource.getFile().exists()) {\r
+ <span class="comment">// Delete the resource if parent is extensible:\r
+</span> <span class="type">boolean</span> <span class="variable-name">extensible</span> = <span class="keyword">false</span>;\r
+ <span class="type">ResourceReference</span> <span class="variable-name">rr</span> = fresource.getParent();\r
+ <span class="type">ResourceReference</span> <span class="variable-name">rrtemp</span> = <span class="keyword">null</span>;\r
+ <span class="type">Resource</span> <span class="variable-name">p</span> = <span class="keyword">null</span>;\r
+ <span class="keyword">while</span> ( <span class="keyword">true</span> ) {\r
+ <span class="keyword">try</span> {\r
+ <span class="keyword">if</span> (rr == <span class="keyword">null</span>)\r
+ <span class="keyword">break</span>;\r
+ p = rr.lock();\r
+ <span class="keyword">if</span> (p <span class="keyword">instanceof</span> <span class="type">DirectoryResource</span>)\r
+ extensible = \r
+ ((<span class="type">DirectoryResource</span>)p).getExtensibleFlag();\r
+ rrtemp = p.getParent();\r
+ } <span class="keyword">catch</span> (<span class="type">InvalidResourceException</span> <span class="variable-name">ex</span>) {\r
+ <span class="keyword">break</span>;\r
+ } <span class="keyword">finally</span> {\r
+ <span class="keyword">if</span> (rr != <span class="keyword">null</span>)\r
+ rr.unlock();\r
+ }\r
+ rr = rrtemp;\r
+ }\r
+ <span class="keyword">if</span> (extensible) {\r
+ <span class="comment">// The resource is indexed but has no file, emit an error\r
+</span> <span class="type">String</span> <span class="variable-name">msg</span> = fresource.getFile()+\r
+ "<span class="string">: deleted, removing the FileResource.</span>";\r
+ getServer().errlog(fresource, msg);\r
+ <span class="keyword">try</span> {\r
+ fresource.delete();\r
+ } <span class="keyword">catch</span> (<span class="type">MultipleLockException</span> <span class="variable-name">ex</span>) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_FOUND) ;\r
+ error.setContent ("<span class="string"><h1>Document not found</h1></span>"+\r
+ "<span class="string"><p>The document </span>"+\r
+ request.getURL()+\r
+ "<span class="string"> is indexed but not available.</span>"+\r
+ "<span class="string"><p></span>"+ex.getMessage()+\r
+ "<span class="string"><p>The server is misconfigured.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+ }\r
+ <span class="comment">// Emit an error back:\r
+</span> <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_FOUND) ;\r
+ error.setContent ("<span class="string"><h1>Document not found</h1></span>"+\r
+ "<span class="string"><p>The document </span>"+\r
+ request.getURL()+\r
+ "<span class="string"> is indexed but not available.</span>"+\r
+ "<span class="string"><p>The server is misconfigured.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+ <span class="keyword">return</span> createDefaultReply(request, HTTP.OK);\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * The default POST method replies with a not implemented.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to handle.\r
+ * </span><span class="keyword">@exception </span><span class="type">ProtocolException</span><span class="comment"> Always thrown, to return a NOT_IMPLEMENTED\r
+ * error.\r
+ * </span><span class="keyword">@exception </span><span class="type">NotAProtocolException</span><span class="comment"> If the client instance controling the\r
+ * request processing got a fatal error.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">post</span>(<span class="type">Request</span> <span class="variable-name">request</span>)\r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_ALLOWED) ;\r
+ <span class="keyword">if</span> ( allowed != <span class="keyword">null</span> )\r
+ error.setHeaderValue(Reply.H_ALLOW, allowed);\r
+ error.setContent("<span class="string">Method POST not allowed on this resource.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * The default PUT method replies with a not implemented.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to handle.\r
+ * </span><span class="keyword">@exception </span><span class="type">ProtocolException</span><span class="comment"> Always thrown, to return a NOT_IMPLEMENTED\r
+ * error.\r
+ * </span><span class="keyword">@exception </span><span class="type">NotAProtocolException</span><span class="comment"> If the client instance controling the\r
+ * request processing got a fatal error.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">put</span>(<span class="type">Request</span> <span class="variable-name">request</span>)\r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="keyword">if</span> (fresource != <span class="keyword">null</span>) {\r
+ <span class="keyword">return</span> putFileResource(request);\r
+ } <span class="keyword">else</span> {\r
+ <span class="keyword">return</span> putOtherResource(request);\r
+ }\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">Reply</span> <span class="function-name">putOtherResource</span>(<span class="type">Request</span> <span class="variable-name">request</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>\r
+ {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_IMPLEMENTED) ;\r
+ error.setContent("<span class="string">Method PUT not implemented.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">Reply</span> <span class="function-name">putFileResource</span>(<span class="type">Request</span> <span class="variable-name">request</span>)\r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="type">Reply</span> <span class="variable-name">reply</span> = <span class="keyword">null</span>;\r
+ <span class="type">int</span> <span class="variable-name">status</span> = HTTP.OK;\r
+ fresource.checkContent();\r
+ updateCachedHeaders();\r
+ <span class="comment">// Is this resource writable ?\r
+</span> <span class="keyword">if</span> ( ! getPutableFlag() ) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_ALLOWED) ;\r
+ error.setContent("<span class="string">Method PUT not allowed.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+ <span class="comment">// Check validators:\r
+</span> <span class="keyword">if</span> ((checkIfMatch(request) == COND_FAILED)\r
+ || (checkIfNoneMatch(request) == COND_FAILED)\r
+ || (checkIfModifiedSince(request) == COND_FAILED)\r
+ || (checkIfUnmodifiedSince(request) == COND_FAILED)) {\r
+ <span class="type">Reply</span> <span class="variable-name">r</span> = request.makeReply(HTTP.PRECONDITION_FAILED);\r
+ r.setContent("<span class="string">Pre-condition failed.</span>");\r
+ <span class="keyword">return</span> r;\r
+ }\r
+ <span class="comment">// Check the request:\r
+</span> <span class="type">InputStream</span> <span class="variable-name">in</span> = <span class="keyword">null</span>;\r
+ <span class="keyword">try</span> {\r
+ in = request.getInputStream();\r
+ <span class="keyword">if</span> ( in == <span class="keyword">null</span> ) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.BAD_REQUEST) ;\r
+ error.setContent ("<span class="string"><p>Request doesn't have a valid content.</span>");\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+ } <span class="keyword">catch</span> (<span class="type">IOException</span> <span class="variable-name">ex</span>) {\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">ClientException</span>(request.getClient(), ex);\r
+ }\r
+ <span class="comment">// We do not support (for the time being) put with ranges:\r
+</span> <span class="keyword">if</span> ( request.hasContentRange() ) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.BAD_REQUEST);\r
+ error.setContent("<span class="string">partial PUT not supported.</span>");\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span>(error);\r
+ }\r
+ <span class="comment">// Check that if some type is provided it doesn't conflict:\r
+</span> <span class="keyword">if</span> ( request.hasContentType() ) {\r
+ <span class="type">MimeType</span> <span class="variable-name">rtype</span> = request.getContentType() ;\r
+ <span class="type">MimeType</span> <span class="variable-name">type</span> = getContentType() ;\r
+ <span class="keyword">if</span> ( type == <span class="keyword">null</span> ) {\r
+ setValue (ATTR_CONTENT_TYPE, rtype) ;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> ( rtype.match (type) < 0 ) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.UNSUPPORTED_MEDIA_TYPE) ;\r
+ error.setContent ("<span class="string"><p>Invalid content type: </span>"+type.toString());\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+ }\r
+ <span class="comment">// Write the body back to the file:\r
+</span> <span class="keyword">try</span> {\r
+ <span class="comment">// We are about to accept the put, notify client before continuing\r
+</span> <span class="type">Client</span> <span class="variable-name">client</span> = request.getClient();\r
+ <span class="keyword">if</span> ( client != <span class="keyword">null</span> && request.getExpect() != <span class="keyword">null</span> ) {\r
+ client.sendContinue();\r
+ }\r
+ <span class="keyword">if</span> ( fresource.newContent(request.getInputStream()) )\r
+ status = HTTP.CREATED;\r
+ <span class="keyword">else</span>\r
+ status = HTTP.NO_CONTENT;\r
+ } <span class="keyword">catch</span> (<span class="type">IOException</span> <span class="variable-name">ex</span>) {\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">ClientException</span>(request.getClient(), ex);\r
+ }\r
+ <span class="keyword">if</span> ( status == HTTP.CREATED ) {\r
+ reply = request.makeReply(status);\r
+ reply.setLocation(getURL(request));\r
+ reply.setContent ("<span class="string"><p>Entity body saved succesfully !</span>") ;\r
+ } <span class="keyword">else</span> {\r
+ reply = createDefaultReply(request, status);\r
+ }\r
+ <span class="keyword">return</span> reply ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * The default OPTIONS method replies with a not implemented.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to handle.\r
+ * </span><span class="keyword">@exception </span><span class="type">ProtocolException</span><span class="comment"> In case of errors.\r
+ * </span><span class="keyword">@exception </span><span class="type">NotAProtocolException</span><span class="comment"> If the client instance controling the\r
+ * request processing got a fatal error.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">options</span>(<span class="type">Request</span> <span class="variable-name">request</span>)\r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="type">Reply</span> <span class="variable-name">reply</span> = createDefaultReply(request, HTTP.OK);\r
+ <span class="comment">// Removed unused headers:\r
+</span> reply.setContentLength(-1);\r
+ reply.setContentType(<span class="keyword">null</span>);\r
+ <span class="comment">// Add the allow header:\r
+</span> <span class="keyword">if</span> ( allowed != <span class="keyword">null</span> )\r
+ reply.setHeaderValue(Reply.H_ALLOW, allowed);\r
+ <span class="keyword">return</span> reply;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * The default DELETE method replies with a not implemented.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to handle.\r
+ * </span><span class="keyword">@exception </span><span class="type">ProtocolException</span><span class="comment"> Always thrown, to return a NOT_IMPLEMENTED\r
+ * error.\r
+ * </span><span class="keyword">@exception </span><span class="type">NotAProtocolException</span><span class="comment"> If the client instance controling the\r
+ * request processing got a fatal error.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">delete</span>(<span class="type">Request</span> <span class="variable-name">request</span>)\r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_IMPLEMENTED) ;\r
+ error.setContent("<span class="string">Method DELETE not implemented.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * The default LINK method replies with a not implemented.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to handle.\r
+ * </span><span class="keyword">@exception </span><span class="type">ProtocolException</span><span class="comment"> Always thrown, to return a NOT_IMPLEMENTED\r
+ * error.\r
+ * </span><span class="keyword">@exception </span><span class="type">NotAProtocolException</span><span class="comment"> If the client instance controling the\r
+ * request processing got a fatal error.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">link</span>(<span class="type">Request</span> <span class="variable-name">request</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_IMPLEMENTED) ;\r
+ error.setContent("<span class="string">Method LINK not implemented.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * The default UNLINK method replies with a not implemented.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to handle.\r
+ * </span><span class="keyword">@exception </span><span class="type">ProtocolException</span><span class="comment"> Always thrown, to return a NOT_IMPLEMENTED\r
+ * error.\r
+ * </span><span class="keyword">@exception </span><span class="type">NotAProtocolException</span><span class="comment"> If the client instance controling the\r
+ * request processing got a fatal error.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">unlink</span>(<span class="type">Request</span> <span class="variable-name">request</span>)\r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_IMPLEMENTED) ;\r
+ error.setContent("<span class="string">Method UNLINK not implemented.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * The default TRACE method replies with a not implemented\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to handle.\r
+ * </span><span class="keyword">@exception </span><span class="type">HTTPException</span><span class="comment"> In case of errors.\r
+ * </span><span class="keyword">@exception </span><span class="type">ClientException</span><span class="comment"> If the client instance controling the\r
+ * request processing got a fatal error.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">trace</span>(<span class="type">Request</span> <span class="variable-name">request</span>)\r
+ <span class="keyword">throws</span> <span class="type">HTTPException</span>, <span class="type">ClientException</span>\r
+ {\r
+ <span class="type">Reply</span> <span class="variable-name">reply</span> = createDefaultReply(request, HTTP.OK);\r
+ reply.setNoCache(); <span class="comment">// don't cache this\r
+</span> reply.setMaxAge(-1); <span class="comment">// \r
+</span> reply.setContentMD5(<span class="keyword">null</span>);\r
+ <span class="comment">// Dump the request as the body\r
+</span> <span class="comment">// Removed unused headers:\r
+</span> <span class="comment">// FIXME should be something else for chuncked stream\r
+</span> <span class="type">ByteArrayOutputStream</span> <span class="variable-name">ba</span> = <span class="keyword">new</span> <span class="type">ByteArrayOutputStream</span>();\r
+ <span class="keyword">try</span> {\r
+ reply.setContentType(<span class="keyword">new</span> <span class="type">MimeType</span>("<span class="string">message/http</span>"));\r
+ request.dump(ba);\r
+ reply.setContentLength(ba.size());\r
+ } <span class="keyword">catch</span> (<span class="type">Exception</span> <span class="variable-name">ex</span>) {\r
+ ex.printStackTrace();\r
+ }\r
+ reply.setStream(<span class="keyword">new</span> <span class="type">ByteArrayInputStream</span>(ba.toByteArray()));\r
+ <span class="keyword">return</span> reply;\r
+ }\r
+ \r
+ <span class="comment">/**\r
+ * The handler for unknown method replies with a not implemented.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to handle.\r
+ * </span><span class="keyword">@exception </span><span class="type">ProtocolException</span><span class="comment"> Always thrown, to return a NOT_IMPLEMENTED\r
+ * error.\r
+ * </span><span class="keyword">@exception </span><span class="type">NotAProtocolException</span><span class="comment"> If the client instance controling the\r
+ * request processing got a fatal error.\r
+ */</span>\r
+\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">extended</span>(<span class="type">Request</span> <span class="variable-name">request</span>)\r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="type">String</span> <span class="variable-name">method</span> = request.getMethod() ;\r
+ <span class="keyword">if</span> ((method != <span class="keyword">null</span>) && method.equals("<span class="string">BROWSE</span>") && getBrowsableFlag())\r
+ <span class="keyword">return</span> browse(request) ;\r
+\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_IMPLEMENTED) ;\r
+ error.setContent("<span class="string">Method </span>"+method+"<span class="string"> not implemented.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Handle the browse method.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to handle.\r
+ */</span>\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">MimeType</span> <span class="variable-name">browsetype</span> = <span class="keyword">null</span>;\r
+\r
+ <span class="preprocessor">protected</span> <span class="type">synchronized</span> <span class="type">MimeType</span> <span class="function-name">getBrowseType</span>() {\r
+ <span class="keyword">if</span> ( browsetype == <span class="keyword">null</span> ) {\r
+ <span class="keyword">try</span> {\r
+ browsetype = <span class="keyword">new</span> <span class="type">MimeType</span>("<span class="string">application/x-navibrowse</span>");\r
+ } <span class="keyword">catch</span> (<span class="type">Exception</span> <span class="variable-name">ex</span>) {\r
+ ex.printStackTrace();\r
+ }\r
+ }\r
+ <span class="keyword">return</span> browsetype;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * A present to GNNPress users !\r
+ * This method implements the <code>BROWSE</code> method that\r
+ * AOL press (or GNN press, or whatever its last name is) expects.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to process.\r
+ * </span><span class="keyword">@exception </span><span class="type">ProtocolException</span><span class="comment"> If some error occurs.\r
+ * </span><span class="keyword">@return </span><span class="comment">A Reply instance.\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">browse</span> (<span class="type">Request</span> <span class="variable-name">request</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>\r
+ {\r
+ <span class="keyword">if</span> (dresource == <span class="keyword">null</span>) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.NOT_IMPLEMENTED) ;\r
+ error.setContent("<span class="string">Method </span>"+request.getMethod()+\r
+ "<span class="string"> not implemented.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+\r
+ <span class="type">Enumeration</span> <span class="variable-name">enum</span> = dresource.enumerateResourceIdentifiers() ;\r
+ <span class="type">Vector</span> <span class="variable-name">resources</span> = Sorter.sortStringEnumeration(enum) ;\r
+ <span class="type">int</span> <span class="variable-name">rsize</span> = ((resources == <span class="keyword">null</span>) ? 0 : resources.size()) ;\r
+ <span class="type">StringBuffer</span> <span class="variable-name">sb</span> = <span class="keyword">new</span> <span class="type">StringBuffer</span>() ;\r
+\r
+ <span class="comment">// As we have enumerated all resources, just looking the store is ok\r
+</span> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable-name">i</span> = 0 ; i < rsize ; i++) {\r
+ <span class="type">String</span> <span class="variable-name">rname</span> = (<span class="type">String</span>) resources.elementAt(i) ;\r
+ <span class="type">ResourceReference</span> <span class="variable-name">rr</span> = <span class="keyword">null</span>;\r
+ <span class="type">Resource</span> <span class="variable-name">r</span> = <span class="keyword">null</span>;\r
+ <span class="keyword">try</span> {\r
+ rr = dresource.lookup(rname) ;\r
+ r = rr.lock();\r
+ <span class="comment">// may throw InvalidResourceException\r
+</span>\r
+ <span class="keyword">if</span> ( r <span class="keyword">instanceof</span> <span class="type">DirectoryResource</span> ) {\r
+ sb.append("<span class="string">application/x-navidir </span>"+\r
+ rname+\r
+ "<span class="string">\r\n</span>") ;\r
+ } <span class="keyword">else</span> {\r
+ <span class="type">HTTPFrame</span> <span class="variable-name">itsframe</span> = \r
+ (<span class="type">HTTPFrame</span>) resource.getFrame(getClass());\r
+ <span class="keyword">if</span> (itsframe != <span class="keyword">null</span>) {\r
+ sb.append(itsframe.getContentType().toString()+\r
+ "<span class="string"> </span>"+\r
+ rname+\r
+ "<span class="string">\r\n</span>") ;\r
+ }\r
+ }\r
+ } <span class="keyword">catch</span> (<span class="type">InvalidResourceException</span> <span class="variable-name">ex</span>) {\r
+ <span class="keyword">continue</span>;\r
+ } <span class="keyword">finally</span> {\r
+ rr.unlock();\r
+ }\r
+ }\r
+ <span class="type">Reply</span> <span class="variable-name">reply</span> = request.makeReply(HTTP.OK) ;\r
+ reply.addPragma("<span class="string">no-cache</span>");\r
+ reply.setNoCache();\r
+ reply.setContent(sb.toString()) ;\r
+ reply.setContentType(getBrowseType());\r
+ <span class="keyword">return</span> reply ;\r
+ }\r
+\r
+ <span class="comment">//\r
+</span> <span class="comment">// Filtered part\r
+</span> <span class="comment">//\r
+</span>\r
+ <span class="comment">/**\r
+ * Get our whole list of filters.\r
+ */</span>\r
+ \r
+ <span class="reference">public</span> <span class="type">synchronized</span> <span class="type">ResourceFilter</span>[] <span class="function-name">getFilters</span>() {\r
+ <span class="type">ResourceFrame</span> <span class="variable-name">frames</span>[] = collectFrames(filterClass);\r
+ <span class="keyword">if</span> ( frames != <span class="keyword">null</span> ) {\r
+ <span class="comment">// FIXME Normally a simple cast should suffice (?)\r
+</span> <span class="type">ResourceFilter</span> <span class="variable-name">f</span>[] = <span class="keyword">new</span> <span class="type">ResourceFilter</span>[frames.length];\r
+ <span class="keyword">for</span> (<span class="type">int</span> <span class="variable-name">i</span> = 0 ; i < frames.length ; i++)\r
+ f[i] = (<span class="type">ResourceFilter</span>) frames[i];\r
+ <span class="keyword">return</span> f;\r
+ }\r
+ <span class="keyword">return</span> <span class="keyword">null</span>;\r
+ }\r
+ \r
+ <span class="comment">/**\r
+ * Get the list of filters of this class.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">cls</span><span class="comment"> The class of filters requested.\r
+ * </span><span class="keyword">@return </span><span class="comment">An array of filters, which are instances of the given class.\r
+ */</span>\r
+ \r
+ <span class="reference">public</span> <span class="type">synchronized</span> <span class="type">ResourceFilter</span>[] <span class="function-name">getFilters</span>(<span class="type">Class</span> <span class="variable-name">cls</span>) {\r
+ <span class="type">ResourceFrame</span> <span class="variable-name">frames</span>[] = collectFrames(cls);\r
+ <span class="keyword">if</span> ( frames != <span class="keyword">null</span> ) {\r
+ <span class="comment">// FIXME Normally a simple cast should suffice (?)\r
+</span> <span class="type">ResourceFilter</span> <span class="variable-name">f</span>[] = <span class="keyword">new</span> <span class="type">ResourceFilter</span>[frames.length];\r
+ <span class="keyword">for</span> (<span class="type">int</span> <span class="variable-name">i</span> = 0 ; i < frames.length ; i++)\r
+ f[i] = (<span class="type">ResourceFilter</span>) frames[i];\r
+ <span class="keyword">return</span> f;\r
+ }\r
+ <span class="keyword">return</span> <span class="keyword">null</span>;\r
+ }\r
+\r
+}\r
+\r
+ </pre>\r
+ </body>\r
+</html>\r