1 22 23 package org.meshcms.core; 24 25 import java.io.*; 26 import java.util.*; 27 import org.meshcms.util.*; 28 import com.opensymphony.module.sitemesh.*; 29 import com.opensymphony.module.sitemesh.parser.*; 30 31 34 public class SiteMap extends DirectoryParser { 35 38 public static final String THEME_DECORATOR = "main.jsp"; 39 40 43 public static final String THEME_CSS = "main.css"; 44 45 49 public static final String MESHCMS_CSS = "meshcms.css"; 50 51 public static final String MODULE_INCLUDE_FILE = "include.jsp"; 52 53 private WebSite webSite; 54 private SortedMap pagesMap; 55 private SiteMap oldSiteMap; 56 private long lastModified; 57 private Map currentWelcomes; 58 private List pagesList; 59 60 private SortedMap themesMap; 61 private SortedMap modulesMap; 62 private List langList; 63 private Map pageCache; 64 65 private Map redirCache; 66 private Path[] redirPaths; 67 68 private boolean obsolete; 69 70 73 public SiteMap(WebSite webSite) { 74 this.webSite = webSite; 75 setRecursive(true); 76 setSorted(true); 77 setProcessStartDir(true); 78 setInitialDir(webSite.getRootFile()); 79 setDaemon(true); 80 setName("Site map parser for \"" + webSite.getTypeDescription() + '"'); 81 pageCache = new HashMap(); 82 } 83 84 protected boolean preProcess() { 85 oldSiteMap = webSite.getSiteMap(); 86 87 if (oldSiteMap != null && oldSiteMap.isObsolete()) { 88 oldSiteMap = null; 89 } 90 91 pagesMap = new TreeMap(); 92 currentWelcomes = new TreeMap(); 93 return true; 94 } 95 96 protected boolean preProcessDirectory(File file, Path path) { 97 if (!webSite.isSystem(path)) { 98 Path wPath = webSite.findCurrentWelcome(path); 99 100 if (wPath == null && path.isRoot()) { 101 String wName = webSite.getWelcomeFileNames()[0]; 102 103 try { 104 Utils.writeFully(new File(file, wName), 105 webSite.getHTMLTemplate("Home Page")); 106 webSite.getSiteInfo().setPageTheme(Path.ROOT, "default"); 107 webSite.getSiteInfo().store(); 108 wPath = new Path(wName); 109 } catch (IOException ex) { 110 webSite.log("Can't create home page for empty site", ex); 111 } 112 } 113 114 if (wPath != null) { 115 currentWelcomes.put(path, wPath); 116 return true; 117 } 118 } 119 120 return false; 121 } 122 123 protected void processFile(File file, Path path) { 124 if (!FileTypes.isPage(path.getLastElement())) { 125 return; 126 } 127 128 Path dirPath = path.getParent(); 129 Path welcome = (Path) currentWelcomes.get(dirPath); 130 131 if (welcome == null) { 132 return; 133 } 134 135 Path parentPath = dirPath.getParent(); 136 137 if (!parentPath.isRelative() && currentWelcomes.get(parentPath) == null) { 138 return; 139 } 140 141 path = welcome.equals(path) ? dirPath : path; 142 PageInfo pageInfo = null; 143 144 if (oldSiteMap != null) { 145 pageInfo = oldSiteMap.getPageInfo(path); 146 } 147 148 if (pageInfo == null) { 149 pageInfo = new PageInfo(webSite, path); 150 } 151 152 if (pageInfo.getLastModified() != file.lastModified()) { 153 HTMLPageParser fpp = new HTMLPageParser(); 154 Reader reader = null; 155 156 try { 157 reader = new BufferedReader(new FileReader(file)); 158 Page page = fpp.parse(Utils.readAllChars(reader)); 159 reader.close(); 160 String title = page.getTitle(); 161 162 if (Utils.isNullOrWhitespace(title)) { 163 title = Utils.beautify(Utils.removeExtension(path), true); 164 } 165 166 pageInfo.setTitle(title); 167 pageInfo.setLastModified(file.lastModified()); 168 169 179 } catch (Exception ex) { 180 pageInfo.setTitle(Utils.beautify(path.getLastElement(), true)); 181 pageInfo.setLastModified(0L); 182 } finally { 183 if (reader != null) { 184 try { 185 reader.close(); 186 } catch (IOException ex) { 187 webSite.log("Can't close file " + file, ex); 188 } 189 } 190 } 191 } 192 193 pagesMap.put(path, pageInfo); 194 } 195 196 protected void postProcess() { 197 pagesMap = Collections.unmodifiableSortedMap(pagesMap); 198 oldSiteMap = null; 199 200 pagesList = new ArrayList(pagesMap.values()); 201 Collections.sort(pagesList, new PageInfoComparator(this, webSite.getSiteInfo())); 202 pagesList = Collections.unmodifiableList(pagesList); 203 204 langList = new ArrayList(); 205 Iterator iter = getPagesInDirectory(Path.ROOT, false).iterator(); 206 207 while (iter.hasNext()) { 208 Path path = ((PageInfo) iter.next()).getPath(); 209 210 if (path.getElementCount() == 1) { 211 Locale locale = Utils.getLocale(path.getElementAt(0)); 212 213 if (locale != null) { 214 langList.add(new CodeLocalePair(path.getElementAt(0), locale)); 215 } 216 } 217 } 218 219 langList = Collections.unmodifiableList(langList); 220 setLastModified(); 221 webSite.setSiteMap(this); 222 } 224 225 228 public PageInfo getPageInfo(Path path) { 229 return (PageInfo) pagesMap.get(getPathInMenu(path)); 230 } 231 232 235 public PageInfo getParentPageInfo(Path path) { 236 path = getPathInMenu(path).getParent(); 237 return path.isRelative() ? null : (PageInfo) pagesMap.get(path); 238 } 239 240 244 public Path getPathInMenu(Path path) { 245 return currentWelcomes.containsValue(path) ? path.getParent() : path; 246 } 247 248 252 public Path getServedPath(Path path) { 253 Path welcome = (Path) currentWelcomes.get(path); 254 return (welcome == null) ? path : welcome; 255 } 256 257 262 public Path getCurrentWelcome(Path dirPath) { 263 return (Path) currentWelcomes.get(dirPath); 264 } 265 266 269 public boolean isCurrentWelcome(Path path) { 270 return currentWelcomes.containsValue(path); 271 } 272 273 276 void setLastModified() { 277 lastModified = System.currentTimeMillis(); 278 } 279 280 283 public long getLastModified() { 284 return lastModified; 285 } 286 287 300 public String getTigraItems(String contextPath, Path path, boolean tree) { 301 return getTigraItems(contextPath, path, tree, false); 302 } 303 304 318 public String getTigraItems(String contextPath, Path path, boolean tree, boolean allowHiding) { 319 if (path == null) { 320 path = Path.ROOT; 321 } 322 323 StringBuffer sb = new StringBuffer (); 324 325 sb.append("var ").append(tree ? "TREE" : "MENU").append("_ITEMS = ["); 326 327 int baseLevel = path.getElementCount() + 1; 328 SiteInfo siteInfo = webSite.getSiteInfo(); 329 SiteMapIterator iter = new SiteMapIterator(webSite, path); 330 iter.setSkipHiddenSubPages(allowHiding); 331 PageInfo current; 332 PageInfo previous = null; 333 int level; 334 335 do { 336 if (iter.hasNext()) { 337 current = (PageInfo) iter.next(); 338 level = Math.max(current.getLevel(), baseLevel); 339 } else { 340 current = null; 341 level = baseLevel; 342 } 343 344 if (previous != null) { 345 int previousLevel = Math.max(previous.getLevel(), baseLevel); 346 347 for (int j = level; j > previousLevel; j--) { 348 } 350 351 if (level <= previousLevel) { 352 sb.append(", null]"); 353 } 354 355 for (int j = previousLevel - 1; j >= level; j--) { 356 sb.append("\n"); 357 358 for (int k = baseLevel; k <= j; k++) { 359 sb.append(" "); 360 } 361 362 sb.append("]"); 363 } 364 365 } 366 367 if (current != null) { 368 if (previous != null) { 369 sb.append(","); 370 } 371 372 sb.append("\n"); 373 374 for (int j = baseLevel; j <= level; j++) { 375 sb.append(" "); 376 } 377 378 sb.append("['"); 379 sb.append(Utils.escapeSingleQuotes(siteInfo.getPageTitle(current))); 380 sb.append("', "); 381 String link = webSite.getLink(current); 382 sb.append(link == null ? "null" : "'" + contextPath + link + "'"); 383 384 if (!tree) { 385 sb.append(", null"); 386 } 387 388 previous = current; 389 } 390 } while (current != null); 391 392 sb.append("\n];"); 393 return sb.toString(); 394 } 395 396 404 public SortedMap getPagesMap(Path root) { 405 if (root == null) { 406 root = Path.ROOT; 407 } 408 409 return root.isRoot() ? pagesMap : pagesMap.subMap(root, root.successor()); 410 } 411 412 public List getLangList() { 413 return langList; 414 } 415 416 420 public boolean hasChildrenPages(Path path) { 421 if (!webSite.isDirectory(path)) { 422 return false; 423 } 424 425 int n = path.getElementCount() + 1; 426 SortedMap map = getPagesMap(path); 427 428 if (map != null) { 429 Iterator iter = map.keySet().iterator(); 430 431 while (iter.hasNext()) { 432 Path p = (Path) iter.next(); 433 434 if (p.getElementCount() == n) { 435 return true; 436 } 437 } 438 } 439 440 return false; 441 } 442 443 449 public List getPagesInDirectory(Path path, boolean includeDir) { 450 PageInfo rootPage = getPageInfo(webSite.getDirectory(path)); 451 int idx = pagesList.indexOf(rootPage); 452 453 if (idx < 0) { 454 return null; 455 } 456 457 List list = new ArrayList(); 458 459 if (includeDir) { 460 list.add(rootPage); 461 } 462 463 for (int i = idx + 1; i < pagesList.size(); i++) { 464 PageInfo pi = (PageInfo) pagesList.get(i); 465 int n = pi.getLevel() - rootPage.getLevel(); 466 467 if (n <= 0) { 468 break; 469 } else if (n == 1) { 470 list.add(pi); 471 } 472 } 473 474 return list; 475 } 476 477 482 public List getPagesList() { 483 return pagesList; 484 } 485 486 491 public List getPagesList(Path root) { 492 root = webSite.getDirectory(root); 493 494 if (root.isRoot()) { 495 return pagesList; 496 } 497 498 PageInfo rootPage = getPageInfo(root); 499 int idx = pagesList.indexOf(rootPage); 500 501 if (idx < 0) { 502 return null; 503 } 504 505 int rootLevel = rootPage.getLevel(); 506 507 for (int i = idx + 1; i < pagesList.size(); i++) { 508 if (((PageInfo) pagesList.get(i)).getLevel() <= rootLevel) { 509 return pagesList.subList(idx, i); 510 } 511 } 512 513 return pagesList.subList(idx, pagesList.size()); 514 } 515 516 526 public List getPagesListNoHiddenSubmenus(Path root) { 527 SiteInfo siteInfo = webSite.getSiteInfo(); 528 List pagesListHiddenSubmenus = new ArrayList(this.getPagesList(root)); 529 Path currentHiddenSubmenuPath = null; 530 int i = 0; 531 while (i < pagesListHiddenSubmenus.size()) { 532 Path currentPath = ((PageInfo)pagesListHiddenSubmenus.get(i)).getPath(); 533 if (currentHiddenSubmenuPath != null) { 534 if (currentPath.isContainedIn(currentHiddenSubmenuPath)) { 535 pagesListHiddenSubmenus.remove(i); 536 } else { 537 currentHiddenSubmenuPath = null; 538 } 539 } 540 if (currentHiddenSubmenuPath == null && siteInfo.getHideSubmenu(currentPath)) { 541 currentHiddenSubmenuPath = currentPath; 542 } 543 i++; 544 } 545 return Collections.unmodifiableList(pagesListHiddenSubmenus); 546 } 547 548 552 public PageInfo[] getBreadcrumbs(Path path) { 553 path = getPathInMenu(path); 554 List list = new ArrayList(); 555 556 for (int i = 0; i < path.getElementCount(); i++) { 557 Path partial = path.getPartial(i); 558 PageInfo pi = getPageInfo(partial); 559 560 if (pi != null) { 561 list.add(pi); 562 } else if (partial.equals(webSite.getAdminPath())) { 563 PageInfo api = new PageInfo(webSite, webSite.getAdminPath()); 564 api.setTitle("MeshCMS"); 565 list.add(api); 566 } 567 } 568 569 if (list.size() != 0) { 570 return (PageInfo[]) list.toArray(new PageInfo[list.size()]); 571 } 572 573 return null; 574 } 575 576 579 public String [] getThemeNames() { 580 Set keys = getThemesMap().keySet(); 581 return (String []) keys.toArray(new String [keys.size()]); 582 } 583 584 587 public String [] getModuleNames() { 588 Set keys = getModulesMap().keySet(); 589 return (String []) keys.toArray(new String [keys.size()]); 590 } 591 592 595 public void cache(Path path, byte[] b) { 596 pageCache.put(path, b); 597 } 598 599 602 public void removeFromCache(Path path) { 603 pageCache.remove(path); 604 } 605 606 609 public byte[] getCached(Path path) { 610 return (byte[]) pageCache.get(path); 611 } 612 613 616 public boolean isCached(Path path) { 617 return pageCache.containsKey(path); 618 } 619 620 public SortedMap getThemesMap() { 621 if (themesMap == null) { 622 themesMap = new TreeMap(); 623 addDirItemsToMap(themesMap, webSite.getAdminThemesPath(), THEME_DECORATOR); 624 addDirItemsToMap(themesMap, webSite.getCustomThemesPath(), THEME_DECORATOR); 625 themesMap = Collections.unmodifiableSortedMap(themesMap); 626 } 627 628 return themesMap; 629 } 630 631 public SortedMap getModulesMap() { 632 if (modulesMap == null) { 633 modulesMap = new TreeMap(); 634 addDirItemsToMap(modulesMap, webSite.getAdminModulesPath(), 635 MODULE_INCLUDE_FILE); 636 addDirItemsToMap(modulesMap, webSite.getCustomModulesPath(), 637 MODULE_INCLUDE_FILE); 638 modulesMap = Collections.unmodifiableSortedMap(modulesMap); 639 } 640 641 return modulesMap; 642 } 643 644 private void addDirItemsToMap(Map map, Path path, String insideDir) { 645 File dir = webSite.getFile(path); 646 647 if (dir.isDirectory()) { 648 String [] files = dir.list(); 649 650 if (files != null) { 651 for (int i = 0; i < files.length; i++) { 652 Path subPath = path.add(files[i]); 653 654 if (insideDir == null || webSite.getFile(subPath.add(insideDir)).exists()) { 655 map.put(files[i], subPath); 656 } 657 } 658 } 659 } 660 } 661 662 665 public boolean isObsolete() { 666 return obsolete; 667 } 668 669 673 public void setObsolete(boolean obsolete) { 674 this.obsolete = obsolete; 675 } 676 677 public Path getRedirMatch(Path requestedPath) { 678 if (redirCache == null) { 679 redirCache = new HashMap(); 680 List list = getPagesList(); 681 redirPaths = new Path[list.size()]; 682 Iterator iter = list.iterator(); 683 684 for (int i = 0; iter.hasNext(); i++) { 685 redirPaths[i] = ((PageInfo) iter.next()).getPath(); 686 } 687 } 688 689 Path result = null; 690 int best = 0; 691 692 if (Utils.searchString(WebUtils.DEFAULT_WELCOME_FILES, 693 requestedPath.getLastElement(), false) >= 0) { 694 requestedPath = requestedPath.getPartial(requestedPath.getElementCount() - 1); 695 } 696 697 if (redirCache.containsKey(requestedPath)) { 698 result = (Path) redirCache.get(requestedPath); 699 } else { 700 for (int i = 0; i < redirPaths.length; i++) { 701 String [] commonPart = Utils.commonPart(requestedPath.getElements(), 702 redirPaths[i].getElements(), true); 703 704 if (commonPart != null && commonPart.length > best) { 705 result = redirPaths[i]; 706 best = commonPart.length; 707 } 708 } 709 710 redirCache.put(requestedPath, result); 711 } 712 713 return result; 714 } 715 716 public static class CodeLocalePair { 717 private String code; 718 private Locale locale; 719 private String name; 720 721 public CodeLocalePair(String code, Locale locale) { 722 this.code = code; 723 this.locale = locale; 724 name = Utils.toTitleCase(locale.getDisplayName(locale)); 725 } 726 727 public String getCode() { 728 return code; 729 } 730 731 public Locale getLocale() { 732 return locale; 733 } 734 735 public String getName() { 736 return name; 737 } 738 } 739 } 740 | Popular Tags |