PageRenderTime 61ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/main/java/ru/tehkode/permissions/PermissionUser.java

https://gitlab.com/Slind/PermissionsEx
Java | 993 lines | 599 code | 197 blank | 197 comment | 170 complexity | db036c7349ad13eedf08286d468eff72 MD5 | raw file
  1. /*
  2. * PermissionsEx - Permissions plugin for Bukkit
  3. * Copyright (C) 2011 t3hk0d3 http://www.tehkode.ru
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; either version 2
  8. * of the License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. package ru.tehkode.permissions;
  20. import org.bukkit.Bukkit;
  21. import org.bukkit.entity.Player;
  22. import org.bukkit.permissions.Permission;
  23. import ru.tehkode.permissions.events.PermissionEntityEvent;
  24. import ru.tehkode.permissions.exceptions.RankingException;
  25. import java.util.*;
  26. import java.util.concurrent.ConcurrentHashMap;
  27. import java.util.logging.Logger;
  28. /**
  29. * @author code
  30. */
  31. public abstract class PermissionUser extends PermissionEntity {
  32. private final static String PERMISSION_NOT_FOUND = "<not found>"; // used replace null for ConcurrentHashMap
  33. protected Map<String, List<PermissionGroup>> cachedGroups = new HashMap<String, List<PermissionGroup>>();
  34. protected Map<String, String[]> cachedPermissions = new HashMap<String, String[]>();
  35. protected Map<String, String> cachedPrefix = new HashMap<String, String>();
  36. protected Map<String, String> cachedSuffix = new HashMap<String, String>();
  37. protected Map<String, String> cachedAnwsers = new ConcurrentHashMap<String, String>();
  38. protected Map<String, String> cachedOptions = new HashMap<String, String>();
  39. public PermissionUser(String playerName, PermissionManager manager) {
  40. super(playerName, manager);
  41. }
  42. @Override
  43. public void initialize() {
  44. super.initialize();
  45. if (this.manager.getBackend().isCreateUserRecords() && this.isVirtual()) {
  46. this.setGroups(this.getGroups(null), null);
  47. this.save();
  48. }
  49. if (this.isDebug()) {
  50. Logger.getLogger("Minecraft").info("[PermissionsEx] User " + this.getName() + " initialized");
  51. }
  52. }
  53. /**
  54. * Return non-inherited user prefix.
  55. * This means if a user don't have has own prefix
  56. * then empty string or null would be returned
  57. *
  58. * @return prefix as string
  59. */
  60. public String getOwnPrefix() {
  61. return this.getOwnPrefix(null);
  62. }
  63. public abstract String getOwnPrefix(String worldName);
  64. /**
  65. * Return non-inherited suffix prefix.
  66. * This means if a user don't has own suffix
  67. * then empty string or null would be returned
  68. *
  69. * @return suffix as string
  70. */
  71. public final String getOwnSuffix() {
  72. return this.getOwnSuffix(null);
  73. }
  74. public abstract String getOwnSuffix(String worldName);
  75. /**
  76. * Return non-inherited permissions of a user in world
  77. *
  78. * @param world world's name
  79. * @return String array of owned Permissions
  80. */
  81. public abstract String[] getOwnPermissions(String world);
  82. @Override
  83. public String getOption(String optionName, String worldName, String defaultValue) {
  84. String cacheIndex = worldName + "|" + optionName;
  85. if (this.cachedOptions.containsKey(cacheIndex)) {
  86. return this.cachedOptions.get(cacheIndex);
  87. }
  88. String value = this.getOwnOption(optionName, worldName, null);
  89. if (value != null) {
  90. this.cachedOptions.put(cacheIndex, value);
  91. return value;
  92. }
  93. if (worldName != null) { // world inheritance
  94. for (String world : manager.getWorldInheritance(worldName)) {
  95. value = this.getOption(optionName, world, null);
  96. if (value != null) {
  97. this.cachedOptions.put(cacheIndex, value);
  98. return value;
  99. }
  100. }
  101. // Check common space
  102. value = this.getOption(optionName, null, null);
  103. if (value != null) {
  104. this.cachedOptions.put(cacheIndex, value);
  105. return value;
  106. }
  107. }
  108. // Inheritance
  109. for (PermissionGroup group : this.getGroups(worldName)) {
  110. value = group.getOption(optionName, worldName, null);
  111. if (value != null) {
  112. this.cachedOptions.put(cacheIndex, value); // put into cache inherited value
  113. return value;
  114. }
  115. }
  116. // Nothing found
  117. return defaultValue;
  118. }
  119. /**
  120. * Return non-inherited value of specified option for user in world
  121. *
  122. * @param option option string
  123. * @param world world's name
  124. * @param defaultValue default value
  125. * @return option value or defaultValue if option is not set
  126. */
  127. public abstract String getOwnOption(String option, String world, String defaultValue);
  128. /**
  129. * Return non-inherited value of specified option in common space (all worlds).
  130. *
  131. * @param option
  132. * @return option value or empty string if option is not set
  133. */
  134. public String getOwnOption(String option) {
  135. return this.getOwnOption(option, null, null);
  136. }
  137. public String getOwnOption(String option, String world) {
  138. return this.getOwnOption(option, world, null);
  139. }
  140. public int getOwnOptionInteger(String optionName, String world, int defaultValue) {
  141. String option = this.getOwnOption(optionName, world, Integer.toString(defaultValue));
  142. try {
  143. return Integer.parseInt(option);
  144. } catch (NumberFormatException e) {
  145. }
  146. return defaultValue;
  147. }
  148. public boolean getOwnOptionBoolean(String optionName, String world, boolean defaultValue) {
  149. String option = this.getOwnOption(optionName, world, Boolean.toString(defaultValue));
  150. if ("false".equalsIgnoreCase(option)) {
  151. return false;
  152. } else if ("true".equalsIgnoreCase(option)) {
  153. return true;
  154. }
  155. return defaultValue;
  156. }
  157. public double getOwnOptionDouble(String optionName, String world, double defaultValue) {
  158. String option = this.getOwnOption(optionName, world, Double.toString(defaultValue));
  159. try {
  160. return Double.parseDouble(option);
  161. } catch (NumberFormatException e) {
  162. }
  163. return defaultValue;
  164. }
  165. protected abstract String[] getGroupsNamesImpl(String worldName);
  166. /**
  167. * Get group for this user, global inheritance only
  168. *
  169. * @return
  170. */
  171. public PermissionGroup[] getGroups() {
  172. return this.getGroups(null);
  173. }
  174. /**
  175. * Get groups for this user for specified world
  176. *
  177. * @param worldName Name of world
  178. * @return PermissionGroup groups
  179. */
  180. public PermissionGroup[] getGroups(String worldName) {
  181. if (!this.cachedGroups.containsKey(worldName)) {
  182. this.cachedGroups.put(worldName, this.getGroups(worldName, this.manager.getDefaultGroup(worldName)));
  183. }
  184. return this.cachedGroups.get(worldName).toArray(new PermissionGroup[0]);
  185. }
  186. private List<PermissionGroup> getGroups(String worldName, PermissionGroup fallback) {
  187. List<PermissionGroup> groups = new LinkedList<PermissionGroup>();
  188. for (String groupName : this.getGroupsNamesImpl(worldName)) {
  189. if (groupName == null || groupName.isEmpty()) {
  190. continue;
  191. }
  192. PermissionGroup group = this.manager.getGroup(groupName);
  193. if (!this.checkMembership(group, worldName)) {
  194. continue;
  195. }
  196. if (!groups.contains(group)) {
  197. groups.add(group);
  198. }
  199. }
  200. if (worldName != null) { // also check world-inheritance
  201. // world inheritance
  202. for (String world : this.manager.getWorldInheritance(worldName)) {
  203. groups.addAll(this.getGroups(world, null));
  204. }
  205. // common groups
  206. groups.addAll(this.getGroups(null, null));
  207. }
  208. if (groups.isEmpty() && fallback != null) {
  209. groups.add(fallback);
  210. }
  211. if (groups.size() > 1) {
  212. Collections.sort(groups);
  213. }
  214. return groups;
  215. }
  216. public Map<String, PermissionGroup[]> getAllGroups() {
  217. Map<String, PermissionGroup[]> allGroups = new HashMap<String, PermissionGroup[]>();
  218. for (String worldName : this.getWorlds()) {
  219. allGroups.put(worldName, this.getWorldGroups(worldName));
  220. }
  221. allGroups.put(null, this.getWorldGroups(null));
  222. return allGroups;
  223. }
  224. protected PermissionGroup[] getWorldGroups(String worldName) {
  225. List<PermissionGroup> groups = new LinkedList<PermissionGroup>();
  226. for (String groupName : this.getGroupsNamesImpl(worldName)) {
  227. if (groupName == null || groupName.isEmpty()) {
  228. continue;
  229. }
  230. PermissionGroup group = this.manager.getGroup(groupName);
  231. if (!groups.contains(group)) {
  232. groups.add(group);
  233. }
  234. }
  235. Collections.sort(groups);
  236. return groups.toArray(new PermissionGroup[0]);
  237. }
  238. /**
  239. * Get group names, common space only
  240. *
  241. * @return
  242. */
  243. public String[] getGroupsNames() {
  244. return this.getGroupsNames(null);
  245. }
  246. /**
  247. * Get group names in specified world
  248. *
  249. * @return String array of user's group names
  250. */
  251. public String[] getGroupsNames(String worldName) {
  252. List<String> groups = new LinkedList<String>();
  253. for (PermissionGroup group : this.getGroups(worldName)) {
  254. if (group != null) {
  255. groups.add(group.getName());
  256. }
  257. }
  258. return groups.toArray(new String[0]);
  259. }
  260. /**
  261. * Set parent groups for user
  262. *
  263. * @param groups array of parent group names
  264. */
  265. public abstract void setGroups(String[] groups, String worldName);
  266. public void setGroups(String[] groups) {
  267. this.setGroups(groups, null);
  268. }
  269. /**
  270. * Set parent groups for user
  271. *
  272. * @param groups array of parent group objects
  273. */
  274. public void setGroups(PermissionGroup[] parentGroups, String worldName) {
  275. List<String> groups = new LinkedList<String>();
  276. for (PermissionGroup group : parentGroups) {
  277. groups.add(group.getName());
  278. }
  279. this.setGroups(groups.toArray(new String[0]), worldName);
  280. }
  281. public void setGroups(PermissionGroup[] parentGroups) {
  282. this.setGroups(parentGroups, null);
  283. }
  284. /**
  285. * Add user to group
  286. *
  287. * @param groupName group's name as String
  288. */
  289. public void addGroup(String groupName, String worldName) {
  290. if (groupName == null || groupName.isEmpty()) {
  291. return;
  292. }
  293. List<String> groups = new ArrayList<String>(Arrays.asList(this.getGroupsNamesImpl(worldName)));
  294. if (groups.contains(groupName)) {
  295. return;
  296. }
  297. if (this.manager.userAddGroupsLast) {
  298. groups.add(groupName);
  299. } else {
  300. groups.add(0, groupName); //add group to start of list
  301. }
  302. this.setGroups(groups.toArray(new String[0]), worldName);
  303. }
  304. public void addGroup(String groupName) {
  305. this.addGroup(groupName, null);
  306. }
  307. /**
  308. * Add user to group
  309. *
  310. * @param group as PermissionGroup object
  311. */
  312. public void addGroup(PermissionGroup group, String worldName) {
  313. if (group == null) {
  314. return;
  315. }
  316. this.addGroup(group.getName(), worldName);
  317. }
  318. public void addGroup(PermissionGroup group) {
  319. this.addGroup(group, null);
  320. }
  321. public void addGroup(String groupName, String worldName, long lifetime) {
  322. this.addGroup(groupName, worldName);
  323. if (lifetime > 0) {
  324. this.setOption("group-" + groupName + "-until", Long.toString(System.currentTimeMillis() / 1000 + lifetime), worldName);
  325. }
  326. }
  327. /**
  328. * Remove user from group
  329. *
  330. * @param groupName group's name as String
  331. */
  332. public void removeGroup(String groupName, String worldName) {
  333. if (groupName == null || groupName.isEmpty()) {
  334. return;
  335. }
  336. List<String> groups = new ArrayList<String>(Arrays.asList(this.getGroupsNamesImpl(worldName)));
  337. if (!groups.contains(groupName)) {
  338. return;
  339. }
  340. groups.remove(groupName);
  341. this.setGroups(groups.toArray(new String[0]), worldName);
  342. }
  343. public void removeGroup(String groupName) {
  344. this.removeGroup(this.manager.getGroup(groupName));
  345. }
  346. /**
  347. * Remove user from group
  348. *
  349. * @param group group as PermissionGroup object
  350. */
  351. public void removeGroup(PermissionGroup group, String worldName) {
  352. if (group == null) {
  353. return;
  354. }
  355. this.removeGroup(group.getName(), worldName);
  356. }
  357. public void removeGroup(PermissionGroup group) {
  358. for (String worldName : this.getWorlds()) {
  359. this.removeGroup(group, worldName);
  360. }
  361. this.removeGroup(group, null);
  362. }
  363. /**
  364. * Check if this user is member of group or one of its descendant groups (optionally)
  365. *
  366. * @param group group as PermissionGroup object
  367. * @param worldName
  368. * @param checkInheritance if true then descendant groups of the given group would be checked too
  369. * @return true on success, false otherwise
  370. */
  371. public boolean inGroup(PermissionGroup group, String worldName, boolean checkInheritance) {
  372. for (PermissionGroup parentGroup : this.getGroups(worldName)) {
  373. if (parentGroup.equals(group)) {
  374. return true;
  375. }
  376. if (checkInheritance && parentGroup.isChildOf(group, worldName, true)) {
  377. return true;
  378. }
  379. }
  380. return false;
  381. }
  382. public boolean inGroup(PermissionGroup group, boolean checkInheritance) {
  383. for (String worldName : this.getWorlds()) {
  384. if (this.inGroup(group, worldName, checkInheritance)) {
  385. return true;
  386. }
  387. }
  388. return this.inGroup(group, null, checkInheritance);
  389. }
  390. /**
  391. * Check if this user is member of group or one of its descendant groups (optionally)
  392. *
  393. * @param groupName group's name to check
  394. * @param worldName
  395. * @param checkInheritance if true than descendant groups of specified group would be checked too
  396. * @return true on success, false otherwise
  397. */
  398. public boolean inGroup(String groupName, String worldName, boolean checkInheritance) {
  399. return this.inGroup(this.manager.getGroup(groupName), worldName, checkInheritance);
  400. }
  401. public boolean inGroup(String groupName, boolean checkInheritance) {
  402. return this.inGroup(this.manager.getGroup(groupName), checkInheritance);
  403. }
  404. /**
  405. * Check if this user is member of group or one of its descendant groups
  406. *
  407. * @param group
  408. * @param worldName
  409. * @return true on success, false otherwise
  410. */
  411. public boolean inGroup(PermissionGroup group, String worldName) {
  412. return this.inGroup(group, worldName, true);
  413. }
  414. public boolean inGroup(PermissionGroup group) {
  415. return this.inGroup(group, true);
  416. }
  417. /**
  418. * Checks if this user is member of specified group or one of its descendant groups
  419. *
  420. * @param group group's name
  421. * @return true on success, false otherwise
  422. */
  423. public boolean inGroup(String groupName, String worldName) {
  424. return this.inGroup(this.manager.getGroup(groupName), worldName, true);
  425. }
  426. public boolean inGroup(String groupName) {
  427. return this.inGroup(groupName, true);
  428. }
  429. /**
  430. * Promotes user in specified ladder.
  431. * If user is not member of the ladder RankingException will be thrown
  432. * If promoter is not null and he is member of the ladder and
  433. * his rank is lower then user's RankingException will be thrown too.
  434. * If there is no group to promote the user to RankingException would be thrown
  435. *
  436. * @param promoter null if action is performed from console or by a plugin
  437. * @param ladderName Ladder name
  438. * @throws RankingException
  439. */
  440. public PermissionGroup promote(PermissionUser promoter, String ladderName) throws RankingException {
  441. if (ladderName == null || ladderName.isEmpty()) {
  442. ladderName = "default";
  443. }
  444. int promoterRank = getPromoterRankAndCheck(promoter, ladderName);
  445. int rank = this.getRank(ladderName);
  446. PermissionGroup sourceGroup = this.getRankLadders().get(ladderName);
  447. PermissionGroup targetGroup = null;
  448. for (Map.Entry<Integer, PermissionGroup> entry : this.manager.getRankLadder(ladderName).entrySet()) {
  449. int groupRank = entry.getValue().getRank();
  450. if (groupRank >= rank) { // group have equal or lower than current rank
  451. continue;
  452. }
  453. if (groupRank <= promoterRank) { // group have higher rank than promoter
  454. continue;
  455. }
  456. if (targetGroup != null && groupRank <= targetGroup.getRank()) { // group have higher rank than target group
  457. continue;
  458. }
  459. targetGroup = entry.getValue();
  460. }
  461. if (targetGroup == null) {
  462. throw new RankingException("User are not promoteable", this, promoter);
  463. }
  464. this.swapGroups(sourceGroup, targetGroup);
  465. this.callEvent(PermissionEntityEvent.Action.RANK_CHANGED);
  466. return targetGroup;
  467. }
  468. /**
  469. * Demotes user in specified ladder.
  470. * If user is not member of the ladder RankingException will be thrown
  471. * If demoter is not null and he is member of the ladder and
  472. * his rank is lower then user's RankingException will be thrown too.
  473. * If there is no group to demote the user to RankingException would be thrown
  474. *
  475. * @param promoter Specify null if action performed from console or by plugin
  476. * @param ladderName
  477. * @throws RankingException
  478. */
  479. public PermissionGroup demote(PermissionUser demoter, String ladderName) throws RankingException {
  480. if (ladderName == null || ladderName.isEmpty()) {
  481. ladderName = "default";
  482. }
  483. int promoterRank = getPromoterRankAndCheck(demoter, ladderName);
  484. int rank = this.getRank(ladderName);
  485. PermissionGroup sourceGroup = this.getRankLadders().get(ladderName);
  486. PermissionGroup targetGroup = null;
  487. for (Map.Entry<Integer, PermissionGroup> entry : this.manager.getRankLadder(ladderName).entrySet()) {
  488. int groupRank = entry.getValue().getRank();
  489. if (groupRank <= rank) { // group have equal or higher than current rank
  490. continue;
  491. }
  492. if (groupRank <= promoterRank) { // group have higher rank than promoter
  493. continue;
  494. }
  495. if (targetGroup != null && groupRank >= targetGroup.getRank()) { // group have lower rank than target group
  496. continue;
  497. }
  498. targetGroup = entry.getValue();
  499. }
  500. if (targetGroup == null) {
  501. throw new RankingException("User are not demoteable", this, demoter);
  502. }
  503. this.swapGroups(sourceGroup, targetGroup);
  504. this.callEvent(PermissionEntityEvent.Action.RANK_CHANGED);
  505. return targetGroup;
  506. }
  507. /**
  508. * Check if the user is in the specified ladder
  509. *
  510. * @param ladder Ladder name
  511. * @return true on success, false otherwise
  512. */
  513. public boolean isRanked(String ladder) {
  514. return (this.getRank(ladder) > 0);
  515. }
  516. /**
  517. * Return user rank in specified ladder
  518. *
  519. * @param ladder Ladder name
  520. * @return rank as int
  521. */
  522. public int getRank(String ladder) {
  523. Map<String, PermissionGroup> ladders = this.getRankLadders();
  524. if (ladders.containsKey(ladder)) {
  525. return ladders.get(ladder).getRank();
  526. }
  527. return 0;
  528. }
  529. /**
  530. * Return user's group in specified ladder
  531. *
  532. * @param ladder Ladder name
  533. * @return PermissionGroup object of ranked ladder group
  534. */
  535. public PermissionGroup getRankLadderGroup(String ladder) {
  536. if (ladder == null || ladder.isEmpty()) {
  537. ladder = "default";
  538. }
  539. return this.getRankLadders().get(ladder);
  540. }
  541. /**
  542. * Return all ladders the user is participating in
  543. *
  544. * @return Map, key - name of ladder, group - corresponding group of that ladder
  545. */
  546. public Map<String, PermissionGroup> getRankLadders() {
  547. Map<String, PermissionGroup> ladders = new HashMap<String, PermissionGroup>();
  548. for (PermissionGroup group : this.getGroups()) {
  549. if (!group.isRanked()) {
  550. continue;
  551. }
  552. ladders.put(group.getRankLadder(), group);
  553. }
  554. return ladders;
  555. }
  556. @Override
  557. public String[] getPermissions(String worldName) {
  558. if (!this.cachedPermissions.containsKey(worldName)) {
  559. List<String> permissions = new LinkedList<String>();
  560. this.getInheritedPermissions(worldName, permissions, true, false);
  561. this.cachedPermissions.put(worldName, permissions.toArray(new String[0]));
  562. }
  563. return this.cachedPermissions.get(worldName);
  564. }
  565. @Override
  566. public void addPermission(String permission, String worldName) {
  567. List<String> permissions = new LinkedList<String>(Arrays.asList(this.getOwnPermissions(worldName)));
  568. if (permissions.contains(permission)) { // remove old permission
  569. permissions.remove(permission);
  570. }
  571. // add permission on the top of list
  572. permissions.add(0, permission);
  573. this.setPermissions(permissions.toArray(new String[0]), worldName);
  574. }
  575. @Override
  576. public void removePermission(String permission, String worldName) {
  577. List<String> permissions = new LinkedList<String>(Arrays.asList(this.getOwnPermissions(worldName)));
  578. permissions.remove(permission);
  579. this.setPermissions(permissions.toArray(new String[0]), worldName);
  580. }
  581. protected void getInheritedPermissions(String worldName, List<String> permissions, boolean groupInheritance, boolean worldInheritance) {
  582. permissions.addAll(Arrays.asList(this.getTimedPermissions(worldName)));
  583. permissions.addAll(Arrays.asList(this.getOwnPermissions(worldName)));
  584. if (worldName != null) {
  585. // World inheritance
  586. for (String parentWorld : this.manager.getWorldInheritance(worldName)) {
  587. getInheritedPermissions(parentWorld, permissions, false, true);
  588. }
  589. // Common permissions
  590. if (!worldInheritance) { // skip common world permissions if we are inside world-inheritance tree
  591. getInheritedPermissions(null, permissions, false, true);
  592. }
  593. }
  594. // Group inhertance
  595. if (groupInheritance) {
  596. for (PermissionGroup parentGroup : this.getGroups(worldName)) {
  597. parentGroup.getInheritedPermissions(worldName, permissions, true, false, new HashSet<PermissionGroup>());
  598. }
  599. }
  600. // Add all child nodes
  601. for (String node : permissions.toArray(new String[0])) {
  602. this.getInheritedChildPermissions(node, permissions);
  603. }
  604. }
  605. protected void getInheritedChildPermissions(String perm, List<String> list) {
  606. getInheritedChildPermissions(perm, list, false);
  607. }
  608. protected void getInheritedChildPermissions(String perm, List<String> list, boolean invert) {
  609. if (perm.startsWith("-")) {
  610. invert = !invert;
  611. perm = perm.substring(1);
  612. }
  613. getInheritedChildPermissions(Bukkit.getPluginManager().getPermission(perm), list, invert);
  614. }
  615. protected void getInheritedChildPermissions(Permission perm, List<String> list, boolean invert) {
  616. if (perm == null) {
  617. return;
  618. }
  619. for (Map.Entry<String, Boolean> entry : perm.getChildren().entrySet()) {
  620. boolean has = entry.getValue().booleanValue() ^ invert;
  621. String node = (has ? "" : "-") + entry.getKey();
  622. if (!list.contains(node)) {
  623. list.add(node);
  624. getInheritedChildPermissions(node, list, !has);
  625. }
  626. }
  627. }
  628. @Override
  629. public void addTimedPermission(String permission, String world, int lifeTime) {
  630. super.addTimedPermission(permission, world, lifeTime);
  631. this.clearCache();
  632. }
  633. @Override
  634. public void removeTimedPermission(String permission, String world) {
  635. super.removeTimedPermission(permission, world);
  636. this.clearCache();
  637. }
  638. protected int getPromoterRankAndCheck(PermissionUser promoter, String ladderName) throws RankingException {
  639. if (!this.isRanked(ladderName)) { // not ranked
  640. throw new RankingException("User are not in this ladder", this, promoter);
  641. }
  642. int rank = this.getRank(ladderName);
  643. int promoterRank = 0;
  644. if (promoter != null && promoter.isRanked(ladderName)) {
  645. promoterRank = promoter.getRank(ladderName);
  646. if (promoterRank >= rank) {
  647. throw new RankingException("Promoter don't have high enough rank to change " + this.getName() + "'s rank", this, promoter);
  648. }
  649. }
  650. return promoterRank;
  651. }
  652. protected void swapGroups(PermissionGroup src, PermissionGroup dst) {
  653. List<PermissionGroup> groups = new ArrayList<PermissionGroup>(Arrays.asList(this.getGroups()));
  654. groups.remove(src);
  655. groups.add(dst);
  656. this.setGroups(groups.toArray(new PermissionGroup[0]));
  657. }
  658. @Override
  659. public String getPrefix(String worldName) {
  660. // @TODO This method should be refactored
  661. if (!this.cachedPrefix.containsKey(worldName)) {
  662. String localPrefix = this.getOwnPrefix(worldName);
  663. if (worldName != null && (localPrefix == null || localPrefix.isEmpty())) {
  664. // World-inheritance
  665. for (String parentWorld : this.manager.getWorldInheritance(worldName)) {
  666. String prefix = this.getOwnPrefix(parentWorld);
  667. if (prefix != null && !prefix.isEmpty()) {
  668. localPrefix = prefix;
  669. break;
  670. }
  671. }
  672. // Common space
  673. if (localPrefix == null || localPrefix.isEmpty()) {
  674. localPrefix = this.getOwnPrefix(null);
  675. }
  676. }
  677. if (localPrefix == null || localPrefix.isEmpty()) {
  678. for (PermissionGroup group : this.getGroups(worldName)) {
  679. localPrefix = group.getPrefix(worldName);
  680. if (localPrefix != null && !localPrefix.isEmpty()) {
  681. break;
  682. }
  683. }
  684. }
  685. if (localPrefix == null) { // just for NPE safety
  686. localPrefix = "";
  687. }
  688. this.cachedPrefix.put(worldName, localPrefix);
  689. }
  690. return this.cachedPrefix.get(worldName);
  691. }
  692. @Override
  693. public boolean has(String permission) {
  694. Player player = Bukkit.getServer().getPlayer(this.getName());
  695. if (player != null) {
  696. return this.has(permission, player.getWorld().getName());
  697. }
  698. return super.has(permission);
  699. }
  700. @Override
  701. public String getSuffix(String worldName) {
  702. // @TODO This method should be refactored
  703. if (!this.cachedSuffix.containsKey(worldName)) {
  704. String localSuffix = this.getOwnSuffix(worldName);
  705. if (worldName != null && (localSuffix == null || localSuffix.isEmpty())) {
  706. // World-inheritance
  707. for (String parentWorld : this.manager.getWorldInheritance(worldName)) {
  708. String suffix = this.getOwnSuffix(parentWorld);
  709. if (suffix != null && !suffix.isEmpty()) {
  710. localSuffix = suffix;
  711. break;
  712. }
  713. }
  714. // Common space
  715. if (localSuffix == null || localSuffix.isEmpty()) {
  716. localSuffix = this.getOwnSuffix(null);
  717. }
  718. }
  719. if (localSuffix == null || localSuffix.isEmpty()) {
  720. for (PermissionGroup group : this.getGroups(worldName)) {
  721. localSuffix = group.getSuffix(worldName);
  722. if (localSuffix != null && !localSuffix.isEmpty()) {
  723. break;
  724. }
  725. }
  726. }
  727. if (localSuffix == null) { // just for NPE safety
  728. localSuffix = "";
  729. }
  730. this.cachedSuffix.put(worldName, localSuffix);
  731. }
  732. return this.cachedSuffix.get(worldName);
  733. }
  734. @Override
  735. public String getMatchingExpression(String permission, String world) {
  736. String cacheId = world + ":" + permission;
  737. if (!this.cachedAnwsers.containsKey(cacheId)) {
  738. String result = super.getMatchingExpression(permission, world);
  739. if (result == null) { // this is actually kinda dirty clutch
  740. result = PERMISSION_NOT_FOUND; // ConcurrentHashMap deny storage of null values
  741. }
  742. this.cachedAnwsers.put(cacheId, result);
  743. }
  744. String result = this.cachedAnwsers.get(cacheId);
  745. if (PERMISSION_NOT_FOUND.equals(result)) {
  746. result = null;
  747. }
  748. return result;
  749. }
  750. protected void clearCache() {
  751. this.cachedPrefix.clear();
  752. this.cachedSuffix.clear();
  753. this.cachedGroups.clear();
  754. this.cachedPermissions.clear();
  755. this.cachedAnwsers.clear();
  756. this.cachedOptions.clear();
  757. }
  758. @Override
  759. public void setPrefix(String prefix, String worldName) {
  760. this.clearCache();
  761. }
  762. @Override
  763. public void setSuffix(String postfix, String worldName) {
  764. this.clearCache();
  765. }
  766. @Override
  767. public void remove() {
  768. this.clearCache();
  769. this.callEvent(PermissionEntityEvent.Action.REMOVED);
  770. }
  771. @Override
  772. public void save() {
  773. this.clearCache();
  774. this.callEvent(PermissionEntityEvent.Action.SAVED);
  775. }
  776. @Override
  777. public boolean explainExpression(String expression) {
  778. if (expression == null && this.manager.allowOps) {
  779. Player player = Bukkit.getServer().getPlayer(this.getName());
  780. if (player != null && player.isOp()) {
  781. return true;
  782. }
  783. }
  784. return super.explainExpression(expression);
  785. }
  786. protected boolean checkMembership(PermissionGroup group, String worldName) {
  787. int groupLifetime = this.getOwnOptionInteger("group-" + group.getName() + "-until", worldName, 0);
  788. if (groupLifetime > 0 && groupLifetime < System.currentTimeMillis() / 1000) { // check for expiration
  789. this.setOption("group-" + group.getName() + "-until", null, worldName); // remove option
  790. this.removeGroup(group, worldName); // remove membership
  791. // @TODO Make notification of player about expired memebership
  792. return false;
  793. }
  794. return true;
  795. }
  796. }