import java.util.List;
import java.util.concurrent.Executor;
-import net.pterodactylus.jsite.core.project.Project;
/**
* Interface for the core.
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
-import net.pterodactylus.jsite.core.project.Project;
-import net.pterodactylus.jsite.core.project.ProjectManager;
/**
* The core of jSite.
package net.pterodactylus.jsite.core;
-import net.pterodactylus.jsite.core.project.Project;
-
/**
* Interface definition for user interfaces.
*
--- /dev/null
+/*
+ * 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;
+
+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 <code>true</code> if this override does not have any effects,
+ * <code>false</code> otherwise
+ */
+ public boolean isEmpty() {
+ return (insert == null) && (contentType == null) && (redirectTarget == null);
+ }
+
+ /**
+ * Returns the insert override.
+ *
+ * @return <code>true</code> if the entry should be inserted,
+ * <code>false</code> if it should not be inserted,
+ * <code>null</code> if the default should not be overridden
+ */
+ public Boolean isInsert() {
+ return insert;
+ }
+
+ /**
+ * Sets the insert override.
+ *
+ * @param insert
+ * <code>true</code> if the entry should be inserted,
+ * <code>false</code> if it should not be inserted,
+ * <code>null</code> 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 <code>null</code> to not override
+ * the default
+ */
+ public String getContentType() {
+ return contentType;
+ }
+
+ /**
+ * Sets the override content type.
+ *
+ * @param contentType
+ * The override content type, or <code>null</code> 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 <code>null</code> 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 <code>null</code> 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 <code>null</code> 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+
+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<String, FileOverride> fileOverrides = new HashMap<String, FileOverride>();
+
+ /** 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 <code>null</code> 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 <code>null</code> 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<String, FileOverride> 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 <code>null</code> 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 <code>null</code> 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<ProjectFileImpl> {
+
+ /** 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<ProjectFileImpl> childProjectFiles = new ArrayList<ProjectFileImpl>();
+
+ /**
+ * Creates a new project fie.
+ *
+ * @param parentProjectFile
+ * The parent of the project file, or <code>null</code> 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
+ * <code>true</code> if this project file is a directory,
+ * <code>false</code> otherwise
+ * @param isHidden
+ * <code>true</code> if this project file is hidden,
+ * <code>false</code> 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.ProjectFile#getName()
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @see net.pterodactylus.jsite.core.ProjectFile#getParent()
+ */
+ public ProjectFile getParent() {
+ return parentProjectFile;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getSize() {
+ return size;
+ }
+
+ /**
+ * @see net.pterodactylus.jsite.core.ProjectFile#getParents()
+ */
+ public List<ProjectFile> getParents() {
+ List<ProjectFile> parentProjectFiles = new ArrayList<ProjectFile>();
+ 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.ProjectFile#isFile()
+ */
+ public boolean isFile() {
+ return !directory;
+ }
+
+ /**
+ * @see net.pterodactylus.jsite.core.ProjectFile#isDirectory()
+ */
+ public boolean isDirectory() {
+ return directory;
+ }
+
+ /**
+ * @see net.pterodactylus.jsite.core.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 <code>null</code> 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.ProjectFile#getFiles()
+ */
+ public List<ProjectFile> getFiles() {
+ List<ProjectFile> projectFiles = new ArrayList<ProjectFile>(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
+ * <code>true</code> if the new file is a directory,
+ * <code>false</code> otherwise
+ * @param isHidden
+ * <code>true</code> if the new file is hidden,
+ * <code>false</code> 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);
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+
+import java.io.File;
+import java.util.List;
+
+
+/**
+ * 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 <code>null</code> 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<ProjectFile> 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 <code>true</code> if this file is a directory,
+ * <code>false</code> otherwise
+ */
+ public boolean isDirectory();
+
+ /**
+ * Returns whether this file is a file (as opposed to being a directory).
+ *
+ * @return <code>true</code> if this file is a file, <code>false</code>
+ * otherwise
+ */
+ public boolean isFile();
+
+ /**
+ * Returns whether this file is hidden.
+ *
+ * @return <code>true</code> 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
+ * <code>null</code> if this file is not a directory
+ */
+ public List<ProjectFile> getFiles();
+
+}
--- /dev/null
+/*
+ * 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;
+
+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.Map.Entry;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.pterodactylus.jsite.util.IdGenerator;
+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 directory the projects are stored in. */
+ private final String directory;
+
+ /** The node manager. */
+ private NodeManager nodeManager;
+
+ /** All projects. */
+ private final List<Project> projects = Collections.synchronizedList(new ArrayList<Project>());
+
+ /**
+ * 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<Project> getProjects() {
+ return Collections.unmodifiableList(new ArrayList<Project>(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<String, FileOverride> 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(Hex.toHex(IdGenerator.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(Hex.toHex(IdGenerator.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. */
+ }
+ }
+
+ //
+ // INTERFACE PropertyChangeListener
+ //
+
+ /**
+ * {@inheritDoc}
+ */
+ public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
+ try {
+ save();
+ } catch (IOException ioe1) {
+ /* ignore. */
+ }
+ }
+
+}
+++ /dev/null
-/*
- * 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 <code>true</code> if this override does not have any effects,
- * <code>false</code> otherwise
- */
- public boolean isEmpty() {
- return (insert == null) && (contentType == null) && (redirectTarget == null);
- }
-
- /**
- * Returns the insert override.
- *
- * @return <code>true</code> if the entry should be inserted,
- * <code>false</code> if it should not be inserted,
- * <code>null</code> if the default should not be overridden
- */
- public Boolean isInsert() {
- return insert;
- }
-
- /**
- * Sets the insert override.
- *
- * @param insert
- * <code>true</code> if the entry should be inserted,
- * <code>false</code> if it should not be inserted,
- * <code>null</code> 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 <code>null</code> to not override
- * the default
- */
- public String getContentType() {
- return contentType;
- }
-
- /**
- * Sets the override content type.
- *
- * @param contentType
- * The override content type, or <code>null</code> 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 <code>null</code> 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 <code>null</code> 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 <code>null</code> 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<String, FileOverride> fileOverrides = new HashMap<String, FileOverride>();
-
- /** 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 <code>null</code> 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 <code>null</code> 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<String, FileOverride> 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 <code>null</code> 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 <code>null</code> 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<ProjectFileImpl> {
-
- /** 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<ProjectFileImpl> childProjectFiles = new ArrayList<ProjectFileImpl>();
-
- /**
- * Creates a new project fie.
- *
- * @param parentProjectFile
- * The parent of the project file, or <code>null</code> 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
- * <code>true</code> if this project file is a directory,
- * <code>false</code> otherwise
- * @param isHidden
- * <code>true</code> if this project file is hidden,
- * <code>false</code> 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<ProjectFile> getParents() {
- List<ProjectFile> parentProjectFiles = new ArrayList<ProjectFile>();
- 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 <code>null</code> 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<ProjectFile> getFiles() {
- List<ProjectFile> projectFiles = new ArrayList<ProjectFile>(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
- * <code>true</code> if the new file is a directory,
- * <code>false</code> otherwise
- * @param isHidden
- * <code>true</code> if the new file is hidden,
- * <code>false</code> 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);
- }
-
- }
-
-}
+++ /dev/null
-/*
- * 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 <code>null</code> 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<ProjectFile> 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 <code>true</code> if this file is a directory,
- * <code>false</code> otherwise
- */
- public boolean isDirectory();
-
- /**
- * Returns whether this file is a file (as opposed to being a directory).
- *
- * @return <code>true</code> if this file is a file, <code>false</code>
- * otherwise
- */
- public boolean isFile();
-
- /**
- * Returns whether this file is hidden.
- *
- * @return <code>true</code> 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
- * <code>null</code> if this file is not a directory
- */
- public List<ProjectFile> getFiles();
-
-}
+++ /dev/null
-/*
- * 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.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.jsite.util.IdGenerator;
-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 directory the projects are stored in. */
- private final String directory;
-
- /** The node manager. */
- private NodeManager nodeManager;
-
- /** All projects. */
- private final List<Project> projects = Collections.synchronizedList(new ArrayList<Project>());
-
- /**
- * 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<Project> getProjects() {
- return Collections.unmodifiableList(new ArrayList<Project>(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<String, FileOverride> 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(Hex.toHex(IdGenerator.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(Hex.toHex(IdGenerator.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. */
- }
- }
-
- //
- // INTERFACE PropertyChangeListener
- //
-
- /**
- * {@inheritDoc}
- */
- public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
- try {
- save();
- } catch (IOException ioe1) {
- /* ignore. */
- }
- }
-
-}
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.core.FileOverride;
+import net.pterodactylus.jsite.core.Project;
+import net.pterodactylus.jsite.core.ProjectFile;
import net.pterodactylus.jsite.i18n.I18n;
import net.pterodactylus.jsite.i18n.I18nable;
import net.pterodactylus.jsite.i18n.gui.I18nAction;
import javax.swing.border.EmptyBorder;
import net.pterodactylus.jsite.core.Node;
-import net.pterodactylus.jsite.core.project.Project;
+import net.pterodactylus.jsite.core.Project;
import net.pterodactylus.jsite.i18n.I18n;
import net.pterodactylus.jsite.i18n.I18nable;
import net.pterodactylus.jsite.i18n.gui.I18nAction;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
-import net.pterodactylus.jsite.core.project.Project;
+import net.pterodactylus.jsite.core.Project;
import net.pterodactylus.jsite.i18n.I18n;
import net.pterodactylus.jsite.i18n.I18nable;
import net.pterodactylus.jsite.i18n.gui.I18nAction;
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.core.Project;
import net.pterodactylus.jsite.i18n.I18n;
import net.pterodactylus.jsite.i18n.gui.I18nAction;
import net.pterodactylus.util.image.IconLoader;
}
/**
- * @see net.pterodactylus.jsite.core.CoreListener#projectInsertStarted(net.pterodactylus.jsite.core.project.Project)
+ * @see net.pterodactylus.jsite.core.CoreListener#projectInsertStarted(net.pterodactylus.jsite.core.Project)
*/
public void projectInsertStarted(Project project) {
mainWindow.projectInsertStarted(project);
}
/**
- * @see net.pterodactylus.jsite.core.CoreListener#projectInsertProgressed(net.pterodactylus.jsite.core.project.Project,
+ * @see net.pterodactylus.jsite.core.CoreListener#projectInsertProgressed(net.pterodactylus.jsite.core.Project,
* int, int, int, int, int, boolean)
*/
public void projectInsertProgressed(Project project, int totalBlocks, int requiredBlocks, int successfulBlocks, int failedBlocks, int fatallyFailedBlocks, boolean finalizedTotal) {
}
/**
- * @see net.pterodactylus.jsite.core.CoreListener#projectInsertGeneratedURI(net.pterodactylus.jsite.core.project.Project,
+ * @see net.pterodactylus.jsite.core.CoreListener#projectInsertGeneratedURI(net.pterodactylus.jsite.core.Project,
* java.lang.String)
*/
public void projectInsertGeneratedURI(Project project, String uri) {
}
/**
- * @see net.pterodactylus.jsite.core.CoreListener#projectInsertFinished(net.pterodactylus.jsite.core.project.Project,
+ * @see net.pterodactylus.jsite.core.CoreListener#projectInsertFinished(net.pterodactylus.jsite.core.Project,
* boolean)
*/
public void projectInsertFinished(Project project, boolean success) {
import net.pterodactylus.jsite.core.CoreImpl;
import net.pterodactylus.jsite.core.NodeManager;
+import net.pterodactylus.jsite.core.ProjectManager;
import net.pterodactylus.jsite.core.RequestManager;
-import net.pterodactylus.jsite.core.project.ProjectManager;
import net.pterodactylus.jsite.gui.SwingInterface;
import net.pterodactylus.util.logging.Logging;