1 package de.todesbaum.jsite.application.validation;
4 import java.util.Arrays;
5 import java.util.HashSet;
8 import java.util.Map.Entry;
10 import java.util.concurrent.CountDownLatch;
11 import java.util.logging.Level;
12 import java.util.logging.Logger;
13 import java.util.stream.Stream;
15 import de.todesbaum.jsite.application.FileOption;
16 import de.todesbaum.jsite.application.Project;
17 import de.todesbaum.jsite.gui.FileScanner;
18 import de.todesbaum.jsite.gui.ScannedFile;
21 * Validates a project and returns a number of {@link Issue}s in a {@link CheckReport}.
23 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
25 public class ProjectValidator {
27 private static final Logger logger = Logger.getLogger(ProjectValidator.class.getName());
29 public static CheckReport validateProject(Project project) {
30 CheckReport checkReport = new CheckReport();
31 if ((project.getLocalPath() == null) || (project.getLocalPath().trim().length() == 0)) {
32 checkReport.addIssue("error.no-local-path", true);
35 if ((project.getPath() == null) || (project.getPath().trim().length() == 0)) {
36 checkReport.addIssue("error.no-path", true);
38 if ((project.getIndexFile() == null) || (project.getIndexFile().length() == 0)) {
39 checkReport.addIssue("warning.empty-index", false);
41 File indexFile = new File(project.getLocalPath(), project.getIndexFile());
42 if (!indexFile.exists()) {
43 checkReport.addIssue("error.index-missing", true);
46 String indexFile = project.getIndexFile();
47 boolean hasIndexFile = (indexFile != null) && (indexFile.length() > 0);
48 if (hasIndexFile && indexFileIsNotHtml(project, indexFile)) {
49 checkReport.addIssue("warning.index-not-html", false);
51 Map<String, FileOption> fileOptions = project.getFileOptions();
52 Set<Entry<String, FileOption>> fileOptionEntries = fileOptions.entrySet();
53 boolean insert = fileOptionEntries.isEmpty();
54 for (Entry<String, FileOption> fileOptionEntry : fileOptionEntries) {
55 String fileName = fileOptionEntry.getKey();
56 FileOption fileOption = fileOptionEntry.getValue();
57 insert |= fileOption.isInsert() || fileOption.isInsertRedirect();
58 if (fileName.equals(project.getIndexFile()) && !fileOption.isInsert() && !fileOption.isInsertRedirect()) {
59 checkReport.addIssue("error.index-not-inserted", true);
61 if (!fileOption.isInsert() && fileOption.isInsertRedirect() && ((fileOption.getCustomKey().length() == 0) || "CHK@".equals(
62 fileOption.getCustomKey()))) {
63 checkReport.addIssue("error.no-custom-key", true, fileName);
67 checkReport.addIssue("error.no-files-to-insert", true);
69 Set<String> fileNames = new HashSet<>();
70 for (Entry<String, FileOption> fileOptionEntry : fileOptionEntries) {
71 FileOption fileOption = fileOptionEntry.getValue();
72 if (!fileOption.isInsert() && !fileOption.isInsertRedirect()) {
73 logger.log(Level.FINEST, "Ignoring {0}.", fileOptionEntry.getKey());
76 String fileName = fileOption.getChangedName().orElse(fileOptionEntry.getKey());
77 logger.log(Level.FINEST, "Adding “{0}” for {1}.", new Object[] { fileName, fileOptionEntry.getKey() });
78 if (!fileNames.add(fileName)) {
79 checkReport.addIssue("error.duplicate-file", true, fileName);
83 final CountDownLatch completionLatch = new CountDownLatch(1);
84 FileScanner fileScanner = new FileScanner(project, (error, files) -> completionLatch.countDown());
85 fileScanner.startInBackground();
86 while (completionLatch.getCount() > 0) {
88 completionLatch.await();
89 } catch (InterruptedException ie1) {
93 for (ScannedFile scannedFile : fileScanner.getFiles()) {
94 String fileName = scannedFile.getFilename();
95 FileOption fileOption = project.getFileOption(fileName);
96 if ((fileOption != null) && !fileOption.isInsert()) {
99 totalSize += new File(project.getLocalPath(), fileName).length();
101 if (totalSize > 2 * 1024 * 1024) {
102 checkReport.addIssue("warning.site-larger-than-2-mib", false);
107 private static boolean indexFileIsNotHtml(Project project, String indexFile) {
108 return Stream.of("text/html", "application/xhtml+xml")
109 .noneMatch(mimeType -> project.getFileOption(indexFile).getMimeType().startsWith(mimeType));