From 14f156d6267b07b46e9e0cbe1010d78d417014d6 Mon Sep 17 00:00:00 2001 From: betasteward Date: Sun, 28 Jun 2015 18:59:30 -0400 Subject: [PATCH] fixed ConcurrentModificationException --- .../src/mage/view/AbilityPickerView.java | 4 +- Mage.Common/src/mage/view/AbilityView.java | 7 +- Mage.Common/src/mage/view/CardView.java | 114 ++++++++++-------- Mage.Common/src/mage/view/PermanentView.java | 11 +- .../src/mage/view/StackAbilityView.java | 24 ++-- .../src/main/java/mage/server/ServerMain.java | 2 +- .../main/java/mage/server/game/GamesRoom.java | 10 +- .../java/mage/server/game/GamesRoomImpl.java | 52 ++++---- 8 files changed, 112 insertions(+), 112 deletions(-) diff --git a/Mage.Common/src/mage/view/AbilityPickerView.java b/Mage.Common/src/mage/view/AbilityPickerView.java index 489883f31af..494cc3041f9 100644 --- a/Mage.Common/src/mage/view/AbilityPickerView.java +++ b/Mage.Common/src/mage/view/AbilityPickerView.java @@ -42,7 +42,7 @@ import mage.abilities.Ability; public class AbilityPickerView implements Serializable { private static final long serialVersionUID = 1L; - private Map choices = new LinkedHashMap(); + private final Map choices = new LinkedHashMap<>(); public AbilityPickerView(String objectName, List abilities) { for (Ability ability: abilities) { @@ -59,7 +59,7 @@ public class AbilityPickerView implements Serializable { } public AbilityPickerView(Map modes) { - this.choices = modes; + this.choices.putAll(modes); } public Map getChoices() { diff --git a/Mage.Common/src/mage/view/AbilityView.java b/Mage.Common/src/mage/view/AbilityView.java index 16492d7a6c4..bd68facf21e 100644 --- a/Mage.Common/src/mage/view/AbilityView.java +++ b/Mage.Common/src/mage/view/AbilityView.java @@ -28,7 +28,6 @@ package mage.view; -import java.util.ArrayList; import mage.ObjectColor; import mage.abilities.Ability; @@ -48,16 +47,12 @@ public class AbilityView extends CardView { this.name = "Ability"; this.sourceName = sourceName; this.sourceCard = sourceCard; - this.rules = new ArrayList<>(); rules.add(ability.getRule()); this.power = ""; this.toughness = ""; this.loyalty = ""; - this.cardTypes = new ArrayList<>(); - this.subTypes = new ArrayList<>(); - this.superTypes = new ArrayList<>(); this.color = new ObjectColor(); - this.manaCost = ability.getManaCosts().getSymbols(); + this.manaCost.addAll(ability.getManaCosts().getSymbols()); } public CardView getSourceCard() { diff --git a/Mage.Common/src/mage/view/CardView.java b/Mage.Common/src/mage/view/CardView.java index d0845cd7ae6..857db14cd63 100644 --- a/Mage.Common/src/mage/view/CardView.java +++ b/Mage.Common/src/mage/view/CardView.java @@ -28,6 +28,9 @@ package mage.view; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; import mage.MageObject; import mage.ObjectColor; import mage.abilities.Modes; @@ -35,9 +38,14 @@ import mage.abilities.SpellAbility; import mage.abilities.costs.mana.ManaCosts; import mage.cards.Card; import mage.cards.SplitCard; -import mage.constants.*; +import mage.constants.AbilityType; +import mage.constants.CardType; +import mage.constants.MageObjectType; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.counters.Counter; import mage.counters.CounterType; +import mage.game.Game; import mage.game.command.Emblem; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; @@ -47,11 +55,6 @@ import mage.game.stack.StackAbility; import mage.target.Target; import mage.target.Targets; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import mage.game.Game; - /** * @author BetaSteward_at_googlemail.com */ @@ -61,15 +64,15 @@ public class CardView extends SimpleCardView { protected UUID parentId; protected String name; protected String displayName; - protected List rules; + protected final List rules = new ArrayList<>(); protected String power; protected String toughness; protected String loyalty; - protected List cardTypes; - protected List subTypes; - protected List superTypes; + protected final List cardTypes = new ArrayList<>(); + protected final List subTypes = new ArrayList<>(); + protected final List superTypes = new ArrayList<>(); protected ObjectColor color; - protected List manaCost; + protected final List manaCost = new ArrayList<>(); protected int convertedManaCost; protected Rarity rarity; @@ -95,16 +98,16 @@ public class CardView extends SimpleCardView { protected boolean isSplitCard; protected String leftSplitName; protected ManaCosts leftSplitCosts; - protected List leftSplitRules; + protected final List leftSplitRules = new ArrayList<>(); protected String rightSplitName; protected ManaCosts rightSplitCosts; - protected List rightSplitRules; + protected final List rightSplitRules = new ArrayList<>(); - protected List targets; + protected final List targets = new ArrayList<>(); protected UUID pairedCard; protected boolean paid; - protected List counters; + protected final List counters = new ArrayList<>(); protected boolean controlledByOwner = true; @@ -158,7 +161,8 @@ public class CardView extends SimpleCardView { if (card instanceof Permanent) { this.power = Integer.toString(card.getPower().getValue()); this.toughness = Integer.toString(card.getToughness().getValue()); - this.cardTypes = card.getCardType(); + this.cardTypes.clear(); + this.cardTypes.addAll(card.getCardType()); } else { // this.hideInfo = true; return; @@ -188,20 +192,22 @@ public class CardView extends SimpleCardView { this.isSplitCard = true; leftSplitName = splitCard.getLeftHalfCard().getName(); leftSplitCosts = splitCard.getLeftHalfCard().getManaCost(); - leftSplitRules = splitCard.getLeftHalfCard().getRules(game); + leftSplitRules.addAll(splitCard.getLeftHalfCard().getRules(game)); rightSplitName = splitCard.getRightHalfCard().getName(); rightSplitCosts = splitCard.getRightHalfCard().getManaCost(); - rightSplitRules = splitCard.getRightHalfCard().getRules(game); + rightSplitRules.addAll(splitCard.getRightHalfCard().getRules(game)); } this.name = card.getImageName(); this.displayName = card.getName(); + this.rules.clear(); if (game == null) { - this.rules = card.getRules(); + this.rules.addAll(card.getRules()); } else { - this.rules = card.getRules(game); + this.rules.addAll(card.getRules(game)); } - this.manaCost = card.getManaCost().getSymbols(); + this.manaCost.clear(); + this.manaCost.addAll(card.getManaCost().getSymbols()); this.convertedManaCost = card.getManaCost().convertedManaCost(); if (card instanceof Permanent) { @@ -213,7 +219,7 @@ public class CardView extends SimpleCardView { controlledByOwner = false; } if (game != null && permanent.getCounters() != null && !permanent.getCounters().isEmpty()) { - counters = new ArrayList<>(); + counters.clear(); for (Counter counter: permanent.getCounters().values()) { counters.add(new CounterView(counter)); } @@ -226,7 +232,7 @@ public class CardView extends SimpleCardView { } this.loyalty = ""; if (game != null && card.getCounters(game) != null && !card.getCounters(game).isEmpty()) { - counters = new ArrayList<>(); + counters.clear(); for (Counter counter: card.getCounters(game).values()) { counters.add(new CounterView(counter)); } @@ -234,9 +240,12 @@ public class CardView extends SimpleCardView { } this.power = Integer.toString(card.getPower().getValue()); this.toughness = Integer.toString(card.getToughness().getValue()); - this.cardTypes = card.getCardType(); - this.subTypes = card.getSubtype(); - this.superTypes = card.getSupertype(); + this.cardTypes.clear(); + this.cardTypes.addAll(card.getCardType()); + this.subTypes.clear(); + this.subTypes.addAll(card.getSubtype()); + this.superTypes.clear(); + this.superTypes.addAll(card.getSupertype()); this.color = card.getColor(game); this.canTransform = card.canTransform(); this.flipCard = card.isFlipCard(); @@ -256,7 +265,8 @@ public class CardView extends SimpleCardView { } // // set code und card number for token copies to get the image - this.rules = ((PermanentToken) card).getRules(game); + this.rules.clear(); + this.rules.addAll(((PermanentToken) card).getRules(game)); this.type = ((PermanentToken)card).getToken().getTokenType(); } else { this.rarity = card.getRarity(); @@ -310,29 +320,35 @@ public class CardView extends SimpleCardView { this.toughness = object.getToughness().toString(); this.loyalty = ""; } - this.cardTypes = object.getCardType(); - this.subTypes = object.getSubtype(); - this.superTypes = object.getSupertype(); + this.cardTypes.clear(); + this.cardTypes.addAll(object.getCardType()); + this.subTypes.clear(); + this.subTypes.addAll(object.getSubtype()); + this.superTypes.clear(); + this.superTypes.addAll(object.getSupertype()); this.color = object.getColor(null); - this.manaCost = object.getManaCost().getSymbols(); + this.manaCost.clear(); + this.manaCost.addAll(object.getManaCost().getSymbols()); this.convertedManaCost = object.getManaCost().convertedManaCost(); if (object instanceof PermanentToken) { this.mageObjectType = MageObjectType.TOKEN; PermanentToken permanentToken = (PermanentToken) object; this.rarity = Rarity.COMMON; this.expansionSetCode = permanentToken.getExpansionSetCode(); - this.rules = permanentToken.getRules(); + this.rules.clear(); + this.rules.addAll(permanentToken.getRules()); this.type = permanentToken.getToken().getTokenType(); } else if (object instanceof Emblem) { this.mageObjectType = MageObjectType.EMBLEM; Emblem emblem = (Emblem) object; this.rarity = Rarity.SPECIAL; - this.rules = emblem.getAbilities().getRules(emblem.getName()); + this.rules.clear(); + this.rules.addAll(emblem.getAbilities().getRules(emblem.getName())); } if (this.rarity == null && object instanceof StackAbility) { StackAbility stackAbility = (StackAbility)object; this.rarity = Rarity.NA; - this.rules = new ArrayList<>(); + this.rules.clear(); this.rules.add(stackAbility.getRule()); if (stackAbility.getZone().equals(Zone.COMMAND)) { this.expansionSetCode = stackAbility.getExpansionSetCode(); @@ -351,7 +367,8 @@ public class CardView extends SimpleCardView { this.mageObjectType = MageObjectType.EMBLEM; this.name = emblem.getName(); this.displayName = name; - this.rules = emblem.getRules(); + this.rules.clear(); + this.rules.addAll(emblem.getRules()); // emblem images are always with common (black) symbol this.expansionSetCode = emblem.getExpansionSetCode(); this.rarity = Rarity.COMMON; @@ -368,15 +385,10 @@ public class CardView extends SimpleCardView { private void fillEmpty(Card card, boolean controlled) { this.name = "Face Down"; this.displayName = name; - this.rules = new ArrayList<>(); this.power = ""; this.toughness = ""; this.loyalty = ""; - this.cardTypes = new ArrayList<>(); - this.subTypes = new ArrayList<>(); - this.superTypes = new ArrayList<>(); this.color = new ObjectColor(); - this.manaCost = new ArrayList<>(); this.convertedManaCost = 0; // the controller can see more information (e.g. enlarged image) than other players for face down cards (e.g. Morph played face down) @@ -414,15 +426,15 @@ public class CardView extends SimpleCardView { this.id = token.getId(); this.name = token.getName(); this.displayName = token.getName(); - this.rules = token.getAbilities().getRules(this.name); + this.rules.addAll(token.getAbilities().getRules(this.name)); this.power = token.getPower().toString(); this.toughness = token.getToughness().toString(); this.loyalty = ""; - this.cardTypes = token.getCardType(); - this.subTypes = token.getSubtype(); - this.superTypes = token.getSupertype(); + this.cardTypes.addAll(token.getCardType()); + this.subTypes.addAll(token.getSubtype()); + this.superTypes.addAll(token.getSupertype()); this.color = token.getColor(null); - this.manaCost = token.getManaCost().getSymbols(); + this.manaCost.addAll(token.getManaCost().getSymbols()); this.rarity = Rarity.NA; this.type = token.getTokenType(); this.tokenSetCode = token.getOriginalExpansionSetCode(); @@ -431,11 +443,9 @@ public class CardView extends SimpleCardView { protected final void setTargets(Targets targets) { for (Target target : targets) { if (target.isChosen()) { + this.targets.clear(); for (UUID targetUUID : target.getTargets()) { - if (this.targets == null) { - this.targets = new ArrayList<>(); - } - this.targets.add(targetUUID); + this.targets.add(targetUUID); } } } @@ -454,7 +464,8 @@ public class CardView extends SimpleCardView { } public void overrideRules(List rules) { - this.rules = rules; + this.rules.clear(); + this.rules.addAll(rules); } public void setIsAbility(boolean isAbility) { @@ -543,7 +554,8 @@ public class CardView extends SimpleCardView { } public void overrideTargets(List newTargets) { - this.targets = newTargets; + this.targets.clear(); + this.targets.addAll(newTargets); } public void overrideId(UUID id) { diff --git a/Mage.Common/src/mage/view/PermanentView.java b/Mage.Common/src/mage/view/PermanentView.java index 2b7fe476f00..44743ec891f 100644 --- a/Mage.Common/src/mage/view/PermanentView.java +++ b/Mage.Common/src/mage/view/PermanentView.java @@ -51,7 +51,7 @@ public class PermanentView extends CardView { private final boolean phasedIn; private final boolean summoningSickness; private final int damage; - private List attachments; + private final List attachments = new ArrayList<>(); private final CardView original; private final boolean copy; private final String nameOwner; // only filled if != controller @@ -64,7 +64,8 @@ public class PermanentView extends CardView { public PermanentView(Permanent permanent, Card card, UUID createdForPlayerId, Game game) { super(permanent, game, permanent.getControllerId().equals(createdForPlayerId)); this.controlled = permanent.getControllerId().equals(createdForPlayerId); - this.rules = permanent.getRules(game); + this.rules.clear(); + this.rules.addAll(permanent.getRules(game)); this.tapped = permanent.isTapped(); this.flipped = permanent.isFlipped(); this.phasedIn = permanent.isPhasedIn(); @@ -72,10 +73,8 @@ public class PermanentView extends CardView { this.morphed = permanent.isMorphed(); this.manifested = permanent.isManifested(); this.damage = permanent.getDamage(); - if (permanent.getAttachments().size() > 0) { - attachments = new ArrayList<>(); - attachments.addAll(permanent.getAttachments()); - } + this.attachments.clear(); + this.attachments.addAll(permanent.getAttachments()); this.attachedTo = permanent.getAttachedTo(); if (isToken()) { original = new CardView(((PermanentToken)permanent).getToken()); diff --git a/Mage.Common/src/mage/view/StackAbilityView.java b/Mage.Common/src/mage/view/StackAbilityView.java index 8cb82fa2ffe..9ec6c3f1776 100644 --- a/Mage.Common/src/mage/view/StackAbilityView.java +++ b/Mage.Common/src/mage/view/StackAbilityView.java @@ -61,18 +61,18 @@ public class StackAbilityView extends CardView { this.name = "Ability"; this.loyalty = ""; - this.cardTypes = ability.getCardType(); - this.subTypes = ability.getSubtype(); - this.superTypes = ability.getSupertype(); + this.cardTypes.addAll(ability.getCardType()); + this.subTypes.addAll(ability.getSubtype()); + this.superTypes.addAll(ability.getSupertype()); this.color = ability.getColor(game); - this.manaCost = ability.getManaCost().getSymbols(); - this.cardTypes = ability.getCardType(); - this.subTypes = ability.getSubtype(); - this.superTypes = ability.getSupertype(); + this.manaCost.addAll(ability.getManaCost().getSymbols()); + this.cardTypes.addAll(ability.getCardType()); + this.subTypes.addAll(ability.getSubtype()); + this.superTypes.addAll(ability.getSupertype()); this.color = ability.getColor(game); - this.manaCost = ability.getManaCost().getSymbols(); + this.manaCost.addAll(ability.getManaCost().getSymbols()); this.power = ability.getPower().toString(); - this.toughness = ability.getToughness().toString(); + this.toughness = ability.getToughness().toString(); String nameToShow; if (sourceCard.isFaceDown()) { CardView tmpSourceCard = this.getSourceCard(); @@ -85,12 +85,12 @@ public class StackAbilityView extends CardView { tmpSourceCard.power = "2"; tmpSourceCard.toughness = "2"; nameToShow = "creature without name"; - } else { + } else { nameToShow = sourceName; } - this.rules = new ArrayList<>(); + rules.clear(); rules.add(ability.getRule(nameToShow)); - this.counters = sourceCard.getCounters(); + this.counters.addAll(sourceCard.getCounters()); updateTargets(game, ability); } diff --git a/Mage.Server/src/main/java/mage/server/ServerMain.java b/Mage.Server/src/main/java/mage/server/ServerMain.java index 258a5aad11d..c6797977cc2 100644 --- a/Mage.Server/src/main/java/mage/server/ServerMain.java +++ b/Mage.Server/src/main/java/mage/server/ServerMain.java @@ -348,7 +348,7 @@ public class ServerMain implements MageServer { public RoomView getRoom(UUID roomId) { GamesRoom room = GamesRoomManager.getInstance().getRoom(roomId); if (room != null) { - return new RoomView(room.getRoomUsersInfo(), room.getTables(), room.getFinished()); + return room.getRoomView(); } else { return null; } diff --git a/Mage.Server/src/main/java/mage/server/game/GamesRoom.java b/Mage.Server/src/main/java/mage/server/game/GamesRoom.java index 4ec966ca7b2..03bbf7271d1 100644 --- a/Mage.Server/src/main/java/mage/server/game/GamesRoom.java +++ b/Mage.Server/src/main/java/mage/server/game/GamesRoom.java @@ -28,16 +28,13 @@ package mage.server.game; -import java.util.List; import java.util.UUID; import mage.MageException; import mage.cards.decks.DeckCardLists; -import mage.game.GameException; import mage.game.match.MatchOptions; import mage.game.tournament.TournamentOptions; import mage.server.Room; -import mage.view.MatchView; -import mage.view.RoomUsersView; +import mage.view.RoomView; import mage.view.TableView; /** @@ -46,9 +43,6 @@ import mage.view.TableView; */ public interface GamesRoom extends Room { - List getTables(); - List getFinished(); - RoomUsersView getRoomUsersInfo(); boolean joinTable(UUID userId, UUID tableId, String name, String playerType, int skill, DeckCardLists deckList, String password); boolean joinTournamentTable(UUID userId, UUID tableId, String name, String playerType, int skill, DeckCardLists deckList, String password); TableView createTable(UUID userId, MatchOptions options); @@ -59,4 +53,6 @@ public interface GamesRoom extends Room { void leaveTable(UUID userId, UUID tableId); boolean watchTable(UUID userId, UUID tableId) throws MageException; + public RoomView getRoomView(); + } diff --git a/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java b/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java index c1c6c2d38c6..0cdab8e20a8 100644 --- a/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java +++ b/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java @@ -38,10 +38,11 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import mage.MageException; import mage.cards.decks.DeckCardLists; import mage.constants.TableState; -import mage.game.GameException; import mage.game.Table; import mage.game.match.MatchOptions; import mage.game.tournament.TournamentOptions; @@ -56,6 +57,7 @@ import mage.server.util.ConfigSettings; import mage.server.util.ThreadExecutor; import mage.view.MatchView; import mage.view.RoomUsersView; +import mage.view.RoomView; import mage.view.TableView; import mage.view.UsersView; import org.apache.log4j.Logger; @@ -69,10 +71,9 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { private static final Logger logger = Logger.getLogger(GamesRoomImpl.class); private static final ScheduledExecutorService updateExecutor = Executors.newSingleThreadScheduledExecutor(); - private static List tableView = new ArrayList<>(); - private static List matchView = new ArrayList<>(); - private static RoomUsersView roomUsersView; + private RoomView roomView; + private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final ConcurrentHashMap tables = new ConcurrentHashMap<>(); public GamesRoomImpl() { @@ -89,25 +90,20 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { }, 2, 2, TimeUnit.SECONDS); } - @Override - public List getTables() { - return tableView; - } - private void update() { - ArrayList tableList = new ArrayList<>(); - ArrayList matchList = new ArrayList<>(); + ArrayList tableView = new ArrayList<>(); + ArrayList matchView = new ArrayList<>(); List allTables = new ArrayList<>(tables.values()); Collections.sort(allTables, new TableListSorter()); for (Table table: allTables) { if (table.getState() != TableState.FINISHED) { - tableList.add(new TableView(table)); + tableView.add(new TableView(table)); } - else if (matchList.size() < 50) { + else if (matchView.size() < 50) { if (table.isTournament()) { - matchList.add(new MatchView(table)); + matchView.add(new MatchView(table)); } else { - matchList.add(new MatchView(table)); + matchView.add(new MatchView(table)); } } else { // more since 50 matches finished since this match so remove it @@ -117,8 +113,6 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { this.removeTable(table.getId()); } } - tableView = tableList; - matchView = matchList; List users = new ArrayList<>(); for (User user : UserManager.getInstance().getUsers()) { Session session = SessionManager.getInstance().getSession(user.getSessionId()); @@ -131,18 +125,17 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { } Collections.sort(users, new UserNameSorter()); -// List roomUserInfo = new ArrayList<>(); - roomUsersView = new RoomUsersView(users, + RoomUsersView roomUsersView = new RoomUsersView(users, GameManager.getInstance().getNumberActiveGames(), ThreadExecutor.getInstance().getActiveThreads(ThreadExecutor.getInstance().getGameExecutor()), ConfigSettings.getInstance().getMaxGameThreads() ); -// roomUsersView = roomUserInfo; - } - - @Override - public List getFinished() { - return matchView; + lock.writeLock().lock(); + try { + roomView = new RoomView(roomUsersView, tableView, matchView); + } finally { + lock.writeLock().unlock(); + } } @Override @@ -213,8 +206,13 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { } @Override - public RoomUsersView getRoomUsersInfo() { - return roomUsersView; + public RoomView getRoomView() { + lock.readLock().lock(); + try { + return roomView; + } finally { + lock.readLock().unlock(); + } } }