Skip to content

Commit 37d1fe4

Browse files
committed
CLI based file conversion
1 parent 31b9a60 commit 37d1fe4

11 files changed

+224
-61
lines changed

pom.xml

+26-9
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@
166166
<dependency>
167167
<groupId>de.tototec</groupId>
168168
<artifactId>de.tototec.cmdoption</artifactId>
169-
<version>0.6.0</version>
169+
<version>0.7.1</version>
170170
</dependency>
171171
<!-- https://github.com/asciidoctor/asciidoctor-diagram/tree/master/deps/plantuml/lib/asciidoctor-diagram/plantuml-->
172172
<dependency>
@@ -294,25 +294,30 @@
294294
<groupId>org.openjfx</groupId>
295295
<artifactId>javafx-swing</artifactId>
296296
<version>${openjfx.version}</version>
297-
<!-- <scope>provided</scope>-->
297+
<scope>provided</scope>
298298
</dependency>
299299
<dependency>
300300
<groupId>org.openjfx</groupId>
301301
<artifactId>javafx-controls</artifactId>
302302
<version>${openjfx.version}</version>
303-
<!-- <scope>provided</scope>-->
303+
<scope>provided</scope>
304304
</dependency>
305305
<dependency>
306306
<groupId>org.openjfx</groupId>
307307
<artifactId>javafx-web</artifactId>
308308
<version>${openjfx.version}</version>
309-
<!-- <scope>provided</scope>-->
309+
<scope>provided</scope>
310310
</dependency>
311311
<dependency>
312312
<groupId>org.openjfx</groupId>
313313
<artifactId>javafx-fxml</artifactId>
314314
<version>${openjfx.version}</version>
315-
<!-- <scope>provided</scope>-->
315+
<scope>provided</scope>
316+
</dependency>
317+
<dependency>
318+
<groupId>one.jpro</groupId>
319+
<artifactId>openjfx-monocle</artifactId>
320+
<version>jfx-${openjfx.version}</version>
316321
</dependency>
317322
<!-- Add test dependencies -->
318323
<dependency>
@@ -475,13 +480,16 @@
475480
-Duser.language=en
476481
-Duser.country=US
477482
-Dfile.encoding=UTF-8
478-
--enable-preview
479-
-Xms256M
480-
-Xmx1G
483+
-XX:+OptimizeStringConcat
484+
-Xms512M
485+
-Xmx750M
481486
-Djava.awt.headless=false
487+
--enable-preview
482488
-Dsun.java2d.metal=true
483-
-Djavafx.autoproxy.disable=true
484489
-Dorg.apache.xml.dtm.DTMManager=org.apache.xml.dtm.ref.DTMManagerDefault
490+
-Djdk.xml.xpathExprGrpLimit=0
491+
-Djdk.xml.xpathExprOpLimit=0
492+
-Djdk.xml.xpathTotalOpLimit=0
485493
--add-opens
486494
java.base/sun.nio.ch=ALL-UNNAMED
487495
--add-opens
@@ -550,12 +558,21 @@
550558
javafx.base/com.sun.javafx.collections=javafx.web
551559
--add-opens
552560
javafx.controls/javafx.scene.control=ALL-UNNAMED
561+
--add-opens
562+
javafx.controls/javafx.scene.control.skin=ALL-UNNAMED
563+
--add-opens
564+
javafx.graphics/javafx.scene.input=ALL-UNNAMED
565+
--add-opens
566+
javafx.web/javafx.scene.web=ALL-UNNAMED
567+
--add-opens
568+
javafx.web/com.sun.webkit=ALL-UNNAMED
553569
--add-exports
554570
javafx.base/com.sun.javafx.property=ALL-UNNAMED
555571
--add-exports
556572
javafx.controls/com.sun.javafx.scene.control=ALL-UNNAMED
557573
--add-modules=ALL-MODULE-PATH
558574
--add-modules=javafx.controls,javafx.fxml,javafx.graphics,javafx.media,javafx.swing,javafx.web
575+
-Djavafx.autoproxy.disable=true
559576
</extraJvmArguments>
560577
<!--&#45;&#45;add-opens javafx.base/com.sun.javafx.collections=javafx.web-->
561578
<!--&#45;&#45;add-exports javafx.controls/com.sun.javafx.scene.control=ALL-UNNAMED-->

src/main/java/com/kodedu/boot/AppStarter.java

+90-25
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
import com.kodedu.controller.ApplicationController;
66
import com.kodedu.helper.IOHelper;
77
import com.kodedu.helper.TaskbarHelper;
8+
import com.kodedu.other.RenderResult;
89
import com.kodedu.service.DirectoryService;
910
import com.kodedu.service.FileOpenListener;
1011
import com.kodedu.service.ThreadService;
11-
import com.kodedu.service.ui.IndikatorService;
12+
import com.kodedu.service.convert.docbook.DocBookConverter;
13+
import com.kodedu.service.convert.html.HtmlBookConverter;
14+
import com.kodedu.service.convert.pdf.PdfBookConverter;
1215
import com.kodedu.service.ui.TabService;
13-
import com.kodedu.terminalfx.helper.ThreadHelper;
1416
import de.tototec.cmdoption.CmdlineParser;
1517
import de.tototec.cmdoption.CmdlineParserException;
1618
import javafx.application.Application;
@@ -27,6 +29,7 @@
2729
import javafx.stage.Modality;
2830
import javafx.stage.Screen;
2931
import javafx.stage.Stage;
32+
import org.apache.commons.lang3.StringUtils;
3033
import org.slf4j.Logger;
3134
import org.slf4j.LoggerFactory;
3235
import org.springframework.boot.SpringApplication;
@@ -45,6 +48,8 @@
4548
import java.nio.file.Path;
4649
import java.nio.file.Paths;
4750
import java.security.SecureRandom;
51+
import java.util.Arrays;
52+
import java.util.Objects;
4853
import java.util.Set;
4954
import java.util.concurrent.ThreadLocalRandom;
5055
import java.util.function.Consumer;
@@ -56,7 +61,7 @@
5661

5762
public class AppStarter extends Application {
5863

59-
private Logger logger = LoggerFactory.getLogger(AppStarter.class);
64+
private static Logger logger = LoggerFactory.getLogger(AppStarter.class);
6065

6166
private static ApplicationController controller;
6267
private static ConfigurableApplicationContext context;
@@ -65,30 +70,40 @@ public class AppStarter extends Application {
6570
private ConfigurationService configurationService;
6671
private Image logoImage;
6772
private long startTime;
73+
public static CmdlineConfig config;
6874

6975
@Override
7076
public void start(final Stage stage) {
7177
this.startTime = System.currentTimeMillis();
72-
initializeSSLContext();
7378
stage.setTitle("AsciidocFX");
7479
logoImage = setApplicationIcon(stage);
7580
Thread.setDefaultUncaughtExceptionHandler((t, e) -> logger.error(e.getMessage(), e));
7681
Thread.startVirtualThread(() -> {
7782
loadRequiredFonts();
7883
});
7984

80-
// http://bit.ly/1Euk8hh
81-
System.setProperty("jsse.enableSNIExtension", "false");
82-
// System.setProperty("https.protocols", "SSLv3");
85+
Thread.startVirtualThread(() -> {
86+
try {
87+
startApp(stage);
88+
} catch (final Throwable e) {
89+
logger.error("Problem occured while starting AsciidocFX", e);
90+
}
91+
});
8392

84-
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
85-
System.setProperty("java.awt.headless", "false");
93+
}
8694

95+
private static void setupMonocle() {
96+
System.setProperty("monocle.platform", "Headless");
97+
System.setProperty("glass.platform", "Monocle");
98+
System.setProperty("prism.order", "sw");
99+
}
100+
101+
private static CmdlineConfig parseCmdArgs(String[] args) {
87102
final CmdlineConfig config = new CmdlineConfig();
88103
final CmdlineParser cp = new CmdlineParser(config);
89104

90105
try {
91-
cp.parse(getParameters().getRaw().toArray(new String[0]));
106+
cp.parse(args);
92107
} catch (final CmdlineParserException e) {
93108
System.err.println("Invalid commandline given: " + e.getMessage());
94109
System.exit(1);
@@ -98,20 +113,21 @@ public void start(final Stage stage) {
98113
cp.usage();
99114
System.exit(0);
100115
}
116+
return config;
117+
}
101118

102-
Thread.startVirtualThread(() -> {
103-
try {
104-
startApp(stage, config);
105-
} catch (final Throwable e) {
106-
logger.error("Problem occured while starting AsciidocFX", e);
107-
}
108-
});
119+
private static void setJvmProperties() {
120+
// http://bit.ly/1Euk8hh
121+
System.setProperty("jsse.enableSNIExtension", "false");
122+
// System.setProperty("https.protocols", "SSLv3");
109123

124+
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
125+
System.setProperty("java.awt.headless", "false");
110126
}
111127

112-
private void initializeSSLContext() {
128+
private static void initializeSSLContext() {
113129
try {
114-
SSLContext sc = SSLContext.getInstance("SSL");
130+
SSLContext sc = SSLContext.getInstance("TLS");
115131
sc.init(null, new TrustManager[]{new FakeTrustManager()}, new SecureRandom());
116132
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
117133
HttpsURLConnection.setDefaultHostnameVerifier((h, s) -> true);
@@ -121,9 +137,10 @@ private void initializeSSLContext() {
121137
}
122138
}
123139

124-
public void registerStartupListener() {
125-
Thread.startVirtualThread(() -> {
126-
StartupNotification.registerStartupListener(parameters -> {
140+
public void registerAssociatedFileHandler() {
141+
StartupNotification.registerStartupListener(parameters -> {
142+
threadService.runTaskLater(() -> {
143+
controller.waitAdocPreviewReadyLatch();
127144
FileOpenListener fileOpenListener = context.getBean(FileOpenListener.class);
128145
fileOpenListener.startupPerformed(parameters);
129146
});
@@ -149,14 +166,15 @@ public void loadRequiredFonts() {
149166
}
150167
}
151168

152-
private void startApp(final Stage stage, final CmdlineConfig config) throws Throwable {
169+
private void startApp(final Stage stage) throws Throwable {
153170

154171
this.stage = stage;
155172
SpringApplication app = new SpringApplication(SpringAppConfig.class);
156173
// app.setApplicationStartup(new BufferingApplicationStartup(20000));
157174
context = app.run(new String[]{});
158175
logger.debug("Spring context loaded in {} ms.", System.currentTimeMillis() - startTime);
159176
controller = context.getBean(ApplicationController.class);
177+
registerAssociatedFileHandler();
160178
threadService = context.getBean(ThreadService.class);
161179
configurationService = context.getBean(ConfigurationService.class);
162180

@@ -180,7 +198,6 @@ private void startApp(final Stage stage, final CmdlineConfig config) throws Thro
180198
configurationService.loadConfigurations();
181199
controller.applyInitialConfigurations();
182200
controller.checkStageInsideScreens();
183-
registerStartupListener();
184201
});
185202

186203
stage.setOnShown(e -> {
@@ -261,6 +278,7 @@ private void startApp(final Stage stage, final CmdlineConfig config) throws Thro
261278

262279
threadService.start(() -> {
263280
try {
281+
controller.waitAdocPreviewReadyLatch();
264282
registerStartupListener(config);
265283
} catch (Exception e) {
266284
logger.error("Problem occured in startup listener", e);
@@ -326,7 +344,13 @@ private void registerStartupListener(CmdlineConfig config) {
326344
if (workingDirectory == null) {
327345
directoryService.changeWorkigDir(file.toPath().getParent());
328346
}
329-
tabService.addTab(file.toPath());
347+
tabService.addTab(file.toPath(), () -> {
348+
threadService.runTaskLater(() -> {
349+
if (Objects.nonNull(config.backend)) {
350+
processFileConversion(config);
351+
}
352+
});
353+
});
330354
} else {
331355
// TODO: do we want to create such a file on demand?
332356
logger.error("Cannot open non-existent file: {}", file);
@@ -336,6 +360,38 @@ private void registerStartupListener(CmdlineConfig config) {
336360
});
337361
}
338362

363+
private void processFileConversion(CmdlineConfig config) {
364+
if (StringUtils.containsIgnoreCase(config.backend, "pdf")) {
365+
PdfBookConverter pdfBookConverter = context.getBean(PdfBookConverter.class);
366+
pdfBookConverter.convert(false, getRenderResultConsumer());
367+
} else if (StringUtils.containsIgnoreCase(config.backend, "html")) {
368+
HtmlBookConverter htmlBookConverter = context.getBean(HtmlBookConverter.class);
369+
htmlBookConverter.convert(false, getRenderResultConsumer());
370+
} else if (StringUtils.containsIgnoreCase(config.backend, "docbook")) {
371+
DocBookConverter docBookConverter = context.getBean(DocBookConverter.class);
372+
docBookConverter.convert(false, getRenderResultConsumer());
373+
}
374+
}
375+
376+
private Consumer<RenderResult> getRenderResultConsumer() {
377+
return renderResult -> {
378+
if (renderResult.isSuccessful()) {
379+
logger.info("Completed {}", renderResult.getDestination());
380+
} else {
381+
Exception exception = renderResult.getException();
382+
logger.info("Error {}", exception.getMessage(), exception);
383+
}
384+
385+
if (!config.noQuitAfter) {
386+
try {
387+
stop();
388+
} catch (Exception e) {
389+
logger.error(e.getMessage(), e);
390+
}
391+
}
392+
};
393+
}
394+
339395
private Path resolveWorkingDirectory(CmdlineConfig config) {
340396
if (config.workingDirectory != null) {
341397
File workingDirectory = new File(config.workingDirectory);
@@ -396,6 +452,15 @@ public void stop() throws Exception {
396452
* @param args the command line arguments
397453
*/
398454
public static void main(String[] args) {
455+
setJvmProperties();
456+
config = parseCmdArgs(args);
457+
logger.info("Args {}", Arrays.stream(args).collect(Collectors.joining(",")));
458+
logger.info("Parsed cmd configs: {}", config);
459+
if (config.headless) {
460+
logger.info("Starting in headless mode..");
461+
setupMonocle();
462+
}
463+
initializeSSLContext();
399464
launch(args);
400465
}
401466

src/main/java/com/kodedu/boot/CmdlineConfig.java

+26-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,33 @@ public class CmdlineConfig {
1111
boolean help = false;
1212

1313
@CmdOption(args = "FILE", description = "File to open", maxCount = -1)
14-
final List<String> files = new LinkedList<String>();
14+
final List<String> files = new LinkedList<>();
1515

16-
@CmdOption(names = {"--workdir", "-W"}, args = "DIRECTORY", description = "Working directory to use when generating opened files views")
16+
@CmdOption(names = {"--workdir", "-w"}, args = "DIRECTORY", description = "Working directory to use when generating opened files views")
1717
String workingDirectory = null;
1818

19+
@CmdOption(names = {"--backend", "-b"}, args = "BACKEND", description = "Defines output format: pdf, html, docbook")
20+
String backend = null;
21+
22+
@CmdOption(names = {"--headless", "-H"}, description = "Selects to start AsciidocFX in headless mode")
23+
boolean headless = false;
24+
25+
@CmdOption(names = {"--keep-after", "-K"}, description = "Keeps AsciidocFX running after conversion completed")
26+
boolean noQuitAfter = false;
27+
28+
public boolean isCmdStart() {
29+
return !files.isEmpty();
30+
}
31+
32+
@Override
33+
public String toString() {
34+
return "CmdlineConfig{" +
35+
"help=" + help +
36+
", files=" + files +
37+
", workingDirectory='" + workingDirectory + '\'' +
38+
", backend='" + backend + '\'' +
39+
", headless=" + headless +
40+
", noQuitAfter=" + noQuitAfter +
41+
'}';
42+
}
1943
}

0 commit comments

Comments
 (0)