package ctbrec.docs; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Objects; import java.util.jar.JarEntry; import java.util.jar.JarFile; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class AbstractDocServlet extends HttpServlet { private static final transient Logger LOG = LoggerFactory.getLogger(AbstractDocServlet.class); String loadFile(String resource) throws IOException { InputStream resourceAsStream = getClass().getResourceAsStream(resource); if(resourceAsStream == null) { throw new FileNotFoundException(); } ByteArrayOutputStream out = new ByteArrayOutputStream(); int length = 0; byte[] buffer = new byte[1024]; while( (length = resourceAsStream.read(buffer)) >= 0 ) { out.write(buffer, 0, length); } return new String(out.toByteArray(), "utf-8"); } String getHeader() throws IOException { return loadFile("/html/docs/header.html"); } String getFooter() throws IOException { return loadFile("/html/docs/footer.html"); } List getPages() throws IOException { List pages = new ArrayList<>(); URL resource = getClass().getResource("/html/docs"); if(Objects.equals(resource.getProtocol(), "file")) { LOG.debug("FILE {}", resource.toString()); indexDirectory(resource, pages); } else if(Objects.equals(resource.getProtocol(), "jar")) { LOG.debug("JAR {}", resource.toString()); indexJar(resource, pages); } pages.add("index.md"); Collections.sort(pages, (a, b) -> a.compareToIgnoreCase(b)); return pages; } private void indexJar(URL resource, List pages) throws IOException { String fileUrl = resource.getFile(); int colon = fileUrl.indexOf(':'); int exclamation = fileUrl.indexOf('!'); String jar = fileUrl.substring(colon + 1, exclamation); String internalFile = fileUrl.substring(exclamation + 2); try (JarFile jarFile = new JarFile(jar)) { Enumeration entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry jarEntry = entries.nextElement(); String name = jarEntry.getName(); if (name.startsWith(internalFile) && name.toLowerCase().endsWith(".md")) { pages.add(name.substring(name.lastIndexOf('/') + 1)); } } } } private void indexDirectory(URL resource, List pages) { File docs = new File(resource.getFile()); String[] files = docs.list((dir, name) -> name.toLowerCase().endsWith(".md")); for (String file : files) { pages.add(file); } } String loadMarkdown(String path) throws IOException { String resource = "/html" + path; return loadFile(resource); } protected void error(HttpServletResponse resp, int status, String message) throws IOException { resp.setStatus(status); resp.getWriter().println(getHeader()); String html = loadFile("/html/docs/" + status + ".html"); if(message == null || message.trim().isEmpty()) { message = ""; } html = html.replace("{message}", message); resp.getWriter().println(html); resp.getWriter().println(getFooter()); } }