From e1e349bae97feb779fc692eb03c2fea0e0e612c9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Tue, 3 Jun 2008 08:15:10 +0200 Subject: [PATCH] move project directory --- src/net/pterodactylus/jsite/core/Core.java | 2 +- src/net/pterodactylus/jsite/core/CoreImpl.java | 4 +- src/net/pterodactylus/jsite/core/CoreListener.java | 2 +- .../jsite/core/project/FileOverride.java | 156 ++++++ .../pterodactylus/jsite/core/project/Project.java | 595 +++++++++++++++++++++ .../jsite/core/project/ProjectFile.java | 108 ++++ .../jsite/core/project/ProjectManager.java | 307 +++++++++++ src/net/pterodactylus/jsite/gui/FileManager.java | 6 +- src/net/pterodactylus/jsite/gui/MainWindow.java | 2 +- src/net/pterodactylus/jsite/gui/ProjectPanel.java | 2 +- .../pterodactylus/jsite/gui/SwingInterface.java | 10 +- src/net/pterodactylus/jsite/main/Main.java | 2 +- .../pterodactylus/jsite/project/FileOverride.java | 156 ------ src/net/pterodactylus/jsite/project/Project.java | 595 --------------------- .../pterodactylus/jsite/project/ProjectFile.java | 108 ---- .../jsite/project/ProjectManager.java | 307 ----------- 16 files changed, 1181 insertions(+), 1181 deletions(-) create mode 100644 src/net/pterodactylus/jsite/core/project/FileOverride.java create mode 100644 src/net/pterodactylus/jsite/core/project/Project.java create mode 100644 src/net/pterodactylus/jsite/core/project/ProjectFile.java create mode 100644 src/net/pterodactylus/jsite/core/project/ProjectManager.java delete mode 100644 src/net/pterodactylus/jsite/project/FileOverride.java delete mode 100644 src/net/pterodactylus/jsite/project/Project.java delete mode 100644 src/net/pterodactylus/jsite/project/ProjectFile.java delete mode 100644 src/net/pterodactylus/jsite/project/ProjectManager.java diff --git a/src/net/pterodactylus/jsite/core/Core.java b/src/net/pterodactylus/jsite/core/Core.java index 7185b2e..c72314f 100644 --- a/src/net/pterodactylus/jsite/core/Core.java +++ b/src/net/pterodactylus/jsite/core/Core.java @@ -24,7 +24,7 @@ import java.net.UnknownHostException; import java.util.List; import java.util.concurrent.Executor; -import net.pterodactylus.jsite.project.Project; +import net.pterodactylus.jsite.core.project.Project; /** * Interface for the core. diff --git a/src/net/pterodactylus/jsite/core/CoreImpl.java b/src/net/pterodactylus/jsite/core/CoreImpl.java index dc35c56..8f26a67 100644 --- a/src/net/pterodactylus/jsite/core/CoreImpl.java +++ b/src/net/pterodactylus/jsite/core/CoreImpl.java @@ -26,8 +26,8 @@ import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.Executors; -import net.pterodactylus.jsite.project.Project; -import net.pterodactylus.jsite.project.ProjectManager; +import net.pterodactylus.jsite.core.project.Project; +import net.pterodactylus.jsite.core.project.ProjectManager; /** * The core of jSite. diff --git a/src/net/pterodactylus/jsite/core/CoreListener.java b/src/net/pterodactylus/jsite/core/CoreListener.java index 8da73bb..3dbc55e 100644 --- a/src/net/pterodactylus/jsite/core/CoreListener.java +++ b/src/net/pterodactylus/jsite/core/CoreListener.java @@ -19,7 +19,7 @@ package net.pterodactylus.jsite.core; -import net.pterodactylus.jsite.project.Project; +import net.pterodactylus.jsite.core.project.Project; /** * Interface definition for user interfaces. diff --git a/src/net/pterodactylus/jsite/core/project/FileOverride.java b/src/net/pterodactylus/jsite/core/project/FileOverride.java new file mode 100644 index 0000000..afbf557 --- /dev/null +++ b/src/net/pterodactylus/jsite/core/project/FileOverride.java @@ -0,0 +1,156 @@ +/* + * jSite2 - Override.java - + * Copyright © 2008 David Roden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package net.pterodactylus.jsite.core.project; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import net.pterodactylus.util.logging.Logging; + +/** + * An override is used to enter other information about a file than the defaults + * would have yielded. It is also used to add redirects to a project. + * + * @author David ‘Bombe’ Roden <bombe@freenetproject.org> + * @version $Id$ + */ +public class FileOverride { + + /** The logger. */ + private static final Logger logger = Logging.getLogger(FileOverride.class.getName()); + + /** The insert override. */ + private Boolean insert; + + /** The override content type. */ + private String contentType; + + /** The redirect target. */ + private String redirectTarget; + + /** + * Checks whether this override has any content. + * + * @return true if this override does not have any effects, + * false otherwise + */ + public boolean isEmpty() { + return (insert == null) && (contentType == null) && (redirectTarget == null); + } + + /** + * Returns the insert override. + * + * @return true if the entry should be inserted, + * false if it should not be inserted, + * null if the default should not be overridden + */ + public Boolean isInsert() { + return insert; + } + + /** + * Sets the insert override. + * + * @param insert + * true if the entry should be inserted, + * false if it should not be inserted, + * null if the default should not be overridden + */ + public void setInsert(Boolean insert) { + this.insert = insert; + } + + /** + * Returns the override content type. + * + * @return The override content type, or null to not override + * the default + */ + public String getContentType() { + return contentType; + } + + /** + * Sets the override content type. + * + * @param contentType + * The override content type, or null to not + * override the default + */ + public void setContentType(String contentType) { + this.contentType = contentType; + } + + /** + * Returns the target of a redirect. + * + * @return The target URI of the redirect, or null if no + * redirect should be created + */ + public String getRedirectTarget() { + return redirectTarget; + } + + /** + * Sets the target of a redirect. + * + * @param redirectTarget + * The target URI of the redirect, or null if no + * redirect should be created + */ + public void setRedirectTarget(String redirectTarget) { + this.redirectTarget = redirectTarget; + } + + /** + * @see java.lang.Object#toString() + */ + @java.lang.Override + public String toString() { + return ((insert != null) ? String.valueOf(insert) : "") + "|" + ((contentType != null) ? contentType : "") + "|" + ((redirectTarget != null) ? redirectTarget : ""); + } + + /** + * Converts an override string created by {@link #toString()} back to an + * {@link FileOverride} object. + * + * @param overrideString + * The textual representation of the override + * @return The parsed override, or null if the string could + * not be parsed + */ + public static FileOverride valueOf(String overrideString) { + FileOverride override = new FileOverride(); + String[] parts = overrideString.split("\\|"); + logger.log(Level.FINEST, "parts.length: " + parts.length); + if ((parts.length > 0) && (parts[0].length() > 0)) { + override.insert = Boolean.valueOf(parts[0]); + } + if ((parts.length > 1) && (parts[1].length() > 0)) { + override.contentType = parts[1]; + } + if ((parts.length > 2) && (parts[2].length() > 0)) { + override.redirectTarget = parts[2]; + } + return override; + } + +} diff --git a/src/net/pterodactylus/jsite/core/project/Project.java b/src/net/pterodactylus/jsite/core/project/Project.java new file mode 100644 index 0000000..bd7634f --- /dev/null +++ b/src/net/pterodactylus/jsite/core/project/Project.java @@ -0,0 +1,595 @@ +/* + * jSite2 - Project.java - + * Copyright © 2008 David Roden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package net.pterodactylus.jsite.core.project; + +import java.beans.PropertyChangeListener; +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.pterodactylus.util.beans.AbstractBean; + +/** + * Container for project information. A Project is capable of notifying + * {@link PropertyChangeListener}s if any of the contained properties change. + * + * @author David ‘Bombe’ Roden <bombe@freenetproject.org> + */ +public class Project extends AbstractBean { + + /** Name of the “name” property. */ + public static final String PROPERTY_NAME = "name"; + + /** Name of the “description” property. */ + public static final String PROPERTY_DESCRIPTION = "description"; + + /** Name of the “public key” property. */ + public static final String PROPERTY_PUBLIC_KEY = "publicKey"; + + /** Name of the “private key” property. */ + public static final String PROPERTY_PRIVATE_KEY = "privateKey"; + + /** Name of the “base path” property. */ + public static final String PROPERTY_BASE_PATH = "basePath"; + + /** Name of the “default file” property. */ + public static final String PROPERTY_DEFAULT_FILE = "defaultFile"; + + /** Internal ID. */ + private String id; + + /** The name of the project. */ + private String name; + + /** The description of the project. */ + private String description; + + /** The public key. */ + private String publicKey; + + /** The private key. */ + private String privateKey; + + /** The base path of the project. */ + private String basePath; + + /** The default file. */ + private String defaultFile; + + /** The overrides. */ + private final Map fileOverrides = new HashMap(); + + /** The current root project file. */ + private ProjectFileImpl rootProjectFile; + + /** + * Creates a new project. + */ + public Project() { + /* do nothing. */ + } + + /** + * Clones the given project. + * + * @param project + */ + Project(Project project) { + this.name = project.name; + this.description = project.description; + this.publicKey = project.publicKey; + this.privateKey = project.privateKey; + this.basePath = project.basePath; + } + + /** + * Returns the internal ID. + * + * @return The internal ID + */ + String getId() { + return id; + } + + /** + * Sets the internal ID. + * + * @param id + * The internal ID + */ + void setId(String id) { + this.id = id; + } + + /** + * Returns the name of the project. + * + * @return The name of the project + */ + public String getName() { + return name; + } + + /** + * Sets the name of the project. + * + * @param name + * The name of the project + */ + public void setName(String name) { + String oldName = this.name; + this.name = name; + fireIfPropertyChanged(PROPERTY_NAME, oldName, name); + } + + /** + * Returns the description of the project. + * + * @return The description of the project + */ + public String getDescription() { + return description; + } + + /** + * Sets the description of the project + * + * @param description + * The description of the project + */ + public void setDescription(String description) { + String oldDescription = this.description; + this.description = description; + fireIfPropertyChanged(PROPERTY_DESCRIPTION, oldDescription, description); + } + + /** + * Returns the public key of the project. + * + * @return The public key of the project + */ + public String getPublicKey() { + return publicKey; + } + + /** + * Sets the public key of the project. + * + * @param publicKey + * The public key of the project + */ + void setPublicKey(String publicKey) { + String oldPublicKey = this.publicKey; + this.publicKey = publicKey; + fireIfPropertyChanged(PROPERTY_PUBLIC_KEY, oldPublicKey, publicKey); + } + + /** + * Returns the private key of the project. + * + * @return The private key of the project + */ + public String getPrivateKey() { + return privateKey; + } + + /** + * Sets the private key of the project. + * + * @param privateKey + * The private key of the project + */ + void setPrivateKey(String privateKey) { + String oldPrivateKey = this.privateKey; + this.privateKey = privateKey; + fireIfPropertyChanged(PROPERTY_PRIVATE_KEY, oldPrivateKey, privateKey); + } + + /** + * Returns the base path of the project. + * + * @return The base path of the project + */ + public String getBasePath() { + return basePath; + } + + /** + * Sets the base path of the project. + * + * @param basePath + * The base path of the project + */ + public void setBasePath(String basePath) { + String oldBasePath = this.basePath; + this.basePath = basePath; + fireIfPropertyChanged(PROPERTY_BASE_PATH, oldBasePath, basePath); + } + + /** + * Returns the default file. + * + * @return The default file + */ + public String getDefaultFile() { + return defaultFile; + } + + /** + * Sets the default file. + * + * @param defaultFile + * The default file + */ + public void setDefaultFile(String defaultFile) { + String oldDefaultFile = this.defaultFile; + this.defaultFile = defaultFile; + fireIfPropertyChanged(PROPERTY_DEFAULT_FILE, oldDefaultFile, defaultFile); + } + + /** + * Adds a file override for the given file. + * + * @param projectFile + * The file + * @param override + * The override for the file + */ + public void addFileOverride(ProjectFile projectFile, FileOverride override) { + addFileOverride(projectFile.getCompletePath(), override); + } + + /** + * Adds a file override for the given file. + * + * @param filePath + * The file path + * @param override + * The override for the file + */ + public void addFileOverride(String filePath, FileOverride override) { + fileOverrides.put(filePath, override); + } + + /** + * Removes the file override for the given file. + * + * @param projectFile + * The file for which to remove the override + */ + public void removeFileOverride(ProjectFile projectFile) { + removeFileOverride(projectFile.getCompletePath()); + } + + /** + * Removes the file override for the given file. + * + * @param filePath + * The file path for which to remove the override + */ + public void removeFileOverride(String filePath) { + fileOverrides.remove(filePath); + } + + /** + * Returns the file override for the given file. + * + * @param projectFile + * The file for which to get the override + * @return The file override, or null if the given file does + * not have an override + */ + public FileOverride getFileOverride(ProjectFile projectFile) { + return getFileOverride(projectFile.getCompletePath()); + } + + /** + * Returns the file override for the given file. + * + * @param filePath + * The file path for which to get the override + * @return The file override, or null if the given file does + * not have an override + */ + public FileOverride getFileOverride(String filePath) { + return fileOverrides.get(filePath); + } + + /** + * Returns the list of {@link FileOverride}s. + * + * @return All file overrides + */ + public Map getFileOverrides() { + return fileOverrides; + } + + /** + * Scans the base path for files and returns the {@link ProjectFile} for the + * base path. From this file it is possible to reach all files in the base + * path. This method is disk-intensive and may take some time on larger + * directories! + * + * @return The file for the base path, or null if the base + * path does not denote an existing directory + */ + public ProjectFile getBaseFile() { + File basePathFile = new File(basePath); + if (!basePathFile.exists() || !basePathFile.isDirectory()) { + return null; + } + rootProjectFile = new ProjectFileImpl(null, "", 0, true, false); + scanDirectory(basePathFile, rootProjectFile); + return rootProjectFile; + } + + /** + * Returns the file that is specified by its complete path. + * + * @param completePath + * The complete path of the file + * @return The project file at the given path, or null if + * there is no such file + */ + public ProjectFile getFile(String completePath) { + if (rootProjectFile == null) { + getBaseFile(); + } + if ((rootProjectFile == null) || (completePath.length() == 0)) { + return rootProjectFile; + } + String[] pathParts = completePath.split("\\" + File.separator); + ProjectFileImpl currentProjectFile = rootProjectFile; + for (String pathPart : pathParts) { + currentProjectFile = currentProjectFile.getFile(pathPart); + if (currentProjectFile == null) { + return null; + } + } + return currentProjectFile; + } + + // + // PRIVATE METHODS + // + + /** + * Scans the given directory and recreates the file and directory structure + * in the given project file. + * + * @param directory + * The directory to scan + * @param projectFile + * The project file in which to recreate the directory and file + * structure + */ + private void scanDirectory(File directory, ProjectFileImpl projectFile) { + if (!directory.isDirectory()) { + return; + } + for (File file : directory.listFiles()) { + ProjectFileImpl projectFileChild = projectFile.addFile(file.getName(), file.length(), file.isDirectory(), file.isHidden()); + if (file.isDirectory()) { + scanDirectory(file, projectFileChild); + } + } + projectFile.sort(); + } + + /** + * Implementation of a {@link ProjectFile}. + * + * @author David ‘Bombe’ Roden <bombe@freenetproject.org> + */ + private static class ProjectFileImpl implements ProjectFile, Comparable { + + /** The parent of this project file. */ + private final ProjectFileImpl parentProjectFile; + + /** The name of this project file. */ + private final String name; + + /** The size of the file. */ + private final long size; + + /** Whether this project file is a directory. */ + private final boolean directory; + + /** Whether this file is hidden. */ + private final boolean hidden; + + /** This project file’s children. */ + private List childProjectFiles = new ArrayList(); + + /** + * Creates a new project fie. + * + * @param parentProjectFile + * The parent of the project file, or null if + * the new project file does not have a parent + * @param name + * The name of the project file + * @param size + * The size of the file + * @param isDirectory + * true if this project file is a directory, + * false otherwise + * @param isHidden + * true if this project file is hidden, + * false otherwise + */ + ProjectFileImpl(ProjectFileImpl parentProjectFile, String name, long size, boolean isDirectory, boolean isHidden) { + this.parentProjectFile = parentProjectFile; + this.name = name; + this.size = size; + this.directory = isDirectory; + this.hidden = isHidden; + } + + // + // INTERFACE ProjectFile + // + + /** + * @see net.pterodactylus.jsite.core.project.ProjectFile#getName() + */ + public String getName() { + return name; + } + + /** + * @see net.pterodactylus.jsite.core.project.ProjectFile#getParent() + */ + public ProjectFile getParent() { + return parentProjectFile; + } + + /** + * {@inheritDoc} + */ + public long getSize() { + return size; + } + + /** + * @see net.pterodactylus.jsite.core.project.ProjectFile#getParents() + */ + public List getParents() { + List parentProjectFiles = new ArrayList(); + ProjectFileImpl currentProjectFile = this; + do { + parentProjectFiles.add(0, currentProjectFile); + } while ((currentProjectFile = currentProjectFile.parentProjectFile) != null); + return parentProjectFiles; + } + + /** + * {@inheritDoc} + */ + /* TODO - caching? */ + public String getCompletePath() { + StringBuilder completePath = new StringBuilder(); + ProjectFileImpl currentProjectFile = this; + while ((currentProjectFile != null) && (currentProjectFile.parentProjectFile != null)) { + completePath.insert(0, currentProjectFile.getName()).insert(0, File.separatorChar); + currentProjectFile = currentProjectFile.parentProjectFile; + } + return (completePath.length() > 0) ? completePath.substring(1) : ""; + } + + /** + * @see net.pterodactylus.jsite.core.project.ProjectFile#isFile() + */ + public boolean isFile() { + return !directory; + } + + /** + * @see net.pterodactylus.jsite.core.project.ProjectFile#isDirectory() + */ + public boolean isDirectory() { + return directory; + } + + /** + * @see net.pterodactylus.jsite.core.project.ProjectFile#isHidden() + */ + public boolean isHidden() { + return hidden; + } + + /** + * Returns the project file with the given name. The project file has to + * be a direct child of this project file. + * + * @param name + * The name of the file to get + * @return The project file, or null if there is no + * project file by that name + */ + public ProjectFileImpl getFile(String name) { + if (!isDirectory()) { + return null; + } + for (ProjectFileImpl projectFile : childProjectFiles) { + if (projectFile.getName().equals(name)) { + return projectFile; + } + } + return null; + } + + /** + * @see net.pterodactylus.jsite.core.project.ProjectFile#getFiles() + */ + public List getFiles() { + List projectFiles = new ArrayList(childProjectFiles); + return projectFiles; + } + + // + // ACTIONS + // + + /** + * Adds a new project file as child to this project file. + * + * @param name + * The name of the file + * @param size + * The size of the file + * @param isDirectory + * true if the new file is a directory, + * false otherwise + * @param isHidden + * true if the new file is hidden, + * false otherwise + * @return The created project file + */ + public ProjectFileImpl addFile(String name, long size, boolean isDirectory, boolean isHidden) { + ProjectFileImpl newProjectFile = new ProjectFileImpl(this, name, size, isDirectory, isHidden); + childProjectFiles.add(newProjectFile); + return newProjectFile; + } + + /** + * Sorts the children of this file. + */ + public void sort() { + Collections.sort(childProjectFiles); + } + + // + // INTERFACE Comparable + // + + /** + * {@inheritDoc} + */ + public int compareTo(ProjectFileImpl otherProjectFileImpl) { + return name.compareTo(otherProjectFileImpl.name); + } + + } + +} diff --git a/src/net/pterodactylus/jsite/core/project/ProjectFile.java b/src/net/pterodactylus/jsite/core/project/ProjectFile.java new file mode 100644 index 0000000..abb5d0a --- /dev/null +++ b/src/net/pterodactylus/jsite/core/project/ProjectFile.java @@ -0,0 +1,108 @@ +/* + * jSite2 - ProjectFile.java - + * Copyright © 2008 David Roden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package net.pterodactylus.jsite.core.project; + +import java.io.File; +import java.util.List; + +import net.pterodactylus.jsite.core.Core; + +/** + * Abstraction for a that exists on the machine {@link Core} is being run on. + * This abstraction layer exists to make it possible to run jSite as a daemon + * and only connect to it via network. + * + * @author David ‘Bombe’ Roden <bombe@freenetproject.org> + */ +public interface ProjectFile { + + /** + * Returns the name of the file. + * + * @return The name of the file + */ + public String getName(); + + /** + * Returns the parent of this project file. + * + * @return The parent of this project file, or null if this + * project file does not have a parent + */ + public ProjectFile getParent(); + + /** + * Returns all parent files of this file. This file is the last file in the + * returned list. + * + * @return A list of all parents of this file and this file itself + */ + public List getParents(); + + /** + * Returns the complete path of this file, without a leading + * {@link File#separator}. + * + * @return The complete path of this file + */ + public String getCompletePath(); + + /** + * Returns the size of the file. If this file is a directory, the returned + * value is unspecified. + * + * @see File#length() + * @return The size of the file + */ + public long getSize(); + + /** + * Returns whether this file is a directory. + * + * @return true if this file is a directory, + * false otherwise + */ + public boolean isDirectory(); + + /** + * Returns whether this file is a file (as opposed to being a directory). + * + * @return true if this file is a file, false + * otherwise + */ + public boolean isFile(); + + /** + * Returns whether this file is hidden. + * + * @return true if this file is hidden + */ + public boolean isHidden(); + + /** + * If this file is a directory, returns all files in this directory. + * + * @see #isDirectory() + * @return All files in this directory if this file is a directory, or + * null if this file is not a directory + */ + public List getFiles(); + +} diff --git a/src/net/pterodactylus/jsite/core/project/ProjectManager.java b/src/net/pterodactylus/jsite/core/project/ProjectManager.java new file mode 100644 index 0000000..62e8f8e --- /dev/null +++ b/src/net/pterodactylus/jsite/core/project/ProjectManager.java @@ -0,0 +1,307 @@ +/* + * jSite2 - ProjectManager.java - + * Copyright © 2008 David Roden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package net.pterodactylus.jsite.core.project; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; +import java.util.Random; +import java.util.Map.Entry; +import java.util.logging.Level; +import java.util.logging.Logger; + +import net.pterodactylus.jsite.core.JSiteException; +import net.pterodactylus.jsite.core.NodeManager; +import net.pterodactylus.util.io.Closer; +import net.pterodactylus.util.logging.Logging; +import net.pterodactylus.util.number.Hex; + +/** + * Manages projects, taking care of persistence, lifetime statistics, and other + * things. + * + * @author David ‘Bombe’ Roden <bombe@freenetproject.org> + */ +public class ProjectManager implements PropertyChangeListener { + + /** Logger. */ + private static final Logger logger = Logging.getLogger(ProjectManager.class.getName()); + + /** The RNG used to create project IDs. */ + private static final Random random = new Random(); + + /** The directory the projects are stored in. */ + private final String directory; + + /** The node manager. */ + private NodeManager nodeManager; + + /** All projects. */ + private final List projects = Collections.synchronizedList(new ArrayList()); + + /** + * Creates a new project manager that saves and restores its state to/from + * the given directory. + * + * @param directory + * The directory to save and restore states to/from + */ + public ProjectManager(String directory) { + this.directory = directory; + } + + // + // ACCESSORS + // + + /** + * Returns the directory the projects are loaded from and saved to. + * + * @return The directory for storing the projects + */ + public String getDirectory() { + return directory; + } + + /** + * Returns a list of all projects. + * + * @return A list of all projects + */ + public List getProjects() { + return Collections.unmodifiableList(new ArrayList(projects)); + } + + /** + * Sets the node manager to use. + * + * @param nodeManager + * The node manager to use + */ + public void setNodeManager(NodeManager nodeManager) { + this.nodeManager = nodeManager; + } + + // + // ACTIONS + // + + /** + * Loads projects and statistics. + * + * @throws IOException + * if an I/O error occurs + */ + public void load() throws IOException { + File directoryFile = new File(directory); + File projectFile = new File(directoryFile, "projects.properties"); + if (!projectFile.exists() || !projectFile.isFile() || !projectFile.canRead()) { + return; + } + Properties projectProperties = new Properties(); + InputStream projectInputStream = null; + try { + projectInputStream = new FileInputStream(projectFile); + projectProperties.load(projectInputStream); + } finally { + Closer.close(projectInputStream); + } + int projectIndex = 0; + while (projectProperties.containsKey("projects." + projectIndex + ".name")) { + String projectPrefix = "projects." + projectIndex; + String projectId = projectProperties.getProperty(projectPrefix + ".id"); + String projectName = projectProperties.getProperty(projectPrefix + ".name"); + String projectDescription = projectProperties.getProperty(projectPrefix + ".description"); + String projectPrivateKey = projectProperties.getProperty(projectPrefix + ".privateKey"); + String projectPublicKey = projectProperties.getProperty(projectPrefix + ".publicKey"); + String projectBasePath = projectProperties.getProperty(projectPrefix + ".basePath"); + String projectDefaultFile = projectProperties.getProperty(projectPrefix + ".defaultFile"); + Project project = new Project(); + project.setId(projectId); + project.setName(projectName); + project.setDescription(projectDescription); + project.setPrivateKey(projectPrivateKey); + project.setPublicKey(projectPublicKey); + project.setBasePath(projectBasePath); + project.setDefaultFile(projectDefaultFile); + int overrideIndex = 0; + while (projectProperties.containsKey(projectPrefix + ".overrides." + overrideIndex + ".override")) { + String filePath = projectProperties.getProperty(projectPrefix + ".overrides." + overrideIndex + ".filePath"); + FileOverride override = FileOverride.valueOf(projectProperties.getProperty(projectPrefix + ".overrides." + overrideIndex + ".override")); + project.addFileOverride(filePath, override); + logger.log(Level.FINEST, "read override: " + filePath + ", " + override); + overrideIndex++; + } + projects.add(project); + logger.fine("loaded project “" + project.getName() + "”."); + projectIndex++; + } + } + + /** + * Saves projects and statistics. + * + * @throws IOException + * if an I/O error occurs + */ + public void save() throws IOException { + File directoryFile = new File(directory); + if (!directoryFile.exists()) { + if (!directoryFile.mkdirs()) { + throw new IOException("could not create directory: " + directory); + } + } + Properties projectProperties = new Properties(); + int projectIndex = 0; + for (Project project : projects) { + String projectPrefix = "projects." + projectIndex; + projectProperties.setProperty(projectPrefix + ".id", project.getId()); + projectProperties.setProperty(projectPrefix + ".name", project.getName()); + projectProperties.setProperty(projectPrefix + ".description", project.getDescription()); + projectProperties.setProperty(projectPrefix + ".privateKey", project.getPrivateKey()); + projectProperties.setProperty(projectPrefix + ".publicKey", project.getPublicKey()); + projectProperties.setProperty(projectPrefix + ".basePath", project.getBasePath()); + projectProperties.setProperty(projectPrefix + ".defaultFile", project.getDefaultFile()); + int overrideIndex = 0; + for (Entry overrideEntry : project.getFileOverrides().entrySet()) { + projectProperties.setProperty(projectPrefix + ".overrides." + overrideIndex + ".filePath", overrideEntry.getKey()); + projectProperties.setProperty(projectPrefix + ".overrides." + overrideIndex + ".override", overrideEntry.getValue().toString()); + overrideIndex++; + } + projectIndex++; + } + File projectFile = new File(directoryFile, "projects.properties"); + OutputStream projectOutputStream = null; + try { + projectOutputStream = new FileOutputStream(projectFile); + projectProperties.store(projectOutputStream, "jSite projects"); + } finally { + Closer.close(projectOutputStream); + } + } + + /** + * Creates a new project. The returned {@link Project} will contain a newly + * generated key pair. + * + * @return A newly created project + * @throws IOException + * if an I/O error occured communicating with the node + * @throws JSiteException + * if there is a problem with the node + */ + public Project createProject() throws IOException, JSiteException { + Project project = new Project(); + String[] keyPair = nodeManager.generateKeyPair(); + project.setId(generateId()); + project.setName(""); + project.setDescription(""); + project.setPrivateKey(keyPair[0]); + project.setPublicKey(keyPair[1]); + project.setBasePath(""); + project.setDefaultFile(""); + projects.add(project); + project.addPropertyChangeListener(this); + try { + save(); + } catch (IOException ioe1) { + /* ignore. */ + } + return project; + } + + /** + * Clones the given project and returns the clone. The clone will be + * identical in all user-exposed fields, except for the project’s + * {@link Project#getId ID}. + * + * @param project + * The project to clone + * @return The cloned project + */ + public Project cloneProject(Project project) { + Project projectClone = new Project(project); + projects.add(projectClone); + projectClone.setId(generateId()); + projectClone.addPropertyChangeListener(this); + try { + save(); + } catch (IOException ioe1) { + /* ignore. */ + } + return projectClone; + } + + /** + * Removes the given project. + * + * @param project + * The project to remove + */ + public void removeProject(Project project) { + projects.remove(project); + try { + save(); + } catch (IOException ioe1) { + /* ignore. */ + } + } + + // + // PRIVATE METHODS + // + + /** + * Generates a new random ID, consisting of 16 random bytes converted to a + * hexadecimal number. + * + * @return The new ID + */ + private static String generateId() { + byte[] idBytes = new byte[16]; + random.nextBytes(idBytes); + return Hex.toHex(idBytes); + } + + // + // INTERFACE PropertyChangeListener + // + + /** + * {@inheritDoc} + */ + public void propertyChange(PropertyChangeEvent propertyChangeEvent) { + try { + save(); + } catch (IOException ioe1) { + /* ignore. */ + } + } + +} diff --git a/src/net/pterodactylus/jsite/gui/FileManager.java b/src/net/pterodactylus/jsite/gui/FileManager.java index d69d222..3058023 100644 --- a/src/net/pterodactylus/jsite/gui/FileManager.java +++ b/src/net/pterodactylus/jsite/gui/FileManager.java @@ -70,14 +70,14 @@ import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; +import net.pterodactylus.jsite.core.project.FileOverride; +import net.pterodactylus.jsite.core.project.Project; +import net.pterodactylus.jsite.core.project.ProjectFile; import net.pterodactylus.jsite.i18n.I18n; import net.pterodactylus.jsite.i18n.I18nable; import net.pterodactylus.jsite.i18n.gui.I18nAction; import net.pterodactylus.jsite.i18n.gui.I18nLabel; import net.pterodactylus.jsite.i18n.gui.I18nMenu; -import net.pterodactylus.jsite.project.FileOverride; -import net.pterodactylus.jsite.project.Project; -import net.pterodactylus.jsite.project.ProjectFile; import net.pterodactylus.util.io.MimeTypes; import net.pterodactylus.util.logging.Logging; import net.pterodactylus.util.swing.SwingUtils; diff --git a/src/net/pterodactylus/jsite/gui/MainWindow.java b/src/net/pterodactylus/jsite/gui/MainWindow.java index 2a50313..134d508 100644 --- a/src/net/pterodactylus/jsite/gui/MainWindow.java +++ b/src/net/pterodactylus/jsite/gui/MainWindow.java @@ -51,12 +51,12 @@ import javax.swing.SwingConstants; import javax.swing.border.EmptyBorder; import net.pterodactylus.jsite.core.Node; +import net.pterodactylus.jsite.core.project.Project; import net.pterodactylus.jsite.i18n.I18n; import net.pterodactylus.jsite.i18n.I18nable; import net.pterodactylus.jsite.i18n.gui.I18nAction; import net.pterodactylus.jsite.i18n.gui.I18nMenu; import net.pterodactylus.jsite.main.Version; -import net.pterodactylus.jsite.project.Project; import net.pterodactylus.util.image.IconLoader; import net.pterodactylus.util.logging.Logging; import net.pterodactylus.util.swing.StatusBar; diff --git a/src/net/pterodactylus/jsite/gui/ProjectPanel.java b/src/net/pterodactylus/jsite/gui/ProjectPanel.java index 0b37d70..42ac416 100644 --- a/src/net/pterodactylus/jsite/gui/ProjectPanel.java +++ b/src/net/pterodactylus/jsite/gui/ProjectPanel.java @@ -37,11 +37,11 @@ import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.Document; +import net.pterodactylus.jsite.core.project.Project; import net.pterodactylus.jsite.i18n.I18n; import net.pterodactylus.jsite.i18n.I18nable; import net.pterodactylus.jsite.i18n.gui.I18nAction; import net.pterodactylus.jsite.i18n.gui.I18nLabel; -import net.pterodactylus.jsite.project.Project; import net.pterodactylus.util.logging.Logging; /** diff --git a/src/net/pterodactylus/jsite/gui/SwingInterface.java b/src/net/pterodactylus/jsite/gui/SwingInterface.java index cf6f4e1..0801a51 100644 --- a/src/net/pterodactylus/jsite/gui/SwingInterface.java +++ b/src/net/pterodactylus/jsite/gui/SwingInterface.java @@ -49,9 +49,9 @@ import net.pterodactylus.jsite.core.Core; import net.pterodactylus.jsite.core.CoreListener; import net.pterodactylus.jsite.core.JSiteException; import net.pterodactylus.jsite.core.Node; +import net.pterodactylus.jsite.core.project.Project; import net.pterodactylus.jsite.i18n.I18n; import net.pterodactylus.jsite.i18n.gui.I18nAction; -import net.pterodactylus.jsite.project.Project; import net.pterodactylus.util.image.IconLoader; import net.pterodactylus.util.io.Closer; import net.pterodactylus.util.logging.Logging; @@ -1037,14 +1037,14 @@ public class SwingInterface implements CoreListener, LoggingListener, PropertyCh } /** - * @see net.pterodactylus.jsite.core.CoreListener#projectInsertStarted(net.pterodactylus.jsite.project.Project) + * @see net.pterodactylus.jsite.core.CoreListener#projectInsertStarted(net.pterodactylus.jsite.core.project.Project) */ public void projectInsertStarted(Project project) { mainWindow.projectInsertStarted(project); } /** - * @see net.pterodactylus.jsite.core.CoreListener#projectInsertProgressed(net.pterodactylus.jsite.project.Project, + * @see net.pterodactylus.jsite.core.CoreListener#projectInsertProgressed(net.pterodactylus.jsite.core.project.Project, * int, int, int, int, int, boolean) */ public void projectInsertProgressed(Project project, int totalBlocks, int requiredBlocks, int successfulBlocks, int failedBlocks, int fatallyFailedBlocks, boolean finalizedTotal) { @@ -1052,7 +1052,7 @@ public class SwingInterface implements CoreListener, LoggingListener, PropertyCh } /** - * @see net.pterodactylus.jsite.core.CoreListener#projectInsertGeneratedURI(net.pterodactylus.jsite.project.Project, + * @see net.pterodactylus.jsite.core.CoreListener#projectInsertGeneratedURI(net.pterodactylus.jsite.core.project.Project, * java.lang.String) */ public void projectInsertGeneratedURI(Project project, String uri) { @@ -1060,7 +1060,7 @@ public class SwingInterface implements CoreListener, LoggingListener, PropertyCh } /** - * @see net.pterodactylus.jsite.core.CoreListener#projectInsertFinished(net.pterodactylus.jsite.project.Project, + * @see net.pterodactylus.jsite.core.CoreListener#projectInsertFinished(net.pterodactylus.jsite.core.project.Project, * boolean) */ public void projectInsertFinished(Project project, boolean success) { diff --git a/src/net/pterodactylus/jsite/main/Main.java b/src/net/pterodactylus/jsite/main/Main.java index 2552260..e5e0030 100644 --- a/src/net/pterodactylus/jsite/main/Main.java +++ b/src/net/pterodactylus/jsite/main/Main.java @@ -30,8 +30,8 @@ import javax.swing.UIManager.LookAndFeelInfo; import net.pterodactylus.jsite.core.CoreImpl; import net.pterodactylus.jsite.core.NodeManager; import net.pterodactylus.jsite.core.RequestManager; +import net.pterodactylus.jsite.core.project.ProjectManager; import net.pterodactylus.jsite.gui.SwingInterface; -import net.pterodactylus.jsite.project.ProjectManager; import net.pterodactylus.util.logging.Logging; /** diff --git a/src/net/pterodactylus/jsite/project/FileOverride.java b/src/net/pterodactylus/jsite/project/FileOverride.java deleted file mode 100644 index f9b44ab..0000000 --- a/src/net/pterodactylus/jsite/project/FileOverride.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * jSite2 - Override.java - - * Copyright © 2008 David Roden - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -package net.pterodactylus.jsite.project; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import net.pterodactylus.util.logging.Logging; - -/** - * An override is used to enter other information about a file than the defaults - * would have yielded. It is also used to add redirects to a project. - * - * @author David ‘Bombe’ Roden <bombe@freenetproject.org> - * @version $Id$ - */ -public class FileOverride { - - /** The logger. */ - private static final Logger logger = Logging.getLogger(FileOverride.class.getName()); - - /** The insert override. */ - private Boolean insert; - - /** The override content type. */ - private String contentType; - - /** The redirect target. */ - private String redirectTarget; - - /** - * Checks whether this override has any content. - * - * @return true if this override does not have any effects, - * false otherwise - */ - public boolean isEmpty() { - return (insert == null) && (contentType == null) && (redirectTarget == null); - } - - /** - * Returns the insert override. - * - * @return true if the entry should be inserted, - * false if it should not be inserted, - * null if the default should not be overridden - */ - public Boolean isInsert() { - return insert; - } - - /** - * Sets the insert override. - * - * @param insert - * true if the entry should be inserted, - * false if it should not be inserted, - * null if the default should not be overridden - */ - public void setInsert(Boolean insert) { - this.insert = insert; - } - - /** - * Returns the override content type. - * - * @return The override content type, or null to not override - * the default - */ - public String getContentType() { - return contentType; - } - - /** - * Sets the override content type. - * - * @param contentType - * The override content type, or null to not - * override the default - */ - public void setContentType(String contentType) { - this.contentType = contentType; - } - - /** - * Returns the target of a redirect. - * - * @return The target URI of the redirect, or null if no - * redirect should be created - */ - public String getRedirectTarget() { - return redirectTarget; - } - - /** - * Sets the target of a redirect. - * - * @param redirectTarget - * The target URI of the redirect, or null if no - * redirect should be created - */ - public void setRedirectTarget(String redirectTarget) { - this.redirectTarget = redirectTarget; - } - - /** - * @see java.lang.Object#toString() - */ - @java.lang.Override - public String toString() { - return ((insert != null) ? String.valueOf(insert) : "") + "|" + ((contentType != null) ? contentType : "") + "|" + ((redirectTarget != null) ? redirectTarget : ""); - } - - /** - * Converts an override string created by {@link #toString()} back to an - * {@link FileOverride} object. - * - * @param overrideString - * The textual representation of the override - * @return The parsed override, or null if the string could - * not be parsed - */ - public static FileOverride valueOf(String overrideString) { - FileOverride override = new FileOverride(); - String[] parts = overrideString.split("\\|"); - logger.log(Level.FINEST, "parts.length: " + parts.length); - if ((parts.length > 0) && (parts[0].length() > 0)) { - override.insert = Boolean.valueOf(parts[0]); - } - if ((parts.length > 1) && (parts[1].length() > 0)) { - override.contentType = parts[1]; - } - if ((parts.length > 2) && (parts[2].length() > 0)) { - override.redirectTarget = parts[2]; - } - return override; - } - -} diff --git a/src/net/pterodactylus/jsite/project/Project.java b/src/net/pterodactylus/jsite/project/Project.java deleted file mode 100644 index 22e66d8..0000000 --- a/src/net/pterodactylus/jsite/project/Project.java +++ /dev/null @@ -1,595 +0,0 @@ -/* - * jSite2 - Project.java - - * Copyright © 2008 David Roden - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -package net.pterodactylus.jsite.project; - -import java.beans.PropertyChangeListener; -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import net.pterodactylus.util.beans.AbstractBean; - -/** - * Container for project information. A Project is capable of notifying - * {@link PropertyChangeListener}s if any of the contained properties change. - * - * @author David ‘Bombe’ Roden <bombe@freenetproject.org> - */ -public class Project extends AbstractBean { - - /** Name of the “name” property. */ - public static final String PROPERTY_NAME = "name"; - - /** Name of the “description” property. */ - public static final String PROPERTY_DESCRIPTION = "description"; - - /** Name of the “public key” property. */ - public static final String PROPERTY_PUBLIC_KEY = "publicKey"; - - /** Name of the “private key” property. */ - public static final String PROPERTY_PRIVATE_KEY = "privateKey"; - - /** Name of the “base path” property. */ - public static final String PROPERTY_BASE_PATH = "basePath"; - - /** Name of the “default file” property. */ - public static final String PROPERTY_DEFAULT_FILE = "defaultFile"; - - /** Internal ID. */ - private String id; - - /** The name of the project. */ - private String name; - - /** The description of the project. */ - private String description; - - /** The public key. */ - private String publicKey; - - /** The private key. */ - private String privateKey; - - /** The base path of the project. */ - private String basePath; - - /** The default file. */ - private String defaultFile; - - /** The overrides. */ - private final Map fileOverrides = new HashMap(); - - /** The current root project file. */ - private ProjectFileImpl rootProjectFile; - - /** - * Creates a new project. - */ - public Project() { - /* do nothing. */ - } - - /** - * Clones the given project. - * - * @param project - */ - Project(Project project) { - this.name = project.name; - this.description = project.description; - this.publicKey = project.publicKey; - this.privateKey = project.privateKey; - this.basePath = project.basePath; - } - - /** - * Returns the internal ID. - * - * @return The internal ID - */ - String getId() { - return id; - } - - /** - * Sets the internal ID. - * - * @param id - * The internal ID - */ - void setId(String id) { - this.id = id; - } - - /** - * Returns the name of the project. - * - * @return The name of the project - */ - public String getName() { - return name; - } - - /** - * Sets the name of the project. - * - * @param name - * The name of the project - */ - public void setName(String name) { - String oldName = this.name; - this.name = name; - fireIfPropertyChanged(PROPERTY_NAME, oldName, name); - } - - /** - * Returns the description of the project. - * - * @return The description of the project - */ - public String getDescription() { - return description; - } - - /** - * Sets the description of the project - * - * @param description - * The description of the project - */ - public void setDescription(String description) { - String oldDescription = this.description; - this.description = description; - fireIfPropertyChanged(PROPERTY_DESCRIPTION, oldDescription, description); - } - - /** - * Returns the public key of the project. - * - * @return The public key of the project - */ - public String getPublicKey() { - return publicKey; - } - - /** - * Sets the public key of the project. - * - * @param publicKey - * The public key of the project - */ - void setPublicKey(String publicKey) { - String oldPublicKey = this.publicKey; - this.publicKey = publicKey; - fireIfPropertyChanged(PROPERTY_PUBLIC_KEY, oldPublicKey, publicKey); - } - - /** - * Returns the private key of the project. - * - * @return The private key of the project - */ - public String getPrivateKey() { - return privateKey; - } - - /** - * Sets the private key of the project. - * - * @param privateKey - * The private key of the project - */ - void setPrivateKey(String privateKey) { - String oldPrivateKey = this.privateKey; - this.privateKey = privateKey; - fireIfPropertyChanged(PROPERTY_PRIVATE_KEY, oldPrivateKey, privateKey); - } - - /** - * Returns the base path of the project. - * - * @return The base path of the project - */ - public String getBasePath() { - return basePath; - } - - /** - * Sets the base path of the project. - * - * @param basePath - * The base path of the project - */ - public void setBasePath(String basePath) { - String oldBasePath = this.basePath; - this.basePath = basePath; - fireIfPropertyChanged(PROPERTY_BASE_PATH, oldBasePath, basePath); - } - - /** - * Returns the default file. - * - * @return The default file - */ - public String getDefaultFile() { - return defaultFile; - } - - /** - * Sets the default file. - * - * @param defaultFile - * The default file - */ - public void setDefaultFile(String defaultFile) { - String oldDefaultFile = this.defaultFile; - this.defaultFile = defaultFile; - fireIfPropertyChanged(PROPERTY_DEFAULT_FILE, oldDefaultFile, defaultFile); - } - - /** - * Adds a file override for the given file. - * - * @param projectFile - * The file - * @param override - * The override for the file - */ - public void addFileOverride(ProjectFile projectFile, FileOverride override) { - addFileOverride(projectFile.getCompletePath(), override); - } - - /** - * Adds a file override for the given file. - * - * @param filePath - * The file path - * @param override - * The override for the file - */ - public void addFileOverride(String filePath, FileOverride override) { - fileOverrides.put(filePath, override); - } - - /** - * Removes the file override for the given file. - * - * @param projectFile - * The file for which to remove the override - */ - public void removeFileOverride(ProjectFile projectFile) { - removeFileOverride(projectFile.getCompletePath()); - } - - /** - * Removes the file override for the given file. - * - * @param filePath - * The file path for which to remove the override - */ - public void removeFileOverride(String filePath) { - fileOverrides.remove(filePath); - } - - /** - * Returns the file override for the given file. - * - * @param projectFile - * The file for which to get the override - * @return The file override, or null if the given file does - * not have an override - */ - public FileOverride getFileOverride(ProjectFile projectFile) { - return getFileOverride(projectFile.getCompletePath()); - } - - /** - * Returns the file override for the given file. - * - * @param filePath - * The file path for which to get the override - * @return The file override, or null if the given file does - * not have an override - */ - public FileOverride getFileOverride(String filePath) { - return fileOverrides.get(filePath); - } - - /** - * Returns the list of {@link FileOverride}s. - * - * @return All file overrides - */ - public Map getFileOverrides() { - return fileOverrides; - } - - /** - * Scans the base path for files and returns the {@link ProjectFile} for the - * base path. From this file it is possible to reach all files in the base - * path. This method is disk-intensive and may take some time on larger - * directories! - * - * @return The file for the base path, or null if the base - * path does not denote an existing directory - */ - public ProjectFile getBaseFile() { - File basePathFile = new File(basePath); - if (!basePathFile.exists() || !basePathFile.isDirectory()) { - return null; - } - rootProjectFile = new ProjectFileImpl(null, "", 0, true, false); - scanDirectory(basePathFile, rootProjectFile); - return rootProjectFile; - } - - /** - * Returns the file that is specified by its complete path. - * - * @param completePath - * The complete path of the file - * @return The project file at the given path, or null if - * there is no such file - */ - public ProjectFile getFile(String completePath) { - if (rootProjectFile == null) { - getBaseFile(); - } - if ((rootProjectFile == null) || (completePath.length() == 0)) { - return rootProjectFile; - } - String[] pathParts = completePath.split("\\" + File.separator); - ProjectFileImpl currentProjectFile = rootProjectFile; - for (String pathPart : pathParts) { - currentProjectFile = currentProjectFile.getFile(pathPart); - if (currentProjectFile == null) { - return null; - } - } - return currentProjectFile; - } - - // - // PRIVATE METHODS - // - - /** - * Scans the given directory and recreates the file and directory structure - * in the given project file. - * - * @param directory - * The directory to scan - * @param projectFile - * The project file in which to recreate the directory and file - * structure - */ - private void scanDirectory(File directory, ProjectFileImpl projectFile) { - if (!directory.isDirectory()) { - return; - } - for (File file : directory.listFiles()) { - ProjectFileImpl projectFileChild = projectFile.addFile(file.getName(), file.length(), file.isDirectory(), file.isHidden()); - if (file.isDirectory()) { - scanDirectory(file, projectFileChild); - } - } - projectFile.sort(); - } - - /** - * Implementation of a {@link ProjectFile}. - * - * @author David ‘Bombe’ Roden <bombe@freenetproject.org> - */ - private static class ProjectFileImpl implements ProjectFile, Comparable { - - /** The parent of this project file. */ - private final ProjectFileImpl parentProjectFile; - - /** The name of this project file. */ - private final String name; - - /** The size of the file. */ - private final long size; - - /** Whether this project file is a directory. */ - private final boolean directory; - - /** Whether this file is hidden. */ - private final boolean hidden; - - /** This project file’s children. */ - private List childProjectFiles = new ArrayList(); - - /** - * Creates a new project fie. - * - * @param parentProjectFile - * The parent of the project file, or null if - * the new project file does not have a parent - * @param name - * The name of the project file - * @param size - * The size of the file - * @param isDirectory - * true if this project file is a directory, - * false otherwise - * @param isHidden - * true if this project file is hidden, - * false otherwise - */ - ProjectFileImpl(ProjectFileImpl parentProjectFile, String name, long size, boolean isDirectory, boolean isHidden) { - this.parentProjectFile = parentProjectFile; - this.name = name; - this.size = size; - this.directory = isDirectory; - this.hidden = isHidden; - } - - // - // INTERFACE ProjectFile - // - - /** - * @see net.pterodactylus.jsite.project.ProjectFile#getName() - */ - public String getName() { - return name; - } - - /** - * @see net.pterodactylus.jsite.project.ProjectFile#getParent() - */ - public ProjectFile getParent() { - return parentProjectFile; - } - - /** - * {@inheritDoc} - */ - public long getSize() { - return size; - } - - /** - * @see net.pterodactylus.jsite.project.ProjectFile#getParents() - */ - public List getParents() { - List parentProjectFiles = new ArrayList(); - ProjectFileImpl currentProjectFile = this; - do { - parentProjectFiles.add(0, currentProjectFile); - } while ((currentProjectFile = currentProjectFile.parentProjectFile) != null); - return parentProjectFiles; - } - - /** - * {@inheritDoc} - */ - /* TODO - caching? */ - public String getCompletePath() { - StringBuilder completePath = new StringBuilder(); - ProjectFileImpl currentProjectFile = this; - while ((currentProjectFile != null) && (currentProjectFile.parentProjectFile != null)) { - completePath.insert(0, currentProjectFile.getName()).insert(0, File.separatorChar); - currentProjectFile = currentProjectFile.parentProjectFile; - } - return (completePath.length() > 0) ? completePath.substring(1) : ""; - } - - /** - * @see net.pterodactylus.jsite.project.ProjectFile#isFile() - */ - public boolean isFile() { - return !directory; - } - - /** - * @see net.pterodactylus.jsite.project.ProjectFile#isDirectory() - */ - public boolean isDirectory() { - return directory; - } - - /** - * @see net.pterodactylus.jsite.project.ProjectFile#isHidden() - */ - public boolean isHidden() { - return hidden; - } - - /** - * Returns the project file with the given name. The project file has to - * be a direct child of this project file. - * - * @param name - * The name of the file to get - * @return The project file, or null if there is no - * project file by that name - */ - public ProjectFileImpl getFile(String name) { - if (!isDirectory()) { - return null; - } - for (ProjectFileImpl projectFile : childProjectFiles) { - if (projectFile.getName().equals(name)) { - return projectFile; - } - } - return null; - } - - /** - * @see net.pterodactylus.jsite.project.ProjectFile#getFiles() - */ - public List getFiles() { - List projectFiles = new ArrayList(childProjectFiles); - return projectFiles; - } - - // - // ACTIONS - // - - /** - * Adds a new project file as child to this project file. - * - * @param name - * The name of the file - * @param size - * The size of the file - * @param isDirectory - * true if the new file is a directory, - * false otherwise - * @param isHidden - * true if the new file is hidden, - * false otherwise - * @return The created project file - */ - public ProjectFileImpl addFile(String name, long size, boolean isDirectory, boolean isHidden) { - ProjectFileImpl newProjectFile = new ProjectFileImpl(this, name, size, isDirectory, isHidden); - childProjectFiles.add(newProjectFile); - return newProjectFile; - } - - /** - * Sorts the children of this file. - */ - public void sort() { - Collections.sort(childProjectFiles); - } - - // - // INTERFACE Comparable - // - - /** - * {@inheritDoc} - */ - public int compareTo(ProjectFileImpl otherProjectFileImpl) { - return name.compareTo(otherProjectFileImpl.name); - } - - } - -} diff --git a/src/net/pterodactylus/jsite/project/ProjectFile.java b/src/net/pterodactylus/jsite/project/ProjectFile.java deleted file mode 100644 index 7f9cc2d..0000000 --- a/src/net/pterodactylus/jsite/project/ProjectFile.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * jSite2 - ProjectFile.java - - * Copyright © 2008 David Roden - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -package net.pterodactylus.jsite.project; - -import java.io.File; -import java.util.List; - -import net.pterodactylus.jsite.core.Core; - -/** - * Abstraction for a that exists on the machine {@link Core} is being run on. - * This abstraction layer exists to make it possible to run jSite as a daemon - * and only connect to it via network. - * - * @author David ‘Bombe’ Roden <bombe@freenetproject.org> - */ -public interface ProjectFile { - - /** - * Returns the name of the file. - * - * @return The name of the file - */ - public String getName(); - - /** - * Returns the parent of this project file. - * - * @return The parent of this project file, or null if this - * project file does not have a parent - */ - public ProjectFile getParent(); - - /** - * Returns all parent files of this file. This file is the last file in the - * returned list. - * - * @return A list of all parents of this file and this file itself - */ - public List getParents(); - - /** - * Returns the complete path of this file, without a leading - * {@link File#separator}. - * - * @return The complete path of this file - */ - public String getCompletePath(); - - /** - * Returns the size of the file. If this file is a directory, the returned - * value is unspecified. - * - * @see File#length() - * @return The size of the file - */ - public long getSize(); - - /** - * Returns whether this file is a directory. - * - * @return true if this file is a directory, - * false otherwise - */ - public boolean isDirectory(); - - /** - * Returns whether this file is a file (as opposed to being a directory). - * - * @return true if this file is a file, false - * otherwise - */ - public boolean isFile(); - - /** - * Returns whether this file is hidden. - * - * @return true if this file is hidden - */ - public boolean isHidden(); - - /** - * If this file is a directory, returns all files in this directory. - * - * @see #isDirectory() - * @return All files in this directory if this file is a directory, or - * null if this file is not a directory - */ - public List getFiles(); - -} diff --git a/src/net/pterodactylus/jsite/project/ProjectManager.java b/src/net/pterodactylus/jsite/project/ProjectManager.java deleted file mode 100644 index 35436ca..0000000 --- a/src/net/pterodactylus/jsite/project/ProjectManager.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * jSite2 - ProjectManager.java - - * Copyright © 2008 David Roden - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -package net.pterodactylus.jsite.project; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Properties; -import java.util.Random; -import java.util.Map.Entry; -import java.util.logging.Level; -import java.util.logging.Logger; - -import net.pterodactylus.jsite.core.JSiteException; -import net.pterodactylus.jsite.core.NodeManager; -import net.pterodactylus.util.io.Closer; -import net.pterodactylus.util.logging.Logging; -import net.pterodactylus.util.number.Hex; - -/** - * Manages projects, taking care of persistence, lifetime statistics, and other - * things. - * - * @author David ‘Bombe’ Roden <bombe@freenetproject.org> - */ -public class ProjectManager implements PropertyChangeListener { - - /** Logger. */ - private static final Logger logger = Logging.getLogger(ProjectManager.class.getName()); - - /** The RNG used to create project IDs. */ - private static final Random random = new Random(); - - /** The directory the projects are stored in. */ - private final String directory; - - /** The node manager. */ - private NodeManager nodeManager; - - /** All projects. */ - private final List projects = Collections.synchronizedList(new ArrayList()); - - /** - * Creates a new project manager that saves and restores its state to/from - * the given directory. - * - * @param directory - * The directory to save and restore states to/from - */ - public ProjectManager(String directory) { - this.directory = directory; - } - - // - // ACCESSORS - // - - /** - * Returns the directory the projects are loaded from and saved to. - * - * @return The directory for storing the projects - */ - public String getDirectory() { - return directory; - } - - /** - * Returns a list of all projects. - * - * @return A list of all projects - */ - public List getProjects() { - return Collections.unmodifiableList(new ArrayList(projects)); - } - - /** - * Sets the node manager to use. - * - * @param nodeManager - * The node manager to use - */ - public void setNodeManager(NodeManager nodeManager) { - this.nodeManager = nodeManager; - } - - // - // ACTIONS - // - - /** - * Loads projects and statistics. - * - * @throws IOException - * if an I/O error occurs - */ - public void load() throws IOException { - File directoryFile = new File(directory); - File projectFile = new File(directoryFile, "projects.properties"); - if (!projectFile.exists() || !projectFile.isFile() || !projectFile.canRead()) { - return; - } - Properties projectProperties = new Properties(); - InputStream projectInputStream = null; - try { - projectInputStream = new FileInputStream(projectFile); - projectProperties.load(projectInputStream); - } finally { - Closer.close(projectInputStream); - } - int projectIndex = 0; - while (projectProperties.containsKey("projects." + projectIndex + ".name")) { - String projectPrefix = "projects." + projectIndex; - String projectId = projectProperties.getProperty(projectPrefix + ".id"); - String projectName = projectProperties.getProperty(projectPrefix + ".name"); - String projectDescription = projectProperties.getProperty(projectPrefix + ".description"); - String projectPrivateKey = projectProperties.getProperty(projectPrefix + ".privateKey"); - String projectPublicKey = projectProperties.getProperty(projectPrefix + ".publicKey"); - String projectBasePath = projectProperties.getProperty(projectPrefix + ".basePath"); - String projectDefaultFile = projectProperties.getProperty(projectPrefix + ".defaultFile"); - Project project = new Project(); - project.setId(projectId); - project.setName(projectName); - project.setDescription(projectDescription); - project.setPrivateKey(projectPrivateKey); - project.setPublicKey(projectPublicKey); - project.setBasePath(projectBasePath); - project.setDefaultFile(projectDefaultFile); - int overrideIndex = 0; - while (projectProperties.containsKey(projectPrefix + ".overrides." + overrideIndex + ".override")) { - String filePath = projectProperties.getProperty(projectPrefix + ".overrides." + overrideIndex + ".filePath"); - FileOverride override = FileOverride.valueOf(projectProperties.getProperty(projectPrefix + ".overrides." + overrideIndex + ".override")); - project.addFileOverride(filePath, override); - logger.log(Level.FINEST, "read override: " + filePath + ", " + override); - overrideIndex++; - } - projects.add(project); - logger.fine("loaded project “" + project.getName() + "”."); - projectIndex++; - } - } - - /** - * Saves projects and statistics. - * - * @throws IOException - * if an I/O error occurs - */ - public void save() throws IOException { - File directoryFile = new File(directory); - if (!directoryFile.exists()) { - if (!directoryFile.mkdirs()) { - throw new IOException("could not create directory: " + directory); - } - } - Properties projectProperties = new Properties(); - int projectIndex = 0; - for (Project project : projects) { - String projectPrefix = "projects." + projectIndex; - projectProperties.setProperty(projectPrefix + ".id", project.getId()); - projectProperties.setProperty(projectPrefix + ".name", project.getName()); - projectProperties.setProperty(projectPrefix + ".description", project.getDescription()); - projectProperties.setProperty(projectPrefix + ".privateKey", project.getPrivateKey()); - projectProperties.setProperty(projectPrefix + ".publicKey", project.getPublicKey()); - projectProperties.setProperty(projectPrefix + ".basePath", project.getBasePath()); - projectProperties.setProperty(projectPrefix + ".defaultFile", project.getDefaultFile()); - int overrideIndex = 0; - for (Entry overrideEntry : project.getFileOverrides().entrySet()) { - projectProperties.setProperty(projectPrefix + ".overrides." + overrideIndex + ".filePath", overrideEntry.getKey()); - projectProperties.setProperty(projectPrefix + ".overrides." + overrideIndex + ".override", overrideEntry.getValue().toString()); - overrideIndex++; - } - projectIndex++; - } - File projectFile = new File(directoryFile, "projects.properties"); - OutputStream projectOutputStream = null; - try { - projectOutputStream = new FileOutputStream(projectFile); - projectProperties.store(projectOutputStream, "jSite projects"); - } finally { - Closer.close(projectOutputStream); - } - } - - /** - * Creates a new project. The returned {@link Project} will contain a newly - * generated key pair. - * - * @return A newly created project - * @throws IOException - * if an I/O error occured communicating with the node - * @throws JSiteException - * if there is a problem with the node - */ - public Project createProject() throws IOException, JSiteException { - Project project = new Project(); - String[] keyPair = nodeManager.generateKeyPair(); - project.setId(generateId()); - project.setName(""); - project.setDescription(""); - project.setPrivateKey(keyPair[0]); - project.setPublicKey(keyPair[1]); - project.setBasePath(""); - project.setDefaultFile(""); - projects.add(project); - project.addPropertyChangeListener(this); - try { - save(); - } catch (IOException ioe1) { - /* ignore. */ - } - return project; - } - - /** - * Clones the given project and returns the clone. The clone will be - * identical in all user-exposed fields, except for the project’s - * {@link Project#getId ID}. - * - * @param project - * The project to clone - * @return The cloned project - */ - public Project cloneProject(Project project) { - Project projectClone = new Project(project); - projects.add(projectClone); - projectClone.setId(generateId()); - projectClone.addPropertyChangeListener(this); - try { - save(); - } catch (IOException ioe1) { - /* ignore. */ - } - return projectClone; - } - - /** - * Removes the given project. - * - * @param project - * The project to remove - */ - public void removeProject(Project project) { - projects.remove(project); - try { - save(); - } catch (IOException ioe1) { - /* ignore. */ - } - } - - // - // PRIVATE METHODS - // - - /** - * Generates a new random ID, consisting of 16 random bytes converted to a - * hexadecimal number. - * - * @return The new ID - */ - private static String generateId() { - byte[] idBytes = new byte[16]; - random.nextBytes(idBytes); - return Hex.toHex(idBytes); - } - - // - // INTERFACE PropertyChangeListener - // - - /** - * {@inheritDoc} - */ - public void propertyChange(PropertyChangeEvent propertyChangeEvent) { - try { - save(); - } catch (IOException ioe1) { - /* ignore. */ - } - } - -} -- 2.7.4