From 8e2fc8b0d42f7e5db24c6146fcc3631a7ecf5b51 Mon Sep 17 00:00:00 2001 From: sk89q Date: Thu, 3 Apr 2014 19:12:30 -0700 Subject: [PATCH] Moved session code into SessionManager. --- .../java/com/sk89q/worldedit/WorldEdit.java | 145 ++++--------- .../worldedit/session/SessionManager.java | 197 ++++++++++++++++++ 2 files changed, 240 insertions(+), 102 deletions(-) create mode 100644 src/main/java/com/sk89q/worldedit/session/SessionManager.java diff --git a/src/main/java/com/sk89q/worldedit/WorldEdit.java b/src/main/java/com/sk89q/worldedit/WorldEdit.java index a61856707..fba9db2e9 100644 --- a/src/main/java/com/sk89q/worldedit/WorldEdit.java +++ b/src/main/java/com/sk89q/worldedit/WorldEdit.java @@ -43,6 +43,7 @@ import com.sk89q.worldedit.regions.selector.RegionSelector; import com.sk89q.worldedit.scripting.CraftScriptContext; import com.sk89q.worldedit.scripting.CraftScriptEngine; import com.sk89q.worldedit.scripting.RhinoCraftScriptEngine; +import com.sk89q.worldedit.session.SessionManager; import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.util.LogFormat; import com.sk89q.worldedit.util.eventbus.EventBus; @@ -74,7 +75,7 @@ public class WorldEdit { private final CommandsManager commands; private final EventBus eventBus = new EventBus(); private final EditSessionFactory editSessionFactory = new InternalEditSessionFactory(eventBus); - private final HashMap sessions = new HashMap(); + private final SessionManager sessions = new SessionManager(this); private final BlockRegistry blockRegistry = new BlockRegistry(this); private final MaskRegistry maskRegistry = new MaskRegistry(this); @@ -252,79 +253,52 @@ public class WorldEdit { } /** - * Gets the LocalSession for a player name if it exists + * Return the session manager. * - * @param player - * @return The session for the player, if it exists + * @return the session manager */ + public SessionManager getSessionManager() { + return sessions; + } + + /** + * @deprecated Use {@link #getSessionManager()} + */ + @Deprecated public LocalSession getSession(String player) { + return sessions.findByName(player); + } + + /** + * @deprecated use {@link #getSessionManager()} + */ + @Deprecated + public LocalSession getSession(LocalPlayer player) { return sessions.get(player); } /** - * Gets the WorldEdit session for a player. - * - * @param player - * @return + * @deprecated use {@link #getSessionManager()} */ - public LocalSession getSession(LocalPlayer player) { - LocalSession session; - - synchronized (sessions) { - if (sessions.containsKey(player.getName())) { - session = sessions.get(player.getName()); - } else { - session = new LocalSession(config); - session.setBlockChangeLimit(config.defaultChangeLimit); - // Remember the session - sessions.put(player.getName(), session); - } - - // Set the limit on the number of blocks that an operation can - // change at once, or don't if the player has an override or there - // is no limit. There is also a default limit - int currentChangeLimit = session.getBlockChangeLimit(); - - if (!player.hasPermission("worldedit.limit.unrestricted") - && config.maxChangeLimit > -1) { - - // If the default limit is infinite but there is a maximum - // limit, make sure to not have it be overridden - if (config.defaultChangeLimit < 0) { - if (currentChangeLimit < 0 || currentChangeLimit > config.maxChangeLimit) { - session.setBlockChangeLimit(config.maxChangeLimit); - } - } else { - // Bound the change limit - int maxChangeLimit = config.maxChangeLimit; - if (currentChangeLimit == -1 || currentChangeLimit > maxChangeLimit) { - session.setBlockChangeLimit(maxChangeLimit); - } - } - } - - // Have the session use inventory if it's enabled and the player - // doesn't have an override - session.setUseInventory(config.useInventory - && !(config.useInventoryOverride - && (player.hasPermission("worldedit.inventory.unrestricted") - || (config.useInventoryCreativeOverride && player.hasCreativeMode())))); - } - - return session; + @Deprecated + public void removeSession(LocalPlayer player) { + sessions.remove(player); } /** - * Returns true if the player has a session. - * - * @param player - * @return + * @deprecated use {@link #getSessionManager()} */ + @Deprecated + public void clearSessions() { + sessions.clear(); + } + + /** + * @deprecated use {@link #getSessionManager()} + */ + @Deprecated public boolean hasSession(LocalPlayer player) { - // TODO: If this is indeed used in multiple threads, we should use Collections.synchronizedMap here to simplify things and exclude sources of error. - synchronized (sessions) { - return sessions.containsKey(player.getName()); - } + return sessions.contains(player); } /** @@ -741,26 +715,6 @@ public class WorldEdit { } } - /** - * Remove a session. - * - * @param player - */ - public void removeSession(LocalPlayer player) { - synchronized (sessions) { - sessions.remove(player.getName()); - } - } - - /** - * Remove all sessions. - */ - public void clearSessions() { - synchronized (sessions) { - sessions.clear(); - } - } - /** * Flush a block bag's changes to a player. * @@ -819,8 +773,9 @@ public class WorldEdit { } /** + * Handle a disconnection. * - * @param player + * @param player the player */ @Deprecated public void handleDisconnect(LocalPlayer player) { @@ -828,42 +783,28 @@ public class WorldEdit { } /** + * Mark for expiration of the session. * - * @param player + * @param player the player */ public void markExpire(LocalPlayer player) { - synchronized (sessions) { - LocalSession session = sessions.get(player.getName()); - if (session != null) { - session.update(); - } - } + sessions.markforExpiration(player); } /** * Forget a player. * - * @param player + * @param player the player */ public void forgetPlayer(LocalPlayer player) { - removeSession(player); + sessions.remove(player); } /* * Flush expired sessions. */ public void flushExpiredSessions(SessionCheck checker) { - synchronized (sessions) { - Iterator> it = sessions.entrySet().iterator(); - - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (entry.getValue().hasExpired() - && !checker.isOnlinePlayer(entry.getKey())) { - it.remove(); - } - } - } + sessions.removeExpired(checker); } /** diff --git a/src/main/java/com/sk89q/worldedit/session/SessionManager.java b/src/main/java/com/sk89q/worldedit/session/SessionManager.java new file mode 100644 index 000000000..5e759a192 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/session/SessionManager.java @@ -0,0 +1,197 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.session; + +import com.sk89q.worldedit.*; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Session manager for WorldEdit. + *

+ * Get a reference to one from {@link WorldEdit}. + *

+ * While this class is thread-safe, the returned session may not be. + */ +public class SessionManager { + + private final WorldEdit worldEdit; + private final HashMap sessions = new HashMap(); + + /** + * Create a new session manager. + * + * @param worldEdit a WorldEdit instance + */ + public SessionManager(WorldEdit worldEdit) { + this.worldEdit = worldEdit; + } + + /** + * Get whether a session exists for the given player. + * + * @param player the player + * @return true if a session exists + */ + public synchronized boolean contains(LocalPlayer player) { + checkNotNull(player); + return sessions.containsKey(getKey(player)); + } + + /** + * Gets the session for a player and return it if it exists, otherwise + * return null. + * + * @param player the player + * @return the session for the player, if it exists + */ + public synchronized @Nullable LocalSession find(LocalPlayer player) { + checkNotNull(player); + return sessions.get(getKey(player)); + } + + /** + * Gets the session for someone named by the given name and return it if + * it exists, otherwise return null. + * + * @param name the player's name + * @return the session for the player, if it exists + */ + public synchronized @Nullable LocalSession findByName(String name) { + checkNotNull(name); + return sessions.get(name); + } + + /** + * Get the session for a player and create one if one doesn't exist. + * + * @param player the player + * @return a session + */ + public synchronized LocalSession get(LocalPlayer player) { + checkNotNull(player); + + LocalSession session; + LocalConfiguration config = worldEdit.getConfiguration(); + + if (sessions.containsKey(player.getName())) { + session = sessions.get(player.getName()); + } else { + session = new LocalSession(config); + session.setBlockChangeLimit(config.defaultChangeLimit); + // Remember the session + sessions.put(player.getName(), session); + } + + // Set the limit on the number of blocks that an operation can + // change at once, or don't if the player has an override or there + // is no limit. There is also a default limit + int currentChangeLimit = session.getBlockChangeLimit(); + + if (!player.hasPermission("worldedit.limit.unrestricted") + && config.maxChangeLimit > -1) { + + // If the default limit is infinite but there is a maximum + // limit, make sure to not have it be overridden + if (config.defaultChangeLimit < 0) { + if (currentChangeLimit < 0 || currentChangeLimit > config.maxChangeLimit) { + session.setBlockChangeLimit(config.maxChangeLimit); + } + } else { + // Bound the change limit + int maxChangeLimit = config.maxChangeLimit; + if (currentChangeLimit == -1 || currentChangeLimit > maxChangeLimit) { + session.setBlockChangeLimit(maxChangeLimit); + } + } + } + + // Have the session use inventory if it's enabled and the player + // doesn't have an override + session.setUseInventory(config.useInventory + && !(config.useInventoryOverride + && (player.hasPermission("worldedit.inventory.unrestricted") + || (config.useInventoryCreativeOverride && player.hasCreativeMode())))); + + return session; + } + + /** + * Get the key to use in the map for a player. + * + * @param player the player + * @return the key object + */ + protected String getKey(LocalPlayer player) { + return player.getName(); + } + + /** + * Mark for expiration. + * + * @param player the player + */ + public synchronized void markforExpiration(LocalPlayer player) { + checkNotNull(player); + LocalSession session = find(player); + if (session != null) { + session.update(); + } + } + + /** + * Remove the session for the given player if one exists. + * + * @param player the player + */ + public synchronized void remove(LocalPlayer player) { + checkNotNull(player); + sessions.remove(player.getName()); + } + + /** + * Remove all sessions. + */ + public synchronized void clear() { + sessions.clear(); + } + + /** + * Remove expired sessions with the given session checker. + * + * @param checker the session checker + */ + public synchronized void removeExpired(SessionCheck checker) { + Iterator> it = sessions.entrySet().iterator(); + + while (it.hasNext()) { + Map.Entry entry = it.next(); + if (entry.getValue().hasExpired() && !checker.isOnlinePlayer(entry.getKey())) { + it.remove(); + } + } + } + +}