package mj.ocraptor.events; import static mj.ocraptor.tools.St.removeLastLineBreak; import static mj.ocraptor.tools.St.shortenHomePathInDirectory; import static mj.ocraptor.tools.St.trimToLengthIndicatorLeft; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Node; import javafx.scene.paint.Color; import javafx.scene.text.Text; import mj.ocraptor.MainController; import mj.ocraptor.configuration.Config; import mj.ocraptor.configuration.properties.ConfigBool; import mj.ocraptor.configuration.properties.ConfigInteger; import mj.ocraptor.configuration.properties.ConfigString; import mj.ocraptor.database.DBFileStatus; import mj.ocraptor.database.search.LuceneResult; import mj.ocraptor.file_handler.utils.FileTools; import mj.ocraptor.javafx.GUIController; import mj.ocraptor.javafx.controllers.EditDatabase; import mj.ocraptor.javafx.controllers.SelectDatabase; 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; /** * * * @author */ public class EventGUI extends EventAbstr { private final static org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(EventGUI.class); private static Long startTime; private static final int timeDifference = 10; private static Long startTimeCount; private static final int timeDifferenceCount = 100; private GUIController gui; private Config cfg; /** * */ public EventGUI() { this.gui = GUIController.instance(); this.cfg = Config.inst(); } @Override protected void configFileNotFound(File invalidFile) { // TODO Auto-generated method stub } @Override protected void startCountingFiles() { // TODO Auto-generated method stub } @Override protected void countingFiles(Long currentCount, boolean finalCount) { if (finalCount || checkTimeRestrictionCount()) { if (!finalCount && currentCount < 10) return; Queue<ProgressUpdate> messageQueue = GUIController.instance().getMessageQueue(); List<Node> progressText = new ArrayList<Node>(); Text fileCount = new Text(this.gui.getText("EVENT_GUI.COUNTED_FILES", String .valueOf(currentCount))); fileCount.getStyleClass().add("countedFilesText"); progressText.add(fileCount); Text finished = new Text((finalCount ? "\n" + this.gui.getText("EVENT_GUI.FILTERING_BY_FILETYPE") : ".") + "\n"); finished.getStyleClass().add("filteringByFiletype"); progressText.add(finished); try { messageQueue.put(new ProgressUpdate(progressText, finalCount ? ProgressType.COUNTING_FILES_FINISHED : ProgressType.COUNTING_FILES)); } catch (InterruptedException e) { e.printStackTrace(); } } } /** * * * @return */ private static boolean checkTimeRestriction() { if (startTime == null || System.currentTimeMillis() - startTime > timeDifference) { startTime = System.currentTimeMillis(); return true; } return false; } /** * * * @return */ private static boolean checkTimeRestrictionCount() { if (startTimeCount == null || System.currentTimeMillis() - startTimeCount > timeDifferenceCount) { startTimeCount = System.currentTimeMillis(); return true; } return false; } @Override protected void configFileNameInvalid() { // TODO Auto-generated method stub } @Override protected void propertiesFileAlreadyExists() { // TODO Auto-generated method stub } private static final String PROCESSED_FILE_LABEL_CLASS = "processedFileLabel"; private static final String PROCESSED_FILE_TEXT_CLASS = "processedFileText"; private List<File> lastProgressText = null; @Override protected void printProcess(File file, Long filesCount, Long processedCount, boolean finalCount, DBFileStatus status) { boolean initialPost = this.gui.getParentController().showInitialCPUList(); ConcurrentHashMap<Long, File> threads = MainController.inst().getCurrentFileWorkers(); List<File> threadIDs = new ArrayList<File>(threads.values()); if (lastProgressText != null && lastProgressText.equals(threadIDs) && file == null) { return; } this.lastProgressText = threadIDs; if (checkTimeRestriction() || initialPost) { Queue<ProgressUpdate> messageQueue = GUIController.instance().getMessageQueue(); List<Node> progressText = new ArrayList<Node>(); ProgressType progressType = null; // ------------------------------------------------ // final int maxNumberOfThreads = MainController.inst().getNumThreads(); if (!threads.isEmpty()) { if (progressType == null) { progressType = ProgressType.THREAD_LIST_ONLY; } if (progressType == ProgressType.THREAD_LIST_ONLY || maxNumberOfThreads > 1) { int cpuIndex = 0; final Text cpuTitle = new Text(this.gui.getText("EVENT_GUI.LOOKING_AT") + " \n"); progressText.add(cpuTitle); // ------------------------------------------------ // for (File threadFile : threads.values()) { String filePath = threadFile.getPath(); // String extension = "(" + // FilenameUtils.getExtension(filePath).toUpperCase() + ")"; final Text cpu = new Text(); final Text cpuDetails = new Text(); if (maxNumberOfThreads > 1 && file != null && threadFile.getAbsoluteFile().equals(file.getAbsoluteFile())) { if (threads.values().size() > 1) { filePath = this.gui.getText("EVENT_GUI.CPU_THREAD_PICKING"); } else { filePath = this.gui.getText("EVENT_GUI.CPU_THREAD_FINISHING"); } cpuDetails.getStyleClass().add("cpuListChanging"); } String shortFilePath = trimToLengthIndicatorLeft(filePath, 50); shortFilePath = shortenHomePathInDirectory(shortFilePath); shortFilePath = FileTools.multiplatformPath(shortFilePath); cpu.setText(this.gui.getText("EVENT_GUI.CPU_THREAD", String.valueOf(++cpuIndex))); cpu.getStyleClass().add("cpuListText"); cpu.getStyleClass().add("cpuListTitle"); cpuDetails.setText(" " + shortFilePath + "\n"); cpuDetails.getStyleClass().add("cpuListText"); progressText.add(cpu); progressText.add(cpuDetails); } // ------------------------------------------------ // } } // ------------------------------------------------ // final boolean showOnlyNewFiles = this.cfg.getProp(ConfigBool.NEW_FILES_NOTIFICATION_ONLY); if (file != null && status != null && status != DBFileStatus.NOT_SUPPORTED && (showOnlyNewFiles && status == DBFileStatus.NOT_FOUND || !showOnlyNewFiles)) { // file name Text processedFileLabel = new Text("\n" + this.gui.getText("EVENT_GUI.PROCESSED_FILE_LABEL") + "\n"); processedFileLabel.getStyleClass().add(PROCESSED_FILE_LABEL_CLASS); progressText.add(processedFileLabel); Text processedFileText = new Text(file.getName() + "\n\n"); processedFileText.getStyleClass().add(PROCESSED_FILE_TEXT_CLASS); progressText.add(processedFileText); // file directory Text filePathLabel = new Text(this.gui.getText("EVENT_GUI.PROCESSED_FILE_PATH_LABEL") + "\n"); filePathLabel.getStyleClass().add("processedFilePathLabel"); progressText.add(filePathLabel); String filePath = shortenHomePathInDirectory(FileTools.multiplatformPath(file.getParentFile().getPath())); Text filePathText = new Text(filePath + "\n\n"); filePathText.getStyleClass().add("processedFilePathText"); progressText.add(filePathText); // classified as new/modified/not_changed Text classifiedLabel = new Text(this.gui.getText("EVENT_GUI.CLASSIFIED_AS") + "\n"); classifiedLabel.getStyleClass().add("classifiedLabel"); progressText.add(classifiedLabel); Text classifiedText = null; if (status == DBFileStatus.NOT_FOUND) { classifiedText = new Text(this.gui.getText("EVENT_GUI.CLASSIFIED_AS_NEW") + "\n"); classifiedText.getStyleClass().add("classifiedAsNew"); progressType = ProgressType.NEW_FILE_FOUND; } else if (status == DBFileStatus.UP_TO_DATE) { classifiedText = new Text(this.gui.getText("EVENT_GUI.CLASSIFIED_AS_UP_TO_DATE") + "\n"); classifiedText.getStyleClass().add("classifiedAsUpToDate"); progressType = ProgressType.KNOWN_FILE; } else { classifiedText = new Text(this.gui.getText("EVENT_GUI.CLASSIFIED_AS_MODIFIED") + "\n"); classifiedText.getStyleClass().add("classifiedAsModified"); progressType = ProgressType.MODIFIED_FILE; } classifiedText.getStyleClass().add("classifiedText"); progressText.add(classifiedText); } else if (initialPost) { // start message Text startMessage = new Text("\n" + this.gui.getText("EVENT_GUI.STARTING", String.valueOf(filesCount)) + "\n"); startMessage.getStyleClass().add("startMessageText"); progressText.add(startMessage); progressType = ProgressType.STARTING; } else { // not supportet file-type: } // ------------------------------------------------ // try { ProgressUpdate indicator = new ProgressUpdate(initialPost ? 0 : processedCount, filesCount, progressText, progressType); messageQueue.put(indicator); } catch (InterruptedException e) { // e.printStackTrace(); } } } @Override protected void cancelingIndexing() { Queue<ProgressUpdate> messageQueue = GUIController.instance().getMessageQueue(); List<Node> progressText = new ArrayList<Node>(); Text canceling = new Text(this.gui.getText("EVENT_GUI.CANCELING") + "\n"); canceling.getStyleClass().add("cancelingMessage"); progressText.add(canceling); try { ProgressUpdate ind = new ProgressUpdate(progressText, ProgressType.CANCELING); messageQueue.put(ind); } catch (InterruptedException e) { e.printStackTrace(); } } @Override protected void printResult(LuceneResult results, String contentSearch, Integer idToShow, int maxSnippetLength) { this.gui.setSearchResult(results, contentSearch); } @Override protected void searchProgressIndicator(double value, String text) { if (value > 0) { try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } GUIController.instance().getTemplate().setProgress(value, text); } @Override protected void initLoggerAppender(Logger logger) { String appenderName = "gui appender"; if (logger.getAppender(appenderName) == null) { logger.addAppender(new GuiLogAppender()); } } // TODO: jbig2-processing problems public static final String[] KNOWN_ISSUES = { "jbig2" }; /** * */ private class GuiLogAppender extends AppenderSkeleton { @Override protected void append(LoggingEvent event) { boolean exceptionScreenEnabled = cfg.getProp(ConfigBool.ENABLE_BUG_REPORT_SCREENS); 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 (GUIController.instance() != null && event != null && event.getLevel().isGreaterOrEqual(thresholdLevel) && exceptionScreenEnabled) { // ------------------------------------------------ // Queue<String> exceptionQueue = null; for (int i = 0; i < 50; i++) { if (exceptionQueue != null || Thread.currentThread().isInterrupted()) { break; } exceptionQueue = GUIController.instance().getExceptionQueue(); try { Thread.sleep(100); } catch (InterruptedException e1) { e1.printStackTrace(); } } // ------------------------------------------------ // try { StringBuffer message = new StringBuffer(); String generalMessage = event.getRenderedMessage(); message.append("[" + event.getLevel() + "] " + new Date() + "\n"); if (generalMessage != null && !generalMessage.trim().isEmpty()) { message.append("[MESSAGE] "); message.append(generalMessage + "\n"); } ThrowableInformation info = event.getThrowableInformation(); if (info != null) { Throwable e = info.getThrowable(); if (e != null) { message.append("[STACKTRACE] "); message.append(ExceptionUtils.getStackTrace(e)); } } for (String knownIssue : KNOWN_ISSUES) { if (message.toString().contains(knownIssue)) { return; } } if (cfg.getProp(ConfigBool.PAUSE_ON_ERROR)) { Platform.runLater(new Runnable() { @Override public void run() { Thread.currentThread().setName(Config.APP_NAME + "JavaFX: Pause Indexing on error"); gui.pauseIndexing(); } }); } // ------------------------------------------------ // // *INDENT-OFF* String[] acceptedMessages = new String[] { "port already in use" }; // *INDENT-ON* if (exceptionQueue != null) { boolean showMessage = true; final String guiMessage = message.toString(); for (String acceptedMessage : acceptedMessages) { if (guiMessage.toLowerCase().contains(acceptedMessage)) { showMessage = false; } } if (showMessage) { exceptionQueue.put(removeLastLineBreak(message.toString())); } } // ------------------------------------------------ // } 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) { Queue<ProgressUpdate> messageQueue = GUIController.instance().getMessageQueue(); List<Node> progressText = new ArrayList<Node>(); ProgressType progressType = null; if (filesDeleted == null && filesToLookAt != null) { Text looking = new Text(this.gui.getText("EVENT_GUI.MISSING_FILES", String .valueOf(filesToLookAt))); looking.getStyleClass().add("missingFiles"); progressText.add(looking); progressType = ProgressType.LOOKING_FOR_MISSING_FILES; } if (filesDeleted != null) { Text deleting = new Text(this.gui.getText("EVENT_GUI.REMOVED_FILES", String .valueOf(filesDeleted))); deleting.getStyleClass().add("removedFilesText"); progressText.add(deleting); progressType = ProgressType.MISSING_FILES_REMOVED; } try { messageQueue.put(new ProgressUpdate(progressText, progressType)); } catch (InterruptedException e) { e.printStackTrace(); } } @Override protected void databaseConnectError(Exception e, String dataPath) { if (e.getMessage() != null && e.getMessage().contains("Database may be already in use")) { this.gui.showConfirmationDialog(this.gui.getText("EVENT_GUI.DB_ALREADY_IN_USE")); } else { LOGGER.error("Problem occurred connecting to database", e); } this.gui.gotoPage(SelectDatabase.FXML, SelectDatabase.INIT_WIDTH, SelectDatabase.INIT_HEIGHT); } @Override protected void ocrEngineDeployError(Exception e) { // } @Override protected void serverStarted() { // } @Override protected void serverProblem(Exception e) { try { MainController.inst().shutdown(false); Platform.runLater(new Runnable() { @Override public void run() { // ------------------------------------------------ // EventHandler<ActionEvent> okHandler = new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent e) { try { gui.gotoPage(EditDatabase.FXML, EditDatabase.INIT_WIDTH, EditDatabase.INIT_HEIGHT); } catch (Exception ex) { LOGGER.error("Cant go back to EditDatabase", ex); } } }; // ------------------------------------------------ // gui.showConfirmationDialog(gui.getText("LOADING_SCREEN.PORT_NOT_FOUND", cfg .getProp(ConfigInteger.RMI_SERVER_PORT)), okHandler, 350, 200, false); Thread.currentThread().setName(Config.APP_NAME + "JavaFX-Event: shutdown indexing"); // ------------------------------------------------ // } }); } catch (Exception e2) { // TODO: logging e2.printStackTrace(); } } @Override protected void cantConnectToClients() { Platform.runLater(new Runnable() { @Override public void run() { gui.gotoPage(EditDatabase.FXML, EditDatabase.INIT_WIDTH, EditDatabase.INIT_HEIGHT); } }); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } Platform.runLater(new Runnable() { @Override public void run() { gui.showConfirmationDialog(gui.getText("EVENT_GUI.CANT_CONNECT_TO_CLIENTS"), 300, 150); } }); } }