package mj.ocraptor.events; import java.io.File; import java.util.Date; import java.util.Map; import java.util.SortedMap; import mj.ocraptor.MainController; import mj.ocraptor.configuration.Config; import mj.ocraptor.configuration.Localization; import mj.ocraptor.configuration.properties.ConfigString; import mj.ocraptor.console.AnsiColor; import mj.ocraptor.console.COF; import mj.ocraptor.database.DBFileStatus; import mj.ocraptor.database.dao.FileEntry; import mj.ocraptor.database.search.LuceneResult; import mj.ocraptor.database.search.PartialEntry; import mj.ocraptor.database.search.StyledSnippet; import mj.ocraptor.database.search.StyledSnippetType; import mj.ocraptor.database.search.TextProcessing; import mj.ocraptor.file_handler.utils.FileTools; import mj.ocraptor.javafx.GUIController; import mj.ocraptor.tools.St; import mj.ocraptor.tools.Tp; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.Priority; import org.apache.log4j.spi.LoggingEvent; import org.apache.log4j.spi.ThrowableInformation; import org.apache.lucene.search.Query; public class EventConsole extends EventAbstr { private static final int timeDifference = 500; private static Long startTime; private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory .getLogger(EventConsole.class); private static final String ERROR_COLOR = AnsiColor.RED_BACKGROUND.toString() + AnsiColor.WHITE.toString(); @Override protected void configFileNotFound(File invalidFile) { COF.printCLIHelp(FILE_NOT_FOUND_ERROR + " \n\"" + invalidFile.getAbsolutePath() + "\""); } @Override protected void startCountingFiles() { COF.printEmptySeparator(); COF.printLine(AnsiColor.BOLD + "Starting to count files:"); } @Override protected void countingFiles(Long currentCount, boolean finalCount) { COF.printFileCount(currentCount, finalCount); } @Override protected void configFileNameInvalid() { // TODO Auto-generated method stub } @Override protected void propertiesFileAlreadyExists() { // TODO Auto-generated method stub } /** * * * @return */ private static boolean checkTimeRestriction() { if (startTime == null || System.currentTimeMillis() - startTime > timeDifference) { startTime = System.currentTimeMillis(); return true; } return false; } /** * @param file * @param filesCount * @param processedCount * @param finalCount * @param status */ @Override protected void printProcess(File file, Long filesCount, Long processedCount, boolean finalCount, DBFileStatus status) { //System.out.println(filesCount + " - " + processedCount); // TODO: DELETE IT! if (Config.inst().verbose() || (filesCount == null || processedCount == null)) { if (status != DBFileStatus.NOT_SUPPORTED && (finalCount || checkTimeRestriction() || file != null)) { COF.printFile(filesCount, processedCount, file, status); startTime = System.currentTimeMillis(); } else if (checkTimeRestriction()) { COF.printFile(filesCount, processedCount, null, status); startTime = System.currentTimeMillis(); } } else if (Config.inst().showProgress()) { COF.printProcess(filesCount, processedCount); } if (finalCount) { COF.printEmptySeparator(); COF.printLine(AnsiColor.BOLD.toString() + "Progress: finished"); COF.printEmptySeparator(); } } @Override protected void cancelingIndexing() { // TODO Auto-generated method stub } @Override protected void printResult(final LuceneResult results, final String contentSearch, final Integer idToShow, final int maxSnippetLength) { // print results is heavy on the cpu, we don't want to run this twice if (GUIController.instance() != null || results == null) { return; } final Throwable throwable = results.getThrowable(); final String error_color = AnsiColor.RED_BACKGROUND.toString() + AnsiColor.WHITE.toString(); if (throwable != null) { COF.printEmptySeparator(); COF.printText(error_color + Localization.instance().getText("ERROR.LUCENE_ERROR") + "\n "); COF.printText(error_color + ExceptionUtils.getRootCauseMessage(throwable)); COF.printEmptySeparator(); } else if (results.getFileEntries().isEmpty()) { COF.printEmptySeparator(); COF.printText(error_color + Localization.instance().getText("SEARCH_RESULT.NO_RESULTS")); COF.printEmptySeparator(); } Integer index = null; int pseudoID = 1; for (Map.Entry<FileEntry, Double> flEntry : results.getFileEntries()) { final Double score = flEntry.getValue(); final FileEntry fileEntry = flEntry.getKey(); SortedMap<Integer, PartialEntry> positions = null; try { String original = fileEntry.getFullTextString(); final String encodedXml = TextProcessing.encodePagePositions(original); // TODO: cancel in cmd? // if (cancelResultGeneration) // return false; positions = TextProcessing.decodePagePositions(encodedXml); } catch (Exception e) { // TODO: logging e.printStackTrace(); } final String fulltext = fileEntry.getFullTextString(); if (fulltext != null && !fulltext.isEmpty() && contentSearch != null) { try { final Query query = TextProcessing.getQueryParser().parse(contentSearch); final String text = TextProcessing.postProcess(fulltext); if (text != null && !text.isEmpty()) { int snippetsToShow = 50; // *INDENT-OFF* Tp<String[], Integer[]> resultTupel = TextProcessing.prepareHighlight( text, "", query, idToShow == null ? maxSnippetLength : maxSnippetLength * 3, snippetsToShow, true ); // *INDENT-ON* // ------------------------------------------------ // COF.printEmptySeparator(); COF.printText(AnsiColor.BOLD + "FILE: " + fileEntry.getFile().getName()); COF.printText(AnsiColor.BOLD + "DIR: " + St.shortenHomePathInDirectory(fileEntry.getFile().getParentFile() .getAbsolutePath())); if (score != null) { COF.printText(AnsiColor.BOLD + "SCORE: " + score); } COF.printText(AnsiColor.BOLD + "ID: " + pseudoID++); // ------------------------------------------------ // if (resultTupel == null) { COF.printText(AnsiColor.RED_BACKGROUND.toString() + AnsiColor.WHITE.toString() + "Something went wrong, can not generate snippet"); COF.printEmptySeparator(); continue; } // ------------------------------------------------ // final String[] snippets = resultTupel.getKey(); for (int i = 0; i < snippets.length; i++) { final String sn = snippets[i]; index = resultTupel.getValue()[i]; final StyledSnippet styledSnippet = TextProcessing.highlightString(text, sn, positions, index, fileEntry.getFile().getName()); String coloredSnipped = colorSnippet(styledSnippet); COF.printEmptySeparator(); COF.printText(coloredSnipped); } COF.printEmptySeparator(); } } catch (Exception e) { e.printStackTrace(); } } } } /** * * * @param snippet * @return */ private String colorSnippet(final StyledSnippet styledSnippet) { final StringBuilder finalStringBuilder = new StringBuilder(); for (final Tp<String, StyledSnippetType> snippet : styledSnippet.getSnippets()) { final String finalSnippetString = snippet.getKey(); final StyledSnippetType snippetType = snippet.getValue(); finalStringBuilder.append(AnsiColor.DEFAULT); // aa if (snippetType == StyledSnippetType.FULLTEXT) { } else if (snippetType == StyledSnippetType.HIGHLIGHT) { finalStringBuilder.append(AnsiColor.BLUE.toString() + AnsiColor.BOLD.toString()); } else if (snippetType == StyledSnippetType.LINE_SEPERATOR) { finalStringBuilder.append(AnsiColor.GREEN.toString()); } else if (snippetType == StyledSnippetType.METADATA) { finalStringBuilder.append(AnsiColor.MAGENTA); } else if (snippetType == StyledSnippetType.IMAGE_TEXT) { finalStringBuilder.append(AnsiColor.RED.toString()); } else if (snippetType == StyledSnippetType.START_INDICATOR) { finalStringBuilder.append(AnsiColor.GREEN.toString()); } else if (snippetType == StyledSnippetType.TRIMMED_INDICATOR) { // TODO: not working for ending indicator, COF.printText removes // formatting // finalStringBuilder.append(AnsiColor.RED_BACKGROUND.toString()); } finalStringBuilder.append(finalSnippetString); finalStringBuilder.append(AnsiColor.DEFAULT); } return finalStringBuilder.toString(); } @Override protected void searchProgressIndicator(double value, String text) { // } public static final String CONSOLE_PATTERN = // "[%-5p]--%d{yyyy-MM-dd HH:mm:ss}--%c{1}%n[Thread:%t][%l]%n%m%n"; // TODO: jbig2-processing problems public static final String[] KNOWN_ISSUES = { "jbig2" }; @Override protected void initLoggerAppender(Logger logger) { String appenderName = "console appender"; if (logger.getAppender(appenderName) == null) { logger.addAppender(new FormattedLogAppender()); } } private class FormattedLogAppender extends AppenderSkeleton { @Override protected void append(LoggingEvent event) { String threshold = Config.inst().getProp(ConfigString.LOGFILE_THRESHOLD_OUTPUT); Priority thresholdLevel = Level.ERROR; if (threshold != null) { if (threshold.equals("FATAL")) { thresholdLevel = Level.FATAL; } else if (threshold.equals("ERROR")) { thresholdLevel = Level.ERROR; } else if (threshold.equals("INFO")) { thresholdLevel = Level.INFO; } else if (threshold.equals("DEBUG")) { thresholdLevel = Level.DEBUG; } } // ------------------------------------------------ // if (event != null && event.getLevel().isGreaterOrEqual(thresholdLevel)) { // ------------------------------------------------ // COF.printSeparator(); COF.printEmptySeparator(); try { String generalMessage = event.getRenderedMessage(); COF.printLine(ERROR_COLOR + "[" + event.getLevel() + "] " + new Date() + "\n"); if (generalMessage != null && !generalMessage.trim().isEmpty()) { COF.printText(ERROR_COLOR + "[MESSAGE] " + generalMessage + "\n"); } ThrowableInformation info = event.getThrowableInformation(); Throwable e = null; if (info != null) { e = info.getThrowable(); } if (e == null) { COF.printEmptySeparator(); return; } String stacktrace = ExceptionUtils.getStackTrace(e); for (String knownIssue : KNOWN_ISSUES) { if (stacktrace.contains(knownIssue)) { return; } } Integer linecount = null; try { linecount = FileTools.countTextfileLines(Config.inst().getMainLogFile()) - St.countLines(stacktrace) + 1; } catch (Exception e2) { } COF.printEmptySeparator(); // *INDENT-OFF* if (e.getMessage() != null) { COF.printText( ERROR_COLOR + (!e.getMessage().equals(generalMessage) ? "[DETAILS] " + e.getMessage(): "") + (e.getCause() != null ? "\n[CAUSE] " + e.getCause() : "") + "\n[LOGFILE] " + Config.inst().getMainLogAbsoluteFilePath() + (linecount != null ? "\n[LOGFILE-LINE] " + linecount : "")); } // *INDENT-ON* final String stack = ERROR_COLOR + "[FULL STACKTRACE]\n" + ExceptionUtils.getStackTrace(e); if (Config.inst().verbose()) { COF.printText(stack); } else { COF.printLines(stack); } COF.printEmptySeparator(); // ------------------------------------------------ // } catch (Exception e) { e.printStackTrace(); } } } public void close() { // --- } public boolean requiresLayout() { return false; } } @Override protected void failedToProcessFile(String error, String filePath) { // TODO Auto-generated method stub } @Override protected void removingMissingFiles(Integer filesDeleted, Integer filesToLookAt) { if (filesDeleted == null && filesToLookAt != null) { COF.printEmptySeparator(); COF.printLine(AnsiColor.BOLD + "Looking for missing files in database:"); String filesToLookAtInfo = AnsiColor.BOLD + "[" + St.zeroPadSpaces(filesToLookAt, 4) + "]" + AnsiColor.DEFAULT + " files to look at"; if (filesToLookAt > 500) { filesToLookAtInfo += " This could take a while"; } COF.printLine(filesToLookAtInfo); } if (filesDeleted != null) { COF.printLine(AnsiColor.BOLD + "[" + St.zeroPadSpaces(filesDeleted, 4) + "]" + AnsiColor.DEFAULT + " files removed from your database"); } } @Override protected void databaseConnectError(final Exception e, final String dataPath) { // *INDENT-OFF* // COF.printLines( // "ERROR: failed to connect to database \"" // + dataPath // + "\"\nSee error-message in the log file:\n" // + Config.inst().getMainLogAbsoluteFilePath() + "\n\n" // + ExceptionUtils.getStackTrace(e) // ); // *INDENT-OFF* LOGGER.error("Failed to connect to database", e); if (EventManager.instance().getEventHandlers().size() == 1) { MainController.inst().shutdown(false); } } @Override protected void ocrEngineDeployError(Exception e) { } @Override protected void serverStarted() { COF.printEmptySeparator(); COF.printLine(AnsiColor.MAGENTA.toString() + AnsiColor.BOLD.toString() + "RMI Server started - listening for clients"); COF.printEmptySeparator(); } @Override protected void serverProblem(Exception e) { LOGGER.error("Can not connect server", e); } @Override protected void cantConnectToClients() { } }