📄 httpframe.java
字号:
ByteArrayOutputStream bos = new ByteArrayOutputStream(); b64 = new Base64Encoder(new ByteArrayInputStream(b), bos); b64.process(); s = bos.toString(); md5Digest = HttpFactory.makeString(s); } catch (Exception mdex) { // error, set it to null md5Digest = null; } return md5Digest; } catch (FileNotFoundException ex) { // silent fail md5Digest = null; } } return null; } /** * Listen its resource. */ public void attributeChanged(AttributeChangedEvent evt) { super.attributeChanged(evt); String name = evt.getAttribute().getName(); if (name.equals("file-stamp")) { etag = null; lastmodified = null; md5Digest = null; } else if (name.equals("file-length")) { setValue(ATTR_CONTENT_LENGTH, evt.getNewValue()); } else if (name.equals("last-modified")) { setValue(ATTR_LAST_MODIFIED, evt.getNewValue()); } else { lastmodified = null; } } /** * Catch setValue, to maintain cached header values correctness. * @param idx The index of the attribute to be set. * @param value The new value for the attribute. */ public synchronized void setValue(int idx, Object value) { super.setValue(idx, value); if (idx == ATTR_CONTENT_TYPE) { contenttype = null; } else if (idx == ATTR_CHARSET) { contenttype = null; } else if (idx == ATTR_CONTENT_LENGTH) { contentlength = null; } else if ( idx == ATTR_CONTENT_ENCODING ) { contentencoding = null; } else if ( idx == ATTR_CONTENT_LANGUAGE ) { contentlanguage = null; } else if ( idx == ATTR_PUTABLE) { allowed = null; } else if (idx == ATTR_ALLOW_DEL) { allowed = null; } else if (idx == ATTR_MD5) { md5Digest = null; // reset the digest state } // Any attribute setting modifies the last modified time: lastmodified = null; } /** * Get the full URL for that resource. * @return An URL instance. */ public URL getURL(Request request) { try { return new URL(request.getURL(), resource.getURLPath()); } catch (MalformedURLException ex) { throw new RuntimeException("unable to build "+ getURLPath()+ " full URL, from server "+ getServer().getURL()); } } /** * Get this resource quality. * @return The resource quality, or some negative value if not defined. */ public double getQuality() { return getDouble(ATTR_QUALITY, -1.0) ; } /** * Get this resource title. * @return This resource's title, or <strong>null</strong> if not * defined. */ public String getTitle() { return getString(ATTR_TITLE, null) ; } /** * Get this resource content language. * Language are stored as a comma separated String of tokens. * @return A comma separated string of language tokens, or * <strong>null</strong> if undefined. */ public String getContentLanguage() { return (String) getValue(ATTR_CONTENT_LANGUAGE, null) ; } /** * Get this resource content encoding. * The content encoding of a resource is stored as a comma separated * list of tokens (as decribed in the Content_encoding header of the * HTTP specification, and in the order they should appear in the header). * @return A string of comma separated encoding tokens, or * <strong>null</strong> if not defined. */ public String getContentEncoding() { String def = (String) attributes[ATTR_CONTENT_ENCODING].getDefault(); String s = (String) getString (ATTR_CONTENT_ENCODING, def) ; return (String) getString (ATTR_CONTENT_ENCODING, def) ; } /** * Get this resource charset. * @return A String, or <strong>null</strong> if not * defined. */ public String getCharset() { return (String) getValue(ATTR_CHARSET, null); } /** * Get this resource content type. * @return An instance of MIMEType, or <strong>null</strong> if not * defined. */ public MimeType getContentType() { return (MimeType) getValue(ATTR_CONTENT_TYPE, null); } /** * Compute the ETag string * @return a string or null if not applicable */ public String computeETag() { String etag_s = null; if (fresource != null) { long lstamp = fresource.getFileStamp(); if ( lstamp >= 0L ) { StringBuffer sb = new StringBuffer(32); sb.append(Integer.toString(getOid(), 32)); sb.append(':'); sb.append(Long.toString(lstamp, 32)); etag_s = sb.toString(); } } return etag_s; } /** * Get this resource Etag * @return an instance of HttpEntityTag, or <strong>null</strong> if not * defined. */ public HttpEntityTag getETag() { if (etag == null) { String etag_s = computeETag(); // no luck, exit if (etag_s == null) { return null; } etag = HttpFactory.makeETag(false, etag_s); } return etag; } /** * Get this resource content length. * @return The resource content length, or <strong>-1</strong> if not * defined. */ public int getContentLength() { return getInt(ATTR_CONTENT_LENGTH, -1) ; } /** * Get this resource's icon. */ public String getIcon() { return getString(ATTR_ICON, null) ; } /** * Get this resource's max age. * The max age of a resource indicates how much drift is allowed between * the physicall version of the resource, and any in-memory cached version * of it. * <p>The max age attribute is a long number giving the number of * milliseconds of allowed drift. */ public long getMaxAge() { return getLong(ATTR_MAXAGE, (long) -1) ; } // // Relative to FileResource ... // /** * Does this resource support byte ranges. */ protected boolean acceptRanges = false; /** * Get the PUT'able flag (are we allow to PUT to the resource ?) */ public boolean getPutableFlag() { return getBoolean(ATTR_PUTABLE, false) ; } /** * Do we send the MD5 digest? */ public boolean getMD5Flag() { return getBoolean(ATTR_MD5, false) ; } /** * delete allowed for the associated resource ? */ public boolean getAllowDeleteFlag() { return getBoolean(ATTR_ALLOW_DEL, false); } /** * get the Allowed methods for this resource * @return an HttpTokenList */ protected HttpTokenList getAllow() { if (allowed != null) { return allowed; } int size = 4; // the default HEAD GET OPTIONS TRACE if (getPutableFlag()) { size++; } if (getAllowDeleteFlag()) { size++; } String allow_str[] = new String[size]; int i = 0; if (getAllowDeleteFlag()) { allow_str[i++] = "DELETE"; } allow_str[i++] = "HEAD"; allow_str[i++] = "GET"; allow_str[i++] = "OPTIONS"; if (getPutableFlag()) { allow_str[i++] = "PUT"; } allow_str[i] = "TRACE"; allowed = HttpFactory.makeStringList(allow_str); return allowed; } /** * handles a Range Request * @param request, the request * @param r, the HttpRange * @return a Reply if range is valid, or null if there is a change in the * resource, or if the HttpRange is not valid ( 4-2, for example). * @exception ProtocolException If processsing the request failed. */ public Reply handleRangeRequest(Request request, HttpRange r) throws ProtocolException { // Should we check against a IfRange header ? HttpEntityTag t = request.getIfRange(); if ( t != null ) { if (t.isWeak() || ! t.getTag().equals(etag.getTag())) return null; } // Check the range: int cl = getContentLength(); int fb = r.getFirstPosition(); int lb = r.getLastPosition(); int sz; if (fb > cl-1) { // first byte already out of range HttpContentRange cr = HttpFactory.makeContentRange("bytes", 0, cl - 1, cl); Reply rr; rr = createDefaultReply(request, HTTP.REQUESTED_RANGE_NOT_SATISFIABLE); rr.setContentLength(-1); rr.setHeaderValue(rr.H_CONTENT_RANGE, cr); if (getMD5Flag()) rr.setContentMD5(null); return rr; } if ((fb < 0) && (lb >= 0)) { // ex: bytes=-20 final 20 bytes if (lb >= cl) // cut the end lb = cl; sz = lb; fb = cl - lb; lb = cl - 1; } else if (lb < 0) { // ex: bytes=10- the last size - 10 lb = cl-1; sz = lb-fb+1; } else { // ex: bytes=10-20 if (lb >= cl) // cut the end lb = cl-1; sz = lb-fb+1; } if ((fb < 0) || (lb < 0) || (fb <= lb)) { HttpContentRange cr = null; fb = (fb < 0) ? 0 : fb; lb = ((lb > cl) || (lb < 0)) ? cl : lb; cr = HttpFactory.makeContentRange("bytes", fb, lb, cl); // Emit reply: Reply rr = createDefaultReply(request, HTTP.PARTIAL_CONTENT); // FIXME check for MD5 of only the subpart try { // create the MD5 for the subpart if (getMD5Flag()) { String s = null; try { ByteRangeOutputStream br; br = new ByteRangeOutputStream(fresource.getFile(), fb, lb+1); Md5 md5 = new Md5 (br); byte b[] = md5.getDigest(); Base64Encoder b64; ByteArrayOutputStream bs = new ByteArrayOutputStream(); b64 = new Base64Encoder(new ByteArrayInputStream(b), bs); b64.process(); s = bs.toString(); } catch (Exception md_ex) { // default to null, no action here then } if (s == null) rr.setContentMD5(null); else rr.setContentMD5(s); } rr.setContentLength(sz); rr.setHeaderValue(rr.H_CONTENT_RANGE, cr); rr.setStream(new ByteRangeOutputStream(fresource.getFile(), fb, lb+1)); return rr; } catch (IOException ex) { } } return null; } // // Relative to DirectoryResource ... // /** * Get this class browsable flag. */ public boolean getBrowsableFlag() { return getBoolean (ATTR_BROWSABLE, false) ; } /** * Get this frame style sheet link */ public String getStyleSheetURL() { return getString (ATTR_STYLE_LINK, null); } /** * Our current (cached) directory listing. */ protected HtmlGenerator listing = null ; /** * The time at which we generated the directory index. */ protected long listing_stamp = -1 ; private String getUnextendedName(String name) { int strlen = name.length() ; for (int i = 0 ; i < strlen ; i++) { // FIXME: Should use the system props to get the right sep if ( name.charAt(i) == '.' ) { if ( i == 0 ) return null ; return name.substring(0, i) ; } } return null ; } /** * Get the optional icon directory. */ public String getIconDirectory() { return getString(ATTR_ICONDIR, "/icons") ; } /** * Should we relocate invalid requests to this directory. * @return A boolean <strong>true</strong> if we should relocate. */ public boolean getRelocateFlag() { return getBoolean(ATTR_RELOCATE, true) ; } /** * Get the optional main index name for this directory listing. * @return The name of the resource responsible to list that container. */ public String getIndex() { return (String) getValue(ATTR_INDEX, null) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -