diff --git a/dspace-api/src/main/java/org/dspace/curate/FileReporter.java b/dspace-api/src/main/java/org/dspace/curate/FileReporter.java new file mode 100644 index 0000000000..7a82347d10 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/curate/FileReporter.java @@ -0,0 +1,81 @@ + +package org.dspace.curate; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.GregorianCalendar; + +import org.dspace.services.ConfigurationService; +import org.dspace.utils.DSpace; + +/** + * Save a curation report to a unique file in the reports directory. + * Reports are named by the date and time of day, for example: + * "curation-20180916T113903045.report". + * + * @author mhwood + */ +public class FileReporter + implements Reporter { + private final Writer writer; + + /** + * Open a writer to a file in a directory named by the configuration + * property {@code reports.dir}, or in {@code [DSpace]/reports} if not + * configured. + * + * @throws IOException if there is a problem with the file path. + */ + public FileReporter() + throws IOException { + // Calculate a unique(?) file name. + Date now = GregorianCalendar.getInstance().getTime(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddThhmmssSSS"); + String filename = String.format("curation-%s.report", sdf.format(now)); + + // Build a path to the directory which is to receive the file. + ConfigurationService cfg = new DSpace().getConfigurationService(); + String reportDir = cfg.getProperty("report.dir"); + Path reportPath; + if (null == reportDir) { + reportPath = Paths.get(cfg.getProperty("dspace.dir"), + "reports", + filename); + } else { + reportPath = Paths.get(reportDir, filename); + } + + // Open the file. + writer = new FileWriter(reportPath.toFile()); + } + + @Override + public Appendable append(CharSequence cs) + throws IOException { + writer.append(cs); + return this; + } + + @Override + public Appendable append(CharSequence cs, int i, int i1) + throws IOException { + writer.append(cs, i, i1); + return this; + } + + @Override + public Appendable append(char c) throws IOException { + writer.append(c); + return this; + } + + @Override + public void close() throws Exception { + writer.close(); + } +} diff --git a/dspace-api/src/main/java/org/dspace/curate/LogReporter.java b/dspace-api/src/main/java/org/dspace/curate/LogReporter.java new file mode 100644 index 0000000000..115ae0193c --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/curate/LogReporter.java @@ -0,0 +1,70 @@ + +package org.dspace.curate; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Write curation report records through the logging framework. + * Whole lines (strings ending in '\n') are written to a log category named by + * the task ID, for example "curation.virusscan". + * Any partial line is flushed when the reporter is {@code close()}d. + * + * @author mhwood + */ +public class LogReporter + implements Reporter { + private static Logger LOG; + private final String taskID; + private final StringBuilder buffer = new StringBuilder(); + + private LogReporter() { + taskID = null; + } + + public LogReporter(String object, String task) { + taskID = task; + } + + private Logger getLogger() { + if (null == LOG) { + LOG = LoggerFactory.getLogger("curation." + taskID); + } + return LOG; + } + + @Override + public Appendable append(CharSequence cs) + throws IOException { + for (int pos = 0; pos < cs.length(); pos++) { + char c = cs.charAt(pos); + if (c == '\n') { + getLogger().info(buffer.toString()); + buffer.delete(0, buffer.length()); // Clear the buffer + } else { + buffer.append(c); + } + } + return this; + } + + @Override + public Appendable append(CharSequence cs, int i, int i1) + throws IOException { + return append(cs.subSequence(i, i1)); + } + + @Override + public Appendable append(char c) + throws IOException { + return append(String.valueOf(c)); + } + + @Override + public void close() + throws Exception { + getLogger().info(buffer.toString()); + } +} diff --git a/dspace-api/src/main/java/org/dspace/curate/Reporter.java b/dspace-api/src/main/java/org/dspace/curate/Reporter.java new file mode 100644 index 0000000000..b48f833e57 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/curate/Reporter.java @@ -0,0 +1,11 @@ + +package org.dspace.curate; + +/** + * A marker interface needed to make curation reporter classes into plugins. + * + * @author mhwood + */ +public interface Reporter + extends Appendable, AutoCloseable { +} diff --git a/dspace-api/src/main/java/org/dspace/curate/WorkflowCuratorServiceImpl.java b/dspace-api/src/main/java/org/dspace/curate/WorkflowCuratorServiceImpl.java index 66c18c2cf3..7389e4517b 100644 --- a/dspace-api/src/main/java/org/dspace/curate/WorkflowCuratorServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/curate/WorkflowCuratorServiceImpl.java @@ -36,6 +36,8 @@ import org.dspace.content.Item; import org.dspace.content.service.CollectionService; import org.dspace.core.Context; import org.dspace.core.LogManager; +import org.dspace.core.factory.CoreServiceFactory; +import org.dspace.core.service.PluginService; import org.dspace.curate.service.WorkflowCuratorService; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; @@ -133,14 +135,15 @@ public class WorkflowCuratorServiceImpl implements WorkflowCuratorService { basicWorkflowItemService.update(c, wfi); return false; } else { - Date now = GregorianCalendar.getInstance().getTime(); - SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddThhmmssSSS"); - String filename = String.format("curation-%s.log", sdf.format(now)); - Path logPath = Paths.get( - configurationService.getProperty("dspace.dir"), "logs", filename); - try (PrintWriter reporter = new PrintWriter(logPath.toFile())) { + PluginService plugins = CoreServiceFactory.getInstance() + .getPluginService(); + try (Reporter reporter + = (Reporter) plugins + .getSinglePlugin(Reporter.class);) { curator.setReporter(reporter); return curate(curator, c, wfi); + } catch (Exception e) { + log.error("Failed to close report", e); } } }