diff --git a/Mage.Client/src/main/java/mage/client/components/MageEditorPane.java b/Mage.Client/src/main/java/mage/client/components/MageEditorPane.java index 76c39f0d92f..b466307618d 100644 --- a/Mage.Client/src/main/java/mage/client/components/MageEditorPane.java +++ b/Mage.Client/src/main/java/mage/client/components/MageEditorPane.java @@ -58,7 +58,7 @@ public class MageEditorPane extends JEditorPane { if (Arrays.stream(getHyperlinkListeners()).findAny().isPresent()) { throw new IllegalStateException("Wrong code usage: popup links support enabled already"); } - addHyperlinkListener(e -> ThreadUtils.threadPoolPopups.submit(() -> { + addHyperlinkListener(e -> MageUI.threadPoolPopups.submit(() -> { if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_TOOLTIPS_DELAY, 300) == 0) { // if disabled return; diff --git a/Mage.Client/src/main/java/mage/client/components/MageUI.java b/Mage.Client/src/main/java/mage/client/components/MageUI.java index 86db500ea86..19b6d3aba8d 100644 --- a/Mage.Client/src/main/java/mage/client/components/MageUI.java +++ b/Mage.Client/src/main/java/mage/client/components/MageUI.java @@ -1,16 +1,51 @@ package mage.client.components; +import mage.utils.ThreadUtils; +import org.apache.log4j.Logger; + import java.awt.Component; import java.util.EnumMap; import java.util.Map; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import javax.swing.JButton; public class MageUI { + private static final Logger logger = Logger.getLogger(MageUI.class); + private final Map ui = new EnumMap<>(MageComponents.class); private final Map sync = new EnumMap<>(MageComponents.class); + public static final ThreadPoolExecutor threadPoolPopups; + private static int threadCount; + + static { + threadPoolPopups = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new ThreadFactory() { + @Override + public Thread newThread(Runnable runnable) { + threadCount++; + Thread thread = new Thread(runnable, "POPUP-" + threadCount); + thread.setDaemon(true); + return thread; + } + }) { + @Override + protected void afterExecute(Runnable r, Throwable t) { + super.afterExecute(r, t); + + // catch errors in popup threads (example: card popup over cards or chat/log messages) + t = ThreadUtils.findRealException(r, t); + if (t != null) { + logger.error("Catch unhandled error in POPUP thread: " + t.getMessage(), t); + } + } + }; + threadPoolPopups.prestartAllCoreThreads(); + } + public JButton getButton(MageComponents name) throws InterruptedException { //System.out.println("request for " + name); Object buttonSync; diff --git a/Mage.Client/src/main/java/mage/client/plugins/adapters/MageActionCallback.java b/Mage.Client/src/main/java/mage/client/plugins/adapters/MageActionCallback.java index cc0b9ee6cb6..f48350c2c4d 100644 --- a/Mage.Client/src/main/java/mage/client/plugins/adapters/MageActionCallback.java +++ b/Mage.Client/src/main/java/mage/client/plugins/adapters/MageActionCallback.java @@ -10,6 +10,7 @@ import mage.client.SessionHandler; import mage.client.cards.BigCard; import mage.client.cards.CardEventProducer; import mage.client.components.MageComponents; +import mage.client.components.MageUI; import mage.client.dialog.PreferencesDialog; import mage.client.game.GamePane; import mage.client.plugins.impl.Plugins; @@ -187,7 +188,7 @@ public class MageActionCallback implements ActionCallback { private void showCardHintPopup(final TransferData data, final Component parentComponent, final Point parentPoint) { MageCard cardPanel = data.getComponent().getTopPanelRef(); - ThreadUtils.threadPoolPopups.submit(new Runnable() { + MageUI.threadPoolPopups.submit(new Runnable() { @Override public void run() { ThreadUtils.sleep(tooltipDelay); @@ -647,7 +648,7 @@ public class MageActionCallback implements ActionCallback { private void displayEnlargedCard(final CardView cardView, final TransferData data) { MageCard cardPanel = data.getComponent().getTopPanelRef(); - ThreadUtils.threadPoolPopups.submit(() -> { + MageUI.threadPoolPopups.submit(() -> { if (cardView == null) { return; } diff --git a/Mage.Client/src/main/java/mage/client/util/audio/LinePool.java b/Mage.Client/src/main/java/mage/client/util/audio/LinePool.java index e356115a6a2..f85d95b7933 100644 --- a/Mage.Client/src/main/java/mage/client/util/audio/LinePool.java +++ b/Mage.Client/src/main/java/mage/client/util/audio/LinePool.java @@ -7,6 +7,10 @@ import java.util.Queue; import java.util.Set; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; @@ -25,6 +29,31 @@ public class LinePool { private final org.apache.log4j.Logger logger = Logger.getLogger(LinePool.class); private static final int LINE_CLEANUP_INTERVAL = 30000; + private static final ThreadPoolExecutor threadPoolSounds; + private static int threadCount = 0; + static { + threadPoolSounds = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new ThreadFactory() { + @Override + public Thread newThread(Runnable runnable) { + threadCount++; + Thread thread = new Thread(runnable, "SOUND-" + threadCount); + thread.setDaemon(true); + return thread; + } + }) { + @Override + protected void afterExecute(Runnable r, Throwable t) { + super.afterExecute(r, t); + t = ThreadUtils.findRealException(r, t); + if (t != null) { + // TODO: show sound errors in client logs? + //logger.error("Catch unhandled error in SOUND thread: " + t.getMessage(), t); + } + } + }; + threadPoolSounds.prestartAllCoreThreads(); + } + private final Queue freeLines = new ArrayDeque<>(); private final Queue activeLines = new ArrayDeque<>(); private final Set busyLines = new HashSet<>(); @@ -106,7 +135,7 @@ public class LinePool { } logLineStats(); } - ThreadUtils.threadPoolSounds.submit(() -> { + threadPoolSounds.submit(() -> { synchronized (LinePool.this) { try { if (!line.isOpen()) { diff --git a/Mage.Common/src/main/java/mage/utils/ThreadUtils.java b/Mage.Common/src/main/java/mage/utils/ThreadUtils.java index 47cf6e67a9f..a4359e08f97 100644 --- a/Mage.Common/src/main/java/mage/utils/ThreadUtils.java +++ b/Mage.Common/src/main/java/mage/utils/ThreadUtils.java @@ -1,8 +1,8 @@ package mage.utils; -import org.apache.log4j.Logger; - -import java.util.concurrent.*; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; /** * Util method to work with threads. @@ -11,57 +11,6 @@ import java.util.concurrent.*; */ public final class ThreadUtils { - private static final Logger logger = Logger.getLogger(ThreadUtils.class); - - public static final ThreadPoolExecutor threadPoolSounds; - public static final ThreadPoolExecutor threadPoolPopups; - private static int threadCount; - - static { - threadPoolSounds = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new ThreadFactory() { - @Override - public Thread newThread(Runnable runnable) { - threadCount++; - Thread thread = new Thread(runnable, "SOUND-" + threadCount); - thread.setDaemon(true); - return thread; - } - }) { - @Override - protected void afterExecute(Runnable r, Throwable t) { - super.afterExecute(r, t); - t = findRealException(r, t); - if (t != null) { - // TODO: show sound errors in client logs? - //logger.error("Catch unhandled error in SOUND thread: " + t.getMessage(), t); - } - } - }; - threadPoolSounds.prestartAllCoreThreads(); - - threadPoolPopups = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new ThreadFactory() { - @Override - public Thread newThread(Runnable runnable) { - threadCount++; - Thread thread = new Thread(runnable, "POPUP-" + threadCount); - thread.setDaemon(true); - return thread; - } - }) { - @Override - protected void afterExecute(Runnable r, Throwable t) { - super.afterExecute(r, t); - - // catch errors in popup threads (example: card popup over cards or chat/log messages) - t = findRealException(r, t); - if (t != null) { - logger.error("Catch unhandled error in POPUP thread: " + t.getMessage(), t); - } - } - }; - threadPoolPopups.prestartAllCoreThreads(); - } - public static void sleep(int millis) { try { Thread.sleep(millis); @@ -81,9 +30,6 @@ public final class ThreadUtils { /** * Find real exception object after thread task completed. Can be used in afterExecute * - * @param r - * @param t - * @return */ public static Throwable findRealException(Runnable r, Throwable t) { // executer.submit - return exception in result diff --git a/Mage.Tests/src/test/resources/log4j.properties b/Mage.Tests/src/test/resources/log4j.properties index e3edadcf937..586fcef2bb2 100644 --- a/Mage.Tests/src/test/resources/log4j.properties +++ b/Mage.Tests/src/test/resources/log4j.properties @@ -30,8 +30,10 @@ log4j.appender.logfileByIndex.MaxBackupIndex=3 log4j.appender.logfileByIndex.append=true #file log - errors only -log4j.appender.watchdog=org.apache.log4j.FileAppender +log4j.appender.watchdog=org.apache.log4j.RollingFileAppender log4j.appender.watchdog.layout=org.apache.log4j.PatternLayout log4j.appender.watchdog.layout.ConversionPattern=%-5p [%d{yyyy-MM-dd HH:mm [ss:SSS]}] %C{1}[%t]: %m%n log4j.appender.watchdog.file=magetestErrors.log +log4j.appender.watchdog.MaxFileSize=10MB +log4j.appender.watchdog.MaxBackupIndex=1 log4j.appender.watchdog.Threshold=error \ No newline at end of file