/* This code is part of Freenet. It is distributed under the GNU General * Public License, version 2 (or at your option any later version). See * http://www.gnu.org/ for further details of the GPL. */ package freenet.node; import freenet.config.InvalidConfigValueException; import freenet.l10n.NodeL10n; import freenet.support.api.StringCallback; import java.util.HashSet; import java.io.File; import java.io.IOException; /** ** Represents a program directory, and keeps track of the files that freenet ** stores there. ** ** @author infinity0 ** @see <a href=http://new-wiki.freenetproject.org/Program_files>New wiki program files documentation</a> ** @see <a href=http://wiki.freenetproject.org/Program_files>Old wiki program files documentation</a> */ public class ProgramDirectory { /** Directory path */ protected File dir = null; /** Keeps track of all the files saved in this directory */ final protected HashSet<String> files = new HashSet<String>(); final private StringCallback callback; final private String moveErrMsg; private static int sortOrder = 0; protected static synchronized int nextOrder() { return sortOrder++; } public ProgramDirectory() { this(null); } public ProgramDirectory(String moveErrMsg) { this.moveErrMsg = moveErrMsg; this.callback = (moveErrMsg != null)? new RWDirectoryCallback(): new DirectoryCallback(); } /** ** Move the directory. Currently not implemented, except in the ** initialisation case. */ public void move(String file) throws IOException { File dir = new File(file); if (this.dir != null && !dir.equals(this.dir)) { throw new IOException("move not implemented"); } if (!((dir.exists() && dir.isDirectory()) || (dir.mkdir()))) { throw new IOException("Could not find or make a directory called: " + l10n(file)); } this.dir = dir; } public StringCallback getStringCallback() { return callback; } public class DirectoryCallback extends StringCallback { @Override public String get() { return dir.getPath(); } @Override public void set(String val) throws InvalidConfigValueException { if (dir == null) { dir = new File(val); return; } if (dir.equals(new File(val))) return; // FIXME support it // Don't need to translate the below as very few users will use it. throw new InvalidConfigValueException("Moving program directory on the fly not supported at present"); } @Override public boolean isReadOnly() { return true; } } public class RWDirectoryCallback extends DirectoryCallback { @Override public void set(String val) throws InvalidConfigValueException { if (dir == null) { dir = new File(val); return; } if (dir.equals(new File(val))) return; File f = new File(val); if(!((f.exists() && f.isDirectory()) || (f.mkdir()))) // Relatively commonly used, despite being advanced (i.e. not something we want to show to newbies). So translate it. throw new InvalidConfigValueException(l10n(moveErrMsg)); dir = new File(val); } @Override public boolean isReadOnly() { return false; } } /** ** Return a {@link File} object from the given string basename. */ public File file(String base) { files.add(base); return new File(dir, base); } public File dir() { return dir; } private static String l10n(String key) { return NodeL10n.getBase().getString(key); } }