From e93e50f6d273b940783e7c313610f4cfa7ed15e2 Mon Sep 17 00:00:00 2001 From: ElgarL Date: Sun, 5 Feb 2012 16:30:58 +0000 Subject: Fix world mirroring so it correctly creates data files and data sources for partially mirrored worlds. Fixed world mirroring so it returns the correct data for the requested world --- EssentialsGroupManager/src/Changelog.txt | 4 +- .../org/anjocaido/groupmanager/GroupManager.java | 5 +- .../org/anjocaido/groupmanager/data/DataUnit.java | 9 ++ .../groupmanager/dataholder/GroupsDataHolder.java | 22 ++-- .../groupmanager/dataholder/UsersDataHolder.java | 23 ++-- .../groupmanager/dataholder/WorldDataHolder.java | 102 +++++++++------- .../dataholder/worlds/WorldsHolder.java | 128 +++++++++++++++++---- 7 files changed, 216 insertions(+), 77 deletions(-) diff --git a/EssentialsGroupManager/src/Changelog.txt b/EssentialsGroupManager/src/Changelog.txt index 0ef3add6f..1e520efb3 100644 --- a/EssentialsGroupManager/src/Changelog.txt +++ b/EssentialsGroupManager/src/Changelog.txt @@ -135,4 +135,6 @@ v 1.9: - Track the 'onPlayerChangeWorld' event as some teleports seem to not be triggering a world move. - Catch all errors in badly formatted groups. - Fix a bug with getWorldData return the main world data for all mirrors, instead of the worlds parent data. - - Prevent getAllPlayersPermissions() processing a group more than once. Improves performance when using complex inheritance structures. \ No newline at end of file + - Prevent getAllPlayersPermissions() processing a group more than once. Improves performance when using complex inheritance structures. + - Fix world mirroring so it correctly creates data files and data sources for partially mirrored worlds. + - Fixed world mirroring so it returns the correct data for the requested world \ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java index bb61b2145..ab1ebebbb 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java @@ -1485,7 +1485,7 @@ public class GroupManager extends JavaPlugin { try { worldsHolder.saveChanges(forced); - sender.sendMessage(ChatColor.YELLOW + " The changes were saved."); + sender.sendMessage(ChatColor.YELLOW + " All changes were saved."); } catch (IllegalStateException ex) { sender.sendMessage(ChatColor.RED + ex.getMessage()); } @@ -1522,6 +1522,7 @@ public class GroupManager extends JavaPlugin { } // WORKING config.load(); + globalGroups.load(); worldsHolder.mirrorSetUp(); isLoaded = false; @@ -1538,7 +1539,7 @@ public class GroupManager extends JavaPlugin { sender.sendMessage("The request to world '" + auxString + "' was sent."); } else { worldsHolder.reloadAll(); - sender.sendMessage(ChatColor.YELLOW + " The current world was reloaded."); + sender.sendMessage(ChatColor.YELLOW + " All worlds were reloaded."); } isLoaded = true; diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java index a35b5aeee..03d31b848 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java @@ -65,6 +65,15 @@ public abstract class DataUnit { hash = 71 * hash + (this.name != null ? this.name.toLowerCase().hashCode() : 0); return hash; } + + /** + * Set the data source to point to a new worldDataHolder + * + * @param source + */ + public void setDataSource(WorldDataHolder source) { + this.dataSource = source; + } /** * @return the dataSource diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java index 4fc819245..444939251 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java @@ -17,7 +17,8 @@ public class GroupsDataHolder { /** * Root World name this set of groups is associated with. */ - private String name; + //private String name; + private WorldDataHolder dataSource; private Group defaultGroup = null; private File groupsFile; private boolean haveGroupsChanged = false; @@ -33,17 +34,24 @@ public class GroupsDataHolder { */ protected GroupsDataHolder() { } - - protected void setWorldName(String worldName) { - name = worldName; + + public void setDataSource(WorldDataHolder dataSource) { + this.dataSource = dataSource; + //push this data source to the users, so they pull the correct groups data. + for (Group group : groups.values()) + group.setDataSource(this.dataSource); } + //protected void setWorldName(String worldName) { + // name = worldName; + //} + /** * @return the name */ - public String getWorldName() { - return name; - } + //public String getWorldName() { + // return name; + //} /** * @return the defaultGroup diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java index 37e1c4b43..1d7bbb704 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java @@ -17,7 +17,8 @@ public class UsersDataHolder { /** * Root World name this set of groups is associated with. */ - private String name; + //private String name; + private WorldDataHolder dataSource; private File usersFile; private boolean haveUsersChanged = false; private long timeStampUsers = 0; @@ -32,20 +33,28 @@ public class UsersDataHolder { */ protected UsersDataHolder() { } + + public void setDataSource(WorldDataHolder dataSource) { + this.dataSource = dataSource; + //push this data source to the users, so they pull the correct groups data. + for (User user : users.values()) + user.setDataSource(this.dataSource); + + } /** * @param worldName */ - public void setWorldName(String worldName) { - this.name = worldName; - } + //public void setWorldName(String worldName) { + // this.name = worldName; + //} /** * @return the name */ - public String getWorldName() { - return this.name; - } + //public String getWorldName() { + // return this.name; + //} /** * @return the users diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java index 581f17770..69305f360 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java @@ -80,6 +80,16 @@ public class WorldDataHolder { //this.defaultGroup = defaultGroup; } + + /** + * update the dataSource to point to this object. + * + * This should be called whenever a set of world data is fetched. + */ + public void updateDataSource() { + this.groups.setDataSource(this); + this.users.setDataSource(this); + } /** * Search for a user. If it doesn't exist, create a new one with @@ -465,54 +475,66 @@ public class WorldDataHolder { } //PERMISSIONS NODE - if (thisGroupNode.get("permissions") == null) { - thisGroupNode.put("permissions", new ArrayList()); - } else { - if (thisGroupNode.get("permissions") instanceof List) { - for (Object o : ((List) thisGroupNode.get("permissions"))) { - try { - thisGrp.addPermission(o.toString()); - } catch (NullPointerException e) { - // Ignore this entry as it's null. - //throw new IllegalArgumentException("Invalid permission node in group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); - } - } - } else if (thisGroupNode.get("permissions") instanceof String) { - thisGrp.addPermission((String) thisGroupNode.get("permissions")); + try { + if (thisGroupNode.get("permissions") == null) { + thisGroupNode.put("permissions", new ArrayList()); } else { - throw new IllegalArgumentException("Unknown type of permissions node(Should be String or List) for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + if (thisGroupNode.get("permissions") instanceof List) { + for (Object o : ((List) thisGroupNode.get("permissions"))) { + try { + thisGrp.addPermission(o.toString()); + } catch (NullPointerException e) { + // Ignore this entry as it's null. + //throw new IllegalArgumentException("Invalid permission node in group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } + } + } else if (thisGroupNode.get("permissions") instanceof String) { + thisGrp.addPermission((String) thisGroupNode.get("permissions")); + } else { + throw new IllegalArgumentException("Unknown type of permissions node(Should be String or List) for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } + thisGrp.sortPermissions(); } - thisGrp.sortPermissions(); + } catch (Exception e) { + throw new IllegalArgumentException("Invalid formatting found in permissions section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); } //INFO NODE - if (thisGroupNode.get("info") instanceof Map) { - Map infoNode = (Map) thisGroupNode.get("info"); - if (infoNode != null) { - thisGrp.setVariables(infoNode); - } - } else - throw new IllegalArgumentException("Unknown entry found in Info section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + try { + if (thisGroupNode.get("info") instanceof Map) { + Map infoNode = (Map) thisGroupNode.get("info"); + if (infoNode != null) { + thisGrp.setVariables(infoNode); + } + } else + throw new IllegalArgumentException("Unknown entry found in Info section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } catch (Exception e1) { + throw new IllegalArgumentException("Invalid formatting found in info section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } //END INFO NODE - if (thisGroupNode.get("inheritance") == null || thisGroupNode.get("inheritance") instanceof List) { - Object inheritNode = thisGroupNode.get("inheritance"); - if (inheritNode == null) { - thisGroupNode.put("inheritance", new ArrayList()); - } else if (inheritNode instanceof List) { - List groupsInh = (List) inheritNode; - for (String grp : groupsInh) { - if (inheritance.get(groupKey) == null) { - List thisInherits = new ArrayList(); - inheritance.put(groupKey, thisInherits); - } - inheritance.get(groupKey).add(grp); - - } - } - }else - throw new IllegalArgumentException("Unknown entry found in inheritance section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + try { + if (thisGroupNode.get("inheritance") == null || thisGroupNode.get("inheritance") instanceof List) { + Object inheritNode = thisGroupNode.get("inheritance"); + if (inheritNode == null) { + thisGroupNode.put("inheritance", new ArrayList()); + } else if (inheritNode instanceof List) { + List groupsInh = (List) inheritNode; + for (String grp : groupsInh) { + if (inheritance.get(groupKey) == null) { + List thisInherits = new ArrayList(); + inheritance.put(groupKey, thisInherits); + } + inheritance.get(groupKey).add(grp); + + } + } + }else + throw new IllegalArgumentException("Unknown entry found in inheritance section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } catch (Exception e2) { + throw new IllegalArgumentException("Invalid formatting found in inheritance section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } } } catch (Exception ex) { ex.printStackTrace(); diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java index 6d819daa5..e72118468 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java @@ -10,6 +10,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; @@ -45,7 +46,7 @@ public class WorldsHolder { private Map mirrorsGroup = new HashMap(); private Map mirrorsUser = new HashMap(); - private OverloadedWorldHolder defaultWorld; + //private OverloadedWorldHolder defaultWorld; private String serverDefaultWorldName; private GroupManager plugin; private File worldsFolder; @@ -59,7 +60,7 @@ public class WorldsHolder { // Setup folders and check files exist for the primary world verifyFirstRun(); initialLoad(); - if (defaultWorld == null) { + if (serverDefaultWorldName == null) { throw new IllegalStateException("There is no default group! OMG!"); } } @@ -76,7 +77,7 @@ public class WorldsHolder { private void initialWorldLoading() { //Load the default world loadWorld(serverDefaultWorldName); - defaultWorld = worldsData.get(serverDefaultWorldName); + //defaultWorld = getUpdatedWorldData(serverDefaultWorldName); } private void loadAllSearchedWorlds() { @@ -117,6 +118,8 @@ public class WorldsHolder { mirrorsGroup.clear(); mirrorsUser.clear(); Map mirrorsMap = plugin.getGMConfig().getMirrorsMap(); + + HashSet mirroredWorlds = new HashSet(); if (mirrorsMap != null) { for (String source : mirrorsMap.keySet()) { @@ -140,6 +143,10 @@ public class WorldsHolder { } mirrorsGroup.put(world, getWorldData(source).getName()); mirrorsUser.put(world, getWorldData(source).getName()); + + // Track this world so we can create a datasource for it later + mirroredWorlds.add(o.toString()); + } else GroupManager.logger.log(Level.WARNING, "Mirroring error with " + o.toString() + ". Recursive loop detected!"); } @@ -171,11 +178,13 @@ public class WorldsHolder { if (type.equals("users")) mirrorsUser.put(key.toLowerCase(), getWorldData(source).getName()); } + + // Track this world so we can create a datasource for it later + mirroredWorlds.add(key); + } else GroupManager.logger.log(Level.WARNING, "Mirroring error with " + key + ". Recursive loop detected!"); - - } else { throw new IllegalStateException("Unknown mirroring format for " + key); } @@ -183,6 +192,14 @@ public class WorldsHolder { } } } + + // Create a datasource for any worlds not already loaded + for (String world : mirroredWorlds){ + if (!worldsData.containsKey(world.toLowerCase())) { + setupWorldFolder(world); + loadWorld(world, true); + } + } } } @@ -329,21 +346,55 @@ public class WorldsHolder { public OverloadedWorldHolder getWorldData(String worldName) { String worldNameLowered = worldName.toLowerCase(); - // Return this worlds data - if (worldsData.containsKey(worldNameLowered)) - return worldsData.get(worldNameLowered); + // Find this worlds data + if (worldsData.containsKey(worldNameLowered)) { + + String usersMirror = mirrorsUser.get(worldNameLowered); + String groupsMirror = mirrorsGroup.get(worldNameLowered); + + if (usersMirror != null) { + + // If both are mirrored + if (groupsMirror != null) { + + // if the data sources are the same, return the parent + if (usersMirror == groupsMirror) + return getUpdatedWorldData(usersMirror.toLowerCase()); + + // Both data sources are mirrors, but they are from different parents + // so we return the actual data object. + return getUpdatedWorldData(worldNameLowered); + } + + // Groups isn't a mirror so return this this worlds data source + return getUpdatedWorldData(worldNameLowered); + } + + // users isn't mirrored so we need to return this worlds data source + return getUpdatedWorldData(worldNameLowered); + } - // If groups mirrored return the parent worlds data - if (mirrorsGroup.containsKey(worldNameLowered)) - return worldsData.get(mirrorsGroup.get(worldNameLowered).toLowerCase()); - - // If users mirrored return the parent worlds data - if (mirrorsUser.containsKey(worldNameLowered)) - return worldsData.get(mirrorsUser.get(worldNameLowered).toLowerCase()); - + // Oddly no data source was found for this world so return the default. GroupManager.logger.finest("Requested world " + worldName + " not found or badly mirrored. Returning default world..."); return getDefaultWorld(); } + + /** + * Get the requested world data and update it's dataSource to be relevant for this world + * + * @param worldName + * @return updated world holder + */ + private OverloadedWorldHolder getUpdatedWorldData(String worldName) { + + if (worldsData.containsKey(worldName.toLowerCase())) { + OverloadedWorldHolder data = worldsData.get(worldName.toLowerCase()); + data.updateDataSource(); + return data; + } + return null; + + } /** * Do a matching of playerName, if its found only one player, do @@ -487,18 +538,29 @@ public class WorldsHolder { } /** + * Wrapper for LoadWorld(String,Boolean) for backwards compatibility + * * Load a world from file. * If it already been loaded, summon reload method from dataHolder. * @param worldName */ public void loadWorld(String worldName) { + loadWorld(worldName, false); + } + + /** + * Load a world from file. + * If it already been loaded, summon reload method from dataHolder. + * @param worldName + */ + public void loadWorld(String worldName, Boolean isMirror) { if (worldsData.containsKey(worldName.toLowerCase())) { worldsData.get(worldName.toLowerCase()).reload(); return; } GroupManager.logger.finest("Trying to load world " + worldName + "..."); File thisWorldFolder = new File(worldsFolder, worldName); - if (thisWorldFolder.exists() && thisWorldFolder.isDirectory()) { + if ((isMirror) || (thisWorldFolder.exists() && thisWorldFolder.isDirectory())) { // Setup file handles, if not mirrored File groupsFile = (mirrorsGroup.containsKey(worldName.toLowerCase()))? null : new File(thisWorldFolder, "groups.yml"); @@ -575,17 +637,43 @@ public class WorldsHolder { * @return the defaultWorld */ public OverloadedWorldHolder getDefaultWorld() { - return defaultWorld; + return getUpdatedWorldData(serverDefaultWorldName); } /** - * Returns all physically loaded worlds. + * Returns all physically loaded worlds which have at least + * one of their own data sets for users or groups. + * * @return ArrayList of all loaded worlds */ public ArrayList allWorldsDataList() { ArrayList list = new ArrayList(); for (OverloadedWorldHolder data : worldsData.values()) { - if (!list.contains(data)) { + if ((!list.contains(data)) && (!mirrorsGroup.containsKey(data.getName().toLowerCase()) || !mirrorsUser.containsKey(data.getName().toLowerCase()))) { + + String worldNameLowered = data.getName().toLowerCase(); + String usersMirror = mirrorsUser.get(worldNameLowered); + String groupsMirror = mirrorsGroup.get(worldNameLowered); + + // is users mirrored? + if (usersMirror != null) { + + // If both are mirrored + if (groupsMirror != null) { + + // if the data sources are the same, return the parent + if (usersMirror == groupsMirror) { + if (!list.contains(usersMirror.toLowerCase())) + list.add(worldsData.get(usersMirror.toLowerCase())); + continue; + } + // Both data sources are mirrors, but they are from different parents + // so fall through to add the actual data object. + } + // Groups isn't a mirror so fall through to add this this worlds data source + } + + // users isn't mirrored so we need to add this worlds data source list.add(data); } } -- cgit v1.2.3