2 * jSite2 - ProjectManager.java -
3 * Copyright © 2008 David Roden
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 package net.pterodactylus.jsite.core;
22 import java.beans.PropertyChangeEvent;
23 import java.beans.PropertyChangeListener;
25 import java.io.FileReader;
26 import java.io.FileWriter;
27 import java.io.IOException;
28 import java.io.Reader;
29 import java.io.Writer;
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.List;
35 import java.util.Map.Entry;
36 import java.util.logging.Level;
37 import java.util.logging.Logger;
39 import net.pterodactylus.util.collection.MapWriter;
40 import net.pterodactylus.util.io.Closer;
41 import net.pterodactylus.util.logging.Logging;
44 * Manages projects, taking care of persistence, lifetime statistics, and other
47 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
49 public class ProjectManager implements PropertyChangeListener {
52 private static final Logger logger = Logging.getLogger(ProjectManager.class.getName());
54 /** The directory the projects are stored in. */
55 private final String directory;
57 /** The node manager. */
58 private NodeManager nodeManager;
61 private final List<Project> projects = Collections.synchronizedList(new ArrayList<Project>());
64 * Creates a new project manager that saves and restores its state to/from
65 * the given directory.
68 * The directory to save and restore states to/from
70 public ProjectManager(String directory) {
71 this.directory = directory;
79 * Returns the directory the projects are loaded from and saved to.
81 * @return The directory for storing the projects
83 public String getDirectory() {
88 * Returns a list of all projects.
90 * @return A list of all projects
92 public List<Project> getProjects() {
93 return Collections.unmodifiableList(new ArrayList<Project>(projects));
97 * Sets the node manager to use.
100 * The node manager to use
102 public void setNodeManager(NodeManager nodeManager) {
103 this.nodeManager = nodeManager;
111 * Loads projects and statistics.
113 * @throws IOException
114 * if an I/O error occurs
116 public void load() throws IOException {
117 File directoryFile = new File(directory);
118 File projectFile = new File(directoryFile, "projects.properties");
119 if (!projectFile.exists() || !projectFile.isFile() || !projectFile.canRead()) {
122 logger.log(Level.INFO, "Loading projects from “" + projectFile + "”...");
123 Map<String, String> projectProperties;
124 Reader reader = null;
126 reader = new FileReader(projectFile);
127 projectProperties = MapWriter.read(reader);
129 Closer.close(reader);
131 int projectIndex = 0;
132 while (projectProperties.containsKey("projects." + projectIndex + ".name")) {
133 String projectPrefix = "projects." + projectIndex;
134 String projectId = projectProperties.get(projectPrefix + ".id");
135 String projectName = projectProperties.get(projectPrefix + ".name");
136 String projectDescription = projectProperties.get(projectPrefix + ".description");
137 String projectPrivateKey = projectProperties.get(projectPrefix + ".privateKey");
138 String projectPublicKey = projectProperties.get(projectPrefix + ".publicKey");
139 String projectBasePath = projectProperties.get(projectPrefix + ".basePath");
140 String projectDefaultFile = projectProperties.get(projectPrefix + ".defaultFile");
141 String projectNode = projectProperties.get(projectPrefix + ".node");
142 Project project = new Project();
143 project.setId(projectId);
144 project.setName(projectName);
145 project.setDescription(projectDescription);
146 project.setPrivateKey(projectPrivateKey);
147 project.setPublicKey(projectPublicKey);
148 project.setBasePath(projectBasePath);
149 project.setDefaultFile(projectDefaultFile);
150 if (projectNode != null) {
151 Node node = nodeManager.getNode(projectNode);
152 project.setNode(node);
154 int overrideIndex = 0;
155 while (projectProperties.containsKey(projectPrefix + ".overrides." + overrideIndex + ".override")) {
156 String filePath = projectProperties.get(projectPrefix + ".overrides." + overrideIndex + ".filePath");
157 FileOverride override = FileOverride.valueOf(projectProperties.get(projectPrefix + ".overrides." + overrideIndex + ".override"));
158 project.addFileOverride(filePath, override);
159 logger.log(Level.FINEST, "read override: " + filePath + ", " + override);
162 project.addPropertyChangeListener(this);
163 projects.add(project);
164 logger.fine("loaded project “" + project.getName() + "”.");
170 * Saves projects and statistics.
172 * @throws IOException
173 * if an I/O error occurs
175 public void save() throws IOException {
176 File directoryFile = new File(directory);
177 if (!directoryFile.exists()) {
178 if (!directoryFile.mkdirs()) {
179 throw new IOException("could not create directory: " + directory);
182 Map<String, String> projectProperties = new HashMap<String, String>();
183 int projectIndex = 0;
184 for (Project project : projects) {
185 String projectPrefix = "projects." + projectIndex;
186 projectProperties.put(projectPrefix + ".id", project.getId());
187 projectProperties.put(projectPrefix + ".name", project.getName());
188 projectProperties.put(projectPrefix + ".description", project.getDescription());
189 projectProperties.put(projectPrefix + ".privateKey", project.getPrivateKey());
190 projectProperties.put(projectPrefix + ".publicKey", project.getPublicKey());
191 projectProperties.put(projectPrefix + ".basePath", project.getBasePath());
192 projectProperties.put(projectPrefix + ".defaultFile", project.getDefaultFile());
193 if (project.getNode() != null) {
194 projectProperties.put(projectPrefix + ".node", project.getNode().getId());
196 int overrideIndex = 0;
197 for (Entry<String, FileOverride> overrideEntry : project.getFileOverrides().entrySet()) {
198 projectProperties.put(projectPrefix + ".overrides." + overrideIndex + ".filePath", overrideEntry.getKey());
199 projectProperties.put(projectPrefix + ".overrides." + overrideIndex + ".override", overrideEntry.getValue().toString());
204 File projectFile = new File(directoryFile, "projects.properties");
205 Writer writer = null;
207 writer = new FileWriter(projectFile);
208 MapWriter.write(writer, projectProperties);
210 Closer.close(writer);
215 * Creates a new project. The returned {@link Project} will contain a newly
216 * generated key pair.
218 * @return A newly created project
219 * @throws IOException
220 * if an I/O error occured communicating with the node
221 * @throws JSiteException
222 * if there is a problem with the node
224 public Project createProject() throws IOException, JSiteException {
225 Project project = new Project();
226 String[] keyPair = nodeManager.generateKeyPair();
228 project.setDescription("");
229 project.setPrivateKey(keyPair[0]);
230 project.setPublicKey(keyPair[1]);
231 project.setBasePath("");
232 project.setDefaultFile("");
233 projects.add(project);
234 project.addPropertyChangeListener(this);
237 } catch (IOException ioe1) {
244 * Clones the given project and returns the clone. The clone will be
245 * identical in all user-exposed fields, except for the project’s
246 * {@link Project#getId ID}.
249 * The project to clone
250 * @return The cloned project
252 public Project cloneProject(Project project) {
253 Project projectClone = new Project(project);
254 projects.add(projectClone);
255 projectClone.addPropertyChangeListener(this);
258 } catch (IOException ioe1) {
265 * Removes the given project.
268 * The project to remove
270 public void removeProject(Project project) {
271 projects.remove(project);
274 } catch (IOException ioe1) {
280 // INTERFACE PropertyChangeListener
286 public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
289 } catch (IOException ioe1) {