1 // -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the GNU General Public License v3+, or later.
7 // See license.mkd for licensing and copyright information.
8 // ---------------------------------------------------------------------------
10 package cc
.squirreljme
.plugin
.general
;
12 import cc
.squirreljme
.plugin
.multivm
.AlwaysFalse
;
13 import cc
.squirreljme
.plugin
.util
.FossilExe
;
14 import cc
.squirreljme
.plugin
.util
.SimpleHTTPRequest
;
15 import cc
.squirreljme
.plugin
.util
.SimpleHTTPResponse
;
16 import cc
.squirreljme
.plugin
.util
.SimpleHTTPResponseBuilder
;
17 import cc
.squirreljme
.plugin
.util
.SimpleHTTPStatus
;
18 import java
.awt
.Desktop
;
19 import java
.awt
.HeadlessException
;
20 import java
.io
.ByteArrayOutputStream
;
21 import java
.io
.IOException
;
22 import java
.io
.PrintStream
;
23 import java
.io
.UnsupportedEncodingException
;
25 import java
.net
.URLDecoder
;
26 import java
.nio
.charset
.StandardCharsets
;
27 import java
.time
.LocalDate
;
28 import java
.time
.LocalDateTime
;
29 import java
.util
.Objects
;
30 import javax
.inject
.Inject
;
31 import org
.gradle
.api
.DefaultTask
;
32 import org
.gradle
.api
.Task
;
35 * Edits the current day in developer notes.
39 public class DeveloperNoteTask
42 /** The server only handles this single path. */
43 private static final String _THE_ONLY_PATH
=
47 * Initializes the task.
49 * @param __exeTask The executable task.
53 public DeveloperNoteTask(FossilExeTask __exeTask
)
55 // Set details of this task
56 this.setGroup("squirreljmeGeneral");
57 this.setDescription("Edits the developer note for the current day.");
59 // The executable task must run first
60 this.dependsOn(__exeTask
);
63 this.onlyIf(__task
-> FossilExe
.isAvailable(true));
64 this.getOutputs().upToDateWhen(new AlwaysFalse());
67 this.doLast(new DeveloperNoteTaskAction());
71 * Returns the blog file path.
73 * @param __date The date to get.
74 * @return The path to the blog file.
75 * @throws NullPointerException On null arguments.
78 static String
__blogFilePath(LocalDate __date
)
79 throws NullPointerException
81 return DeveloperNoteTask
.__blogFilePath(__date
,
82 FossilExe
.instance().currentUser());
86 * Returns the blog file path.
88 * @param __date The date to get.
89 * @param __user The user to lookup.
90 * @return The path to the blog file.
91 * @throws NullPointerException On null arguments.
94 private static String
__blogFilePath(LocalDate __date
, String __user
)
95 throws NullPointerException
97 if (__date
== null || __user
== null)
98 throw new NullPointerException("NARG");
100 // Determine where this is
101 return String
.format("developer-notes/%s/%tY/%tm/%td.mkd",
102 __user
.replace('.', '-'), __date
, __date
, __date
);
106 * Handles the HTTP request.
108 * @param __session The session being used.
109 * @param __request The request.
110 * @return The response, may be {@code null}.
111 * @throws NullPointerException On null arguments.
114 @SuppressWarnings("FeatureEnvy")
115 static SimpleHTTPResponse
__httpHandler(__DeveloperNoteSession__ __session
,
116 SimpleHTTPRequest __request
)
117 throws NullPointerException
119 if (__session
== null || __request
== null)
120 throw new NullPointerException("NARG");
122 // Setup base response, always returning the same path
123 SimpleHTTPResponseBuilder response
= new SimpleHTTPResponseBuilder();
125 // If we got a request that is not from the root, it is somewhere else
126 if (!DeveloperNoteTask
._THE_ONLY_PATH
.equals(
127 __request
.path
.getPath()))
128 return response
.status(SimpleHTTPStatus
.NOT_FOUND
).build();
130 // Submission of the form? Load in that data
134 query
= URLDecoder
.decode(Objects
.toString(
135 __request
.path
.getRawQuery(), ""), "utf-8");
137 catch (UnsupportedEncodingException e
)
139 throw new RuntimeException("Could not decode query", e
);
143 if (query
!= null && query
.startsWith("content="))
145 // Split off the data
146 String data
= query
.substring("content=".length())
147 .replace("\r\n", "\n");
149 // Store into the session bytes
150 __session
._content
= data
.getBytes(StandardCharsets
.UTF_8
);
151 __session
._saveCount
++;
154 System
.out
.println("Notes saved!");
158 else if (query
!= null && query
.startsWith("finish="))
161 // Everything is okay
162 response
.status(SimpleHTTPStatus
.OK
);
164 // Setup some headers
165 response
.addHeader("Content-Type",
166 "text/html; charset=UTF-8");
167 response
.addHeader("Server",
168 "SquirrelJME-Build/0.3.0");
169 response
.addHeader("Connection",
172 // Splice in resources
173 response
.spliceResources(DeveloperNoteTask
.class,
174 "form-header.html", "form-footer.html",
177 // Build final response
178 return response
.build();
182 * Attempts to launch a browser.
184 * @param __task The task used.
185 * @param __url The URL to launch.
186 * @throws NullPointerException On null arguments.
189 static void __launchBrowser(Task __task
, String __url
)
190 throws NullPointerException
193 throw new NullPointerException("NARG");
195 // Inform on the terminal what the URL is for the server
196 __task
.getLogger().lifecycle(String
.format(
197 "Notes URL is at %s !", __url
));
199 // Try to use normal AWT stuff?
202 // Not a supported desktop?
203 if (!Desktop
.isDesktopSupported())
204 throw new HeadlessException();
206 // Open browser, or try to anyway
207 Desktop desktop
= Desktop
.getDesktop();
208 desktop
.browse(URI
.create(__url
));
210 // It worked, so stop
214 // Do not fail on this, just try more
215 catch (IOException
|HeadlessException ignored
)
219 // Open the browser using another means
220 System
.err
.printf("TODO -- Open browser?%n");
224 * Returns template for blank notes.
226 * @param __at The date.
227 * @return The note template.
228 * @throws NullPointerException On null arguments.
231 @SuppressWarnings("resource")
232 static byte[] __template(LocalDateTime __at
)
233 throws NullPointerException
236 throw new NullPointerException("NARG");
238 // Write the template
239 try (ByteArrayOutputStream out
= new ByteArrayOutputStream();
240 PrintStream ps
= new PrintStream(
244 ps
.printf("# %tY/%tm/%td\n", __at
, __at
, __at
);
248 ps
.printf("## %tH:%tM", __at
, __at
);
251 // Ending space line for content
254 // Clear out and use this template
256 return out
.toByteArray();
260 catch (IOException e
)
262 throw new RuntimeException("Could not create template", e
);