fileresource.java
来自「很棒的web服务器源代码」· Java 代码 · 共 382 行
JAVA
382 行
// FileResource.java// $Id: FileResource.java,v 1.20 2003/05/28 09:27:40 ylafon Exp $// (c) COPYRIGHT MIT and INRIA, 1996.// Please first read the full copyright statement in file COPYRIGHT.htmlpackage org.w3c.tools.resources ;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;/** * A simple file resource. */public class FileResource extends FramedResource { /** * Attributes index - The filename attribute. */ protected static int ATTR_FILENAME = -1 ; /** * Attribute index - The date at which we last checked the file content. */ protected static int ATTR_FILESTAMP = -1 ; /** * Attribute index - The index for the content length attribute. */ protected static int ATTR_FILE_LENGTH = -1 ; /** * Attribute index - The index for the backup flag */ protected static int ATTR_FILE_BACKUP = -1 ; static { Attribute a = null ; Class cls = null ; try { cls = Class.forName("org.w3c.tools.resources.FileResource") ; } catch (Exception ex) { ex.printStackTrace(); System.exit(0); } // The filename attribute. a = new FilenameAttribute("filename" , null , Attribute.EDITABLE) ; ATTR_FILENAME = AttributeRegistry.registerAttribute(cls, a) ; // The file stamp attribute a = new DateAttribute("file-stamp" , new Long(-1) , Attribute.COMPUTED) ; ATTR_FILESTAMP = AttributeRegistry.registerAttribute(cls, a) ; // The file length attribute: a = new IntegerAttribute("file-length" , null , Attribute.COMPUTED); ATTR_FILE_LENGTH = AttributeRegistry.registerAttribute(cls,a); // The backup attribute: a = new BooleanAttribute("backup" , Boolean.FALSE , Attribute.EDITABLE); ATTR_FILE_BACKUP = AttributeRegistry.registerAttribute(cls,a); } /** * The file we refer to. * This is a cached version of some attributes, so we need to override * the setValue method in order to be able to catch any changes to it. */ protected File file = null ; /** * Get this resource filename attribute. */ public String getFilename() { return (String) getValue(ATTR_FILENAME, null); } /** * Get this file length */ public int getFileLength() { return ((Integer) getValue(ATTR_FILE_LENGTH, new Integer(0))).intValue(); } /** * Get the date at which we last examined the file. */ public long getFileStamp() { return getLong(ATTR_FILESTAMP, (long) -1) ; } /** * Get the backup flag, create a backup file when content change * if true. */ public boolean getBackupFlag() { return getBoolean(ATTR_FILE_BACKUP, false) ; } /** * Get the name of the backup file for this resource. * @return A File object suitable to receive the backup version of this * file. */ public File getBackupFile() { File file = getFile() ; String name = file.getName() ; return new File(file.getParent(), name+"~") ; } /** * Save the given stream as the underlying file content. * This method preserve the old file version in a <code>~</code> file. * @param in The input stream to use as the resource entity. * @return A boolean, <strong>true</strong> if the resource was just * created, <strong>false</strong> otherwise. * @exception IOException If dumping the content failed. */ public synchronized boolean newContent(InputStream in) throws IOException { File file = getFile() ; boolean created = (! file.exists() || (file.length() == 0)); String name = file.getName() ; File temp = new File(file.getParent(), "#"+name+"#") ; String iomsg = null ; // We are not catching IO exceptions here, except to remove temp: try { FileOutputStream fout = new FileOutputStream(temp) ; byte buf[] = new byte[4096] ; for (int got = 0 ; (got = in.read(buf)) > 0 ; ) fout.write(buf, 0, got) ; fout.close() ; } catch (IOException ex) { iomsg = ex.getMessage() ; } finally { if ( iomsg != null ) { temp.delete() ; throw new IOException(iomsg) ; } else { if (getBackupFlag()) { File backup = getBackupFile(); if (backup.exists()) backup.delete(); file.renameTo(getBackupFile()) ; } // with some OSes, rename doesn't overwrite so... if (file.exists()) file.delete(); temp.renameTo(file) ; // update our attributes for this new content: updateFileAttributes() ; } } return created; } /** * Check this file content, and update attributes if needed. * This method is normally called before any perform request is done, so * that we make sure that all meta-informations is up to date before * handling a request. * @return The time of the last update to the resource. */ public long checkContent() { File file = getFile() ; // Has this resource changed since last queried ? long lmt = file.lastModified() ; long cmt = getFileStamp() ; if ((cmt < 0) || (cmt < lmt)) { updateFileAttributes() ; return getLastModified() ; } else { return cmt; } } /** * Set some of this resource attribute. * We just catch here any write access to the filename's, to update * our cache file object. */ public synchronized void setValue(int idx, Object value) { if (idx == ATTR_IDENTIFIER) { String oldid = getIdentifier(); if (getFilename() == null) { File oldfile = getFile(oldid); if ((oldfile != null) && (oldfile.exists())) super.setValue(ATTR_FILENAME, oldid); } } super.setValue(idx, value) ; if ((idx == ATTR_FILENAME) || (idx == ATTR_IDENTIFIER)) file = null; } private synchronized File getFile(String name) { ResourceReference rr = getParent(); ResourceReference rrtemp = null; Resource p = this; while ( true ) { try { if (rr == null) return null; p = rr.lock(); if (p instanceof DirectoryResource) { DirectoryResource dr = (DirectoryResource) p; return new File(dr.unsafeGetDirectory(), name); } rrtemp = p.getParent(); } catch (InvalidResourceException ex) { ex.printStackTrace(); return null; } finally { if (rr != null) rr.unlock(); } rr = rrtemp; } } /** * Get this file resource file name. * @return a File instance. * @exception InvalidParentException If no parent is available, * and then the FileReource is unable to get its file. */ public synchronized File getFile() { // Have we already computed this ? if ( file == null ) { // Get the file name: String name = getFilename() ; if ( name == null ) name = getIdentifier() ; // Get the file directory: ResourceReference rr = getParent(); ResourceReference rrtemp = null; Resource p = this; while ( true ) { try { if (rr == null) throw new InvalidParentException(p.getIdentifier()+ " can't find his parent, "+ "context : "+ p.unsafeGetContext()); p = rr.lock(); if (p instanceof DirectoryResource) { DirectoryResource dr = (DirectoryResource) p; file = new File(dr.unsafeGetDirectory(), name); return file; } rrtemp = p.getParent(); } catch (InvalidResourceException ex) { ex.printStackTrace(); return null; } finally { if (rr != null) rr.unlock(); } rr = rrtemp; } } return file ; } /** * Is that resource still wrapping an existing file ? * If the underlying file has disappeared <string> and if</strong> the * container directory is extensible, remove the resource. * @return true if that resource is wrapping an existing file * @exception org.w3c.tools.resources.MultipleLockException When the * resource try to delete itself (because there is no more file) */ public synchronized boolean verify() throws MultipleLockException { File file = getFile(); if ( ! file.exists() ) { // Is the parent extensible: ResourceReference rr = getParent(); ResourceReference rrtemp = null; Resource p = null; while ( true ) { try { if (rr == null) return false; p = rr.lock(); if (p instanceof DirectoryResource) { DirectoryResource d = (DirectoryResource) p; if ( ! d.unsafeGetShrinkableFlag() ) return false; else { // Emit an error message, and delete the resource: String msg = file+ ": deleted, removing the FileResource."; getServer().errlog(this, msg); delete(); return false; } } rrtemp = p.getParent(); } catch (InvalidResourceException ex) { return false; } finally { if (rr != null) rr.unlock(); } rr = rrtemp; } } else { return true; } } /** * Update the file related attributes. * The file we serve has changed since the last time we checked it, if * any of the attribute values depend on the file content, this is the * appropriate place to recompute them. */ public void updateFileAttributes() { File file = getFile() ; setValue(ATTR_FILESTAMP, new Long(file.lastModified())); setValue(ATTR_FILE_LENGTH, new Integer((int)file.length())); return ; } /** * Update our computed attributes. */ public void updateAttributes() { long fstamp = getFile().lastModified() ; long stamp = getLong(ATTR_FILESTAMP, -1) ; // should be stamp < fstamp, but it avoid clocks weirdness if ((stamp < 0) || (stamp != fstamp)) updateFileAttributes() ; } /** * Initialize the FileResource instance. */ public void initialize(Object values[]) { super.initialize(values); disableEvent(); // If we have a filename attribute, update url: String filename = getFilename(); if ( filename != null ) { ResourceReference rr = getParent(); if (rr != null) { try { Resource parent = rr.lock(); setValue(ATTR_URL, parent.getURLPath()+ java.net.URLEncoder.encode(getIdentifier())); } catch (InvalidResourceException ex) { //FIXME } finally { rr.unlock(); } } } enableEvent(); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?