// FileResource.java
// $Id: FileResource.html,v 1.2 1999/10/27 22:10:34 ylafon Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html
packageorg.w3c.tools.resources ;
importjava.io.* ;
/**
* A simple file resource.
*/publicclassFileResourceextendsFramedResource {
/**
* Attributes index - The filename attribute.
*/protectedstaticintATTR_FILENAME = -1 ;
/**
* Attribute index - The date at which we last checked the file content.
*/protectedstaticintATTR_FILESTAMP = -1 ;
/**
* Attribute index - The index for the content length attribute.
*/protectedstaticintATTR_FILE_LENGTH = -1 ;
/**
* Attribute index - The index for the backup flag
*/protectedstaticintATTR_FILE_BACKUP = -1 ;
static {
Attributea = null ;
Classcls = null ;
try {
cls = Class.forName("org.w3c.tools.resources.FileResource") ;
} catch (Exceptionex) {
ex.printStackTrace();
System.exit(0);
}
// The filename attribute.
a = newFilenameAttribute("filename"
, null
, Attribute.EDITABLE) ;
ATTR_FILENAME = AttributeRegistry.registerAttribute(cls, a) ;
// The file stamp attribute
a = newDateAttribute("file-stamp"
, newLong(-1)
, Attribute.COMPUTED) ;
ATTR_FILESTAMP = AttributeRegistry.registerAttribute(cls, a) ;
// The file length attribute:
a = newIntegerAttribute("file-length"
, null
, Attribute.COMPUTED);
ATTR_FILE_LENGTH = AttributeRegistry.registerAttribute(cls,a);
// The backup attribute:
a = newBooleanAttribute("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.
*/protectedFilefile = null ;
/**
* Get this resource filename attribute.
*/publicStringgetFilename() {
return (String) getValue(ATTR_FILENAME, null);
}
/**
* Get this file length
*/publicintgetFileLength() {
return ((Integer) getValue(ATTR_FILE_LENGTH,
newInteger(0))).intValue();
}
/**
* Get the date at which we last examined the file.
*/publiclonggetFileStamp() {
return getLong(ATTR_FILESTAMP, (long) -1) ;
}
/**
* Get the backup flag, create a backup file when content change
* if true.
*/publicbooleangetBackupFlag() {
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.
*/publicFilegetBackupFile() {
Filefile = getFile() ;
Stringname = file.getName() ;
returnnewFile(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.
*/publicsynchronizedbooleannewContent(InputStreamin)
throwsIOException
{
Filefile = getFile() ;
booleancreated = (! file.exists() | (file.length() == 0));
Stringname = file.getName() ;
Filetemp = newFile(file.getParent(), "#"+name+"#") ;
Stringiomsg = null ;
// We are not catching IO exceptions here, except to remove temp:
try {
FileOutputStreamfout = newFileOutputStream(temp) ;
bytebuf[] = newbyte[4096] ;
for (intgot = 0 ; (got = in.read(buf)) > 0 ; )
fout.write(buf, 0, got) ;
fout.close() ;
} catch (IOExceptionex) {
iomsg = ex.getMessage() ;
} finally {
if ( iomsg != null ) {
temp.delete() ;
thrownewIOException(iomsg) ;
} else {
if (getBackupFlag()) {
Filebackup = getBackupFile();
if ( backup.exists() )
backup.delete();
file.renameTo(getBackupFile()) ;
}
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.
*/publiclongcheckContent() {
Filefile = getFile() ;
// Has this resource changed since last queried ?
longlmt = file.lastModified() ;
longcmt = 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.
*/publicsynchronizedvoidsetValue(intidx, Objectvalue) {
super.setValue(idx, value) ;
if ((idx == ATTR_FILENAME) || (idx == ATTR_IDENTIFIER))
file = null;
}
/**
* Get this file resource file name.
*/publicsynchronizedFilegetFile() {
// Have we already computed this ?
if ( file == null ) {
// Get the file name:
Stringname = getFilename() ;
if ( name == null )
name = getIdentifier() ;
// Get the file directory:
ResourceReferencerr = getParent();
ResourceReferencerrtemp = null;
Resourcep = null;
while ( true ) {
try {
if (rr == null)
returnnull;
p = rr.lock();
if (p instanceofDirectoryResource) {
file = newFile(((DirectoryResource) p)
.getDirectory(), name);
return file;
}
rrtemp = p.getParent();
} catch (InvalidResourceExceptionex) {
returnnull;
} 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.
*/publicsynchronizedbooleanverify()
throwsMultipleLockException
{
Filefile = getFile();
if ( ! file.exists() ) {
// Is the parent extensible:
ResourceReferencerr = getParent();
ResourceReferencerrtemp = null;
Resourcep = null;
while ( true ) {
try {
if (rr == null)
returnfalse;
p = rr.lock();
if (p instanceofDirectoryResource) {
DirectoryResourced = (DirectoryResource) p;
if ( ! d.getExtensibleFlag() )
returnfalse;
else {
// Emit an error message, and delete the resource:
Stringmsg = file+
": deleted, removing the FileResource.";
getServer().errlog(this, msg);
delete();
returnfalse;
}
}
rrtemp = p.getParent();
} catch (InvalidResourceExceptionex) {
returnfalse;
} finally {
if (rr != null)
rr.unlock();
}
rr = rrtemp;
}
} else {
returntrue;
}
}
/**
* 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.
*/publicvoidupdateFileAttributes() {
Filefile = getFile() ;
setValue(ATTR_FILESTAMP, newLong(file.lastModified()));
setValue(ATTR_FILE_LENGTH, newInteger((int)file.length()));
return ;
}
/**
* Update our computed attributes.
*/publicvoidupdateAttributes() {
longfstamp = getFile().lastModified() ;
longstamp = getLong(ATTR_FILESTAMP, -1) ;
if ((stamp < 0) || (stamp < fstamp))
updateFileAttributes() ;
}
/**
* Initialize the FileResource instance.
*/publicvoidinitialize(Objectvalues[]) {
super.initialize(values);
disableEvent();
// If we have a filename attribute, update url:
Stringfilename = getFilename();
if ( filename != null ) {
ResourceReferencerr = getParent();
try {
Resourceparent = rr.lock();
setValue(ATTR_URL, parent.getURLPath()+filename);
} catch (InvalidResourceExceptionex) {
//FIXME
} finally {
rr.unlock();
}
}
enableEvent();
}
}