/*
http-adoc - Asciidoctor extensions to jdk.httpserver
Copyright (C) 2021 Ulrich Hilger
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
package de.uhilger.httpserver.adoc;
import com.sun.net.httpserver.HttpExchange;
import de.uhilger.httpserver.base.HttpResponder;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.asciidoctor.Asciidoctor.Factory.create;
import org.asciidoctor.Asciidoctor;
import static org.asciidoctor.AttributesBuilder.attributes;
import static org.asciidoctor.OptionsBuilder.options;
import org.asciidoctor.SafeMode;
/**
* Der AdocActor transformiert den Asciidoctor-Quellcode aus einer
* gegebenen Datei zu HTML oder PDF und legt das Ergebnis als HTML- oder
* PDF-Datei ab.
*
* Der AdocActor benötigt AsciidoctorJ im Classpath.
*
* @author Ulrich Hilger
* @version 1, 16.06.2021
*/
public class AdocActor {
private static final Logger logger = Logger.getLogger(AdocActor.class.getName());
private static final String DOT = ".";
public static final String HTML = "html";
public static final String PDF = "pdf";
public void handle(HttpExchange e, String fileBase, String fileName) throws IOException {
File adocfile = new File(fileBase, fileName);
logger.fine("adocfile: " + adocfile.getAbsolutePath());
AdocActor actor = new AdocActor();
File outfile = actor.getTargetFile(adocfile, AdocActor.HTML);
logger.fine("outfile: " + outfile.getAbsolutePath());
HttpResponder fs = new HttpResponder();
fs.serveFile(e, outfile);
}
public File getTargetFile(File adocfile, String ext) {
String nameext = adocfile.getName();
String fname = nameext.substring(0, nameext.lastIndexOf(DOT));
File outfile = new File(adocfile.getParentFile(), fname + DOT + ext);
logger.log(Level.FINE, "out: {0}", outfile.getAbsolutePath());
return outfile;
}
public void processAdocFile(File adocfile, String pdf) {
String absname = adocfile.getAbsolutePath();
logger.log(Level.FINE, "in: {0}", absname);
// HTML-Datei ermitteln
//String nameext = adocfile.getName();
//String fname = nameext.substring(0, nameext.lastIndexOf(DOT));
//File htmlfile = new File(adocfile.getParentFile(), fname + DOT + HTML);
//File outfile = htmlfile; // Standardmaessig wird HTML zurueckgegeben
//logger.fine("out: " + outfile.getAbsolutePath());
//response.setCharacterEncoding("UTF-8");
File outfile = getTargetFile(adocfile, HTML);
File htmlfile = outfile;
/*
nach HTML transformieren, wenn die Quelle sich geandert hat oder
die HTML-Datei noch nicht existiert
*/
if(!htmlfile.exists() || adocfile.lastModified() > htmlfile.lastModified()) {
logger.fine("calling transform for " + absname);
transform(absname);
}
/*
nach PDF transformieren, wenn der Parameter pdf=true existiert und
wenn die Quelle sich geandert hat oder
die PDF-Datei noch nicht existiert
*/
if(null != pdf && pdf.equalsIgnoreCase(Boolean.TRUE.toString())) {
//File pdffile = new File(adocfile.getParentFile(), fname + DOT + PDF);
File pdffile = getTargetFile(adocfile, PDF);
outfile = pdffile; // PDF soll zurueckgegeben werden
if(!pdffile.exists() || adocfile.lastModified() > pdffile.lastModified()) {
//response.setContentType("application/pdf");
transform(absname, PDF);
}
//ServletOutputStream os = response.getOutputStream();
//InputStream bytes = new FileInputStream(outfile);
//int b = bytes.read();
//while(b > -1 ) {
// os.write(b);
// b = bytes.read();
//}
} else {
//PrintWriter out = response.getWriter();
//InputStreamReader in = new InputStreamReader(new FileInputStream(outfile), "UTF-8");
//in.transferTo(out);
}
}
/**
* Nach HTML transformieren
* @param fileName der Dateiname der Quelldatei samt absoluter Pfadangabe
*/
private void transform(String fileName) {
transform(fileName, null);
}
/**
* In ein Format transformieren, das von einem 'Backend' von Asciidoctor
* unterstuetzt wird
* @param fileName der Dateiname der Quelldatei samt absoluter Pfadangabe
* @param backend das Kuerzel des Backends, z.B. der String 'pdf', wenn
* nach PDF transformiert werden soll
*/
private void transform(String fileName, String backend) {
logger.fine("fileName: " + fileName + ", backend: " + backend);
Map attributes;
File outFile = new File(fileName);
String thisDirName = outFile.getParent();
File pdfStyles = new File(outFile.getParentFile(), "custom-theme.yml");
if(pdfStyles.exists()) {
attributes = attributes()
.attribute("pdf-themesdir", thisDirName)
.attribute("pdf-theme","custom")
.attribute("pdf-fontsdir", thisDirName + "/fonts")
.attribute("allow-uri-read")
.sourceHighlighter("highlightjs")
.asMap();
} else {
attributes = attributes()
.sourceHighlighter("highlightjs")
.asMap();
}
Map options;
if(null != backend) {
options = options().inPlace(false)
.safe(SafeMode.SERVER)
.backend(backend).attributes(attributes).asMap();
} else {
options = options().inPlace(false)
.safe(SafeMode.SERVER)
.attributes(attributes).asMap();
}
File adcf = new File(fileName);
logger.fine("before asciidoctor create, adcf: " + adcf.getAbsolutePath());
Asciidoctor asciidoctor = create();
logger.fine("asciidoctor created.");
asciidoctor.requireLibrary("asciidoctor-diagram");
logger.fine("asciidoctor requireLibrary diagram passed.");
logger.fine("calling asciidoctor.convert for file " + adcf.getAbsolutePath());
asciidoctor.convertFile(adcf, options);
}
}