X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fde%2Ftodesbaum%2Fjsite%2Fapplication%2FProjectInserter.java;h=22ddaa0af2d0aa625137874d0a2715cd2f0b86a3;hb=8db42d2121e8ee465ab8380a66febde1949a0106;hp=1504a9fb7891868d7af617d2e962565ec73fbc45;hpb=f936411037a6ec1afbc5efbb17dc9b0136adda76;p=jSite.git diff --git a/src/main/java/de/todesbaum/jsite/application/ProjectInserter.java b/src/main/java/de/todesbaum/jsite/application/ProjectInserter.java index 1504a9f..22ddaa0 100644 --- a/src/main/java/de/todesbaum/jsite/application/ProjectInserter.java +++ b/src/main/java/de/todesbaum/jsite/application/ProjectInserter.java @@ -1,5 +1,5 @@ /* - * jSite - ProjectInserter.java - Copyright © 2006–2014 David Roden + * jSite - ProjectInserter.java - Copyright © 2006–2019 David Roden * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,23 +23,17 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Iterator; +import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.CountDownLatch; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; import net.pterodactylus.util.io.StreamCopier.ProgressListener; -import com.google.common.base.Optional; import de.todesbaum.jsite.gui.FileScanner; -import de.todesbaum.jsite.gui.FileScanner.ScannedFile; +import de.todesbaum.jsite.gui.ScannedFile; import de.todesbaum.jsite.gui.FileScannerListener; import de.todesbaum.util.freenet.fcp2.Client; import de.todesbaum.util.freenet.fcp2.ClientPutComplexDir; @@ -65,7 +59,7 @@ public class ProjectInserter implements FileScannerListener, Runnable { private static final int random = (int) (Math.random() * Integer.MAX_VALUE); /** Counter for FCP connection identifier. */ - private static int counter = 0; + private static final AtomicInteger counter = new AtomicInteger(); private final ProjectInsertListeners projectInsertListeners = new ProjectInsertListeners(); @@ -170,9 +164,8 @@ public class ProjectInserter implements FileScannerListener, Runnable { public void start(ProgressListener progressListener) { cancelled = false; this.progressListener = progressListener; - fileScanner = new FileScanner(project); - fileScanner.addFileScannerListener(this); - new Thread(fileScanner).start(); + fileScanner = new FileScanner(project, this); + fileScanner.startInBackground(); } /** @@ -195,7 +188,7 @@ public class ProjectInserter implements FileScannerListener, Runnable { * The name and hash of the file to insert * @return A file entry for the given file */ - private FileEntry createFileEntry(ScannedFile file) { + private Optional createFileEntry(ScannedFile file) { String filename = file.getFilename(); FileOption fileOption = project.getFileOption(filename); if (fileOption.isInsert()) { @@ -204,118 +197,25 @@ public class ProjectInserter implements FileScannerListener, Runnable { if (!project.isAlwaysForceInsert() && !fileOption.isForceInsert() && file.getHash().equals(fileOption.getLastInsertHash())) { /* only insert a redirect. */ logger.log(Level.FINE, String.format("Inserting redirect to edition %d for %s.", fileOption.getLastInsertEdition(), filename)); - return new RedirectFileEntry(fileOption.getChangedName().or(filename), fileOption.getMimeType(), "SSK@" + project.getRequestURI() + "/" + project.getPath() + "-" + fileOption.getLastInsertEdition() + "/" + fileOption.getLastInsertFilename()); + return Optional.of(new RedirectFileEntry(fileOption.getChangedName().orElse(filename), fileOption.getMimeType(), "SSK@" + project.getRequestURI() + "/" + project.getPath() + "-" + fileOption.getLastInsertEdition() + "/" + fileOption.getLastInsertFilename())); } try { - return createFileEntry(filename, fileOption.getChangedName(), fileOption.getMimeType()); + return Optional.of(createFileEntry(filename, fileOption.getChangedName(), fileOption.getMimeType())); } catch (IOException ioe1) { /* ignore, null is returned. */ } } else { if (fileOption.isInsertRedirect()) { - return new RedirectFileEntry(fileOption.getChangedName().or(filename), fileOption.getMimeType(), fileOption.getCustomKey()); + return Optional.of(new RedirectFileEntry(fileOption.getChangedName().orElse(filename), fileOption.getMimeType(), fileOption.getCustomKey())); } } - return null; + return Optional.empty(); } private FileEntry createFileEntry(String filename, Optional changedName, String mimeType) throws FileNotFoundException { File physicalFile = new File(project.getLocalPath(), filename); InputStream fileEntryInputStream = new FileInputStream(physicalFile); - return new DirectFileEntry(changedName.or(filename), mimeType, fileEntryInputStream, physicalFile.length()); - } - - /** - * Validates the given project. The project will be checked for any invalid - * conditions, such as invalid insert or request keys, missing path names, - * missing default file, and so on. - * - * @param project - * The project to check - * @return The encountered warnings and errors - */ - public static CheckReport validateProject(Project project) { - CheckReport checkReport = new CheckReport(); - if ((project.getLocalPath() == null) || (project.getLocalPath().trim().length() == 0)) { - checkReport.addIssue("error.no-local-path", true); - } - if ((project.getPath() == null) || (project.getPath().trim().length() == 0)) { - checkReport.addIssue("error.no-path", true); - } - if ((project.getIndexFile() == null) || (project.getIndexFile().length() == 0)) { - checkReport.addIssue("warning.empty-index", false); - } else { - File indexFile = new File(project.getLocalPath(), project.getIndexFile()); - if (!indexFile.exists()) { - checkReport.addIssue("error.index-missing", true); - } - } - String indexFile = project.getIndexFile(); - boolean hasIndexFile = (indexFile != null) && (indexFile.length() > 0); - List allowedIndexContentTypes = Arrays.asList("text/html", "application/xhtml+xml"); - if (hasIndexFile && !allowedIndexContentTypes.contains(project.getFileOption(indexFile).getMimeType())) { - checkReport.addIssue("warning.index-not-html", false); - } - Map fileOptions = project.getFileOptions(); - Set> fileOptionEntries = fileOptions.entrySet(); - boolean insert = fileOptionEntries.isEmpty(); - for (Entry fileOptionEntry : fileOptionEntries) { - String fileName = fileOptionEntry.getKey(); - FileOption fileOption = fileOptionEntry.getValue(); - insert |= fileOption.isInsert() || fileOption.isInsertRedirect(); - if (fileName.equals(project.getIndexFile()) && !fileOption.isInsert() && !fileOption.isInsertRedirect()) { - checkReport.addIssue("error.index-not-inserted", true); - } - if (!fileOption.isInsert() && fileOption.isInsertRedirect() && ((fileOption.getCustomKey().length() == 0) || "CHK@".equals(fileOption.getCustomKey()))) { - checkReport.addIssue("error.no-custom-key", true, fileName); - } - } - if (!insert) { - checkReport.addIssue("error.no-files-to-insert", true); - } - Set fileNames = new HashSet(); - for (Entry fileOptionEntry : fileOptionEntries) { - FileOption fileOption = fileOptionEntry.getValue(); - if (!fileOption.isInsert() && !fileOption.isInsertRedirect()) { - logger.log(Level.FINEST, "Ignoring {0}.", fileOptionEntry.getKey()); - continue; - } - String fileName = fileOption.getChangedName().or(fileOptionEntry.getKey()); - logger.log(Level.FINEST, "Adding “{0}” for {1}.", new Object[] { fileName, fileOptionEntry.getKey() }); - if (!fileNames.add(fileName)) { - checkReport.addIssue("error.duplicate-file", true, fileName); - } - } - long totalSize = 0; - FileScanner fileScanner = new FileScanner(project); - final CountDownLatch completionLatch = new CountDownLatch(1); - fileScanner.addFileScannerListener(new FileScannerListener() { - - @Override - public void fileScannerFinished(FileScanner fileScanner) { - completionLatch.countDown(); - } - }); - new Thread(fileScanner).start(); - while (completionLatch.getCount() > 0) { - try { - completionLatch.await(); - } catch (InterruptedException ie1) { - /* TODO: logging */ - } - } - for (ScannedFile scannedFile : fileScanner.getFiles()) { - String fileName = scannedFile.getFilename(); - FileOption fileOption = project.getFileOption(fileName); - if ((fileOption != null) && !fileOption.isInsert()) { - continue; - } - totalSize += new File(project.getLocalPath(), fileName).length(); - } - if (totalSize > 2 * 1024 * 1024) { - checkReport.addIssue("warning.site-larger-than-2-mib", false); - } - return checkReport; + return new DirectFileEntry(changedName.orElse(filename), mimeType, fileEntryInputStream, physicalFile.length()); } /** @@ -328,7 +228,7 @@ public class ProjectInserter implements FileScannerListener, Runnable { /* create connection to node */ synchronized (lockObject) { - connection = freenetInterface.getConnection("project-insert-" + random + counter++); + connection = freenetInterface.getConnection("project-insert-" + random + counter.getAndIncrement()); } connection.setTempDirectory(tempDirectory); boolean connected = false; @@ -349,7 +249,7 @@ public class ProjectInserter implements FileScannerListener, Runnable { /* collect files */ int edition = project.getEdition(); String dirURI = "USK@" + project.getInsertURI() + "/" + project.getPath() + "/" + edition + "/"; - ClientPutComplexDir putDir = new ClientPutComplexDir("dir-" + counter++, dirURI, tempDirectory); + ClientPutComplexDir putDir = new ClientPutComplexDir("dir-" + counter.getAndIncrement(), dirURI, tempDirectory); if ((project.getIndexFile() != null) && (project.getIndexFile().length() > 0)) { FileOption indexFileOption = project.getFileOption(project.getIndexFile()); Optional changedName = indexFileOption.getChangedName(); @@ -364,10 +264,10 @@ public class ProjectInserter implements FileScannerListener, Runnable { putDir.setEarlyEncode(useEarlyEncode); putDir.setPriorityClass(priority); for (ScannedFile file : files) { - FileEntry fileEntry = createFileEntry(file); - if (fileEntry != null) { + Optional fileEntry = createFileEntry(file); + if (fileEntry.isPresent()) { try { - putDir.addFileEntry(fileEntry); + putDir.addFileEntry(fileEntry.get()); } catch (IOException ioe1) { projectInsertListeners.fireProjectInsertFinished(project, false, ioe1); return; @@ -433,148 +333,12 @@ public class ProjectInserter implements FileScannerListener, Runnable { * {@inheritDoc} */ @Override - public void fileScannerFinished(FileScanner fileScanner) { - if (!fileScanner.isError()) { + public void fileScannerFinished(boolean error, Collection files) { + if (!error) { new Thread(this).start(); } else { projectInsertListeners.fireProjectInsertFinished(project, false, null); } - fileScanner.removeFileScannerListener(this); - } - - /** - * Container class that collects all warnings and errors that occured during - * {@link ProjectInserter#validateProject(Project) project validation}. - * - * @author David ‘Bombe’ Roden - */ - public static class CheckReport implements Iterable { - - /** The issures that occured. */ - private final List issues = new ArrayList(); - - /** - * Adds an issue. - * - * @param issue - * The issue to add - */ - public void addIssue(Issue issue) { - issues.add(issue); - } - - /** - * Creates an {@link Issue} from the given error key and fatality flag - * and {@link #addIssue(Issue) adds} it. - * - * @param errorKey - * The error key - * @param fatal - * {@code true} if the error is fatal, {@code false} if only - * a warning should be generated - * @param parameters - * Any additional parameters - */ - public void addIssue(String errorKey, boolean fatal, String... parameters) { - addIssue(new Issue(errorKey, fatal, parameters)); - } - - /** - * {@inheritDoc} - */ - @Override - public Iterator iterator() { - return issues.iterator(); - } - - /** - * Returns whether this check report does not contain any errors. - * - * @return {@code true} if this check report does not contain any - * errors, {@code false} if this check report does contain - * errors - */ - public boolean isEmpty() { - return issues.isEmpty(); - } - - /** - * Returns the number of issues in this check report. - * - * @return The number of issues - */ - public int size() { - return issues.size(); - } - - } - - /** - * Container class for a single issue. An issue contains an error key - * that describes the error, and a fatality flag that determines whether - * the insert has to be aborted (if the flag is {@code true}) or if it - * can still be performed and only a warning should be generated (if the - * flag is {@code false}). - * - * @author David ‘Bombe’ - * Roden - */ - public static class Issue { - - /** The error key. */ - private final String errorKey; - - /** The fatality flag. */ - private final boolean fatal; - - /** Additional parameters. */ - private String[] parameters; - - /** - * Creates a new issue. - * - * @param errorKey - * The error key - * @param fatal - * The fatality flag - * @param parameters - * Any additional parameters - */ - protected Issue(String errorKey, boolean fatal, String... parameters) { - this.errorKey = errorKey; - this.fatal = fatal; - this.parameters = parameters; - } - - /** - * Returns the key of the encountered error. - * - * @return The error key - */ - public String getErrorKey() { - return errorKey; - } - - /** - * Returns whether the issue is fatal and the insert has to be - * aborted. Otherwise only a warning should be shown. - * - * @return {@code true} if the insert needs to be aborted, {@code - * false} otherwise - */ - public boolean isFatal() { - return fatal; - } - - /** - * Returns any additional parameters. - * - * @return The additional parameters - */ - public String[] getParameters() { - return parameters; - } - } }