📄 httpframe.java
字号:
} /** * Get the optional index name array for this directory listing. * @return The index name array (including the main index) * @see #getIndex */ public String[] getIndexes() { String mainIndex = getIndex(); if (mainIndex != null) { String indexes[] = (String[]) getValue(ATTR_INDEXES, null); if (indexes != null) { int len = indexes.length + 1; String mergeIndex[] = new String[len]; mergeIndex[0] = mainIndex; System.arraycopy(indexes, 0, mergeIndex, 1, len-1); return mergeIndex; } else { indexes = new String[1]; indexes[0] = mainIndex; return indexes; } } else { return (String[]) getValue(ATTR_INDEXES, null) ; } } /** * Add our own Style Sheet to the HtmlGenerator. * @param g The HtmlGenerator. */ public void addStyleSheet(HtmlGenerator g) { // Add style link String css_url = getStyleSheetURL(); if (css_url != null) { g.addLink( new HtmlLink("STYLESHEET", css_url)); } } /** * Get ContainerResource listing * @param refresh should we refresh the listing? * @return a boolean (true if refreshed) */ public boolean computeContainerListing(boolean refresh) { ContainerResource cresource = (ContainerResource)resource; synchronized (cresource) { if ((refresh) || (listing == null) || (cresource.getLastModified() > listing_stamp) || (getLastModified() > listing_stamp)) { Class http_class = null; try { http_class = Class.forName("org.w3c.jigsaw.frames.HTTPFrame"); } catch (ClassNotFoundException ex) { http_class = null; } Enumeration enum = cresource.enumerateResourceIdentifiers(); Vector resources = Sorter.sortStringEnumeration(enum) ; HtmlGenerator g = new HtmlGenerator("Index of "+cresource.getIdentifier()); // Add style link addStyleSheet(g); g.append("<h1>"+cresource.getIdentifier()+"</h1>"); // Link to the parent, when possible: if ( cresource.getParent() != null ) { g.append("<p><a href=\"..\">Parent</a><br>"); } // List the children: for (int i = 0 ; i < resources.size() ; i++) { String name = (String) resources.elementAt(i); ResourceReference rr = null; long size = -1; rr = cresource.lookup(name); FramedResource resource = null; if (rr != null) { try { resource = (FramedResource) rr.unsafeLock(); // remove manually deleted FileResources if( resource instanceof FileResource ) { FileResource fr = (FileResource)resource; if( !fr.getFile().exists() ) { try { fr.delete(); } catch (MultipleLockException ex) {}; continue; } else { size = fr.getFile().length(); } } HTTPFrame itsframe = null; if (http_class != null) itsframe = (HTTPFrame) resource.getFrame(http_class); if (itsframe != null) { // Icon first, if available String icon = itsframe.getIcon() ; if ( icon != null ) { g.append("<img src=\""+ getIconDirectory() +"/"+ icon+ "\" alt=\"" + icon + "\">"); } // Resource's name with link: if (resource instanceof ContainerInterface) { g.append("<a href=\"" , URLEncoder.encode(name) , "/\">"+name+"</a>"); } else { g.append("<a href=\"" , URLEncoder.encode(name) , "\">"+name+"</a>"); } // resource's title, if any: String title = itsframe.getTitle(); if ( title != null ) { g.append(" "+title); } //size (if any) if (size != -1) { String s = null; if (size > 1023) { s = " ["+(size/1024)+" Kb]"; } else { s = " ["+size+" bytes]"; } g.append(s); } g.append("<br>\n"); } else { // Resource's name with link: g.append(name+ " (<i>Not available via HTTP.</i>)"); g.append("<br>\n"); } } catch (InvalidResourceException ex) { g.append(name+ " cannot be loaded (server misconfigured)"); g.append("<br>\n"); continue; } finally { rr.unlock(); } } } g.close() ; listing_stamp = getLastModified() ; listing = g ; return true; } } return false; } /** * Reply with an HTML doc listing the resources of this container. * This function takes special care not to regenerate a listing * when one is available. It also caches the date of the * listing, so that it can win big with NOT_MODIFIED. * <p>Using a modem, I know that each place I can reply with an * NOT_MODIFIED, <strong>is</strong> a big win. * @param request The request to handle. * @exception ProtocolException If processsing the request failed. * @exception ResourceException If the resource got a fatal error. */ public Reply getDirectoryListing(Request request) throws ProtocolException, ResourceException { if (! (resource instanceof ContainerResource)) { throw new ResourceException("this frame is not attached to a "+ "ContainerResource. ("+ resource.getIdentifier()+")"); } // delete us if the directory was deleted boolean refresh = false; if (dresource != null) { synchronized (dresource) { if (! dresource.getDirectory().exists()) { //delete us and emit an error String msg = dresource.getIdentifier()+ ": deleted, removing the DirectoryResource"; getServer().errlog(dresource, msg); try { dresource.delete(); } catch (MultipleLockException ex) { } // Emit an error back: Reply error = request.makeReply(HTTP.NOT_FOUND) ; error.setContent ("<h1>Document not found</h1>"+ "<p>The document "+ request.getURL()+ " is indexed but not available."+ "<p>The server is misconfigured.") ; throw new HTTPException (error) ; } refresh = (dresource.getDirectory().lastModified() > listing_stamp); } } if ((! computeContainerListing(refresh)) && ( checkIfModifiedSince(request) == COND_FAILED )) { // Is it an IMS request ? Reply reply = createDefaultReply(request, HTTP.NOT_MODIFIED) ; return reply; } // New content or need update: Reply reply = createDefaultReply(request, HTTP.OK) ; reply.setLastModified(listing_stamp) ; reply.setStream(listing) ; // check MD5 return reply ; } // // Commom part. // /** * Update the cached headers value. * Each resource maintains a set of cached values for headers, this * allows for a nice sped-up in headers marshalling, which - as the * complexity of the protocol increases - becomes a bottleneck. */ protected void updateCachedHeaders() { // Precompute a set of header values to keep by: if ( contenttype == null ) { String charset = getCharset(); if (charset == null) contenttype = HttpFactory.makeMimeType(getContentType()); else { MimeType ctype = getContentType().getClone(); ctype.addParameter("charset", charset); contenttype = HttpFactory.makeMimeType(ctype); } } if (contentlength == null) { int cl = -1; if (fresource != null) cl = fresource.getFileLength(); if ( cl >= 0 ) { if (cl != getInt(ATTR_CONTENT_LENGTH, -1)) { setValue(ATTR_CONTENT_LENGTH, new Integer(cl)); } contentlength = HttpFactory.makeInteger(cl); } } if ( lastmodified == null ) { long lm = getLastModified(); if ( lm > 0 ) lastmodified = HttpFactory.makeDate(getLastModified()); } if (definesAttribute(ATTR_CONTENT_ENCODING) &&(contentencoding==null)) contentencoding = HttpFactory.makeStringList(getContentEncoding()); if (definesAttribute(ATTR_CONTENT_LANGUAGE) &&(contentlanguage==null)) contentlanguage = HttpFactory.makeStringList(getContentLanguage()); if (fresource != null) { // We only take care of etag here: if ( etag == null ) { getETag(); } if (getMD5Flag() && (md5Digest == null)) { getMd5Digest(); } } } /** * Create a reply to answer to request on this file. * This method will create a suitable reply (matching the given request) * and will set all its default header values to the appropriate * values. * @param request The request to make a reply for. * @return An instance of Reply, suited to answer this request. */ public Reply createDefaultReply(Request request, int status) { Reply reply = request.makeReply(status); updateCachedHeaders(); if ( status != HTTP.NOT_MODIFIED ) { if ( contentlength != null ) reply.setHeaderValue(Reply.H_CONTENT_LENGTH, contentlength); if ( contenttype != null ) reply.setHeaderValue(Reply.H_CONTENT_TYPE, contenttype); if ( lastmodified != null ) reply.setHeaderValue(Reply.H_LAST_MODIFIED, lastmodified); if ( contentencoding != null ) { reply.setHeaderValue(Reply.H_CONTENT_ENCODING,contentencoding); } if ( contentlanguage != null ) reply.setHeaderValue(Reply.H_CONTENT_LANGUAGE,contentlanguage); } long maxage = getMaxAge(); if ( maxage >= 0 ) { if (reply.getMajorVersion() >= 1 ) { if (reply.getMinorVersion() >= 1) { reply.setMaxAge((int) (maxage / 1000)); } // If max-age is zero, say what you mean: long expires = (System.currentTimeMillis() + ((maxage == 0) ? -1000 : maxage)); reply.setExpires(expires); } } // Set the date of the reply (round it to secs): reply.setDate((System.currentTimeMillis() / 1000L) * 1000L); if (fresource != null) { // Set the entity tag: if ( getETag() != null ) { reply.setETag(etag); } if ( status != HTTP.NOT_MODIFIED ) { if ( acceptRanges ) { reply.setHeaderValue(reply.H_ACCEPT_RANGES,_accept_ranges); } if ( getMD5Flag()) { reply.setHeaderValue(reply.H_CONTENT_MD5, getMd5Digest()); } } } return reply; } /** * Check the <code>If-Match</code> condition of that request. * @param request The request to check. * @return An integer, either <code>COND_FAILED</cond> if condition * was checked, but failed, <code>COND_OK</code> if condition was checked * and succeeded, or <strong>0</strong> if the condition was not checked * at all (eg because the resource or the request didn't support it). */ public int checkIfMatch(Request request) { if (fresource != null) { HttpEntityTag tags[] = request.getIfMatch(); if ( tags != null ) { // Good, real validators in use: if ( etag != null ) { // Note: if etag is null this means that the resource has // changed and has not been even emited since then... for (int i = 0 ; i < tags.length ; i++) { HttpEntityTag t = tags[i]; if (t.getTag().equals(etag.getTag())) { if (t.isWeak() || etag.isWeak()) { return COND_WEAK; } else { return COND_OK; } } } } return COND_FAILED; } } return 0; } /** * Check the <code>If-None-Match</code> condition of that request. * @param request The request to check. * @return An integer, either <code>COND_FAILED</cond> if condition * was checked, but failed, <code>COND_OK</code> if condition was checked * and succeeded, or <strong>0</strong> if the condition was not checked * at all (eg because the resource or the request didn't support it). */ public int checkIfNoneMatch(Request request) { if (fresource != null) { // Check for an If-None-Match conditional: HttpEntityTag tags[] = request.getIfNoneMatch(); if ( tags != null ) { if ( etag == null ) { return COND_OK; } int status = COND_OK; for (int i = 0 ; i < tags.length ; i++) { HttpEntityTag t = tags[i]; if (t.getTag().equals(etag.getTag())) { if (t.isWeak() || etag.isWeak()) { status = COND_WEAK; } else { return COND_FAILED; } } if (t.getTag().equals("*")) { if (fresource != null) { File f = fresource.getFile(); if (f.exists()) { return COND_FAILED; } } else { return COND_FAILED; } } } return status; } } return 0; } /** * Check the <code>If-Modified-Since</code> condition of that request. * @param request The request to check. * @return An integer, either <code>COND_FAILED</cond> if condition * was checked, but failed, <code>COND_OK</code> if condition was checked * and succeeded, or <strong>0</strong> if the condition was not checked * at all (eg because the resource or the request didn't support it). */ public int checkIfModifiedSince(Request request) { // Check for an If-Modified-Since conditional: long ims = request.getIfModifiedSince(); if (dresource != null) { if (ims >= 0) { if (listing_stamp > 0) { long s_listing_stamp = listing_stamp / 1000; long s_ims = ims / 1000; if (s_listing_stamp < s_ims) { return COND_FAILED; } else if (s_listing_stamp == s_ims) { return COND_WEAK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -