/*
WebBox - Dein Server.
Copyright (C) 2020 Ulrich Hilger, http://uhilger.de
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.wbx.web;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import static org.asciidoctor.Asciidoctor.Factory.create;
import org.asciidoctor.Asciidoctor;
import static org.asciidoctor.AttributesBuilder.attributes;
import static org.asciidoctor.OptionsBuilder.options;
/**
* Das AdocServlet wandelt AsciiDoc-Inhalte (*.adoc)
* zu HTML-Seiten und PDF-Dokumenten
*
* Mit Angabe des Parameters ?pdf=true im URL wird PDF erzeugt, andernfalls HTML
*/
public class AdocServlet extends HttpServlet {
private static final String DOT = ".";
private static final String HTML = "html";
private static final String PDF = "pdf";
private static final String SERVLET_NAME = "AdocServlet";
/**
* Die Methode processRequest verarbeitet HTTP-Anfragen des Typs
* GET
und POST
.
*
* @param request die Servlet-Anfrage
* @param response die Servlet-Antwort
* @throws ServletException wenn ein Servlet-spezifischer Fehler passiert
* @throws IOException wenn ein Eingabe- oder Ausgabe-Fehler passiert
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
// Asciidoc-Quelldatei aus HTTP-Request ermitteln
String vPath = request.getServletPath();
String absname = getServletContext().getRealPath(vPath);
File adocfile = new File(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
response.setCharacterEncoding("UTF-8");
/*
nach HTML transformieren, wenn die Quelle sich geandert hat oder
die HTML-Datei noch nicht existiert
*/
if(!htmlfile.exists() || adocfile.lastModified() > htmlfile.lastModified()) {
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
*/
String pdf = request.getParameter(PDF);
if(null != pdf && pdf.equalsIgnoreCase(Boolean.TRUE.toString())) {
File pdffile = new File(adocfile.getParentFile(), fname + DOT + PDF);
outfile = pdffile; // PDF soll zurueckgegeben werden
if(!pdffile.exists() || adocfile.lastModified() > pdffile.lastModified()) {
transform(absname, PDF);
}
}
try (PrintWriter out = response.getWriter()) {
// abhaengig vom Parameter pdf HTML- oder PDF-Datei ausgeben
FileInputStream in = new FileInputStream(outfile);
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String line;
while ((line = reader.readLine()) != null) {
out.println(line);
}
}
}
/**
* 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) {
Map attributes;
File outFile = new File(fileName);
File pdfStyles = new File(outFile.getParentFile(), "custom-theme.yml");
if(pdfStyles.exists()) {
attributes = attributes()
.attribute("pdf-themesdir", outFile.getParent())
.attribute("pdf-theme","custom")
.sourceHighlighter("highlightjs")
.asMap();
} else {
attributes = attributes()
.sourceHighlighter("highlightjs")
.asMap();
}
Map options;
if(null != backend) {
options = options().inPlace(false)
.backend(backend).attributes(attributes).asMap();
} else {
options = options().inPlace(false)
.attributes(attributes).asMap();
}
Asciidoctor asciidoctor = create();
asciidoctor.requireLibrary("asciidoctor-diagram");
asciidoctor.convertFile(new File(fileName), options);
}
/**
* Die HTTP-GET
-Methode verarbeiten.
*
* @param request die Servlet-Anfrage
* @param response die Servlet-Antwort
* @throws ServletException wenn ein Servlet-spezifischer Fehler passiert
* @throws IOException wenn ein Eingabe- oder Ausgabe-Fehler passiert
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Die HTTP-POST
-Methode verarbeiten.
*
* @param request die Servlet-Anfrage
* @param response die Servlet-Antwort
* @throws ServletException wenn ein Servlet-spezifischer Fehler passiert
* @throws IOException wenn ein Eingabe- oder Ausgabe-Fehler passiert
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Eine Kurzbeschreibung des Servlets ausgeben.
*
* @return einen String mit der Kurzbeschreibung des Servlets
*/
@Override
public String getServletInfo() {
return SERVLET_NAME;
}
}