mirror of
https://github.com/correl/mage.git
synced 2024-12-24 11:50:45 +00:00
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:
parent
ec77cecbf6
commit
5ac975c52e
31 changed files with 288 additions and 276 deletions
|
@ -68,6 +68,10 @@ public class ManaPieChart extends JComponent {
|
|||
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;
|
||||
int startAngle = 0;
|
||||
int lastAngle = 0;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package mage.client.deckeditor;
|
||||
|
||||
import mage.util.StreamUtils;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.BufferedWriter;
|
||||
|
@ -39,15 +41,16 @@ public class DeckImportFromClipboardDialog extends JDialog {
|
|||
}
|
||||
|
||||
private void onOK() {
|
||||
BufferedWriter bw = null;
|
||||
try {
|
||||
File temp = File.createTempFile("cbimportdeck", ".txt");
|
||||
BufferedWriter bw = new BufferedWriter(new FileWriter(temp));
|
||||
bw = new BufferedWriter(new FileWriter(temp));
|
||||
bw.write(txtDeckList.getText());
|
||||
bw.close();
|
||||
|
||||
tmpPath = temp.getPath();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(bw);
|
||||
}
|
||||
|
||||
dispose();
|
||||
|
|
|
@ -43,6 +43,7 @@ import java.io.FileReader;
|
|||
import java.io.FileWriter;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Writer;
|
||||
import java.io.Closeable;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.SocketException;
|
||||
|
@ -73,6 +74,7 @@ import mage.client.util.Config;
|
|||
import mage.client.util.gui.countryBox.CountryItemEditor;
|
||||
import mage.client.util.sets.ConstructedFormats;
|
||||
import mage.remote.Connection;
|
||||
import mage.utils.StreamUtils;
|
||||
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
|
||||
BufferedReader in = null;
|
||||
Writer output = null;
|
||||
try {
|
||||
String serverUrl = PreferencesDialog.getCachedValue(KEY_CONNECTION_URL_SERVER_LIST, "http://xmage.de/files/server-list.txt");
|
||||
if (serverUrl.contains("xmage.info/files/")) {
|
||||
|
@ -618,7 +621,7 @@ public class ConnectDialog extends MageDialog {
|
|||
}
|
||||
List<String> servers = new ArrayList<>();
|
||||
if (in != null) {
|
||||
Writer output = null;
|
||||
|
||||
if (!URLNotFound) {
|
||||
// write serverlist to be able to read if URL is not available
|
||||
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()) {
|
||||
JOptionPane.showMessageDialog(null, "Couldn't find any server.");
|
||||
|
@ -668,15 +667,12 @@ public class ConnectDialog extends MageDialog {
|
|||
} catch (Exception ex) {
|
||||
logger.error(ex, ex);
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
StreamUtils.closeQuietly(in);
|
||||
StreamUtils.closeQuietly(output);
|
||||
}
|
||||
}//GEN-LAST:event_jButton1ActionPerformed
|
||||
|
||||
|
||||
private void jProxySettingsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jProxySettingsButtonActionPerformed
|
||||
PreferencesDialog.main(new String[]{PreferencesDialog.OPEN_CONNECTION_TAB});
|
||||
}//GEN-LAST:event_jProxySettingsButtonActionPerformed
|
||||
|
|
|
@ -45,17 +45,13 @@ public class ArrowBuilder {
|
|||
* Get the panel where all arrows are being drawn.
|
||||
* @return
|
||||
*/
|
||||
public JPanel getArrowsManagerPanel() {
|
||||
if (arrowsManagerPanel == null) {
|
||||
synchronized (ArrowBuilder.class) {
|
||||
public synchronized JPanel getArrowsManagerPanel() {
|
||||
if (arrowsManagerPanel == null) {
|
||||
arrowsManagerPanel = new JPanel();
|
||||
arrowsManagerPanel.setVisible(true);
|
||||
arrowsManagerPanel.setOpaque(false);
|
||||
arrowsManagerPanel.setLayout(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
return arrowsManagerPanel;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package mage.client.util.object;
|
||||
|
||||
import mage.utils.StreamUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -61,10 +63,9 @@ public final class SaveObjectUtil {
|
|||
oos.writeObject(object);
|
||||
oos.close();
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
return;
|
||||
} catch (IOException io) {
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(oos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import mage.client.constants.Constants.ResourceSymbolSize;
|
|||
import mage.client.util.GUISizeHelper;
|
||||
import mage.client.util.ImageHelper;
|
||||
import mage.client.util.gui.BufferedImageBuilder;
|
||||
import mage.utils.StreamUtils;
|
||||
import org.apache.batik.dom.svg.SVGDOMImplementation;
|
||||
import org.apache.batik.transcoder.TranscoderException;
|
||||
import org.apache.batik.transcoder.TranscoderInput;
|
||||
|
@ -249,10 +250,15 @@ public final class ManaSymbols {
|
|||
+ "color-rendering: optimizeQuality;"
|
||||
+ "image-rendering: optimizeQuality;"
|
||||
+ "}";
|
||||
|
||||
File cssFile = File.createTempFile("batik-default-override-", ".css");
|
||||
FileWriter w = new FileWriter(cssFile);
|
||||
FileWriter w = null;
|
||||
try {
|
||||
w = new FileWriter(cssFile);
|
||||
w.write(css);
|
||||
w.close();
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(w);
|
||||
}
|
||||
|
||||
TranscodingHints transcoderHints = new TranscodingHints();
|
||||
|
||||
|
@ -284,7 +290,6 @@ public final class ManaSymbols {
|
|||
|
||||
try {
|
||||
TranscoderInput input = new TranscoderInput(new FileInputStream(svgFile));
|
||||
|
||||
ImageTranscoder t = new ImageTranscoder() {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.mage.card.arcane;
|
||||
|
||||
import mage.utils.StreamUtils;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
|
@ -72,8 +74,8 @@ public final class UI {
|
|||
}
|
||||
|
||||
public static ImageIcon getImageIcon (String path) {
|
||||
InputStream stream = null;
|
||||
try {
|
||||
InputStream stream;
|
||||
stream = UI.class.getResourceAsStream(path);
|
||||
if (stream == null && new File(path).exists()) {
|
||||
stream = new FileInputStream(path);
|
||||
|
@ -86,6 +88,8 @@ public final class UI {
|
|||
return new ImageIcon(data);
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Error reading image: " + path);
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,10 +37,14 @@ public final class Util {
|
|||
}
|
||||
|
||||
public static void broadcast(byte[] data, int port) throws IOException {
|
||||
DatagramSocket socket = new DatagramSocket();
|
||||
DatagramSocket socket = null;
|
||||
try {
|
||||
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)
|
||||
throws IOException {
|
||||
|
|
|
@ -9,6 +9,7 @@ import java.util.*;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import mage.util.StreamUtils;
|
||||
import org.mage.plugins.card.dl.DownloadJob;
|
||||
|
||||
import static org.mage.card.arcane.ManaSymbols.getSymbolFileNameAsSVG;
|
||||
|
@ -106,20 +107,21 @@ public class ScryfallSymbolsSource implements Iterable<DownloadJob> {
|
|||
if (destFile.exists() && (destFile.length() > 0)){
|
||||
continue;
|
||||
}
|
||||
|
||||
FileOutputStream stream = null;
|
||||
try {
|
||||
// base64 transform
|
||||
String data64 = foundedData.get(searchCode);
|
||||
Base64.Decoder dec = Base64.getDecoder();
|
||||
byte[] fileData = dec.decode(data64);
|
||||
|
||||
FileOutputStream stream = new FileOutputStream(destFile);
|
||||
stream = new FileOutputStream(destFile);
|
||||
stream.write(fileData);
|
||||
stream.close();
|
||||
|
||||
LOGGER.info("New svg symbol downloaded: " + needCode);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Can't decode svg icon and save to file: " + destFile.getPath() + ", reason: " + e.getMessage());
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import mage.client.MageFrame;
|
|||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.util.sets.ConstructedFormats;
|
||||
import mage.remote.Connection;
|
||||
import mage.util.StreamUtils;
|
||||
import net.java.truevfs.access.TFile;
|
||||
import net.java.truevfs.access.TFileOutputStream;
|
||||
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());
|
||||
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");
|
||||
|
@ -782,18 +755,18 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
if (responseCode == 200) {
|
||||
// download OK
|
||||
// save data to temp
|
||||
BufferedOutputStream out;
|
||||
try (BufferedInputStream in = new BufferedInputStream(httpConn.getInputStream())) {
|
||||
out = new BufferedOutputStream(new TFileOutputStream(fileTempImage));
|
||||
OutputStream out = null;
|
||||
OutputStream tfileout = null;
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = new BufferedInputStream(httpConn.getInputStream());
|
||||
tfileout = new TFileOutputStream(fileTempImage);
|
||||
out = new BufferedOutputStream(tfileout);
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buf)) != -1) {
|
||||
// user cancelled
|
||||
if (cancel) {
|
||||
in.close();
|
||||
out.flush();
|
||||
out.close();
|
||||
|
||||
// stop download, save current state and exit
|
||||
TFile archive = destFile.getTopLevelArchive();
|
||||
///* not need to unmout/close - it's auto action
|
||||
|
@ -804,8 +777,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
} catch (Exception e) {
|
||||
logger.error("Can't close archive file: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
}//*/
|
||||
}
|
||||
try {
|
||||
TFile.rm(fileTempImage);
|
||||
} catch (Exception e) {
|
||||
|
@ -816,9 +788,12 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
out.write(buf, 0, len);
|
||||
}
|
||||
}
|
||||
// TODO: remove to finnaly section?
|
||||
out.flush();
|
||||
out.close();
|
||||
finally {
|
||||
StreamUtils.closeQuietly(in);
|
||||
StreamUtils.closeQuietly(out);
|
||||
StreamUtils.closeQuietly(tfileout);
|
||||
}
|
||||
|
||||
|
||||
// TODO: add two faces card correction? (WTF)
|
||||
// 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) {
|
||||
logger.error("Can't access to files: " + card.getName() + "(" + card.getSet() + "). Try rebooting your system to remove the file lock.");
|
||||
} catch (Exception e) {
|
||||
|
@ -933,26 +833,6 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
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) {
|
||||
|
|
|
@ -12,14 +12,10 @@ public class SettingsManager {
|
|||
|
||||
private static SettingsManager settingsManager = null;
|
||||
|
||||
public static SettingsManager getIntance() {
|
||||
if (settingsManager == null) {
|
||||
synchronized (SettingsManager.class) {
|
||||
public static synchronized SettingsManager getIntance() {
|
||||
if (settingsManager == null) {
|
||||
settingsManager = new SettingsManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return settingsManager;
|
||||
}
|
||||
|
||||
|
|
|
@ -150,9 +150,7 @@ public class ThemePluginImpl implements ThemePlugin {
|
|||
return bgPanel;
|
||||
}
|
||||
|
||||
private ImagePanel createImagePanelInstance() {
|
||||
if (background == null) {
|
||||
synchronized (ThemePluginImpl.class) {
|
||||
private synchronized ImagePanel createImagePanelInstance() {
|
||||
if (background == null) {
|
||||
String filename = "/background.png";
|
||||
try {
|
||||
|
@ -190,8 +188,6 @@ public class ThemePluginImpl implements ThemePlugin {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ImagePanel(background, ImagePanelStyle.SCALED);
|
||||
}
|
||||
|
||||
|
|
30
Mage.Common/src/main/java/mage/utils/StreamUtils.java
Normal file
30
Mage.Common/src/main/java/mage/utils/StreamUtils.java
Normal 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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -957,10 +957,11 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
|||
}
|
||||
|
||||
protected final void getSuggestedActions() {
|
||||
Scanner scanner = null;
|
||||
try {
|
||||
File file = new File(FILE_WITH_INSTRUCTIONS);
|
||||
if (file.exists()) {
|
||||
Scanner scanner = new Scanner(file);
|
||||
scanner = new Scanner(file);
|
||||
while (scanner.hasNextLine()) {
|
||||
String line = scanner.nextLine();
|
||||
if (line.startsWith("cast:")
|
||||
|
@ -976,6 +977,10 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
|||
} catch (Exception e) {
|
||||
// swallow
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(scanner != null) {
|
||||
scanner.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,8 +90,8 @@ public class ChatSession {
|
|||
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
|
||||
final Lock w = lock.writeLock();
|
||||
w.lock();
|
||||
try {
|
||||
w.lock();
|
||||
clients.remove(userId);
|
||||
} finally {
|
||||
w.unlock();
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
package mage.server;
|
||||
|
||||
import mage.server.util.PluginClassLoader;
|
||||
import mage.util.StreamUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -54,10 +55,12 @@ public final class ExtensionPackageLoader {
|
|||
String entryPoint = entryPointReader.nextLine().trim();
|
||||
entryPointReader.close();
|
||||
|
||||
PluginClassLoader classLoader = new PluginClassLoader();
|
||||
for(File f : packagesDirectory.listFiles()) classLoader.addURL(f.toURI().toURL());
|
||||
|
||||
PluginClassLoader classLoader = null;
|
||||
try {
|
||||
classLoader = new PluginClassLoader();
|
||||
for(File f : packagesDirectory.listFiles()) {
|
||||
classLoader.addURL(f.toURI().toURL());
|
||||
}
|
||||
return (ExtensionPackage) Class.forName(entryPoint, false, classLoader).newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
@ -65,6 +68,8 @@ public final class ExtensionPackageLoader {
|
|||
throw new RuntimeException("Entry point class not found!", e);
|
||||
} catch (ClassCastException e) {
|
||||
throw new RuntimeException("Entry point not an instance of ExtensionPackage.", e);
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(classLoader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -231,8 +231,8 @@ public enum UserManager {
|
|||
}
|
||||
logger.debug("Users to remove " + toRemove.size());
|
||||
final Lock w = lock.readLock();
|
||||
w.lock();
|
||||
try {
|
||||
w.lock();
|
||||
for (User user : toRemove) {
|
||||
users.remove(user.getId());
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ import mage.server.util.ConfigSettings;
|
|||
import mage.server.util.Splitter;
|
||||
import mage.server.util.SystemUtil;
|
||||
import mage.server.util.ThreadExecutor;
|
||||
import mage.utils.StreamUtils;
|
||||
import mage.utils.timer.PriorityTimer;
|
||||
import mage.view.*;
|
||||
import mage.view.ChatMessage.MessageColor;
|
||||
|
@ -902,17 +903,23 @@ public class GameController implements GameCallback {
|
|||
}
|
||||
|
||||
public boolean saveGame() {
|
||||
OutputStream file = null;
|
||||
ObjectOutput output = null;
|
||||
OutputStream buffer = null;
|
||||
try {
|
||||
OutputStream file = new FileOutputStream("saved/" + game.getId().toString() + ".game");
|
||||
OutputStream buffer = new BufferedOutputStream(file);
|
||||
try (ObjectOutput output = new ObjectOutputStream(new GZIPOutputStream(buffer))) {
|
||||
file = new FileOutputStream("saved/" + game.getId().toString() + ".game");
|
||||
buffer = new BufferedOutputStream(file);
|
||||
output = new ObjectOutputStream(new GZIPOutputStream(buffer));
|
||||
output.writeObject(game);
|
||||
output.writeObject(game.getGameStates());
|
||||
}
|
||||
logger.debug("Saved game:" + game.getId());
|
||||
return true;
|
||||
} catch (IOException ex) {
|
||||
logger.fatal("Cannot save game.", ex);
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(file);
|
||||
StreamUtils.closeQuietly(output);
|
||||
StreamUtils.closeQuietly(buffer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import mage.game.GameState;
|
|||
import mage.game.GameStates;
|
||||
import mage.server.Main;
|
||||
import mage.util.CopierObjectInputStream;
|
||||
import mage.utils.StreamUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
||||
|
@ -84,21 +85,31 @@ public class GameReplay {
|
|||
}
|
||||
|
||||
private Game loadGame(UUID gameId) {
|
||||
InputStream file = null;
|
||||
InputStream buffer = null;
|
||||
InputStream gzip = null;
|
||||
ObjectInput input = null;
|
||||
try{
|
||||
InputStream file = new FileInputStream("saved/" + gameId.toString() + ".game");
|
||||
InputStream buffer = new BufferedInputStream(file);
|
||||
try (ObjectInput input = new CopierObjectInputStream(Main.classLoader, new GZIPInputStream(buffer))) {
|
||||
file = new FileInputStream("saved/" + gameId.toString() + ".game");
|
||||
buffer = new BufferedInputStream(file);
|
||||
gzip = new GZIPInputStream(buffer);
|
||||
input = new CopierObjectInputStream(Main.classLoader, gzip);
|
||||
Game loadGame = (Game) input.readObject();
|
||||
GameStates states = (GameStates) input.readObject();
|
||||
loadGame.loadGameStates(states);
|
||||
return loadGame;
|
||||
}
|
||||
|
||||
}
|
||||
catch(ClassNotFoundException ex) {
|
||||
logger.fatal("Cannot load game. Class not found.", ex);
|
||||
}
|
||||
catch(IOException ex) {
|
||||
logger.fatal("Cannot load game:" + gameId, ex);
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(file);
|
||||
StreamUtils.closeQuietly(buffer);
|
||||
StreamUtils.closeQuietly(input);
|
||||
StreamUtils.closeQuietly(gzip);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
package mage.server.util;
|
||||
|
||||
import mage.utils.StreamUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -49,7 +50,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|||
* @author nantuko
|
||||
*/
|
||||
public enum ServerMessagesUtil {
|
||||
instance;
|
||||
instance;
|
||||
private static final Logger log = Logger.getLogger(ServerMessagesUtil.class);
|
||||
private static final String SERVER_MSG_TXT_FILE = "server.msg.txt";
|
||||
private ScheduledExecutorService updateExecutor;
|
||||
|
@ -147,14 +148,23 @@ instance;
|
|||
log.warn("Couldn't find server.msg");
|
||||
return null;
|
||||
}
|
||||
Scanner scanner = new Scanner(is);
|
||||
|
||||
Scanner scanner = null;
|
||||
List<String> newMessages = new ArrayList<>();
|
||||
try {
|
||||
scanner = new Scanner(is);
|
||||
while (scanner.hasNextLine()) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,6 @@ class EmpyrialArchangelEffect extends ReplacementEffectImpl {
|
|||
Permanent p = game.getPermanent(source.getSourceId());
|
||||
if (p != null) {
|
||||
p.damage(damageEvent.getAmount(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable());
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ class FalkenrathAristocratEffect extends OneShotEffect {
|
|||
Permanent sourceCreature = game.getPermanent(source.getSourceId());
|
||||
if (sacrificedCreature.hasSubtype(SubType.HUMAN, game) && sourceCreature != null) {
|
||||
sourceCreature.addCounters(CounterType.P1P1.createInstance(), source, game);
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,13 +95,12 @@ class GilderBairnEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent target = game.getPermanent(source.getFirstTarget());
|
||||
if (target == null) {
|
||||
return false;
|
||||
}
|
||||
if (target != null) {
|
||||
for (Counter counter : target.getCounters(game).values()) {
|
||||
Counter newCounter = new Counter(counter.getName(), counter.getCount());
|
||||
target.addCounters(newCounter, source, game);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ class IceCaveEffect extends OneShotEffect {
|
|||
if (cost.pay(source, game, source.getSourceId(), playerId, false, null)) {
|
||||
game.informPlayers(player.getLogName() + " pays" + cost.getText() + " to counter " + spell.getIdName() + '.');
|
||||
game.getStack().counter(spell.getId(), source.getSourceId(), game);
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,7 +99,6 @@ class KjeldoranRoyalGuardEffect extends ReplacementEffectImpl {
|
|||
Permanent p = game.getPermanent(source.getSourceId());
|
||||
if (p != null) {
|
||||
p.damage(damageEvent.getAmount(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable());
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -129,7 +129,6 @@ class LegionsInitiativeExileEffect extends OneShotEffect {
|
|||
//create delayed triggered ability
|
||||
AtTheBeginOfCombatDelayedTriggeredAbility delayedAbility = new AtTheBeginOfCombatDelayedTriggeredAbility(new LegionsInitiativeReturnFromExileEffect());
|
||||
game.addDelayedTriggeredAbility(delayedAbility, source);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -84,10 +84,7 @@ class NaturesWillEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Set<UUID> damagedPlayers = (HashSet<UUID>) this.getValue("damagedPlayers");
|
||||
if (damagedPlayers == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (damagedPlayers != null) {
|
||||
List<Permanent> lands = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LAND, source.getControllerId(), source.getSourceId(), game);
|
||||
for (Permanent land : lands) {
|
||||
if (damagedPlayers.contains(land.getControllerId())) {
|
||||
|
@ -96,7 +93,7 @@ class NaturesWillEffect extends OneShotEffect {
|
|||
land.untap(game);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import java.io.*;
|
|||
import java.net.HttpURLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import java.io.Closeable;
|
||||
/**
|
||||
* Helper for file operations.
|
||||
*
|
||||
|
@ -84,15 +84,17 @@ public final class FileHelper {
|
|||
*/
|
||||
public static void downloadFile(String filename, HttpURLConnection urlConnection) {
|
||||
System.out.println("Downloading " + filename);
|
||||
InputStream in = null;
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
InputStream in = urlConnection.getInputStream();
|
||||
in = urlConnection.getInputStream();
|
||||
File f = new File(filename);
|
||||
if (!f.exists() && f.getParentFile() != null) {
|
||||
f.getParentFile().mkdirs();
|
||||
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];
|
||||
int bytesRead;
|
||||
|
||||
|
@ -103,6 +105,19 @@ public final class FileHelper {
|
|||
System.out.println("File has been updated: " + filename);
|
||||
} catch (IOException e) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package mage.verify;
|
|||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import mage.util.StreamUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
@ -94,9 +95,16 @@ public final class MtgJson {
|
|||
}
|
||||
stream = new FileInputStream(file);
|
||||
}
|
||||
ZipInputStream zipInputStream = new ZipInputStream(stream);
|
||||
ZipInputStream zipInputStream = null;
|
||||
try {
|
||||
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() {
|
||||
|
|
|
@ -50,36 +50,44 @@ public class Copier<T> {
|
|||
|
||||
public T copy(T obj) {
|
||||
T copy = null;
|
||||
|
||||
FastByteArrayOutputStream fbos = null;
|
||||
ObjectOutputStream out = null;
|
||||
ObjectInputStream in = null;
|
||||
try {
|
||||
FastByteArrayOutputStream fbos = new FastByteArrayOutputStream();
|
||||
ObjectOutputStream out= new ObjectOutputStream(fbos);
|
||||
fbos = new FastByteArrayOutputStream();
|
||||
out = new ObjectOutputStream(fbos);
|
||||
|
||||
// Write the object out to a byte array
|
||||
out.writeObject(obj);
|
||||
out.flush();
|
||||
out.close();
|
||||
|
||||
// Retrieve an input stream from the byte array and read
|
||||
// a copy of the object back in.
|
||||
ObjectInputStream in = new CopierObjectInputStream(loader, fbos.getInputStream());
|
||||
in = new CopierObjectInputStream(loader, fbos.getInputStream());
|
||||
copy = (T) in.readObject();
|
||||
}
|
||||
catch(IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(fbos);
|
||||
StreamUtils.closeQuietly(out);
|
||||
StreamUtils.closeQuietly(in);
|
||||
}
|
||||
return copy;
|
||||
|
||||
}
|
||||
|
||||
public byte[] copyCompressed(T obj) {
|
||||
FastByteArrayOutputStream fbos = null;
|
||||
ObjectOutputStream out = null;
|
||||
try {
|
||||
FastByteArrayOutputStream fbos = new FastByteArrayOutputStream();
|
||||
ObjectOutputStream out= new ObjectOutputStream(new GZIPOutputStream(fbos));
|
||||
fbos = new FastByteArrayOutputStream();
|
||||
out = new ObjectOutputStream(new GZIPOutputStream(fbos));
|
||||
|
||||
// Write the object out to a byte array
|
||||
out.writeObject(obj);
|
||||
out.flush();
|
||||
out.close();
|
||||
|
||||
byte[] copy = new byte[fbos.getSize()];
|
||||
System.arraycopy(fbos.getByteArray(), 0, copy, 0, fbos.getSize());
|
||||
|
@ -87,6 +95,9 @@ public class Copier<T> {
|
|||
}
|
||||
catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(fbos);
|
||||
StreamUtils.closeQuietly(out);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
30
Mage/src/main/java/mage/util/StreamUtils.java
Normal file
30
Mage/src/main/java/mage/util/StreamUtils.java
Normal 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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue