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 + -
显示快捷键?