1 43 package net.jforum.repository; 44 45 import java.text.SimpleDateFormat ; 46 import java.util.ArrayList ; 47 import java.util.HashMap ; 48 import java.util.Iterator ; 49 import java.util.List ; 50 import java.util.Map ; 51 import java.util.Set ; 52 import java.util.TreeSet ; 53 54 import org.apache.log4j.Logger; 55 56 import net.jforum.SessionFacade; 57 import net.jforum.cache.CacheEngine; 58 import net.jforum.cache.Cacheable; 59 import net.jforum.dao.CategoryDAO; 60 import net.jforum.dao.ConfigDAO; 61 import net.jforum.dao.DataAccessDriver; 62 import net.jforum.dao.ForumDAO; 63 import net.jforum.dao.UserDAO; 64 import net.jforum.entities.Category; 65 import net.jforum.entities.Config; 66 import net.jforum.entities.Forum; 67 import net.jforum.entities.LastPostInfo; 68 import net.jforum.entities.MostUsersEverOnline; 69 import net.jforum.entities.Post; 70 import net.jforum.entities.Topic; 71 import net.jforum.entities.User; 72 import net.jforum.exceptions.CategoryNotFoundException; 73 import net.jforum.exceptions.DatabaseException; 74 import net.jforum.security.PermissionControl; 75 import net.jforum.security.SecurityConstants; 76 import net.jforum.util.CategoryOrderComparator; 77 import net.jforum.util.preferences.ConfigKeys; 78 import net.jforum.util.preferences.SystemGlobals; 79 80 89 public class ForumRepository implements Cacheable 90 { 91 private static CacheEngine cache; 92 private static ForumRepository instance; 93 private static Logger logger = Logger.getLogger(ForumRepository.class); 94 95 private static final String FQN = "forumRepository"; 96 private static final String CATEGORIES_SET = "categoriesSet"; 97 private static final String RELATION = "relationForums"; 98 private static final String FQN_TOTAL_TOPICS = FQN + "/totalTopics"; 99 private static final String FQN_MODERATORS = FQN + "/moderators"; 100 private static final String TOTAL_MESSAGES = "totalMessages"; 101 private static final String MOST_USERS_ONLINE = "mostUsersEverOnline"; 102 private static final String LOADED = "loaded"; 103 private static final String LAST_USER = "lastUser"; 104 private static final String TOTAL_USERS = "totalUsers"; 105 106 109 public void setCacheEngine(CacheEngine engine) 110 { 111 cache = engine; 112 } 113 114 123 public synchronized static void start(ForumDAO fm, 124 CategoryDAO cm, 125 ConfigDAO configModel) throws Exception 126 { 127 instance = new ForumRepository(); 128 129 if (cache.get(FQN, LOADED) == null) { 130 instance.loadCategories(cm); 131 instance.loadForums(fm); 132 instance.loadMostUsersEverOnline(configModel); 133 instance.loadUsersInfo(); 134 135 Integer i = (Integer )cache.get(FQN, TOTAL_MESSAGES); 136 137 if (i == null) { 138 cache.add(FQN, TOTAL_MESSAGES, new Integer (0)); 139 } 140 141 cache.add(FQN, LOADED, "1"); 142 } 143 } 144 145 156 public static Category getCategory(int categoryId) 157 { 158 return getCategory(SessionFacade.getUserSession().getUserId(), categoryId); 159 } 160 161 170 public static Category getCategory(int userId, int categoryId) 171 { 172 if (!isCategoryAccessible(userId, categoryId)) { 173 return null; 174 } 175 176 return (Category)cache.get(FQN, Integer.toString(categoryId)); 177 } 178 179 public static Category getCategory(PermissionControl pc, int categoryId) 180 { 181 if (!isCategoryAccessible(pc, categoryId)) { 182 return null; 183 } 184 185 return (Category)cache.get(FQN, Integer.toString(categoryId)); 186 } 187 188 public static Category retrieveCategory(int categoryId) 189 { 190 return (Category)cache.get(FQN, Integer.toString(categoryId)); 191 } 192 193 200 public static boolean isCategoryAccessible(int userId, int categoryId) 201 { 202 return isCategoryAccessible(SecurityRepository.get(userId), categoryId); 203 } 204 205 211 public static boolean isCategoryAccessible(int categoryId) 212 { 213 return isCategoryAccessible(SessionFacade.getUserSession().getUserId(), categoryId); 214 } 215 216 224 public static boolean isCategoryAccessible(PermissionControl pc, int categoryId) 225 { 226 return pc.canAccess(SecurityConstants.PERM_CATEGORY, Integer.toString(categoryId)); 227 } 228 229 234 public static List getAllCategories(int userId) 235 { 236 PermissionControl pc = SecurityRepository.get(userId); 237 List l = new ArrayList (); 238 239 Set categoriesSet = (Set )cache.get(FQN, CATEGORIES_SET); 240 241 if (categoriesSet == null) { 242 logger.warn("Categories set returned null from the cache. Trying to reload"); 243 244 try { 245 ForumRepository.instance.loadCategories(DataAccessDriver.getInstance().newCategoryDAO()); 246 ForumRepository.instance.loadForums(DataAccessDriver.getInstance().newForumDAO()); 247 } 248 catch (Exception e) { 249 throw new CategoryNotFoundException("Failed to get the category", e); 250 } 251 252 categoriesSet = (Set )cache.get(FQN, CATEGORIES_SET); 253 254 if (categoriesSet == null) { 255 throw new CategoryNotFoundException("Could not find all categories. There must be a problem " 256 + "with the cache"); 257 } 258 } 259 260 for (Iterator iter = categoriesSet.iterator(); iter.hasNext(); ) { 261 Category c = (Category)iter.next(); 262 263 if (isCategoryAccessible(pc, c.getId())) { 264 l.add(c); 265 } 266 } 267 268 return l; 269 } 270 271 280 public static List getAllCategories() 281 { 282 return getAllCategories(SessionFacade.getUserSession().getUserId()); 283 } 284 285 private static Category findCategoryByOrder(int order) 286 { 287 for (Iterator iter = ((Set )cache.get(FQN, CATEGORIES_SET)).iterator(); iter.hasNext(); ) { 288 Category c = (Category)iter.next(); 289 if (c.getOrder() == order) { 290 return c; 291 } 292 } 293 294 return null; 295 } 296 297 304 public synchronized static void reloadCategory(Category c) 305 { 306 Category current = (Category)cache.get(FQN, Integer.toString(c.getId())); 307 Category currentAtOrder = findCategoryByOrder(c.getOrder()); 308 309 Set tmpSet = new TreeSet (new CategoryOrderComparator()); 310 tmpSet.addAll((Set )cache.get(FQN, CATEGORIES_SET)); 311 312 if (currentAtOrder != null) { 313 tmpSet.remove(currentAtOrder); 314 cache.remove(FQN, Integer.toString(currentAtOrder.getId())); 315 } 316 317 tmpSet.add(c); 318 cache.add(FQN, Integer.toString(c.getId()), c); 319 320 if (currentAtOrder != null && c.getId() != currentAtOrder.getId()) { 321 tmpSet.remove(current); 322 currentAtOrder.setOrder(current.getOrder()); 323 tmpSet.add(currentAtOrder); 324 325 cache.add(FQN, Integer.toString(currentAtOrder.getId()), currentAtOrder); 326 } 327 328 cache.add(FQN, CATEGORIES_SET, tmpSet); 329 } 330 331 336 public synchronized static void refreshCategory(Category c) 337 { 338 cache.add(FQN, Integer.toString(c.getId()), c); 339 Set s = (Set )cache.get(FQN, CATEGORIES_SET); 340 s.remove(c); 341 s.add(c); 342 cache.add(FQN, CATEGORIES_SET, s); 343 } 344 345 public synchronized static void refreshForum(Forum forum) 346 { 347 Category c = retrieveCategory(forum.getCategoryId()); 348 c.addForum(forum); 349 refreshCategory(c); 350 } 351 352 357 public synchronized static void removeCategory(Category c) 358 { 359 cache.remove(FQN, Integer.toString(c.getId())); 360 361 Set s = (Set )cache.get(FQN, CATEGORIES_SET); 362 s.remove(c); 363 cache.add(FQN, CATEGORIES_SET, s); 364 365 Map m = (Map )cache.get(FQN, RELATION); 366 for (Iterator iter = m.values().iterator(); iter.hasNext(); ) { 367 if (Integer.parseInt((String )iter.next()) == c.getId()) { 368 iter.remove(); 369 } 370 } 371 372 cache.add(FQN, RELATION, m); 373 } 374 375 379 public synchronized static void addCategory(Category c) 380 { 381 String categoryId = Integer.toString(c.getId()); 382 cache.add(FQN, categoryId, c); 383 384 Set s = (Set )cache.get(FQN, CATEGORIES_SET); 385 386 if (s == null) { 387 s = new TreeSet (new CategoryOrderComparator()); 388 } 389 390 s.add(c); 391 cache.add(FQN, CATEGORIES_SET, s); 392 393 Map relation = (Map )cache.get(FQN, RELATION); 394 if (relation == null) { 395 relation = new HashMap (); 396 } 397 398 for (Iterator iter = c.getForums().iterator(); iter.hasNext(); ) { 399 Forum f = (Forum)iter.next(); 400 relation.put(Integer.toString(f.getId()), categoryId); 401 } 402 403 cache.add(FQN, RELATION, relation); 404 } 405 406 413 public static Forum getForum(int forumId) 414 { 415 String categoryId = (String )((Map )cache.get(FQN, RELATION)).get(Integer.toString(forumId)); 416 417 if (categoryId != null) { 418 Category category = (Category)cache.get(FQN, categoryId); 419 420 if (isCategoryAccessible(category.getId())) { 421 return category.getForum(forumId); 422 } 423 } 424 425 return null; 426 } 427 428 public static boolean isForumAccessible(int forumId) 429 { 430 return isForumAccessible(SessionFacade.getUserSession().getUserId(), forumId); 431 } 432 433 public static boolean isForumAccessible(int userId, int forumId) 434 { 435 int categoryId = Integer.parseInt((String )((Map )cache.get(FQN, RELATION)).get(Integer.toString(forumId))); 436 return isForumAccessible(userId, categoryId, forumId); 437 } 438 439 public static boolean isForumAccessible(int userId, int categoryId, int forumId) 440 { 441 return ((Category)cache.get(FQN, Integer.toString(categoryId))).getForum(userId, forumId) != null; 442 } 443 444 449 public synchronized static void addForum(Forum forum) 450 { 451 String categoryId = Integer.toString(forum.getCategoryId()); 452 453 Category c = (Category)cache.get(FQN, categoryId); 454 c.addForum(forum); 455 cache.add(FQN, categoryId, c); 456 457 Map m = (Map )cache.get(FQN, RELATION); 458 m.put(Integer.toString(forum.getId()), categoryId); 459 cache.add(FQN, RELATION, m); 460 461 Set s = (Set )cache.get(FQN, CATEGORIES_SET); 462 cache.add(FQN, CATEGORIES_SET, s); 463 } 464 465 470 public synchronized static void removeForum(Forum forum) 471 { 472 String id = Integer.toString(forum.getId()); 473 Map m = (Map )cache.get(FQN, RELATION); 474 m.remove(id); 475 cache.add(FQN, RELATION, m); 476 477 id = Integer.toString(forum.getCategoryId()); 478 479 Category c = (Category)cache.get(FQN, id); 480 c.removeForum(forum.getId()); 481 cache.add(FQN, id, c); 482 483 Set s = (Set )cache.get(FQN, CATEGORIES_SET); 484 cache.add(FQN, CATEGORIES_SET, s); 485 } 486 487 497 public static synchronized void reloadForum(int forumId) throws Exception 498 { 499 Forum f = DataAccessDriver.getInstance().newForumDAO().selectById(forumId); 500 501 if (((Map )cache.get(FQN, RELATION)).containsKey(Integer.toString(forumId))) { 502 String id = Integer.toString(f.getCategoryId()); 503 Category c = (Category)cache.get(FQN, id); 504 505 f.setLastPostInfo(null); 506 f.setLastPostInfo(ForumRepository.getLastPostInfo(f)); 507 c.reloadForum(f); 508 509 cache.add(FQN, id, c); 510 Set s = (Set )cache.get(FQN, CATEGORIES_SET); 511 cache.add(FQN, CATEGORIES_SET, s); 512 } 513 514 getTotalMessages(true); 515 } 516 517 public static synchronized void updateForumStats(Topic t, User u, Post p) 518 { 519 String f = Integer.toString(t.getForumId()); 520 521 if (((Map )cache.get(FQN, RELATION)).containsKey(f)) { 522 Forum forum = getForum(t.getForumId()); 523 524 SimpleDateFormat df = new SimpleDateFormat (SystemGlobals.getValue(ConfigKeys.DATE_TIME_FORMAT)); 525 526 LastPostInfo lpi = forum.getLastPostInfo(); 527 528 if (lpi == null) { 529 lpi = new LastPostInfo(); 530 } 531 532 lpi.setPostId(p.getId()); 533 lpi.setPostDate(df.format(p.getTime())); 534 lpi.setPostTimeMillis(p.getTime().getTime()); 535 lpi.setTopicId(t.getId()); 536 lpi.setTopicReplies(t.getTotalReplies()); 537 lpi.setUserId(u.getId()); 538 lpi.setUsername(u.getUsername()); 539 540 forum.setLastPostInfo(lpi); 541 542 if (t.getTotalReplies() == 0) { 543 forum.setTotalTopics(forum.getTotalTopics() + 1); 544 } 545 else { 546 forum.setTotalPosts(forum.getTotalPosts() + 1); 547 } 548 549 Category c = retrieveCategory(forum.getCategoryId()); 550 c.reloadForum(forum); 551 552 refreshCategory(c); 553 } 554 } 555 556 561 public static LastPostInfo getLastPostInfo(Forum forum) throws Exception 562 { 563 LastPostInfo lpi = forum.getLastPostInfo(); 564 565 if (lpi == null || !forum.getLastPostInfo().hasInfo()) { 566 lpi = DataAccessDriver.getInstance().newForumDAO().getLastPostInfo(forum.getId()); 567 forum.setLastPostInfo(lpi); 568 } 569 570 return lpi; 571 } 572 573 580 public static LastPostInfo getLastPostInfo(int forumId) throws Exception 581 { 582 return getLastPostInfo(getForum(forumId)); 583 } 584 585 590 public static List getModeratorList(int forumId) 591 { 592 List l = (List )cache.get(FQN_MODERATORS, Integer.toString(forumId)); 593 594 if (l == null) { 595 synchronized (FQN_MODERATORS) { 596 try { 597 l = DataAccessDriver.getInstance().newForumDAO().getModeratorList(forumId); 598 cache.add(FQN_MODERATORS, Integer.toString(forumId), l); 599 } 600 catch (Exception e) { 601 throw new DatabaseException(e); 602 } 603 } 604 } 605 606 return l; 607 } 608 609 public static void clearModeratorList() 610 { 611 cache.remove(FQN_MODERATORS); 612 } 613 614 public static User lastRegisteredUser() 615 { 616 return (User)cache.get(FQN, LAST_USER); 617 } 618 619 public static void setLastRegisteredUser(User user) 620 { 621 cache.add(FQN, LAST_USER, user); 622 } 623 624 public static Integer totalUsers() 625 { 626 return (Integer )cache.get(FQN, TOTAL_USERS); 627 } 628 629 public static void incrementTotalUsers() 630 { 631 Integer i = (Integer )cache.get(FQN, TOTAL_USERS); 632 633 if (i == null) { 634 i = new Integer (0); 635 } 636 637 cache.add(FQN,TOTAL_USERS, new Integer (i.intValue() + 1)); 638 } 639 640 651 public static int getTotalTopics(int forumId, boolean fromDb) throws Exception 652 { 653 Integer i = (Integer )cache.get(FQN_TOTAL_TOPICS, Integer.toString(forumId)); 654 int total = (i != null ? i.intValue() : 0); 655 656 if (fromDb || total == -1) { 657 total = DataAccessDriver.getInstance().newForumDAO().getTotalTopics(forumId); 658 cache.add(FQN_TOTAL_TOPICS, Integer.toString(forumId), new Integer (total)); 659 } 660 661 return total; 662 } 663 664 671 public static int getTotalTopics(int forumId) throws Exception 672 { 673 return ForumRepository.getTotalTopics(forumId, false); 674 } 675 676 682 public static int getTotalMessages() throws Exception 683 { 684 return getTotalMessages(false); 685 } 686 687 697 public static int getTotalMessages(boolean fromDb) throws Exception 698 { 699 int total = ((Integer )cache.get(FQN, TOTAL_MESSAGES)).intValue(); 700 701 if (fromDb || total == 0) { 702 total = DataAccessDriver.getInstance().newForumDAO().getTotalMessages(); 703 cache.add(FQN, TOTAL_MESSAGES, new Integer (total)); 704 } 705 706 return total; 707 } 708 709 public static synchronized void incrementTotalMessages() 710 { 711 int total = ((Integer )cache.get(FQN, TOTAL_MESSAGES)).intValue(); 712 cache.add(FQN, TOTAL_MESSAGES, new Integer (total + 1)); 713 } 714 715 719 public static MostUsersEverOnline getMostUsersEverOnline() 720 { 721 return (MostUsersEverOnline)cache.get(FQN, MOST_USERS_ONLINE); 722 } 723 724 731 public static void updateMostUsersEverOnline(MostUsersEverOnline m) throws Exception 732 { 733 ConfigDAO cm = DataAccessDriver.getInstance().newConfigDAO(); 734 Config config = cm.selectByName(ConfigKeys.MOST_USERS_EVER_ONLINE); 735 if (config == null) { 736 config = new Config(); 738 config.setName(ConfigKeys.MOST_USERS_EVER_ONLINE); 739 config.setValue(Integer.toString(m.getTotal())); 740 741 cm.insert(config); 742 743 config.setName(ConfigKeys.MOST_USER_EVER_ONLINE_DATE); 745 config.setValue(Long.toString(m.getTimeInMillis())); 746 747 cm.insert(config); 748 } 749 else { 750 config.setValue(Integer.toString(m.getTotal())); 752 cm.update(config); 753 754 config.setName(ConfigKeys.MOST_USER_EVER_ONLINE_DATE); 756 config.setValue(Long.toString(m.getTimeInMillis())); 757 cm.update(config); 758 } 759 760 cache.add(FQN, MOST_USERS_ONLINE, m); 761 } 762 763 767 private void loadForums(ForumDAO fm) throws Exception 768 { 769 List l = fm.selectAll(); 770 771 Map m = (Map )cache.get(FQN, RELATION); 772 if (m == null) { 773 m = new HashMap (); 774 } 775 776 int lastId = 0; 777 Category c = null; 778 String catId = null; 779 780 for (Iterator iter = l.iterator(); iter.hasNext(); ) { 781 Forum f = (Forum)iter.next(); 782 783 if (f.getCategoryId() != lastId) { 784 if (c != null) { 785 cache.add(FQN, catId, c); 786 } 787 788 lastId = f.getCategoryId(); 789 catId = Integer.toString(f.getCategoryId()); 790 c = (Category)cache.get(FQN, catId); 791 } 792 793 if (c == null) { 794 throw new CategoryNotFoundException("Category for forum #" + f.getId() + " not found"); 795 } 796 797 String forumId = Integer.toString(f.getId()); 798 c.addForum(f); 799 m.put(forumId, catId); 800 cache.add(FQN_TOTAL_TOPICS, forumId, new Integer (-1)); 801 } 802 803 if (c != null) { 804 cache.add(FQN, catId, c); 805 } 806 807 cache.add(FQN, RELATION, m); 808 } 809 810 private void loadUsersInfo() throws Exception 811 { 812 UserDAO udao = DataAccessDriver.getInstance().newUserDAO(); 813 cache.add(FQN, LAST_USER, udao.getLastUserInfo()); 814 cache.add(FQN, TOTAL_USERS, new Integer (udao.getTotalUsers())); 815 } 816 817 821 private void loadCategories(CategoryDAO cm) throws Exception 822 { 823 List categories = cm.selectAll(); 824 Set categoriesSet = new TreeSet (new CategoryOrderComparator()); 825 826 for (Iterator iter = categories.iterator(); iter.hasNext(); ) { 827 Category c = (Category)iter.next(); 828 829 cache.add(FQN, Integer.toString(c.getId()), c); 830 categoriesSet.add(c); 831 } 832 833 cache.add(FQN, CATEGORIES_SET, categoriesSet); 834 } 835 836 private void loadMostUsersEverOnline(ConfigDAO cm) throws Exception 837 { 838 Config config = cm.selectByName(ConfigKeys.MOST_USERS_EVER_ONLINE); 839 MostUsersEverOnline mostUsersEverOnline = new MostUsersEverOnline(); 840 841 if (config != null) { 842 mostUsersEverOnline.setTotal(Integer.parseInt(config.getValue())); 843 844 config = cm.selectByName(ConfigKeys.MOST_USER_EVER_ONLINE_DATE); 847 mostUsersEverOnline.setTimeInMillis(Long.parseLong(config.getValue())); 848 } 849 850 cache.add(FQN, MOST_USERS_ONLINE, mostUsersEverOnline); 851 } 852 } 853 | Popular Tags |