df08244cc6f821617d290fae209fcb1aab1a69b1
[jSite.git] / src / main / java / de / todesbaum / jsite / main / CLI.java
1 /*
2  * jSite - CLI.java - Copyright © 2006–2014 David Roden
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18
19 package de.todesbaum.jsite.main;
20
21 import java.io.PrintWriter;
22 import java.util.List;
23
24 import net.pterodactylus.util.io.StreamCopier.ProgressListener;
25 import de.todesbaum.jsite.application.Freenet7Interface;
26 import de.todesbaum.jsite.application.InsertListener;
27 import de.todesbaum.jsite.application.Node;
28 import de.todesbaum.jsite.application.Project;
29 import de.todesbaum.jsite.application.ProjectInserter;
30 import de.todesbaum.jsite.main.JarFileLocator.DefaultJarFileLocator;
31
32 /**
33  * Command-line interface for jSite.
34  *
35  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
36  */
37 public class CLI implements InsertListener {
38
39         /** Object used for synchronization. */
40         private Object lockObject = new Object();
41
42         /** Writer for the console. */
43         private PrintWriter outputWriter = new PrintWriter(System.out, true);
44
45         /** The freenet interface. */
46         private Freenet7Interface freenetInterface;
47
48         /** The project inserter. */
49         private ProjectInserter projectInserter = new ProjectInserter();
50
51         /** The list of nodes. */
52         private Node[] nodes;
53
54         /** The projects. */
55         private List<Project> projects;
56
57         /** Whether the insert has finished. */
58         private boolean finished = false;
59
60         /** Whether the insert finished successfully. */
61         private boolean success;
62
63         /**
64          * Creates a new command-line interface.
65          *
66          * @param args
67          *            The command-line arguments
68          */
69         private CLI(String[] args) {
70
71                 if ((args.length == 0) || args[0].equals("-h") || args[0].equals("--help")) {
72                         outputWriter.println("\nParameters:\n");
73                         outputWriter.println("  --config-file=<configuration file>");
74                         outputWriter.println("  --node=<node name>");
75                         outputWriter.println("  --project=<project name>");
76                         outputWriter.println("  --local-directory=<local directory>");
77                         outputWriter.println("  --path=<path>");
78                         outputWriter.println("  --edition=<edition>");
79                         outputWriter.println("\nA project gets inserted when a new project is loaded on the command line,");
80                         outputWriter.println("or when the command line is finished. --local-directory, --path, and --edition");
81                         outputWriter.println("override the parameters in the project.");
82                         return;
83                 }
84
85                 String configFile = System.getProperty("user.home") + "/.jSite/config7";
86                 for (String argument : args) {
87                         String value = argument.substring(argument.indexOf('=') + 1).trim();
88                         if (argument.startsWith("--config-file=")) {
89                                 configFile = value;
90                         }
91                 }
92
93                 ConfigurationLocator configurationLocator = new ConfigurationLocator(new DefaultJarFileLocator(getClass().getClassLoader()));
94                 if (configFile != null) {
95                         configurationLocator.setCustomLocation(configFile);
96                 }
97                 Configuration configuration = new Configuration(configurationLocator, configurationLocator.findPreferredLocation());
98
99                 projectInserter.addInsertListener(this);
100                 projects = configuration.getProjects();
101                 Node node = configuration.getSelectedNode();
102                 nodes = configuration.getNodes();
103
104                 freenetInterface = new Freenet7Interface();
105                 freenetInterface.setNode(node);
106
107                 projectInserter.setFreenetInterface(freenetInterface);
108         projectInserter.setPriority(configuration.getPriority());
109
110                 Project currentProject = null;
111                 for (String argument : args) {
112                         if (argument.startsWith("--config-file=")) {
113                                 /* we already parsed this one. */
114                                 continue;
115                         }
116                         String value = argument.substring(argument.indexOf('=') + 1).trim();
117                         if (argument.startsWith("--node=")) {
118                                 Node newNode = getNode(value);
119                                 if (newNode == null) {
120                                         outputWriter.println("Node \"" + value + "\" not found.");
121                                         return;
122                                 }
123                                 node = newNode;
124                                 freenetInterface.setNode(node);
125                         } else if (argument.startsWith("--project=")) {
126                                 if (currentProject != null) {
127                                         if (insertProject(currentProject)) {
128                                                 outputWriter.println("Project \"" + currentProject.getName() + "\" successfully inserted.");
129                                         } else {
130                                                 outputWriter.println("Project \"" + currentProject.getName() + "\" was not successfully inserted.");
131                                         }
132                                         currentProject = null;
133                                 }
134                                 currentProject = getProject(value);
135                                 if (currentProject == null) {
136                                         outputWriter.println("Project \"" + value + "\" not found.");
137                                 }
138                         } else if (argument.startsWith("--local-directory")) {
139                                 if (currentProject == null) {
140                                         outputWriter.println("You can't specifiy --local-directory before --project.");
141                                         return;
142                                 }
143                                 currentProject.setLocalPath(value);
144                         } else if (argument.startsWith("--path=")) {
145                                 if (currentProject == null) {
146                                         outputWriter.println("You can't specify --path before --project.");
147                                         return;
148                                 }
149                                 currentProject.setPath(value);
150                         } else if (argument.startsWith("--edition=")) {
151                                 if (currentProject == null) {
152                                         outputWriter.println("You can't specify --edition before --project.");
153                                         return;
154                                 }
155                                 currentProject.setEdition(Integer.parseInt(value));
156                         } else {
157                                 outputWriter.println("Unknown parameter: " + argument);
158                                 return;
159                         }
160                 }
161
162                 int errorCode = 1;
163                 if (currentProject != null) {
164                         if (insertProject(currentProject)) {
165                                 outputWriter.println("Project \"" + currentProject.getName() + "\" successfully inserted.");
166                                 errorCode = 0;
167                         } else {
168                                 outputWriter.println("Project \"" + currentProject.getName() + "\" was not successfully inserted.");
169                         }
170                 }
171
172                 configuration.setProjects(projects);
173                 configuration.save();
174
175                 System.exit(errorCode);
176         }
177
178         /**
179          * Returns the project with the given name.
180          *
181          * @param name
182          *            The name of the project
183          * @return The project, or <code>null</code> if no project could be found
184          */
185         private Project getProject(String name) {
186                 for (Project project : projects) {
187                         if (project.getName().equals(name)) {
188                                 return project;
189                         }
190                 }
191                 return null;
192         }
193
194         /**
195          * Returns the node with the given name.
196          *
197          * @param name
198          *            The name of the node
199          * @return The node, or <code>null</code> if no node could be found
200          */
201         private Node getNode(String name) {
202                 for (Node node : nodes) {
203                         if (node.getName().equals(name)) {
204                                 return node;
205                         }
206                 }
207                 return null;
208         }
209
210         /**
211          * Inserts the given project.
212          *
213          * @param currentProject
214          *            The project to insert
215          * @return <code>true</code> if the insert finished successfully,
216          *         <code>false</code> otherwise
217          */
218         private boolean insertProject(Project currentProject) {
219                 if (!freenetInterface.hasNode()) {
220                         outputWriter.println("Node is not running!");
221                         return false;
222                 }
223                 projectInserter.setProject(currentProject);
224                 projectInserter.start(new ProgressListener() {
225
226                         @Override
227                         public void onProgress(long copied, long length) {
228                                 System.out.print("Uploaded: " + copied + " / " + length + " bytes...\r");
229                         }
230                 });
231                 synchronized (lockObject) {
232                         while (!finished) {
233                                 try {
234                                         lockObject.wait();
235                                 } catch (InterruptedException e) {
236                                         /* ignore, we're in a loop. */
237                                 }
238                         }
239                 }
240                 return success;
241         }
242
243         //
244         // INTERFACE InsertListener
245         //
246
247         /**
248          * {@inheritDoc}
249          */
250         @Override
251         public void projectInsertStarted(Project project) {
252                 outputWriter.println("Starting Insert of project \"" + project.getName() + "\".");
253         }
254
255         /**
256          * {@inheritDoc}
257          */
258         @Override
259         public void projectUploadFinished(Project project) {
260                 outputWriter.println("Project \"" + project.getName() + "\" has been uploaded, starting insert...");
261         }
262
263         /**
264          * {@inheritDoc}
265          */
266         @Override
267         public void projectURIGenerated(Project project, String uri) {
268                 outputWriter.println("URI: " + uri);
269         }
270
271         /**
272          * {@inheritDoc}
273          */
274         @Override
275         public void projectInsertProgress(Project project, int succeeded, int failed, int fatal, int total, boolean finalized) {
276                 if (total == 0) {
277                         return;
278                 }
279                 outputWriter.println("Progress: " + succeeded + " done, " + failed + " failed, " + fatal + " fatal, " + total + " total" + (finalized ? " (finalized)" : "") + ", " + ((succeeded + failed + fatal) * 100 / total) + "%");
280         }
281
282         /**
283          * {@inheritDoc}
284          */
285         @Override
286         public void projectInsertFinished(Project project, boolean success, Throwable cause) {
287                 outputWriter.println("Request URI: " + project.getFinalRequestURI(0));
288                 finished = true;
289                 this.success = success;
290                 synchronized (lockObject) {
291                         lockObject.notify();
292                 }
293         }
294
295         //
296         // MAIN
297         //
298
299         /**
300          * Creates a new command-line interface with the given arguments.
301          *
302          * @param args
303          *            The command-line arguments
304          */
305         public static void main(String[] args) {
306                 new CLI(args);
307         }
308
309 }