1 16 17 package org.apache.jetspeed.services.registry; 18 19 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService; 21 import org.apache.jetspeed.services.logging.JetspeedLogger; 22 import org.apache.jetspeed.om.registry.Registry; 23 import org.apache.jetspeed.om.registry.RegistryEntry; 24 import org.apache.jetspeed.om.registry.RegistryException; 25 import org.apache.jetspeed.om.registry.base.BaseRegistry; 26 import org.apache.jetspeed.om.registry.base.LocalRegistry; 27 28 import org.apache.turbine.services.InitializationException; 30 import org.apache.turbine.services.TurbineBaseService; 31 import org.apache.turbine.services.TurbineServices; 32 import org.apache.turbine.services.servlet.TurbineServlet; 33 import org.apache.turbine.services.servlet.ServletService; 34 import org.apache.turbine.services.resources.ResourceService; 35 36 import org.exolab.castor.mapping.Mapping; 38 import org.exolab.castor.xml.Unmarshaller; 39 import org.exolab.castor.xml.Marshaller; 40 import org.xml.sax.InputSource; 41 import org.apache.xml.serialize.Serializer; 42 import org.apache.xml.serialize.XMLSerializer; 43 import org.apache.xml.serialize.OutputFormat; 44 import org.w3c.dom.Document; 45 import org.w3c.dom.Node; 46 47 import java.io.File; 49 import java.io.FileFilter; 50 import java.io.FileReader; 51 import java.io.FileOutputStream; 52 import java.io.OutputStreamWriter; 53 import java.io.Reader; 54 import java.util.Enumeration; 55 import java.util.Hashtable; 56 import java.util.Map; 57 import java.util.Iterator; 58 import java.util.Vector; 59 import javax.servlet.ServletConfig; 60 import javax.xml.parsers.DocumentBuilder; 61 import javax.xml.parsers.DocumentBuilderFactory; 62 63 89 public class CastorRegistryService 90 extends TurbineBaseService 91 implements RegistryService, FileRegistry 92 { 93 96 private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(CastorRegistryService.class.getName()); 97 98 public static final int DEFAULT_REFRESH = 300; 99 public static final String DEFAULT_EXTENSION = ".xreg"; 100 public static final String DEFAULT_MAPPING = "${webapp}/WEB-INF/conf/mapping.xml"; 101 102 103 private Hashtable registries = new Hashtable(); 104 105 106 private Hashtable fragments = new Hashtable(); 107 108 109 private Hashtable defaults = new Hashtable(); 110 111 112 private Hashtable entryIndex = new Hashtable(); 113 114 115 private RegistryWatcher watcher = null; 116 117 118 private Mapping mapping = null; 119 120 121 private OutputFormat format = null; 122 123 124 private String directory = null; 125 126 127 private String extension = null; 128 129 135 public Registry get(String regName) 136 { 137 return (Registry) registries.get(regName); 138 } 139 140 145 public Enumeration getNames() 146 { 147 return registries.keys(); 148 } 149 150 157 public RegistryEntry createEntry(String regName) 158 { 159 RegistryEntry entry = null; 160 Registry registry = (Registry) registries.get(regName); 161 162 if (registry != null) 163 { 164 entry = registry.createEntry(); 165 } 166 167 return entry; 168 } 169 170 180 public RegistryEntry getEntry(String regName, String entryName) 181 { 182 try 183 { 184 return ((Registry) registries.get(regName)).getEntry(entryName); 185 } 186 catch (RegistryException e) 187 { 188 if (logger.isInfoEnabled()) 189 { 190 logger.info("RegistryService: Failed to retrieve " + entryName + " from " + regName); 191 } 192 } 193 catch (NullPointerException e) 194 { 195 logger.error("RegistryService: " + regName + " registry is not known ", e); 196 } 197 198 return null; 199 } 200 201 211 public void addEntry(String regName, RegistryEntry entry) throws RegistryException 212 { 213 if (entry == null) 214 { 215 return; 216 } 217 218 LocalRegistry registry = (LocalRegistry) registries.get(regName); 219 220 if (registry != null) 221 { 222 String fragmentName = (String) entryIndex.get(entry.getName()); 223 224 if (fragmentName == null) 225 { 226 fragmentName = (String) defaults.get(regName); 229 } 230 231 RegistryFragment fragment = (RegistryFragment) fragments.get(fragmentName); 232 233 if (fragment == null) 235 { 236 fragment = new RegistryFragment(); 237 fragment.put(regName, new Vector()); 238 fragments.put(fragmentName, fragment); 239 } 240 else 241 { 242 Vector vectRegistry = (Vector) fragment.get(regName); 243 if (vectRegistry == null) 244 { 245 fragment.put(regName, new Vector()); 246 } 247 } 248 249 synchronized (entryIndex) 250 { 251 if (registry.hasEntry(entry.getName())) 252 { 253 fragment.setEntry(regName, entry); 254 registry.setLocalEntry(entry); 255 } 256 else 257 { 258 fragment.addEntry(regName, entry); 259 registry.addLocalEntry(entry); 260 } 261 262 entryIndex.put(entry.getName(), fragmentName); 263 fragment.setDirty(true); 266 } 267 } 268 } 269 270 278 public void removeEntry(String regName, String entryName) 279 { 280 if (entryName == null) 281 { 282 return; 283 } 284 285 LocalRegistry registry = (LocalRegistry) registries.get(regName); 286 287 if (registry != null) 288 { 289 String fragmentName = (String) entryIndex.get(entryName); 290 291 if (fragmentName != null) 292 { 293 RegistryFragment fragment = (RegistryFragment) fragments.get(fragmentName); 294 295 synchronized (entryIndex) 296 { 297 fragment.removeEntry(regName, entryName); 298 entryIndex.remove(entryName); 299 300 fragment.setDirty(true); 303 } 304 } 305 306 registry.removeLocalEntry(entryName); 308 } 309 } 310 311 315 public synchronized void init(ServletConfig conf) throws InitializationException 316 { 317 318 TurbineServices.getInstance().initService(ServletService.SERVICE_NAME, conf); 320 321 ResourceService serviceConf = ((TurbineServices) TurbineServices.getInstance()) 322 .getResources(RegistryService.SERVICE_NAME); 323 String mapFile = null; 324 Vector names = new Vector(); 325 int refreshRate = 0; 326 327 try 329 { 330 directory = serviceConf.getString("directory"); 331 mapFile = serviceConf.getString("mapping", DEFAULT_MAPPING); 332 extension = serviceConf.getString("extension", DEFAULT_EXTENSION); 333 refreshRate = serviceConf.getInt("refreshRate", DEFAULT_REFRESH); 334 335 mapFile = TurbineServlet.getRealPath(mapFile); 336 directory = TurbineServlet.getRealPath(directory); 337 } 338 catch (Throwable t) 339 { 340 throw new InitializationException("Unable to initialize CastorRegistryService, missing config keys"); 341 } 342 343 try 346 { 347 ResourceService defaults = serviceConf.getResources("default"); 348 Iterator i = defaults.getKeys(); 349 while (i.hasNext()) 350 { 351 String name = (String) i.next(); 352 String fragmentFileName = defaults.getString(name); 353 354 String absFileName = new File(directory, fragmentFileName + extension).getCanonicalPath(); 355 names.add(name); 357 358 this.defaults.put(name, absFileName); 360 } 361 } 362 catch (Exception e) 363 { 364 logger.error("RegistryService: Registry init error", e); 365 throw new InitializationException("Unable to initialize CastorRegistryService, invalid registries definition"); 366 } 367 368 this.format = new OutputFormat(); 370 format.setIndenting(true); 371 format.setIndent(4); 372 format.setLineWidth(0); 373 374 376 if (mapFile != null) 377 { 378 File map = new File(mapFile); 379 if (map.exists() && map.isFile() && map.canRead()) 380 { 381 try 382 { 383 mapping = new Mapping(); 384 InputSource is = new InputSource(new FileReader(map)); 385 is.setSystemId(mapFile); 386 mapping.loadMapping(is); 387 } 388 catch (Exception e) 389 { 390 logger.error("RegistryService: Error in mapping creation", e); 391 throw new InitializationException("Error in mapping", e); 392 } 393 } 394 else 395 { 396 throw new InitializationException("Mapping not found or not a file or unreadable: " + mapFile); 397 } 398 } 399 400 File base = new File(directory); 402 File[] files = null; 403 404 if (base.exists() && base.isDirectory() && base.canRead()) 405 { 406 this.watcher = new RegistryWatcher(); 407 this.watcher.setSubscriber(this); 408 this.watcher.setFilter(new ExtFileFilter(extension)); 409 if (refreshRate == 0) 410 { 411 this.watcher.setDone(); 412 } 413 else 414 { 415 this.watcher.setRefreshRate(refreshRate); 416 } 417 this.watcher.changeBase(base); 419 } 420 421 setInit(true); 423 424 425 Enumeration en = names.elements(); 427 428 while (en.hasMoreElements()) 429 { 430 String name = (String) en.nextElement(); 431 Registry registry = (Registry) registries.get(name); 432 433 if (registry == null) 434 { 435 String registryClass = null; 436 try 437 { 438 registryClass = 439 "org.apache.jetspeed.om.registry.base.Base" 440 + name 441 + "Registry"; 442 443 registry = (Registry) Class.forName(registryClass).newInstance(); 444 } 445 catch (Exception e) 446 { 447 if (logger.isWarnEnabled()) 448 { 449 logger.warn("RegistryService: Class " 450 + registryClass 451 + " not found, reverting to default Registry"); 452 } 453 registry = new BaseRegistry(); 454 } 455 456 registries.put(name, registry); 457 } 458 459 refresh(name); 460 } 461 462 if (this.watcher != null) 465 { 466 this.watcher.start(); 467 } 468 469 if (logger.isDebugEnabled()) 470 { 471 logger.debug("RegistryService: early init()....end!, this.getInit()= " + getInit()); 472 } 473 474 } 475 476 477 478 public void init() throws InitializationException 479 { 480 if (logger.isDebugEnabled()) 481 { 482 logger.debug("RegistryService: Late init called"); 483 } 484 485 while (!getInit()) 486 { 487 try 489 { 490 Thread.sleep(500); 491 if (logger.isDebugEnabled()) 492 { 493 logger.debug("RegistryService: Waiting for init of Registry..."); 494 } 495 } 496 catch (InterruptedException ie) 497 { 498 logger.error("Exception", ie); 499 } 500 } 501 502 if (logger.isDebugEnabled()) 503 { 504 logger.debug("RegistryService: We are done"); 505 } 506 } 507 508 512 public void shutdown() 513 { 514 this.watcher.setDone(); 515 516 Iterator i = fragments.keySet().iterator(); 517 while (i.hasNext()) 518 { 519 saveFragment((String) i.next()); 520 } 521 } 522 523 525 528 public void refresh() 529 { 530 synchronized (watcher) 531 { 532 Enumeration en = getNames(); 533 while (en.hasMoreElements()) 534 { 535 refresh((String) en.nextElement()); 536 } 537 } 538 } 539 540 543 public Map getFragmentMap() 544 { 545 return (Map) fragments.clone(); 546 } 547 548 552 public void loadFragment(String file) 553 { 554 try 555 { 556 DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance(); 557 DocumentBuilder builder = dbfactory.newDocumentBuilder(); 558 559 Document d = builder.parse(new File(file)); 560 561 Unmarshaller unmarshaller = new Unmarshaller(this.mapping); 562 RegistryFragment fragment = (RegistryFragment) unmarshaller.unmarshal((Node) d); 563 564 fragment.setChanged(true); 566 567 updateFragment(file, fragment); 569 570 } 571 catch (Throwable t) 572 { 573 logger.error("RegistryService: Could not unmarshal: " + file, t); 574 } 575 576 } 577 578 585 public void createFragment(String name, Reader reader, boolean persistent) 586 { 587 String file = null; 588 589 try 590 { 591 synchronized(watcher) 592 { 593 file = new File(directory, name + extension).getCanonicalPath(); 594 595 Unmarshaller unmarshaller = new Unmarshaller(this.mapping); 596 RegistryFragment fragment = (RegistryFragment) unmarshaller.unmarshal(reader); 597 598 fragment.setChanged(true); 599 600 updateFragment(file, fragment); 601 602 if (persistent) 603 { 604 saveFragment(file); 605 } 606 } 607 } 608 catch (Throwable t) 609 { 610 logger.error("RegistryService: Could not create fragment: " + file, t); 611 } 612 finally 613 { 614 try 615 { 616 reader.close(); 617 } 618 catch (Exception e) 619 { 620 logger.error("Exception", e); } 622 } 623 } 624 625 629 public void saveFragment(String file) 630 { 631 OutputStreamWriter writer = null; 632 FileOutputStream fos = null; 633 String encoding = new String("UTF-8"); 634 RegistryFragment fragment = (RegistryFragment) fragments.get(file); 635 636 if (fragment != null) 637 { 638 try 639 { 640 fos = new FileOutputStream(file); 641 writer = new OutputStreamWriter(fos, encoding); 642 format.setEncoding(encoding); 643 Serializer serializer = new XMLSerializer(writer, format); 644 Marshaller marshaller = new Marshaller(serializer.asDocumentHandler()); 645 marshaller.setMapping(this.mapping); 646 marshaller.marshal(fragment); 647 } 648 catch (Throwable t) 649 { 650 logger.error("RegistryService: Could not marshal: " + file, t); 651 } 652 finally 653 { 654 try 655 { 656 writer.close(); 657 } 658 catch (Exception e) 659 { 660 logger.error("Exception", e); } 662 663 try 664 { 665 fos.close(); 666 } 667 catch (Exception e) 668 { 669 logger.error("Exception", e); } 671 } 672 } 673 } 674 675 679 public void removeFragment(String file) 680 { 681 RegistryFragment fragment = (RegistryFragment) fragments.get(file); 682 683 if (fragment != null) 684 { 685 synchronized (entryIndex) 686 { 687 Iterator i = entryIndex.keySet().iterator(); 689 while (i.hasNext()) 690 { 691 if (file.equals(entryIndex.get(i.next()))) 692 { 693 i.remove(); 694 } 695 } 696 697 fragment.clear(); 701 fragments.remove(file); 703 } 704 } 705 } 706 707 709 712 protected void updateFragment(String name, RegistryFragment fragment) 713 { 714 synchronized (entryIndex) 715 { 716 Iterator i = entryIndex.keySet().iterator(); 718 while (i.hasNext()) 719 { 720 if (name.equals(entryIndex.get(i.next()))) 721 { 722 i.remove(); 723 } 724 } 725 726 fragments.put(name, fragment); 728 729 731 Enumeration enum = fragment.keys(); 732 while (enum.hasMoreElements()) 733 { 734 String strReg = (String) enum.nextElement(); 735 Vector v = fragment.getEntries(strReg); 736 737 for (int counter = 0; counter < v.size(); counter++) 738 { 739 RegistryEntry str = (RegistryEntry) v.elementAt(counter); 740 entryIndex.put(str.getName(), name); 741 } 742 } 743 } 744 } 745 746 752 protected void refresh(String regName) 753 { 754 755 if (logger.isDebugEnabled()) 756 { 757 logger.debug("RegistryService: Updating the " + regName + " registry"); 758 } 759 760 int count = 0; 761 int counDeleted = 0; 762 LocalRegistry registry = (LocalRegistry) get(regName); 763 764 Vector toDelete = new Vector(); 765 Iterator i = registry.listEntryNames(); 766 767 while (i.hasNext()) 768 { 769 toDelete.add(i.next()); 770 } 771 772 if (registry == null) 773 { 774 logger.error("RegistryService: Null " + name + " registry in refresh"); 775 return; 776 } 777 778 Enumeration en = fragments.keys(); 780 while (en.hasMoreElements()) 781 { 782 String location = (String) en.nextElement(); 783 RegistryFragment fragment = (RegistryFragment) fragments.get(location); 784 int fragCount = 0; 785 786 if (!fragment.hasChanged()) 787 { 788 if (logger.isDebugEnabled()) 789 { 790 logger.debug("RegistryService: Skipping fragment " + location); 791 } 792 793 Vector entries = fragment.getEntries(regName); 795 i = entries.iterator(); 796 while (i.hasNext()) 797 { 798 toDelete.remove(((RegistryEntry) i.next()).getName()); 799 } 800 801 continue; 802 } 803 804 806 Vector entries = fragment.getEntries(regName); 807 808 if (entries != null) 810 { 811 Enumeration en2 = entries.elements(); 813 while (en2.hasMoreElements()) 814 { 815 RegistryEntry entry = (RegistryEntry) en2.nextElement(); 816 try 818 { 819 if (registry.hasEntry(entry.getName())) 820 { 821 if (registry.getEntry(entry.getName()).equals(entry)) 822 { 823 if (logger.isDebugEnabled()) 824 { 825 logger.debug("RegistryService: No changes to entry " + entry.getName()); 826 } 827 } 828 else 829 { 830 if (logger.isDebugEnabled()) 831 { 832 logger.debug("RegistryService: Updating entry " + entry.getName() 833 + " of class " + entry.getClass() + " to registry " + name); 834 } 835 836 registry.setLocalEntry(entry); 837 this.entryIndex.put(entry.getName(), location); 839 ++fragCount; 840 } 841 } 842 else 843 { 844 registry.addLocalEntry(entry); 845 this.entryIndex.put(entry.getName(), location); 847 ++fragCount; 848 849 if (logger.isDebugEnabled()) 850 { 851 logger.debug("RegistryService: Adding entry " + entry.getName() + " of class " 852 + entry.getClass() + " to registry " + name); 853 } 854 } 855 } 856 catch (RegistryException e) 857 { 858 logger.error("RegistryService: RegistryException while adding " + entry.getName() + "from " + location, e); 859 } 860 861 toDelete.remove(entry.getName()); 863 } 864 } 865 866 count += fragCount; 867 } 868 869 i = toDelete.iterator(); 871 while (i.hasNext()) 872 { 873 String entryName = (String) i.next(); 874 875 if (logger.isDebugEnabled()) 876 { 877 logger.debug("RegistryService: removing entry " + entryName); 878 } 879 880 registry.removeLocalEntry(entryName); 881 } 882 883 884 if (logger.isDebugEnabled()) 885 { 886 logger.debug("RegistryService: Merged " + count + " entries and deleted " + toDelete.size() + " in " + name); 887 } 888 } 889 890 891 892 class ExtFileFilter implements FileFilter 893 { 894 private String extension = null; 895 896 ExtFileFilter(String extension) 897 { 898 this.extension = extension; 899 } 900 901 public boolean accept(File f) 902 { 903 return f.toString().endsWith(extension); 904 } 905 } 906 907 } 908 | Popular Tags |