/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author: root $
* $Revision: 8604 $
* $Date: 2007-09-28 15:16:38 +0200 (Fre, 28. Sep 2007) $
*/
package helma.framework.repository;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
/**
* Repository implementation for directories providing file resources
*/
public class FileRepository extends AbstractRepository {
// Directory serving sub-repositories and file resources
protected File directory;
protected long lastModified = -1;
protected long lastChecksum = 0;
protected long lastChecksumTime = 0;
/**
* Defines how long the checksum of the repository will be cached
*/
final long cacheTime = 1000L;
/**
* Constructs a FileRepository using the given argument
* @param initArgs absolute path to the directory
*/
public FileRepository(String initArgs) {
this(new File(initArgs), null);
}
/**
* Constructs a FileRepository using the given directory as top-level
* repository
* @param dir directory
*/
public FileRepository(File dir) {
this(dir, null);
}
/**
* Constructs a FileRepository using the given directory and top-level
* repository
* @param dir directory
* @param parent the parent repository, or null
*/
public FileRepository(File dir, Repository parent) {
// make sure our directory has an absolute path,
// see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4117557
if (dir.isAbsolute()) {
directory = dir;
} else {
directory = dir.getAbsoluteFile();
}
if (!directory.exists()) {
create();
} else if (!directory.isDirectory()) {
throw new IllegalArgumentException("File " + directory + " is not a directory");
}
if (parent == null) {
name = shortName = directory.getAbsolutePath();
} else {
this.parent = parent;
shortName = directory.getName();
name = directory.getAbsolutePath();
}
}
public boolean exists() {
return directory.exists() && directory.isDirectory();
}
public void create() {
if (!directory.exists() || !directory.isDirectory()) {
directory.mkdirs();
}
}
/**
* Checks wether the repository is to be considered a top-level
* repository from a scripting point of view. For example, a zip
* file within a file repository is not a root repository from
* a physical point of view, but from the scripting point of view it is.
*
* @return true if the repository is to be considered a top-level script repository
*/
public boolean isScriptRoot() {
return parent == null || parent instanceof MultiFileRepository;
}
public long lastModified() {
return directory.lastModified();
}
public synchronized long getChecksum() throws IOException {
// delay checksum check if already checked recently
if (System.currentTimeMillis() > lastChecksumTime + cacheTime) {
update();
long checksum = lastModified;
for (int i = 0; i < repositories.length; i++) {
checksum += repositories[i].getChecksum();
}
lastChecksum = checksum;
lastChecksumTime = System.currentTimeMillis();
}
return lastChecksum;
}
/**
* Updates the content cache of the repository
* Gets called from within all methods returning sub-repositories or
* resources
*/
public synchronized void update() {
if (!directory.exists()) {
repositories = emptyRepositories;
if (resources == null) {
resources = new HashMap();
} else {
resources.clear();
}
lastModified = 0;
return;
}
if (directory.lastModified() != lastModified) {
lastModified = directory.lastModified();
File[] list = directory.listFiles();
ArrayList newRepositories = new ArrayList(list.length);
HashMap newResources = new HashMap(list.length);
for (int i = 0; i < list.length; i++) {
if (list[i].isDirectory()) {
// a nested directory aka child file repository
newRepositories.add(new FileRepository(list[i], this));
} else if (list[i].getName().endsWith(".zip")) {
// a nested zip repository
newRepositories.add(new ZipRepository(list[i], this));
} else if (list[i].isFile()) {
// a file resource
FileResource resource = new FileResource(list[i], this);
newResources.put(resource.getShortName(), resource);
}
}
repositories = (Repository[])
newRepositories.toArray(new Repository[newRepositories.size()]);
resources = newResources;
}
}
/**
* Called to create a child resource for this repository
*/
protected Resource createResource(String name) {
return new FileResource(new File(directory, name), this);
}
/**
* Get the repository's directory
*/
public File getDirectory() {
return directory;
}
public int hashCode() {
return 17 + (37 * directory.hashCode());
}
public boolean equals(Object obj) {
return obj instanceof FileRepository &&
directory.equals(((FileRepository) obj).directory);
}
public String toString() {
return new StringBuffer("FileRepository[").append(name).append("]").toString();
}
}