Blocker and Critical level bugfixes throughout the project (#4648)

* fixed https://sonarcloud.io/project/issues?id=org.xmage%3Amage-root&issues=AWIlv32RgrzAwlaaQ7rP&open=AWIlv32RgrzAwlaaQ7rP

* ensure closing of scanner if it was opened

* Refactored method in EmpyrialArchAngel to not always return same value.

* Refactored method in FalkenrathAristocrat to not always return same value.

* Refactored method in GilderBairn to not always return the same value.

* fixed left open resources, ensured quiet closing of the streams

* Refactored method in IceCave to not always return same value.

* Refactored method in KjeldoranRoyalGuard to not always return same value.

* Refactored method in LegionsInitiative to not always return same value.

* Refactored method in NaturesWill to not always return same value.

* added quiet closing method in new streamutils class, used to clean up the connectdialog

* Fix small typo

* added quiet closing to saveobjectutil

* closed resources in savegame method of gamecontroller

* properly close resources in loadGame method of GameReplay class

* further proper resource closing in ServerMessagesUtil

* fixed unclosed resources in copy method in mage framework Copier

* closed unclosed resources in copyCompressed method in Copier

* ensure closing of filewriter in manasymbols

* ensure proper closing of Stream in arcane UI

* ensure closing of datagram socket in arcane Util

* ensure resource closing in deckimport from clipboard

* ensure closing of plugin classloader

* ensured closing of zipinputstream resource

* ensure closing of fileoutputstream in ScryfallSymbolsSource

* ensure closing resources after finishing/canceling download of pictures

* remove commented code

* move locks to try block to ensure unlocking along all execution paths

* remove dangerous instance of double-checked locking

* removed dangerous instance of double checked locking in settingsmanager

* Removed dangerous instance of double-checked locking in ThemePluginImpl

* close resource which did not happen certainly

* close another stream

* ensure closing of inputstream
This commit is contained in:
ArcadeMode 2018-03-22 14:13:13 +01:00 committed by Jeff Wadsworth
parent ec77cecbf6
commit 5ac975c52e
31 changed files with 288 additions and 276 deletions

View file

@ -67,6 +67,10 @@ public class ManaPieChart extends JComponent {
for (int i = 0; i < slices.length; i++) { for (int i = 0; i < slices.length; i++) {
total += slices[i].value; total += slices[i].value;
} }
if (total == 0.0D) {
return; //there are no slices or no slices with a value > 0, stop here
}
double curValue = 0.0D; double curValue = 0.0D;
int startAngle = 0; int startAngle = 0;

View file

@ -1,5 +1,7 @@
package mage.client.deckeditor; package mage.client.deckeditor;
import mage.util.StreamUtils;
import java.awt.*; import java.awt.*;
import java.awt.event.*; import java.awt.event.*;
import java.io.BufferedWriter; import java.io.BufferedWriter;
@ -39,15 +41,16 @@ public class DeckImportFromClipboardDialog extends JDialog {
} }
private void onOK() { private void onOK() {
BufferedWriter bw = null;
try { try {
File temp = File.createTempFile("cbimportdeck", ".txt"); File temp = File.createTempFile("cbimportdeck", ".txt");
BufferedWriter bw = new BufferedWriter(new FileWriter(temp)); bw = new BufferedWriter(new FileWriter(temp));
bw.write(txtDeckList.getText()); bw.write(txtDeckList.getText());
bw.close();
tmpPath = temp.getPath(); tmpPath = temp.getPath();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
StreamUtils.closeQuietly(bw);
} }
dispose(); dispose();

View file

@ -43,6 +43,7 @@ import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Writer; import java.io.Writer;
import java.io.Closeable;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Proxy; import java.net.Proxy;
import java.net.SocketException; import java.net.SocketException;
@ -73,6 +74,7 @@ import mage.client.util.Config;
import mage.client.util.gui.countryBox.CountryItemEditor; import mage.client.util.gui.countryBox.CountryItemEditor;
import mage.client.util.sets.ConstructedFormats; import mage.client.util.sets.ConstructedFormats;
import mage.remote.Connection; import mage.remote.Connection;
import mage.utils.StreamUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
@ -565,6 +567,7 @@ public class ConnectDialog extends MageDialog {
private void findPublicServerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed private void findPublicServerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
BufferedReader in = null; BufferedReader in = null;
Writer output = null;
try { try {
String serverUrl = PreferencesDialog.getCachedValue(KEY_CONNECTION_URL_SERVER_LIST, "http://xmage.de/files/server-list.txt"); String serverUrl = PreferencesDialog.getCachedValue(KEY_CONNECTION_URL_SERVER_LIST, "http://xmage.de/files/server-list.txt");
if (serverUrl.contains("xmage.info/files/")) { if (serverUrl.contains("xmage.info/files/")) {
@ -618,7 +621,7 @@ public class ConnectDialog extends MageDialog {
} }
List<String> servers = new ArrayList<>(); List<String> servers = new ArrayList<>();
if (in != null) { if (in != null) {
Writer output = null;
if (!URLNotFound) { if (!URLNotFound) {
// write serverlist to be able to read if URL is not available // write serverlist to be able to read if URL is not available
File file = new File("serverlist.txt"); File file = new File("serverlist.txt");
@ -637,10 +640,6 @@ public class ConnectDialog extends MageDialog {
} }
} }
if (output != null) {
output.close();
}
in.close();
} }
if (servers.isEmpty()) { if (servers.isEmpty()) {
JOptionPane.showMessageDialog(null, "Couldn't find any server."); JOptionPane.showMessageDialog(null, "Couldn't find any server.");
@ -668,15 +667,12 @@ public class ConnectDialog extends MageDialog {
} catch (Exception ex) { } catch (Exception ex) {
logger.error(ex, ex); logger.error(ex, ex);
} finally { } finally {
if (in != null) { StreamUtils.closeQuietly(in);
try { StreamUtils.closeQuietly(output);
in.close();
} catch (Exception e) {
}
}
} }
}//GEN-LAST:event_jButton1ActionPerformed }//GEN-LAST:event_jButton1ActionPerformed
private void jProxySettingsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jProxySettingsButtonActionPerformed private void jProxySettingsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jProxySettingsButtonActionPerformed
PreferencesDialog.main(new String[]{PreferencesDialog.OPEN_CONNECTION_TAB}); PreferencesDialog.main(new String[]{PreferencesDialog.OPEN_CONNECTION_TAB});
}//GEN-LAST:event_jProxySettingsButtonActionPerformed }//GEN-LAST:event_jProxySettingsButtonActionPerformed

View file

@ -45,16 +45,12 @@ public class ArrowBuilder {
* Get the panel where all arrows are being drawn. * Get the panel where all arrows are being drawn.
* @return * @return
*/ */
public JPanel getArrowsManagerPanel() { public synchronized JPanel getArrowsManagerPanel() {
if (arrowsManagerPanel == null) { if (arrowsManagerPanel == null) {
synchronized (ArrowBuilder.class) { arrowsManagerPanel = new JPanel();
if (arrowsManagerPanel == null) { arrowsManagerPanel.setVisible(true);
arrowsManagerPanel = new JPanel(); arrowsManagerPanel.setOpaque(false);
arrowsManagerPanel.setVisible(true); arrowsManagerPanel.setLayout(null);
arrowsManagerPanel.setOpaque(false);
arrowsManagerPanel.setLayout(null);
}
}
} }
return arrowsManagerPanel; return arrowsManagerPanel;
} }

View file

@ -1,5 +1,7 @@
package mage.client.util.object; package mage.client.util.object;
import mage.utils.StreamUtils;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -61,10 +63,9 @@ public final class SaveObjectUtil {
oos.writeObject(object); oos.writeObject(object);
oos.close(); oos.close();
} catch (FileNotFoundException e) { } catch (Exception e) {
return; } finally {
} catch (IOException io) { StreamUtils.closeQuietly(oos);
return;
} }
} }
} }

View file

@ -41,6 +41,7 @@ import mage.client.constants.Constants.ResourceSymbolSize;
import mage.client.util.GUISizeHelper; import mage.client.util.GUISizeHelper;
import mage.client.util.ImageHelper; import mage.client.util.ImageHelper;
import mage.client.util.gui.BufferedImageBuilder; import mage.client.util.gui.BufferedImageBuilder;
import mage.utils.StreamUtils;
import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.dom.svg.SVGDOMImplementation;
import org.apache.batik.transcoder.TranscoderException; import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput; import org.apache.batik.transcoder.TranscoderInput;
@ -249,10 +250,15 @@ public final class ManaSymbols {
+ "color-rendering: optimizeQuality;" + "color-rendering: optimizeQuality;"
+ "image-rendering: optimizeQuality;" + "image-rendering: optimizeQuality;"
+ "}"; + "}";
File cssFile = File.createTempFile("batik-default-override-", ".css"); File cssFile = File.createTempFile("batik-default-override-", ".css");
FileWriter w = new FileWriter(cssFile); FileWriter w = null;
w.write(css); try {
w.close(); w = new FileWriter(cssFile);
w.write(css);
} finally {
StreamUtils.closeQuietly(w);
}
TranscodingHints transcoderHints = new TranscodingHints(); TranscodingHints transcoderHints = new TranscodingHints();
@ -284,7 +290,6 @@ public final class ManaSymbols {
try { try {
TranscoderInput input = new TranscoderInput(new FileInputStream(svgFile)); TranscoderInput input = new TranscoderInput(new FileInputStream(svgFile));
ImageTranscoder t = new ImageTranscoder() { ImageTranscoder t = new ImageTranscoder() {
@Override @Override

View file

@ -1,5 +1,7 @@
package org.mage.card.arcane; package org.mage.card.arcane;
import mage.utils.StreamUtils;
import java.awt.Component; import java.awt.Component;
import java.awt.Container; import java.awt.Container;
import java.awt.Dimension; import java.awt.Dimension;
@ -72,8 +74,8 @@ public final class UI {
} }
public static ImageIcon getImageIcon (String path) { public static ImageIcon getImageIcon (String path) {
InputStream stream = null;
try { try {
InputStream stream;
stream = UI.class.getResourceAsStream(path); stream = UI.class.getResourceAsStream(path);
if (stream == null && new File(path).exists()) { if (stream == null && new File(path).exists()) {
stream = new FileInputStream(path); stream = new FileInputStream(path);
@ -86,6 +88,8 @@ public final class UI {
return new ImageIcon(data); return new ImageIcon(data);
} catch (IOException ex) { } catch (IOException ex) {
throw new RuntimeException("Error reading image: " + path); throw new RuntimeException("Error reading image: " + path);
} finally {
StreamUtils.closeQuietly(stream);
} }
} }

View file

@ -37,9 +37,13 @@ public final class Util {
} }
public static void broadcast(byte[] data, int port) throws IOException { public static void broadcast(byte[] data, int port) throws IOException {
DatagramSocket socket = new DatagramSocket(); DatagramSocket socket = null;
broadcast(socket, data, port, NetworkInterface.getNetworkInterfaces()); try {
socket.close(); socket = new DatagramSocket();
broadcast(socket, data, port, NetworkInterface.getNetworkInterfaces());
} finally {
socket.close();
}
} }
private static void broadcast(DatagramSocket socket, byte[] data, int port, Enumeration<NetworkInterface> ifaces) private static void broadcast(DatagramSocket socket, byte[] data, int port, Enumeration<NetworkInterface> ifaces)

View file

@ -9,6 +9,7 @@ import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import mage.util.StreamUtils;
import org.mage.plugins.card.dl.DownloadJob; import org.mage.plugins.card.dl.DownloadJob;
import static org.mage.card.arcane.ManaSymbols.getSymbolFileNameAsSVG; import static org.mage.card.arcane.ManaSymbols.getSymbolFileNameAsSVG;
@ -106,20 +107,21 @@ public class ScryfallSymbolsSource implements Iterable<DownloadJob> {
if (destFile.exists() && (destFile.length() > 0)){ if (destFile.exists() && (destFile.length() > 0)){
continue; continue;
} }
FileOutputStream stream = null;
try { try {
// base64 transform // base64 transform
String data64 = foundedData.get(searchCode); String data64 = foundedData.get(searchCode);
Base64.Decoder dec = Base64.getDecoder(); Base64.Decoder dec = Base64.getDecoder();
byte[] fileData = dec.decode(data64); byte[] fileData = dec.decode(data64);
FileOutputStream stream = new FileOutputStream(destFile); stream = new FileOutputStream(destFile);
stream.write(fileData); stream.write(fileData);
stream.close();
LOGGER.info("New svg symbol downloaded: " + needCode); LOGGER.info("New svg symbol downloaded: " + needCode);
} catch (Exception e) { } catch (Exception e) {
LOGGER.error("Can't decode svg icon and save to file: " + destFile.getPath() + ", reason: " + e.getMessage()); LOGGER.error("Can't decode svg icon and save to file: " + destFile.getPath() + ", reason: " + e.getMessage());
} finally {
StreamUtils.closeQuietly(stream);
} }
} }
} }

View file

@ -24,6 +24,7 @@ import mage.client.MageFrame;
import mage.client.dialog.PreferencesDialog; import mage.client.dialog.PreferencesDialog;
import mage.client.util.sets.ConstructedFormats; import mage.client.util.sets.ConstructedFormats;
import mage.remote.Connection; import mage.remote.Connection;
import mage.util.StreamUtils;
import net.java.truevfs.access.TFile; import net.java.truevfs.access.TFile;
import net.java.truevfs.access.TFileOutputStream; import net.java.truevfs.access.TFileOutputStream;
import net.java.truevfs.access.TVFS; import net.java.truevfs.access.TVFS;
@ -745,34 +746,6 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
} }
} }
/*
if(!destFile.getParentFile().exists()){
destFile.getParentFile().mkdirs();
}
*/
/*
// WTF start?! TODO: wtf
File existingFile = new File(imagePath.replaceFirst("\\w{3}.zip", ""));
if (existingFile.exists()) {
try {
new TFile(existingFile).cp_rp(outputFile);
} catch (IOException e) {
logger.error("Error while copying file " + card.getName(), e);
}
synchronized (sync) {
update(cardIndex + 1, count);
}
existingFile.delete();
File parent = existingFile.getParentFile();
if (parent != null && parent.isDirectory() && parent.list().length == 0) {
parent.delete();
}
return;
}
// WTF end?!
*/
// START to download
cardImageSource.doPause(url.getPath()); cardImageSource.doPause(url.getPath());
URLConnection httpConn = url.openConnection(p); URLConnection httpConn = url.openConnection(p);
httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2"); httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2");
@ -782,18 +755,18 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
if (responseCode == 200) { if (responseCode == 200) {
// download OK // download OK
// save data to temp // save data to temp
BufferedOutputStream out; OutputStream out = null;
try (BufferedInputStream in = new BufferedInputStream(httpConn.getInputStream())) { OutputStream tfileout = null;
out = new BufferedOutputStream(new TFileOutputStream(fileTempImage)); InputStream in = null;
try {
in = new BufferedInputStream(httpConn.getInputStream());
tfileout = new TFileOutputStream(fileTempImage);
out = new BufferedOutputStream(tfileout);
byte[] buf = new byte[1024]; byte[] buf = new byte[1024];
int len; int len;
while ((len = in.read(buf)) != -1) { while ((len = in.read(buf)) != -1) {
// user cancelled // user cancelled
if (cancel) { if (cancel) {
in.close();
out.flush();
out.close();
// stop download, save current state and exit // stop download, save current state and exit
TFile archive = destFile.getTopLevelArchive(); TFile archive = destFile.getTopLevelArchive();
///* not need to unmout/close - it's auto action ///* not need to unmout/close - it's auto action
@ -804,8 +777,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
} catch (Exception e) { } catch (Exception e) {
logger.error("Can't close archive file: " + e.getMessage(), e); logger.error("Can't close archive file: " + e.getMessage(), e);
} }
}
}//*/
try { try {
TFile.rm(fileTempImage); TFile.rm(fileTempImage);
} catch (Exception e) { } catch (Exception e) {
@ -816,9 +788,12 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
out.write(buf, 0, len); out.write(buf, 0, len);
} }
} }
// TODO: remove to finnaly section? finally {
out.flush(); StreamUtils.closeQuietly(in);
out.close(); StreamUtils.closeQuietly(out);
StreamUtils.closeQuietly(tfileout);
}
// TODO: add two faces card correction? (WTF) // TODO: add two faces card correction? (WTF)
// SAVE final data // SAVE final data
@ -847,81 +822,6 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
} }
} }
/*
// Logger.getLogger(this.getClass()).info(url.toString());
boolean useTempFile = false;
int responseCode = 0;
URLConnection httpConn = null;
if (temporaryFile != null && temporaryFile.length() > 100) {
useTempFile = true;
} else {
cardImageSource.doPause(url.getPath());
httpConn = url.openConnection(p);
httpConn.connect();
responseCode = ((HttpURLConnection) httpConn).getResponseCode();
}
if (responseCode == 200 || useTempFile) {
if (!useTempFile) {
BufferedOutputStream out;
try (BufferedInputStream in = new BufferedInputStream(httpConn.getInputStream())) {
//try (BufferedInputStream in = new BufferedInputStream(url.openConnection(p).getInputStream())) {
out = new BufferedOutputStream(new TFileOutputStream(temporaryFile));
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) != -1) {
// user cancelled
if (cancel) {
in.close();
out.flush();
out.close();
temporaryFile.delete();
return;
}
out.write(buf, 0, len);
}
}
out.flush();
out.close();
}
// TODO: WTF?! start
if (card != null && card.isTwoFacedCard()) {
BufferedImage image = ImageIO.read(temporaryFile);
if (image.getHeight() == 470) {
BufferedImage renderedImage = new BufferedImage(265, 370, BufferedImage.TYPE_INT_RGB);
renderedImage.getGraphics();
Graphics2D graphics2D = renderedImage.createGraphics();
if (card.isTwoFacedCard() && card.isSecondSide()) {
graphics2D.drawImage(image, 0, 0, 265, 370, 313, 62, 578, 432, null);
} else {
graphics2D.drawImage(image, 0, 0, 265, 370, 41, 62, 306, 432, null);
}
graphics2D.dispose();
writeImageToFile(renderedImage, outputFile);
} else {
outputFile.getParentFile().mkdirs();
new TFile(temporaryFile).cp_rp(outputFile);
}
//temporaryFile.delete();
} else {
outputFile.getParentFile().mkdirs();
new TFile(temporaryFile).cp_rp(outputFile);
}
// WTF?! end
} else {
if (card != null && !useSpecifiedPaths) {
logger.warn("Image download for " + card.getName()
+ (!card.getDownloadName().equals(card.getName()) ? " downloadname: " + card.getDownloadName() : "")
+ '(' + card.getSet() + ") failed - responseCode: " + responseCode + " url: " + url.toString());
}
if (logger.isDebugEnabled()) { // Shows the returned html from the request to the web server
logger.debug("Returned HTML ERROR:\n" + convertStreamToString(((HttpURLConnection) httpConn).getErrorStream()));
}
}
*/
} catch (AccessDeniedException e) { } catch (AccessDeniedException e) {
logger.error("Can't access to files: " + card.getName() + "(" + card.getSet() + "). Try rebooting your system to remove the file lock."); logger.error("Can't access to files: " + card.getName() + "(" + card.getSet() + "). Try rebooting your system to remove the file lock.");
} catch (Exception e) { } catch (Exception e) {
@ -933,26 +833,6 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
update(cardIndex + 1, count); update(cardIndex + 1, count);
} }
} }
// private void writeImageToFile(BufferedImage image, TFile file) throws IOException {
// Iterator iter = ImageIO.getImageWritersByFormatName("jpg");
//
// ImageWriter writer = (ImageWriter) iter.next();
// ImageWriteParam iwp = writer.getDefaultWriteParam();
// iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
// iwp.setCompressionQuality(0.96f);
//
// File tempFile = new File(getImagesDir() + File.separator + image.hashCode() + file.getName());
// FileImageOutputStream output = new FileImageOutputStream(tempFile);
// writer.setOutput(output);
// IIOImage image2 = new IIOImage(image, null, null);
// writer.write(null, image2, iwp);
// writer.dispose();
// output.close();
//
// new TFile(tempFile).cp_rp(file);
// tempFile.delete();
// }
} }
private void update(int card, int count) { private void update(int card, int count) {

View file

@ -12,13 +12,9 @@ public class SettingsManager {
private static SettingsManager settingsManager = null; private static SettingsManager settingsManager = null;
public static SettingsManager getIntance() { public static synchronized SettingsManager getIntance() {
if (settingsManager == null) { if (settingsManager == null) {
synchronized (SettingsManager.class) { settingsManager = new SettingsManager();
if (settingsManager == null) {
settingsManager = new SettingsManager();
}
}
} }
return settingsManager; return settingsManager;
} }

View file

@ -150,47 +150,43 @@ public class ThemePluginImpl implements ThemePlugin {
return bgPanel; return bgPanel;
} }
private ImagePanel createImagePanelInstance() { private synchronized ImagePanel createImagePanelInstance() {
if (background == null) { if (background == null) {
synchronized (ThemePluginImpl.class) { String filename = "/background.png";
if (background == null) { try {
String filename = "/background.png"; if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_BACKGROUND_IMAGE_DEFAULT, "true").equals("true")) {
try { InputStream is = this.getClass().getResourceAsStream(filename);
if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_BACKGROUND_IMAGE_DEFAULT, "true").equals("true")) { if (is == null) {
InputStream is = this.getClass().getResourceAsStream(filename);
if (is == null) {
throw new FileNotFoundException("Couldn't find " + filename + " in resources.");
}
background = ImageIO.read(is);
} else {
String path = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_BACKGROUND_IMAGE, "");
if (path != null && !path.isEmpty()) {
try {
File f = new File(path);
if (f != null) {
background = ImageIO.read(f);
}
} catch (Exception e) {
background = null;
}
}
}
if (background == null) {
InputStream is = this.getClass().getResourceAsStream(filename);
if (is == null) {
throw new FileNotFoundException("Couldn't find " + filename + " in resources.");
}
background = ImageIO.read(is);
}
if (background == null) {
throw new FileNotFoundException("Couldn't find " + filename + " in resources."); throw new FileNotFoundException("Couldn't find " + filename + " in resources.");
} }
} catch (Exception e) { background = ImageIO.read(is);
log.error(e.getMessage(), e); } else {
return null; String path = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_BACKGROUND_IMAGE, "");
if (path != null && !path.isEmpty()) {
try {
File f = new File(path);
if (f != null) {
background = ImageIO.read(f);
}
} catch (Exception e) {
background = null;
}
}
} }
if (background == null) {
InputStream is = this.getClass().getResourceAsStream(filename);
if (is == null) {
throw new FileNotFoundException("Couldn't find " + filename + " in resources.");
}
background = ImageIO.read(is);
}
if (background == null) {
throw new FileNotFoundException("Couldn't find " + filename + " in resources.");
}
} catch (Exception e) {
log.error(e.getMessage(), e);
return null;
} }
}
} }
return new ImagePanel(background, ImagePanelStyle.SCALED); return new ImagePanel(background, ImagePanelStyle.SCALED);
} }

View file

@ -0,0 +1,30 @@
package mage.utils;
import java.io.Closeable;
public final class StreamUtils {
/***
* Quietly closes the closable, ignoring nulls and exceptions
* @param c - the closable to be closed
*/
public static void closeQuietly(Closeable c) {
if (c != null) {
try {
c.close();
}
catch (Exception e) {
}
}
}
public static void closeQuietly(AutoCloseable ac) {
if (ac != null) {
try {
ac.close();
}
catch (Exception e) {
}
}
}
}

View file

@ -957,10 +957,11 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
} }
protected final void getSuggestedActions() { protected final void getSuggestedActions() {
Scanner scanner = null;
try { try {
File file = new File(FILE_WITH_INSTRUCTIONS); File file = new File(FILE_WITH_INSTRUCTIONS);
if (file.exists()) { if (file.exists()) {
Scanner scanner = new Scanner(file); scanner = new Scanner(file);
while (scanner.hasNextLine()) { while (scanner.hasNextLine()) {
String line = scanner.nextLine(); String line = scanner.nextLine();
if (line.startsWith("cast:") if (line.startsWith("cast:")
@ -976,6 +977,10 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
} catch (Exception e) { } catch (Exception e) {
// swallow // swallow
e.printStackTrace(); e.printStackTrace();
} finally {
if(scanner != null) {
scanner.close();
}
} }
} }

View file

@ -90,8 +90,8 @@ public class ChatSession {
String userName = clients.get(userId); String userName = clients.get(userId);
if (reason != DisconnectReason.LostConnection) { // for lost connection the user will be reconnected or session expire so no removeUserFromAllTablesAndChat of chat yet if (reason != DisconnectReason.LostConnection) { // for lost connection the user will be reconnected or session expire so no removeUserFromAllTablesAndChat of chat yet
final Lock w = lock.writeLock(); final Lock w = lock.writeLock();
w.lock();
try { try {
w.lock();
clients.remove(userId); clients.remove(userId);
} finally { } finally {
w.unlock(); w.unlock();

View file

@ -29,6 +29,7 @@
package mage.server; package mage.server;
import mage.server.util.PluginClassLoader; import mage.server.util.PluginClassLoader;
import mage.util.StreamUtils;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -54,10 +55,12 @@ public final class ExtensionPackageLoader {
String entryPoint = entryPointReader.nextLine().trim(); String entryPoint = entryPointReader.nextLine().trim();
entryPointReader.close(); entryPointReader.close();
PluginClassLoader classLoader = new PluginClassLoader(); PluginClassLoader classLoader = null;
for(File f : packagesDirectory.listFiles()) classLoader.addURL(f.toURI().toURL());
try { try {
classLoader = new PluginClassLoader();
for(File f : packagesDirectory.listFiles()) {
classLoader.addURL(f.toURI().toURL());
}
return (ExtensionPackage) Class.forName(entryPoint, false, classLoader).newInstance(); return (ExtensionPackage) Class.forName(entryPoint, false, classLoader).newInstance();
} catch (InstantiationException | IllegalAccessException e) { } catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -65,6 +68,8 @@ public final class ExtensionPackageLoader {
throw new RuntimeException("Entry point class not found!", e); throw new RuntimeException("Entry point class not found!", e);
} catch (ClassCastException e) { } catch (ClassCastException e) {
throw new RuntimeException("Entry point not an instance of ExtensionPackage.", e); throw new RuntimeException("Entry point not an instance of ExtensionPackage.", e);
} finally {
StreamUtils.closeQuietly(classLoader);
} }
} }
} }

View file

@ -231,8 +231,8 @@ public enum UserManager {
} }
logger.debug("Users to remove " + toRemove.size()); logger.debug("Users to remove " + toRemove.size());
final Lock w = lock.readLock(); final Lock w = lock.readLock();
w.lock();
try { try {
w.lock();
for (User user : toRemove) { for (User user : toRemove) {
users.remove(user.getId()); users.remove(user.getId());
} }

View file

@ -64,6 +64,7 @@ import mage.server.util.ConfigSettings;
import mage.server.util.Splitter; import mage.server.util.Splitter;
import mage.server.util.SystemUtil; import mage.server.util.SystemUtil;
import mage.server.util.ThreadExecutor; import mage.server.util.ThreadExecutor;
import mage.utils.StreamUtils;
import mage.utils.timer.PriorityTimer; import mage.utils.timer.PriorityTimer;
import mage.view.*; import mage.view.*;
import mage.view.ChatMessage.MessageColor; import mage.view.ChatMessage.MessageColor;
@ -902,17 +903,23 @@ public class GameController implements GameCallback {
} }
public boolean saveGame() { public boolean saveGame() {
OutputStream file = null;
ObjectOutput output = null;
OutputStream buffer = null;
try { try {
OutputStream file = new FileOutputStream("saved/" + game.getId().toString() + ".game"); file = new FileOutputStream("saved/" + game.getId().toString() + ".game");
OutputStream buffer = new BufferedOutputStream(file); buffer = new BufferedOutputStream(file);
try (ObjectOutput output = new ObjectOutputStream(new GZIPOutputStream(buffer))) { output = new ObjectOutputStream(new GZIPOutputStream(buffer));
output.writeObject(game); output.writeObject(game);
output.writeObject(game.getGameStates()); output.writeObject(game.getGameStates());
}
logger.debug("Saved game:" + game.getId()); logger.debug("Saved game:" + game.getId());
return true; return true;
} catch (IOException ex) { } catch (IOException ex) {
logger.fatal("Cannot save game.", ex); logger.fatal("Cannot save game.", ex);
} finally {
StreamUtils.closeQuietly(file);
StreamUtils.closeQuietly(output);
StreamUtils.closeQuietly(buffer);
} }
return false; return false;
} }

View file

@ -40,6 +40,7 @@ import mage.game.GameState;
import mage.game.GameStates; import mage.game.GameStates;
import mage.server.Main; import mage.server.Main;
import mage.util.CopierObjectInputStream; import mage.util.CopierObjectInputStream;
import mage.utils.StreamUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -84,21 +85,31 @@ public class GameReplay {
} }
private Game loadGame(UUID gameId) { private Game loadGame(UUID gameId) {
InputStream file = null;
InputStream buffer = null;
InputStream gzip = null;
ObjectInput input = null;
try{ try{
InputStream file = new FileInputStream("saved/" + gameId.toString() + ".game"); file = new FileInputStream("saved/" + gameId.toString() + ".game");
InputStream buffer = new BufferedInputStream(file); buffer = new BufferedInputStream(file);
try (ObjectInput input = new CopierObjectInputStream(Main.classLoader, new GZIPInputStream(buffer))) { gzip = new GZIPInputStream(buffer);
Game loadGame = (Game) input.readObject(); input = new CopierObjectInputStream(Main.classLoader, gzip);
GameStates states = (GameStates) input.readObject(); Game loadGame = (Game) input.readObject();
loadGame.loadGameStates(states); GameStates states = (GameStates) input.readObject();
return loadGame; loadGame.loadGameStates(states);
} return loadGame;
} }
catch(ClassNotFoundException ex) { catch(ClassNotFoundException ex) {
logger.fatal("Cannot load game. Class not found.", ex); logger.fatal("Cannot load game. Class not found.", ex);
} }
catch(IOException ex) { catch(IOException ex) {
logger.fatal("Cannot load game:" + gameId, ex); logger.fatal("Cannot load game:" + gameId, ex);
} finally {
StreamUtils.closeQuietly(file);
StreamUtils.closeQuietly(buffer);
StreamUtils.closeQuietly(input);
StreamUtils.closeQuietly(gzip);
} }
return null; return null;
} }

View file

@ -27,6 +27,7 @@
*/ */
package mage.server.util; package mage.server.util;
import mage.utils.StreamUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.io.File; import java.io.File;
@ -49,7 +50,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
* @author nantuko * @author nantuko
*/ */
public enum ServerMessagesUtil { public enum ServerMessagesUtil {
instance; instance;
private static final Logger log = Logger.getLogger(ServerMessagesUtil.class); private static final Logger log = Logger.getLogger(ServerMessagesUtil.class);
private static final String SERVER_MSG_TXT_FILE = "server.msg.txt"; private static final String SERVER_MSG_TXT_FILE = "server.msg.txt";
private ScheduledExecutorService updateExecutor; private ScheduledExecutorService updateExecutor;
@ -147,13 +148,22 @@ instance;
log.warn("Couldn't find server.msg"); log.warn("Couldn't find server.msg");
return null; return null;
} }
Scanner scanner = new Scanner(is);
Scanner scanner = null;
List<String> newMessages = new ArrayList<>(); List<String> newMessages = new ArrayList<>();
while (scanner.hasNextLine()) { try {
String message = scanner.nextLine(); scanner = new Scanner(is);
if (!message.trim().isEmpty()) { while (scanner.hasNextLine()) {
newMessages.add(message.trim()); String message = scanner.nextLine();
if (!message.trim().isEmpty()) {
newMessages.add(message.trim());
}
} }
} catch(Exception e) {
log.error(e,e);
} finally {
StreamUtils.closeQuietly(scanner);
StreamUtils.closeQuietly(is);
} }
return newMessages; return newMessages;
} }

View file

@ -91,7 +91,6 @@ class EmpyrialArchangelEffect extends ReplacementEffectImpl {
Permanent p = game.getPermanent(source.getSourceId()); Permanent p = game.getPermanent(source.getSourceId());
if (p != null) { if (p != null) {
p.damage(damageEvent.getAmount(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable()); p.damage(damageEvent.getAmount(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable());
return true;
} }
return true; return true;
} }

View file

@ -105,7 +105,7 @@ class FalkenrathAristocratEffect extends OneShotEffect {
Permanent sourceCreature = game.getPermanent(source.getSourceId()); Permanent sourceCreature = game.getPermanent(source.getSourceId());
if (sacrificedCreature.hasSubtype(SubType.HUMAN, game) && sourceCreature != null) { if (sacrificedCreature.hasSubtype(SubType.HUMAN, game) && sourceCreature != null) {
sourceCreature.addCounters(CounterType.P1P1.createInstance(), source, game); sourceCreature.addCounters(CounterType.P1P1.createInstance(), source, game);
return true; break;
} }
} }
} }

View file

@ -95,12 +95,11 @@ class GilderBairnEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Permanent target = game.getPermanent(source.getFirstTarget()); Permanent target = game.getPermanent(source.getFirstTarget());
if (target == null) { if (target != null) {
return false; for (Counter counter : target.getCounters(game).values()) {
} Counter newCounter = new Counter(counter.getName(), counter.getCount());
for (Counter counter : target.getCounters(game).values()) { target.addCounters(newCounter, source, game);
Counter newCounter = new Counter(counter.getName(), counter.getCount()); }
target.addCounters(newCounter, source, game);
} }
return false; return false;
} }

View file

@ -102,7 +102,7 @@ class IceCaveEffect extends OneShotEffect {
if (cost.pay(source, game, source.getSourceId(), playerId, false, null)) { if (cost.pay(source, game, source.getSourceId(), playerId, false, null)) {
game.informPlayers(player.getLogName() + " pays" + cost.getText() + " to counter " + spell.getIdName() + '.'); game.informPlayers(player.getLogName() + " pays" + cost.getText() + " to counter " + spell.getIdName() + '.');
game.getStack().counter(spell.getId(), source.getSourceId(), game); game.getStack().counter(spell.getId(), source.getSourceId(), game);
return true; break;
} }
} }
} }

View file

@ -99,7 +99,6 @@ class KjeldoranRoyalGuardEffect extends ReplacementEffectImpl {
Permanent p = game.getPermanent(source.getSourceId()); Permanent p = game.getPermanent(source.getSourceId());
if (p != null) { if (p != null) {
p.damage(damageEvent.getAmount(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable()); p.damage(damageEvent.getAmount(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable());
return true;
} }
return true; return true;
} }

View file

@ -129,7 +129,6 @@ class LegionsInitiativeExileEffect extends OneShotEffect {
//create delayed triggered ability //create delayed triggered ability
AtTheBeginOfCombatDelayedTriggeredAbility delayedAbility = new AtTheBeginOfCombatDelayedTriggeredAbility(new LegionsInitiativeReturnFromExileEffect()); AtTheBeginOfCombatDelayedTriggeredAbility delayedAbility = new AtTheBeginOfCombatDelayedTriggeredAbility(new LegionsInitiativeReturnFromExileEffect());
game.addDelayedTriggeredAbility(delayedAbility, source); game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
} }
return true; return true;
} }

View file

@ -84,19 +84,16 @@ class NaturesWillEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Set<UUID> damagedPlayers = (HashSet<UUID>) this.getValue("damagedPlayers"); Set<UUID> damagedPlayers = (HashSet<UUID>) this.getValue("damagedPlayers");
if (damagedPlayers == null) { if (damagedPlayers != null) {
return false; List<Permanent> lands = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LAND, source.getControllerId(), source.getSourceId(), game);
} for (Permanent land : lands) {
if (damagedPlayers.contains(land.getControllerId())) {
List<Permanent> lands = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LAND, source.getControllerId(), source.getSourceId(), game); land.tap(game);
for (Permanent land : lands) { } else if (land.getControllerId().equals(source.getControllerId())) {
if (damagedPlayers.contains(land.getControllerId())) { land.untap(game);
land.tap(game); }
} else if (land.getControllerId().equals(source.getControllerId())) {
land.untap(game);
} }
} }
return false; return false;
} }
} }

View file

@ -4,7 +4,7 @@ import java.io.*;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.io.Closeable;
/** /**
* Helper for file operations. * Helper for file operations.
* *
@ -84,15 +84,17 @@ public final class FileHelper {
*/ */
public static void downloadFile(String filename, HttpURLConnection urlConnection) { public static void downloadFile(String filename, HttpURLConnection urlConnection) {
System.out.println("Downloading " + filename); System.out.println("Downloading " + filename);
InputStream in = null;
FileOutputStream out = null;
try { try {
InputStream in = urlConnection.getInputStream(); in = urlConnection.getInputStream();
File f = new File(filename); File f = new File(filename);
if (!f.exists() && f.getParentFile() != null) { if (!f.exists() && f.getParentFile() != null) {
f.getParentFile().mkdirs(); f.getParentFile().mkdirs();
System.out.println("Directories have been created: " + f.getParentFile().getPath()); System.out.println("Directories have been created: " + f.getParentFile().getPath());
} }
FileOutputStream out = new FileOutputStream(filename); out = new FileOutputStream(filename);
byte[] buf = new byte[4 * 1024]; byte[] buf = new byte[4 * 1024];
int bytesRead; int bytesRead;
@ -103,6 +105,19 @@ public final class FileHelper {
System.out.println("File has been updated: " + filename); System.out.println("File has been updated: " + filename);
} catch (IOException e) { } catch (IOException e) {
System.out.println("i/o exception - " + e.getMessage()); System.out.println("i/o exception - " + e.getMessage());
} finally {
closeQuietly(in);
closeQuietly(out);
}
}
public static void closeQuietly(Closeable s) {
if(s != null) {
try {
s.close();
} catch (Exception e) {
System.out.println("i/o exception - " + e.getMessage());
}
} }
} }
} }

View file

@ -2,6 +2,7 @@ package mage.verify;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import mage.util.StreamUtils;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -94,9 +95,16 @@ public final class MtgJson {
} }
stream = new FileInputStream(file); stream = new FileInputStream(file);
} }
ZipInputStream zipInputStream = new ZipInputStream(stream); ZipInputStream zipInputStream = null;
zipInputStream.getNextEntry(); try {
return new ObjectMapper().readValue(zipInputStream, ref); zipInputStream = new ZipInputStream(stream);
zipInputStream.getNextEntry();
return new ObjectMapper().readValue(zipInputStream, ref);
} finally {
StreamUtils.closeQuietly(zipInputStream);
StreamUtils.closeQuietly(stream);
}
} }
public static Map<String, JsonSet> sets() { public static Map<String, JsonSet> sets() {

View file

@ -50,36 +50,44 @@ public class Copier<T> {
public T copy(T obj) { public T copy(T obj) {
T copy = null; T copy = null;
FastByteArrayOutputStream fbos = null;
ObjectOutputStream out = null;
ObjectInputStream in = null;
try { try {
FastByteArrayOutputStream fbos = new FastByteArrayOutputStream(); fbos = new FastByteArrayOutputStream();
ObjectOutputStream out= new ObjectOutputStream(fbos); out = new ObjectOutputStream(fbos);
// Write the object out to a byte array // Write the object out to a byte array
out.writeObject(obj); out.writeObject(obj);
out.flush(); out.flush();
out.close();
// Retrieve an input stream from the byte array and read // Retrieve an input stream from the byte array and read
// a copy of the object back in. // a copy of the object back in.
ObjectInputStream in = new CopierObjectInputStream(loader, fbos.getInputStream()); in = new CopierObjectInputStream(loader, fbos.getInputStream());
copy = (T) in.readObject(); copy = (T) in.readObject();
} }
catch(IOException | ClassNotFoundException e) { catch(IOException | ClassNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
StreamUtils.closeQuietly(fbos);
StreamUtils.closeQuietly(out);
StreamUtils.closeQuietly(in);
} }
return copy; return copy;
} }
public byte[] copyCompressed(T obj) { public byte[] copyCompressed(T obj) {
FastByteArrayOutputStream fbos = null;
ObjectOutputStream out = null;
try { try {
FastByteArrayOutputStream fbos = new FastByteArrayOutputStream(); fbos = new FastByteArrayOutputStream();
ObjectOutputStream out= new ObjectOutputStream(new GZIPOutputStream(fbos)); out = new ObjectOutputStream(new GZIPOutputStream(fbos));
// Write the object out to a byte array // Write the object out to a byte array
out.writeObject(obj); out.writeObject(obj);
out.flush(); out.flush();
out.close();
byte[] copy = new byte[fbos.getSize()]; byte[] copy = new byte[fbos.getSize()];
System.arraycopy(fbos.getByteArray(), 0, copy, 0, fbos.getSize()); System.arraycopy(fbos.getByteArray(), 0, copy, 0, fbos.getSize());
@ -87,6 +95,9 @@ public class Copier<T> {
} }
catch(IOException e) { catch(IOException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
StreamUtils.closeQuietly(fbos);
StreamUtils.closeQuietly(out);
} }
return null; return null;
} }

View file

@ -0,0 +1,30 @@
package mage.util;
import java.io.Closeable;
public final class StreamUtils {
/***
* Quietly closes the closable, ignoring nulls and exceptions
* @param c - the closable to be closed
*/
public static void closeQuietly(Closeable c) {
if (c != null) {
try {
c.close();
}
catch (Exception e) {
}
}
}
public static void closeQuietly(AutoCloseable ac) {
if (ac != null) {
try {
ac.close();
}
catch (Exception e) {
}
}
}
}